@dmsi/wedgekit-react 0.0.82 → 0.0.84

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/{chunk-6R2HCLEL.js → chunk-37TJJQL3.js} +2 -2
  2. package/dist/{chunk-B6PDZCU7.js → chunk-5GUW4DUY.js} +1 -1
  3. package/dist/{chunk-ATOEGP3V.js → chunk-CKSDMI2Q.js} +14 -7
  4. package/dist/{chunk-2DCVAATK.js → chunk-MQWWNAO3.js} +4 -4
  5. package/dist/{chunk-FOC6LTSX.js → chunk-UPBBOZM3.js} +1 -1
  6. package/dist/{chunk-SWA5WVQO.js → chunk-WNQ53SVY.js} +30 -0
  7. package/dist/components/DataGridCell.cjs +53 -43
  8. package/dist/components/DataGridCell.js +5 -5
  9. package/dist/components/Menu.cjs +17 -14
  10. package/dist/components/Menu.js +3 -3
  11. package/dist/components/MenuOption.cjs +10 -7
  12. package/dist/components/MenuOption.js +2 -2
  13. package/dist/components/Modal.cjs +18 -15
  14. package/dist/components/Modal.js +3 -3
  15. package/dist/components/NestedMenu.cjs +12 -9
  16. package/dist/components/NestedMenu.js +2 -2
  17. package/dist/components/PDFViewer.cjs +21 -18
  18. package/dist/components/PDFViewer.js +3 -3
  19. package/dist/components/ProjectBar.cjs +6 -3
  20. package/dist/components/ProjectBar.js +1 -1
  21. package/dist/components/TopBar.cjs +1 -1
  22. package/dist/components/TopBar.js +1 -1
  23. package/dist/components/{DataGrid.cjs → index.cjs} +1424 -1335
  24. package/dist/components/{DataGrid.js → index.js} +948 -883
  25. package/dist/components/useMenuSystem.cjs +20 -17
  26. package/dist/components/useMenuSystem.js +2 -2
  27. package/dist/hooks/index.cjs +34 -3
  28. package/dist/hooks/index.js +3 -1
  29. package/package.json +6 -1
  30. package/src/components/DataGrid/ColumnSelectorHeaderCell/ColumnSelectorMenuOption.tsx +32 -0
  31. package/src/components/DataGrid/ColumnSelectorHeaderCell/index.tsx +66 -0
  32. package/src/components/DataGrid/PinnedColumns.tsx +145 -0
  33. package/src/components/DataGrid/TableBody/LoadingCell.tsx +40 -0
  34. package/src/components/DataGrid/TableBody/TableBodyRow.tsx +129 -0
  35. package/src/components/DataGrid/TableBody/index.tsx +159 -0
  36. package/src/components/{DataGrid.tsx → DataGrid/index.tsx} +42 -678
  37. package/src/components/DataGrid/types.ts +86 -0
  38. package/src/components/DataGrid/utils.tsx +15 -0
  39. package/src/components/DataGridCell.tsx +37 -21
  40. package/src/components/TopBar.tsx +1 -1
  41. package/src/components/index.ts +20 -0
  42. package/src/hooks/index.ts +1 -0
  43. package/dist/chunk-AWQSSKCK.js +0 -32
  44. package/dist/components/useInfiniteScroll.cjs +0 -57
  45. package/dist/components/useInfiniteScroll.js +0 -8
  46. /package/src/{components → hooks}/useInfiniteScroll.tsx +0 -0
@@ -1,35 +1,31 @@
1
1
  "use client";
2
2
 
