@dmsi/wedgekit-react 0.0.82 → 0.0.83
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/{chunk-6R2HCLEL.js → chunk-37TJJQL3.js} +2 -2
- package/dist/{chunk-B6PDZCU7.js → chunk-5GUW4DUY.js} +1 -1
- package/dist/{chunk-ATOEGP3V.js → chunk-CKSDMI2Q.js} +14 -7
- package/dist/{chunk-2DCVAATK.js → chunk-MQWWNAO3.js} +4 -4
- package/dist/{chunk-FOC6LTSX.js → chunk-UPBBOZM3.js} +1 -1
- package/dist/{chunk-SWA5WVQO.js → chunk-WNQ53SVY.js} +30 -0
- package/dist/components/DataGridCell.cjs +53 -43
- package/dist/components/DataGridCell.js +5 -5
- package/dist/components/Menu.cjs +17 -14
- package/dist/components/Menu.js +3 -3
- package/dist/components/MenuOption.cjs +10 -7
- package/dist/components/MenuOption.js +2 -2
- package/dist/components/Modal.cjs +18 -15
- package/dist/components/Modal.js +3 -3
- package/dist/components/NestedMenu.cjs +12 -9
- package/dist/components/NestedMenu.js +2 -2
- package/dist/components/PDFViewer.cjs +21 -18
- package/dist/components/PDFViewer.js +3 -3
- package/dist/components/ProjectBar.cjs +6 -3
- package/dist/components/ProjectBar.js +1 -1
- package/dist/components/TopBar.cjs +1 -1
- package/dist/components/TopBar.js +1 -1
- package/dist/components/{DataGrid.cjs → index.cjs} +1424 -1335
- package/dist/components/{DataGrid.js → index.js} +948 -883
- package/dist/components/useMenuSystem.cjs +20 -17
- package/dist/components/useMenuSystem.js +2 -2
- package/dist/hooks/index.cjs +34 -3
- package/dist/hooks/index.js +3 -1
- package/package.json +6 -1
- package/src/components/DataGrid/ColumnSelectorHeaderCell/ColumnSelectorMenuOption.tsx +32 -0
- package/src/components/DataGrid/ColumnSelectorHeaderCell/index.tsx +66 -0
- package/src/components/DataGrid/PinnedColumns.tsx +145 -0
- package/src/components/DataGrid/TableBody/LoadingCell.tsx +40 -0
- package/src/components/DataGrid/TableBody/TableBodyRow.tsx +129 -0
- package/src/components/DataGrid/TableBody/index.tsx +159 -0
- package/src/components/{DataGrid.tsx → DataGrid/index.tsx} +42 -678
- package/src/components/DataGrid/types.ts +86 -0
- package/src/components/DataGrid/utils.tsx +15 -0
- package/src/components/DataGridCell.tsx +37 -21
- package/src/components/TopBar.tsx +1 -1
- package/src/components/index.ts +20 -0
- package/src/hooks/index.ts +1 -0
- package/dist/chunk-AWQSSKCK.js +0 -32
- package/dist/components/useInfiniteScroll.cjs +0 -57
- package/dist/components/useInfiniteScroll.js +0 -8
- /package/src/{components → hooks}/useInfiniteScroll.tsx +0 -0
|
@@ -39,16 +39,19 @@ __export(useMenuSystem_exports, {
|
|
|
39
39
|
useSubMenuSystem: () => useSubMenuSystem
|
|
40
40
|
});
|
|
41
41
|
module.exports = __toCommonJS(useMenuSystem_exports);
|
|
42
|
-
var
|
|
42
|
+
var import_react4 = require("react");
|
|
43
43
|
|
|
44
44
|
// src/hooks/useKeydown.ts
|
|
45
45
|
var import_react = require("react");
|
|
46
46
|
|
|
47
|
-
// src/hooks/
|
|
47
|
+
// src/hooks/useInfiniteScroll.tsx
|
|
48
48
|
var import_react2 = require("react");
|
|
49
|
+
|
|
50
|
+
// src/hooks/useMatchesMedia.ts
|
|
51
|
+
var import_react3 = require("react");
|
|
49
52
|
var useMatchesMedia = (query) => {
|
|
50
|
-
const [matches, setMatches] = (0,
|
|
51
|
-
(0,
|
|
53
|
+
const [matches, setMatches] = (0, import_react3.useState)();
|
|
54
|
+
(0, import_react3.useLayoutEffect)(() => {
|
|
52
55
|
const mediaQueryList = window.matchMedia(query);
|
|
53
56
|
const listener = () => setMatches(mediaQueryList.matches);
|
|
54
57
|
listener();
|
|
@@ -61,17 +64,17 @@ var useMatchesMobile = () => useMatchesMedia("(width < 48rem)");
|
|
|
61
64
|
|
|
62
65
|
// src/components/useMenuSystem.tsx
|
|
63
66
|
function useSubMenuSystem(mobilePositionTo) {
|
|
64
|
-
const [activeMenus, setActiveMenus] = (0,
|
|
67
|
+
const [activeMenus, setActiveMenus] = (0, import_react4.useState)(
|
|
65
68
|
{}
|
|
66
69
|
);
|
|
67
|
-
const [activeMenu, setActiveMenu] = (0,
|
|
68
|
-
const [currentSubMenuLevel, setCurrentSubMenuLevel] = (0,
|
|
70
|
+
const [activeMenu, setActiveMenu] = (0, import_react4.useState)("");
|
|
71
|
+
const [currentSubMenuLevel, setCurrentSubMenuLevel] = (0, import_react4.useState)(
|
|
69
72
|
null
|
|
70
73
|
);
|
|
71
|
-
const menuRootRef = (0,
|
|
72
|
-
const subMenuRefs = (0,
|
|
73
|
-
const hoverTimeoutRef = (0,
|
|
74
|
-
const closeTimeoutRef = (0,
|
|
74
|
+
const menuRootRef = (0, import_react4.useRef)(null);
|
|
75
|
+
const subMenuRefs = (0, import_react4.useRef)({});
|
|
76
|
+
const hoverTimeoutRef = (0, import_react4.useRef)(null);
|
|
77
|
+
const closeTimeoutRef = (0, import_react4.useRef)(null);
|
|
75
78
|
const isMobile = useMatchesMobile();
|
|
76
79
|
const toggleMenu = (menuId, level) => {
|
|
77
80
|
if (closeTimeoutRef.current) {
|
|
@@ -169,7 +172,7 @@ function useSubMenuSystem(mobilePositionTo) {
|
|
|
169
172
|
const isMenuActive = (menuId, level) => {
|
|
170
173
|
return activeMenus[level] === menuId;
|
|
171
174
|
};
|
|
172
|
-
(0,
|
|
175
|
+
(0, import_react4.useEffect)(() => {
|
|
173
176
|
const handleClickOutside = (event) => {
|
|
174
177
|
var _a;
|
|
175
178
|
if (Object.keys(activeMenus).length === 0) return;
|
|
@@ -188,7 +191,7 @@ function useSubMenuSystem(mobilePositionTo) {
|
|
|
188
191
|
document.removeEventListener("mousedown", handleClickOutside);
|
|
189
192
|
};
|
|
190
193
|
}, [activeMenus]);
|
|
191
|
-
(0,
|
|
194
|
+
(0, import_react4.useEffect)(() => {
|
|
192
195
|
return () => {
|
|
193
196
|
if (hoverTimeoutRef.current) {
|
|
194
197
|
clearTimeout(hoverTimeoutRef.current);
|
|
@@ -265,13 +268,13 @@ function useSubMenuSystem(mobilePositionTo) {
|
|
|
265
268
|
};
|
|
266
269
|
}
|
|
267
270
|
function useMenuPosition(elementRef, position = "bottom", options) {
|
|
268
|
-
const [menuPosition, setMenuPosition] = (0,
|
|
271
|
+
const [menuPosition, setMenuPosition] = (0, import_react4.useState)({
|
|
269
272
|
top: 0,
|
|
270
273
|
left: 0,
|
|
271
274
|
minWidth: 0
|
|
272
275
|
});
|
|
273
276
|
const isMobile = useMatchesMobile();
|
|
274
|
-
const updatePosition = (0,
|
|
277
|
+
const updatePosition = (0, import_react4.useCallback)(() => {
|
|
275
278
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
276
279
|
if (!(elementRef == null ? void 0 : elementRef.current)) return;
|
|
277
280
|
const triggerRect = elementRef.current.getBoundingClientRect();
|
|
@@ -307,7 +310,7 @@ function useMenuPosition(elementRef, position = "bottom", options) {
|
|
|
307
310
|
minWidth: triggerRect.width
|
|
308
311
|
});
|
|
309
312
|
}, [elementRef, position, options == null ? void 0 : options.menuRef, options == null ? void 0 : options.topOffset, isMobile]);
|
|
310
|
-
(0,
|
|
313
|
+
(0, import_react4.useEffect)(() => {
|
|
311
314
|
if (!(options == null ? void 0 : options.isOpen) || !(options == null ? void 0 : options.setIsOpen)) return;
|
|
312
315
|
const handleClickOutside = (event) => {
|
|
313
316
|
var _a, _b, _c, _d, _e;
|
|
@@ -333,7 +336,7 @@ function useMenuPosition(elementRef, position = "bottom", options) {
|
|
|
333
336
|
options == null ? void 0 : options.menuRef,
|
|
334
337
|
options == null ? void 0 : options.additionalRefs
|
|
335
338
|
]);
|
|
336
|
-
(0,
|
|
339
|
+
(0, import_react4.useEffect)(() => {
|
|
337
340
|
updatePosition();
|
|
338
341
|
const resizeObserver = new ResizeObserver(updatePosition);
|
|
339
342
|
if (elementRef == null ? void 0 : elementRef.current) {
|
package/dist/hooks/index.cjs
CHANGED
|
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/hooks/index.ts
|
|
21
21
|
var hooks_exports = {};
|
|
22
22
|
__export(hooks_exports, {
|
|
23
|
+
useInfiniteScroll: () => useInfiniteScroll,
|
|
23
24
|
useKeydown: () => useKeydown,
|
|
24
25
|
useMatchesMedia: () => useMatchesMedia,
|
|
25
26
|
useMatchesMobile: () => useMatchesMobile
|
|
@@ -55,11 +56,40 @@ function useKeydown(keys, isActive) {
|
|
|
55
56
|
}, [keys, isActive]);
|
|
56
57
|
}
|
|
57
58
|
|
|
58
|
-
// src/hooks/
|
|
59
|
+
// src/hooks/useInfiniteScroll.tsx
|
|
59
60
|
var import_react2 = require("react");
|
|
61
|
+
function useInfiniteScroll({
|
|
62
|
+
containerRef,
|
|
63
|
+
onLoadMore,
|
|
64
|
+
isLoading,
|
|
65
|
+
offset = 50,
|
|
66
|
+
enabled = true
|
|
67
|
+
// ✅ Add this
|
|
68
|
+
}) {
|
|
69
|
+
(0, import_react2.useEffect)(() => {
|
|
70
|
+
if (!enabled) return;
|
|
71
|
+
const handleScroll = () => {
|
|
72
|
+
const el2 = containerRef.current;
|
|
73
|
+
if (!el2 || isLoading) return;
|
|
74
|
+
const { scrollTop, scrollHeight, clientHeight } = el2;
|
|
75
|
+
const isNearBottom = scrollTop + clientHeight >= scrollHeight - offset;
|
|
76
|
+
if (isNearBottom) {
|
|
77
|
+
onLoadMore();
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
const el = containerRef.current;
|
|
81
|
+
if (el) el.addEventListener("scroll", handleScroll);
|
|
82
|
+
return () => {
|
|
83
|
+
if (el) el.removeEventListener("scroll", handleScroll);
|
|
84
|
+
};
|
|
85
|
+
}, [containerRef, onLoadMore, isLoading, offset, enabled]);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// src/hooks/useMatchesMedia.ts
|
|
89
|
+
var import_react3 = require("react");
|
|
60
90
|
var useMatchesMedia = (query) => {
|
|
61
|
-
const [matches, setMatches] = (0,
|
|
62
|
-
(0,
|
|
91
|
+
const [matches, setMatches] = (0, import_react3.useState)();
|
|
92
|
+
(0, import_react3.useLayoutEffect)(() => {
|
|
63
93
|
const mediaQueryList = window.matchMedia(query);
|
|
64
94
|
const listener = () => setMatches(mediaQueryList.matches);
|
|
65
95
|
listener();
|
|
@@ -71,6 +101,7 @@ var useMatchesMedia = (query) => {
|
|
|
71
101
|
var useMatchesMobile = () => useMatchesMedia("(width < 48rem)");
|
|
72
102
|
// Annotate the CommonJS export names for ESM import in node:
|
|
73
103
|
0 && (module.exports = {
|
|
104
|
+
useInfiniteScroll,
|
|
74
105
|
useKeydown,
|
|
75
106
|
useMatchesMedia,
|
|
76
107
|
useMatchesMobile
|
package/dist/hooks/index.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
|
+
useInfiniteScroll,
|
|
2
3
|
useKeydown,
|
|
3
4
|
useMatchesMedia,
|
|
4
5
|
useMatchesMobile
|
|
5
|
-
} from "../chunk-
|
|
6
|
+
} from "../chunk-WNQ53SVY.js";
|
|
6
7
|
import "../chunk-ORMEWXMH.js";
|
|
7
8
|
export {
|
|
9
|
+
useInfiniteScroll,
|
|
8
10
|
useKeydown,
|
|
9
11
|
useMatchesMedia,
|
|
10
12
|
useMatchesMobile
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dmsi/wedgekit-react",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.83",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"build": "tsup",
|
|
@@ -22,6 +22,11 @@
|
|
|
22
22
|
"import": "./dist/components/*.js",
|
|
23
23
|
"require": "./dist/components/*.cjs"
|
|
24
24
|
},
|
|
25
|
+
"./components": {
|
|
26
|
+
"types": "./src/components/index.ts",
|
|
27
|
+
"import": "./dist/components/index.js",
|
|
28
|
+
"require": "./dist/components/index.cjs"
|
|
29
|
+
},
|
|
25
30
|
"./hooks": {
|
|
26
31
|
"types": "./src/hooks/index.ts",
|
|
27
32
|
"import": "./dist/hooks/index.js",
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Column } from "@tanstack/react-table";
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import { Checkbox, MenuOption } from "../..";
|
|
4
|
+
|
|
5
|
+
export function ColumnSelectorMenuOption<T>({
|
|
6
|
+
id,
|
|
7
|
+
column,
|
|
8
|
+
toggleColumnVisibility,
|
|
9
|
+
}: {
|
|
10
|
+
id?: string;
|
|
11
|
+
column: Column<T, unknown>;
|
|
12
|
+
toggleColumnVisibility: (id: string, isVisible: boolean) => void;
|
|
13
|
+
}) {
|
|
14
|
+
const [isVisible, setIsVisible] = useState(column.getIsVisible());
|
|
15
|
+
const label =
|
|
16
|
+
typeof column.columnDef.header === "string"
|
|
17
|
+
? column.columnDef.header
|
|
18
|
+
: null;
|
|
19
|
+
return (
|
|
20
|
+
<MenuOption id={id} selected={isVisible} defaultChecked={isVisible}>
|
|
21
|
+
<Checkbox
|
|
22
|
+
id={id ? `${id}-checkbox` : undefined}
|
|
23
|
+
label={label ?? "Unknown"}
|
|
24
|
+
checked={isVisible}
|
|
25
|
+
onChange={(e) => {
|
|
26
|
+
setIsVisible(e.target.checked);
|
|
27
|
+
toggleColumnVisibility(column.id, e.target.checked);
|
|
28
|
+
}}
|
|
29
|
+
/>
|
|
30
|
+
</MenuOption>
|
|
31
|
+
);
|
|
32
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { Table } from "@tanstack/react-table";
|
|
2
|
+
import { useRef, useState } from "react";
|
|
3
|
+
import { Button, DataGridCell, Icon, Menu } from "../..";
|
|
4
|
+
import { ColumnSelectorMenuOption } from "./ColumnSelectorMenuOption";
|
|
5
|
+
|
|
6
|
+
export function ColumnSelectorHeaderCell<T>({
|
|
7
|
+
id,
|
|
8
|
+
table,
|
|
9
|
+
toggleColumnVisibility,
|
|
10
|
+
resetColumnVisibility,
|
|
11
|
+
}: {
|
|
12
|
+
id?: string;
|
|
13
|
+
table: Table<T>;
|
|
14
|
+
toggleColumnVisibility: (id: string, isVisible: boolean) => void;
|
|
15
|
+
resetColumnVisibility: () => void;
|
|
16
|
+
}) {
|
|
17
|
+
const ref = useRef<HTMLElement>(null);
|
|
18
|
+
const [show, setShow] = useState(false);
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<DataGridCell
|
|
22
|
+
id={id}
|
|
23
|
+
width="48"
|
|
24
|
+
type="header"
|
|
25
|
+
color="text-secondary-normal"
|
|
26
|
+
ref={ref}
|
|
27
|
+
>
|
|
28
|
+
<Button
|
|
29
|
+
id={id ? `${id}-button` : undefined}
|
|
30
|
+
onClick={() => setShow((prev) => !prev)}
|
|
31
|
+
variant="navigation"
|
|
32
|
+
iconOnly
|
|
33
|
+
leftIcon={<Icon name="tune" />}
|
|
34
|
+
></Button>
|
|
35
|
+
<Menu
|
|
36
|
+
id={id ? `${id}-menu` : undefined}
|
|
37
|
+
positionTo={ref}
|
|
38
|
+
position="bottom-right"
|
|
39
|
+
show={show}
|
|
40
|
+
setShow={setShow}
|
|
41
|
+
>
|
|
42
|
+
<Button
|
|
43
|
+
id={id ? `${id}-reset-button` : undefined}
|
|
44
|
+
variant="tertiary"
|
|
45
|
+
onClick={() => {
|
|
46
|
+
resetColumnVisibility();
|
|
47
|
+
setShow(false);
|
|
48
|
+
}}
|
|
49
|
+
>
|
|
50
|
+
Reset to default
|
|
51
|
+
</Button>
|
|
52
|
+
{table
|
|
53
|
+
.getAllColumns()
|
|
54
|
+
.filter((x) => x.columnDef.meta?.inVisibilityMenu)
|
|
55
|
+
.map((column) => (
|
|
56
|
+
<ColumnSelectorMenuOption
|
|
57
|
+
id={id ? `${id}-option-${column.id}` : undefined}
|
|
58
|
+
key={column.id}
|
|
59
|
+
column={column}
|
|
60
|
+
toggleColumnVisibility={toggleColumnVisibility}
|
|
61
|
+
/>
|
|
62
|
+
))}
|
|
63
|
+
</Menu>
|
|
64
|
+
</DataGridCell>
|
|
65
|
+
);
|
|
66
|
+
}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { flexRender, RowData, Table } from "@tanstack/react-table";
|
|
2
|
+
import { Checkbox, DataCellHeader, DataGridCell, Subheader } from "..";
|
|
3
|
+
import { DataGridPagination } from "./types";
|
|
4
|
+
import clsx from "clsx";
|
|
5
|
+
import { getSortIcon } from "./utils";
|
|
6
|
+
import React from "react";
|
|
7
|
+
import { TableBody } from "./TableBody";
|
|
8
|
+
interface PinnedColumnsProps<TData extends RowData> {
|
|
9
|
+
pinDirection: "left" | "right";
|
|
10
|
+
table: Table<TData>;
|
|
11
|
+
tableContainerRef: React.RefObject<HTMLDivElement | null>;
|
|
12
|
+
pagination: DataGridPagination | undefined;
|
|
13
|
+
isLoadingMore: boolean;
|
|
14
|
+
hasMore: boolean;
|
|
15
|
+
showFilterRow: boolean;
|
|
16
|
+
enableColumnSelector?: boolean;
|
|
17
|
+
centerHeader?: boolean;
|
|
18
|
+
allSelectedAcrossPages?: boolean;
|
|
19
|
+
someSelectedAcrossPages?: boolean;
|
|
20
|
+
toggleSelectAllAcrossPages?: () => void;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function PinnedColumns<TData>({
|
|
24
|
+
pinDirection = "left",
|
|
25
|
+
table,
|
|
26
|
+
centerHeader,
|
|
27
|
+
allSelectedAcrossPages,
|
|
28
|
+
someSelectedAcrossPages,
|
|
29
|
+
toggleSelectAllAcrossPages,
|
|
30
|
+
...props
|
|
31
|
+
}: PinnedColumnsProps<TData>) {
|
|
32
|
+
const headerGroups =
|
|
33
|
+
pinDirection === "left"
|
|
34
|
+
? table.getLeftHeaderGroups()
|
|
35
|
+
: table.getRightHeaderGroups();
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
headerGroups[0]?.headers.length > 0 && (
|
|
39
|
+
<table
|
|
40
|
+
className={clsx(
|
|
41
|
+
"flex flex-col min-h-min sticky z-20 bg-background-grouped-primary-normal",
|
|
42
|
+
pinDirection === "left" ? "left-0" : "right-0",
|
|
43
|
+
)}
|
|
44
|
+
>
|
|
45
|
+
<thead className="sticky top-0 z-20 grid">
|
|
46
|
+
{headerGroups.map((headerGroup) => {
|
|
47
|
+
return (
|
|
48
|
+
<tr key={headerGroup.id} className="flex w-full">
|
|
49
|
+
{headerGroup.headers.map((header) => {
|
|
50
|
+
if (!header) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (typeof header.column.columnDef.header === "string") {
|
|
55
|
+
const customHeaderWidth =
|
|
56
|
+
header.column.columnDef.meta?.headerWidth;
|
|
57
|
+
|
|
58
|
+
return (
|
|
59
|
+
<DataCellHeader
|
|
60
|
+
locked
|
|
61
|
+
key={header.id}
|
|
62
|
+
header={header}
|
|
63
|
+
center={centerHeader}
|
|
64
|
+
width={customHeaderWidth}
|
|
65
|
+
className={clsx(
|
|
66
|
+
header.column.getCanSort()
|
|
67
|
+
? "cursor-pointer"
|
|
68
|
+
: "cursor-grab",
|
|
69
|
+
"group",
|
|
70
|
+
)}
|
|
71
|
+
>
|
|
72
|
+
<Subheader tall>
|
|
73
|
+
{header.column.columnDef.header}
|
|
74
|
+
</Subheader>
|
|
75
|
+
|
|
76
|
+
{getSortIcon(header.column.getIsSorted())}
|
|
77
|
+
|
|
78
|
+
{!header.column.getIsSorted() &&
|
|
79
|
+
header.column.getCanSort() &&
|
|
80
|
+
getSortIcon(
|
|
81
|
+
header.column.getNextSortingOrder(),
|
|
82
|
+
true,
|
|
83
|
+
)}
|
|
84
|
+
|
|
85
|
+
{header.column.getSortIndex() !== -1 &&
|
|
86
|
+
table.getState().sorting.length > 1 && (
|
|
87
|
+
<Subheader tall>
|
|
88
|
+
{header.column.getSortIndex() + 1}
|
|
89
|
+
</Subheader>
|
|
90
|
+
)}
|
|
91
|
+
|
|
92
|
+
{!header.column.columnDef.meta?.locked && (
|
|
93
|
+
<div
|
|
94
|
+
onDoubleClick={(e) => {
|
|
95
|
+
e.stopPropagation();
|
|
96
|
+
header.column.resetSize();
|
|
97
|
+
}}
|
|
98
|
+
onMouseDown={(e) => {
|
|
99
|
+
e.stopPropagation();
|
|
100
|
+
header.getResizeHandler()(e);
|
|
101
|
+
}}
|
|
102
|
+
onTouchStart={(e) => {
|
|
103
|
+
e.stopPropagation();
|
|
104
|
+
header.getResizeHandler()(e);
|
|
105
|
+
}}
|
|
106
|
+
className="absolute right-0 inset-y-0 w-px bg-black cursor-col-resize"
|
|
107
|
+
/>
|
|
108
|
+
)}
|
|
109
|
+
</DataCellHeader>
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
return (
|
|
113
|
+
<React.Fragment key={header.id}>
|
|
114
|
+
{header.column.columnDef.meta?.checkbox ? (
|
|
115
|
+
<DataGridCell type="header" component="checkbox" locked>
|
|
116
|
+
<Checkbox
|
|
117
|
+
checked={allSelectedAcrossPages}
|
|
118
|
+
indeterminate={someSelectedAcrossPages}
|
|
119
|
+
onChange={toggleSelectAllAcrossPages}
|
|
120
|
+
/>
|
|
121
|
+
</DataGridCell>
|
|
122
|
+
) : (
|
|
123
|
+
flexRender(
|
|
124
|
+
header.column.columnDef.header,
|
|
125
|
+
header.getContext(),
|
|
126
|
+
)
|
|
127
|
+
)}
|
|
128
|
+
</React.Fragment>
|
|
129
|
+
);
|
|
130
|
+
})}
|
|
131
|
+
</tr>
|
|
132
|
+
);
|
|
133
|
+
})}
|
|
134
|
+
</thead>
|
|
135
|
+
|
|
136
|
+
<TableBody
|
|
137
|
+
{...props}
|
|
138
|
+
table={table}
|
|
139
|
+
locked={true}
|
|
140
|
+
pinDirection={pinDirection}
|
|
141
|
+
/>
|
|
142
|
+
</table>
|
|
143
|
+
)
|
|
144
|
+
);
|
|
145
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { ColumnDef, RowData } from "@tanstack/react-table";
|
|
2
|
+
import { Checkbox, DataGridCell, Input } from "../..";
|
|
3
|
+
|
|
4
|
+
export function LoadingCell<T extends RowData>({
|
|
5
|
+
id,
|
|
6
|
+
column,
|
|
7
|
+
}: {
|
|
8
|
+
id?: string;
|
|
9
|
+
column: ColumnDef<T>;
|
|
10
|
+
}) {
|
|
11
|
+
const key = `loading-${column.id}`;
|
|
12
|
+
if (column.cell === "checkbox") {
|
|
13
|
+
return (
|
|
14
|
+
<DataGridCell id={id ? `${id}-${key}` : undefined} key={key}>
|
|
15
|
+
<Checkbox id={id ? `${id}-${key}-checkbox` : undefined} disabled />
|
|
16
|
+
</DataGridCell>
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
if (column.cell === "input") {
|
|
20
|
+
return (
|
|
21
|
+
<DataGridCell
|
|
22
|
+
id={id ? `${id}-${key}` : undefined}
|
|
23
|
+
key={key}
|
|
24
|
+
component="input"
|
|
25
|
+
>
|
|
26
|
+
<Input
|
|
27
|
+
id={id ? `${id}-${key}-input` : undefined}
|
|
28
|
+
align="left"
|
|
29
|
+
disabled
|
|
30
|
+
wrapperClassName="!rounded-none !border-0"
|
|
31
|
+
/>
|
|
32
|
+
</DataGridCell>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
return (
|
|
36
|
+
<DataGridCell id={id ? `${id}-${key}` : undefined} key={key}>
|
|
37
|
+
<div className="bg-linear-270 to-neutral-300/[24%] from-neutral-300/[12%] rounded-xs w-full max-w-25 h-6"></div>
|
|
38
|
+
</DataGridCell>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import clsx from "clsx";
|
|
2
|
+
import { Cell, flexRender, Row } from "@tanstack/react-table";
|
|
3
|
+
import { VirtualItem, Virtualizer } from "@tanstack/react-virtual";
|
|
4
|
+
import React from "react";
|
|
5
|
+
import { DataGridCell, DragAlongCell, Paragraph, Tooltip } from "../..";
|
|
6
|
+
|
|
7
|
+
interface TableBodyRowProps<T> {
|
|
8
|
+
id?: string;
|
|
9
|
+
columnVirtualizer?: Virtualizer<HTMLDivElement, HTMLTableCellElement>;
|
|
10
|
+
row: Row<T>;
|
|
11
|
+
rowVirtualizer: Virtualizer<HTMLDivElement, HTMLTableRowElement>;
|
|
12
|
+
virtualPaddingLeft?: number | undefined;
|
|
13
|
+
virtualPaddingRight?: number | undefined;
|
|
14
|
+
virtualRow: VirtualItem;
|
|
15
|
+
showFilterRow: boolean;
|
|
16
|
+
enableColumnSelector?: boolean;
|
|
17
|
+
locked?: boolean;
|
|
18
|
+
pinDirection?: "left" | "right";
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function TableBodyRow<T>({
|
|
22
|
+
id,
|
|
23
|
+
columnVirtualizer,
|
|
24
|
+
row,
|
|
25
|
+
// rowVirtualizer,
|
|
26
|
+
virtualPaddingLeft,
|
|
27
|
+
virtualPaddingRight,
|
|
28
|
+
virtualRow,
|
|
29
|
+
showFilterRow,
|
|
30
|
+
enableColumnSelector = false,
|
|
31
|
+
locked,
|
|
32
|
+
pinDirection,
|
|
33
|
+
}: TableBodyRowProps<T>) {
|
|
34
|
+
let visibleCells: Cell<T, unknown>[];
|
|
35
|
+
|
|
36
|
+
if (locked) {
|
|
37
|
+
visibleCells =
|
|
38
|
+
pinDirection === "left"
|
|
39
|
+
? row.getLeftVisibleCells()
|
|
40
|
+
: row.getRightVisibleCells();
|
|
41
|
+
} else {
|
|
42
|
+
visibleCells = row.getCenterVisibleCells();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const virtualColumns = columnVirtualizer?.getVirtualItems() ?? [];
|
|
46
|
+
const columns = locked ? visibleCells : virtualColumns;
|
|
47
|
+
|
|
48
|
+
const isError =
|
|
49
|
+
typeof row.original === "object" &&
|
|
50
|
+
row.original !== null &&
|
|
51
|
+
"rowState" in row.original &&
|
|
52
|
+
row.original.rowState === "error";
|
|
53
|
+
|
|
54
|
+
const CellElement = locked ? DataGridCell : DragAlongCell;
|
|
55
|
+
|
|
56
|
+
return (
|
|
57
|
+
<tr
|
|
58
|
+
key={row.id}
|
|
59
|
+
className={clsx(
|
|
60
|
+
"transition-colors hover:bg-background-action-secondary-hover",
|
|
61
|
+
row.getIsSelected() && "!bg-background-action-secondary-hover",
|
|
62
|
+
isError && "!bg-background-action-critical-secondary-hover",
|
|
63
|
+
showFilterRow
|
|
64
|
+
? "even:bg-background-grouped-primary-normal odd:bg-background-grouped-secondary-normal"
|
|
65
|
+
: "odd:bg-background-grouped-primary-normal even:bg-background-grouped-secondary-normal",
|
|
66
|
+
)}
|
|
67
|
+
style={{
|
|
68
|
+
display: "flex",
|
|
69
|
+
position: "absolute",
|
|
70
|
+
transform: `translateY(${
|
|
71
|
+
showFilterRow ? virtualRow.start + 40 : virtualRow.start
|
|
72
|
+
}px)`,
|
|
73
|
+
width: "100%",
|
|
74
|
+
}}
|
|
75
|
+
>
|
|
76
|
+
{!locked && virtualPaddingLeft ? (
|
|
77
|
+
// fake empty column to the left for virtualization scroll padding
|
|
78
|
+
<td style={{ display: "flex", width: virtualPaddingLeft }} />
|
|
79
|
+
) : null}
|
|
80
|
+
|
|
81
|
+
{columns.map((column) => {
|
|
82
|
+
const cell = locked
|
|
83
|
+
? (column as Cell<T, unknown>)
|
|
84
|
+
: visibleCells[(column as VirtualItem).index];
|
|
85
|
+
|
|
86
|
+
if (!cell) {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
const cellValue = cell.getValue();
|
|
90
|
+
|
|
91
|
+
return cell.column.columnDef.meta?.useCustomRenderer ? (
|
|
92
|
+
<React.Fragment key={cell.id}>
|
|
93
|
+
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
|
94
|
+
</React.Fragment>
|
|
95
|
+
) : (
|
|
96
|
+
<CellElement
|
|
97
|
+
key={cell.id}
|
|
98
|
+
id={id ? `${id}-cell-${cell.id}` : undefined}
|
|
99
|
+
cell={cell}
|
|
100
|
+
className={clsx({
|
|
101
|
+
"justify-end": typeof cellValue === "number",
|
|
102
|
+
})}
|
|
103
|
+
width={cell.column.columnDef.meta?.headerWidth}
|
|
104
|
+
>
|
|
105
|
+
<Tooltip
|
|
106
|
+
id={id ? `${id}-tooltip-${cell.id}` : undefined}
|
|
107
|
+
showOnTruncation
|
|
108
|
+
message={cellValue as string}
|
|
109
|
+
position="bottom"
|
|
110
|
+
>
|
|
111
|
+
<Paragraph addOverflow tall>
|
|
112
|
+
{cellValue as React.ReactNode | string}
|
|
113
|
+
</Paragraph>
|
|
114
|
+
</Tooltip>
|
|
115
|
+
</CellElement>
|
|
116
|
+
);
|
|
117
|
+
})}
|
|
118
|
+
|
|
119
|
+
{!locked && virtualPaddingRight ? (
|
|
120
|
+
// fake empty column to the right for virtualization scroll padding
|
|
121
|
+
<td style={{ display: "flex", width: virtualPaddingRight }} />
|
|
122
|
+
) : null}
|
|
123
|
+
|
|
124
|
+
{enableColumnSelector && !locked && (
|
|
125
|
+
<td className="p-2" style={{ width: "48.8px" }}></td>
|
|
126
|
+
)}
|
|
127
|
+
</tr>
|
|
128
|
+
);
|
|
129
|
+
}
|