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