@bsol-oss/react-datatable5 12.0.0-beta.80 → 12.0.0-beta.82

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -18,13 +18,12 @@ var _defineProperty = require('@babel/runtime/helpers/defineProperty');
18
18
  var _toConsumableArray = require('@babel/runtime/helpers/toConsumableArray');
19
19
  var rafSchd = require('raf-schd');
20
20
  var invariant = require('tiny-invariant');
21
- var hi = require('react-icons/hi');
22
- var reactTable = require('@tanstack/react-table');
23
- var matchSorterUtils = require('@tanstack/match-sorter-utils');
24
- var bs = require('react-icons/bs');
25
- var usehooks = require('@uidotdev/usehooks');
26
21
  var reactQuery = require('@tanstack/react-query');
27
22
  var io5 = require('react-icons/io5');
23
+ var usehooks = require('@uidotdev/usehooks');
24
+ var bs = require('react-icons/bs');
25
+ var hi = require('react-icons/hi');
26
+ var reactTable = require('@tanstack/react-table');
28
27
  var gr = require('react-icons/gr');
29
28
  var reactI18next = require('react-i18next');
30
29
  var axios = require('axios');
@@ -35,6 +34,7 @@ var dayjs = require('dayjs');
35
34
  var utc = require('dayjs/plugin/utc');
36
35
  var timezone = require('dayjs/plugin/timezone');
37
36
  var ti = require('react-icons/ti');
37
+ var matchSorterUtils = require('@tanstack/match-sorter-utils');
38
38
 
39
39
  function _interopNamespaceDefault(e) {
40
40
  var n = Object.create(null);
@@ -2622,13 +2622,12 @@ const ViewDialog = ({ icon = jsxRuntime.jsx(io.IoMdEye, {}) }) => {
2622
2622
  return (jsxRuntime.jsxs(DialogRoot, { children: [jsxRuntime.jsx(react.DialogBackdrop, {}), jsxRuntime.jsx(DialogTrigger, { asChild: true, children: jsxRuntime.jsxs(react.Button, { as: react.Box, variant: "ghost", onClick: viewModel.onOpen, children: [icon, " ", view] }) }), jsxRuntime.jsxs(DialogContent, { children: [jsxRuntime.jsx(DialogCloseTrigger, {}), jsxRuntime.jsx(DialogHeader, { children: jsxRuntime.jsx(DialogTitle, { children: view }) }), jsxRuntime.jsx(DialogBody, { children: jsxRuntime.jsx(TableViewer, {}) }), jsxRuntime.jsx(DialogFooter, {})] })] }));
2623
2623
  };
2624
2624
 
2625
- const CardHeader = ({ row, imageColumnId = undefined, titleColumnId = undefined, tagColumnId = undefined, tagIcon = undefined, showTag = true, imageProps = {}, }) => {
2626
- if (!!row.original === false) {
2627
- return jsxRuntime.jsx(jsxRuntime.Fragment, {});
2628
- }
2629
- const isShowFirstColumn = !!titleColumnId || showTag;
2630
- return (jsxRuntime.jsxs(react.Grid, { templateRows: "auto auto", gap: "1rem", children: [!!imageColumnId && (jsxRuntime.jsx(react.Image, { width: "100%", src: row.original[imageColumnId], ...imageProps })), isShowFirstColumn && (jsxRuntime.jsxs(react.Flex, { gap: "0.5rem", flexFlow: "wrap", children: [!!titleColumnId && (jsxRuntime.jsx(react.Text, { fontWeight: "bold", fontSize: "large", children: row.original[titleColumnId] })), showTag && (jsxRuntime.jsx(Tag, { fontSize: "large", startElement: tagIcon && tagIcon({}), children: row.original[tagColumnId] }))] }))] }));
2631
- };
2625
+ const Tooltip = React__namespace.forwardRef(function Tooltip(props, ref) {
2626
+ const { showArrow, children, disabled, portalled, content, contentProps, portalRef, ...rest } = props;
2627
+ if (disabled)
2628
+ return children;
2629
+ return (jsxRuntime.jsxs(react.Tooltip.Root, { ...rest, children: [jsxRuntime.jsx(react.Tooltip.Trigger, { asChild: true, children: children }), jsxRuntime.jsx(react.Portal, { disabled: !portalled, container: portalRef, children: jsxRuntime.jsx(react.Tooltip.Positioner, { children: jsxRuntime.jsxs(react.Tooltip.Content, { ref: ref, ...contentProps, children: [showArrow && (jsxRuntime.jsx(react.Tooltip.Arrow, { children: jsxRuntime.jsx(react.Tooltip.ArrowTip, {}) })), content] }) }) })] }));
2630
+ });
2632
2631
 
2633
2632
  const DataTableServerContext = React.createContext({
2634
2633
  url: "",
@@ -2641,697 +2640,435 @@ const useDataTableServerContext = () => {
2641
2640
  return { ...context, isEmpty };
2642
2641
  };
2643
2642
 
2644
- const EmptyState$1 = ({ title = "No records", description = "Add a new events to get started or refine your search", }) => {
2645
- const { isEmpty } = useDataTableServerContext();
2646
- return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: isEmpty && (jsxRuntime.jsx(react.EmptyState.Root, { children: jsxRuntime.jsxs(react.EmptyState.Content, { children: [jsxRuntime.jsx(react.EmptyState.Indicator, { children: jsxRuntime.jsx(hi.HiColorSwatch, {}) }), jsxRuntime.jsxs(react.VStack, { textAlign: "center", children: [jsxRuntime.jsx(react.EmptyState.Title, { children: title }), jsxRuntime.jsx(react.EmptyState.Description, { children: description })] })] }) })) }));
2643
+ const ReloadButton = ({ variant = "icon", }) => {
2644
+ const { url } = useDataTableServerContext();
2645
+ const queryClient = reactQuery.useQueryClient();
2646
+ const { tableLabel } = useDataTableContext();
2647
+ const { reloadTooltip, reloadButtonText } = tableLabel;
2648
+ if (variant === "icon") {
2649
+ return (jsxRuntime.jsx(Tooltip, { showArrow: true, content: reloadTooltip, children: jsxRuntime.jsx(Button, { variant: "ghost", onClick: () => {
2650
+ queryClient.invalidateQueries({ queryKey: [url] });
2651
+ }, "aria-label": "refresh", children: jsxRuntime.jsx(io5.IoReload, {}) }) }));
2652
+ }
2653
+ return (jsxRuntime.jsxs(Button, { variant: "ghost", onClick: () => {
2654
+ queryClient.invalidateQueries({ queryKey: [url] });
2655
+ }, children: [jsxRuntime.jsx(io5.IoReload, {}), " ", reloadButtonText] }));
2647
2656
  };
2648
2657
 
2649
- const ErrorAlert = ({ showMessage = true }) => {
2650
- const { query } = useDataTableServerContext();
2651
- const { isError, error } = query;
2652
- return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: isError && (jsxRuntime.jsxs(react.Alert.Root, { status: "error", children: [jsxRuntime.jsx(react.Alert.Indicator, {}), jsxRuntime.jsxs(react.Alert.Content, { children: [jsxRuntime.jsx(react.Alert.Title, { children: error.name }), showMessage && (jsxRuntime.jsx(react.Alert.Description, { children: error.message }))] })] })) }));
2658
+ const InputGroup = React__namespace.forwardRef(function InputGroup(props, ref) {
2659
+ const { startElement, startElementProps, endElement, endElementProps, children, startOffset = "6px", endOffset = "6px", ...rest } = props;
2660
+ return (jsxRuntime.jsxs(react.Group, { ref: ref, ...rest, children: [startElement && (jsxRuntime.jsx(react.InputElement, { pointerEvents: "none", ...startElementProps, children: startElement })), React__namespace.cloneElement(children, {
2661
+ ...(startElement && {
2662
+ ps: `calc(var(--input-height) - ${startOffset})`,
2663
+ }),
2664
+ ...(endElement && { pe: `calc(var(--input-height) - ${endOffset})` }),
2665
+ // @ts-expect-error chakra generated files
2666
+ ...children.props,
2667
+ }), endElement && (jsxRuntime.jsx(react.InputElement, { placement: "end", ...endElementProps, children: endElement }))] }));
2668
+ });
2669
+
2670
+ const GlobalFilter = () => {
2671
+ const { table, tableLabel } = useDataTableContext();
2672
+ const { globalFilterPlaceholder } = tableLabel;
2673
+ const [searchTerm, setSearchTerm] = React.useState("");
2674
+ const debouncedSearchTerm = usehooks.useDebounce(searchTerm, 500);
2675
+ React.useEffect(() => {
2676
+ const searchHN = async () => {
2677
+ table.setGlobalFilter(debouncedSearchTerm);
2678
+ };
2679
+ searchHN();
2680
+ }, [debouncedSearchTerm]);
2681
+ return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsx(InputGroup, { flex: "1", startElement: jsxRuntime.jsx(md.MdSearch, {}), children: jsxRuntime.jsx(react.Input, { placeholder: globalFilterPlaceholder, variant: "outline", onChange: (e) => {
2682
+ setSearchTerm(e.target.value);
2683
+ } }) }) }));
2653
2684
  };
2654
2685
 
2655
- const snakeToLabel = (str) => {
2656
- return str
2657
- .split("_") // Split by underscore
2658
- .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()) // Capitalize each word
2659
- .join(" "); // Join with space
2686
+ const SelectAllRowsToggle = ({ selectAllIcon = jsxRuntime.jsx(md.MdOutlineChecklist, {}), clearAllIcon = jsxRuntime.jsx(md.MdClear, {}), selectAllText = "", clearAllText = "", }) => {
2687
+ const { table } = useDataTableContext();
2688
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [!!selectAllText === false && (jsxRuntime.jsx(react.IconButton, { variant: "ghost", "aria-label": table.getIsAllRowsSelected() ? clearAllText : selectAllText, onClick: (event) => {
2689
+ table.getToggleAllRowsSelectedHandler()(event);
2690
+ }, children: table.getIsAllRowsSelected() ? clearAllIcon : selectAllIcon })), !!selectAllText !== false && (jsxRuntime.jsxs(react.Button, { variant: "ghost", onClick: (event) => {
2691
+ table.getToggleAllRowsSelectedHandler()(event);
2692
+ }, children: [table.getIsAllRowsSelected() ? clearAllIcon : selectAllIcon, table.getIsAllRowsSelected() ? clearAllText : selectAllText] }))] }));
2660
2693
  };
2661
2694
 
2662
- const RecordDisplay = ({ object, boxProps, translate, prefix = "", }) => {
2663
- const getColumn = ({ field }) => {
2664
- if (translate !== undefined) {
2665
- return translate.t(`${prefix}${field}`);
2666
- }
2667
- return snakeToLabel(field);
2668
- };
2669
- if (object === null) {
2670
- return jsxRuntime.jsx(jsxRuntime.Fragment, { children: "null" });
2671
- }
2672
- return (jsxRuntime.jsx(react.Grid, { rowGap: 1, padding: 1, overflow: "auto", ...boxProps, children: Object.entries(object).map(([field, value]) => {
2673
- 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));
2674
- }) }));
2695
+ const TableSelector = () => {
2696
+ const { table } = useDataTableContext();
2697
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [table.getSelectedRowModel().rows.length > 0 && (jsxRuntime.jsxs(react.Button, { onClick: () => { }, variant: "ghost", display: "flex", gap: "0.25rem", children: [jsxRuntime.jsx(react.Box, { fontSize: "sm", children: `${table.getSelectedRowModel().rows.length}` }), jsxRuntime.jsx(io.IoMdCheckbox, {})] })), !table.getIsAllPageRowsSelected() && jsxRuntime.jsx(SelectAllRowsToggle, {}), table.getSelectedRowModel().rows.length > 0 && (jsxRuntime.jsx(react.IconButton, { variant: "ghost", onClick: () => {
2698
+ table.resetRowSelection();
2699
+ }, "aria-label": "reset selection", children: jsxRuntime.jsx(md.MdClear, {}) }))] }));
2675
2700
  };
2676
2701
 
