@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.
Files changed (26) hide show
  1. package/README.md +17 -0
  2. package/dist/index.d.ts +12 -6
  3. package/dist/index.js +490 -287
  4. package/dist/index.mjs +490 -288
  5. package/dist/types/components/DataTable/context/useDataTableServerContext.d.ts +1 -1
  6. package/dist/types/components/DataTable/controls/ReloadButton.d.ts +1 -1
  7. package/dist/types/components/DataTable/display/RecordDisplay.d.ts +2 -2
  8. package/dist/types/components/Form/SchemaFormContext.d.ts +2 -1
  9. package/dist/types/components/Form/components/core/FormRoot.d.ts +3 -4
  10. package/dist/types/components/Form/components/fields/ArrayRenderer.d.ts +1 -1
  11. package/dist/types/components/Form/components/fields/StringInputField.d.ts +0 -1
  12. package/dist/types/components/Form/components/fields/TextAreaInput.d.ts +0 -5
  13. package/dist/types/components/Form/components/types/CustomJSONSchema7.d.ts +8 -0
  14. package/dist/types/components/Form/components/viewers/ArrayViewer.d.ts +1 -1
  15. package/dist/types/components/Form/components/viewers/BooleanViewer.d.ts +1 -1
  16. package/dist/types/components/Form/components/viewers/DateTimeViewer.d.ts +1 -1
  17. package/dist/types/components/Form/components/viewers/DateViewer.d.ts +1 -1
  18. package/dist/types/components/Form/components/viewers/IdViewer.d.ts +1 -1
  19. package/dist/types/components/Form/components/viewers/ObjectViewer.d.ts +1 -1
  20. package/dist/types/components/Form/components/viewers/RecordViewer.d.ts +2 -2
  21. package/dist/types/components/Form/components/viewers/StringViewer.d.ts +1 -6
  22. package/dist/types/components/Form/components/viewers/TextAreaViewer.d.ts +1 -6
  23. package/dist/types/components/Form/components/viewers/TimeViewer.d.ts +1 -1
  24. package/dist/types/components/Form/utils/useFormI18n.d.ts +5 -3
  25. package/dist/types/components/ui/pagination.d.ts +10 -7
  26. 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: "RootPropsProvider",
545
+ name: 'RootPropsProvider',
546
546
  });
547
547
  const variantMap = {
548
- outline: { default: "ghost", ellipsis: "plain", current: "outline" },
549
- solid: { default: "outline", ellipsis: "outline", current: "solid" },
550
- subtle: { default: "ghost", ellipsis: "plain", current: "subtle" },
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 = "sm", variant = "outline", getHref, ...rest } = props;
554
- return (jsx(RootPropsProvider, { value: { size, variantMap: variantMap[variant], getHref }, children: jsx(Pagination$1.Root, { ref: ref, type: getHref ? "link" : "button", ...rest }) }));
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 === "ellipsis" ? (jsx(PaginationEllipsis, { index: index, ...props }, index)) : (jsx(PaginationItem, { type: "page", value: page.value, ...props }, index));
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 = "compact", ...rest } = props;
687
+ const { format = 'compact', ...rest } = props;
593
688
  const { page, totalPages, pageRange, count } = usePaginationContext();