3
- import React, { ReactNode, useCallback, useId, useRef, useState } from "react";
4
-
5
- // TanStack Table
3
+ import { useInfiniteScroll } from "../../hooks";
4
+ import { componentGap, componentPadding } from "../../classNames";
5
+ import {
6
+ Button,
7
+ Checkbox,
8
+ DataGridCell,
9
+ DraggableCellHeader,
10
+ Icon,
11
+ Label,
12
+ Menu,
13
+ MenuOption,
14
+ Paragraph,
15
+ Select,
16
+ Subheader,
17
+ } from "..";
18
+ import React, { useCallback, useId, useState } from "react";
6
19
  import {
7
- Cell,
8
- Column,
9
- ColumnDef,
10
20
  ColumnFiltersState,
11
- FilterFn,
12
21
  flexRender,
13
22
  getCoreRowModel,
14
23
  getFilteredRowModel,
15
24
  getSortedRowModel,
16
- Header,
17
- HeaderGroup,
18
- PartialKeys,
19
- RowData,
20
- SortDirection,
21
25
  SortingState,
22
- Table,
23
- TableOptionsResolved,
24
26
  useReactTable,
25
27
  } from "@tanstack/react-table";
26
28
 
27
- import {
28
- useVirtualizer,
29
- VirtualItem,
30
- Virtualizer,
31
- } from "@tanstack/react-virtual";
32
-
33
29
  // DnD Kit