2677
- const CellRenderer = ({ cell }) => {
2678
- const { translate } = useDataTableContext();
2679
- const getLabel = ({ columnId }) => {
2680
- if (translate !== undefined) {
2681
- return translate.t(`${columnId}`);
2682
- }
2683
- return snakeToLabel(columnId);
2684
- };
2685
- const formatValue = (value) => {
2686
- if (typeof value === "object") {
2687
- return JSON.stringify(value);
2688
- }
2689
- if (typeof value === "string") {
2690
- return value;
2691
- }
2692
- if (typeof value === "number" || typeof value === "boolean") {
2693
- return `${value}`;
2694
- }
2695
- if (value === undefined) {
2696
- if (translate !== undefined) {
2697
- return translate.t(`undefined`);
2698
- }
2699
- return `undefined`;
2700
- }
2701
- throw new Error(`value is unknown, ${typeof value}`);
2702
- };
2703
- const showCustomDataDisplay = cell.column.columnDef.meta?.showCustomDisplay ?? false;
2704
- const gridColumn = cell.column.columnDef.meta?.gridColumn ?? [
2705
- "span 12",
2706
- "span 6",
2707
- "span 3",
2708
- ];
2709
- const gridRow = cell.column.columnDef.meta?.gridRow ?? {};
2710
- if (showCustomDataDisplay) {
2711
- return (jsxRuntime.jsx(react.Flex, { gridColumn, gridRow, children: reactTable.flexRender(cell.column.columnDef.cell, cell.getContext()) }, cell.id));
2712
- }
2713
- const value = cell.getValue();
2714
- if (typeof value === "object") {
2715
- return (jsxRuntime.jsxs(react.Box, { gridColumn, gridRow, children: [jsxRuntime.jsx(react.Box, { children: getLabel({ columnId: cell.column.id }) }), jsxRuntime.jsx(RecordDisplay, { boxProps: {
2716
- borderWidth: 1,
2717
- borderRadius: 4,
2718
- borderColor: "gray.400",
2719
- paddingX: 4,
2720
- paddingY: 2,
2721
- }, object: value })] }, cell.id));
2722
- }
2723
- return (jsxRuntime.jsxs(react.Box, { gridColumn, gridRow, children: [jsxRuntime.jsx(react.Box, { color: "colorPalette.400", children: getLabel({ columnId: cell.column.id }) }), jsxRuntime.jsx(react.Box, { wordBreak: "break-word", textOverflow: "ellipsis", overflow: "hidden", children: `${formatValue(cell.getValue())}` })] }, cell.id));
2702
+ const TableFilterTags = () => {
2703
+ const { table } = useDataTableContext();
2704
+ return (jsxRuntime.jsx(react.Flex, { gap: "0.5rem", flexFlow: "wrap", children: table.getState().columnFilters.map(({ id, value }) => {
2705
+ return (jsxRuntime.jsx(Tag, { gap: "0.5rem", closable: true, cursor: "pointer", onClick: () => {
2706
+ table.setColumnFilters(table.getState().columnFilters.filter((filter) => {
2707
+ return filter.value != value;
2708
+ }));
2709
+ }, children: `${id}: ${value}` }, `${id}-${value}`));
2710
+ }) }));
2724
2711
  };
2725
- const DataDisplay = ({ variant = "" }) => {
2726
- const { table, translate } = useDataTableContext();
2727
- return (jsxRuntime.jsx(react.Flex, { flexFlow: "column", gap: "1", children: table.getRowModel().rows.map((row) => {
2728
- const rowId = row.id;
2729
- return (jsxRuntime.jsx(react.Card.Root, { children: jsxRuntime.jsx(react.Card.Body, { display: "grid", gap: 4, padding: 4, gridTemplateColumns: "repeat(12, 1fr)", children: table.getAllColumns().map((column) => {
2730
- const childCell = row.getAllCells().find((cell) => {
2731
- return cell.id === `${rowId}_${column.id}`;
2732
- });
2733
- if (column.columns.length > 0) {
2734
- return (jsxRuntime.jsxs(react.Card.Root, { margin: "1", gridColumn: "span 12", children: [jsxRuntime.jsx(react.Card.Header, { color: "gray.400", children: translate.t(column.id) }), jsxRuntime.jsx(react.Card.Body, { display: "grid", gap: "4", gridTemplateColumns: "repeat(12, 1fr)", children: column.columns.map((column) => {
2735
- if (!column.getIsVisible()) {
2736
- return jsxRuntime.jsx(jsxRuntime.Fragment, {});
2712
+
2713
+ const TableControls = ({ fitTableWidth = false, fitTableHeight = false, children = jsxRuntime.jsx(jsxRuntime.Fragment, {}), showGlobalFilter = false, showFilter = false, showFilterName = false, showFilterTags = false, showReload = false, showPagination = true, showPageSizeControl = true, showPageCountText = true, showView = true, filterTagsOptions = [], extraItems = jsxRuntime.jsx(jsxRuntime.Fragment, {}), loading = false, hasError = false, gridProps = {}, }) => {
2714
+ const { tableLabel, table } = useDataTableContext();
2715
+ const { rowCountText, hasErrorText } = tableLabel;
2716
+ return (jsxRuntime.jsxs(react.Grid, { templateRows: "auto 1fr", width: fitTableWidth ? "fit-content" : "100%", height: fitTableHeight ? "fit-content" : "100%", gap: "0.5rem", ...gridProps, children: [jsxRuntime.jsxs(react.Flex, { flexFlow: "column", gap: 2, children: [jsxRuntime.jsxs(react.Flex, { justifyContent: "space-between", children: [jsxRuntime.jsx(react.Box, { children: showView && jsxRuntime.jsx(ViewDialog, { icon: jsxRuntime.jsx(md.MdOutlineViewColumn, {}) }) }), jsxRuntime.jsxs(react.Flex, { gap: "0.5rem", alignItems: "center", justifySelf: "end", children: [loading && jsxRuntime.jsx(react.Spinner, { size: "sm" }), hasError && (jsxRuntime.jsx(Tooltip, { content: hasErrorText, children: jsxRuntime.jsx(react.Icon, { as: bs.BsExclamationCircleFill, color: "red.400" }) })), showGlobalFilter && jsxRuntime.jsx(GlobalFilter, {}), showFilter && jsxRuntime.jsx(FilterDialog, {}), showReload && jsxRuntime.jsx(ReloadButton, {}), extraItems] })] }), filterTagsOptions.length > 0 && (jsxRuntime.jsx(react.Flex, { flexFlow: "column", gap: "0.5rem", children: filterTagsOptions.map((option) => {
2717
+ const { column, options } = option;
2718
+ const tableColumn = table.getColumn(column);
2719
+ return (jsxRuntime.jsxs(react.Flex, { alignItems: "center", flexFlow: "wrap", gap: "0.5rem", children: [tableColumn?.columnDef.meta?.displayName && (jsxRuntime.jsx(react.Text, { children: tableColumn?.columnDef.meta?.displayName })), jsxRuntime.jsx(TagFilter, { availableTags: options, selectedTags: tableColumn?.getFilterValue() ?? [], selectOne: true, onTagChange: (tags) => {
2720
+ if (tags.length === 0) {
2721
+ return tableColumn?.setFilterValue(undefined);
2737
2722
  }
2738
- const foundCell = row
2739
- .getVisibleCells()
2740
- .find((cell) => {
2741
- return cell.id === `${rowId}_${column.id}`;
2742
- });
2743
- return jsxRuntime.jsx(CellRenderer, { cell: foundCell });
2744
- }) })] }, `chakra-table-card-${childCell?.id}`));
2745
- }
2746
- return jsxRuntime.jsx(CellRenderer, { cell: childCell });
2747
- }) }) }, `chakra-table-card-${rowId}`));
2748
- }) }));
2723
+ tableColumn?.setFilterValue(tags);
2724
+ } })] }, column));
2725
+ }) })), showFilterTags && (jsxRuntime.jsx(react.Flex, { children: jsxRuntime.jsx(TableFilterTags, {}) }))] }), jsxRuntime.jsx(react.Grid, { overflow: "auto", bg: { base: "colorPalette.50", _dark: "colorPalette.950" }, children: children }), (showPageSizeControl || showPageCountText || showPagination) && (jsxRuntime.jsxs(react.Flex, { justifyContent: "space-between", children: [jsxRuntime.jsxs(react.Flex, { gap: "1rem", alignItems: "center", children: [showPageSizeControl && jsxRuntime.jsx(PageSizeControl, {}), showPageCountText && (jsxRuntime.jsxs(react.Flex, { children: [jsxRuntime.jsx(react.Text, { paddingRight: "0.5rem", children: rowCountText }), jsxRuntime.jsx(RowCountText, {})] }))] }), jsxRuntime.jsx(react.Box, { justifySelf: "end", children: showPagination && jsxRuntime.jsx(Pagination, {}) })] }))] }));
2749
2726
  };
2750
2727
 
2751
- // Reference: https://tanstack.com/table/latest/docs/framework/react/examples/custom-features
2752
- // TypeScript setup for our new feature with all of the same type-safety as stock TanStack Table features
2753
- // end of TS setup!
2754
- // Here is all of the actual javascript code for our new feature
2755
- const DensityFeature = {
2756
- // define the new feature's initial state
2757
- getInitialState: (state) => {
2758
- return {
2759
- density: "sm",
2760
- ...state,
2761
- };
2762
- },
2763
- // define the new feature's default options
2764
- getDefaultOptions: (table) => {
2765
- return {
2766
- enableDensity: true,
2767
- onDensityChange: reactTable.makeStateUpdater("density", table),
2768
- };
2769
- },
2770
- // if you need to add a default column definition...
2771
- // getDefaultColumnDef: <TData extends RowData>(): Partial<ColumnDef<TData>> => {
2772
- // return { meta: {} } //use meta instead of directly adding to the columnDef to avoid typescript stuff that's hard to workaround
2773
- // },
2774
- // define the new feature's table instance methods
2775
- createTable: (table) => {
2776
- table.setDensity = (updater) => {
2777
- const safeUpdater = (old) => {
2778
- let newState = reactTable.functionalUpdate(updater, old);
2779
- return newState;
2780
- };
2781
- return table.options.onDensityChange?.(safeUpdater);
2782
- };
2783
- table.toggleDensity = (value) => {
2784
- table.setDensity((old) => {
2785
- if (value)
2786
- return value;
2787
- if (old === "sm") {
2788
- return "md";
2728
+ const EmptyState$1 = React__namespace.forwardRef(function EmptyState(props, ref) {
2729
+ const { title, description, icon, children, ...rest } = props;
2730
+ return (jsxRuntime.jsx(react.EmptyState.Root, { ref: ref, ...rest, children: jsxRuntime.jsxs(react.EmptyState.Content, { children: [icon && (jsxRuntime.jsx(react.EmptyState.Indicator, { children: icon })), description ? (jsxRuntime.jsxs(react.VStack, { textAlign: "center", children: [jsxRuntime.jsx(react.EmptyState.Title, { children: title }), jsxRuntime.jsx(react.EmptyState.Description, { children: description })] })) : (jsxRuntime.jsx(react.EmptyState.Title, { children: title })), children] }) }));
2731
+ });
2732
+
2733
+ /**
2734
+ * Hook to automatically hide/show columns based on container width.
2735
+ * Columns are hidden based on their responsivePriority (lower = hide first).
2736
+ * Only activates when canResize={false}.
2737
+ */
2738
+ const useResponsiveColumnVisibility = ({ containerRef, enabled, showSelector = false, }) => {
2739
+ const { table, setColumnVisibility } = useDataTableContext();
2740
+ const autoHiddenRef = React.useRef(new Set());
2741
+ const userBaselineRef = React.useRef(null);
2742
+ const SELECTION_BOX_WIDTH = 20;
2743
+ React.useEffect(() => {
2744
+ if (!enabled || !containerRef.current) {
2745
+ // Reset when disabled
2746
+ if (!enabled) {
2747
+ userBaselineRef.current = null;
2748
+ autoHiddenRef.current = new Set();
2749
+ }
2750
+ return;
2751
+ }
2752
+ // Capture baseline visibility when hook is first enabled
2753
+ if (userBaselineRef.current === null) {
2754
+ userBaselineRef.current = { ...table.getState().columnVisibility };
2755
+ }
2756
+ const updateColumnVisibility = () => {
2757
+ const container = containerRef.current;
2758
+ if (!container || !userBaselineRef.current)
2759
+ return;
2760
+ const containerWidth = container.clientWidth;
2761
+ // Get all columns
2762
+ const allColumns = table.getAllLeafColumns();
2763
+ // Get current visibility state
2764
+ const currentVisibility = table.getState().columnVisibility;
2765
+ // Determine user-hidden columns based on baseline
2766
+ // Columns that are hidden in baseline are considered user-hidden
2767
+ const userBaseline = userBaselineRef.current;
2768
+ const userHiddenColumns = new Set();
2769
+ for (const col of allColumns) {
2770
+ // If column was hidden in baseline, it's user-hidden
2771
+ if (userBaseline[col.id] === false) {
2772
+ userHiddenColumns.add(col.id);
2789
2773
  }
2790
- if (old === "md") {
2791
- return "lg";
2774
+ }
2775
+ // Consider all columns except those hidden by user in baseline
2776
+ const columnsToConsider = allColumns.filter((col) => {
2777
+ return !userHiddenColumns.has(col.id);
2778
+ });
2779
+ // Calculate priority for each column
2780
+ // Lower priority = hide first, Infinity = never auto-hide
2781
+ const columnsWithPriority = columnsToConsider.map((col, index) => {
2782
+ const priority = col.columnDef.meta?.responsivePriority ?? Infinity;
2783
+ return {
2784
+ column: col,
2785
+ priority,
2786
+ size: col.getSize(),
2787
+ index,
2788
+ };
2789
+ });
2790
+ // Sort by priority (ascending), then by index for stable ordering
2791
+ columnsWithPriority.sort((a, b) => {
2792
+ if (a.priority !== b.priority) {
2793
+ return a.priority - b.priority;
2792
2794
  }
2793
- return "sm";
2795
+ return a.index - b.index;
2794
2796
  });
2795
- };
2796
- table.getDensityValue = (value) => {
2797
- let density;
2798
- if (value) {
2799
- density = value;
2797
+ // Calculate available width (account for selector column if present)
2798
+ const availableWidth = showSelector
2799
+ ? containerWidth - SELECTION_BOX_WIDTH
2800
+ : containerWidth;
2801
+ // Calculate which columns can fit
2802
+ let totalWidth = 0;
2803
+ const columnsToShow = new Set();
2804
+ // Always keep at least one column visible
2805
+ let minColumnsShown = 0;
2806
+ for (const { column, priority } of columnsWithPriority) {
2807
+ // If this is the first column and we haven't shown any, always show it
2808
+ if (minColumnsShown === 0) {
2809
+ columnsToShow.add(column.id);
2810
+ totalWidth += column.getSize();
2811
+ minColumnsShown = 1;
2812
+ continue;
2813
+ }
2814
+ // Check if adding this column would exceed available width
2815
+ const newTotalWidth = totalWidth + column.getSize();
2816
+ // If priority is Infinity, always show (never auto-hide)
2817
+ if (priority === Infinity) {
2818
+ columnsToShow.add(column.id);
2819
+ totalWidth = newTotalWidth;
2820
+ }
2821
+ else if (newTotalWidth <= availableWidth) {
2822
+ // Column fits, show it
2823
+ columnsToShow.add(column.id);
2824
+ totalWidth = newTotalWidth;
2825
+ }
2826
+ else ;
2800
2827
  }
2801
- else {
2802
- density = table.getState().density;
2803
- }
2804
- if (density === "sm") {
2805
- return 8;
2828
+ // Update auto-hidden columns
2829
+ const newAutoHidden = new Set();
2830
+ const newVisibility = { ...currentVisibility };
2831
+ // Update visibility for all columns
2832
+ for (const col of allColumns) {
2833
+ const isUserHidden = userHiddenColumns.has(col.id);
2834
+ if (isUserHidden) {
2835
+ // Respect user preference to hide
2836
+ newVisibility[col.id] = false;
2837
+ }
2838
+ else {
2839
+ const shouldBeVisible = columnsToShow.has(col.id);
2840
+ if (!shouldBeVisible) {
2841
+ // Column should be auto-hidden
2842
+ newAutoHidden.add(col.id);
2843
+ newVisibility[col.id] = false;
2844
+ }
2845
+ else {
2846
+ // Column should be visible
2847
+ newVisibility[col.id] = true;
2848
+ }
2849
+ }
2806
2850
  }
2807
- if (density === "md") {
2808
- return 16;
2851
+ // Update auto-hidden ref
2852
+ autoHiddenRef.current = newAutoHidden;
2853
+ // Only update if visibility actually changed
2854
+ const visibilityChanged = Object.keys(newVisibility).some((key) => newVisibility[key] !== currentVisibility[key]) ||
2855
+ Object.keys(currentVisibility).some((key) => newVisibility[key] !== currentVisibility[key]);
2856
+ if (visibilityChanged) {
2857
+ setColumnVisibility(newVisibility);
2809
2858
  }
2810
- return 32;
2811
2859
  };
2812
- },
2813
- // if you need to add row instance APIs...
2814
- // createRow: <TData extends RowData>(row, table): void => {},
2815
- // if you need to add cell instance APIs...
2816
- // createCell: <TData extends RowData>(cell, column, row, table): void => {},
2817
- // if you need to add column instance APIs...
2818
- // createColumn: <TData extends RowData>(column, table): void => {},
2819
- // if you need to add header instance APIs...
2820
- // createHeader: <TData extends RowData>(header, table): void => {},
2860
+ // Initial calculation
2861
+ updateColumnVisibility();
2862
+ // Set up ResizeObserver
2863
+ const resizeObserver = new ResizeObserver(() => {
2864
+ updateColumnVisibility();
2865
+ });
2866
+ resizeObserver.observe(containerRef.current);
2867
+ return () => {
2868
+ resizeObserver.disconnect();
2869
+ };
2870
+ }, [enabled, containerRef, table, setColumnVisibility, showSelector]);
2821
2871
  };
2822
- //end of custom feature code
2823
2872
 
2824
- // Define a custom fuzzy filter function that will apply ranking info to rows (using match-sorter utils)
2825
- const fuzzyFilter = (row, columnId, value, addMeta) => {
2826
- // Rank the item
2827
- const itemRank = matchSorterUtils.rankItem(row.getValue(columnId), value);
2828
- // Store the itemRank info
2829
- addMeta({
2830
- itemRank,
2873
+ const EmptyResult = (jsxRuntime.jsx(EmptyState$1, { icon: jsxRuntime.jsx(hi.HiColorSwatch, {}), title: "No results found", description: "Try adjusting your search", children: jsxRuntime.jsxs(react.List.Root, { variant: "marker", children: [jsxRuntime.jsx(react.List.Item, { children: "Try removing filters" }), jsxRuntime.jsx(react.List.Item, { children: "Try different keywords" })] }) }));
2874
+ const Table = ({ children, emptyComponent = EmptyResult, canResize = true, showLoading = false, showSelector = false, ...props }) => {
2875
+ const { table } = useDataTableContext();
2876
+ const containerRef = React.useRef(null);
2877
+ // Enable responsive column hiding when canResize is false
2878
+ useResponsiveColumnVisibility({
2879
+ containerRef,
2880
+ enabled: !canResize,
2881
+ showSelector,
2831
2882
  });
2832
- // Return if the item should be filtered in/out
2833
- return itemRank.passed;
2883
+ // Skip empty check when loading to allow skeleton to render
2884
+ if (!showLoading && table.getRowModel().rows.length <= 0) {
2885
+ return emptyComponent;
2886
+ }
2887
+ return (jsxRuntime.jsx(react.Box, { ref: containerRef, width: "100%", overflow: "auto", children: jsxRuntime.jsx(react.Table.Root, { stickyHeader: true, variant: 'outline', width: canResize ? table.getCenterTotalSize() : undefined, display: 'grid', alignContent: 'start', overflowY: 'auto', bg: { base: 'colorPalette.50', _dark: 'colorPalette.950' }, ...props, children: children }) }));
2888
+ };
2889
+
2890
+ const Checkbox = React__namespace.forwardRef(function Checkbox(props, ref) {
2891
+ const { icon, children, inputProps, rootRef, ...rest } = props;
2892
+ return (jsxRuntime.jsxs(react.Checkbox.Root, { ref: rootRef, ...rest, children: [jsxRuntime.jsx(react.Checkbox.HiddenInput, { ref: ref, ...inputProps }), jsxRuntime.jsx(react.Checkbox.Control, { children: icon || jsxRuntime.jsx(react.Checkbox.Indicator, {}) }), children != null && (jsxRuntime.jsx(react.Checkbox.Label, { children: children }))] }));
2893
+ });
2894
+
2895
+ const TableBody = ({ showSelector = false, canResize = true, }) => {
2896
+ "use no memo";
2897
+ const { table } = useDataTableContext();
2898
+ const SELECTION_BOX_WIDTH = 20;
2899
+ const [hoveredRow, setHoveredRow] = React.useState(-1);
2900
+ const handleRowHover = (index) => {
2901
+ setHoveredRow(index);
2902
+ };
2903
+ const getTdProps = (cell) => {
2904
+ const tdProps = cell.column.getIsPinned()
2905
+ ? {
2906
+ left: showSelector
2907
+ ? `${cell.column.getStart("left") + SELECTION_BOX_WIDTH + table.getDensityValue() * 2}px`
2908
+ : `${cell.column.getStart("left")}px`,
2909
+ position: "relative",
2910
+ }
2911
+ : {};
2912
+ return tdProps;
2913
+ };
2914
+ const getTrProps = ({ hoveredRow, index, }) => {
2915
+ if (hoveredRow === -1) {
2916
+ return {};
2917
+ }
2918
+ if (hoveredRow === index) {
2919
+ return {
2920
+ opacity: "1",
2921
+ };
2922
+ }
2923
+ return {
2924
+ opacity: "0.8",
2925
+ };
2926
+ };
2927
+ return (jsxRuntime.jsx(react.Table.Body, { children: table.getRowModel().rows.map((row, index) => {
2928
+ return (jsxRuntime.jsxs(react.Table.Row, { display: "flex", zIndex: 1, onMouseEnter: () => handleRowHover(index), onMouseLeave: () => handleRowHover(-1), ...getTrProps({ hoveredRow, index }), children: [showSelector && (jsxRuntime.jsx(TableRowSelector, { index: index, row: row, hoveredRow: hoveredRow })), row.getVisibleCells().map((cell, index) => {
2929
+ return (jsxRuntime.jsx(react.Table.Cell, { padding: `${table.getDensityValue()}px`,
2930
+ // styling resize and pinning start
2931
+ flex: `${canResize ? "0" : "1"} 0 ${cell.column.getSize()}px`,
2932
+ // this is to avoid the cell from being too wide
2933
+ minWidth: `0`, color: {
2934
+ base: "colorPalette.900",
2935
+ _dark: "colorPalette.100",
2936
+ },
2937
+ bg: { base: "colorPalette.50", _dark: "colorPalette.950" }, ...getTdProps(cell), children: reactTable.flexRender(cell.column.columnDef.cell, cell.getContext()) }, `chakra-table-rowcell-${cell.id}-${index}`));
2938
+ })] }, `chakra-table-row-${row.id}`));
2939
+ }) }));
2940
+ };
2941
+ const TableRowSelector = ({ row, }) => {
2942
+ const { table } = useDataTableContext();
2943
+ const SELECTION_BOX_WIDTH = 20;
2944
+ return (jsxRuntime.jsx(react.Table.Cell, { padding: `${table.getDensityValue()}px`, display: "grid", color: {
2945
+ base: "colorPalette.900",
2946
+ _dark: "colorPalette.100",
2947
+ },
2948
+ bg: { base: "colorPalette.50", _dark: "colorPalette.950" }, justifyItems: "center", alignItems: "center", children: jsxRuntime.jsx(Checkbox, { width: `${SELECTION_BOX_WIDTH}px`, height: `${SELECTION_BOX_WIDTH}px`, checked: row.getIsSelected(),
2949
+ disabled: !row.getCanSelect(),
2950
+ onCheckedChange: row.getToggleSelectedHandler() }) }));
2951
+ };
2952
+
2953
+ const TableCardContainer = ({ children, variant = "", gap = "1rem", gridTemplateColumns = "repeat(auto-fit, minmax(20rem, 1fr))", direction = "row", ...props }) => {
2954
+ if (variant === "carousel") {
2955
+ return (jsxRuntime.jsx(react.Flex, { overflow: "auto", gap: gap, direction: direction, ...props, children: children }));
2956
+ }
2957
+ return (jsxRuntime.jsx(react.Grid, { gridTemplateColumns: gridTemplateColumns, gap: gap, ...props, children: children }));
2958
+ };
2959
+
2960
+ const DefaultCardTitle = () => {
2961
+ return jsxRuntime.jsx(jsxRuntime.Fragment, {});
2962
+ };
2963
+ const TableCards = ({ isSelectable = false, showDisplayNameOnly = false, renderTitle = DefaultCardTitle, cardBodyProps = {}, }) => {
2964
+ const { table } = useDataTableContext();
2965
+ return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: table.getRowModel().rows.map((row) => {
2966
+ 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: row.getIsSelected(),
2967
+ disabled: !row.getCanSelect(),
2968
+ // indeterminate: row.getIsSomeSelected(),
2969
+ onChange: row.getToggleSelectedHandler() })), renderTitle(row), jsxRuntime.jsx(react.Grid, { templateColumns: "auto 1fr", gap: "1rem", children: row.getVisibleCells().map((cell) => {
2970
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs(react.Box, { children: [showDisplayNameOnly && (jsxRuntime.jsx(react.Text, { fontWeight: "bold", children: cell.column.columnDef.meta?.displayName ??
2971
+ cell.column.id })), !showDisplayNameOnly && (jsxRuntime.jsx(jsxRuntime.Fragment, { children: reactTable.flexRender(cell.column.columnDef.header,
2972
+ // @ts-expect-error Assuming the CellContext interface is the same as HeaderContext
2973
+ 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}`)] }));
2974
+ }) })] }) }, `chakra-table-card-${row.id}`));
2975
+ }) }));
2976
+ };
2977
+
2978
+ const TableComponent = ({ render = () => {
2979
+ throw Error("Not Implemented");
2980
+ }, }) => {
2981
+ const { table } = useDataTableContext();
2982
+ return render(table);
2983
+ };
2984
+
2985
+ const TableFooter = ({ showSelector = false, alwaysShowSelector = true, }) => {
2986
+ const table = useDataTableContext().table;
2987
+ const SELECTION_BOX_WIDTH = 20;
2988
+ const [hoveredCheckBox, setHoveredCheckBox] = React.useState(false);
2989
+ const handleRowHover = (isHovered) => {
2990
+ setHoveredCheckBox(isHovered);
2991
+ };
2992
+ const isCheckBoxVisible = () => {
2993
+ if (alwaysShowSelector) {
2994
+ return true;
2995
+ }
2996
+ if (table.getIsAllRowsSelected()) {
2997
+ return true;
2998
+ }
2999
+ if (hoveredCheckBox) {
3000
+ return true;
3001
+ }
3002
+ return false;
3003
+ };
3004
+ 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: table.getIsAllRowsSelected(),
3005
+ // indeterminate: table.getIsSomeRowsSelected(),
3006
+ onChange: table.getToggleAllRowsSelectedHandler() }) })), !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}`,
3007
+ // styling resize and pinning start
3008
+ 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
3009
+ ? null
3010
+ : reactTable.flexRender(header.column.columnDef.footer, header.getContext()), jsxRuntime.jsx(react.Box, { children: header.column.getCanSort() && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [header.column.getIsSorted() === false && jsxRuntime.jsx(jsxRuntime.Fragment, {}), header.column.getIsSorted() === "asc" && (jsxRuntime.jsx(bi.BiUpArrow, {})), header.column.getIsSorted() === "desc" && (jsxRuntime.jsx(bi.BiDownArrow, {}))] })) })] }) }) }) }) }, `chakra-table-footer-${header.column.id}-${footerGroup.id}`)))] }, `chakra-table-footergroup-${footerGroup.id}`))) }));
3011
+ };
3012
+
3013
+ // Default text values
3014
+ const DEFAULT_HEADER_TEXTS = {
3015
+ pinColumn: "Pin Column",
3016
+ cancelPin: "Cancel Pin",
3017
+ sortAscending: "Sort Ascending",
3018
+ sortDescending: "Sort Descending",
3019
+ clearSorting: "Clear Sorting",
2834
3020
  };