594
689
  const content = React.useMemo(() => {
595
- if (format === "short")
690
+ if (format === 'short')
596
691
  return `${page} / ${totalPages}`;
597
- if (format === "compact")
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 = "icon", }) => {
2741
- const { url } = useDataTableServerContext();
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
- if (variant === "icon") {
2746
- return (jsx(Tooltip, { showArrow: true, content: reloadTooltip, children: jsx(Button, { variant: "ghost", onClick: () => {
2747
- queryClient.invalidateQueries({ queryKey: [url] });
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
- }, children: [jsx(IoReload, {}), " ", reloadButtonText] }));
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, { isChecked: isRowSelected(row.id, rowSelection),
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(Fragment, { children: [jsxs(Box, { children: [showDisplayNameOnly && (jsx(Text, { fontWeight: 'bold', children: cell.column.columnDef.meta?.displayName ??
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()) }))] }, `chakra-table-cardcolumnid-${row.id}`), jsx(Box, { justifySelf: 'end', children: flexRender(cell.column.columnDef.cell, cell.getContext()) }, `chakra-table-cardcolumn-${row.id}`)] }));
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 && (jsxs(Table$1.Header, { padding: `${table.getDensityValue()}px`, onMouseEnter: () => handleRowHover(true), onMouseLeave: () => handleRowHover(false), display: 'grid', children: [isCheckBoxVisible() && (jsx(Box, { margin: '0rem', display: 'grid', justifyItems: 'center', alignItems: 'center', children: jsx(Checkbox, { width: `${SELECTION_BOX_WIDTH}px`, height: `${SELECTION_BOX_WIDTH}px`, isChecked: areAllRowsSelected(table, rowSelection),
3124
- // indeterminate: areSomeRowsSelected(table, rowSelection),
3125
- onChange: createToggleAllRowsHandler(table, rowSelection, setRowSelection) }) })), !isCheckBoxVisible() && (jsx(Box, { as: "span", margin: '0rem', display: 'grid', justifyItems: 'center', alignItems: 'center', width: `${SELECTION_BOX_WIDTH}px`, height: `${SELECTION_BOX_WIDTH}px` }))] })), footerGroup.headers.map((header) => (jsx(Table$1.Cell, { padding: '0', columnSpan: `${header.colSpan}`,
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: "auto", ...boxProps, children: Object.entries(object).map(([field, value]) => {
3622
- return (jsxs(Grid, { columnGap: 2, gridTemplateColumns: "auto 1fr", children: [jsx(Text, { color: "colorPalette.400", children: getColumn({ field }) }), typeof value === "object" ? (jsx(RecordDisplay, { object: value, prefix: `${prefix}${field}.`, translate: translate })) : (jsx(Text, { children: JSON.stringify(value) }))] }, field));
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, display_column } = foreign_key;
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 = "1/span 12", required, items } = schema;
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: "column", gap: 2, children: [jsxs(Box, { as: "label", children: [`${translate.t(removeIndex(`${colLabel}.field_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: {
4037
- base: "colorPalette.200",
4038
- _dark: "colorPalette.800",
4039
- }, children: [jsx(Grid, { gridTemplateColumns: "repeat(12, 1fr)", autoFlow: "row", children: jsx(SchemaRenderer, { column: `${index}`,
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: "end", children: jsx(Button$1, { variant: "ghost", onClick: () => {
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 === "number") {
4217
+ if (type === 'number') {
4048
4218
  setValue(colLabel, [...fields, 0]);
4049
4219
  return;
4050
4220
  }
4051
- if (type === "string") {
4052
- setValue(colLabel, [...fields, ""]);
4221
+ if (type === 'string') {
4222
+ setValue(colLabel, [...fields, '']);
4053
4223
  return;
4054
4224
  }
4055
- if (type === "boolean") {
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: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
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
- return (jsx(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, alignItems: 'stretch', gridColumn,
4076
- gridRow, errorText: errors[`${colLabel}`]
4077
- ? translate.t(removeIndex(`${colLabel}.field_required`))
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, display_column, customQueryFn, } = foreign_key;
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
- return dataList.map((item) => ({
5428
- label: String(item[display_column] ?? ''), // Always use display_column for filtering
5429
- value: String(item[column_ref]),
5430
- raw: item,
5431
- }));
5432
- }, [dataList, display_column, column_ref]);
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
- if (dataList.length > 0 && comboboxItems.length > 0) {
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
- // Apply filter to the collection using the immediate searchText for UI responsiveness
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
- }, [dataList, searchText]);
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: !!renderDisplay === true
5717
+ }, children: renderDisplay
5479
5718
  ? renderDisplay(item)
5480
- : item[display_column] }, id));
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
- return (jsx(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, gridColumn, gridRow, errorText: fieldError
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
- ? translate.t(removeIndex(`${colLabel}.field_required`))
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: [`${translate.t(removeIndex(`${colLabel}.field_label`))}`, isRequired && jsx("span", { children: "*" })] })), jsx(Grid, { bgColor: { base: 'colorPalette.100', _dark: 'colorPalette.900' }, p: 2, borderRadius: 4, borderWidth: 1, borderColor: {
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: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
5846
+ }) }), errors[`${column}`] && (jsx(Text, { color: 'red.400', children: formI18n.required() }))] }));
5608
5847
  };
5609
5848
 
5610
- const RecordInput$1 = ({ column, schema, prefix }) => {
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
- return (jsxs(Field, { label: `${translate.t(`${column}.field_label`)}`, required: isRequired, alignItems: 'stretch', gridColumn, gridRow, errorText: errors[`${column}`]
5620
- ? translate.t(`${column}.field_required`)
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
- return (jsx(Fragment, { children: jsx(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, gridColumn: gridColumn, gridRow: gridRow, errorText: fieldError, invalid: !!fieldError, children: jsx(Input, { ...register(`${colLabel}`, { required: isRequired }), autoComplete: "off" }) }) }));
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: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, gridColumn: gridColumn ?? 'span 4', gridRow: gridRow ?? 'span 1', display: "grid", errorText: fieldError
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
- ? translate.t(removeIndex(`${colLabel}.field_required`))
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 { translate, timezone, insideDialog } = useSchemaContext();
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: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, alignItems: 'stretch', gridColumn,
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$1, { schema: colSchema, prefix, column });
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 = "span 12", gridRow = "span 1", required, items, } = schema;
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: "1/span12", children: [`${translate.t(removeIndex(`${colLabel}.field_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: {
7342
- base: "colorPalette.200",
7343
- _dark: "colorPalette.800",
7344
- }, children: jsx(Grid, { gap: "4", gridTemplateColumns: "repeat(12, 1fr)", autoFlow: "row", children: jsx(SchemaViewer, { column: `${index}`,
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: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
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 { translate } = useSchemaContext();
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
- return (jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, alignItems: "stretch", gridColumn,
7358
- gridRow, children: [jsx(Text, { children: value
7359
- ? translate.t(removeIndex(`${colLabel}.true`))
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 { translate, timezone } = useSchemaContext();
7378
- const { required, gridColumn = "span 4", gridRow = "span 1", displayDateFormat = "YYYY-MM-DD", } = schema;
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 displayDate = dayjs(selectedDate).tz(timezone).format(displayDateFormat);
7383
- return (jsxs(Field, { label: `${translate.t(removeIndex(`${column}.field_label`))}`, required: isRequired, alignItems: "stretch", gridColumn,
7384
- gridRow, children: [jsxs(Text, { children: [" ", selectedDate !== undefined ? displayDate : ""] }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: translate.t(`${column}.field_required`) }))] }));
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 { translate } = useSchemaContext();
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 colLabel = `${prefix}${column}`;
7415
- return (jsx(Field, { label: `${translate.t(`${colLabel}.field_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) => {
7416
- 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));
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 = "span 12", gridRow = "span 1", renderDisplay, foreign_key, } = schema;
7660
+ const { required, gridColumn = 'span 12', gridRow = 'span 1', renderDisplay, foreign_key, } = schema;
7424
7661
  const isRequired = required?.some((columnId) => columnId === column);
7425
- const { display_column } = foreign_key;
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
- return record[display_column];
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: `${translate.t(removeIndex(`${column}.field_label`))}`, required: isRequired, alignItems: "stretch", gridColumn,
7440
- gridRow, children: [isMultiple && (jsx(Flex, { flexFlow: "wrap", gap: 1, children: watchIds.map((id) => {
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: !!renderDisplay === true
7685
+ return (jsx(Tag, { closable: true, children: renderDisplay
7446
7686
  ? renderDisplay(item)
7447
- : item[display_column] }, id));
7448
- }) })), !isMultiple && jsx(Text, { children: getPickedValue() }), errors[`${colLabel}`] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
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: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, gridColumn, gridRow, children: [jsx(Text, { children: formatValue(value) }), errors[`${column}`] && (jsx(Text, { color: 'red.400', children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
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 = "span 12", gridRow = "span 1", required, showLabel = true, } = schema;
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: [`${translate.t(removeIndex(`${colLabel}.field_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: {
7489
- base: "colorPalette.200",
7490
- _dark: "colorPalette.800",
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: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }));
7737
+ }) }), errors[`${column}`] && (jsx(Text, { color: 'red.400', children: formI18n.required() }))] }));
7498
7738
  };
7499
7739
 
7500
- const RecordInput = ({ column, schema, prefix }) => {
7501
- const { formState: { errors }, setValue, getValues, } = useFormContext();
7502
- const { translate } = useSchemaContext();
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 [showNewEntries, setShowNewEntries] = useState(false);
7507
- const [newKey, setNewKey] = useState();
7508
- const [newValue, setNewValue] = useState();
7509
- return (jsxs(Field, { label: `${translate.t(`${column}.field_label`)}`, required: isRequired, alignItems: "stretch", gridColumn, gridRow, children: [entries.map(([key, value]) => {
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 { translate } = useSchemaContext();
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
- return (jsx(Fragment, { children: jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, gridColumn: gridColumn ?? "span 4", gridRow: gridRow ?? "span 1", children: [jsx(Text, { children: value }), errors[colLabel] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }) }));
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 { translate } = useSchemaContext();
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
- return (jsx(Fragment, { children: jsxs(Field, { label: `${translate.t(removeIndex(`${colLabel}.field_label`))}`, required: isRequired, gridColumn: gridColumn, gridRow: gridRow, children: [jsx(Text, { whiteSpace: "pre-wrap", children: value }), " ", errors[colLabel] && (jsx(Text, { color: "red.400", children: translate.t(removeIndex(`${colLabel}.field_required`)) }))] }) }));
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 { translate, timezone } = useSchemaContext();
7660
- const { required, gridColumn = "span 12", gridRow = "span 1", displayTimeFormat = "hh:mm A", } = schema;
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: `${translate.t(removeIndex(`${column}.field_label`))}`, required: isRequired, alignItems: "stretch", gridColumn,
7670
- gridRow, children: [jsx(Text, { children: displayedTime }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: translate.t(`${column}.field_required`) }))] }));
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 { translate, timezone } = useSchemaContext();
7676
- const { required, gridColumn = "span 4", gridRow = "span 1", displayDateFormat = "YYYY-MM-DD HH:mm:ss", } = schema;
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 displayDate = dayjs(selectedDate).tz(timezone).format(displayDateFormat);
7681
- return (jsxs(Field, { label: `${translate.t(removeIndex(`${column}.field_label`))}`, required: isRequired, alignItems: "stretch", gridColumn,
7682
- gridRow, children: [jsxs(Text, { children: [" ", selectedDate !== undefined ? displayDate : ""] }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: translate.t(`${column}.field_required`) }))] }));
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(RecordInput, { schema: colSchema, prefix, column });
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, setError, schema, requireConfirmation, onFormSubmit, } = useSchemaContext();
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(Fragment, { children: columnHeaders.map((header) => {
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((column) => {
8362
- if (!column.getIsVisible()) {
8363
- return jsx(Fragment, {});
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}_${column.id}`;
8570
+ return cell.id === `${rowId}_${subColumn.id}`;
8369
8571
  });
8370
- return jsx(CellRenderer, { cell: foundCell });
8371
- }) })] }, `chakra-table-card-${childCell?.id}`));
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 };