34
30
  import {
35
31
  closestCenter,
@@ -47,84 +43,18 @@ import {
47
43
  SortableContext,
48
44
  } from "@dnd-kit/sortable";
49
45
  import { restrictToHorizontalAxis } from "@dnd-kit/modifiers";
50
-
51
- // UI Components
52
- import { Button } from "./Button";
53
- import { Checkbox } from "./Checkbox";
54
- import {
55
- DataCellHeader,
56
- DataGridCell,
57
- DragAlongCell,
58
- DraggableCellHeader,
59
- } from "./DataGridCell";
60
- import { Icon } from "./Icon";
61
- import { Input } from "./Input";
62
- import { Search } from "./Search";
63
- import { Label } from "./Label";
64
- import { Menu } from "./Menu";
65
- import { MenuOption } from "./MenuOption";
66
- import { Paragraph } from "./Paragraph";
67
- import { Select } from "./Select";
68
- import { Subheader } from "./Subheader";
69
- import { Tooltip } from "./Tooltip";
70
-
71
- // Utils & Hooks
72
- import { useInfiniteScroll } from "./useInfiniteScroll";
73
- import { componentGap, componentPadding } from "../classNames";
46
+ import { DataGridProps } from "./types";
47
+ import { useVirtualizer } from "@tanstack/react-virtual";
74
48
  import clsx from "clsx";
75
- import { Row } from "@tanstack/react-table";
49
+ import { PinnedColumns } from "./PinnedColumns";
50
+ import { getSortIcon } from "./utils";
51
+ import { TableBody } from "./TableBody";
52
+ import { ColumnSelectorHeaderCell } from "./ColumnSelectorHeaderCell";
76
53
 
77
54
  // Constants
78
55
  const PAGE_SIZE_OPTIONS = [5, 10, 15, 20, 25, 30, 35];
79
56
  const NO_RESULTS_HEIGHT = "h-[120px]";
80
57
 
81
- function adaptTableStateSetter<T>(
82
- setter: React.Dispatch<React.SetStateAction<T>>,
83
- ) {
84
- return (valueOrFn: T | ((prev: T) => T)) => {
85
- setter((prev) =>
86
- typeof valueOrFn === "function"
87
- ? (valueOrFn as (prev: T) => T)(prev)
88
- : valueOrFn,
89
- );
90
- };
91
- }
92
-
93
- // Types
94
- export interface DataGridPagination {
95
- pageIndex: number;
96
- pageSize: number;
97
- total: number;
98
- onPageChange: (pageIndex: number) => void;
99
- onPageSizeChange?: (pageSize: number) => void;
100
- }
101
-
102
- export interface DataGridProps<T extends Record<string, unknown>> {
103
- id?: string;
104
- data: T[];
105
- columns: ColumnDef<T>[];
106
- status?: string;
107
- locked?: boolean;
108
- isLoadingMore?: boolean;
109
- onLoadMore?: () => void;
110
- hasMore?: boolean;
111
- pagination?: DataGridPagination;
112
- showFilterRow?: boolean;
113
- sorting?: SortingState;
114
- onSortingChange?: (state: SortingState) => void;
115
- columnFilters?: ColumnFiltersState;
116
- onColumnFiltersChange?: (filters: ColumnFiltersState) => void;
117
- rowSelection?: Record<string, boolean>;
118
- onRowSelectionChange?: (selection: Record<string, boolean>) => void;
119
- filteredSortedData?: T[];
120
- totalRowCount: number;
121
- hideStatusBar?: boolean;
122
- centerHeader?: boolean;
123
- enableColumnSelector?: boolean;
124
- predeterminedLeftPins?: string[];
125
- predeterminedRightPins?: string[];
126
- }
127
-
128
58
  export function DataGrid<T extends Record<string, unknown>>({
129
59
  id,
130
60
  data,
@@ -148,6 +78,7 @@ export function DataGrid<T extends Record<string, unknown>>({
148
78
  enableColumnSelector,
149
79
  predeterminedLeftPins = [],
150
80
  predeterminedRightPins = [],
81
+ useMenuDefaultMinWidth,
151
82
  }: DataGridProps<T>) {
152
83
  const [columnOrder, setColumnOrder] = useState<string[]>(() =>
153
84
  columns.map((c) => c.id!),
@@ -439,6 +370,10 @@ export function DataGrid<T extends Record<string, unknown>>({
439
370
  const customHeaderWidth =
440
371
  header.column.columnDef.meta?.headerWidth;
441
372
 
373
+ const cellValue = table
374
+ .getRowModel()
375
+ .rows[0]?.getValue(header.column.id);
376
+
442
377
  return (
443
378
  <DraggableCellHeader
444
379
  key={header.id}
@@ -452,7 +387,11 @@ export function DataGrid<T extends Record<string, unknown>>({
452
387
  ? "cursor-pointer"
453
388
  : "cursor-grab",
454
389
  "group",
390
+ {
391
+ "justify-end": typeof cellValue === "number",
392
+ },
455
393
  )}
394
+ useMenuDefaultMinWidth={useMenuDefaultMinWidth}
456
395
  >
457
396
  <Subheader tall>
458
397
  {header.column.columnDef.header}
@@ -664,594 +603,19 @@ export function DataGrid<T extends Record<string, unknown>>({
664
603
  </DndContext>
665
604
  );
666
605
  }
667
-
668
606
  DataGrid.displayName = "DataGrid";
669
607
 
670
- interface TableBodyProps<TData extends RowData> {
671
- id?: string;
672
- columnVirtualizer?: Virtualizer<HTMLDivElement, HTMLTableCellElement>;
673
- table: Table<TData>;
674
- tableContainerRef: React.RefObject<HTMLDivElement | null>;
675
- virtualPaddingLeft?: number | undefined;
676
- virtualPaddingRight?: number | undefined;
677
- pagination: DataGridPagination | undefined;
678
- isLoadingMore: boolean;
679
- hasMore: boolean;
680
- showFilterRow: boolean;
681
- enableColumnSelector?: boolean;
682
- locked?: boolean;
683
- pinDirection?: "left" | "right";
684
- }
685
-
686
- // Helpers
687
-
688
- function TableBody<T>({
689
- id,
690
- columnVirtualizer,
691
- table,
692
- tableContainerRef,
693
- virtualPaddingLeft,
694
- virtualPaddingRight,
695
- pagination,
696
- isLoadingMore,
697
- hasMore,
698
- showFilterRow,
699
- enableColumnSelector = false,
700
- locked,
701
- pinDirection,
702
- }: TableBodyProps<T>) {
703
- const { rows } = table.getRowModel();
704
-
705
- const rowVirtualizer = useVirtualizer<HTMLDivElement, HTMLTableRowElement>({
706
- count: rows.length,
707
- estimateSize: () => 40,
708
- getScrollElement: () => tableContainerRef.current,
709
- overscan: 8,
710
- });
711
-
712
- const virtualRows = rowVirtualizer.getVirtualItems();
713
- const CellElement = locked ? DataGridCell : DragAlongCell;
714
-
715
- let headerGroups: HeaderGroup<T>[];
716
- if (pinDirection === "left") {
717
- headerGroups = table.getLeftHeaderGroups();
718
- } else if (pinDirection === "right") {
719
- headerGroups = table.getRightHeaderGroups();
720
- } else {
721
- headerGroups = table.getCenterHeaderGroups();
722
- }
723
-
724
- return (
725
- <tbody
726
- className={clsx(locked ? "shadow-16" : "")}
727
- style={{
728
- display: "grid",
729
- height: `${
730
- showFilterRow
731
- ? rowVirtualizer.getTotalSize() + 40
732
- : rowVirtualizer.getTotalSize()
733
- }px`, // tells scrollbar how big the table is
734
- position: "relative", // needed for absolute positioning of rows
735
- }}
736
- >
737
- {showFilterRow && (
738
- <tr
739
- style={{
740
- display: "flex",
741
- position: "sticky",
742
- top: "40px",
743
- width: "100%",
744
- height: "40px",
745
- zIndex: 10,
746
- }}
747
- className="even:bg-background-grouped-primary-normal odd:bg-background-grouped-secondary-normal"
748
- >
749
- {headerGroups.flatMap((x) =>
750
- x.headers.map((header) => (
751
- <CellElement
752
- id={id ? `${id}-filter-cell-${header.id}` : undefined}
753
- noPadding
754
- key={header.id}
755
- cell={header}
756
- width={
757
- header.column.columnDef.meta?.headerWidth ||
758
- (locked ? `${header.column.getSize()}px` : "")
759
- }
760
- >
761
- {header.column.getCanFilter() &&
762
- (header.column.columnDef.meta?.filterRowCell?.({
763
- header,
764
- table,
765
- }) ?? (
766
- <Search
767
- id={id ? `${id}-filter-search-${header.id}` : undefined}
768
- removeRoundness
769
- onChange={(e) =>
770
- header.column.setFilterValue(e.target.value)
771
- }
772
- value={(header.column.getFilterValue() ?? "") as string}
773
- placeholder=""
774
- removeSearchIcon
775
- />
776
- ))}
777
- </CellElement>
778
- )),
779
- )}
780
- </tr>
781
- )}
782
-
783
- {virtualRows.map((virtualRow) => {
784
- const row = rows[virtualRow.index] as Row<T>;
785
-
786
- return (
787
- <TableBodyRow
788
- id={id}
789
- columnVirtualizer={columnVirtualizer}
790
- key={row.id}
791
- row={row}
792
- rowVirtualizer={rowVirtualizer}
793
- virtualPaddingLeft={virtualPaddingLeft}
794
- virtualPaddingRight={virtualPaddingRight}
795
- virtualRow={virtualRow}
796
- showFilterRow={showFilterRow}
797
- enableColumnSelector={enableColumnSelector}
798
- locked={locked}
799
- pinDirection={pinDirection}
800
- />
801
- );
802
- })}
803
-
804
- {!pagination && isLoadingMore && hasMore && (
805
- <tr
806
- style={{
807
- display: "flex",
808
- position: "absolute",
809
- width: "100%",
810
- transform: `translateY(${
811
- virtualRows[virtualRows.length - 1].start + 40
812
- }px)`,
813
- }}
814
- className="odd:bg-background-grouped-primary-normal even:bg-background-grouped-secondary-normal"
815
- >
816
- {table.getAllLeafColumns().map((column) => (
817
- <LoadingCell id={id} key={column.id} column={column.columnDef} />
818
- ))}
819
- </tr>
820
- )}
821
- </tbody>
822
- );
823
- }
824
-
825
- interface TableBodyRowProps<T> {
826
- id?: string;
827
- columnVirtualizer?: Virtualizer<HTMLDivElement, HTMLTableCellElement>;
828
- row: Row<T>;
829
- rowVirtualizer: Virtualizer<HTMLDivElement, HTMLTableRowElement>;
830
- virtualPaddingLeft?: number | undefined;
831
- virtualPaddingRight?: number | undefined;
832
- virtualRow: VirtualItem;
833
- showFilterRow: boolean;
834
- enableColumnSelector?: boolean;
835
- locked?: boolean;
836
- pinDirection?: "left" | "right";
837
- }
838
-
839
- function TableBodyRow<T>({
840
- id,
841
- columnVirtualizer,
842
- row,
843
- // rowVirtualizer,
844
- virtualPaddingLeft,
845
- virtualPaddingRight,
846
- virtualRow,
847
- showFilterRow,
848
- enableColumnSelector = false,
849
- locked,
850
- pinDirection,
851
- }: TableBodyRowProps<T>) {
852
- let visibleCells: Cell<T, unknown>[];
853
-
854
- if (locked) {
855
- visibleCells =
856
- pinDirection === "left"
857
- ? row.getLeftVisibleCells()
858
- : row.getRightVisibleCells();
859
- } else {
860
- visibleCells = row.getCenterVisibleCells();
861
- }
862
-
863
- const virtualColumns = columnVirtualizer?.getVirtualItems() ?? [];
864
- const columns = locked ? visibleCells : virtualColumns;
865
-
866
- const isError =
867
- typeof row.original === "object" &&
868
- row.original !== null &&
869
- "rowState" in row.original &&
870
- row.original.rowState === "error";
871
-
872
- const CellElement = locked ? DataGridCell : DragAlongCell;
873
-
874
- return (
875
- <tr
876
- key={row.id}
877
- className={clsx(
878
- "transition-colors hover:bg-background-action-secondary-hover",
879
- row.getIsSelected() && "!bg-background-action-secondary-hover",
880
- isError && "!bg-background-action-critical-secondary-hover",
881
- showFilterRow
882
- ? "even:bg-background-grouped-primary-normal odd:bg-background-grouped-secondary-normal"
883
- : "odd:bg-background-grouped-primary-normal even:bg-background-grouped-secondary-normal",
884
- )}
885
- style={{
886
- display: "flex",
887
- position: "absolute",
888
- transform: `translateY(${
889
- showFilterRow ? virtualRow.start + 40 : virtualRow.start
890
- }px)`,
891
- width: "100%",
892
- }}
893
- >
894
- {!locked && virtualPaddingLeft ? (
895
- // fake empty column to the left for virtualization scroll padding
896
- <td style={{ display: "flex", width: virtualPaddingLeft }} />
897
- ) : null}
898
-
899
- {columns.map((column) => {
900
- const cell = locked
901
- ? (column as Cell<T, unknown>)
902
- : visibleCells[(column as VirtualItem).index];
903
-
904
- if (!cell) {
905
- return;
906
- }
907
-
908
- return cell.column.columnDef.meta?.useCustomRenderer ? (
909
- <React.Fragment key={cell.id}>
910
- {flexRender(cell.column.columnDef.cell, cell.getContext())}
911
- </React.Fragment>
912
- ) : (
913
- <CellElement
914
- key={cell.id}
915
- id={id ? `${id}-cell-${cell.id}` : undefined}
916
- cell={cell}
917
- >
918
- <Tooltip
919
- id={id ? `${id}-tooltip-${cell.id}` : undefined}
920
- showOnTruncation
921
- message={cell.getValue() as string}
922
- position="bottom"
923
- >
924
- <Paragraph addOverflow tall>
925
- {cell.getValue() as ReactNode | string}
926
- </Paragraph>
927
- </Tooltip>
928
- </CellElement>
929
- );
930
- })}
931
-
932
- {!locked && virtualPaddingRight ? (
933
- // fake empty column to the right for virtualization scroll padding
934
- <td style={{ display: "flex", width: virtualPaddingRight }} />
935
- ) : null}
936
-
937
- {enableColumnSelector && !locked && (
938
- <td className="p-2" style={{ width: "48.8px" }}></td>
939
- )}
940
- </tr>
941
- );
942
- }
943
-
944
- interface PinnedColumnsProps<TData extends RowData> {
945
- pinDirection: "left" | "right";
946
- table: Table<TData>;
947
- tableContainerRef: React.RefObject<HTMLDivElement | null>;
948
- pagination: DataGridPagination | undefined;
949
- isLoadingMore: boolean;
950
- hasMore: boolean;
951
- showFilterRow: boolean;
952
- enableColumnSelector?: boolean;
953
- centerHeader?: boolean;
954
- allSelectedAcrossPages?: boolean;
955
- someSelectedAcrossPages?: boolean;
956
- toggleSelectAllAcrossPages?: () => void;
957
- }
958
-
959
- function PinnedColumns<TData>({
960
- pinDirection = "left",
961
- table,
962
- centerHeader,
963
- allSelectedAcrossPages,
964
- someSelectedAcrossPages,
965
- toggleSelectAllAcrossPages,
966
- ...props
967
- }: PinnedColumnsProps<TData>) {
968
- const headerGroups =
969
- pinDirection === "left"
970
- ? table.getLeftHeaderGroups()
971
- : table.getRightHeaderGroups();
972
-
973
- return (
974
- headerGroups[0]?.headers.length > 0 && (
975
- <table
976
- className={clsx(
977
- "flex flex-col min-h-min sticky z-20 bg-background-grouped-primary-normal",
978
- pinDirection === "left" ? "left-0" : "right-0",
979
- )}
980
- >
981
- <thead className="sticky top-0 z-20 grid">
982
- {headerGroups.map((headerGroup) => {
983
- return (
984
- <tr key={headerGroup.id} className="flex w-full">
985
- {headerGroup.headers.map((header) => {
986
- if (!header) {
987
- return;
988
- }
989
-
990
- if (typeof header.column.columnDef.header === "string") {
991
- const customHeaderWidth =
992
- header.column.columnDef.meta?.headerWidth;
993
-
994
- return (
995
- <DataCellHeader
996
- locked
997
- key={header.id}
998
- header={header}
999
- center={centerHeader}
1000
- width={customHeaderWidth}
1001
- className={clsx(
1002
- header.column.getCanSort()
1003
- ? "cursor-pointer"
1004
- : "cursor-grab",
1005
- "group",
1006
- )}
1007
- >
1008
- <Subheader tall>
1009
- {header.column.columnDef.header}
1010
- </Subheader>
1011
-
1012
- {getSortIcon(header.column.getIsSorted())}
1013
-
1014
- {!header.column.getIsSorted() &&
1015
- header.column.getCanSort() &&
1016
- getSortIcon(
1017
- header.column.getNextSortingOrder(),
1018
- true,
1019
- )}
1020
-
1021
- {header.column.getSortIndex() !== -1 &&
1022
- table.getState().sorting.length > 1 && (
1023
- <Subheader tall>
1024
- {header.column.getSortIndex() + 1}
1025
- </Subheader>
1026
- )}
1027
-
1028
- {!header.column.columnDef.meta?.locked && (
1029
- <div
1030
- onDoubleClick={(e) => {
1031
- e.stopPropagation();
1032
- header.column.resetSize();
1033
- }}
1034
- onMouseDown={(e) => {
1035
- e.stopPropagation();
1036
- header.getResizeHandler()(e);
1037
- }}
1038
- onTouchStart={(e) => {
1039
- e.stopPropagation();
1040
- header.getResizeHandler()(e);
1041
- }}
1042
- className="absolute right-0 inset-y-0 w-px bg-black cursor-col-resize"
1043
- />
1044
- )}
1045
- </DataCellHeader>
1046
- );
1047
- }
1048
- return (
1049
- <React.Fragment key={header.id}>
1050
- {header.column.columnDef.meta?.checkbox ? (
1051
- <DataGridCell type="header" component="checkbox" locked>
1052
- <Checkbox
1053
- checked={allSelectedAcrossPages}
1054
- indeterminate={someSelectedAcrossPages}
1055
- onChange={toggleSelectAllAcrossPages}
1056
- />
1057
- </DataGridCell>
1058
- ) : (
1059
- flexRender(
1060
- header.column.columnDef.header,
1061
- header.getContext(),
1062
- )
1063
- )}
1064
- </React.Fragment>
1065
- );
1066
- })}
1067
- </tr>
1068
- );
1069
- })}
1070
- </thead>
1071
-
1072
- <TableBody
1073
- {...props}
1074
- table={table}
1075
- locked={true}
1076
- pinDirection={pinDirection}
1077
- />
1078
- </table>
1079
- )
1080
- );
1081
- }
1082
-
1083
- const LoadingCell = <T extends RowData>({
1084
- id,
1085
- column,
1086
- }: {
1087
- id?: string;
1088
- column: ColumnDef<T>;
1089
- }) => {
1090
- const key = `loading-${column.id}`;
1091
- if (column.cell === "checkbox") {
1092
- return (
1093
- <DataGridCell id={id ? `${id}-${key}` : undefined} key={key}>
1094
- <Checkbox id={id ? `${id}-${key}-checkbox` : undefined} disabled />
1095
- </DataGridCell>
1096
- );
1097
- }
1098
- if (column.cell === "input") {
1099
- return (
1100
- <DataGridCell
1101
- id={id ? `${id}-${key}` : undefined}
1102
- key={key}
1103
- component="input"
1104
- >
1105
- <Input
1106
- id={id ? `${id}-${key}-input` : undefined}
1107
- align="left"
1108
- disabled
1109
- wrapperClassName="!rounded-none !border-0"
1110
- />
1111
- </DataGridCell>
608
+ // Utils
609
+ function adaptTableStateSetter<T>(
610
+ setter: React.Dispatch<React.SetStateAction<T>>,
611
+ ) {
612
+ return (valueOrFn: T | ((prev: T) => T)) => {
613
+ setter((prev) =>
614
+ typeof valueOrFn === "function"
615
+ ? (valueOrFn as (prev: T) => T)(prev)
616
+ : valueOrFn,
1112
617
  );
1113
- }
1114
- return (
1115
- <DataGridCell id={id ? `${id}-${key}` : undefined} key={key}>
1116
- <div className="bg-linear-270 to-neutral-300/[24%] from-neutral-300/[12%] rounded-xs w-full max-w-25 h-6"></div>
1117
- </DataGridCell>
1118
- );
1119
- };
1120
-
1121
- function ColumnSelectorHeaderCell<T>({
1122
- id,
1123
- table,
1124
- toggleColumnVisibility,
1125
- resetColumnVisibility,
1126
- }: {
1127
- id?: string;
1128
- table: Table<T>;
1129
- toggleColumnVisibility: (id: string, isVisible: boolean) => void;
1130
- resetColumnVisibility: () => void;
1131
- }) {
1132
- const ref = useRef<HTMLElement>(null);
1133
- const [show, setShow] = useState(false);
1134
-
1135
- return (
1136
- <DataGridCell
1137
- id={id}
1138
- width="48"
1139
- type="header"
1140
- color="text-secondary-normal"
1141
- ref={ref}
1142
- >
1143
- <Button
1144
- id={id ? `${id}-button` : undefined}
1145
- onClick={() => setShow((prev) => !prev)}
1146
- variant="navigation"
1147
- iconOnly
1148
- leftIcon={<Icon name="tune" />}
1149
- ></Button>
1150
- <Menu
1151
- id={id ? `${id}-menu` : undefined}
1152
- positionTo={ref}
1153
- position="bottom-right"
1154
- show={show}
1155
- setShow={setShow}
1156
- >
1157
- <Button
1158
- id={id ? `${id}-reset-button` : undefined}
1159
- variant="tertiary"
1160
- onClick={() => {
1161
- resetColumnVisibility();
1162
- setShow(false);
1163
- }}
1164
- >
1165
- Reset to default
1166
- </Button>
1167
- {table
1168
- .getAllColumns()
1169
- .filter((x) => x.columnDef.meta?.inVisibilityMenu)
1170
- .map((column) => (
1171
- <ColumnSelectorMenuOption
1172
- id={id ? `${id}-option-${column.id}` : undefined}
1173
- key={column.id}
1174
- column={column}
1175
- toggleColumnVisibility={toggleColumnVisibility}
1176
- />
1177
- ))}
1178
- </Menu>
1179
- </DataGridCell>
1180
- );
1181
- }
1182
-
1183
- function ColumnSelectorMenuOption<T>({
1184
- id,
1185
- column,
1186
- toggleColumnVisibility,
1187
- }: {
1188
- id?: string;
1189
- column: Column<T, unknown>;
1190
- toggleColumnVisibility: (id: string, isVisible: boolean) => void;
1191
- }) {
1192
- const [isVisible, setIsVisible] = useState(column.getIsVisible());
1193
- const label =
1194
- typeof column.columnDef.header === "string"
1195
- ? column.columnDef.header
1196
- : null;
1197
- return (
1198
- <MenuOption id={id} selected={isVisible} defaultChecked={isVisible}>
1199
- <Checkbox
1200
- id={id ? `${id}-checkbox` : undefined}
1201
- label={label ?? "Unknown"}
1202
- checked={isVisible}
1203
- onChange={(e) => {
1204
- setIsVisible(e.target.checked);
1205
- toggleColumnVisibility(column.id, e.target.checked);
1206
- }}
1207
- />
1208
- </MenuOption>
1209
- );
1210
- }
1211
-
1212
- function getSortIcon(sort: SortDirection | false, nextSort = false) {
1213
- const iconClassName = clsx(
1214
- "text-icon-on-action-primary-normal",
1215
- nextSort && "hidden group-hover:block",
1216
- );
1217
- if (sort === "asc")
1218
- return <Icon size={16} className={iconClassName} name="arrow_upward" />;
1219
- if (sort === "desc")
1220
- return <Icon size={16} className={iconClassName} name="arrow_downward" />;
1221
- return null;
618
+ };
1222
619
  }
1223
620
 
1224
- // Extend TanStack ColumnMeta
1225
- declare module "@tanstack/react-table" {
1226
- interface TableOptions<TData extends RowData>
1227
- extends PartialKeys<
1228
- TableOptionsResolved<TData>,
1229
- "state" | "onStateChange" | "renderFallbackValue"
1230
- > {
1231
- filterFns?: FilterFns;
1232
- }
1233
- interface FilterFns {
1234
- endsWith?: FilterFn<RowData>;
1235
- startsWith?: FilterFn<RowData>;
1236
- }
1237
-
1238
- interface ColumnMeta<TData extends RowData, TValue> {
1239
- filterVariant?: "text" | "select" | "range";
1240
- className?: string;
1241
- sticky?: boolean;
1242
- useCustomRenderer?: boolean;
1243
- locked?: boolean;
1244
- checkbox?: boolean;
1245
- headerWidth?: string;
1246
- visible?: boolean;
1247
- inVisibilityMenu?: boolean;
1248
- filterRowCell?: ({
1249
- header,
1250
- table,
1251
- }: {
1252
- header: Header<TData, TValue>;
1253
- table: Table<TData>;
1254
- }) => ReactNode;
1255
- }
1256
- }
1257
- export type { ColumnDef };
621
+ export type { ColumnDef } from "@tanstack/react-table";