2835
3021
  /**
2836
- * DataTable will create a context to hold all values to
2837
- * help the render of the DataTable in serverside
3022
+ * TableHeader component with configurable text strings.
2838
3023
  *
3024
+ * @example
3025
+ * // Using default texts
3026
+ * <TableHeader />
2839
3027
  *
2840
- * The query is required to be a GET request that can receive
2841
- * specified params and return a specified response
3028
+ * @example
3029
+ * // Customizing default texts for all columns
3030
+ * <TableHeader
3031
+ * defaultTexts={{
3032
+ * pinColumn: "Pin This Column",
3033
+ * sortAscending: "Sort A-Z"
3034
+ * }}
3035
+ * />
2842
3036
  *
2843
- * @link https://tanstack.com/table/latest/docs/guide/column-defs
3037
+ * @example
3038
+ * // Customizing texts per column via meta
3039
+ * const columns = [
3040
+ * columnHelper.accessor("name", {
3041
+ * header: "Name",
3042
+ * meta: {
3043
+ * headerTexts: {
3044
+ * pinColumn: "Pin Name Column",
3045
+ * sortAscending: "Sort Names A-Z"
3046
+ * }
3047
+ * }
3048
+ * })
3049
+ * ];
2844
3050
  */
2845
- function DataTable({ columns, data, enableRowSelection = true, enableMultiRowSelection = true, enableSubRowSelection = true, columnOrder, columnFilters, columnVisibility, density, globalFilter, pagination, sorting, rowSelection, setPagination, setSorting, setColumnFilters, setRowSelection, setGlobalFilter, setColumnOrder, setDensity, setColumnVisibility, translate, children, tableLabel = {
2846
- view: 'View',
2847
- edit: 'Edit',
2848
- filterButtonText: 'Filter',
2849
- filterTitle: 'Filter',
2850
- filterReset: 'Reset',
2851
- filterClose: 'Close',
2852
- reloadTooltip: 'Reload',
2853
- reloadButtonText: 'Reload',
2854
- resetSelection: 'Reset Selection',
2855
- resetSorting: 'Reset Sorting',
2856
- rowCountText: 'Row Count',
2857
- hasErrorText: 'Has Error',
2858
- globalFilterPlaceholder: 'Search',
2859
- trueLabel: 'True',
2860
- falseLabel: 'False',
2861
- }, }) {
2862
- const table = reactTable.useReactTable({
2863
- _features: [DensityFeature],
2864
- data: data,
2865
- rowCount: data.length,
2866
- columns: columns,
2867
- getCoreRowModel: reactTable.getCoreRowModel(),
2868
- getFilteredRowModel: reactTable.getFilteredRowModel(),
2869
- getSortedRowModel: reactTable.getSortedRowModel(),
2870
- getPaginationRowModel: reactTable.getPaginationRowModel(),
2871
- defaultColumn: {
2872
- size: 150, //starting column size
2873
- minSize: 10, //enforced during column resizing
2874
- maxSize: 10000, //enforced during column resizing
2875
- },
2876
- enableRowSelection: enableRowSelection,
2877
- enableMultiRowSelection: enableMultiRowSelection,
2878
- enableSubRowSelection: enableSubRowSelection,
2879
- columnResizeMode: 'onChange',
2880
- // global filter start
2881
- filterFns: {
2882
- fuzzy: fuzzyFilter,
2883
- },
2884
- globalFilterFn: 'fuzzy',
2885
- state: {
2886
- pagination,
2887
- sorting,
2888
- columnFilters,
2889
- rowSelection,
2890
- columnOrder,
2891
- globalFilter,
2892
- density,
2893
- columnVisibility,
2894
- },
2895
- onPaginationChange: setPagination,
2896
- onSortingChange: setSorting,
2897
- onColumnFiltersChange: setColumnFilters,
2898
- onRowSelectionChange: setRowSelection,
2899
- onColumnOrderChange: (state) => {
2900
- setColumnOrder(state);
2901
- },
2902
- onGlobalFilterChange: (state) => {
2903
- setGlobalFilter(state);
2904
- },
2905
- onDensityChange: setDensity,
2906
- onColumnVisibilityChange: setColumnVisibility,
2907
- });
2908
- return (jsxRuntime.jsx(DataTableContext.Provider, { value: {
2909
- table: table,
2910
- globalFilter,
2911
- setGlobalFilter,
2912
- type: 'client',
2913
- translate,
2914
- columns: columns,
2915
- sorting,
2916
- setSorting,
2917
- columnFilters,
2918
- setColumnFilters,
2919
- pagination,
2920
- setPagination,
2921
- rowSelection,
2922
- setRowSelection,
2923
- columnOrder,
2924
- setColumnOrder,
2925
- density,
2926
- setDensity,
2927
- columnVisibility,
2928
- setColumnVisibility,
2929
- data,
2930
- tableLabel,
2931
- }, children: children }));
2932
- }
2933
-
2934
- /**
2935
- * DataTableServer will create a context to hold all values to
2936
- * help the render of the DataTable in serverside
2937
- *
2938
- * The query is required to be a GET request that can receive
2939
- * specified params and return a specified response
2940
- *
2941
- * The `useDataTableServer` can help to create the specified request and response
2942
- *
2943
- * @link https://tanstack.com/table/latest/docs/guide/column-defs
2944
- */
2945
- function DataTableServer({ columns, enableRowSelection = true, enableMultiRowSelection = true, enableSubRowSelection = true, columnOrder, columnFilters, columnVisibility, density, globalFilter, pagination, sorting, rowSelection, setPagination, setSorting, setColumnFilters, setRowSelection, setGlobalFilter, setColumnOrder, setDensity, setColumnVisibility, query, url, translate, children, tableLabel = {
2946
- view: "View",
2947
- edit: "Edit",
2948
- filterButtonText: "Filter",
2949
- filterTitle: "Filter",
2950
- filterReset: "Reset",
2951
- filterClose: "Close",
2952
- reloadTooltip: "Reload",
2953
- reloadButtonText: "Reload",
2954
- resetSelection: "Reset Selection",
2955
- resetSorting: "Reset Sorting",
2956
- rowCountText: "Row Count",
2957
- hasErrorText: "Has Error",
2958
- globalFilterPlaceholder: "Search",
2959
- trueLabel: "True",
2960
- falseLabel: "False",
2961
- }, }) {
2962
- const table = reactTable.useReactTable({
2963
- _features: [DensityFeature],
2964
- data: (query.data?.data ?? []),
2965
- rowCount: query.data?.count ?? 0,
2966
- columns: columns,
2967
- getCoreRowModel: reactTable.getCoreRowModel(),
2968
- manualPagination: true,
2969
- manualSorting: true,
2970
- columnResizeMode: "onChange",
2971
- defaultColumn: {
2972
- size: 150, //starting column size
2973
- minSize: 10, //enforced during column resizing
2974
- maxSize: 10000, //enforced during column resizing
2975
- },
2976
- enableRowSelection: enableRowSelection,
2977
- enableMultiRowSelection: enableMultiRowSelection,
2978
- enableSubRowSelection: enableSubRowSelection,
2979
- state: {
2980
- pagination,
2981
- sorting,
2982
- columnFilters,
2983
- rowSelection,
2984
- columnOrder,
2985
- globalFilter,
2986
- density,
2987
- columnVisibility,
2988
- },
2989
- onPaginationChange: setPagination,
2990
- onSortingChange: setSorting,
2991
- onColumnFiltersChange: setColumnFilters,
2992
- onRowSelectionChange: setRowSelection,
2993
- onColumnOrderChange: (state) => {
2994
- setColumnOrder(state);
2995
- },
2996
- onGlobalFilterChange: (state) => {
2997
- setGlobalFilter(state);
2998
- },
2999
- onDensityChange: setDensity,
3000
- onColumnVisibilityChange: setColumnVisibility,
3001
- // for tanstack-table ts bug start
3002
- filterFns: {
3003
- fuzzy: () => {
3004
- return false;
3005
- },
3006
- },
3007
- // for tanstack-table ts bug end
3008
- });
3009
- return (jsxRuntime.jsx(DataTableContext.Provider, { value: {
3010
- table: table,
3011
- globalFilter,
3012
- setGlobalFilter,
3013
- type: "server",
3014
- translate,
3015
- columns: columns,
3016
- sorting,
3017
- setSorting,
3018
- columnFilters,
3019
- setColumnFilters,
3020
- pagination,
3021
- setPagination,
3022
- rowSelection,
3023
- setRowSelection,
3024
- columnOrder,
3025
- setColumnOrder,
3026
- density,
3027
- setDensity,
3028
- columnVisibility,
3029
- setColumnVisibility,
3030
- data: query.data?.data ?? [],
3031
- tableLabel,
3032
- }, children: jsxRuntime.jsx(DataTableServerContext.Provider, { value: { url, query }, children: children }) }));
3033
- }
3034
-
3035
- const InputGroup = React__namespace.forwardRef(function InputGroup(props, ref) {
3036
- const { startElement, startElementProps, endElement, endElementProps, children, startOffset = "6px", endOffset = "6px", ...rest } = props;
3037
- return (jsxRuntime.jsxs(react.Group, { ref: ref, ...rest, children: [startElement && (jsxRuntime.jsx(react.InputElement, { pointerEvents: "none", ...startElementProps, children: startElement })), React__namespace.cloneElement(children, {
3038
- ...(startElement && {
3039
- ps: `calc(var(--input-height) - ${startOffset})`,
3040
- }),
3041
- ...(endElement && { pe: `calc(var(--input-height) - ${endOffset})` }),
3042
- // @ts-expect-error chakra generated files
3043
- ...children.props,
3044
- }), endElement && (jsxRuntime.jsx(react.InputElement, { placement: "end", ...endElementProps, children: endElement }))] }));
3045
- });
3046
-
3047
- const GlobalFilter = () => {
3048
- const { table, tableLabel } = useDataTableContext();
3049
- const { globalFilterPlaceholder } = tableLabel;
3050
- const [searchTerm, setSearchTerm] = React.useState("");
3051
- const debouncedSearchTerm = usehooks.useDebounce(searchTerm, 500);
3052
- React.useEffect(() => {
3053
- const searchHN = async () => {
3054
- table.setGlobalFilter(debouncedSearchTerm);
3055
- };
3056
- searchHN();
3057
- }, [debouncedSearchTerm]);
3058
- return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsx(InputGroup, { flex: "1", startElement: jsxRuntime.jsx(md.MdSearch, {}), children: jsxRuntime.jsx(react.Input, { placeholder: globalFilterPlaceholder, variant: "outline", onChange: (e) => {
3059
- setSearchTerm(e.target.value);
3060
- } }) }) }));
3061
- };
3062
-
3063
- const Tooltip = React__namespace.forwardRef(function Tooltip(props, ref) {
3064
- const { showArrow, children, disabled, portalled, content, contentProps, portalRef, ...rest } = props;
3065
- if (disabled)
3066
- return children;
3067
- return (jsxRuntime.jsxs(react.Tooltip.Root, { ...rest, children: [jsxRuntime.jsx(react.Tooltip.Trigger, { asChild: true, children: children }), jsxRuntime.jsx(react.Portal, { disabled: !portalled, container: portalRef, children: jsxRuntime.jsx(react.Tooltip.Positioner, { children: jsxRuntime.jsxs(react.Tooltip.Content, { ref: ref, ...contentProps, children: [showArrow && (jsxRuntime.jsx(react.Tooltip.Arrow, { children: jsxRuntime.jsx(react.Tooltip.ArrowTip, {}) })), content] }) }) })] }));
3068
- });
3069
-
3070
- const ReloadButton = ({ variant = "icon", }) => {
3071
- const { url } = useDataTableServerContext();
3072
- const queryClient = reactQuery.useQueryClient();
3073
- const { tableLabel } = useDataTableContext();
3074
- const { reloadTooltip, reloadButtonText } = tableLabel;
3075
- if (variant === "icon") {
3076
- return (jsxRuntime.jsx(Tooltip, { showArrow: true, content: reloadTooltip, children: jsxRuntime.jsx(Button, { variant: "ghost", onClick: () => {
3077
- queryClient.invalidateQueries({ queryKey: [url] });
3078
- }, "aria-label": "refresh", children: jsxRuntime.jsx(io5.IoReload, {}) }) }));
3079
- }
3080
- return (jsxRuntime.jsxs(Button, { variant: "ghost", onClick: () => {
3081
- queryClient.invalidateQueries({ queryKey: [url] });
3082
- }, children: [jsxRuntime.jsx(io5.IoReload, {}), " ", reloadButtonText] }));
3083
- };
3084
-
3085
- const TableFilterTags = () => {
3086
- const { table } = useDataTableContext();
3087
- return (jsxRuntime.jsx(react.Flex, { gap: "0.5rem", flexFlow: "wrap", children: table.getState().columnFilters.map(({ id, value }) => {
3088
- return (jsxRuntime.jsx(Tag, { gap: "0.5rem", closable: true, cursor: "pointer", onClick: () => {
3089
- table.setColumnFilters(table.getState().columnFilters.filter((filter) => {
3090
- return filter.value != value;
3091
- }));
3092
- }, children: `${id}: ${value}` }, `${id}-${value}`));
3093
- }) }));
3094
- };
3095
-
3096
- const TableControls = ({ fitTableWidth = false, fitTableHeight = false, children = jsxRuntime.jsx(jsxRuntime.Fragment, {}), showGlobalFilter = false, showFilter = false, showFilterName = false, showFilterTags = false, showReload = false, showPagination = true, showPageSizeControl = true, showPageCountText = true, showView = true, filterTagsOptions = [], extraItems = jsxRuntime.jsx(jsxRuntime.Fragment, {}), loading = false, hasError = false, gridProps = {}, }) => {
3097
- const { tableLabel, table } = useDataTableContext();
3098
- const { rowCountText, hasErrorText } = tableLabel;
3099
- return (jsxRuntime.jsxs(react.Grid, { templateRows: "auto 1fr", width: fitTableWidth ? "fit-content" : "100%", height: fitTableHeight ? "fit-content" : "100%", gap: "0.5rem", ...gridProps, children: [jsxRuntime.jsxs(react.Flex, { flexFlow: "column", gap: 2, children: [jsxRuntime.jsxs(react.Flex, { justifyContent: "space-between", children: [jsxRuntime.jsx(react.Box, { children: showView && jsxRuntime.jsx(ViewDialog, { icon: jsxRuntime.jsx(md.MdOutlineViewColumn, {}) }) }), jsxRuntime.jsxs(react.Flex, { gap: "0.5rem", alignItems: "center", justifySelf: "end", children: [loading && jsxRuntime.jsx(react.Spinner, { size: "sm" }), hasError && (jsxRuntime.jsx(Tooltip, { content: hasErrorText, children: jsxRuntime.jsx(react.Icon, { as: bs.BsExclamationCircleFill, color: "red.400" }) })), showGlobalFilter && jsxRuntime.jsx(GlobalFilter, {}), showFilter && jsxRuntime.jsx(FilterDialog, {}), showReload && jsxRuntime.jsx(ReloadButton, {}), extraItems] })] }), filterTagsOptions.length > 0 && (jsxRuntime.jsx(react.Flex, { flexFlow: "column", gap: "0.5rem", children: filterTagsOptions.map((option) => {
3100
- const { column, options } = option;
3101
- const tableColumn = table.getColumn(column);
3102
- return (jsxRuntime.jsxs(react.Flex, { alignItems: "center", flexFlow: "wrap", gap: "0.5rem", children: [tableColumn?.columnDef.meta?.displayName && (jsxRuntime.jsx(react.Text, { children: tableColumn?.columnDef.meta?.displayName })), jsxRuntime.jsx(TagFilter, { availableTags: options, selectedTags: tableColumn?.getFilterValue() ?? [], selectOne: true, onTagChange: (tags) => {
3103
- if (tags.length === 0) {
3104
- return tableColumn?.setFilterValue(undefined);
3105
- }
3106
- tableColumn?.setFilterValue(tags);
3107
- } })] }, column));
3108
- }) })), showFilterTags && (jsxRuntime.jsx(react.Flex, { children: jsxRuntime.jsx(TableFilterTags, {}) }))] }), jsxRuntime.jsx(react.Grid, { overflow: "auto", bg: { base: "colorPalette.50", _dark: "colorPalette.950" }, children: children }), (showPageSizeControl || showPageCountText || showPagination) && (jsxRuntime.jsxs(react.Flex, { justifyContent: "space-between", children: [jsxRuntime.jsxs(react.Flex, { gap: "1rem", alignItems: "center", children: [showPageSizeControl && jsxRuntime.jsx(PageSizeControl, {}), showPageCountText && (jsxRuntime.jsxs(react.Flex, { children: [jsxRuntime.jsx(react.Text, { paddingRight: "0.5rem", children: rowCountText }), jsxRuntime.jsx(RowCountText, {})] }))] }), jsxRuntime.jsx(react.Box, { justifySelf: "end", children: showPagination && jsxRuntime.jsx(Pagination, {}) })] }))] }));
3109
- };
3110
-
3111
- const EmptyState = React__namespace.forwardRef(function EmptyState(props, ref) {
3112
- const { title, description, icon, children, ...rest } = props;
3113
- return (jsxRuntime.jsx(react.EmptyState.Root, { ref: ref, ...rest, children: jsxRuntime.jsxs(react.EmptyState.Content, { children: [icon && (jsxRuntime.jsx(react.EmptyState.Indicator, { children: icon })), description ? (jsxRuntime.jsxs(react.VStack, { textAlign: "center", children: [jsxRuntime.jsx(react.EmptyState.Title, { children: title }), jsxRuntime.jsx(react.EmptyState.Description, { children: description })] })) : (jsxRuntime.jsx(react.EmptyState.Title, { children: title })), children] }) }));
3114
- });
3115
-
3116
- const EmptyResult = (jsxRuntime.jsx(EmptyState, { icon: jsxRuntime.jsx(hi.HiColorSwatch, {}), title: "No results found", description: "Try adjusting your search", children: jsxRuntime.jsxs(react.List.Root, { variant: "marker", children: [jsxRuntime.jsx(react.List.Item, { children: "Try removing filters" }), jsxRuntime.jsx(react.List.Item, { children: "Try different keywords" })] }) }));
3117
- const Table = ({ children, emptyComponent = EmptyResult, canResize = true, showLoading = false, ...props }) => {
3118
- const { table } = useDataTableContext();
3119
- // Skip empty check when loading to allow skeleton to render
3120
- if (!showLoading && table.getRowModel().rows.length <= 0) {
3121
- return emptyComponent;
3122
- }
3123
- return (jsxRuntime.jsx(react.Table.Root, { stickyHeader: true, variant: 'outline', width: canResize ? table.getCenterTotalSize() : undefined, display: 'grid', alignContent: 'start', overflowY: 'auto', bg: { base: 'colorPalette.50', _dark: 'colorPalette.950' }, ...props, children: children }));
3124
- };
3125
-
3126
- const Checkbox = React__namespace.forwardRef(function Checkbox(props, ref) {
3127
- const { icon, children, inputProps, rootRef, ...rest } = props;
3128
- return (jsxRuntime.jsxs(react.Checkbox.Root, { ref: rootRef, ...rest, children: [jsxRuntime.jsx(react.Checkbox.HiddenInput, { ref: ref, ...inputProps }), jsxRuntime.jsx(react.Checkbox.Control, { children: icon || jsxRuntime.jsx(react.Checkbox.Indicator, {}) }), children != null && (jsxRuntime.jsx(react.Checkbox.Label, { children: children }))] }));
3129
- });
3130
-
3131
- const TableBody = ({ showSelector = false, canResize = true, }) => {
3132
- "use no memo";
3051
+ const TableHeader = ({ canResize = true, showSelector = false, isSticky = true, tableHeaderProps = {}, tableRowProps = {}, defaultTexts = {}, }) => {
3133
3052
  const { table } = useDataTableContext();
3134
3053
  const SELECTION_BOX_WIDTH = 20;
3135
- const [hoveredRow, setHoveredRow] = React.useState(-1);
3136
- const handleRowHover = (index) => {
3137
- setHoveredRow(index);
3054
+ // Merge default texts with provided defaults
3055
+ const mergedDefaultTexts = { ...DEFAULT_HEADER_TEXTS, ...defaultTexts };
3056
+ // Helper function to get text for a specific header
3057
+ const getHeaderText = (header, key) => {
3058
+ const columnMeta = header.column.columnDef.meta;
3059
+ return columnMeta?.headerTexts?.[key] || mergedDefaultTexts[key];
3138
3060
  };
3139
- const getTdProps = (cell) => {
3140
- const tdProps = cell.column.getIsPinned()
3061
+ const getThProps = (header) => {
3062
+ const thProps = header.column.getIsPinned()
3141
3063
  ? {
3142
3064
  left: showSelector
3143
- ? `${cell.column.getStart("left") + SELECTION_BOX_WIDTH + table.getDensityValue() * 2}px`
3144
- : `${cell.column.getStart("left")}px`,
3145
- position: "relative",
3065
+ ? `${header.getStart("left") + SELECTION_BOX_WIDTH + table.getDensityValue() * 2}px`
3066
+ : `${header.getStart("left")}px`,
3067
+ position: "sticky",
3068
+ zIndex: 100 + 1,
3146
3069
  }
3147
3070
  : {};
3148
- return tdProps;
3149
- };
3150
- const getTrProps = ({ hoveredRow, index, }) => {
3151
- if (hoveredRow === -1) {
3152
- return {};
3153
- }
3154
- if (hoveredRow === index) {
3155
- return {
3156
- opacity: "1",
3157
- };
3158
- }
3159
- return {
3160
- opacity: "0.8",
3161
- };
3162
- };
3163
- return (jsxRuntime.jsx(react.Table.Body, { children: table.getRowModel().rows.map((row, index) => {
3164
- return (jsxRuntime.jsxs(react.Table.Row, { display: "flex", zIndex: 1, onMouseEnter: () => handleRowHover(index), onMouseLeave: () => handleRowHover(-1), ...getTrProps({ hoveredRow, index }), children: [showSelector && (jsxRuntime.jsx(TableRowSelector, { index: index, row: row, hoveredRow: hoveredRow })), row.getVisibleCells().map((cell, index) => {
3165
- return (jsxRuntime.jsx(react.Table.Cell, { padding: `${table.getDensityValue()}px`,
3166
- // styling resize and pinning start
3167
- flex: `${canResize ? "0" : "1"} 0 ${cell.column.getSize()}px`,
3168
- // this is to avoid the cell from being too wide
3169
- minWidth: `0`, color: {
3170
- base: "colorPalette.900",
3171
- _dark: "colorPalette.100",
3172
- },
3173
- bg: { base: "colorPalette.50", _dark: "colorPalette.950" }, ...getTdProps(cell), children: reactTable.flexRender(cell.column.columnDef.cell, cell.getContext()) }, `chakra-table-rowcell-${cell.id}-${index}`));
3174
- })] }, `chakra-table-row-${row.id}`));
3175
- }) }));
3176
- };
3177
- const TableRowSelector = ({ row, }) => {
3178
- const { table } = useDataTableContext();
3179
- const SELECTION_BOX_WIDTH = 20;
3180
- return (jsxRuntime.jsx(react.Table.Cell, { padding: `${table.getDensityValue()}px`, display: "grid", color: {
3181
- base: "colorPalette.900",
3182
- _dark: "colorPalette.100",
3183
- },
3184
- bg: { base: "colorPalette.50", _dark: "colorPalette.950" }, justifyItems: "center", alignItems: "center", children: jsxRuntime.jsx(Checkbox, { width: `${SELECTION_BOX_WIDTH}px`, height: `${SELECTION_BOX_WIDTH}px`, checked: row.getIsSelected(),
3185
- disabled: !row.getCanSelect(),
3186
- onCheckedChange: row.getToggleSelectedHandler() }) }));
3187
- };
3188
-
3189
- const TableBodySkeleton = ({ showSelector = false, canResize = true, }) => {
3190
- 'use no memo';
3191
- const { table } = useDataTableContext();
3192
- const SELECTION_BOX_WIDTH = 20;
3193
- const [hoveredRow, setHoveredRow] = React.useState(-1);
3194
- const handleRowHover = (index) => {
3195
- setHoveredRow(index);
3196
- };
3197
- const getTdProps = (column) => {
3198
- const tdProps = column.getIsPinned()
3199
- ? {
3200
- left: showSelector
3201
- ? `${column.getStart('left') + SELECTION_BOX_WIDTH + table.getDensityValue() * 2}px`
3202
- : `${column.getStart('left')}px`,
3203
- position: 'relative',
3204
- }
3205
- : {};
3206
- return tdProps;
3207
- };
3208
- const getTrProps = ({ hoveredRow, index, }) => {
3209
- if (hoveredRow === -1) {
3210
- return {};
3211
- }
3212
- if (hoveredRow === index) {
3213
- return {
3214
- opacity: '1',
3215
- };
3216
- }
3217
- return {
3218
- opacity: '0.8',
3219
- };
3220
- };
3221
- // Get the number of skeleton rows based on current pageSize
3222
- const pageSize = table.getState().pagination.pageSize;
3223
- const visibleColumns = table.getVisibleLeafColumns();
3224
- return (jsxRuntime.jsx(react.Table.Body, { children: Array.from({ length: pageSize }).map((_, rowIndex) => {
3225
- return (jsxRuntime.jsxs(react.Table.Row, { display: 'flex', zIndex: 1, onMouseEnter: () => handleRowHover(rowIndex), onMouseLeave: () => handleRowHover(-1), ...getTrProps({ hoveredRow, index: rowIndex }), children: [showSelector && jsxRuntime.jsx(TableRowSelectorSkeleton, {}), visibleColumns.map((column, colIndex) => {
3226
- return (jsxRuntime.jsx(react.Table.Cell, { padding: `${table.getDensityValue()}px`,
3227
- // styling resize and pinning start
3228
- flex: `${canResize ? '0' : '1'} 0 ${column.getSize()}px`,
3229
- // this is to avoid the cell from being too wide
3230
- minWidth: `0`, color: {
3231
- base: 'colorPalette.900',
3232
- _dark: 'colorPalette.100',
3233
- },
3234
- bg: { base: 'colorPalette.50', _dark: 'colorPalette.950' }, ...getTdProps(column), children: jsxRuntime.jsx(react.Skeleton, { height: "20px", width: "80%" }) }, `chakra-table-skeleton-cell-${rowIndex}-${colIndex}`));
3235
- })] }, `chakra-table-skeleton-row-${rowIndex}`));
3236
- }) }));
3237
- };
3238
- const TableRowSelectorSkeleton = () => {
3239
- const { table } = useDataTableContext();
3240
- const SELECTION_BOX_WIDTH = 20;
3241
- return (jsxRuntime.jsx(react.Table.Cell, { padding: `${table.getDensityValue()}px`, display: 'grid', color: {
3242
- base: 'colorPalette.900',
3243
- _dark: 'colorPalette.100',
3244
- },
3245
- bg: { base: 'colorPalette.50', _dark: 'colorPalette.950' }, justifyItems: 'center', alignItems: 'center', children: jsxRuntime.jsx(react.Skeleton, { width: `${SELECTION_BOX_WIDTH}px`, height: `${SELECTION_BOX_WIDTH}px` }) }));
3246
- };
3247
-
3248
- const TableFooter = ({ showSelector = false, alwaysShowSelector = true, }) => {
3249
- const table = useDataTableContext().table;
3250
- const SELECTION_BOX_WIDTH = 20;
3251
- const [hoveredCheckBox, setHoveredCheckBox] = React.useState(false);
3252
- const handleRowHover = (isHovered) => {
3253
- setHoveredCheckBox(isHovered);
3254
- };
3255
- const isCheckBoxVisible = () => {
3256
- if (alwaysShowSelector) {
3257
- return true;
3258
- }
3259
- if (table.getIsAllRowsSelected()) {
3260
- return true;
3261
- }
3262
- if (hoveredCheckBox) {
3263
- return true;
3264
- }
3265
- return false;
3266
- };
3267
- 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: table.getIsAllRowsSelected(),
3268
- // indeterminate: table.getIsSomeRowsSelected(),
3269
- onChange: table.getToggleAllRowsSelectedHandler() }) })), !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}`,
3270
- // styling resize and pinning start
3271
- 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
3272
- ? null
3273
- : reactTable.flexRender(header.column.columnDef.footer, header.getContext()), jsxRuntime.jsx(react.Box, { children: header.column.getCanSort() && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [header.column.getIsSorted() === false && jsxRuntime.jsx(jsxRuntime.Fragment, {}), header.column.getIsSorted() === "asc" && (jsxRuntime.jsx(bi.BiUpArrow, {})), header.column.getIsSorted() === "desc" && (jsxRuntime.jsx(bi.BiDownArrow, {}))] })) })] }) }) }) }) }, `chakra-table-footer-${header.column.id}-${footerGroup.id}`)))] }, `chakra-table-footergroup-${footerGroup.id}`))) }));
3274
- };
3275
-
3276
- // Default text values
3277
- const DEFAULT_HEADER_TEXTS = {
3278
- pinColumn: "Pin Column",
3279
- cancelPin: "Cancel Pin",
3280
- sortAscending: "Sort Ascending",
3281
- sortDescending: "Sort Descending",
3282
- clearSorting: "Clear Sorting",
3283
- };
3284
- /**
3285
- * TableHeader component with configurable text strings.
3286
- *
3287
- * @example
3288
- * // Using default texts
3289
- * <TableHeader />
3290
- *
3291
- * @example
3292
- * // Customizing default texts for all columns
3293
- * <TableHeader
3294
- * defaultTexts={{
3295
- * pinColumn: "Pin This Column",
3296
- * sortAscending: "Sort A-Z"
3297
- * }}
3298
- * />
3299
- *
3300
- * @example
3301
- * // Customizing texts per column via meta
3302
- * const columns = [
3303
- * columnHelper.accessor("name", {
3304
- * header: "Name",
3305
- * meta: {
3306
- * headerTexts: {
3307
- * pinColumn: "Pin Name Column",
3308
- * sortAscending: "Sort Names A-Z"
3309
- * }
3310
- * }
3311
- * })
3312
- * ];
3313
- */
3314
- const TableHeader = ({ canResize = true, showSelector = false, isSticky = true, tableHeaderProps = {}, tableRowProps = {}, defaultTexts = {}, }) => {
3315
- const { table } = useDataTableContext();
3316
- const SELECTION_BOX_WIDTH = 20;
3317
- // Merge default texts with provided defaults
3318
- const mergedDefaultTexts = { ...DEFAULT_HEADER_TEXTS, ...defaultTexts };
3319
- // Helper function to get text for a specific header
3320
- const getHeaderText = (header, key) => {
3321
- const columnMeta = header.column.columnDef.meta;
3322
- return columnMeta?.headerTexts?.[key] || mergedDefaultTexts[key];
3323
- };
3324
- const getThProps = (header) => {
3325
- const thProps = header.column.getIsPinned()
3326
- ? {
3327
- left: showSelector
3328
- ? `${header.getStart("left") + SELECTION_BOX_WIDTH + table.getDensityValue() * 2}px`
3329
- : `${header.getStart("left")}px`,
3330
- position: "sticky",
3331
- zIndex: 100 + 1,
3332
- }
3333
- : {};
3334
- return thProps;
3071
+ return thProps;
3335
3072
  };
3336
3073
  const stickyProps = {
3337
3074
  position: "sticky",
@@ -3406,94 +3143,35 @@ const TableHeader = ({ canResize = true, showSelector = false, isSticky = true,
3406
3143
  })] }, `chakra-table-headergroup-${headerGroup.id}`))) }));
3407
3144
  };
3408
3145
 
3409
- const DefaultTable = ({ showFooter = false, tableProps = {}, tableHeaderProps = {}, tableBodyProps = {}, tableFooterProps = {}, controlProps = {}, variant = '', isLoading = false, }) => {
3410
- if (variant === 'greedy') {
3411
- const bodyComponent = isLoading ? (jsxRuntime.jsx(TableBodySkeleton, { showSelector: tableBodyProps.showSelector, canResize: false })) : (jsxRuntime.jsx(TableBody, { ...tableBodyProps, canResize: false, ...tableBodyProps }));
3412
- return (jsxRuntime.jsx(TableControls, { ...controlProps, children: jsxRuntime.jsxs(Table, { canResize: false, showLoading: isLoading, ...tableProps, children: [jsxRuntime.jsx(TableHeader, { canResize: false, ...tableHeaderProps }), bodyComponent, showFooter && (jsxRuntime.jsx(TableFooter, { canResize: false, ...tableFooterProps }))] }) }));
3413
- }
3414
- const bodyComponent = isLoading ? (jsxRuntime.jsx(TableBodySkeleton, { showSelector: tableBodyProps.showSelector, canResize: tableBodyProps.canResize })) : (jsxRuntime.jsx(TableBody, { ...tableBodyProps }));
3415
- return (jsxRuntime.jsx(TableControls, { ...controlProps, children: jsxRuntime.jsxs(Table, { showLoading: isLoading, ...tableProps, children: [jsxRuntime.jsx(TableHeader, { ...tableHeaderProps }), bodyComponent, showFooter && jsxRuntime.jsx(TableFooter, { ...tableFooterProps })] }) }));
3416
- };
3417
-
3418
- /**
3419
- * DefaultTableServer is a wrapper around DefaultTable that automatically
3420
- * detects server-side loading state from DataTableServerContext.
3421
- *
3422
- * Use this component when working with DataTableServer to automatically
3423
- * show skeleton loading state during data fetching.
3424
- *
3425
- * @example
3426
- * ```tsx
3427
- * <DataTableServer columns={columns} {...datatableServer}>
3428
- * <DefaultTableServer />
3429
- * </DataTableServer>
3430
- * ```
3431
- */
3432
- const DefaultTableServer = ({ isLoading: isLoadingOverride, ...props }) => {
3433
- // Automatically detect loading state from server context
3434
- const serverContext = useDataTableServerContext();
3435
- const isLoading = isLoadingOverride ?? serverContext?.query?.isLoading ?? false;
3436
- return jsxRuntime.jsx(DefaultTable, { ...props, isLoading: isLoading });
3146
+ const TableLoadingComponent = ({ render, }) => {
3147
+ const { query } = useDataTableServerContext();
3148
+ return jsxRuntime.jsx(jsxRuntime.Fragment, { children: render(query.isLoading) });
3437
3149
  };
3438
3150
 
3439
- const TableCardContainer = ({ children, variant = "", gap = "1rem", gridTemplateColumns = "repeat(auto-fit, minmax(20rem, 1fr))", direction = "row", ...props }) => {
3440
- if (variant === "carousel") {
3441
- return (jsxRuntime.jsx(react.Flex, { overflow: "auto", gap: gap, direction: direction, ...props, children: children }));
3151
+ const TextCell = ({ label, containerProps = {}, textProps = {}, children, }) => {
3152
+ if (label) {
3153
+ return (jsxRuntime.jsx(react.Flex, { alignItems: "center", height: "100%", ...containerProps, children: jsxRuntime.jsx(Tooltip, { content: jsxRuntime.jsx(react.Text, { as: "span", overflow: "hidden", textOverflow: "ellipsis", children: label }), children: jsxRuntime.jsx(react.Text, { as: "span", overflow: "hidden", textOverflow: "ellipsis", wordBreak: "break-all", ...textProps, children: children }) }) }));
3442
3154
  }
3443
- return (jsxRuntime.jsx(react.Grid, { gridTemplateColumns: gridTemplateColumns, gap: gap, ...props, children: children }));
3155
+ return (jsxRuntime.jsx(react.Flex, { alignItems: "center", height: "100%", ...containerProps, children: jsxRuntime.jsx(react.Text, { as: "span", overflow: "hidden", textOverflow: "ellipsis", wordBreak: "break-all", ...textProps, children: children }) }));
3444
3156
  };
3445
3157
 
3446
- const DefaultCardTitle = () => {
3447
- return jsxRuntime.jsx(jsxRuntime.Fragment, {});
3448
- };
3449
- const TableCards = ({ isSelectable = false, showDisplayNameOnly = false, renderTitle = DefaultCardTitle, cardBodyProps = {}, }) => {
3450
- const { table } = useDataTableContext();
3451
- return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: table.getRowModel().rows.map((row) => {
3452
- 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: row.getIsSelected(),
3453
- disabled: !row.getCanSelect(),
3454
- // indeterminate: row.getIsSomeSelected(),
3455
- onChange: row.getToggleSelectedHandler() })), renderTitle(row), jsxRuntime.jsx(react.Grid, { templateColumns: "auto 1fr", gap: "1rem", children: row.getVisibleCells().map((cell) => {
3456
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs(react.Box, { children: [showDisplayNameOnly && (jsxRuntime.jsx(react.Text, { fontWeight: "bold", children: cell.column.columnDef.meta?.displayName ??
3457
- cell.column.id })), !showDisplayNameOnly && (jsxRuntime.jsx(jsxRuntime.Fragment, { children: reactTable.flexRender(cell.column.columnDef.header,
3458
- // @ts-expect-error Assuming the CellContext interface is the same as HeaderContext
3459
- 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}`)] }));
3460
- }) })] }) }, `chakra-table-card-${row.id}`));
3461
- }) }));
3158
+ const CardHeader = ({ row, imageColumnId = undefined, titleColumnId = undefined, tagColumnId = undefined, tagIcon = undefined, showTag = true, imageProps = {}, }) => {
3159
+ if (!!row.original === false) {
3160
+ return jsxRuntime.jsx(jsxRuntime.Fragment, {});
3161
+ }
3162
+ const isShowFirstColumn = !!titleColumnId || showTag;
3163
+ return (jsxRuntime.jsxs(react.Grid, { templateRows: "auto auto", gap: "1rem", children: [!!imageColumnId && (jsxRuntime.jsx(react.Image, { width: "100%", src: row.original[imageColumnId], ...imageProps })), isShowFirstColumn && (jsxRuntime.jsxs(react.Flex, { gap: "0.5rem", flexFlow: "wrap", children: [!!titleColumnId && (jsxRuntime.jsx(react.Text, { fontWeight: "bold", fontSize: "large", children: row.original[titleColumnId] })), showTag && (jsxRuntime.jsx(Tag, { fontSize: "large", startElement: tagIcon && tagIcon({}), children: row.original[tagColumnId] }))] }))] }));
3462
3164
  };
