@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.mjs
CHANGED
|
@@ -542,16 +542,111 @@ const { withContext } = createRecipeContext({ key: "button" });
|
|
|
542
542
|
const LinkButton = withContext("a");
|
|
543
543
|
|
|
544
544
|
const [RootPropsProvider, useRootProps] = createContext$1({
|
|
545
|
-
name:
|
|
545
|
+
name: 'RootPropsProvider',
|
|
546
546
|
});
|
|
547
547
|
const variantMap = {
|
|
548
|
-
outline: { default:
|
|
549
|
-
solid: { default:
|
|
550
|
-
subtle: { default:
|
|
548
|
+
outline: { default: 'ghost', ellipsis: 'plain', current: 'outline' },
|
|
549
|
+
solid: { default: 'outline', ellipsis: 'outline', current: 'solid' },
|
|
550
|
+
subtle: { default: 'ghost', ellipsis: 'plain', current: 'subtle' },
|
|
551
551
|
};
|
|
552
552
|
const PaginationRoot = React.forwardRef(function PaginationRoot(props, ref) {
|
|
553
|
-
const { size =
|
|
554
|
-
|
|
553
|
+
const { size = 'sm', variant = 'outline', getHref, siblingCount, minSiblingCount = 1, maxSiblingCount, ...rest } = props;
|
|
554
|
+
const containerRef = React.useRef(null);
|
|
555
|
+
const [calculatedSiblingCount, setCalculatedSiblingCount] = React.useState(siblingCount);
|
|
556
|
+
React.useEffect(() => {
|
|
557
|
+
if (siblingCount !== undefined || !containerRef.current) {
|
|
558
|
+
setCalculatedSiblingCount(siblingCount);
|
|
559
|
+
return;
|
|
560
|
+
}
|
|
561
|
+
const container = containerRef.current;
|
|
562
|
+
let rafId = null;
|
|
563
|
+
const calculateSiblingCount = () => {
|
|
564
|
+
if (!container)
|
|
565
|
+
return;
|
|
566
|
+
const width = container.offsetWidth;
|
|
567
|
+
if (width === 0)
|
|
568
|
+
return;
|
|
569
|
+
// Estimate button width based on size
|
|
570
|
+
// These are approximate widths including padding for different button sizes
|
|
571
|
+
const buttonWidthMap = {
|
|
572
|
+
xs: 28,
|
|
573
|
+
sm: 36,
|
|
574
|
+
md: 40,
|
|
575
|
+
lg: 44,
|
|
576
|
+
};
|
|
577
|
+
let buttonWidth = buttonWidthMap[size] || 36;
|
|
578
|
+
// Try to measure actual button if available (for more accuracy)
|
|
579
|
+
const buttons = container.querySelectorAll('button');
|
|
580
|
+
if (buttons.length > 0) {
|
|
581
|
+
const firstButton = buttons[0];
|
|
582
|
+
if (firstButton.offsetWidth > 0) {
|
|
583
|
+
// Use measured width, but account for text content variation
|
|
584
|
+
const measuredWidth = firstButton.offsetWidth;
|
|
585
|
+
// Page number buttons might be slightly wider due to text, use measured width
|
|
586
|
+
buttonWidth = Math.max(buttonWidth, measuredWidth);
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
// Account for prev/next buttons and gaps
|
|
590
|
+
// HStack gap is typically 8px in Chakra UI
|
|
591
|
+
const gap = 8;
|
|
592
|
+
const prevNextWidth = buttonWidth * 2 + gap;
|
|
593
|
+
const availableWidth = Math.max(0, width - prevNextWidth);
|
|
594
|
+
// Each page button takes buttonWidth + gap
|
|
595
|
+
const buttonWithGap = buttonWidth + gap;
|
|
596
|
+
const maxButtons = Math.floor(availableWidth / buttonWithGap);
|
|
597
|
+
// Calculate sibling count
|
|
598
|
+
// Minimum structure: [prev] [1] [current] [last] [next] = 5 buttons
|
|
599
|
+
// With siblings: [prev] [1] [...] [current-N] ... [current] ... [current+N] [...] [last] [next]
|
|
600
|
+
// We need: prev(1) + first(1) + ellipsis(1) + siblings*2 + current(1) + ellipsis(1) + last(1) + next(1)
|
|
601
|
+
// Minimum: 5 buttons (prev, first, current, last, next)
|
|
602
|
+
// With siblings: 5 + siblings*2 + ellipsis*2 (if needed)
|
|
603
|
+
const minRequired = 5;
|
|
604
|
+
const extraButtons = Math.max(0, maxButtons - minRequired);
|
|
605
|
+
// Calculate sibling count
|
|
606
|
+
// If we have enough space for ellipsis (2 buttons), account for that
|
|
607
|
+
let calculated = minSiblingCount;
|
|
608
|
+
if (extraButtons >= 4) {
|
|
609
|
+
// Space for ellipsis (2) + siblings
|
|
610
|
+
calculated = Math.floor((extraButtons - 2) / 2);
|
|
611
|
+
}
|
|
612
|
+
else if (extraButtons >= 2) {
|
|
613
|
+
// Space for some siblings but not ellipsis
|
|
614
|
+
calculated = Math.floor(extraButtons / 2);
|
|
615
|
+
}
|
|
616
|
+
// Apply max limit if provided
|
|
617
|
+
if (maxSiblingCount !== undefined) {
|
|
618
|
+
calculated = Math.min(calculated, maxSiblingCount);
|
|
619
|
+
}
|
|
620
|
+
setCalculatedSiblingCount(Math.max(minSiblingCount, calculated));
|
|
621
|
+
};
|
|
622
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
623
|
+
// Use requestAnimationFrame to debounce and ensure DOM is updated
|
|
624
|
+
if (rafId !== null) {
|
|
625
|
+
cancelAnimationFrame(rafId);
|
|
626
|
+
}
|
|
627
|
+
rafId = requestAnimationFrame(calculateSiblingCount);
|
|
628
|
+
});
|
|
629
|
+
resizeObserver.observe(container);
|
|
630
|
+
// Initial calculation after a short delay to ensure buttons are rendered
|
|
631
|
+
const timeoutId = setTimeout(calculateSiblingCount, 100);
|
|
632
|
+
return () => {
|
|
633
|
+
resizeObserver.disconnect();
|
|
634
|
+
if (rafId !== null) {
|
|
635
|
+
cancelAnimationFrame(rafId);
|
|
636
|
+
}
|
|
637
|
+
clearTimeout(timeoutId);
|
|
638
|
+
};
|
|
639
|
+
}, [size, siblingCount, minSiblingCount, maxSiblingCount]);
|
|
640
|
+
const mergedRef = React.useCallback((node) => {
|
|
641
|
+
if (typeof ref === 'function') {
|
|
642
|
+
ref(node);
|
|
643
|
+
}
|
|
644
|
+
else if (ref) {
|
|
645
|
+
ref.current = node;
|
|
646
|
+
}
|
|
647
|
+
containerRef.current = node;
|
|
648
|
+
}, [ref]);
|
|
649
|
+
return (jsx(RootPropsProvider, { value: { size, variantMap: variantMap[variant], getHref }, children: jsx(Pagination$1.Root, { ref: mergedRef, type: getHref ? 'link' : 'button', siblingCount: calculatedSiblingCount, ...rest }) }));
|
|
555
650
|
});
|
|
556
651
|
const PaginationEllipsis = React.forwardRef(function PaginationEllipsis(props, ref) {
|
|
557
652
|
const { size, variantMap } = useRootProps();
|
|
@@ -585,16 +680,16 @@ const PaginationNextTrigger = React.forwardRef(function PaginationNextTrigger(pr
|
|
|
585
680
|
});
|
|
586
681
|
const PaginationItems = (props) => {
|
|
587
682
|
return (jsx(Pagination$1.Context, { children: ({ pages }) => pages.map((page, index) => {
|
|
588
|
-
return page.type ===
|
|
683
|
+
return page.type === 'ellipsis' ? (jsx(PaginationEllipsis, { index: index, ...props }, index)) : (jsx(PaginationItem, { type: "page", value: page.value, ...props }, index));
|
|
589
684
|
}) }));
|
|
590
685
|
};
|
|
591
686
|
React.forwardRef(function PaginationPageText(props, ref) {
|
|
592
|
-
const { format =
|
|
687
|
+
const { format = 'compact', ...rest } = props;
|
|
593
688
|
const { page, totalPages, pageRange, count } = usePaginationContext();
|
|
594
689
|
const content = React.useMemo(() => {
|
|
595
|
-
if (format ===
|
|
690
|
+
if (format === 'short')
|
|
596
691
|
return `${page} / ${totalPages}`;
|
|
597
|
-
if (format ===
|
|
692
|
+
if (format === 'compact')
|
|
598
693
|
return `${page} / ${totalPages}`;
|
|
599
694
|
return `${pageRange.start + 1} - ${Math.min(pageRange.end, count)} / ${count}`;
|
|
600
695
|
}, [format, page, totalPages, pageRange, count]);
|
|
@@ -2733,23 +2828,28 @@ const DataTableServerContext = createContext({
|
|
|
2733
2828
|
const useDataTableServerContext = () => {
|
|
2734
2829
|
const context = useContext(DataTableServerContext);
|
|
2735
2830
|
const { query } = context;
|
|
2736
|
-
const isEmpty = (query.data?.count ?? 0) <= 0;
|
|
2831
|
+
const isEmpty = query ? (query.data?.count ?? 0) <= 0 : false;
|
|
2737
2832
|
return { ...context, isEmpty };
|
|
2738
2833
|
};
|
|
2739
2834
|
|
|
2740
|
-
const ReloadButton = ({ variant =
|
|
2741
|
-
const
|
|
2835
|
+
const ReloadButton = ({ variant = 'icon' }) => {
|
|
2836
|
+
const serverContext = useDataTableServerContext();
|
|
2837
|
+
const { url, query } = serverContext;
|
|
2742
2838
|
const queryClient = useQueryClient();
|
|
2743
2839
|
const { tableLabel } = useDataTableContext();
|
|
2744
2840
|
const { reloadTooltip, reloadButtonText } = tableLabel;
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
}, "aria-label": "refresh", children: jsx(IoReload, {}) }) }));
|
|
2749
|
-
}
|
|
2750
|
-
return (jsxs(Button, { variant: "ghost", onClick: () => {
|
|
2841
|
+
const handleReload = () => {
|
|
2842
|
+
// Only invalidate queries for server-side tables (when query exists)
|
|
2843
|
+
if (query && url) {
|
|
2751
2844
|
queryClient.invalidateQueries({ queryKey: [url] });
|
|
2752
|
-
}
|
|
2845
|
+
}
|
|
2846
|
+
// For client-side tables, reload button doesn't need to do anything
|
|
2847
|
+
// as the data is already in memory
|
|
2848
|
+
};
|
|
2849
|
+
if (variant === 'icon') {
|
|
2850
|
+
return (jsx(Tooltip, { showArrow: true, content: reloadTooltip, children: jsx(Button, { variant: 'ghost', onClick: handleReload, "aria-label": 'refresh', children: jsx(IoReload, {}) }) }));
|
|
2851
|
+
}
|
|
2852
|
+
return (jsxs(Button, { variant: 'ghost', onClick: handleReload, children: [jsx(IoReload, {}), " ", reloadButtonText] }));
|
|
2753
2853
|
};
|
|
2754
2854
|
|
|
2755
2855
|
const InputGroup = React.forwardRef(function InputGroup(props, ref) {
|
|
@@ -3082,14 +3182,14 @@ const DefaultCardTitle = () => {
|
|
|
3082
3182
|
const TableCards = ({ isSelectable = false, showDisplayNameOnly = false, renderTitle = DefaultCardTitle, cardBodyProps = {}, }) => {
|
|
3083
3183
|
const { table, rowSelection, setRowSelection } = useDataTableContext();
|
|
3084
3184
|
return (jsx(Fragment, { children: table.getRowModel().rows.map((row) => {
|
|
3085
|
-
return (jsx(Card.Root, { flex: '1 0 20rem', children: jsxs(Card.Body, { display: 'flex', flexFlow: 'column', gap: '0.5rem', ...cardBodyProps, children: [isSelectable && (jsx(Checkbox, {
|
|
3185
|
+
return (jsx(Card.Root, { flex: '1 0 20rem', children: jsxs(Card.Body, { display: 'flex', flexFlow: 'column', gap: '0.5rem', ...cardBodyProps, children: [isSelectable && (jsx(Checkbox, { checked: isRowSelected(row.id, rowSelection),
|
|
3086
3186
|
disabled: !canRowSelect(row),
|
|
3087
3187
|
// indeterminate: row.getIsSomeSelected(),
|
|
3088
3188
|
onChange: createRowToggleHandler(row, rowSelection, setRowSelection) })), renderTitle(row), jsx(Grid, { templateColumns: 'auto 1fr', gap: '1rem', children: row.getVisibleCells().map((cell) => {
|
|
3089
|
-
return (jsxs(
|
|
3189
|
+
return (jsxs(Box, { display: "contents", children: [jsxs(Box, { children: [showDisplayNameOnly && (jsx(Text, { fontWeight: 'bold', children: cell.column.columnDef.meta?.displayName ??
|
|
3090
3190
|
cell.column.id })), !showDisplayNameOnly && (jsx(Fragment, { children: flexRender(cell.column.columnDef.header,
|
|
3091
3191
|
// @ts-expect-error Assuming the CellContext interface is the same as HeaderContext
|
|
3092
|
-
cell.getContext()) }))] }
|
|
3192
|
+
cell.getContext()) }))] }), jsx(Box, { justifySelf: 'end', children: flexRender(cell.column.columnDef.cell, cell.getContext()) })] }, `chakra-table-cardcell-${cell.id}`));
|
|
3093
3193
|
}) })] }) }, `chakra-table-card-${row.id}`));
|
|
3094
3194
|
}) }));
|
|
3095
3195
|
};
|
|
@@ -3120,9 +3220,13 @@ const TableFooter = ({ showSelector = false, alwaysShowSelector = true, }) => {
|
|
|
3120
3220
|
}
|
|
3121
3221
|
return false;
|
|
3122
3222
|
};
|
|
3123
|
-
return (jsx(Table$1.Footer, { children: table.getFooterGroups().map((footerGroup) => (jsxs(Table$1.Row, { display: 'flex', children: [showSelector && (
|
|
3124
|
-
|
|
3125
|
-
|
|
3223
|
+
return (jsx(Table$1.Footer, { children: table.getFooterGroups().map((footerGroup) => (jsxs(Table$1.Row, { display: 'flex', children: [showSelector && (jsx(Table$1.Cell, { padding: `${table.getDensityValue()}px`, onMouseEnter: () => handleRowHover(true), onMouseLeave: () => handleRowHover(false), display: 'grid', justifyItems: 'center', alignItems: 'center', color: {
|
|
3224
|
+
base: 'colorPalette.900',
|
|
3225
|
+
_dark: 'colorPalette.100',
|
|
3226
|
+
},
|
|
3227
|
+
bg: { base: 'colorPalette.50', _dark: 'colorPalette.950' }, children: isCheckBoxVisible() ? (jsx(Checkbox, { width: `${SELECTION_BOX_WIDTH}px`, height: `${SELECTION_BOX_WIDTH}px`, checked: areAllRowsSelected(table, rowSelection),
|
|
3228
|
+
// indeterminate: areSomeRowsSelected(table, rowSelection),
|
|
3229
|
+
onChange: createToggleAllRowsHandler(table, rowSelection, setRowSelection) })) : (jsx(Box, { as: "span", width: `${SELECTION_BOX_WIDTH}px`, height: `${SELECTION_BOX_WIDTH}px` })) })), footerGroup.headers.map((header) => (jsx(Table$1.Cell, { padding: '0', columnSpan: `${header.colSpan}`,
|
|
3126
3230
|
// styling resize and pinning start
|
|
3127
3231
|
maxWidth: `${header.getSize()}px`, width: `${header.getSize()}px`, display: 'grid', children: jsx(MenuRoot$1, { children: jsx(MenuTrigger$1, { asChild: true, children: jsx(Box, { padding: `${table.getDensityValue()}px`, display: 'flex', alignItems: 'center', justifyContent: 'start', borderRadius: '0rem', children: jsxs(Flex, { gap: "0.5rem", alignItems: 'center', children: [header.isPlaceholder
|
|
3128
3232
|
? null
|
|
@@ -3354,7 +3458,7 @@ const TextWithCopy = ({ text, globalFilter, highlightedText, }) => {
|
|
|
3354
3458
|
const displayText = highlightedText !== undefined
|
|
3355
3459
|
? highlightedText
|
|
3356
3460
|
: highlightText$1(textValue, globalFilter);
|
|
3357
|
-
return (jsxs(HStack, { gap: 2, alignItems: "center", children: [jsx(Text, { as: "span", children: displayText }), jsx(Clipboard.Root, { value: textValue, children: jsx(Clipboard.Trigger, { asChild: true, children: jsx(IconButton, { size: "xs", variant: "ghost", "aria-label": "Copy", children: jsx(Clipboard.Indicator, { copied: jsx(LuCheck, {}), children: jsx(LuCopy, {}) }) }) }) })] }));
|
|
3461
|
+
return (jsxs(HStack, { gap: 2, alignItems: "center", children: [jsx(Text, { as: "span", children: displayText }), jsx(Clipboard.Root, { value: textValue, children: jsx(Clipboard.Trigger, { asChild: true, children: jsx(IconButton, { size: "xs", variant: "ghost", "aria-label": "Copy", fontSize: "1em", children: jsx(Clipboard.Indicator, { copied: jsx(LuCheck, {}), children: jsx(LuCopy, {}) }) }) }) })] }));
|
|
3358
3462
|
};
|
|
3359
3463
|
|
|
3360
3464
|
// Helper function to highlight matching text
|
|
@@ -3608,7 +3712,7 @@ const snakeToLabel = (str) => {
|
|
|
3608
3712
|
.join(" "); // Join with space
|
|
3609
3713
|
};
|
|
3610
3714
|
|
|
3611
|
-
const RecordDisplay = ({ object, boxProps, translate, prefix =
|
|
3715
|
+
const RecordDisplay = ({ object, boxProps, translate, prefix = '', }) => {
|
|
3612
3716
|
const getColumn = ({ field }) => {
|
|
3613
3717
|
if (translate !== undefined) {
|
|
3614
3718
|
return translate.t(`${prefix}${field}`);
|
|
@@ -3618,8 +3722,9 @@ const RecordDisplay = ({ object, boxProps, translate, prefix = "", }) => {
|
|
|
3618
3722
|
if (object === null) {
|
|
3619
3723
|
return jsx(Fragment, { children: "null" });
|
|
3620
3724
|
}
|
|
3621
|
-
return (jsx(Grid, { rowGap: 1, padding: 1, overflow:
|
|
3622
|
-
|
|
3725
|
+
return (jsx(Grid, { rowGap: 1, padding: 1, overflow: 'auto', ...boxProps, children: Object.entries(object).map(([field, value], index) => {
|
|
3726
|
+
const uniqueKey = `${prefix}${field}-${index}`;
|
|
3727
|
+
return (jsxs(Grid, { columnGap: 2, gridTemplateColumns: 'auto 1fr', children: [jsx(Text, { color: 'colorPalette.400', children: getColumn({ field }) }), typeof value === 'object' && value !== null ? (jsx(RecordDisplay, { object: value, prefix: `${prefix}${field}.`, translate: translate })) : (jsx(Text, { children: JSON.stringify(value) }))] }, uniqueKey));
|
|
3623
3728
|
}) }));
|
|
3624
3729
|
};
|
|
3625
3730
|
|
|
@@ -3910,13 +4015,10 @@ const idPickerSanityCheck = (column, foreign_key) => {
|
|
|
3910
4015
|
if (!!foreign_key == false) {
|
|
3911
4016
|
throw new Error(`The key foreign_key does not exist in properties of column ${column} when using id-picker.`);
|
|
3912
4017
|
}
|
|
3913
|
-
const { table, column: foreignKeyColumn
|
|
4018
|
+
const { table, column: foreignKeyColumn } = foreign_key;
|
|
3914
4019
|
if (!!table == false) {
|
|
3915
4020
|
throw new Error(`The key table does not exist in properties of column ${table} when using id-picker.`);
|
|
3916
4021
|
}
|
|
3917
|
-
if (!!display_column == false) {
|
|
3918
|
-
throw new Error(`The key display_column does not exist in properties of column ${column} when using id-picker.`);
|
|
3919
|
-
}
|
|
3920
4022
|
if (!!foreignKeyColumn == false) {
|
|
3921
4023
|
throw new Error(`The key column does not exist in properties of column ${column} when using id-picker.`);
|
|
3922
4024
|
}
|
|
@@ -3925,7 +4027,7 @@ const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, childre
|
|
|
3925
4027
|
showSubmitButton: true,
|
|
3926
4028
|
showResetButton: true,
|
|
3927
4029
|
showTitle: true,
|
|
3928
|
-
}, requireConfirmation = false, dateTimePickerLabels, idPickerLabels, enumPickerLabels, filePickerLabels, insideDialog = false, }) => {
|
|
4030
|
+
}, requireConfirmation = false, dateTimePickerLabels, idPickerLabels, enumPickerLabels, filePickerLabels, formButtonLabels, insideDialog = false, }) => {
|
|
3929
4031
|
const [isSuccess, setIsSuccess] = useState(false);
|
|
3930
4032
|
const [isError, setIsError] = useState(false);
|
|
3931
4033
|
const [isSubmiting, setIsSubmiting] = useState(false);
|
|
@@ -4015,6 +4117,7 @@ const FormRoot = ({ schema, idMap, setIdMap, form, serverUrl, translate, childre
|
|
|
4015
4117
|
idPickerLabels,
|
|
4016
4118
|
enumPickerLabels,
|
|
4017
4119
|
filePickerLabels,
|
|
4120
|
+
formButtonLabels,
|
|
4018
4121
|
ajvResolver: ajvResolver(schema),
|
|
4019
4122
|
insideDialog,
|
|
4020
4123
|
}, children: jsx(FormProvider, { ...form, children: children }) }));
|
|
@@ -4024,40 +4127,107 @@ function removeIndex(str) {
|
|
|
4024
4127
|
return str.replace(/\.\d+\./g, ".");
|
|
4025
4128
|
}
|
|
4026
4129
|
|
|
4130
|
+
/**
|
|
4131
|
+
* Custom hook to simplify i18n translation for form fields.
|
|
4132
|
+
* Automatically handles colLabel construction and removeIndex logic.
|
|
4133
|
+
*
|
|
4134
|
+
* @param column - The column name
|
|
4135
|
+
* @param prefix - The prefix for the field (usually empty string or parent path)
|
|
4136
|
+
* @returns Object with translation helper functions
|
|
4137
|
+
*
|
|
4138
|
+
* @example
|
|
4139
|
+
* ```tsx
|
|
4140
|
+
* const formI18n = useFormI18n(column, prefix);
|
|
4141
|
+
*
|
|
4142
|
+
* // Get field label
|
|
4143
|
+
* <Field label={formI18n.label()} />
|
|
4144
|
+
*
|
|
4145
|
+
* // Get error message
|
|
4146
|
+
* <Text>{formI18n.required()}</Text>
|
|
4147
|
+
*
|
|
4148
|
+
* // Get custom translation key
|
|
4149
|
+
* <Text>{formI18n.t('add_more')}</Text>
|
|
4150
|
+
*
|
|
4151
|
+
* // Access the raw colLabel
|
|
4152
|
+
* const colLabel = formI18n.colLabel;
|
|
4153
|
+
* ```
|
|
4154
|
+
*/
|
|
4155
|
+
const useFormI18n$1 = (column, prefix = '', schema) => {
|
|
4156
|
+
const { translate } = useSchemaContext();
|
|
4157
|
+
const colLabel = `${prefix}${column}`;
|
|
4158
|
+
return {
|
|
4159
|
+
/**
|
|
4160
|
+
* The constructed column label (prefix + column)
|
|
4161
|
+
*/
|
|
4162
|
+
colLabel,
|
|
4163
|
+
/**
|
|
4164
|
+
* Get the field label from schema title prop, or fall back to translation
|
|
4165
|
+
* Uses schema.title if available, otherwise: translate.t(removeIndex(`${colLabel}.field_label`))
|
|
4166
|
+
*/
|
|
4167
|
+
label: (options) => {
|
|
4168
|
+
if (schema?.title) {
|
|
4169
|
+
return schema.title;
|
|
4170
|
+
}
|
|
4171
|
+
return translate.t(removeIndex(`${colLabel}.field_label`), options);
|
|
4172
|
+
},
|
|
4173
|
+
/**
|
|
4174
|
+
* Get the required error message translation
|
|
4175
|
+
* Equivalent to: translate.t(removeIndex(`${colLabel}.field_required`))
|
|
4176
|
+
*/
|
|
4177
|
+
required: (options) => {
|
|
4178
|
+
return translate.t(removeIndex(`${colLabel}.field_required`), options);
|
|
4179
|
+
},
|
|
4180
|
+
/**
|
|
4181
|
+
* Get a translation for any custom key relative to the field
|
|
4182
|
+
* Equivalent to: translate.t(removeIndex(`${colLabel}.${key}`))
|
|
4183
|
+
*
|
|
4184
|
+
* @param key - The translation key suffix (e.g., 'add_more', 'total', etc.)
|
|
4185
|
+
* @param options - Optional translation options (e.g., defaultValue, interpolation variables)
|
|
4186
|
+
*/
|
|
4187
|
+
t: (key, options) => {
|
|
4188
|
+
return translate.t(removeIndex(`${colLabel}.${key}`), options);
|
|
4189
|
+
},
|
|
4190
|
+
/**
|
|
4191
|
+
* Access to the original translate object for edge cases
|
|
4192
|
+
*/
|
|
4193
|
+
translate,
|
|
4194
|
+
};
|
|
4195
|
+
};
|
|
4196
|
+
|
|
4027
4197
|
const ArrayRenderer = ({ schema, column, prefix, }) => {
|
|
4028
|
-
const { gridRow, gridColumn =
|
|
4198
|
+
const { gridRow, gridColumn = '1/span 12', required, items } = schema;
|
|
4029
4199
|
// @ts-expect-error TODO: find suitable types
|
|
4030
4200
|
const { type } = items;
|
|
4031
|
-
const { translate } = useSchemaContext();
|
|
4032
4201
|
const colLabel = `${prefix}${column}`;
|
|
4033
4202
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
4203
|
+
const formI18n = useFormI18n$1(column, prefix, schema);
|
|
4034
4204
|
const { formState: { errors }, setValue, watch, } = useFormContext();
|
|
4035
4205
|
const fields = (watch(colLabel) ?? []);
|
|
4036
|
-
return (jsxs(Flex, { gridRow, gridColumn, flexFlow:
|
|
4037
|
-
base:
|
|
4038
|
-
_dark:
|
|
4039
|
-
}, children: [jsx(Grid, { gridTemplateColumns:
|
|
4206
|
+
return (jsxs(Flex, { gridRow, gridColumn, flexFlow: 'column', gap: 2, children: [jsxs(Box, { as: "label", children: [formI18n.label(), isRequired && jsx("span", { children: "*" })] }), jsx(Flex, { flexFlow: 'column', gap: 2, children: fields.map((field, index) => (jsxs(Grid, { gridTemplateColumns: '1fr auto', gap: 2, bgColor: { base: 'colorPalette.100', _dark: 'colorPalette.900' }, p: 2, borderRadius: 4, borderWidth: 1, borderColor: {
|
|
4207
|
+
base: 'colorPalette.200',
|
|
4208
|
+
_dark: 'colorPalette.800',
|
|
4209
|
+
}, children: [jsx(Grid, { gridTemplateColumns: 'repeat(12, 1fr)', autoFlow: 'row', children: jsx(SchemaRenderer, { column: `${index}`,
|
|
4040
4210
|
prefix: `${colLabel}.`,
|
|
4041
4211
|
// @ts-expect-error find suitable types
|
|
4042
|
-
schema: { showLabel: false, ...(items ?? {}) } }) }), jsx(Flex, { justifyContent:
|
|
4212
|
+
schema: { showLabel: false, ...(items ?? {}) } }) }), jsx(Flex, { justifyContent: 'end', children: jsx(Button$1, { variant: 'ghost', onClick: () => {
|
|
4043
4213
|
setValue(colLabel, fields.filter((_, curIndex) => {
|
|
4044
4214
|
return curIndex !== index;
|
|
4045
4215
|
}));
|
|
4046
4216
|
}, children: jsx(Icon, { children: jsx(CgTrash, {}) }) }) })] }, `${colLabel}.${index}`))) }), jsx(Flex, { children: jsx(Button$1, { onClick: () => {
|
|
4047
|
-
if (type ===
|
|
4217
|
+
if (type === 'number') {
|
|
4048
4218
|
setValue(colLabel, [...fields, 0]);
|
|
4049
4219
|
return;
|
|
4050
4220
|
}
|
|
4051
|
-
if (type ===
|
|
4052
|
-
setValue(colLabel, [...fields,
|
|
4221
|
+
if (type === 'string') {
|
|
4222
|
+
setValue(colLabel, [...fields, '']);
|
|
4053
4223
|
return;
|
|
4054
4224
|
}
|
|
4055
|
-
if (type ===
|
|
4225
|
+
if (type === 'boolean') {
|
|
4056
4226
|
setValue(colLabel, [...fields, false]);
|
|
4057
4227
|
return;
|
|
4058
4228
|
}
|
|
4059
4229
|
setValue(colLabel, [...fields, {}]);
|
|
4060
|
-
}, children: translate.t(removeIndex(`${colLabel}.add`)) }) }), errors[`${column}`] && (jsx(Text, { color:
|
|
4230
|
+
}, children: translate.t(removeIndex(`${colLabel}.add`)) }) }), errors[`${column}`] && (jsx(Text, { color: 'red.400', children: formI18n.required() }))] }));
|
|
4061
4231
|
};
|
|
4062
4232
|
|
|
4063
4233
|
const Field = React.forwardRef(function Field(props, ref) {
|
|
@@ -4067,15 +4237,13 @@ const Field = React.forwardRef(function Field(props, ref) {
|
|
|
4067
4237
|
|
|
4068
4238
|
const BooleanPicker = ({ schema, column, prefix }) => {
|
|
4069
4239
|
const { watch, formState: { errors }, setValue, } = useFormContext();
|
|
4070
|
-
const { translate } = useSchemaContext();
|
|
4071
4240
|
const { required, gridColumn = 'span 12', gridRow = 'span 1' } = schema;
|
|
4072
4241
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
4073
4242
|
const colLabel = `${prefix}${column}`;
|
|
4074
4243
|
const value = watch(colLabel);
|
|
4075
|
-
|
|
4076
|
-
|
|
4077
|
-
|
|
4078
|
-
: undefined, invalid: !!errors[colLabel], children: jsx(CheckboxCard, { checked: value, variant: 'surface', onChange: () => {
|
|
4244
|
+
const formI18n = useFormI18n$1(column, prefix, schema);
|
|
4245
|
+
return (jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
4246
|
+
gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: jsx(CheckboxCard, { checked: value, variant: 'surface', onChange: () => {
|
|
4079
4247
|
setValue(colLabel, !value);
|
|
4080
4248
|
} }) }));
|
|
4081
4249
|
};
|
|
@@ -4191,76 +4359,12 @@ let DatePicker$1 = class DatePicker extends React__default.Component {
|
|
|
4191
4359
|
}
|
|
4192
4360
|
};
|
|
4193
4361
|
|
|
4194
|
-
/**
|
|
4195
|
-
* Custom hook to simplify i18n translation for form fields.
|
|
4196
|
-
* Automatically handles colLabel construction and removeIndex logic.
|
|
4197
|
-
*
|
|
4198
|
-
* @param column - The column name
|
|
4199
|
-
* @param prefix - The prefix for the field (usually empty string or parent path)
|
|
4200
|
-
* @returns Object with translation helper functions
|
|
4201
|
-
*
|
|
4202
|
-
* @example
|
|
4203
|
-
* ```tsx
|
|
4204
|
-
* const formI18n = useFormI18n(column, prefix);
|
|
4205
|
-
*
|
|
4206
|
-
* // Get field label
|
|
4207
|
-
* <Field label={formI18n.label()} />
|
|
4208
|
-
*
|
|
4209
|
-
* // Get error message
|
|
4210
|
-
* <Text>{formI18n.required()}</Text>
|
|
4211
|
-
*
|
|
4212
|
-
* // Get custom translation key
|
|
4213
|
-
* <Text>{formI18n.t('add_more')}</Text>
|
|
4214
|
-
*
|
|
4215
|
-
* // Access the raw colLabel
|
|
4216
|
-
* const colLabel = formI18n.colLabel;
|
|
4217
|
-
* ```
|
|
4218
|
-
*/
|
|
4219
|
-
const useFormI18n = (column, prefix = "") => {
|
|
4220
|
-
const { translate } = useSchemaContext();
|
|
4221
|
-
const colLabel = `${prefix}${column}`;
|
|
4222
|
-
return {
|
|
4223
|
-
/**
|
|
4224
|
-
* The constructed column label (prefix + column)
|
|
4225
|
-
*/
|
|
4226
|
-
colLabel,
|
|
4227
|
-
/**
|
|
4228
|
-
* Get the field label translation
|
|
4229
|
-
* Equivalent to: translate.t(removeIndex(`${colLabel}.field_label`))
|
|
4230
|
-
*/
|
|
4231
|
-
label: (options) => {
|
|
4232
|
-
return translate.t(removeIndex(`${colLabel}.field_label`), options);
|
|
4233
|
-
},
|
|
4234
|
-
/**
|
|
4235
|
-
* Get the required error message translation
|
|
4236
|
-
* Equivalent to: translate.t(removeIndex(`${colLabel}.field_required`))
|
|
4237
|
-
*/
|
|
4238
|
-
required: (options) => {
|
|
4239
|
-
return translate.t(removeIndex(`${colLabel}.field_required`), options);
|
|
4240
|
-
},
|
|
4241
|
-
/**
|
|
4242
|
-
* Get a translation for any custom key relative to the field
|
|
4243
|
-
* Equivalent to: translate.t(removeIndex(`${colLabel}.${key}`))
|
|
4244
|
-
*
|
|
4245
|
-
* @param key - The translation key suffix (e.g., 'add_more', 'total', etc.)
|
|
4246
|
-
* @param options - Optional translation options (e.g., defaultValue, interpolation variables)
|
|
4247
|
-
*/
|
|
4248
|
-
t: (key, options) => {
|
|
4249
|
-
return translate.t(removeIndex(`${colLabel}.${key}`), options);
|
|
4250
|
-
},
|
|
4251
|
-
/**
|
|
4252
|
-
* Access to the original translate object for edge cases
|
|
4253
|
-
*/
|
|
4254
|
-
translate,
|
|
4255
|
-
};
|
|
4256
|
-
};
|
|
4257
|
-
|
|
4258
4362
|
dayjs.extend(utc);
|
|
4259
4363
|
dayjs.extend(timezone);
|
|
4260
4364
|
const DatePicker = ({ column, schema, prefix }) => {
|
|
4261
4365
|
const { watch, formState: { errors }, setValue, } = useFormContext();
|
|
4262
4366
|
const { timezone, dateTimePickerLabels, insideDialog } = useSchemaContext();
|
|
4263
|
-
const formI18n = useFormI18n(column, prefix);
|
|
4367
|
+
const formI18n = useFormI18n$1(column, prefix, schema);
|
|
4264
4368
|
const { required, gridColumn = 'span 12', gridRow = 'span 1', displayDateFormat = 'YYYY-MM-DD', dateFormat = 'YYYY-MM-DD', } = schema;
|
|
4265
4369
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
4266
4370
|
const colLabel = formI18n.colLabel;
|
|
@@ -4378,7 +4482,7 @@ dayjs.extend(timezone);
|
|
|
4378
4482
|
const DateRangePicker = ({ column, schema, prefix, }) => {
|
|
4379
4483
|
const { watch, formState: { errors }, setValue, } = useFormContext();
|
|
4380
4484
|
const { timezone, insideDialog } = useSchemaContext();
|
|
4381
|
-
const formI18n = useFormI18n(column, prefix);
|
|
4485
|
+
const formI18n = useFormI18n$1(column, prefix);
|
|
4382
4486
|
const { required, gridColumn = 'span 12', gridRow = 'span 1', displayDateFormat = 'YYYY-MM-DD', dateFormat = 'YYYY-MM-DD', } = schema;
|
|
4383
4487
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
4384
4488
|
const colLabel = formI18n.colLabel;
|
|
@@ -4476,7 +4580,7 @@ const DateRangePicker = ({ column, schema, prefix, }) => {
|
|
|
4476
4580
|
const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLimit = false, }) => {
|
|
4477
4581
|
const { watch, formState: { errors }, setValue, } = useFormContext();
|
|
4478
4582
|
const { enumPickerLabels, insideDialog } = useSchemaContext();
|
|
4479
|
-
const formI18n = useFormI18n(column, prefix);
|
|
4583
|
+
const formI18n = useFormI18n$1(column, prefix, schema);
|
|
4480
4584
|
const { required, variant } = schema;
|
|
4481
4585
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
4482
4586
|
const { gridColumn = 'span 12', gridRow = 'span 1', renderDisplay } = schema;
|
|
@@ -5120,7 +5224,7 @@ function MediaBrowserDialog({ open, onClose, onSelect, title, filterImageOnly =
|
|
|
5120
5224
|
const FilePicker = ({ column, schema, prefix }) => {
|
|
5121
5225
|
const { setValue, formState: { errors }, watch, } = useFormContext();
|
|
5122
5226
|
const { filePickerLabels } = useSchemaContext();
|
|
5123
|
-
const formI18n = useFormI18n(column, prefix);
|
|
5227
|
+
const formI18n = useFormI18n$1(column, prefix);
|
|
5124
5228
|
const { required, gridColumn = 'span 12', gridRow = 'span 1', type, } = schema;
|
|
5125
5229
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
5126
5230
|
const isSingleSelect = type === 'string';
|
|
@@ -5196,7 +5300,7 @@ const FilePicker = ({ column, schema, prefix }) => {
|
|
|
5196
5300
|
const FormMediaLibraryBrowser = ({ column, schema, prefix, }) => {
|
|
5197
5301
|
const { setValue, formState: { errors }, watch, } = useFormContext();
|
|
5198
5302
|
const { filePickerLabels } = useSchemaContext();
|
|
5199
|
-
const formI18n = useFormI18n(column, prefix);
|
|
5303
|
+
const formI18n = useFormI18n$1(column, prefix);
|
|
5200
5304
|
const { required, gridColumn = 'span 12', gridRow = 'span 1', filePicker, type, } = schema;
|
|
5201
5305
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
5202
5306
|
const isSingleSelect = type === 'string';
|
|
@@ -5337,13 +5441,18 @@ const getTableData = async ({ serverUrl, in_table, searching = "", where = [], l
|
|
|
5337
5441
|
}
|
|
5338
5442
|
};
|
|
5339
5443
|
|
|
5444
|
+
// Default renderDisplay function that stringifies JSON
|
|
5445
|
+
const defaultRenderDisplay = (item) => {
|
|
5446
|
+
return JSON.stringify(item);
|
|
5447
|
+
};
|
|
5448
|
+
|
|
5340
5449
|
const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
|
|
5341
5450
|
const { watch, getValues, formState: { errors }, setValue, } = useFormContext();
|
|
5342
5451
|
const { serverUrl, idMap, setIdMap, idPickerLabels, insideDialog } = useSchemaContext();
|
|
5343
|
-
const formI18n = useFormI18n(column, prefix);
|
|
5452
|
+
const formI18n = useFormI18n$1(column, prefix, schema);
|
|
5344
5453
|
const { required, gridColumn = 'span 12', gridRow = 'span 1', renderDisplay, foreign_key, } = schema;
|
|
5345
5454
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
5346
|
-
const { table, column: column_ref,
|
|
5455
|
+
const { table, column: column_ref, customQueryFn, } = foreign_key;
|
|
5347
5456
|
const [searchText, setSearchText] = useState('');
|
|
5348
5457
|
const [debouncedSearchText, setDebouncedSearchText] = useState('');
|
|
5349
5458
|
const [limit] = useState(50); // Increased limit for combobox
|
|
@@ -5378,6 +5487,69 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
|
|
|
5378
5487
|
}, 300);
|
|
5379
5488
|
return () => clearTimeout(timer);
|
|
5380
5489
|
}, [searchText]);
|
|
5490
|
+
// Find IDs that are in currentValue but missing from idMap
|
|
5491
|
+
const missingIds = useMemo(() => {
|
|
5492
|
+
return currentValue.filter((id) => !idMap[id]);
|
|
5493
|
+
}, [currentValue, idMap]);
|
|
5494
|
+
// Stable key for query based on sorted missing IDs
|
|
5495
|
+
const missingIdsKey = useMemo(() => {
|
|
5496
|
+
return JSON.stringify([...missingIds].sort());
|
|
5497
|
+
}, [missingIds]);
|
|
5498
|
+
// Query to fetch initial values that are missing from idMap
|
|
5499
|
+
// This query runs automatically when missingIds.length > 0 and updates idMap
|
|
5500
|
+
const initialValuesQuery = useQuery({
|
|
5501
|
+
queryKey: [`idpicker-initial`, column, missingIdsKey],
|
|
5502
|
+
queryFn: async () => {
|
|
5503
|
+
if (missingIds.length === 0) {
|
|
5504
|
+
return { data: [], count: 0 };
|
|
5505
|
+
}
|
|
5506
|
+
if (customQueryFn) {
|
|
5507
|
+
const { data, idMap } = await customQueryFn({
|
|
5508
|
+
searching: '',
|
|
5509
|
+
limit: missingIds.length,
|
|
5510
|
+
offset: 0,
|
|
5511
|
+
where: [
|
|
5512
|
+
{
|
|
5513
|
+
id: column_ref,
|
|
5514
|
+
value: missingIds.length === 1 ? missingIds[0] : missingIds,
|
|
5515
|
+
},
|
|
5516
|
+
],
|
|
5517
|
+
});
|
|
5518
|
+
setIdMap((state) => {
|
|
5519
|
+
return { ...state, ...idMap };
|
|
5520
|
+
});
|
|
5521
|
+
return data;
|
|
5522
|
+
}
|
|
5523
|
+
const data = await getTableData({
|
|
5524
|
+
serverUrl,
|
|
5525
|
+
searching: '',
|
|
5526
|
+
in_table: table,
|
|
5527
|
+
limit: missingIds.length,
|
|
5528
|
+
offset: 0,
|
|
5529
|
+
where: [
|
|
5530
|
+
{
|
|
5531
|
+
id: column_ref,
|
|
5532
|
+
value: missingIds.length === 1 ? missingIds[0] : missingIds,
|
|
5533
|
+
},
|
|
5534
|
+
],
|
|
5535
|
+
});
|
|
5536
|
+
const newMap = Object.fromEntries((data ?? { data: [] }).data.map((item) => {
|
|
5537
|
+
return [
|
|
5538
|
+
item[column_ref],
|
|
5539
|
+
{
|
|
5540
|
+
...item,
|
|
5541
|
+
},
|
|
5542
|
+
];
|
|
5543
|
+
}));
|
|
5544
|
+
setIdMap((state) => {
|
|
5545
|
+
return { ...state, ...newMap };
|
|
5546
|
+
});
|
|
5547
|
+
return data;
|
|
5548
|
+
},
|
|
5549
|
+
enabled: missingIds.length > 0, // Only fetch if there are missing IDs
|
|
5550
|
+
staleTime: 300000,
|
|
5551
|
+
});
|
|
5552
|
+
const { isLoading: isLoadingInitialValues, isFetching: isFetchingInitialValues, } = initialValuesQuery;
|
|
5381
5553
|
// Query for search results (async loading)
|
|
5382
5554
|
const query = useQuery({
|
|
5383
5555
|
queryKey: [`idpicker`, { column, searchText: debouncedSearchText, limit }],
|
|
@@ -5420,16 +5592,60 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
|
|
|
5420
5592
|
const dataList = data?.data ?? [];
|
|
5421
5593
|
// Check if we're currently searching (user typed but debounce hasn't fired yet)
|
|
5422
5594
|
const isSearching = searchText !== debouncedSearchText;
|
|
5595
|
+
// Extract items from idMap for currentValue IDs
|
|
5596
|
+
// Use useMemo with a stable dependency to minimize recalculations
|
|
5597
|
+
const currentValueKey = useMemo(() => JSON.stringify([...currentValue].sort()), [currentValue]);
|
|
5598
|
+
// Serialize the relevant part of idMap to detect when items we care about change
|
|
5599
|
+
const idMapKey = useMemo(() => {
|
|
5600
|
+
const relevantItems = currentValue
|
|
5601
|
+
.map((id) => {
|
|
5602
|
+
const item = idMap[id];
|
|
5603
|
+
return item ? JSON.stringify({ id, hasItem: true }) : null;
|
|
5604
|
+
})
|
|
5605
|
+
.filter(Boolean)
|
|
5606
|
+
.sort()
|
|
5607
|
+
.join('|');
|
|
5608
|
+
return relevantItems;
|
|
5609
|
+
}, [currentValue, idMap]);
|
|
5610
|
+
const idMapItems = useMemo(() => {
|
|
5611
|
+
return currentValue
|
|
5612
|
+
.map((id) => idMap[id])
|
|
5613
|
+
.filter((item) => item !== undefined);
|
|
5614
|
+
// Depend on idMapKey which only changes when items we care about change
|
|
5615
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
5616
|
+
}, [currentValueKey, idMapKey]);
|
|
5423
5617
|
// Transform data for combobox collection
|
|
5424
5618
|
// label is used for filtering/searching (must be a string)
|
|
5425
5619
|
// raw item is stored for custom rendering
|
|
5620
|
+
// Also include items from idMap that match currentValue (for initial values display)
|
|
5426
5621
|
const comboboxItems = useMemo(() => {
|
|
5427
|
-
|
|
5428
|
-
|
|
5429
|
-
|
|
5430
|
-
|
|
5431
|
-
|
|
5432
|
-
|
|
5622
|
+
const renderFn = renderDisplay || defaultRenderDisplay;
|
|
5623
|
+
const itemsFromDataList = dataList.map((item) => {
|
|
5624
|
+
const rendered = renderFn(item);
|
|
5625
|
+
return {
|
|
5626
|
+
label: typeof rendered === 'string' ? rendered : JSON.stringify(item), // Use string for filtering
|
|
5627
|
+
value: String(item[column_ref]),
|
|
5628
|
+
raw: item,
|
|
5629
|
+
};
|
|
5630
|
+
});
|
|
5631
|
+
// Add items from idMap that match currentValue but aren't in dataList
|
|
5632
|
+
// This ensures initial values are displayed correctly in the combobox
|
|
5633
|
+
const itemsFromIdMap = idMapItems
|
|
5634
|
+
.map((item) => {
|
|
5635
|
+
// Check if this item is already in itemsFromDataList
|
|
5636
|
+
const alreadyIncluded = itemsFromDataList.some((i) => i.value === String(item[column_ref]));
|
|
5637
|
+
if (alreadyIncluded)
|
|
5638
|
+
return null;
|
|
5639
|
+
const rendered = renderFn(item);
|
|
5640
|
+
return {
|
|
5641
|
+
label: typeof rendered === 'string' ? rendered : JSON.stringify(item),
|
|
5642
|
+
value: String(item[column_ref]),
|
|
5643
|
+
raw: item,
|
|
5644
|
+
};
|
|
5645
|
+
})
|
|
5646
|
+
.filter((item) => item !== null);
|
|
5647
|
+
return [...itemsFromIdMap, ...itemsFromDataList];
|
|
5648
|
+
}, [dataList, column_ref, renderDisplay, idMapItems]);
|
|
5433
5649
|
// Use filter hook for combobox
|
|
5434
5650
|
const { contains } = useFilter({ sensitivity: 'base' });
|
|
5435
5651
|
// Create collection for combobox
|
|
@@ -5453,31 +5669,54 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
|
|
|
5453
5669
|
setValue(colLabel, details.value[0] || '');
|
|
5454
5670
|
}
|
|
5455
5671
|
};
|
|
5672
|
+
// Track previous comboboxItems to avoid unnecessary updates
|
|
5673
|
+
const prevComboboxItemsRef = useRef('');
|
|
5674
|
+
const prevSearchTextRef = useRef('');
|
|
5456
5675
|
// Update collection and filter when data changes
|
|
5676
|
+
// This includes both search results and initial values from idMap
|
|
5457
5677
|
useEffect(() => {
|
|
5458
|
-
|
|
5678
|
+
// Create a stable string representation to compare (only value and label, not raw)
|
|
5679
|
+
const currentItemsKey = JSON.stringify(comboboxItems.map((item) => ({ value: item.value, label: item.label })));
|
|
5680
|
+
const itemsChanged = prevComboboxItemsRef.current !== currentItemsKey;
|
|
5681
|
+
const searchChanged = prevSearchTextRef.current !== searchText;
|
|
5682
|
+
// Only update if items or search actually changed
|
|
5683
|
+
if (!itemsChanged && !searchChanged) {
|
|
5684
|
+
return;
|
|
5685
|
+
}
|
|
5686
|
+
if (comboboxItems.length > 0 && itemsChanged) {
|
|
5459
5687
|
set(comboboxItems);
|
|
5460
|
-
|
|
5688
|
+
prevComboboxItemsRef.current = currentItemsKey;
|
|
5689
|
+
}
|
|
5690
|
+
// Apply filter to the collection using the immediate searchText for UI responsiveness
|
|
5691
|
+
if (searchChanged) {
|
|
5461
5692
|
if (searchText) {
|
|
5462
5693
|
filter(searchText);
|
|
5463
5694
|
}
|
|
5695
|
+
prevSearchTextRef.current = searchText;
|
|
5464
5696
|
}
|
|
5465
|
-
// Only depend on dataList and searchText, not comboboxItems (which is derived from dataList)
|
|
5466
5697
|
// set and filter are stable functions from useListCollection
|
|
5698
|
+
// comboboxItems and searchText are the only dependencies we care about
|
|
5467
5699
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
5468
|
-
}, [
|
|
5700
|
+
}, [comboboxItems, searchText]);
|
|
5469
5701
|
return (jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
5470
5702
|
gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: [isMultiple && currentValue.length > 0 && (jsx(Flex, { flexFlow: 'wrap', gap: 1, mb: 2, children: currentValue.map((id) => {
|
|
5471
5703
|
const item = idMap[id];
|
|
5704
|
+
// Show loading skeleton while fetching initial values
|
|
5705
|
+
if (item === undefined &&
|
|
5706
|
+
(isLoadingInitialValues || isFetchingInitialValues) &&
|
|
5707
|
+
missingIds.includes(id)) {
|
|
5708
|
+
return (jsx(Skeleton, { height: "24px", width: "100px", borderRadius: "md" }, id));
|
|
5709
|
+
}
|
|
5710
|
+
// Only show "not found" if we're not loading and item is still missing
|
|
5472
5711
|
if (item === undefined) {
|
|
5473
5712
|
return (jsx(Text, { fontSize: "sm", children: idPickerLabels?.undefined ?? formI18n.t('undefined') }, id));
|
|
5474
5713
|
}
|
|
5475
5714
|
return (jsx(Tag, { closable: true, onClick: () => {
|
|
5476
5715
|
const newValue = currentValue.filter((itemId) => itemId !== id);
|
|
5477
5716
|
setValue(colLabel, newValue);
|
|
5478
|
-
}, children:
|
|
5717
|
+
}, children: renderDisplay
|
|
5479
5718
|
? renderDisplay(item)
|
|
5480
|
-
: item
|
|
5719
|
+
: defaultRenderDisplay(item) }, id));
|
|
5481
5720
|
}) })), jsxs(Combobox.Root, { collection: collection, value: currentValue, onValueChange: handleValueChange, onInputValueChange: handleInputValueChange, multiple: isMultiple, closeOnSelect: !isMultiple, openOnClick: true, invalid: !!errors[colLabel], width: "100%", positioning: insideDialog
|
|
5482
5721
|
? { strategy: 'fixed', hideWhenDetached: true }
|
|
5483
5722
|
: undefined, children: [jsxs(Combobox.Control, { children: [jsx(Combobox.Input, { placeholder: idPickerLabels?.typeToSearch ?? formI18n.t('type_to_search') }), jsxs(Combobox.IndicatorGroup, { children: [(isFetching || isLoading || isPending) && jsx(Spinner, { size: "xs" }), isError && (jsx(Icon, { color: "fg.error", children: jsx(BiError, {}) })), !isMultiple && currentValue.length > 0 && (jsx(Combobox.ClearTrigger, { onClick: () => {
|
|
@@ -5566,15 +5805,15 @@ const extractErrorMessage = (error) => {
|
|
|
5566
5805
|
|
|
5567
5806
|
const NumberInputField = ({ schema, column, prefix, }) => {
|
|
5568
5807
|
const { setValue, formState: { errors }, watch, } = useFormContext();
|
|
5569
|
-
const { translate } = useSchemaContext();
|
|
5570
5808
|
const { required, gridColumn = 'span 12', gridRow = 'span 1', numberStorageType = 'number', } = schema;
|
|
5571
5809
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
5572
5810
|
const colLabel = `${prefix}${column}`;
|
|
5573
5811
|
const value = watch(`${colLabel}`);
|
|
5574
5812
|
const fieldError = getFieldError(errors, colLabel);
|
|
5575
|
-
|
|
5813
|
+
const formI18n = useFormI18n$1(column, prefix, schema);
|
|
5814
|
+
return (jsx(Field, { label: formI18n.label(), required: isRequired, gridColumn, gridRow, errorText: fieldError
|
|
5576
5815
|
? fieldError.includes('required')
|
|
5577
|
-
?
|
|
5816
|
+
? formI18n.required()
|
|
5578
5817
|
: fieldError
|
|
5579
5818
|
: undefined, invalid: !!fieldError, children: jsx(NumberInputRoot, { value: value, onValueChange: (details) => {
|
|
5580
5819
|
// Store as string or number based on configuration, default to number
|
|
@@ -5587,14 +5826,14 @@ const NumberInputField = ({ schema, column, prefix, }) => {
|
|
|
5587
5826
|
|
|
5588
5827
|
const ObjectInput = ({ schema, column, prefix }) => {
|
|
5589
5828
|
const { properties, gridColumn = 'span 12', gridRow = 'span 1', required, showLabel = true, } = schema;
|
|
5590
|
-
const { translate } = useSchemaContext();
|
|
5591
5829
|
const colLabel = `${prefix}${column}`;
|
|
5592
5830
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
5831
|
+
const formI18n = useFormI18n$1(column, prefix, schema);
|
|
5593
5832
|
const { formState: { errors }, } = useFormContext();
|
|
5594
5833
|
if (properties === undefined) {
|
|
5595
5834
|
throw new Error(`properties is undefined when using ObjectInput`);
|
|
5596
5835
|
}
|
|
5597
|
-
return (jsxs(Box, { gridRow, gridColumn, children: [showLabel && (jsxs(Box, { as: "label", children: [
|
|
5836
|
+
return (jsxs(Box, { gridRow, gridColumn, children: [showLabel && (jsxs(Box, { as: "label", children: [formI18n.label(), isRequired && jsx("span", { children: "*" })] })), jsx(Grid, { bgColor: { base: 'colorPalette.100', _dark: 'colorPalette.900' }, p: 2, borderRadius: 4, borderWidth: 1, borderColor: {
|
|
5598
5837
|
base: 'colorPalette.200',
|
|
5599
5838
|
_dark: 'colorPalette.800',
|
|
5600
5839
|
}, gap: "4", padding: '4', gridTemplateColumns: 'repeat(12, 1fr)', autoFlow: 'row', children: Object.keys(properties ?? {}).map((key) => {
|
|
@@ -5604,10 +5843,10 @@ const ObjectInput = ({ schema, column, prefix }) => {
|
|
|
5604
5843
|
prefix: `${prefix}${column}.`,
|
|
5605
5844
|
properties,
|
|
5606
5845
|
parentRequired: required }, `form-${colLabel}-${key}`));
|
|
5607
|
-
}) }), errors[`${column}`] && (jsx(Text, { color: 'red.400', children:
|
|
5846
|
+
}) }), errors[`${column}`] && (jsx(Text, { color: 'red.400', children: formI18n.required() }))] }));
|
|
5608
5847
|
};
|
|
5609
5848
|
|
|
5610
|
-
const RecordInput
|
|
5849
|
+
const RecordInput = ({ column, schema, prefix }) => {
|
|
5611
5850
|
const { formState: { errors }, setValue, getValues, } = useFormContext();
|
|
5612
5851
|
const { translate } = useSchemaContext();
|
|
5613
5852
|
const { required, gridColumn = 'span 12', gridRow = 'span 1' } = schema;
|
|
@@ -5616,9 +5855,8 @@ const RecordInput$1 = ({ column, schema, prefix }) => {
|
|
|
5616
5855
|
const [showNewEntries, setShowNewEntries] = useState(false);
|
|
5617
5856
|
const [newKey, setNewKey] = useState();
|
|
5618
5857
|
const [newValue, setNewValue] = useState();
|
|
5619
|
-
|
|
5620
|
-
|
|
5621
|
-
: undefined, invalid: !!errors[column], children: [entries.map(([key, value]) => {
|
|
5858
|
+
const formI18n = useFormI18n$1(column, prefix, schema);
|
|
5859
|
+
return (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]) => {
|
|
5622
5860
|
return (jsxs(Grid, { templateColumns: '1fr 1fr auto', gap: 1, children: [jsx(Input, { value: key, onChange: (e) => {
|
|
5623
5861
|
const filtered = entries.filter(([target]) => {
|
|
5624
5862
|
return target !== key;
|
|
@@ -5663,12 +5901,12 @@ const RecordInput$1 = ({ column, schema, prefix }) => {
|
|
|
5663
5901
|
|
|
5664
5902
|
const StringInputField = ({ column, schema, prefix, }) => {
|
|
5665
5903
|
const { register, formState: { errors }, } = useFormContext();
|
|
5666
|
-
const { translate } = useSchemaContext();
|
|
5667
5904
|
const { required, gridColumn = 'span 12', gridRow = 'span 1' } = schema;
|
|
5668
5905
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
5669
5906
|
const colLabel = `${prefix}${column}`;
|
|
5670
5907
|
const fieldError = getFieldError(errors, colLabel);
|
|
5671
|
-
|
|
5908
|
+
const formI18n = useFormI18n$1(column, prefix, schema);
|
|
5909
|
+
return (jsx(Fragment, { children: jsx(Field, { label: formI18n.label(), required: isRequired, gridColumn: gridColumn, gridRow: gridRow, errorText: fieldError, invalid: !!fieldError, children: jsx(Input, { ...register(`${colLabel}`, { required: isRequired }), autoComplete: "off" }) }) }));
|
|
5672
5910
|
};
|
|
5673
5911
|
|
|
5674
5912
|
const RadioCardItem = React.forwardRef(function RadioCardItem(props, ref) {
|
|
@@ -5853,17 +6091,17 @@ Textarea.displayName = "Textarea";
|
|
|
5853
6091
|
|
|
5854
6092
|
const TextAreaInput = ({ column, schema, prefix, }) => {
|
|
5855
6093
|
const { register, formState: { errors }, } = useFormContext();
|
|
5856
|
-
const { translate } = useSchemaContext();
|
|
5857
6094
|
const { required, gridColumn = 'span 12', gridRow = 'span 1' } = schema;
|
|
5858
6095
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
5859
6096
|
const colLabel = `${prefix}${column}`;
|
|
5860
6097
|
const form = useFormContext();
|
|
5861
6098
|
const { setValue, watch } = form;
|
|
5862
6099
|
const fieldError = getFieldError(errors, colLabel);
|
|
6100
|
+
const formI18n = useFormI18n$1(column, prefix, schema);
|
|
5863
6101
|
const watchValue = watch(colLabel);
|
|
5864
|
-
return (jsx(Fragment, { children: jsx(Field, { label:
|
|
6102
|
+
return (jsx(Fragment, { children: jsx(Field, { label: formI18n.label(), required: isRequired, gridColumn: gridColumn ?? 'span 4', gridRow: gridRow ?? 'span 1', display: "grid", errorText: fieldError
|
|
5865
6103
|
? fieldError.includes('required')
|
|
5866
|
-
?
|
|
6104
|
+
? formI18n.required()
|
|
5867
6105
|
: fieldError
|
|
5868
6106
|
: undefined, invalid: !!fieldError, children: jsx(Textarea, { value: watchValue, onChange: (value) => setValue(colLabel, value) }) }) }));
|
|
5869
6107
|
};
|
|
@@ -6185,10 +6423,11 @@ onChange = (_newValue) => { }, timezone = 'Asia/Hong_Kong', startTime, selectedD
|
|
|
6185
6423
|
dayjs.extend(timezone);
|
|
6186
6424
|
const TimePicker = ({ column, schema, prefix }) => {
|
|
6187
6425
|
const { watch, formState: { errors }, setValue, } = useFormContext();
|
|
6188
|
-
const {
|
|
6426
|
+
const { timezone, insideDialog } = useSchemaContext();
|
|
6189
6427
|
const { required, gridColumn = 'span 12', gridRow = 'span 1', timeFormat = 'HH:mm:ssZ', displayTimeFormat = 'hh:mm A', } = schema;
|
|
6190
6428
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
6191
6429
|
const colLabel = `${prefix}${column}`;
|
|
6430
|
+
const formI18n = useFormI18n$1(column, prefix, schema);
|
|
6192
6431
|
const [open, setOpen] = useState(false);
|
|
6193
6432
|
const value = watch(colLabel);
|
|
6194
6433
|
const displayedTime = dayjs(`1970-01-01T${value}`).tz(timezone).isValid()
|
|
@@ -6243,10 +6482,8 @@ const TimePicker = ({ column, schema, prefix }) => {
|
|
|
6243
6482
|
const timeString = getTimeString(newHour, newMinute, newMeridiem);
|
|
6244
6483
|
setValue(colLabel, timeString, { shouldValidate: true, shouldDirty: true });
|
|
6245
6484
|
};
|
|
6246
|
-
return (jsx(Field, { label:
|
|
6247
|
-
gridRow, errorText: errors[`${colLabel}`]
|
|
6248
|
-
? translate.t(removeIndex(`${colLabel}.field_required`))
|
|
6249
|
-
: undefined, invalid: !!errors[colLabel], children: jsxs(Popover.Root, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, children: [jsx(Popover.Trigger, { asChild: true, children: jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
|
|
6485
|
+
return (jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
6486
|
+
gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: jsxs(Popover.Root, { open: open, onOpenChange: (e) => setOpen(e.open), closeOnInteractOutside: true, children: [jsx(Popover.Trigger, { asChild: true, children: jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
|
|
6250
6487
|
setOpen(true);
|
|
6251
6488
|
}, justifyContent: 'start', children: [jsx(IoMdClock, {}), !!value ? `${displayedTime}` : ''] }) }), insideDialog ? (jsx(Popover.Positioner, { children: jsx(Popover.Content, { maxH: "70vh", overflowY: "auto", children: jsx(Popover.Body, { overflow: "visible", children: jsx(TimePicker$1, { hour: hour, setHour: setHour, minute: minute, setMinute: setMinute, meridiem: meridiem, setMeridiem: setMeridiem, onChange: handleTimeChange, meridiemLabel: {
|
|
6252
6489
|
am: translate.t(`common.am`, { defaultValue: 'AM' }),
|
|
@@ -7136,7 +7373,7 @@ dayjs.extend(timezone);
|
|
|
7136
7373
|
const DateTimePicker = ({ column, schema, prefix, }) => {
|
|
7137
7374
|
const { watch, formState: { errors }, setValue, } = useFormContext();
|
|
7138
7375
|
const { timezone, dateTimePickerLabels, insideDialog } = useSchemaContext();
|
|
7139
|
-
const formI18n = useFormI18n(column, prefix);
|
|
7376
|
+
const formI18n = useFormI18n$1(column, prefix, schema);
|
|
7140
7377
|
const { required, gridColumn = 'span 12', gridRow = 'span 1', displayDateFormat = 'YYYY-MM-DD HH:mm:ss',
|
|
7141
7378
|
// with timezone
|
|
7142
7379
|
dateFormat = 'YYYY-MM-DD[T]HH:mm:ssZ', } = schema;
|
|
@@ -7278,7 +7515,7 @@ const SchemaRenderer = ({ schema, prefix, column, }) => {
|
|
|
7278
7515
|
if (innerProperties) {
|
|
7279
7516
|
return jsx(ObjectInput, { schema: colSchema, prefix, column });
|
|
7280
7517
|
}
|
|
7281
|
-
return jsx(RecordInput
|
|
7518
|
+
return jsx(RecordInput, { schema: colSchema, prefix, column });
|
|
7282
7519
|
}
|
|
7283
7520
|
if (type === 'array') {
|
|
7284
7521
|
if (variant === 'id-picker') {
|
|
@@ -7332,32 +7569,30 @@ const ColumnRenderer = ({ column, properties, prefix, parentRequired, }) => {
|
|
|
7332
7569
|
};
|
|
7333
7570
|
|
|
7334
7571
|
const ArrayViewer = ({ schema, column, prefix }) => {
|
|
7335
|
-
const { gridColumn =
|
|
7336
|
-
const { translate } = useSchemaContext();
|
|
7572
|
+
const { gridColumn = 'span 12', gridRow = 'span 1', required, items, } = schema;
|
|
7337
7573
|
const colLabel = `${prefix}${column}`;
|
|
7338
7574
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
7575
|
+
const formI18n = useFormI18n$1(column, prefix, schema);
|
|
7339
7576
|
const { watch, formState: { errors }, } = useFormContext();
|
|
7340
7577
|
const values = watch(colLabel) ?? [];
|
|
7341
|
-
return (jsxs(Box, { gridRow, gridColumn, children: [jsxs(Box, { as: "label", gridColumn:
|
|
7342
|
-
base:
|
|
7343
|
-
_dark:
|
|
7344
|
-
}, children: jsx(Grid, { gap: "4", gridTemplateColumns:
|
|
7578
|
+
return (jsxs(Box, { gridRow, gridColumn, children: [jsxs(Box, { as: "label", gridColumn: '1/span12', children: [formI18n.label(), isRequired && jsx("span", { children: "*" })] }), jsx(Flex, { flexFlow: 'column', gap: 1, children: values.map((field, index) => (jsx(Flex, { flexFlow: 'column', bgColor: { base: 'colorPalette.100', _dark: 'colorPalette.900' }, p: '2', borderRadius: 'md', borderWidth: 'thin', borderColor: {
|
|
7579
|
+
base: 'colorPalette.200',
|
|
7580
|
+
_dark: 'colorPalette.800',
|
|
7581
|
+
}, children: jsx(Grid, { gap: "4", gridTemplateColumns: 'repeat(12, 1fr)', autoFlow: 'row', children: jsx(SchemaViewer, { column: `${index}`,
|
|
7345
7582
|
prefix: `${colLabel}.`,
|
|
7346
7583
|
// @ts-expect-error find suitable types
|
|
7347
|
-
schema: { showLabel: false, ...(items ?? {}) } }) }) }, `form-${prefix}${column}.${index}`))) }), errors[`${column}`] && (jsx(Text, { color:
|
|
7584
|
+
schema: { showLabel: false, ...(items ?? {}) } }) }) }, `form-${prefix}${column}.${index}`))) }), errors[`${column}`] && (jsx(Text, { color: 'red.400', children: formI18n.required() }))] }));
|
|
7348
7585
|
};
|
|
7349
7586
|
|
|
7350
7587
|
const BooleanViewer = ({ schema, column, prefix, }) => {
|
|
7351
7588
|
const { watch, formState: { errors }, } = useFormContext();
|
|
7352
|
-
const {
|
|
7353
|
-
const { required, gridColumn = "span 12", gridRow = "span 1" } = schema;
|
|
7589
|
+
const { required, gridColumn = 'span 12', gridRow = 'span 1' } = schema;
|
|
7354
7590
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
7355
7591
|
const colLabel = `${prefix}${column}`;
|
|
7356
7592
|
const value = watch(colLabel);
|
|
7357
|
-
|
|
7358
|
-
|
|
7359
|
-
|
|
7360
|
-
: translate.t(removeIndex(`${colLabel}.false`)) }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
|
|
7593
|
+
const formI18n = useFormI18n$1(column, prefix, schema);
|
|
7594
|
+
return (jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
7595
|
+
gridRow, children: [jsx(Text, { children: value ? formI18n.t('true') : formI18n.t('false') }), errors[`${column}`] && (jsx(Text, { color: 'red.400', children: formI18n.required() }))] }));
|
|
7361
7596
|
};
|
|
7362
7597
|
|
|
7363
7598
|
const CustomViewer = ({ column, schema, prefix }) => {
|
|
@@ -7374,19 +7609,22 @@ const CustomViewer = ({ column, schema, prefix }) => {
|
|
|
7374
7609
|
|
|
7375
7610
|
const DateViewer = ({ column, schema, prefix }) => {
|
|
7376
7611
|
const { watch, formState: { errors }, } = useFormContext();
|
|
7377
|
-
const {
|
|
7378
|
-
const { required, gridColumn =
|
|
7612
|
+
const { timezone } = useSchemaContext();
|
|
7613
|
+
const { required, gridColumn = 'span 4', gridRow = 'span 1', displayDateFormat = 'YYYY-MM-DD', } = schema;
|
|
7379
7614
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
7380
7615
|
const colLabel = `${prefix}${column}`;
|
|
7381
7616
|
const selectedDate = watch(colLabel);
|
|
7382
|
-
const
|
|
7383
|
-
|
|
7384
|
-
|
|
7617
|
+
const formI18n = useFormI18n$1(column, prefix, schema);
|
|
7618
|
+
const displayDate = dayjs(selectedDate)
|
|
7619
|
+
.tz(timezone)
|
|
7620
|
+
.format(displayDateFormat);
|
|
7621
|
+
return (jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
7622
|
+
gridRow, children: [jsxs(Text, { children: [" ", selectedDate !== undefined ? displayDate : ''] }), errors[`${column}`] && (jsx(Text, { color: 'red.400', children: formI18n.required() }))] }));
|
|
7385
7623
|
};
|
|
7386
7624
|
|
|
7387
7625
|
const EnumViewer = ({ column, isMultiple = false, schema, prefix, }) => {
|
|
7388
7626
|
const { watch, formState: { errors }, } = useFormContext();
|
|
7389
|
-
const formI18n = useFormI18n(column, prefix);
|
|
7627
|
+
const formI18n = useFormI18n$1(column, prefix);
|
|
7390
7628
|
const { required } = schema;
|
|
7391
7629
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
7392
7630
|
const { gridColumn = "span 12", gridRow = "span 1", renderDisplay } = schema;
|
|
@@ -7407,54 +7645,56 @@ const EnumViewer = ({ column, isMultiple = false, schema, prefix, }) => {
|
|
|
7407
7645
|
|
|
7408
7646
|
const FileViewer = ({ column, schema, prefix }) => {
|
|
7409
7647
|
const { watch } = useFormContext();
|
|
7410
|
-
const {
|
|
7411
|
-
const { required, gridColumn = "span 12", gridRow = "span 1", } = schema;
|
|
7648
|
+
const { required, gridColumn = 'span 12', gridRow = 'span 1', } = schema;
|
|
7412
7649
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
7413
7650
|
const currentFiles = (watch(column) ?? []);
|
|
7414
|
-
const
|
|
7415
|
-
return (jsx(Field, { label:
|
|
7416
|
-
return (jsx(Card.Root, { variant:
|
|
7651
|
+
const formI18n = useFormI18n$1(column, prefix, schema);
|
|
7652
|
+
return (jsx(Field, { label: formI18n.label(), required: isRequired, gridColumn: gridColumn, gridRow: gridRow, display: 'grid', gridTemplateRows: 'auto 1fr auto', alignItems: 'stretch', children: jsx(Flex, { flexFlow: 'column', gap: 1, children: currentFiles.map((file) => {
|
|
7653
|
+
return (jsx(Card.Root, { variant: 'subtle', children: jsxs(Card.Body, { gap: "2", display: 'flex', flexFlow: 'row', alignItems: 'center', padding: '2', children: [file.type.startsWith('image/') && (jsx(Image, { src: URL.createObjectURL(file), alt: file.name, boxSize: "50px", objectFit: "cover", borderRadius: "md", marginRight: "2" })), jsx(Box, { children: file.name })] }) }, file.name));
|
|
7417
7654
|
}) }) }));
|
|
7418
7655
|
};
|
|
7419
7656
|
|
|
7420
7657
|
const IdViewer = ({ column, schema, prefix, isMultiple = false, }) => {
|
|
7421
7658
|
const { watch, formState: { errors }, } = useFormContext();
|
|
7422
7659
|
const { idMap, translate } = useSchemaContext();
|
|
7423
|
-
const { required, gridColumn =
|
|
7660
|
+
const { required, gridColumn = 'span 12', gridRow = 'span 1', renderDisplay, foreign_key, } = schema;
|
|
7424
7661
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
7425
|
-
const
|
|
7662
|
+
const formI18n = useFormI18n(column, prefix, schema);
|
|
7426
7663
|
const colLabel = `${prefix}${column}`;
|
|
7427
7664
|
const watchId = watch(colLabel);
|
|
7428
7665
|
const watchIds = (watch(colLabel) ?? []);
|
|
7429
7666
|
const getPickedValue = () => {
|
|
7430
7667
|
if (Object.keys(idMap).length <= 0) {
|
|
7431
|
-
return
|
|
7668
|
+
return '';
|
|
7432
7669
|
}
|
|
7433
7670
|
const record = idMap[watchId];
|
|
7434
7671
|
if (record === undefined) {
|
|
7435
|
-
return
|
|
7672
|
+
return '';
|
|
7436
7673
|
}
|
|
7437
|
-
|
|
7674
|
+
const rendered = renderDisplay
|
|
7675
|
+
? renderDisplay(record)
|
|
7676
|
+
: defaultRenderDisplay(record);
|
|
7677
|
+
return typeof rendered === 'string' ? rendered : JSON.stringify(record);
|
|
7438
7678
|
};
|
|
7439
|
-
return (jsxs(Field, { label:
|
|
7440
|
-
gridRow, children: [isMultiple && (jsx(Flex, { flexFlow:
|
|
7679
|
+
return (jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
7680
|
+
gridRow, children: [isMultiple && (jsx(Flex, { flexFlow: 'wrap', gap: 1, children: watchIds.map((id) => {
|
|
7441
7681
|
const item = idMap[id];
|
|
7442
7682
|
if (item === undefined) {
|
|
7443
7683
|
return (jsx(Text, { children: translate.t(removeIndex(`${colLabel}.undefined`)) }, id));
|
|
7444
7684
|
}
|
|
7445
|
-
return (jsx(Tag, { closable: true, children:
|
|
7685
|
+
return (jsx(Tag, { closable: true, children: renderDisplay
|
|
7446
7686
|
? renderDisplay(item)
|
|
7447
|
-
: item
|
|
7448
|
-
}) })), !isMultiple && jsx(Text, { children: getPickedValue() }), errors[`${colLabel}`] && (jsx(Text, { color:
|
|
7687
|
+
: defaultRenderDisplay(item) }, id));
|
|
7688
|
+
}) })), !isMultiple && jsx(Text, { children: getPickedValue() }), errors[`${colLabel}`] && (jsx(Text, { color: 'red.400', children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
|
|
7449
7689
|
};
|
|
7450
7690
|
|
|
7451
7691
|
const NumberViewer = ({ schema, column, prefix, }) => {
|
|
7452
7692
|
const { watch, formState: { errors }, } = useFormContext();
|
|
7453
|
-
const { translate } = useSchemaContext();
|
|
7454
7693
|
const { required, gridColumn = 'span 12', gridRow = 'span 1' } = schema;
|
|
7455
7694
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
7456
7695
|
const colLabel = `${prefix}${column}`;
|
|
7457
7696
|
const value = watch(colLabel);
|
|
7697
|
+
const formI18n = useFormI18n$1(column, prefix, schema);
|
|
7458
7698
|
// Format the value for display if formatOptions are provided
|
|
7459
7699
|
const formatValue = (val) => {
|
|
7460
7700
|
if (val === undefined || val === null || val === '')
|
|
@@ -7473,90 +7713,49 @@ const NumberViewer = ({ schema, column, prefix, }) => {
|
|
|
7473
7713
|
}
|
|
7474
7714
|
return String(val);
|
|
7475
7715
|
};
|
|
7476
|
-
return (jsxs(Field, { label:
|
|
7716
|
+
return (jsxs(Field, { label: formI18n.label(), required: isRequired, gridColumn, gridRow, children: [jsx(Text, { children: formatValue(value) }), errors[`${column}`] && (jsx(Text, { color: 'red.400', children: formI18n.required() }))] }));
|
|
7477
7717
|
};
|
|
7478
7718
|
|
|
7479
7719
|
const ObjectViewer = ({ schema, column, prefix }) => {
|
|
7480
|
-
const { properties, gridColumn =
|
|
7481
|
-
const { translate } = useSchemaContext();
|
|
7720
|
+
const { properties, gridColumn = 'span 12', gridRow = 'span 1', required, showLabel = true, } = schema;
|
|
7482
7721
|
const colLabel = `${prefix}${column}`;
|
|
7483
7722
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
7723
|
+
const formI18n = useFormI18n$1(column, prefix, schema);
|
|
7484
7724
|
const { formState: { errors }, } = useFormContext();
|
|
7485
7725
|
if (properties === undefined) {
|
|
7486
7726
|
throw new Error(`properties is undefined when using ObjectInput`);
|
|
7487
7727
|
}
|
|
7488
|
-
return (jsxs(Box, { gridRow, gridColumn, children: [showLabel && (jsxs(Box, { as: "label", children: [
|
|
7489
|
-
base:
|
|
7490
|
-
_dark:
|
|
7728
|
+
return (jsxs(Box, { gridRow, gridColumn, children: [showLabel && (jsxs(Box, { as: "label", children: [formI18n.label(), isRequired && jsx("span", { children: "*" })] })), jsx(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: {
|
|
7729
|
+
base: 'colorPalette.200',
|
|
7730
|
+
_dark: 'colorPalette.800',
|
|
7491
7731
|
}, children: Object.keys(properties ?? {}).map((key) => {
|
|
7492
7732
|
return (
|
|
7493
7733
|
// @ts-expect-error find suitable types
|
|
7494
7734
|
jsx(ColumnViewer, { column: `${key}`,
|
|
7495
7735
|
prefix: `${prefix}${column}.`,
|
|
7496
7736
|
properties }, `form-objectviewer-${colLabel}-${key}`));
|
|
7497
|
-
}) }), errors[`${column}`] && (jsx(Text, { color:
|
|
7737
|
+
}) }), errors[`${column}`] && (jsx(Text, { color: 'red.400', children: formI18n.required() }))] }));
|
|
7498
7738
|
};
|
|
7499
7739
|
|
|
7500
|
-
const
|
|
7501
|
-
const { formState: { errors },
|
|
7502
|
-
const {
|
|
7503
|
-
const { required, gridColumn = "span 12", gridRow = "span 1" } = schema;
|
|
7740
|
+
const RecordViewer = ({ column, schema, prefix }) => {
|
|
7741
|
+
const { formState: { errors }, getValues, } = useFormContext();
|
|
7742
|
+
const { required, gridColumn = 'span 12', gridRow = 'span 1' } = schema;
|
|
7504
7743
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
7505
7744
|
const entries = Object.entries(getValues(column) ?? {});
|
|
7506
|
-
const
|
|
7507
|
-
|
|
7508
|
-
|
|
7509
|
-
|
|
7510
|
-
return (jsxs(Grid, { templateColumns: "1fr 1fr auto", gap: 1, children: [jsx(Input, { value: key, onChange: (e) => {
|
|
7511
|
-
const filtered = entries.filter(([target]) => {
|
|
7512
|
-
return target !== key;
|
|
7513
|
-
});
|
|
7514
|
-
setValue(column, Object.fromEntries([...filtered, [e.target.value, value]]));
|
|
7515
|
-
}, autoComplete: "off" }), jsx(Input, { value: value, onChange: (e) => {
|
|
7516
|
-
setValue(column, {
|
|
7517
|
-
...getValues(column),
|
|
7518
|
-
[key]: e.target.value,
|
|
7519
|
-
});
|
|
7520
|
-
}, autoComplete: "off" }), jsx(IconButton, { variant: "ghost", onClick: () => {
|
|
7521
|
-
const filtered = entries.filter(([target]) => {
|
|
7522
|
-
return target !== key;
|
|
7523
|
-
});
|
|
7524
|
-
setValue(column, Object.fromEntries([...filtered]));
|
|
7525
|
-
}, children: jsx(CgClose, {}) })] }));
|
|
7526
|
-
}), jsx(Show, { when: showNewEntries, children: jsxs(Card.Root, { children: [jsx(Card.Body, { gap: "2", children: jsxs(Grid, { templateColumns: "1fr 1fr auto", gap: 1, children: [jsx(Input, { value: newKey, onChange: (e) => {
|
|
7527
|
-
setNewKey(e.target.value);
|
|
7528
|
-
}, autoComplete: "off" }), jsx(Input, { value: newValue, onChange: (e) => {
|
|
7529
|
-
setNewValue(e.target.value);
|
|
7530
|
-
}, autoComplete: "off" })] }) }), jsxs(Card.Footer, { justifyContent: "flex-end", children: [jsx(IconButton, { variant: "subtle", onClick: () => {
|
|
7531
|
-
setShowNewEntries(false);
|
|
7532
|
-
setNewKey(undefined);
|
|
7533
|
-
setNewValue(undefined);
|
|
7534
|
-
}, children: jsx(CgClose, {}) }), jsx(Button, { onClick: () => {
|
|
7535
|
-
if (!!newKey === false) {
|
|
7536
|
-
setShowNewEntries(false);
|
|
7537
|
-
setNewKey(undefined);
|
|
7538
|
-
setNewValue(undefined);
|
|
7539
|
-
return;
|
|
7540
|
-
}
|
|
7541
|
-
setValue(column, Object.fromEntries([...entries, [newKey, newValue]]));
|
|
7542
|
-
setShowNewEntries(false);
|
|
7543
|
-
setNewKey(undefined);
|
|
7544
|
-
setNewValue(undefined);
|
|
7545
|
-
}, children: translate.t(`${column}.save`) })] })] }) }), jsx(Button, { onClick: () => {
|
|
7546
|
-
setShowNewEntries(true);
|
|
7547
|
-
setNewKey(undefined);
|
|
7548
|
-
setNewValue(undefined);
|
|
7549
|
-
}, children: translate.t(`${column}.addNew`) }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: translate.t(`${column}.field_required`) }))] }));
|
|
7745
|
+
const formI18n = useFormI18n$1(column, prefix, schema);
|
|
7746
|
+
return (jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn, gridRow, children: [entries.length === 0 ? (jsx(Text, { color: "gray.500", children: "No entries" })) : (jsx(Grid, { templateColumns: '1fr 1fr', gap: 2, children: entries.map(([key, value]) => {
|
|
7747
|
+
return (jsxs(Grid, { templateColumns: '1fr 1fr', gap: 2, children: [jsxs(Text, { fontWeight: "medium", children: [key, ":"] }), jsx(Text, { children: String(value ?? '') })] }, key));
|
|
7748
|
+
}) })), errors[`${column}`] && (jsx(Text, { color: 'red.400', children: formI18n.required() }))] }));
|
|
7550
7749
|
};
|
|
7551
7750
|
|
|
7552
7751
|
const StringViewer = ({ column, schema, prefix, }) => {
|
|
7553
7752
|
const { watch, formState: { errors }, } = useFormContext();
|
|
7554
|
-
const {
|
|
7555
|
-
const { required, gridColumn = "span 12", gridRow = "span 1" } = schema;
|
|
7753
|
+
const { required, gridColumn = 'span 12', gridRow = 'span 1' } = schema;
|
|
7556
7754
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
7557
7755
|
const colLabel = `${prefix}${column}`;
|
|
7558
7756
|
const value = watch(colLabel);
|
|
7559
|
-
|
|
7757
|
+
const formI18n = useFormI18n$1(column, prefix, schema);
|
|
7758
|
+
return (jsx(Fragment, { children: jsxs(Field, { label: formI18n.label(), required: isRequired, gridColumn: gridColumn ?? 'span 4', gridRow: gridRow ?? 'span 1', children: [jsx(Text, { children: value }), errors[colLabel] && (jsx(Text, { color: 'red.400', children: formI18n.required() }))] }) }));
|
|
7560
7759
|
};
|
|
7561
7760
|
|
|
7562
7761
|
const TagViewer = ({ column, schema, prefix }) => {
|
|
@@ -7646,40 +7845,44 @@ const TagViewer = ({ column, schema, prefix }) => {
|
|
|
7646
7845
|
|
|
7647
7846
|
const TextAreaViewer = ({ column, schema, prefix, }) => {
|
|
7648
7847
|
const { watch, formState: { errors }, } = useFormContext();
|
|
7649
|
-
const {
|
|
7650
|
-
const { required, gridColumn = "span 12", gridRow = "span 1" } = schema;
|
|
7848
|
+
const { required, gridColumn = 'span 12', gridRow = 'span 1' } = schema;
|
|
7651
7849
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
7652
7850
|
const colLabel = `${prefix}${column}`;
|
|
7653
7851
|
const value = watch(colLabel);
|
|
7654
|
-
|
|
7852
|
+
const formI18n = useFormI18n$1(column, prefix, schema);
|
|
7853
|
+
return (jsx(Fragment, { children: jsxs(Field, { label: formI18n.label(), required: isRequired, gridColumn: gridColumn, gridRow: gridRow, children: [jsx(Text, { whiteSpace: "pre-wrap", children: value }), ' ', errors[colLabel] && (jsx(Text, { color: 'red.400', children: formI18n.required() }))] }) }));
|
|
7655
7854
|
};
|
|
7656
7855
|
|
|
7657
7856
|
const TimeViewer = ({ column, schema, prefix }) => {
|
|
7658
7857
|
const { watch, formState: { errors }, } = useFormContext();
|
|
7659
|
-
const {
|
|
7660
|
-
const { required, gridColumn =
|
|
7858
|
+
const { timezone } = useSchemaContext();
|
|
7859
|
+
const { required, gridColumn = 'span 12', gridRow = 'span 1', displayTimeFormat = 'hh:mm A', } = schema;
|
|
7661
7860
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
7662
7861
|
const colLabel = `${prefix}${column}`;
|
|
7663
7862
|
const selectedDate = watch(colLabel);
|
|
7863
|
+
const formI18n = useFormI18n$1(column, prefix, schema);
|
|
7664
7864
|
const displayedTime = dayjs(`1970-01-01T${selectedDate}`)
|
|
7665
7865
|
.tz(timezone)
|
|
7666
7866
|
.isValid()
|
|
7667
7867
|
? dayjs(`1970-01-01T${selectedDate}`).tz(timezone).format(displayTimeFormat)
|
|
7668
|
-
:
|
|
7669
|
-
return (jsxs(Field, { label:
|
|
7670
|
-
gridRow, children: [jsx(Text, { children: displayedTime }), errors[`${column}`] && (jsx(Text, { color:
|
|
7868
|
+
: '';
|
|
7869
|
+
return (jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
7870
|
+
gridRow, children: [jsx(Text, { children: displayedTime }), errors[`${column}`] && (jsx(Text, { color: 'red.400', children: formI18n.required() }))] }));
|
|
7671
7871
|
};
|
|
7672
7872
|
|
|
7673
7873
|
const DateTimeViewer = ({ column, schema, prefix }) => {
|
|
7674
7874
|
const { watch, formState: { errors }, } = useFormContext();
|
|
7675
|
-
const {
|
|
7676
|
-
const { required, gridColumn =
|
|
7875
|
+
const { timezone } = useSchemaContext();
|
|
7876
|
+
const { required, gridColumn = 'span 4', gridRow = 'span 1', displayDateFormat = 'YYYY-MM-DD HH:mm:ss', } = schema;
|
|
7677
7877
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
7678
7878
|
const colLabel = `${prefix}${column}`;
|
|
7679
7879
|
const selectedDate = watch(colLabel);
|
|
7680
|
-
const
|
|
7681
|
-
|
|
7682
|
-
|
|
7880
|
+
const formI18n = useFormI18n$1(column, prefix, schema);
|
|
7881
|
+
const displayDate = dayjs(selectedDate)
|
|
7882
|
+
.tz(timezone)
|
|
7883
|
+
.format(displayDateFormat);
|
|
7884
|
+
return (jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
7885
|
+
gridRow, children: [jsxs(Text, { children: [" ", selectedDate !== undefined ? displayDate : ''] }), errors[`${column}`] && (jsx(Text, { color: 'red.400', children: formI18n.required() }))] }));
|
|
7683
7886
|
};
|
|
7684
7887
|
|
|
7685
7888
|
const SchemaViewer = ({ schema, prefix, column, }) => {
|
|
@@ -7720,7 +7923,7 @@ const SchemaViewer = ({ schema, prefix, column, }) => {
|
|
|
7720
7923
|
if (innerProperties) {
|
|
7721
7924
|
return jsx(ObjectViewer, { schema: colSchema, prefix, column });
|
|
7722
7925
|
}
|
|
7723
|
-
return jsx(
|
|
7926
|
+
return jsx(RecordViewer, { schema: colSchema, prefix, column });
|
|
7724
7927
|
}
|
|
7725
7928
|
if (type === 'array') {
|
|
7726
7929
|
if (variant === 'id-picker') {
|
|
@@ -7768,7 +7971,7 @@ const ColumnViewer = ({ column, properties, prefix, }) => {
|
|
|
7768
7971
|
};
|
|
7769
7972
|
|
|
7770
7973
|
const SubmitButton = () => {
|
|
7771
|
-
const { translate, setValidatedData, setIsError, setIsConfirming,
|
|
7974
|
+
const { translate, setValidatedData, setIsError, setIsConfirming, requireConfirmation, onFormSubmit, formButtonLabels, } = useSchemaContext();
|
|
7772
7975
|
const methods = useFormContext();
|
|
7773
7976
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
7774
7977
|
const onValid = (data) => {
|
|
@@ -7797,11 +8000,11 @@ const SubmitButton = () => {
|
|
|
7797
8000
|
};
|
|
7798
8001
|
return (jsx(Button$1, { onClick: () => {
|
|
7799
8002
|
methods.handleSubmit(onValid)();
|
|
7800
|
-
}, formNoValidate: true, children: translate.t('submit') }));
|
|
8003
|
+
}, formNoValidate: true, children: formButtonLabels?.submit ?? translate.t('submit') }));
|
|
7801
8004
|
};
|
|
7802
8005
|
|
|
7803
8006
|
const FormBody = () => {
|
|
7804
|
-
const { schema, order, ignore, include, translate, isSuccess, setIsSuccess, isError, setIsError, isSubmiting, setIsSubmiting, isConfirming, setIsConfirming, validatedData, setValidatedData, error, getUpdatedData, customErrorRenderer, customSuccessRenderer, displayConfig, onFormSubmit, } = useSchemaContext();
|
|
8007
|
+
const { schema, order, ignore, include, translate, isSuccess, setIsSuccess, isError, setIsError, isSubmiting, setIsSubmiting, isConfirming, setIsConfirming, validatedData, setValidatedData, error, getUpdatedData, customErrorRenderer, customSuccessRenderer, displayConfig, onFormSubmit, formButtonLabels, } = useSchemaContext();
|
|
7805
8008
|
const { showSubmitButton, showResetButton } = displayConfig;
|
|
7806
8009
|
const methods = useFormContext();
|
|
7807
8010
|
const { properties } = schema;
|
|
@@ -7831,7 +8034,7 @@ const FormBody = () => {
|
|
|
7831
8034
|
if (customSuccessRenderer) {
|
|
7832
8035
|
return customSuccessRenderer(resetHandler);
|
|
7833
8036
|
}
|
|
7834
|
-
return (jsxs(Flex, { flexFlow: 'column', gap: "2", children: [jsxs(Alert.Root, { status: "success", children: [jsx(Alert.Indicator, {}), jsx(Alert.Content, { children: jsx(Alert.Title, { children: translate.t('submit_success') }) })] }), jsx(Flex, { justifyContent: 'end', children: jsx(Button$1, { onClick: resetHandler, formNoValidate: true, children: translate.t('submit_again') }) })] }));
|
|
8037
|
+
return (jsxs(Flex, { flexFlow: 'column', gap: "2", children: [jsxs(Alert.Root, { status: "success", children: [jsx(Alert.Indicator, {}), jsx(Alert.Content, { children: jsx(Alert.Title, { children: translate.t('submit_success') }) })] }), jsx(Flex, { justifyContent: 'end', children: jsx(Button$1, { onClick: resetHandler, formNoValidate: true, children: formButtonLabels?.submitAgain ?? translate.t('submit_again') }) })] }));
|
|
7835
8038
|
}
|
|
7836
8039
|
if (isConfirming) {
|
|
7837
8040
|
return (jsxs(Flex, { flexFlow: 'column', gap: "2", children: [jsx(Grid, { gap: 4, gridTemplateColumns: 'repeat(12, 1fr)', gridTemplateRows: 'repeat(12, max-content)', autoFlow: 'row', children: ordered.map((column) => {
|
|
@@ -7842,9 +8045,9 @@ const FormBody = () => {
|
|
|
7842
8045
|
properties: properties, prefix: ``, column }, `form-viewer-${column}`));
|
|
7843
8046
|
}) }), jsxs(Flex, { justifyContent: 'end', gap: '2', children: [jsx(Button$1, { onClick: () => {
|
|
7844
8047
|
setIsConfirming(false);
|
|
7845
|
-
}, variant: 'subtle', children: translate.t('cancel') }), jsx(Button$1, { onClick: () => {
|
|
8048
|
+
}, variant: 'subtle', children: formButtonLabels?.cancel ?? translate.t('cancel') }), jsx(Button$1, { onClick: () => {
|
|
7846
8049
|
onFormSubmit(validatedData);
|
|
7847
|
-
}, children: translate.t('confirm') })] }), isSubmiting && (jsx(Box, { pos: "absolute", inset: "0", bg: "bg/80", children: jsx(Center, { h: "full", children: jsx(Spinner, { color: "teal.500" }) }) })), isError && customErrorRenderer && customErrorRenderer(error)] }));
|
|
8050
|
+
}, children: formButtonLabels?.confirm ?? translate.t('confirm') })] }), isSubmiting && (jsx(Box, { pos: "absolute", inset: "0", bg: "bg/80", children: jsx(Center, { h: "full", children: jsx(Spinner, { color: "teal.500" }) }) })), isError && customErrorRenderer && customErrorRenderer(error)] }));
|
|
7848
8051
|
}
|
|
7849
8052
|
return (jsxs(Flex, { flexFlow: 'column', gap: "2", children: [jsx(Grid, { gap: "4", gridTemplateColumns: 'repeat(12, 1fr)', autoFlow: 'row', children: ordered.map((column) => {
|
|
7850
8053
|
return (jsx(ColumnRenderer
|
|
@@ -7854,7 +8057,7 @@ const FormBody = () => {
|
|
|
7854
8057
|
properties: properties, prefix: ``, parentRequired: schema.required, column }, `form-input-${column}`));
|
|
7855
8058
|
}) }), jsxs(Flex, { justifyContent: 'end', gap: "2", children: [showResetButton && (jsx(Button$1, { onClick: () => {
|
|
7856
8059
|
methods.reset();
|
|
7857
|
-
}, variant: 'subtle', children: translate.t('reset') })), showSubmitButton && jsx(SubmitButton, {})] }), isError && customErrorRenderer && customErrorRenderer(error)] }));
|
|
8060
|
+
}, variant: 'subtle', children: formButtonLabels?.reset ?? translate.t('reset') })), showSubmitButton && jsx(SubmitButton, {})] }), isError && customErrorRenderer && customErrorRenderer(error)] }));
|
|
7858
8061
|
};
|
|
7859
8062
|
|
|
7860
8063
|
const FormTitle = () => {
|
|
@@ -8173,7 +8376,6 @@ const TableDataDisplay = ({ colorPalette, emptyComponent, }) => {
|
|
|
8173
8376
|
return `minmax(${size}px, ${(size / totalWidths) * 100}%)`;
|
|
8174
8377
|
})
|
|
8175
8378
|
.join(' ');
|
|
8176
|
-
console.log({ columnWidths }, 'hadfg');
|
|
8177
8379
|
const cellProps = {
|
|
8178
8380
|
flex: '1 0 0%',
|
|
8179
8381
|
overflow: 'auto',
|
|
@@ -8190,22 +8392,22 @@ const TableDataDisplay = ({ colorPalette, emptyComponent, }) => {
|
|
|
8190
8392
|
}
|
|
8191
8393
|
return (jsxs(Grid, { templateColumns: `${columnWidths}`, overflow: 'auto', borderWidth: '1px', color: { base: 'colorPalette.900', _dark: 'colorPalette.100' }, borderColor: { base: 'colorPalette.200', _dark: 'colorPalette.800' }, colorPalette, children: [jsx(Grid, { templateColumns: `${columnWidths}`, column: `1/span ${columns.length}`, bg: { base: 'colorPalette.200', _dark: 'colorPalette.800' }, colorPalette, children: columnHeaders.map((header) => {
|
|
8192
8394
|
const columnDef = columnsMap[header];
|
|
8193
|
-
return (jsx(Box, { flex: '1 0 0%', paddingX: '2', py: '1', overflow: 'auto', textOverflow: 'ellipsis', children: columnDef?.meta?.displayName ?? header }));
|
|
8194
|
-
}) }), data.map((record) => {
|
|
8195
|
-
return (jsx(
|
|
8395
|
+
return (jsx(Box, { flex: '1 0 0%', paddingX: '2', py: '1', overflow: 'auto', textOverflow: 'ellipsis', children: columnDef?.meta?.displayName ?? header }, `chakra-table-header-${header}`));
|
|
8396
|
+
}) }), data.map((record, recordIndex) => {
|
|
8397
|
+
return (jsx(Box, { display: "contents", children: columnHeaders.map((header) => {
|
|
8196
8398
|
const { cell } = columnsMap[header];
|
|
8197
8399
|
const value = record[header];
|
|
8198
8400
|
if (!!record === false) {
|
|
8199
|
-
return (jsx(Box, { ...cellProps }));
|
|
8401
|
+
return (jsx(Box, { ...cellProps }, `chakra-table-cell-${recordIndex}-${header}`));
|
|
8200
8402
|
}
|
|
8201
8403
|
if (cell) {
|
|
8202
|
-
return (jsx(Box, { ...cellProps, children: cell({ row: { original: record } }) }));
|
|
8404
|
+
return (jsx(Box, { ...cellProps, children: cell({ row: { original: record } }) }, `chakra-table-cell-${recordIndex}-${header}`));
|
|
8203
8405
|
}
|
|
8204
8406
|
if (typeof value === 'object') {
|
|
8205
|
-
return (jsx(Box, { ...cellProps, children: jsx(RecordDisplay, { object: value }) }));
|
|
8407
|
+
return (jsx(Box, { ...cellProps, children: jsx(RecordDisplay, { object: value }) }, `chakra-table-cell-${recordIndex}-${header}`));
|
|
8206
8408
|
}
|
|
8207
|
-
return jsx(Box, { ...cellProps, children: value });
|
|
8208
|
-
}) }));
|
|
8409
|
+
return (jsx(Box, { ...cellProps, children: value }, `chakra-table-cell-${recordIndex}-${header}`));
|
|
8410
|
+
}) }, `chakra-table-record-${recordIndex}`));
|
|
8209
8411
|
})] }));
|
|
8210
8412
|
};
|
|
8211
8413
|
|
|
@@ -8358,19 +8560,19 @@ const DataDisplay = ({ variant = '' }) => {
|
|
|
8358
8560
|
return cell.id === `${rowId}_${column.id}`;
|
|
8359
8561
|
});
|
|
8360
8562
|
if (column.columns.length > 0) {
|
|
8361
|
-
return (jsxs(Card.Root, { margin: '1', gridColumn: 'span 12', children: [jsx(Card.Header, { color: 'gray.400', children: column.columnDef.meta?.displayName ?? column.id }), jsx(Card.Body, { display: 'grid', gap: '4', gridTemplateColumns: 'repeat(12, 1fr)', children: column.columns.map((
|
|
8362
|
-
if (!
|
|
8363
|
-
return
|
|
8563
|
+
return (jsxs(Card.Root, { margin: '1', gridColumn: 'span 12', children: [jsx(Card.Header, { color: 'gray.400', children: column.columnDef.meta?.displayName ?? column.id }), jsx(Card.Body, { display: 'grid', gap: '4', gridTemplateColumns: 'repeat(12, 1fr)', children: column.columns.map((subColumn) => {
|
|
8564
|
+
if (!subColumn.getIsVisible()) {
|
|
8565
|
+
return null;
|
|
8364
8566
|
}
|
|
8365
8567
|
const foundCell = row
|
|
8366
8568
|
.getVisibleCells()
|
|
8367
8569
|
.find((cell) => {
|
|
8368
|
-
return cell.id === `${rowId}_${
|
|
8570
|
+
return cell.id === `${rowId}_${subColumn.id}`;
|
|
8369
8571
|
});
|
|
8370
|
-
return jsx(CellRenderer, { cell: foundCell });
|
|
8371
|
-
}) })] }, `chakra-table-card-${
|
|
8572
|
+
return (jsx(CellRenderer, { cell: foundCell }, `chakra-table-cell-${rowId}-${subColumn.id}`));
|
|
8573
|
+
}) })] }, `chakra-table-card-${rowId}-${column.id}`));
|
|
8372
8574
|
}
|
|
8373
|
-
return jsx(CellRenderer, { cell: childCell });
|
|
8575
|
+
return (jsx(CellRenderer, { cell: childCell }, `chakra-table-cell-${rowId}-${column.id}`));
|
|
8374
8576
|
}) }) }, `chakra-table-card-${rowId}`));
|
|
8375
8577
|
}) }));
|
|
8376
8578
|
};
|
|
@@ -8665,4 +8867,4 @@ function DataTableServer({ columns, enableRowSelection = true, enableMultiRowSel
|
|
|
8665
8867
|
}, children: jsx(DataTableServerContext.Provider, { value: { url, query }, children: children }) }));
|
|
8666
8868
|
}
|
|
8667
8869
|
|
|
8668
|
-
export { CardHeader, DataDisplay, DataTable, DataTableServer, DatePickerInput, DefaultCardTitle, DefaultForm, DefaultTable, DefaultTableServer, DensityToggleButton, EditSortingButton, EmptyState, ErrorAlert, FilterDialog, FormBody, FormRoot, FormTitle, GlobalFilter, MediaLibraryBrowser, PageSizeControl, Pagination, RecordDisplay, ReloadButton, ResetFilteringButton, ResetSelectionButton, ResetSortingButton, RowCountText, SelectAllRowsToggle, Table, TableBody, TableCardContainer, TableCards, TableComponent, TableControls, TableDataDisplay, TableFilter, TableFilterTags, TableFooter, TableHeader, TableLoadingComponent, TableSelector, TableSorter, TableViewer, TextCell, ViewDialog, buildErrorMessages, buildFieldErrors, buildRequiredErrors, convertToAjvErrorsFormat, createErrorMessage, getColumns, getMultiDates, getRangeDates, idPickerSanityCheck, useDataTable, useDataTableContext, useDataTableServer, useForm, widthSanityCheck };
|
|
8870
|
+
export { CardHeader, DataDisplay, DataTable, DataTableServer, DatePickerInput, DefaultCardTitle, DefaultForm, DefaultTable, DefaultTableServer, DensityToggleButton, EditSortingButton, EmptyState, ErrorAlert, FilterDialog, FormBody, FormRoot, FormTitle, GlobalFilter, MediaLibraryBrowser, PageSizeControl, Pagination, RecordDisplay, ReloadButton, ResetFilteringButton, ResetSelectionButton, ResetSortingButton, RowCountText, SelectAllRowsToggle, Table, TableBody, TableCardContainer, TableCards, TableComponent, TableControls, TableDataDisplay, TableFilter, TableFilterTags, TableFooter, TableHeader, TableLoadingComponent, TableSelector, TableSorter, TableViewer, TextCell, ViewDialog, buildErrorMessages, buildFieldErrors, buildRequiredErrors, convertToAjvErrorsFormat, createErrorMessage, defaultRenderDisplay, getColumns, getMultiDates, getRangeDates, idPickerSanityCheck, useDataTable, useDataTableContext, useDataTableServer, useForm, widthSanityCheck };
|