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