3463
3165
 
3464
- const TableComponent = ({ render = () => {
3465
- throw Error("Not Implemented");
3466
- }, }) => {
3467
- const { table } = useDataTableContext();
3468
- return render(table);
3166
+ const EmptyState = ({ title = "No records", description = "Add a new events to get started or refine your search", }) => {
3167
+ const { isEmpty } = useDataTableServerContext();
3168
+ return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: isEmpty && (jsxRuntime.jsx(react.EmptyState.Root, { children: jsxRuntime.jsxs(react.EmptyState.Content, { children: [jsxRuntime.jsx(react.EmptyState.Indicator, { children: jsxRuntime.jsx(hi.HiColorSwatch, {}) }), jsxRuntime.jsxs(react.VStack, { textAlign: "center", children: [jsxRuntime.jsx(react.EmptyState.Title, { children: title }), jsxRuntime.jsx(react.EmptyState.Description, { children: description })] })] }) })) }));
3469
3169
  };
3470
3170
 
3471
- const TableLoadingComponent = ({ render, }) => {
3171
+ const ErrorAlert = ({ showMessage = true }) => {
3472
3172
  const { query } = useDataTableServerContext();
3473
- return jsxRuntime.jsx(jsxRuntime.Fragment, { children: render(query.isLoading) });
3474
- };
3475
-
3476
- const SelectAllRowsToggle = ({ selectAllIcon = jsxRuntime.jsx(md.MdOutlineChecklist, {}), clearAllIcon = jsxRuntime.jsx(md.MdClear, {}), selectAllText = "", clearAllText = "", }) => {
3477
- const { table } = useDataTableContext();
3478
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [!!selectAllText === false && (jsxRuntime.jsx(react.IconButton, { variant: "ghost", "aria-label": table.getIsAllRowsSelected() ? clearAllText : selectAllText, onClick: (event) => {
3479
- table.getToggleAllRowsSelectedHandler()(event);
3480
- }, children: table.getIsAllRowsSelected() ? clearAllIcon : selectAllIcon })), !!selectAllText !== false && (jsxRuntime.jsxs(react.Button, { variant: "ghost", onClick: (event) => {
3481
- table.getToggleAllRowsSelectedHandler()(event);
3482
- }, children: [table.getIsAllRowsSelected() ? clearAllIcon : selectAllIcon, table.getIsAllRowsSelected() ? clearAllText : selectAllText] }))] }));
3483
- };
3484
-
3485
- const TableSelector = () => {
3486
- const { table } = useDataTableContext();
3487
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [table.getSelectedRowModel().rows.length > 0 && (jsxRuntime.jsxs(react.Button, { onClick: () => { }, variant: "ghost", display: "flex", gap: "0.25rem", children: [jsxRuntime.jsx(react.Box, { fontSize: "sm", children: `${table.getSelectedRowModel().rows.length}` }), jsxRuntime.jsx(io.IoMdCheckbox, {})] })), !table.getIsAllPageRowsSelected() && jsxRuntime.jsx(SelectAllRowsToggle, {}), table.getSelectedRowModel().rows.length > 0 && (jsxRuntime.jsx(react.IconButton, { variant: "ghost", onClick: () => {
3488
- table.resetRowSelection();
3489
- }, "aria-label": "reset selection", children: jsxRuntime.jsx(md.MdClear, {}) }))] }));
3490
- };
3491
-
3492
- const TextCell = ({ label, containerProps = {}, textProps = {}, children, }) => {
3493
- if (label) {
3494
- return (jsxRuntime.jsx(react.Flex, { alignItems: "center", height: "100%", ...containerProps, children: jsxRuntime.jsx(Tooltip, { content: jsxRuntime.jsx(react.Text, { as: "span", overflow: "hidden", textOverflow: "ellipsis", children: label }), children: jsxRuntime.jsx(react.Text, { as: "span", overflow: "hidden", textOverflow: "ellipsis", wordBreak: "break-all", ...textProps, children: children }) }) }));
3495
- }
3496
- return (jsxRuntime.jsx(react.Flex, { alignItems: "center", height: "100%", ...containerProps, children: jsxRuntime.jsx(react.Text, { as: "span", overflow: "hidden", textOverflow: "ellipsis", wordBreak: "break-all", ...textProps, children: children }) }));
3173
+ const { isError, error } = query;
3174
+ return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: isError && (jsxRuntime.jsxs(react.Alert.Root, { status: "error", children: [jsxRuntime.jsx(react.Alert.Indicator, {}), jsxRuntime.jsxs(react.Alert.Content, { children: [jsxRuntime.jsx(react.Alert.Title, { children: error.name }), showMessage && (jsxRuntime.jsx(react.Alert.Description, { children: error.message }))] })] })) }));
3497
3175
  };
3498
3176
 
3499
3177
  const useDataTable = ({ default: { sorting: defaultSorting = [], pagination: defaultPagination = {
@@ -3625,6 +3303,28 @@ const idListSanityCheck = (param, idList, properties) => {
3625
3303
  }
3626
3304
  };
3627
3305
 
3306
+ const snakeToLabel = (str) => {
3307
+ return str
3308
+ .split("_") // Split by underscore
3309
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()) // Capitalize each word
3310
+ .join(" "); // Join with space
3311
+ };
3312
+
3313
+ const RecordDisplay = ({ object, boxProps, translate, prefix = "", }) => {
3314
+ const getColumn = ({ field }) => {
3315
+ if (translate !== undefined) {
3316
+ return translate.t(`${prefix}${field}`);
3317
+ }
3318
+ return snakeToLabel(field);
3319
+ };
3320
+ if (object === null) {
3321
+ return jsxRuntime.jsx(jsxRuntime.Fragment, { children: "null" });
3322
+ }
3323
+ return (jsxRuntime.jsx(react.Grid, { rowGap: 1, padding: 1, overflow: "auto", ...boxProps, children: Object.entries(object).map(([field, value]) => {
3324
+ 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));
3325
+ }) }));
3326
+ };
3327
+
3628
3328
  const widthSanityCheck = (widthList, ignoreList, properties) => {
3629
3329
  const widthListToolong = widthList.length > Object.keys(properties).length;
3630
3330
  if (widthListToolong) {
@@ -3682,70 +3382,6 @@ const getColumns = ({ schema, include = [], ignore = [], width = [], meta = {},
3682
3382
  return columns;
3683
3383
  };
3684
3384
 
3685
- const TableDataDisplay = ({ colorPalette, emptyComponent, }) => {
3686
- const { columns, translate, data } = useDataTableContext();
3687
- const columnsMap = Object.fromEntries(columns.map((def) => {
3688
- const { accessorKey, id } = def;
3689
- if (accessorKey) {
3690
- return [accessorKey, def];
3691
- }
3692
- return [id, def];
3693
- }));
3694
- const columnHeaders = Object.keys(columnsMap);
3695
- const totalWidths = columns
3696
- .map(({ size }) => {
3697
- if (!!size === false) {
3698
- return 0;
3699
- }
3700
- if (typeof size === "number") {
3701
- return size;
3702
- }
3703
- return 0;
3704
- })
3705
- .reduce((previous, current) => previous + current, 0);
3706
- const columnWidths = columns
3707
- .map(({ size }) => {
3708
- if (!!size === false) {
3709
- return "1fr";
3710
- }
3711
- return `minmax(${size}px, ${(size / totalWidths) * 100}%)`;
3712
- })
3713
- .join(" ");
3714
- console.log({ columnWidths }, "hadfg");
3715
- const cellProps = {
3716
- flex: "1 0 0%",
3717
- overflow: "auto",
3718
- paddingX: "2",
3719
- py: "1",
3720
- color: { base: "colorPalette.900", _dark: "colorPalette.100" },
3721
- bgColor: { base: "colorPalette.50", _dark: "colorPalette.950" },
3722
- borderBottomColor: { base: "colorPalette.200", _dark: "colorPalette.800" },
3723
- borderBottomWidth: "1px",
3724
- ...{ colorPalette },
3725
- };
3726
- if (data.length <= 0) {
3727
- return jsxRuntime.jsx(jsxRuntime.Fragment, { children: emptyComponent });
3728
- }
3729
- 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) => {
3730
- return (jsxRuntime.jsx(react.Box, { flex: "1 0 0%", paddingX: "2", py: "1", overflow: "auto", textOverflow: "ellipsis", children: translate.t(`column_header.${header}`) }));
3731
- }) }), data.map((record) => {
3732
- return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: columnHeaders.map((header) => {
3733
- const { cell } = columnsMap[header];
3734
- const value = record[header];
3735
- if (!!record === false) {
3736
- return (jsxRuntime.jsx(react.Box, { ...cellProps, children: translate.t(`column_cell.placeholder`) }));
3737
- }
3738
- if (cell) {
3739
- return (jsxRuntime.jsx(react.Box, { ...cellProps, children: cell({ row: { original: record } }) }));
3740
- }
3741
- if (typeof value === "object") {
3742
- return (jsxRuntime.jsx(react.Box, { ...cellProps, children: jsxRuntime.jsx(RecordDisplay, { object: value }) }));
3743
- }
3744
- return jsxRuntime.jsx(react.Box, { ...cellProps, children: value });
3745
- }) }));
3746
- })] }));
3747
- };
3748
-
3749
3385
  //@ts-expect-error TODO: find appropriate type
3750
3386
  const SchemaFormContext = React.createContext({
3751
3387
  schema: {},
@@ -5008,10 +4644,13 @@ function formatBytes(bytes) {
5008
4644
  return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
5009
4645
  }
5010
4646
 
5011
- function FilePickerDialog({ open, onClose, onSelect, title, filterImageOnly = false, onFetchFiles, labels, translate, colLabel, }) {
4647
+ const MediaLibraryBrowser = ({ onFetchFiles, filterImageOnly = false, labels, enabled = true, multiple = false, onFileSelect, selectedFileId: controlledSelectedFileId, onSelectedFileIdChange, }) => {
5012
4648
  const [searchTerm, setSearchTerm] = React.useState('');
5013
- const [selectedFileId, setSelectedFileId] = React.useState('');
4649
+ const [internalSelectedFileId, setInternalSelectedFileId] = React.useState(multiple ? [] : '');
5014
4650
  const [failedImageIds, setFailedImageIds] = React.useState(new Set());
4651
+ // Use controlled or internal state for selectedFileId
4652
+ const selectedFileId = controlledSelectedFileId ?? internalSelectedFileId;
4653
+ const setSelectedFileId = onSelectedFileIdChange ?? setInternalSelectedFileId;
5015
4654
  const { data: filesData, isLoading, isError, } = reactQuery.useQuery({
5016
4655
  queryKey: ['file-picker-library', searchTerm],
5017
4656
  queryFn: async () => {
@@ -5020,91 +4659,176 @@ function FilePickerDialog({ open, onClose, onSelect, title, filterImageOnly = fa
5020
4659
  const files = await onFetchFiles(searchTerm.trim() || '');
5021
4660
  return { data: files };
5022
4661
  },
5023
- enabled: open && !!onFetchFiles,
4662
+ enabled: enabled && !!onFetchFiles,
5024
4663
  });
5025
4664
  const files = (filesData?.data || []);
5026
4665
  const filteredFiles = filterImageOnly
5027
4666
  ? files.filter((file) => /\.(jpg|jpeg|png|gif|bmp|webp|svg)$/i.test(file.name))
5028
4667
  : files;
4668
+ const handleFileClick = (fileId) => {
4669
+ if (multiple) {
4670
+ const currentSelection = Array.isArray(selectedFileId)
4671
+ ? selectedFileId
4672
+ : [];
4673
+ const newSelection = currentSelection.includes(fileId)
4674
+ ? currentSelection.filter((id) => id !== fileId)
4675
+ : [...currentSelection, fileId];
4676
+ setSelectedFileId(newSelection);
4677
+ if (onFileSelect) {
4678
+ onFileSelect(newSelection);
4679
+ }
4680
+ }
4681
+ else {
4682
+ setSelectedFileId(fileId);
4683
+ if (onFileSelect) {
4684
+ onFileSelect(fileId);
4685
+ }
4686
+ }
4687
+ };
4688
+ const handleImageError = (fileId) => {
4689
+ setFailedImageIds((prev) => new Set(prev).add(fileId));
4690
+ };
4691
+ if (!onFetchFiles)
4692
+ return null;
4693
+ return (jsxRuntime.jsxs(react.VStack, { align: "stretch", gap: 4, children: [jsxRuntime.jsxs(react.Box, { position: "relative", children: [jsxRuntime.jsx(react.Input, { placeholder: labels?.searchPlaceholder ?? 'Search files...', value: searchTerm, onChange: (e) => setSearchTerm(e.target.value), bg: "bg.panel", border: "1px solid", borderColor: "border.default", colorPalette: "blue", _focus: {
4694
+ borderColor: 'colorPalette.500',
4695
+ _dark: {
4696
+ borderColor: 'colorPalette.400',
4697
+ },
4698
+ boxShadow: {
4699
+ base: '0 0 0 1px var(--chakra-colors-blue-500)',
4700
+ _dark: '0 0 0 1px var(--chakra-colors-blue-400)',
4701
+ },
4702
+ }, pl: 10 }), jsxRuntime.jsx(react.Icon, { as: lu.LuSearch, position: "absolute", left: 3, top: "50%", transform: "translateY(-50%)", color: "fg.muted", boxSize: 4 })] }), isLoading && (jsxRuntime.jsxs(react.Box, { textAlign: "center", py: 8, children: [jsxRuntime.jsx(react.Spinner, { size: "lg", colorPalette: "blue" }), jsxRuntime.jsx(react.Text, { mt: 4, color: "fg.muted", children: labels?.loading ?? 'Loading files...' })] })), isError && (jsxRuntime.jsx(react.Box, { bg: { base: 'colorPalette.50', _dark: 'colorPalette.900/20' }, border: "1px solid", borderColor: {
4703
+ base: 'colorPalette.200',
4704
+ _dark: 'colorPalette.800',
4705
+ }, colorPalette: "red", borderRadius: "md", p: 4, children: jsxRuntime.jsx(react.Text, { color: {
4706
+ base: 'colorPalette.600',
4707
+ _dark: 'colorPalette.300',
4708
+ }, children: labels?.loadingFailed ?? 'Failed to load files' }) })), !isLoading && !isError && (jsxRuntime.jsx(react.Box, { maxHeight: "400px", overflowY: "auto", children: filteredFiles.length === 0 ? (jsxRuntime.jsx(react.Box, { textAlign: "center", py: 8, children: jsxRuntime.jsx(react.Text, { color: "fg.muted", children: labels?.noFilesFound ?? 'No files found' }) })) : (jsxRuntime.jsx(react.VStack, { align: "stretch", gap: 2, children: filteredFiles.map((file) => {
4709
+ const isImage = /\.(jpg|jpeg|png|gif|bmp|webp|svg)$/i.test(file.name);
4710
+ const isSelected = multiple
4711
+ ? Array.isArray(selectedFileId) &&
4712
+ selectedFileId.includes(file.id)
4713
+ : selectedFileId === file.id;
4714
+ const imageFailed = failedImageIds.has(file.id);
4715
+ return (jsxRuntime.jsx(react.Box, { p: 3, border: "2px solid", borderColor: isSelected
4716
+ ? {
4717
+ base: 'colorPalette.500',
4718
+ _dark: 'colorPalette.400',
4719
+ }
4720
+ : 'border.default', borderRadius: "md", bg: isSelected
4721
+ ? {
4722
+ base: 'colorPalette.50',
4723
+ _dark: 'colorPalette.900/20',
4724
+ }
4725
+ : 'bg.panel', colorPalette: "blue", cursor: "pointer", onClick: () => handleFileClick(file.id), _hover: {
4726
+ borderColor: isSelected
4727
+ ? {
4728
+ base: 'colorPalette.600',
4729
+ _dark: 'colorPalette.400',
4730
+ }
4731
+ : {
4732
+ base: 'colorPalette.300',
4733
+ _dark: 'colorPalette.400',
4734
+ },
4735
+ bg: isSelected
4736
+ ? {
4737
+ base: 'colorPalette.100',
4738
+ _dark: 'colorPalette.800/30',
4739
+ }
4740
+ : 'bg.muted',
4741
+ }, transition: "all 0.2s", children: jsxRuntime.jsxs(react.HStack, { gap: 3, children: [jsxRuntime.jsx(react.Box, { width: "60px", height: "60px", display: "flex", alignItems: "center", justifyContent: "center", bg: "bg.muted", borderRadius: "md", flexShrink: 0, children: isImage && file.url && !imageFailed ? (jsxRuntime.jsx(react.Image, { src: file.url, alt: file.name, boxSize: "60px", objectFit: "cover", borderRadius: "md", onError: () => handleImageError(file.id) })) : isImage && (imageFailed || !file.url) ? (jsxRuntime.jsx(react.Icon, { as: lu.LuImage, boxSize: 6, color: "fg.muted" })) : (jsxRuntime.jsx(react.Icon, { as: lu.LuFile, boxSize: 6, color: "fg.muted" })) }), jsxRuntime.jsxs(react.VStack, { align: "start", flex: 1, gap: 1, children: [jsxRuntime.jsx(react.Text, { fontSize: "sm", fontWeight: "medium", color: "fg.default", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", children: file.name }), jsxRuntime.jsxs(react.HStack, { gap: 2, children: [file.size && (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsx(react.Text, { fontSize: "xs", color: "fg.muted", children: typeof file.size === 'number'
4742
+ ? formatBytes(file.size)
4743
+ : file.size }) })), file.comment && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [file.size && (jsxRuntime.jsx(react.Text, { fontSize: "xs", color: "fg.muted", children: "\u2022" })), jsxRuntime.jsx(react.Text, { fontSize: "xs", color: "fg.muted", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", children: file.comment })] }))] })] }), isSelected && (jsxRuntime.jsx(react.Box, { width: "24px", height: "24px", borderRadius: "full", bg: {
4744
+ base: 'colorPalette.500',
4745
+ _dark: 'colorPalette.400',
4746
+ }, colorPalette: "blue", display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0, children: jsxRuntime.jsx(react.Text, { color: "white", fontSize: "xs", fontWeight: "bold", children: "\u2713" }) }))] }) }, file.id));
4747
+ }) })) }))] }));
4748
+ };
4749
+
4750
+ function FilePickerDialog({ open, onClose, onSelect, title, filterImageOnly = false, onFetchFiles, onUploadFile, enableUpload = false, labels, translate, colLabel, }) {
4751
+ const [selectedFileId, setSelectedFileId] = React.useState('');
4752
+ const [activeTab, setActiveTab] = React.useState('browse');
4753
+ const [uploadingFiles, setUploadingFiles] = React.useState(new Set());
4754
+ const [uploadErrors, setUploadErrors] = React.useState(new Map());
5029
4755
  const handleSelect = () => {
5030
4756
  if (selectedFileId) {
5031
4757
  onSelect(selectedFileId);
5032
4758
  onClose();
5033
4759
  setSelectedFileId('');
5034
- setSearchTerm('');
4760
+ setActiveTab('browse');
5035
4761
  }
5036
4762
  };
5037
4763
  const handleClose = () => {
5038
4764
  onClose();
5039
4765
  setSelectedFileId('');
5040
- setSearchTerm('');
5041
- setFailedImageIds(new Set());
4766
+ setActiveTab('browse');
4767
+ setUploadingFiles(new Set());
4768
+ setUploadErrors(new Map());
5042
4769
  };
5043
- const handleImageError = (fileId) => {
5044
- setFailedImageIds((prev) => new Set(prev).add(fileId));
4770
+ const handleFileUpload = async (files) => {
4771
+ if (!onUploadFile)
4772
+ return;
4773
+ for (const file of files) {
4774
+ const fileKey = `${file.name}-${file.size}`;
4775
+ setUploadingFiles((prev) => new Set(prev).add(fileKey));
4776
+ setUploadErrors((prev) => {
4777
+ const newMap = new Map(prev);
4778
+ newMap.delete(fileKey);
4779
+ return newMap;
4780
+ });
4781
+ try {
4782
+ const fileId = await onUploadFile(file);
4783
+ setSelectedFileId(fileId);
4784
+ setUploadingFiles((prev) => {
4785
+ const newSet = new Set(prev);
4786
+ newSet.delete(fileKey);
4787
+ return newSet;
4788
+ });
4789
+ // Auto-select and close in single-select mode
4790
+ onSelect(fileId);
4791
+ onClose();
4792
+ setSelectedFileId('');
4793
+ setActiveTab('browse');
4794
+ }
4795
+ catch (error) {
4796
+ setUploadingFiles((prev) => {
4797
+ const newSet = new Set(prev);
4798
+ newSet.delete(fileKey);
4799
+ return newSet;
4800
+ });
4801
+ setUploadErrors((prev) => {
4802
+ const newMap = new Map(prev);
4803
+ newMap.set(fileKey, error instanceof Error ? error.message : 'Upload failed');
4804
+ return newMap;
4805
+ });
4806
+ }
4807
+ }
5045
4808
  };
5046
- if (!onFetchFiles)
4809
+ const showTabs = enableUpload && !!onUploadFile && !!onFetchFiles;
4810
+ if (!onFetchFiles && !onUploadFile)
5047
4811
  return null;
5048
- return (jsxRuntime.jsx(DialogRoot, { open: open, onOpenChange: (e) => !e.open && handleClose(), children: jsxRuntime.jsxs(DialogContent, { maxWidth: "800px", maxHeight: "90vh", children: [jsxRuntime.jsxs(DialogHeader, { children: [jsxRuntime.jsx(DialogTitle, { fontSize: "lg", fontWeight: "bold", children: title }), jsxRuntime.jsx(DialogCloseTrigger, {})] }), jsxRuntime.jsx(DialogBody, { children: jsxRuntime.jsxs(react.VStack, { align: "stretch", gap: 4, children: [jsxRuntime.jsxs(react.Box, { position: "relative", children: [jsxRuntime.jsx(react.Input, { placeholder: labels?.searchPlaceholder ??
5049
- translate(removeIndex(`${colLabel}.search_placeholder`)) ??
5050
- 'Search files...', value: searchTerm, onChange: (e) => setSearchTerm(e.target.value), bg: "bg.panel", border: "1px solid", borderColor: "border.default", colorPalette: "blue", _focus: {
5051
- borderColor: 'colorPalette.500',
5052
- _dark: {
5053
- borderColor: 'colorPalette.400',
5054
- },
5055
- boxShadow: {
5056
- base: '0 0 0 1px var(--chakra-colors-blue-500)',
5057
- _dark: '0 0 0 1px var(--chakra-colors-blue-400)',
5058
- },
5059
- }, pl: 10 }), jsxRuntime.jsx(react.Icon, { as: lu.LuSearch, position: "absolute", left: 3, top: "50%", transform: "translateY(-50%)", color: "fg.muted", boxSize: 4 })] }), isLoading && (jsxRuntime.jsxs(react.Box, { textAlign: "center", py: 8, children: [jsxRuntime.jsx(react.Spinner, { size: "lg", colorPalette: "blue" }), jsxRuntime.jsx(react.Text, { mt: 4, color: "fg.muted", children: labels?.loading ??
5060
- translate(removeIndex(`${colLabel}.loading`)) ??
5061
- 'Loading files...' })] })), isError && (jsxRuntime.jsx(react.Box, { bg: { base: 'colorPalette.50', _dark: 'colorPalette.900/20' }, border: "1px solid", borderColor: {
5062
- base: 'colorPalette.200',
5063
- _dark: 'colorPalette.800',
5064
- }, colorPalette: "red", borderRadius: "md", p: 4, children: jsxRuntime.jsx(react.Text, { color: {
5065
- base: 'colorPalette.600',
5066
- _dark: 'colorPalette.300',
5067
- }, children: labels?.loadingFailed ??
5068
- translate(removeIndex(`${colLabel}.error.loading_failed`)) ??
5069
- 'Failed to load files' }) })), !isLoading && !isError && (jsxRuntime.jsx(react.Box, { maxHeight: "400px", overflowY: "auto", children: filteredFiles.length === 0 ? (jsxRuntime.jsx(react.Box, { textAlign: "center", py: 8, children: jsxRuntime.jsx(react.Text, { color: "fg.muted", children: labels?.noFilesFound ??
5070
- translate(removeIndex(`${colLabel}.no_files_found`)) ??
5071
- 'No files found' }) })) : (jsxRuntime.jsx(react.VStack, { align: "stretch", gap: 2, children: filteredFiles.map((file) => {
5072
- const isImage = /\.(jpg|jpeg|png|gif|bmp|webp|svg)$/i.test(file.name);
5073
- const isSelected = selectedFileId === file.id;
5074
- const imageFailed = failedImageIds.has(file.id);
5075
- return (jsxRuntime.jsx(react.Box, { p: 3, border: "2px solid", borderColor: isSelected
5076
- ? {
5077
- base: 'colorPalette.500',
5078
- _dark: 'colorPalette.400',
5079
- }
5080
- : 'border.default', borderRadius: "md", bg: isSelected
5081
- ? {
4812
+ return (jsxRuntime.jsx(DialogRoot, { open: open, onOpenChange: (e) => !e.open && handleClose(), children: jsxRuntime.jsxs(DialogContent, { maxWidth: "800px", maxHeight: "90vh", children: [jsxRuntime.jsxs(DialogHeader, { children: [jsxRuntime.jsx(DialogTitle, { fontSize: "lg", fontWeight: "bold", children: title }), jsxRuntime.jsx(DialogCloseTrigger, {})] }), jsxRuntime.jsx(DialogBody, { children: showTabs ? (jsxRuntime.jsxs(react.Tabs.Root, { value: activeTab, onValueChange: (e) => setActiveTab(e.value ?? 'browse'), children: [jsxRuntime.jsxs(react.Tabs.List, { children: [jsxRuntime.jsx(react.Tabs.Trigger, { value: "browse", children: labels?.browseTab ??
4813
+ translate(removeIndex(`${colLabel}.browse_tab`)) ??
4814
+ 'Browse Library' }), jsxRuntime.jsx(react.Tabs.Trigger, { value: "upload", children: labels?.uploadTab ??
4815
+ translate(removeIndex(`${colLabel}.upload_tab`)) ??
4816
+ 'Upload Files' })] }), jsxRuntime.jsx(react.Tabs.Content, { value: "browse", children: onFetchFiles && (jsxRuntime.jsx(MediaLibraryBrowser, { onFetchFiles: onFetchFiles, filterImageOnly: filterImageOnly, labels: labels, enabled: open && activeTab === 'browse', selectedFileId: selectedFileId, onSelectedFileIdChange: setSelectedFileId })) }), jsxRuntime.jsx(react.Tabs.Content, { value: "upload", children: jsxRuntime.jsxs(react.VStack, { align: "stretch", gap: 4, children: [jsxRuntime.jsx(FileDropzone, { onDrop: ({ files }) => handleFileUpload(files), placeholder: labels?.fileDropzone ??
4817
+ translate(removeIndex(`${colLabel}.fileDropzone`)) ??
4818
+ 'Drop files here or click to upload' }), uploadingFiles.size > 0 && (jsxRuntime.jsx(react.Box, { children: Array.from(uploadingFiles).map((fileKey) => (jsxRuntime.jsx(react.Box, { py: 2, children: jsxRuntime.jsxs(react.HStack, { gap: 2, children: [jsxRuntime.jsx(react.Spinner, { size: "sm", colorPalette: "blue" }), jsxRuntime.jsxs(react.Text, { fontSize: "sm", color: "fg.muted", children: [labels?.uploading ??
4819
+ translate(removeIndex(`${colLabel}.uploading`)) ??
4820
+ 'Uploading...', ' ', fileKey.split('-')[0]] })] }) }, fileKey))) })), uploadErrors.size > 0 && (jsxRuntime.jsx(react.VStack, { align: "stretch", gap: 2, children: Array.from(uploadErrors.entries()).map(([fileKey, error]) => (jsxRuntime.jsx(react.Box, { bg: {
5082
4821
  base: 'colorPalette.50',
5083
4822
  _dark: 'colorPalette.900/20',
5084
- }
5085
- : 'bg.panel', colorPalette: "blue", cursor: "pointer", onClick: () => setSelectedFileId(file.id), _hover: {
5086
- borderColor: isSelected
5087
- ? {
4823
+ }, border: "1px solid", borderColor: {
4824
+ base: 'colorPalette.200',
4825
+ _dark: 'colorPalette.800',
4826
+ }, colorPalette: "red", borderRadius: "md", p: 3, children: jsxRuntime.jsxs(react.Text, { fontSize: "sm", color: {
5088
4827
  base: 'colorPalette.600',
5089
- _dark: 'colorPalette.400',
5090
- }
5091
- : {
5092
- base: 'colorPalette.300',
5093
- _dark: 'colorPalette.400',
5094
- },
5095
- bg: isSelected
5096
- ? {
5097
- base: 'colorPalette.100',
5098
- _dark: 'colorPalette.800/30',
5099
- }
5100
- : 'bg.muted',
5101
- }, transition: "all 0.2s", children: jsxRuntime.jsxs(react.HStack, { gap: 3, children: [jsxRuntime.jsx(react.Box, { width: "60px", height: "60px", display: "flex", alignItems: "center", justifyContent: "center", bg: "bg.muted", borderRadius: "md", flexShrink: 0, children: isImage && file.url && !imageFailed ? (jsxRuntime.jsx(react.Image, { src: file.url, alt: file.name, boxSize: "60px", objectFit: "cover", borderRadius: "md", onError: () => handleImageError(file.id) })) : isImage && (imageFailed || !file.url) ? (jsxRuntime.jsx(react.Icon, { as: lu.LuImage, boxSize: 6, color: "fg.muted" })) : (jsxRuntime.jsx(react.Icon, { as: lu.LuFile, boxSize: 6, color: "fg.muted" })) }), jsxRuntime.jsxs(react.VStack, { align: "start", flex: 1, gap: 1, children: [jsxRuntime.jsx(react.Text, { fontSize: "sm", fontWeight: "medium", color: "fg.default", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", children: file.name }), jsxRuntime.jsxs(react.HStack, { gap: 2, children: [file.size && (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsx(react.Text, { fontSize: "xs", color: "fg.muted", children: typeof file.size === 'number'
5102
- ? formatBytes(file.size)
5103
- : file.size }) })), file.comment && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [file.size && (jsxRuntime.jsx(react.Text, { fontSize: "xs", color: "fg.muted", children: "\u2022" })), jsxRuntime.jsx(react.Text, { fontSize: "xs", color: "fg.muted", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", children: file.comment })] }))] })] }), isSelected && (jsxRuntime.jsx(react.Box, { width: "24px", height: "24px", borderRadius: "full", bg: {
5104
- base: 'colorPalette.500',
5105
- _dark: 'colorPalette.400',
5106
- }, colorPalette: "blue", display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0, children: jsxRuntime.jsx(react.Text, { color: "white", fontSize: "xs", fontWeight: "bold", children: "\u2713" }) }))] }) }, file.id));
5107
- }) })) }))] }) }), jsxRuntime.jsx(DialogFooter, { children: jsxRuntime.jsxs(react.HStack, { gap: 3, justify: "end", children: [jsxRuntime.jsx(react.Button, { variant: "outline", onClick: handleClose, borderColor: "border.default", bg: "bg.panel", _hover: { bg: 'bg.muted' }, children: labels?.cancel ??
4828
+ _dark: 'colorPalette.300',
4829
+ }, children: [fileKey.split('-')[0], ":", ' ', labels?.uploadFailed ??
4830
+ translate(removeIndex(`${colLabel}.upload_failed`)) ??
4831
+ 'Upload failed', error && ` - ${error}`] }) }, fileKey))) }))] }) })] })) : onFetchFiles ? (jsxRuntime.jsx(MediaLibraryBrowser, { onFetchFiles: onFetchFiles, filterImageOnly: filterImageOnly, labels: labels, enabled: open, selectedFileId: selectedFileId, onSelectedFileIdChange: setSelectedFileId })) : null }), jsxRuntime.jsx(DialogFooter, { children: jsxRuntime.jsxs(react.HStack, { gap: 3, justify: "end", children: [jsxRuntime.jsx(react.Button, { variant: "outline", onClick: handleClose, borderColor: "border.default", bg: "bg.panel", _hover: { bg: 'bg.muted' }, children: labels?.cancel ??
5108
4832
  translate(removeIndex(`${colLabel}.cancel`)) ??
5109
4833
  'Cancel' }), jsxRuntime.jsx(react.Button, { colorPalette: "blue", onClick: handleSelect, disabled: !selectedFileId, children: labels?.select ??
5110
4834
  translate(removeIndex(`${colLabel}.select`)) ??
@@ -5114,84 +4838,71 @@ const FilePicker = ({ column, schema, prefix }) => {
5114
4838
  const { setValue, formState: { errors }, watch, } = reactHookForm.useFormContext();
5115
4839
  const { filePickerLabels } = useSchemaContext();
5116
4840
  const formI18n = useFormI18n(column, prefix);
5117
- const { required, gridColumn = 'span 12', gridRow = 'span 1', filePicker, } = schema;
4841
+ const { required, gridColumn = 'span 12', gridRow = 'span 1', type, } = schema;
5118
4842
  const isRequired = required?.some((columnId) => columnId === column);
5119
- const currentValue = watch(column) ?? [];
5120
- const currentFiles = Array.isArray(currentValue)
5121
- ? currentValue
5122
- : [];
4843
+ const isSingleSelect = type === 'string';
4844
+ const currentValue = watch(column) ?? (isSingleSelect ? '' : []);
4845
+ // Handle File objects only
4846
+ const currentFiles = isSingleSelect
4847
+ ? currentValue && currentValue instanceof File
4848
+ ? [currentValue]
4849
+ : []
4850
+ : Array.isArray(currentValue)
4851
+ ? currentValue.filter((f) => f instanceof File)
4852
+ : [];
5123
4853
  const colLabel = formI18n.colLabel;
5124
- const [dialogOpen, setDialogOpen] = React.useState(false);
5125
4854
  const [failedImageIds, setFailedImageIds] = React.useState(new Set());
5126
- const { onFetchFiles, enableMediaLibrary = false, filterImageOnly = false, } = filePicker || {};
5127
- const showMediaLibrary = enableMediaLibrary && !!onFetchFiles;
4855
+ // FilePicker variant: Only handle File objects, no media library browser
5128
4856
  const handleImageError = (fileIdentifier) => {
5129
4857
  setFailedImageIds((prev) => new Set(prev).add(fileIdentifier));
5130
4858
  };
5131
- const handleMediaLibrarySelect = (fileId) => {
5132
- const newFiles = [...currentFiles, fileId];
5133
- setValue(colLabel, newFiles);
5134
- };
5135
4859
  const handleRemove = (index) => {
5136
- const newFiles = currentFiles.filter((_, i) => i !== index);
5137
- setValue(colLabel, newFiles);
5138
- };
5139
- const isFileObject = (value) => {
5140
- return value instanceof File;
4860
+ if (isSingleSelect) {
4861
+ setValue(colLabel, '');
4862
+ }
4863
+ else {
4864
+ const newFiles = currentFiles.filter((_, i) => i !== index);
4865
+ setValue(colLabel, newFiles);
4866
+ }
5141
4867
  };
5142
4868
  const getFileIdentifier = (file, index) => {
5143
- if (isFileObject(file)) {
5144
- return `${file.name}-${file.size}-${index}`;
5145
- }
5146
- return file;
4869
+ // file-picker: file is a File object, create identifier from name and size
4870
+ return `${file.name}-${file.size}-${index}`;
5147
4871
  };
5148
4872
  const getFileName = (file) => {
5149
- if (isFileObject(file)) {
5150
- return file.name;
5151
- }
5152
- return typeof file === 'string' ? file : 'Unknown file';
4873
+ return file.name;
5153
4874
  };
5154
4875
  const getFileSize = (file) => {
5155
- if (isFileObject(file)) {
5156
- return file.size;
5157
- }
5158
- return undefined;
4876
+ return file.size;
5159
4877
  };
5160
4878
  const isImageFile = (file) => {
5161
- if (isFileObject(file)) {
5162
- return file.type.startsWith('image/');
5163
- }
5164
- if (typeof file === 'string') {
5165
- return /\.(jpg|jpeg|png|gif|bmp|webp|svg)$/i.test(file);
5166
- }
5167
- return false;
4879
+ return file.type.startsWith('image/');
5168
4880
  };
5169
4881
  const getImageUrl = (file) => {
5170
- if (isFileObject(file)) {
5171
- return URL.createObjectURL(file);
5172
- }
5173
- return undefined;
4882
+ return URL.createObjectURL(file);
5174
4883
  };
5175
4884
  return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
5176
- gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: [jsxRuntime.jsxs(react.VStack, { align: "stretch", gap: 2, children: [jsxRuntime.jsx(FileDropzone, { onDrop: ({ files }) => {
5177
- const newFiles = files.filter(({ name }) => !currentFiles.some((cur) => {
5178
- if (isFileObject(cur)) {
5179
- return cur.name === name;
5180
- }
5181
- return false;
5182
- }));
4885
+ gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: [jsxRuntime.jsx(react.VStack, { align: "stretch", gap: 2, children: jsxRuntime.jsx(FileDropzone, { onDrop: ({ files }) => {
4886
+ // file-picker variant: Store File objects directly (no ID conversion)
4887
+ if (isSingleSelect) {
4888
+ // In single-select mode, use the first file and replace any existing file
4889
+ if (files.length > 0) {
4890
+ setValue(colLabel, files[0]);
4891
+ }
4892
+ }
4893
+ else {
4894
+ // In multi-select mode, filter duplicates and append
4895
+ const newFiles = files.filter(({ name }) => !currentFiles.some((cur) => cur.name === name));
5183
4896
  setValue(colLabel, [...currentFiles, ...newFiles]);
5184
- }, placeholder: filePickerLabels?.fileDropzone ?? formI18n.t('fileDropzone') }), showMediaLibrary && (jsxRuntime.jsx(react.Button, { variant: "outline", onClick: () => setDialogOpen(true), borderColor: "border.default", bg: "bg.panel", _hover: { bg: 'bg.muted' }, children: filePickerLabels?.browseLibrary ??
5185
- formI18n.t('browse_library') ??
5186
- 'Browse from Library' }))] }), showMediaLibrary && (jsxRuntime.jsx(FilePickerDialog, { open: dialogOpen, onClose: () => setDialogOpen(false), onSelect: handleMediaLibrarySelect, title: filePickerLabels?.dialogTitle ??
5187
- formI18n.t('dialog_title') ??
5188
- 'Select File', filterImageOnly: filterImageOnly, onFetchFiles: onFetchFiles, labels: filePickerLabels, translate: formI18n.t, colLabel: colLabel })), jsxRuntime.jsx(react.Flex, { flexFlow: 'column', gap: 1, children: currentFiles.map((file, index) => {
4897
+ }
4898
+ }, placeholder: filePickerLabels?.fileDropzone ?? formI18n.t('fileDropzone') }) }), jsxRuntime.jsx(react.Flex, { flexFlow: 'column', gap: 1, children: currentFiles.map((file, index) => {
5189
4899
  const fileIdentifier = getFileIdentifier(file, index);
5190
4900
  const fileName = getFileName(file);
5191
4901
  const fileSize = getFileSize(file);
5192
4902
  const isImage = isImageFile(file);
5193
4903
  const imageUrl = getImageUrl(file);
5194
4904
  const imageFailed = failedImageIds.has(fileIdentifier);
4905
+ // File Viewer
5195
4906
  return (jsxRuntime.jsx(react.Card.Root, { variant: 'subtle', colorPalette: "blue", children: jsxRuntime.jsxs(react.Card.Body, { gap: "2", cursor: 'pointer', onClick: () => handleRemove(index), display: 'flex', flexFlow: 'row', alignItems: 'center', padding: '2', border: "2px solid", borderColor: "border.default", borderRadius: "md", _hover: {
5196
4907
  borderColor: 'colorPalette.300',
5197
4908
  bg: 'bg.muted',
@@ -5199,6 +4910,66 @@ const FilePicker = ({ column, schema, prefix }) => {
5199
4910
  }) })] }));
5200
4911
  };
5201
4912
 
4913
+ const FormMediaLibraryBrowser = ({ column, schema, prefix, }) => {
4914
+ const { setValue, formState: { errors }, watch, } = reactHookForm.useFormContext();
4915
+ const { filePickerLabels } = useSchemaContext();
4916
+ const formI18n = useFormI18n(column, prefix);
4917
+ const { required, gridColumn = 'span 12', gridRow = 'span 1', filePicker, type, } = schema;
4918
+ const isRequired = required?.some((columnId) => columnId === column);
4919
+ const isSingleSelect = type === 'string';
4920
+ const currentValue = watch(column) ?? (isSingleSelect ? '' : []);
4921
+ // Handle string IDs only
4922
+ const currentFileIds = isSingleSelect
4923
+ ? currentValue
4924
+ ? [currentValue]
4925
+ : []
4926
+ : Array.isArray(currentValue)
4927
+ ? currentValue
4928
+ : [];
4929
+ const colLabel = formI18n.colLabel;
4930
+ const [dialogOpen, setDialogOpen] = React.useState(false);
4931
+ const [failedImageIds, setFailedImageIds] = React.useState(new Set());
4932
+ const { onFetchFiles, filterImageOnly = false, enableUpload = false, onUploadFile, } = filePicker || {};
4933
+ if (!onFetchFiles) {
4934
+ return (jsxRuntime.jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
4935
+ gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: jsxRuntime.jsx(react.Text, { color: "fg.muted", children: "Media library browser requires onFetchFiles" }) }));
4936
+ }
4937
+ const handleMediaLibrarySelect = (fileId) => {
4938
+ if (isSingleSelect) {
4939
+ setValue(colLabel, fileId);
4940
+ }
4941
+ else {
4942
+ const newFileIds = [...currentFileIds, fileId];
4943
+ setValue(colLabel, newFileIds);
4944
+ }
4945
+ };
4946
+ const handleRemove = (index) => {
4947
+ if (isSingleSelect) {
4948
+ setValue(colLabel, '');
4949
+ }
4950
+ else {
4951
+ const newFileIds = currentFileIds.filter((_, i) => i !== index);
4952
+ setValue(colLabel, newFileIds);
4953
+ }
4954
+ };
4955
+ const isImageId = (fileId) => {
4956
+ return /\.(jpg|jpeg|png|gif|bmp|webp|svg)$/i.test(fileId);
4957
+ };
4958
+ return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
4959
+ gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: [jsxRuntime.jsx(react.VStack, { align: "stretch", gap: 2, children: jsxRuntime.jsx(react.Button, { variant: "outline", onClick: () => setDialogOpen(true), borderColor: "border.default", bg: "bg.panel", _hover: { bg: 'bg.muted' }, children: filePickerLabels?.browseLibrary ??
4960
+ formI18n.t('browse_library') ??
4961
+ 'Browse from Library' }) }), jsxRuntime.jsx(FilePickerDialog, { open: dialogOpen, onClose: () => setDialogOpen(false), onSelect: handleMediaLibrarySelect, title: filePickerLabels?.dialogTitle ??
4962
+ formI18n.t('dialog_title') ??
4963
+ 'Select File', filterImageOnly: filterImageOnly, onFetchFiles: onFetchFiles, onUploadFile: onUploadFile, enableUpload: enableUpload, labels: filePickerLabels, translate: formI18n.t, colLabel: colLabel }), jsxRuntime.jsx(react.Flex, { flexFlow: 'column', gap: 1, children: currentFileIds.map((fileId, index) => {
4964
+ const isImage = isImageId(fileId);
4965
+ const imageFailed = failedImageIds.has(fileId);
4966
+ return (jsxRuntime.jsx(react.Card.Root, { variant: 'subtle', colorPalette: "blue", children: jsxRuntime.jsxs(react.Card.Body, { gap: "2", cursor: 'pointer', onClick: () => handleRemove(index), display: 'flex', flexFlow: 'row', alignItems: 'center', padding: '2', border: "2px solid", borderColor: "border.default", borderRadius: "md", _hover: {
4967
+ borderColor: 'colorPalette.300',
4968
+ bg: 'bg.muted',
4969
+ }, transition: "all 0.2s", children: [jsxRuntime.jsx(react.Box, { width: "60px", height: "60px", display: "flex", alignItems: "center", justifyContent: "center", bg: "bg.muted", borderRadius: "md", flexShrink: 0, marginRight: "2", children: isImage && !imageFailed ? (jsxRuntime.jsx(react.Icon, { as: lu.LuImage, boxSize: 6, color: "fg.muted" })) : (jsxRuntime.jsx(react.Icon, { as: lu.LuFile, boxSize: 6, color: "fg.muted" })) }), jsxRuntime.jsx(react.VStack, { align: "start", flex: 1, gap: 1, children: jsxRuntime.jsx(react.Text, { fontSize: "sm", fontWeight: "medium", color: "fg.default", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", children: fileId }) }), jsxRuntime.jsx(react.Icon, { as: ti.TiDeleteOutline, boxSize: 5, color: "fg.muted" })] }) }, `${fileId}-${index}`));
4970
+ }) })] }));
4971
+ };
4972
+
5202
4973
  const ToggleTip = React__namespace.forwardRef(function ToggleTip(props, ref) {
5203
4974
  const { showArrow, children, portalled = true, content, portalRef, ...rest } = props;
5204
4975
  return (jsxRuntime.jsxs(react.Popover.Root, { ...rest, positioning: { ...rest.positioning, gutter: 4 }, children: [jsxRuntime.jsx(react.Popover.Trigger, { asChild: true, children: children }), jsxRuntime.jsx(react.Portal, { disabled: !portalled, container: portalRef, children: jsxRuntime.jsx(react.Popover.Positioner, { children: jsxRuntime.jsxs(react.Popover.Content, { width: "auto", px: "2", py: "1", textStyle: "xs", rounded: "sm", ref: ref, children: [showArrow && (jsxRuntime.jsx(react.Popover.Arrow, { children: jsxRuntime.jsx(react.Popover.ArrowTip, {}) })), content] }) }) })] }));
@@ -5237,7 +5008,7 @@ const getTableData = async ({ serverUrl, in_table, searching = "", where = [], l
5237
5008
  };
5238
5009
 
5239
5010
  const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
5240
- const { watch, formState: { errors }, setValue, } = reactHookForm.useFormContext();
5011
+ const { watch, getValues, formState: { errors }, setValue, } = reactHookForm.useFormContext();
5241
5012
  const { serverUrl, idMap, setIdMap, schema: parentSchema, idPickerLabels, } = useSchemaContext();
5242
5013
  const formI18n = useFormI18n(column, prefix);
5243
5014
  const { required, gridColumn = 'span 12', gridRow = 'span 1', renderDisplay, foreign_key, } = schema;
@@ -5249,8 +5020,26 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
5249
5020
  const [page, setPage] = React.useState(0);
5250
5021
  const ref = React.useRef(null);
5251
5022
  const colLabel = formI18n.colLabel;
5252
- const watchId = watch(colLabel);
5253
- const watchIds = isMultiple ? (watch(colLabel) ?? []) : [];
5023
+ const watchedValue = watch(colLabel);
5024
+ const watchId = !isMultiple ? watchedValue : undefined;
5025
+ const watchIds = isMultiple
5026
+ ? (Array.isArray(watchedValue) ? watchedValue : [])
5027
+ : [];
5028
+ // Get initial values immediately to ensure query can trigger on mount
5029
+ const initialValue = getValues(colLabel);
5030
+ const initialId = !isMultiple ? initialValue : undefined;
5031
+ const initialIds = isMultiple
5032
+ ? (Array.isArray(initialValue) ? initialValue : [])
5033
+ : [];
5034
+ // Use watched values if they exist (including empty string for single select),
5035
+ // otherwise fall back to initial values from getValues()
5036
+ // This ensures the query can trigger on mount with initial values
5037
+ // For single: use watchId if it's not undefined/null, otherwise use initialId
5038
+ // For multiple: use watchIds if watchedValue is defined, otherwise use initialIds
5039
+ const currentId = watchId !== undefined && watchId !== null ? watchId : initialId;
5040
+ const currentIds = watchedValue !== undefined && watchedValue !== null && isMultiple
5041
+ ? watchIds
5042
+ : initialIds;
5254
5043
  // Query for search results
5255
5044
  const query = reactQuery.useQuery({
5256
5045
  queryKey: [`idpicker`, { column, searchText, limit, page }],
@@ -5290,33 +5079,43 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
5290
5079
  staleTime: 300000,
5291
5080
  });
5292
5081
  // Query for currently selected items (to display them properly)
5082
+ // Use currentId/currentIds in queryKey so it includes initial values and updates when watched values change
5293
5083
  const queryDefault = reactQuery.useQuery({
5294
5084
  queryKey: [
5295
5085
  `idpicker-default`,
5296
- { form: parentSchema.title, column, id: isMultiple ? watchIds : watchId },
5086
+ {
5087
+ form: parentSchema.title,
5088
+ column,
5089
+ id: isMultiple ? currentIds : currentId,
5090
+ },
5297
5091
  ],
5298
5092
  queryFn: async () => {
5093
+ // Use current values (which include initial) for the query
5094
+ const queryId = currentId;
5095
+ const queryIds = currentIds;
5299
5096
  if (customQueryFn) {
5097
+ // For customQueryFn, pass where clause to fetch specific IDs
5300
5098
  const { data, idMap } = await customQueryFn({
5301
- searching: watchIds.join(','),
5302
- limit: isMultiple ? watchIds.length : 1,
5099
+ searching: '',
5100
+ limit: isMultiple ? queryIds.length : 1,
5303
5101
  offset: 0,
5102
+ where: [{ id: column_ref, value: isMultiple ? queryIds : queryId }],
5304
5103
  });
5305
5104
  setIdMap((state) => {
5306
5105
  return { ...state, ...idMap };
5307
5106
  });
5308
5107
  return data;
5309
5108
  }
5310
- if (!watchId && (!watchIds || watchIds.length === 0)) {
5109
+ if (!queryId && (!queryIds || queryIds.length === 0)) {
5311
5110
  return { data: [] };
5312
5111
  }
5313
- const searchValue = isMultiple ? watchIds.join(',') : watchId;
5112
+ const searchValue = isMultiple ? queryIds.join(',') : queryId;
5314
5113
  const data = await getTableData({
5315
5114
  serverUrl,
5316
5115
  searching: searchValue,
5317
5116
  in_table: table,
5318
- where: [{ id: column_ref, value: isMultiple ? watchIds : watchId }],
5319
- limit: isMultiple ? watchIds.length : 1,
5117
+ where: [{ id: column_ref, value: isMultiple ? queryIds : queryId }],
5118
+ limit: isMultiple ? queryIds.length : 1,
5320
5119
  offset: 0,
5321
5120
  });
5322
5121
  const newMap = Object.fromEntries((data ?? { data: [] }).data.map((item) => {
@@ -5333,16 +5132,9 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
5333
5132
  return data;
5334
5133
  },
5335
5134
  enabled: isMultiple
5336
- ? Array.isArray(watchIds) && watchIds.length > 0
5337
- : !!watchId,
5135
+ ? Array.isArray(currentIds) && currentIds.length > 0
5136
+ : !!currentId,
5338
5137
  });
5339
- // Effect to load selected values when component mounts
5340
- React.useEffect(() => {
5341
- if (isMultiple ? watchIds.length > 0 : !!watchId) {
5342
- queryDefault.refetch();
5343
- }
5344
- // eslint-disable-next-line react-hooks/exhaustive-deps
5345
- }, []);
5346
5138
  // Effect to trigger initial data fetch when popover opens
5347
5139
  React.useEffect(() => {
5348
5140
  if (openSearchResult) {
@@ -5375,7 +5167,8 @@ const IdPicker = ({ column, schema, prefix, isMultiple = false, }) => {
5375
5167
  if (Object.keys(idMap).length <= 0) {
5376
5168
  return '';
5377
5169
  }
5378
- const record = idMap[watchId];
5170
+ // Use currentId which includes initial values
5171
+ const record = idMap[currentId];
5379
5172
  if (record === undefined) {
5380
5173
  return '';
5381
5174
  }
@@ -6367,6 +6160,9 @@ const SchemaRenderer = ({ schema, prefix, column, }) => {
6367
6160
  if (variant === 'file-picker') {
6368
6161
  return jsxRuntime.jsx(FilePicker, { schema: colSchema, prefix, column });
6369
6162
  }
6163
+ if (variant === 'media-library-browser') {
6164
+ return (jsxRuntime.jsx(FormMediaLibraryBrowser, { schema: colSchema, prefix, column }));
6165
+ }
6370
6166
  if (variant === 'date-range') {
6371
6167
  return jsxRuntime.jsx(DateRangePicker, { schema: colSchema, prefix, column });
6372
6168
  }
@@ -6758,59 +6554,62 @@ const DateTimeViewer = ({ column, schema, prefix }) => {
6758
6554
  const SchemaViewer = ({ schema, prefix, column, }) => {
6759
6555
  const colSchema = schema;
6760
6556
  const { type, variant, properties: innerProperties, foreign_key, items, format, } = schema;
6761
- if (variant === "custom-input") {
6557
+ if (variant === 'custom-input') {
6762
6558
  return jsxRuntime.jsx(CustomViewer, { schema: colSchema, prefix, column });
6763
6559
  }
6764
- if (type === "string") {
6560
+ if (type === 'string') {
6765
6561
  if ((schema.enum ?? []).length > 0) {
6766
6562
  return jsxRuntime.jsx(EnumViewer, { schema: colSchema, prefix, column });
6767
6563
  }
6768
- if (variant === "id-picker") {
6564
+ if (variant === 'id-picker') {
6769
6565
  idPickerSanityCheck(column, foreign_key);
6770
6566
  return jsxRuntime.jsx(IdViewer, { schema: colSchema, prefix, column });
6771
6567
  }
6772
- if (format === "time") {
6568
+ if (format === 'time') {
6773
6569
  return jsxRuntime.jsx(TimeViewer, { schema: colSchema, prefix, column });
6774
6570
  }
6775
- if (format === "date") {
6571
+ if (format === 'date') {
6776
6572
  return jsxRuntime.jsx(DateViewer, { schema: colSchema, prefix, column });
6777
6573
  }
6778
- if (format === "date-time") {
6574
+ if (format === 'date-time') {
6779
6575
  return jsxRuntime.jsx(DateTimeViewer, { schema: colSchema, prefix, column });
6780
6576
  }
6781
- if (variant === "text-area") {
6577
+ if (variant === 'text-area') {
6782
6578
  return jsxRuntime.jsx(TextAreaViewer, { schema: colSchema, prefix, column });
6783
6579
  }
6784
6580
  return jsxRuntime.jsx(StringViewer, { schema: colSchema, prefix, column });
6785
6581
  }
6786
- if (type === "number" || type === "integer") {
6582
+ if (type === 'number' || type === 'integer') {
6787
6583
  return jsxRuntime.jsx(NumberViewer, { schema: colSchema, prefix, column });
6788
6584
  }
6789
- if (type === "boolean") {
6585
+ if (type === 'boolean') {
6790
6586
  return jsxRuntime.jsx(BooleanViewer, { schema: colSchema, prefix, column });
6791
6587
  }
6792
- if (type === "object") {
6588
+ if (type === 'object') {
6793
6589
  if (innerProperties) {
6794
6590
  return jsxRuntime.jsx(ObjectViewer, { schema: colSchema, prefix, column });
6795
6591
  }
6796
6592
  return jsxRuntime.jsx(RecordInput, { schema: colSchema, prefix, column });
6797
6593
  }
6798
- if (type === "array") {
6799
- if (variant === "id-picker") {
6594
+ if (type === 'array') {
6595
+ if (variant === 'id-picker') {
6800
6596
  idPickerSanityCheck(column, foreign_key);
6801
6597
  return (jsxRuntime.jsx(IdViewer, { schema: colSchema, prefix, column, isMultiple: true }));
6802
6598
  }
6803
- if (variant === "tag-picker") {
6599
+ if (variant === 'tag-picker') {
6804
6600
  return jsxRuntime.jsx(TagViewer, { schema: colSchema, prefix, column });
6805
6601
  }
6806
- if (variant === "file-picker") {
6602
+ if (variant === 'file-picker') {
6603
+ return jsxRuntime.jsx(FileViewer, { schema: colSchema, prefix, column });
6604
+ }
6605
+ if (variant === 'media-library-browser') {
6807
6606
  return jsxRuntime.jsx(FileViewer, { schema: colSchema, prefix, column });
6808
6607
  }
6809
- if (variant === "enum-picker") {
6608
+ if (variant === 'enum-picker') {
6810
6609
  const { items } = schema;
6811
6610
  const { enum: enumItems } = items;
6812
6611
  const enumSchema = {
6813
- type: "string",
6612
+ type: 'string',
6814
6613
  enum: enumItems,
6815
6614
  };
6816
6615
  return (jsxRuntime.jsx(EnumViewer, { isMultiple: true, schema: enumSchema, prefix, column }));
@@ -6820,7 +6619,7 @@ const SchemaViewer = ({ schema, prefix, column, }) => {
6820
6619
  }
6821
6620
  return jsxRuntime.jsx(react.Text, { children: `array ${column}` });
6822
6621
  }
6823
- if (type === "null") {
6622
+ if (type === 'null') {
6824
6623
  return jsxRuntime.jsx(react.Text, { children: `null ${column}` });
6825
6624
  }
6826
6625
  return jsxRuntime.jsx(react.Text, { children: "missing type" });
@@ -7214,6 +7013,526 @@ const getMultiDates = ({ selected, selectedDate, selectedDates, selectable, }) =
7214
7013
  }
7215
7014
  };
7216
7015
 
7016
+ const TableDataDisplay = ({ colorPalette, emptyComponent, }) => {
7017
+ const { columns, translate, data } = useDataTableContext();
7018
+ const columnsMap = Object.fromEntries(columns.map((def) => {
7019
+ const { accessorKey, id } = def;
7020
+ if (accessorKey) {
7021
+ return [accessorKey, def];
7022
+ }
7023
+ return [id, def];
7024
+ }));
7025
+ const columnHeaders = Object.keys(columnsMap);
7026
+ const totalWidths = columns
7027
+ .map(({ size }) => {
7028
+ if (!!size === false) {
7029
+ return 0;
7030
+ }
7031
+ if (typeof size === "number") {
7032
+ return size;
7033
+ }
7034
+ return 0;
7035
+ })
7036
+ .reduce((previous, current) => previous + current, 0);
7037
+ const columnWidths = columns
7038
+ .map(({ size }) => {
7039
+ if (!!size === false) {
7040
+ return "1fr";
7041
+ }
7042
+ return `minmax(${size}px, ${(size / totalWidths) * 100}%)`;
7043
+ })
7044
+ .join(" ");
7045
+ console.log({ columnWidths }, "hadfg");
7046
+ const cellProps = {
7047
+ flex: "1 0 0%",
7048
+ overflow: "auto",
7049
+ paddingX: "2",
7050
+ py: "1",
7051
+ color: { base: "colorPalette.900", _dark: "colorPalette.100" },
7052
+ bgColor: { base: "colorPalette.50", _dark: "colorPalette.950" },
7053
+ borderBottomColor: { base: "colorPalette.200", _dark: "colorPalette.800" },
7054
+ borderBottomWidth: "1px",
7055
+ ...{ colorPalette },
7056
+ };
7057
+ if (data.length <= 0) {
7058
+ return jsxRuntime.jsx(jsxRuntime.Fragment, { children: emptyComponent });
7059
+ }
7060
+ 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) => {
7061
+ return (jsxRuntime.jsx(react.Box, { flex: "1 0 0%", paddingX: "2", py: "1", overflow: "auto", textOverflow: "ellipsis", children: translate.t(`column_header.${header}`) }));
7062
+ }) }), data.map((record) => {
7063
+ return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: columnHeaders.map((header) => {
7064
+ const { cell } = columnsMap[header];
7065
+ const value = record[header];
7066
+ if (!!record === false) {
7067
+ return (jsxRuntime.jsx(react.Box, { ...cellProps, children: translate.t(`column_cell.placeholder`) }));
7068
+ }
7069
+ if (cell) {
7070
+ return (jsxRuntime.jsx(react.Box, { ...cellProps, children: cell({ row: { original: record } }) }));
7071
+ }
7072
+ if (typeof value === "object") {
7073
+ return (jsxRuntime.jsx(react.Box, { ...cellProps, children: jsxRuntime.jsx(RecordDisplay, { object: value }) }));
7074
+ }
7075
+ return jsxRuntime.jsx(react.Box, { ...cellProps, children: value });
7076
+ }) }));
7077
+ })] }));
7078
+ };
7079
+
7080
+ const TableBodySkeleton = ({ showSelector = false, canResize = true, }) => {
7081
+ 'use no memo';
7082
+ const { table } = useDataTableContext();
7083
+ const SELECTION_BOX_WIDTH = 20;
7084
+ const [hoveredRow, setHoveredRow] = React.useState(-1);
7085
+ const handleRowHover = (index) => {
7086
+ setHoveredRow(index);
7087
+ };
7088
+ const getTdProps = (column) => {
7089
+ const tdProps = column.getIsPinned()
7090
+ ? {
7091
+ left: showSelector
7092
+ ? `${column.getStart('left') + SELECTION_BOX_WIDTH + table.getDensityValue() * 2}px`
7093
+ : `${column.getStart('left')}px`,
7094
+ position: 'relative',
7095
+ }
7096
+ : {};
7097
+ return tdProps;
7098
+ };
7099
+ const getTrProps = ({ hoveredRow, index, }) => {
7100
+ if (hoveredRow === -1) {
7101
+ return {};
7102
+ }
7103
+ if (hoveredRow === index) {
7104
+ return {
7105
+ opacity: '1',
7106
+ };
7107
+ }
7108
+ return {
7109
+ opacity: '0.8',
7110
+ };
7111
+ };
7112
+ // Get the number of skeleton rows based on current pageSize
7113
+ const pageSize = table.getState().pagination.pageSize;
7114
+ const visibleColumns = table.getVisibleLeafColumns();
7115
+ return (jsxRuntime.jsx(react.Table.Body, { children: Array.from({ length: pageSize }).map((_, rowIndex) => {
7116
+ return (jsxRuntime.jsxs(react.Table.Row, { display: 'flex', zIndex: 1, onMouseEnter: () => handleRowHover(rowIndex), onMouseLeave: () => handleRowHover(-1), ...getTrProps({ hoveredRow, index: rowIndex }), children: [showSelector && jsxRuntime.jsx(TableRowSelectorSkeleton, {}), visibleColumns.map((column, colIndex) => {
7117
+ return (jsxRuntime.jsx(react.Table.Cell, { padding: `${table.getDensityValue()}px`,
7118
+ // styling resize and pinning start
7119
+ flex: `${canResize ? '0' : '1'} 0 ${column.getSize()}px`,
7120
+ // this is to avoid the cell from being too wide
7121
+ minWidth: `0`, color: {
7122
+ base: 'colorPalette.900',
7123
+ _dark: 'colorPalette.100',
7124
+ },
7125
+ bg: { base: 'colorPalette.50', _dark: 'colorPalette.950' }, ...getTdProps(column), children: jsxRuntime.jsx(react.Skeleton, { height: "20px", width: "80%" }) }, `chakra-table-skeleton-cell-${rowIndex}-${colIndex}`));
7126
+ })] }, `chakra-table-skeleton-row-${rowIndex}`));
7127
+ }) }));
7128
+ };
7129
+ const TableRowSelectorSkeleton = () => {
7130
+ const { table } = useDataTableContext();
7131
+ const SELECTION_BOX_WIDTH = 20;
7132
+ return (jsxRuntime.jsx(react.Table.Cell, { padding: `${table.getDensityValue()}px`, display: 'grid', color: {
7133
+ base: 'colorPalette.900',
7134
+ _dark: 'colorPalette.100',
7135
+ },
7136
+ bg: { base: 'colorPalette.50', _dark: 'colorPalette.950' }, justifyItems: 'center', alignItems: 'center', children: jsxRuntime.jsx(react.Skeleton, { width: `${SELECTION_BOX_WIDTH}px`, height: `${SELECTION_BOX_WIDTH}px` }) }));
7137
+ };
7138
+
7139
+ const DefaultTable = ({ showFooter = false, tableProps = {}, tableHeaderProps = {}, tableBodyProps = {}, tableFooterProps = {}, controlProps = {}, variant = '', isLoading = false, }) => {
7140
+ if (variant === 'greedy') {
7141
+ const bodyComponent = isLoading ? (jsxRuntime.jsx(TableBodySkeleton, { showSelector: tableBodyProps.showSelector, canResize: false })) : (jsxRuntime.jsx(TableBody, { ...tableBodyProps, canResize: false, ...tableBodyProps }));
7142
+ return (jsxRuntime.jsx(TableControls, { ...controlProps, children: jsxRuntime.jsxs(Table, { canResize: false,
7143
+ showLoading: isLoading,
7144
+ showSelector: tableHeaderProps.showSelector ??
7145
+ tableBodyProps.showSelector ??
7146
+ false,
7147
+ ...tableProps, children: [jsxRuntime.jsx(TableHeader, { canResize: false, ...tableHeaderProps }), bodyComponent, showFooter && (jsxRuntime.jsx(TableFooter, { canResize: false, ...tableFooterProps }))] }) }));
7148
+ }
7149
+ const bodyComponent = isLoading ? (jsxRuntime.jsx(TableBodySkeleton, { showSelector: tableBodyProps.showSelector, canResize: tableBodyProps.canResize })) : (jsxRuntime.jsx(TableBody, { ...tableBodyProps }));
7150
+ return (jsxRuntime.jsx(TableControls, { ...controlProps, children: jsxRuntime.jsxs(Table, { showLoading: isLoading,
7151
+ showSelector: tableHeaderProps.showSelector ??
7152
+ tableBodyProps.showSelector ??
7153
+ false,
7154
+ ...tableProps, children: [jsxRuntime.jsx(TableHeader, { ...tableHeaderProps }), bodyComponent, showFooter && jsxRuntime.jsx(TableFooter, { ...tableFooterProps })] }) }));
7155
+ };
7156
+
7157
+ /**
7158
+ * DefaultTableServer is a wrapper around DefaultTable that automatically
7159
+ * detects server-side loading state from DataTableServerContext.
7160
+ *
7161
+ * Use this component when working with DataTableServer to automatically
7162
+ * show skeleton loading state during data fetching.
7163
+ *
7164
+ * @example
7165
+ * ```tsx
7166
+ * <DataTableServer columns={columns} {...datatableServer}>
7167
+ * <DefaultTableServer />
7168
+ * </DataTableServer>
7169
+ * ```
7170
+ */
7171
+ const DefaultTableServer = ({ isLoading: isLoadingOverride, ...props }) => {
7172
+ // Automatically detect loading state from server context
7173
+ const serverContext = useDataTableServerContext();
7174
+ const isLoading = isLoadingOverride ?? serverContext?.query?.isLoading ?? false;
7175
+ return jsxRuntime.jsx(DefaultTable, { ...props, isLoading: isLoading });
7176
+ };
7177
+
7178
+ const CellRenderer = ({ cell }) => {
7179
+ const { translate } = useDataTableContext();
7180
+ const getLabel = ({ columnId }) => {
7181
+ if (translate !== undefined) {
7182
+ return translate.t(`${columnId}`);
7183
+ }
7184
+ return snakeToLabel(columnId);
7185
+ };
7186
+ const formatValue = (value) => {
7187
+ if (typeof value === "object") {
7188
+ return JSON.stringify(value);
7189
+ }
7190
+ if (typeof value === "string") {
7191
+ return value;
7192
+ }
7193
+ if (typeof value === "number" || typeof value === "boolean") {
7194
+ return `${value}`;
7195
+ }
7196
+ if (value === undefined) {
7197
+ if (translate !== undefined) {
7198
+ return translate.t(`undefined`);
7199
+ }
7200
+ return `undefined`;
7201
+ }
7202
+ throw new Error(`value is unknown, ${typeof value}`);
7203
+ };
7204
+ const showCustomDataDisplay = cell.column.columnDef.meta?.showCustomDisplay ?? false;
7205
+ const gridColumn = cell.column.columnDef.meta?.gridColumn ?? [
7206
+ "span 12",
7207
+ "span 6",
7208
+ "span 3",
7209
+ ];
7210
+ const gridRow = cell.column.columnDef.meta?.gridRow ?? {};
7211
+ if (showCustomDataDisplay) {
7212
+ return (jsxRuntime.jsx(react.Flex, { gridColumn, gridRow, children: reactTable.flexRender(cell.column.columnDef.cell, cell.getContext()) }, cell.id));
7213
+ }
7214
+ const value = cell.getValue();
7215
+ if (typeof value === "object") {
7216
+ return (jsxRuntime.jsxs(react.Box, { gridColumn, gridRow, children: [jsxRuntime.jsx(react.Box, { children: getLabel({ columnId: cell.column.id }) }), jsxRuntime.jsx(RecordDisplay, { boxProps: {
7217
+ borderWidth: 1,
7218
+ borderRadius: 4,
7219
+ borderColor: "gray.400",
7220
+ paddingX: 4,
7221
+ paddingY: 2,
7222
+ }, object: value })] }, cell.id));
7223
+ }
7224
+ return (jsxRuntime.jsxs(react.Box, { gridColumn, gridRow, children: [jsxRuntime.jsx(react.Box, { color: "colorPalette.400", children: getLabel({ columnId: cell.column.id }) }), jsxRuntime.jsx(react.Box, { wordBreak: "break-word", textOverflow: "ellipsis", overflow: "hidden", children: `${formatValue(cell.getValue())}` })] }, cell.id));
7225
+ };
7226
+ const DataDisplay = ({ variant = "" }) => {
7227
+ const { table, translate } = useDataTableContext();
7228
+ return (jsxRuntime.jsx(react.Flex, { flexFlow: "column", gap: "1", children: table.getRowModel().rows.map((row) => {
7229
+ const rowId = row.id;
7230
+ return (jsxRuntime.jsx(react.Card.Root, { children: jsxRuntime.jsx(react.Card.Body, { display: "grid", gap: 4, padding: 4, gridTemplateColumns: "repeat(12, 1fr)", children: table.getAllColumns().map((column) => {
7231
+ const childCell = row.getAllCells().find((cell) => {
7232
+ return cell.id === `${rowId}_${column.id}`;
7233
+ });
7234
+ if (column.columns.length > 0) {
7235
+ return (jsxRuntime.jsxs(react.Card.Root, { margin: "1", gridColumn: "span 12", children: [jsxRuntime.jsx(react.Card.Header, { color: "gray.400", children: translate.t(column.id) }), jsxRuntime.jsx(react.Card.Body, { display: "grid", gap: "4", gridTemplateColumns: "repeat(12, 1fr)", children: column.columns.map((column) => {
7236
+ if (!column.getIsVisible()) {
7237
+ return jsxRuntime.jsx(jsxRuntime.Fragment, {});
7238
+ }
7239
+ const foundCell = row
7240
+ .getVisibleCells()
7241
+ .find((cell) => {
7242
+ return cell.id === `${rowId}_${column.id}`;
7243
+ });
7244
+ return jsxRuntime.jsx(CellRenderer, { cell: foundCell });
7245
+ }) })] }, `chakra-table-card-${childCell?.id}`));
7246
+ }
7247
+ return jsxRuntime.jsx(CellRenderer, { cell: childCell });
7248
+ }) }) }, `chakra-table-card-${rowId}`));
7249
+ }) }));
7250
+ };
7251
+
7252
+ // Reference: https://tanstack.com/table/latest/docs/framework/react/examples/custom-features
7253
+ // TypeScript setup for our new feature with all of the same type-safety as stock TanStack Table features
7254
+ // end of TS setup!
7255
+ // Here is all of the actual javascript code for our new feature
7256
+ const DensityFeature = {
7257
+ // define the new feature's initial state
7258
+ getInitialState: (state) => {
7259
+ return {
7260
+ density: "sm",
7261
+ ...state,
7262
+ };
7263
+ },
7264
+ // define the new feature's default options
7265
+ getDefaultOptions: (table) => {
7266
+ return {
7267
+ enableDensity: true,
7268
+ onDensityChange: reactTable.makeStateUpdater("density", table),
7269
+ };
7270
+ },
7271
+ // if you need to add a default column definition...
7272
+ // getDefaultColumnDef: <TData extends RowData>(): Partial<ColumnDef<TData>> => {
7273
+ // return { meta: {} } //use meta instead of directly adding to the columnDef to avoid typescript stuff that's hard to workaround
7274
+ // },
7275
+ // define the new feature's table instance methods
7276
+ createTable: (table) => {
7277
+ table.setDensity = (updater) => {
7278
+ const safeUpdater = (old) => {
7279
+ let newState = reactTable.functionalUpdate(updater, old);
7280
+ return newState;
7281
+ };
7282
+ return table.options.onDensityChange?.(safeUpdater);
7283
+ };
7284
+ table.toggleDensity = (value) => {
7285
+ table.setDensity((old) => {
7286
+ if (value)
7287
+ return value;
7288
+ if (old === "sm") {
7289
+ return "md";
7290
+ }
7291
+ if (old === "md") {
7292
+ return "lg";
7293
+ }
7294
+ return "sm";
7295
+ });
7296
+ };
7297
+ table.getDensityValue = (value) => {
7298
+ let density;
7299
+ if (value) {
7300
+ density = value;
7301
+ }
7302
+ else {
7303
+ density = table.getState().density;
7304
+ }
7305
+ if (density === "sm") {
7306
+ return 8;
7307
+ }
7308
+ if (density === "md") {
7309
+ return 16;
7310
+ }
7311
+ return 32;
7312
+ };
7313
+ },
7314
+ // if you need to add row instance APIs...
7315
+ // createRow: <TData extends RowData>(row, table): void => {},
7316
+ // if you need to add cell instance APIs...
7317
+ // createCell: <TData extends RowData>(cell, column, row, table): void => {},
7318
+ // if you need to add column instance APIs...
7319
+ // createColumn: <TData extends RowData>(column, table): void => {},
7320
+ // if you need to add header instance APIs...
7321
+ // createHeader: <TData extends RowData>(header, table): void => {},
7322
+ };
7323
+ //end of custom feature code
7324
+
7325
+ // Define a custom fuzzy filter function that will apply ranking info to rows (using match-sorter utils)
7326
+ const fuzzyFilter = (row, columnId, value, addMeta) => {
7327
+ // Rank the item
7328
+ const itemRank = matchSorterUtils.rankItem(row.getValue(columnId), value);
7329
+ // Store the itemRank info
7330
+ addMeta({
7331
+ itemRank,
7332
+ });
7333
+ // Return if the item should be filtered in/out
7334
+ return itemRank.passed;
7335
+ };
7336
+ /**
7337
+ * DataTable will create a context to hold all values to
7338
+ * help the render of the DataTable in serverside
7339
+ *
7340
+ *
7341
+ * The query is required to be a GET request that can receive
7342
+ * specified params and return a specified response
7343
+ *
7344
+ * @link https://tanstack.com/table/latest/docs/guide/column-defs
7345
+ */
7346
+ function DataTable({ columns, data, enableRowSelection = true, enableMultiRowSelection = true, enableSubRowSelection = true, columnOrder, columnFilters, columnVisibility, density, globalFilter, pagination, sorting, rowSelection, setPagination, setSorting, setColumnFilters, setRowSelection, setGlobalFilter, setColumnOrder, setDensity, setColumnVisibility, translate, children, tableLabel = {
7347
+ view: 'View',
7348
+ edit: 'Edit',
7349
+ filterButtonText: 'Filter',
7350
+ filterTitle: 'Filter',
7351
+ filterReset: 'Reset',
7352
+ filterClose: 'Close',
7353
+ reloadTooltip: 'Reload',
7354
+ reloadButtonText: 'Reload',
7355
+ resetSelection: 'Reset Selection',
7356
+ resetSorting: 'Reset Sorting',
7357
+ rowCountText: 'Row Count',
7358
+ hasErrorText: 'Has Error',
7359
+ globalFilterPlaceholder: 'Search',
7360
+ trueLabel: 'True',
7361
+ falseLabel: 'False',
7362
+ }, }) {
7363
+ const table = reactTable.useReactTable({
7364
+ _features: [DensityFeature],
7365
+ data: data,
7366
+ rowCount: data.length,
7367
+ columns: columns,
7368
+ getCoreRowModel: reactTable.getCoreRowModel(),
7369
+ getFilteredRowModel: reactTable.getFilteredRowModel(),
7370
+ getSortedRowModel: reactTable.getSortedRowModel(),
7371
+ getPaginationRowModel: reactTable.getPaginationRowModel(),
7372
+ defaultColumn: {
7373
+ size: 150, //starting column size
7374
+ minSize: 10, //enforced during column resizing
7375
+ maxSize: 10000, //enforced during column resizing
7376
+ },
7377
+ enableRowSelection: enableRowSelection,
7378
+ enableMultiRowSelection: enableMultiRowSelection,
7379
+ enableSubRowSelection: enableSubRowSelection,
7380
+ columnResizeMode: 'onChange',
7381
+ // global filter start
7382
+ filterFns: {
7383
+ fuzzy: fuzzyFilter,
7384
+ },
7385
+ globalFilterFn: 'fuzzy',
7386
+ state: {
7387
+ pagination,
7388
+ sorting,
7389
+ columnFilters,
7390
+ rowSelection,
7391
+ columnOrder,
7392
+ globalFilter,
7393
+ density,
7394
+ columnVisibility,
7395
+ },
7396
+ onPaginationChange: setPagination,
7397
+ onSortingChange: setSorting,
7398
+ onColumnFiltersChange: setColumnFilters,
7399
+ onRowSelectionChange: setRowSelection,
7400
+ onColumnOrderChange: (state) => {
7401
+ setColumnOrder(state);
7402
+ },
7403
+ onGlobalFilterChange: (state) => {
7404
+ setGlobalFilter(state);
7405
+ },
7406
+ onDensityChange: setDensity,
7407
+ onColumnVisibilityChange: setColumnVisibility,
7408
+ });
7409
+ return (jsxRuntime.jsx(DataTableContext.Provider, { value: {
7410
+ table: table,
7411
+ globalFilter,
7412
+ setGlobalFilter,
7413
+ type: 'client',
7414
+ translate,
7415
+ columns: columns,
7416
+ sorting,
7417
+ setSorting,
7418
+ columnFilters,
7419
+ setColumnFilters,
7420
+ pagination,
7421
+ setPagination,
7422
+ rowSelection,
7423
+ setRowSelection,
7424
+ columnOrder,
7425
+ setColumnOrder,
7426
+ density,
7427
+ setDensity,
7428
+ columnVisibility,
7429
+ setColumnVisibility,
7430
+ data,
7431
+ tableLabel,
7432
+ }, children: children }));
7433
+ }
7434
+
7435
+ /**
7436
+ * DataTableServer will create a context to hold all values to
7437
+ * help the render of the DataTable in serverside
7438
+ *
7439
+ * The query is required to be a GET request that can receive
7440
+ * specified params and return a specified response
7441
+ *
7442
+ * The `useDataTableServer` can help to create the specified request and response
7443
+ *
7444
+ * @link https://tanstack.com/table/latest/docs/guide/column-defs
7445
+ */
7446
+ function DataTableServer({ columns, enableRowSelection = true, enableMultiRowSelection = true, enableSubRowSelection = true, columnOrder, columnFilters, columnVisibility, density, globalFilter, pagination, sorting, rowSelection, setPagination, setSorting, setColumnFilters, setRowSelection, setGlobalFilter, setColumnOrder, setDensity, setColumnVisibility, query, url, translate, children, tableLabel = {
7447
+ view: "View",
7448
+ edit: "Edit",
7449
+ filterButtonText: "Filter",
7450
+ filterTitle: "Filter",
7451
+ filterReset: "Reset",
7452
+ filterClose: "Close",
7453
+ reloadTooltip: "Reload",
7454
+ reloadButtonText: "Reload",
7455
+ resetSelection: "Reset Selection",
7456
+ resetSorting: "Reset Sorting",
7457
+ rowCountText: "Row Count",
7458
+ hasErrorText: "Has Error",
7459
+ globalFilterPlaceholder: "Search",
7460
+ trueLabel: "True",
7461
+ falseLabel: "False",
7462
+ }, }) {
7463
+ const table = reactTable.useReactTable({
7464
+ _features: [DensityFeature],
7465
+ data: (query.data?.data ?? []),
7466
+ rowCount: query.data?.count ?? 0,
7467
+ columns: columns,
7468
+ getCoreRowModel: reactTable.getCoreRowModel(),
7469
+ manualPagination: true,
7470
+ manualSorting: true,
7471
+ columnResizeMode: "onChange",
7472
+ defaultColumn: {
7473
+ size: 150, //starting column size
7474
+ minSize: 10, //enforced during column resizing
7475
+ maxSize: 10000, //enforced during column resizing
7476
+ },
7477
+ enableRowSelection: enableRowSelection,
7478
+ enableMultiRowSelection: enableMultiRowSelection,
7479
+ enableSubRowSelection: enableSubRowSelection,
7480
+ state: {
7481
+ pagination,
7482
+ sorting,
7483
+ columnFilters,
7484
+ rowSelection,
7485
+ columnOrder,
7486
+ globalFilter,
7487
+ density,
7488
+ columnVisibility,
7489
+ },
7490
+ onPaginationChange: setPagination,
7491
+ onSortingChange: setSorting,
7492
+ onColumnFiltersChange: setColumnFilters,
7493
+ onRowSelectionChange: setRowSelection,
7494
+ onColumnOrderChange: (state) => {
7495
+ setColumnOrder(state);
7496
+ },
7497
+ onGlobalFilterChange: (state) => {
7498
+ setGlobalFilter(state);
7499
+ },
7500
+ onDensityChange: setDensity,
7501
+ onColumnVisibilityChange: setColumnVisibility,
7502
+ // for tanstack-table ts bug start
7503
+ filterFns: {
7504
+ fuzzy: () => {
7505
+ return false;
7506
+ },
7507
+ },
7508
+ // for tanstack-table ts bug end
7509
+ });
7510
+ return (jsxRuntime.jsx(DataTableContext.Provider, { value: {
7511
+ table: table,
7512
+ globalFilter,
7513
+ setGlobalFilter,
7514
+ type: "server",
7515
+ translate,
7516
+ columns: columns,
7517
+ sorting,
7518
+ setSorting,
7519
+ columnFilters,
7520
+ setColumnFilters,
7521
+ pagination,
7522
+ setPagination,
7523
+ rowSelection,
7524
+ setRowSelection,
7525
+ columnOrder,
7526
+ setColumnOrder,
7527
+ density,
7528
+ setDensity,
7529
+ columnVisibility,
7530
+ setColumnVisibility,
7531
+ data: query.data?.data ?? [],
7532
+ tableLabel,
7533
+ }, children: jsxRuntime.jsx(DataTableServerContext.Provider, { value: { url, query }, children: children }) }));
7534
+ }
7535
+
7217
7536
  exports.CardHeader = CardHeader;
7218
7537
  exports.DataDisplay = DataDisplay;
7219
7538
  exports.DataTable = DataTable;
@@ -7224,13 +7543,14 @@ exports.DefaultTable = DefaultTable;
7224
7543
  exports.DefaultTableServer = DefaultTableServer;
7225
7544
  exports.DensityToggleButton = DensityToggleButton;
7226
7545
  exports.EditSortingButton = EditSortingButton;
7227
- exports.EmptyState = EmptyState$1;
7546
+ exports.EmptyState = EmptyState;
7228
7547
  exports.ErrorAlert = ErrorAlert;
7229
7548
  exports.FilterDialog = FilterDialog;
7230
7549
  exports.FormBody = FormBody;
7231
7550
  exports.FormRoot = FormRoot;
7232
7551
  exports.FormTitle = FormTitle;
7233
7552
  exports.GlobalFilter = GlobalFilter;
7553
+ exports.MediaLibraryBrowser = MediaLibraryBrowser;
7234
7554
  exports.PageSizeControl = PageSizeControl;
7235
7555
  exports.Pagination = Pagination;
7236
7556
  exports.RecordDisplay = RecordDisplay;