@rowsncolumns/grid 9.0.3 → 13.2.32
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/LICENSE.md +100 -0
- package/Readme.md +53 -59
- package/dist/cjs/Cell.d.ts +35 -0
- package/dist/cjs/Cell.d.ts.map +1 -0
- package/dist/cjs/Cell.js +29 -0
- package/dist/{CellOverlay.d.ts → cjs/CellOverlay.d.ts} +5 -5
- package/dist/cjs/CellOverlay.d.ts.map +1 -0
- package/dist/cjs/CellOverlay.js +126 -0
- package/dist/cjs/Context.d.ts +8 -0
- package/dist/cjs/Context.d.ts.map +1 -0
- package/dist/cjs/Context.js +13 -0
- package/dist/{FillHandle.d.ts → cjs/FillHandle.d.ts} +2 -1
- package/dist/cjs/FillHandle.d.ts.map +1 -0
- package/dist/cjs/FillHandle.js +26 -0
- package/dist/cjs/Grid.d.ts +558 -0
- package/dist/cjs/Grid.d.ts.map +1 -0
- package/dist/cjs/Grid.js +2446 -0
- package/dist/{GridLine.d.ts → cjs/GridLine.d.ts} +2 -1
- package/dist/cjs/GridLine.d.ts.map +1 -0
- package/dist/cjs/GridLine.js +10 -0
- package/dist/cjs/Image.d.ts +11 -0
- package/dist/cjs/Image.d.ts.map +1 -0
- package/dist/cjs/Image.js +57 -0
- package/dist/cjs/MemoizedGrid.d.ts +49 -0
- package/dist/cjs/MemoizedGrid.d.ts.map +1 -0
- package/dist/cjs/MemoizedGrid.js +105 -0
- package/dist/cjs/Selection.d.ts +5 -0
- package/dist/cjs/Selection.d.ts.map +1 -0
- package/dist/cjs/Selection.js +10 -0
- package/dist/{helpers.d.ts → cjs/helpers.d.ts} +59 -39
- package/dist/cjs/helpers.d.ts.map +1 -0
- package/dist/cjs/helpers.js +1409 -0
- package/dist/{hooks → cjs/hooks}/useCopyPaste.d.ts +3 -2
- package/dist/cjs/hooks/useCopyPaste.d.ts.map +1 -0
- package/dist/cjs/hooks/useCopyPaste.js +230 -0
- package/dist/{hooks → cjs/hooks}/useEditable.d.ts +21 -8
- package/dist/cjs/hooks/useEditable.d.ts.map +1 -0
- package/dist/cjs/hooks/useEditable.js +491 -0
- package/dist/{hooks → cjs/hooks}/useFilter.d.ts +3 -2
- package/dist/cjs/hooks/useFilter.d.ts.map +1 -0
- package/dist/cjs/hooks/useFilter.js +97 -0
- package/dist/{hooks → cjs/hooks}/useImage.d.ts +1 -0
- package/dist/cjs/hooks/useImage.d.ts.map +1 -0
- package/dist/cjs/hooks/useImage.js +80 -0
- package/dist/{hooks → cjs/hooks}/usePagination.d.ts +3 -2
- package/dist/cjs/hooks/usePagination.d.ts.map +1 -0
- package/dist/cjs/hooks/usePagination.js +53 -0
- package/dist/{hooks → cjs/hooks}/useSizer.d.ts +28 -29
- package/dist/cjs/hooks/useSizer.d.ts.map +1 -0
- package/dist/cjs/hooks/useSizer.js +176 -0
- package/dist/{hooks → cjs/hooks}/useTooltip.d.ts +2 -1
- package/dist/cjs/hooks/useTooltip.d.ts.map +1 -0
- package/dist/cjs/hooks/useTooltip.js +82 -0
- package/dist/{hooks → cjs/hooks}/useUndo.d.ts +2 -1
- package/dist/cjs/hooks/useUndo.d.ts.map +1 -0
- package/dist/cjs/hooks/useUndo.js +87 -0
- package/dist/cjs/index.d.ts +19 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +29 -0
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -0
- package/dist/{types.d.ts → cjs/types.d.ts} +8 -3
- package/dist/cjs/types.d.ts.map +1 -0
- package/dist/{types.js → cjs/types.js} +7 -8
- package/dist/cjs/utils.d.ts +9 -0
- package/dist/cjs/utils.d.ts.map +1 -0
- package/dist/cjs/utils.js +58 -0
- package/dist/cjs/vitest.config.d.ts +3 -0
- package/dist/cjs/vitest.config.d.ts.map +1 -0
- package/dist/cjs/vitest.config.js +24 -0
- package/dist/esm/Cell.d.ts +35 -0
- package/dist/esm/Cell.d.ts.map +1 -0
- package/dist/esm/Cell.js +24 -0
- package/dist/esm/CellOverlay.d.ts +21 -0
- package/dist/esm/CellOverlay.d.ts.map +1 -0
- package/dist/esm/CellOverlay.js +120 -0
- package/dist/esm/Context.d.ts +8 -0
- package/dist/esm/Context.d.ts.map +1 -0
- package/dist/esm/Context.js +9 -0
- package/dist/esm/FillHandle.d.ts +8 -0
- package/dist/esm/FillHandle.d.ts.map +1 -0
- package/dist/{FillHandle.js → esm/FillHandle.js} +5 -11
- package/dist/esm/Grid.d.ts +558 -0
- package/dist/esm/Grid.d.ts.map +1 -0
- package/dist/esm/Grid.js +2451 -0
- package/dist/esm/GridLine.d.ts +5 -0
- package/dist/esm/GridLine.d.ts.map +1 -0
- package/dist/esm/GridLine.js +7 -0
- package/dist/esm/Image.d.ts +11 -0
- package/dist/esm/Image.d.ts.map +1 -0
- package/dist/esm/Image.js +53 -0
- package/dist/esm/MemoizedGrid.d.ts +49 -0
- package/dist/esm/MemoizedGrid.d.ts.map +1 -0
- package/dist/esm/MemoizedGrid.js +98 -0
- package/dist/esm/Selection.d.ts +5 -0
- package/dist/esm/Selection.d.ts.map +1 -0
- package/dist/esm/Selection.js +7 -0
- package/dist/esm/helpers.d.ts +281 -0
- package/dist/esm/helpers.d.ts.map +1 -0
- package/dist/esm/helpers.js +1260 -0
- package/dist/esm/hooks/useCopyPaste.d.ts +53 -0
- package/dist/esm/hooks/useCopyPaste.d.ts.map +1 -0
- package/dist/{hooks → esm/hooks}/useCopyPaste.js +40 -46
- package/dist/esm/hooks/useEditable.d.ts +253 -0
- package/dist/esm/hooks/useEditable.d.ts.map +1 -0
- package/dist/esm/hooks/useEditable.js +482 -0
- package/dist/esm/hooks/useFilter.d.ts +69 -0
- package/dist/esm/hooks/useFilter.d.ts.map +1 -0
- package/dist/{hooks → esm/hooks}/useFilter.js +22 -42
- package/dist/esm/hooks/useImage.d.ts +13 -0
- package/dist/esm/hooks/useImage.d.ts.map +1 -0
- package/dist/esm/hooks/useImage.js +76 -0
- package/dist/esm/hooks/usePagination.d.ts +69 -0
- package/dist/esm/hooks/usePagination.d.ts.map +1 -0
- package/dist/esm/hooks/usePagination.js +47 -0
- package/dist/esm/hooks/useSizer.d.ts +114 -0
- package/dist/esm/hooks/useSizer.d.ts.map +1 -0
- package/dist/esm/hooks/useSizer.js +176 -0
- package/dist/esm/hooks/useTooltip.d.ts +43 -0
- package/dist/esm/hooks/useTooltip.d.ts.map +1 -0
- package/dist/esm/hooks/useTooltip.js +80 -0
- package/dist/esm/hooks/useUndo.d.ts +36 -0
- package/dist/esm/hooks/useUndo.d.ts.map +1 -0
- package/dist/{hooks → esm/hooks}/useUndo.js +16 -25
- package/dist/esm/index.d.ts +19 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +17 -0
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -0
- package/dist/esm/types.d.ts +70 -0
- package/dist/esm/types.d.ts.map +1 -0
- package/dist/esm/types.js +68 -0
- package/dist/esm/utils.d.ts +9 -0
- package/dist/esm/utils.d.ts.map +1 -0
- package/dist/esm/utils.js +104 -0
- package/dist/esm/vitest.config.d.ts +3 -0
- package/dist/esm/vitest.config.d.ts.map +1 -0
- package/dist/esm/vitest.config.js +22 -0
- package/package.json +28 -29
- package/dist/Cell.d.ts +0 -23
- package/dist/Cell.js +0 -55
- package/dist/Cell.js.map +0 -1
- package/dist/CellOverlay.js +0 -116
- package/dist/CellOverlay.js.map +0 -1
- package/dist/FillHandle.js.map +0 -1
- package/dist/Grid.d.ts +0 -385
- package/dist/Grid.js +0 -1684
- package/dist/Grid.js.map +0 -1
- package/dist/GridLine.js +0 -13
- package/dist/GridLine.js.map +0 -1
- package/dist/Image.d.ts +0 -8
- package/dist/Image.js +0 -50
- package/dist/Image.js.map +0 -1
- package/dist/Selection.d.ts +0 -4
- package/dist/Selection.js +0 -9
- package/dist/Selection.js.map +0 -1
- package/dist/helpers.js +0 -1033
- package/dist/helpers.js.map +0 -1
- package/dist/hooks/useCopyPaste.js.map +0 -1
- package/dist/hooks/useEditable.js +0 -477
- package/dist/hooks/useEditable.js.map +0 -1
- package/dist/hooks/useFilter.js.map +0 -1
- package/dist/hooks/useImage.js +0 -42
- package/dist/hooks/useImage.js.map +0 -1
- package/dist/hooks/usePagination.js +0 -73
- package/dist/hooks/usePagination.js.map +0 -1
- package/dist/hooks/useSelection.d.ts +0 -175
- package/dist/hooks/useSelection.js +0 -980
- package/dist/hooks/useSelection.js.map +0 -1
- package/dist/hooks/useSizer.js +0 -150
- package/dist/hooks/useSizer.js.map +0 -1
- package/dist/hooks/useTooltip.js +0 -106
- package/dist/hooks/useTooltip.js.map +0 -1
- package/dist/hooks/useTouch.d.ts +0 -21
- package/dist/hooks/useTouch.js +0 -73
- package/dist/hooks/useTouch.js.map +0 -1
- package/dist/hooks/useUndo.js.map +0 -1
- package/dist/index.d.ts +0 -25
- package/dist/index.js +0 -61
- package/dist/index.js.map +0 -1
- package/dist/types.js.map +0 -1
- package/dist/utils.d.ts +0 -8
- package/dist/utils.js +0 -153
- package/dist/utils.js.map +0 -1
- package/src/Cell.tsx +0 -100
- package/src/CellOverlay.tsx +0 -191
- package/src/FillHandle.tsx +0 -37
- package/src/Grid.tsx +0 -2677
- package/src/GridLine.tsx +0 -23
- package/src/Image.tsx +0 -43
- package/src/Selection.tsx +0 -9
- package/src/helpers.ts +0 -1455
- package/src/hooks/useCopyPaste.ts +0 -265
- package/src/hooks/useEditable.tsx +0 -945
- package/src/hooks/useFilter.tsx +0 -233
- package/src/hooks/useImage.ts +0 -57
- package/src/hooks/usePagination.tsx +0 -153
- package/src/hooks/useSelection.ts +0 -1437
- package/src/hooks/useSizer.ts +0 -312
- package/src/hooks/useTooltip.tsx +0 -172
- package/src/hooks/useTouch.ts +0 -116
- package/src/hooks/useUndo.ts +0 -134
- package/src/index.tsx +0 -46
- package/src/tests/Grid.spec.tsx +0 -47
- package/src/tests/helpers.test.ts +0 -292
- package/src/tests/usePagination.test.ts +0 -28
- package/src/tests/useSelection.test.ts +0 -27
- package/src/tests/useUndo.test.ts +0 -73
- package/src/types.ts +0 -69
- package/src/utils.tsx +0 -287
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface UseImageProps {
|
|
2
|
+
url: string;
|
|
3
|
+
crossOrigin?: string;
|
|
4
|
+
}
|
|
5
|
+
export interface UseImageResults {
|
|
6
|
+
image?: HTMLImageElement;
|
|
7
|
+
width: number;
|
|
8
|
+
height: number;
|
|
9
|
+
status: string;
|
|
10
|
+
}
|
|
11
|
+
declare const useImage: ({ url, crossOrigin }: UseImageProps) => UseImageResults;
|
|
12
|
+
export default useImage;
|
|
13
|
+
//# sourceMappingURL=useImage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useImage.d.ts","sourceRoot":"","sources":["../../../hooks/useImage.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,gBAAgB,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAmDD,QAAA,MAAM,QAAQ,GAAI,sBAAsB,aAAa,oBAgDpD,CAAC;AAEF,eAAe,QAAQ,CAAC"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
// Global cache to share images across all component instances
|
|
3
|
+
const imageCache = new Map();
|
|
4
|
+
const loadImage = (url, crossOrigin) => {
|
|
5
|
+
const existing = imageCache.get(url);
|
|
6
|
+
if (existing) {
|
|
7
|
+
return existing;
|
|
8
|
+
}
|
|
9
|
+
const img = new Image();
|
|
10
|
+
img.crossOrigin = crossOrigin || "anonymous";
|
|
11
|
+
const entry = {
|
|
12
|
+
image: img,
|
|
13
|
+
status: "loading",
|
|
14
|
+
width: 0,
|
|
15
|
+
height: 0,
|
|
16
|
+
subscribers: new Set(),
|
|
17
|
+
};
|
|
18
|
+
imageCache.set(url, entry);
|
|
19
|
+
const onload = () => {
|
|
20
|
+
entry.status = "loaded";
|
|
21
|
+
entry.width = img.width;
|
|
22
|
+
entry.height = img.height;
|
|
23
|
+
entry.subscribers.forEach((callback) => callback(entry));
|
|
24
|
+
};
|
|
25
|
+
const onerror = () => {
|
|
26
|
+
entry.status = "failed";
|
|
27
|
+
entry.subscribers.forEach((callback) => callback(entry));
|
|
28
|
+
};
|
|
29
|
+
img.addEventListener("load", onload);
|
|
30
|
+
img.addEventListener("error", onerror);
|
|
31
|
+
img.src = url;
|
|
32
|
+
return entry;
|
|
33
|
+
};
|
|
34
|
+
const useImage = ({ url, crossOrigin }) => {
|
|
35
|
+
const [state, setState] = useState(() => {
|
|
36
|
+
if (!url) {
|
|
37
|
+
return {
|
|
38
|
+
image: undefined,
|
|
39
|
+
status: "loading",
|
|
40
|
+
width: 0,
|
|
41
|
+
height: 0,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
const entry = loadImage(url, crossOrigin);
|
|
45
|
+
return {
|
|
46
|
+
image: entry.status === "loaded" ? entry.image : undefined,
|
|
47
|
+
status: entry.status,
|
|
48
|
+
width: entry.width,
|
|
49
|
+
height: entry.height,
|
|
50
|
+
};
|
|
51
|
+
});
|
|
52
|
+
useEffect(() => {
|
|
53
|
+
if (!url)
|
|
54
|
+
return;
|
|
55
|
+
const entry = loadImage(url, crossOrigin);
|
|
56
|
+
const updateState = (entry) => {
|
|
57
|
+
setState({
|
|
58
|
+
image: entry.status === "loaded" ? entry.image : undefined,
|
|
59
|
+
status: entry.status,
|
|
60
|
+
width: entry.width,
|
|
61
|
+
height: entry.height,
|
|
62
|
+
});
|
|
63
|
+
};
|
|
64
|
+
// Subscribe to updates
|
|
65
|
+
entry.subscribers.add(updateState);
|
|
66
|
+
// If already loaded, update immediately
|
|
67
|
+
if (entry.status !== "loading") {
|
|
68
|
+
updateState(entry);
|
|
69
|
+
}
|
|
70
|
+
return () => {
|
|
71
|
+
entry.subscribers.delete(updateState);
|
|
72
|
+
};
|
|
73
|
+
}, [url, crossOrigin]);
|
|
74
|
+
return state;
|
|
75
|
+
};
|
|
76
|
+
export default useImage;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
export interface PaginationProps {
|
|
3
|
+
/**
|
|
4
|
+
* No of items in each page
|
|
5
|
+
*/
|
|
6
|
+
pageSize: number;
|
|
7
|
+
/**
|
|
8
|
+
* Initial current page index. Start from 1
|
|
9
|
+
*/
|
|
10
|
+
initialCurrentPage?: number;
|
|
11
|
+
/**
|
|
12
|
+
* Total number of rows
|
|
13
|
+
*/
|
|
14
|
+
total: number;
|
|
15
|
+
/**
|
|
16
|
+
* Callback when page is changed
|
|
17
|
+
*/
|
|
18
|
+
onChange?: (page: number) => void;
|
|
19
|
+
/**
|
|
20
|
+
* Pagination Component
|
|
21
|
+
*/
|
|
22
|
+
component?: React.FC<PaginationComponentProps> | React.ComponentClass<PaginationComponentProps>;
|
|
23
|
+
}
|
|
24
|
+
export type PaginationComponentProps = Omit<PaginationResults, "paginationComponent">;
|
|
25
|
+
export interface PaginationResults {
|
|
26
|
+
/**
|
|
27
|
+
* Current page number
|
|
28
|
+
*/
|
|
29
|
+
currentPage: number;
|
|
30
|
+
/**
|
|
31
|
+
* Total pages
|
|
32
|
+
*/
|
|
33
|
+
totalPages: number;
|
|
34
|
+
/**
|
|
35
|
+
* No of items in each page
|
|
36
|
+
*/
|
|
37
|
+
pageSize: number;
|
|
38
|
+
/**
|
|
39
|
+
* Pagination component
|
|
40
|
+
*/
|
|
41
|
+
paginationComponent: React.ReactNode;
|
|
42
|
+
/**
|
|
43
|
+
* Navigate to next page
|
|
44
|
+
*/
|
|
45
|
+
nextPage: () => void;
|
|
46
|
+
/**
|
|
47
|
+
* Navigate to prev page
|
|
48
|
+
*/
|
|
49
|
+
prevPage: () => void;
|
|
50
|
+
/**
|
|
51
|
+
* Navigate to first page
|
|
52
|
+
*/
|
|
53
|
+
goToFirst: () => void;
|
|
54
|
+
/**
|
|
55
|
+
* Navigate to last page
|
|
56
|
+
*/
|
|
57
|
+
goToLast: () => void;
|
|
58
|
+
/**
|
|
59
|
+
* Navigate to specific page
|
|
60
|
+
*/
|
|
61
|
+
goToPage: (page: number) => void;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Pagination hook
|
|
65
|
+
* @param props
|
|
66
|
+
*/
|
|
67
|
+
declare const usePagination: (props: PaginationProps) => PaginationResults;
|
|
68
|
+
export default usePagination;
|
|
69
|
+
//# sourceMappingURL=usePagination.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usePagination.d.ts","sourceRoot":"","sources":["../../../hooks/usePagination.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA6B,MAAM,OAAO,CAAC;AAElD,MAAM,WAAW,eAAe;IAC9B;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC;;OAEG;IACH,SAAS,CAAC,EACN,KAAK,CAAC,EAAE,CAAC,wBAAwB,CAAC,GAClC,KAAK,CAAC,cAAc,CAAC,wBAAwB,CAAC,CAAC;CACpD;AAED,MAAM,MAAM,wBAAwB,GAAG,IAAI,CACzC,iBAAiB,EACjB,qBAAqB,CACtB,CAAC;AAEF,MAAM,WAAW,iBAAiB;IAChC;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,mBAAmB,EAAE,KAAK,CAAC,SAAS,CAAC;IACrC;;OAEG;IACH,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB;;OAEG;IACH,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB;;OAEG;IACH,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB;;OAEG;IACH,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB;;OAEG;IACH,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAClC;AAED;;;GAGG;AACH,QAAA,MAAM,aAAa,GAAI,OAAO,eAAe,KAAG,iBAsC/C,CAAC;AAuCF,eAAe,aAAa,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import React, { useEffect, useState } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Pagination hook
|
|
4
|
+
* @param props
|
|
5
|
+
*/
|
|
6
|
+
const usePagination = (props) => {
|
|
7
|
+
const { initialCurrentPage = 1, pageSize = 10, total = 0, onChange, component = PaginationComponent, } = props;
|
|
8
|
+
const [currentPage, setCurrentPage] = useState(initialCurrentPage);
|
|
9
|
+
const totalPages = Math.ceil(total / pageSize);
|
|
10
|
+
const nextPage = () => setCurrentPage((prev) => Math.min(prev + 1, totalPages));
|
|
11
|
+
const prevPage = () => setCurrentPage((prev) => Math.max(prev - 1, 1));
|
|
12
|
+
const goToFirst = () => setCurrentPage(1);
|
|
13
|
+
const goToLast = () => setCurrentPage(totalPages);
|
|
14
|
+
const goToPage = (page) => setCurrentPage(page);
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
onChange && onChange(currentPage);
|
|
17
|
+
}, [currentPage]);
|
|
18
|
+
const pageProps = {
|
|
19
|
+
currentPage,
|
|
20
|
+
totalPages,
|
|
21
|
+
nextPage,
|
|
22
|
+
prevPage,
|
|
23
|
+
goToFirst,
|
|
24
|
+
goToLast,
|
|
25
|
+
goToPage,
|
|
26
|
+
pageSize,
|
|
27
|
+
};
|
|
28
|
+
const paginationComponent = React.createElement(component, pageProps);
|
|
29
|
+
return {
|
|
30
|
+
paginationComponent,
|
|
31
|
+
...pageProps,
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
const PaginationComponent = ({ currentPage, goToFirst, goToLast, goToPage, totalPages, nextPage, prevPage, }) => {
|
|
35
|
+
const pages = [];
|
|
36
|
+
for (let i = 1; i <= totalPages; i++) {
|
|
37
|
+
const isActive = currentPage === i;
|
|
38
|
+
pages.push(React.createElement("button", { onClick: () => goToPage(i) }, isActive ? React.createElement("strong", null, i) : i));
|
|
39
|
+
}
|
|
40
|
+
return (React.createElement("div", null,
|
|
41
|
+
React.createElement("button", { onClick: goToFirst, disabled: currentPage === 1 }, "First page"),
|
|
42
|
+
React.createElement("button", { onClick: prevPage, disabled: currentPage === 1 }, "Prev page"),
|
|
43
|
+
pages,
|
|
44
|
+
React.createElement("button", { onClick: nextPage, disabled: currentPage === totalPages }, "Next page"),
|
|
45
|
+
React.createElement("button", { onClick: goToLast, disabled: currentPage === totalPages }, "Last page")));
|
|
46
|
+
};
|
|
47
|
+
export default usePagination;
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import type React from "react";
|
|
2
|
+
import type { GridRef, ViewPortProps } from "./../Grid";
|
|
3
|
+
import type { HiddenType } from "./../helpers";
|
|
4
|
+
export interface IProps {
|
|
5
|
+
/**
|
|
6
|
+
* Used to access grid functions
|
|
7
|
+
*/
|
|
8
|
+
gridRef: React.MutableRefObject<GridRef | null>;
|
|
9
|
+
/**
|
|
10
|
+
* Value getter for a cell
|
|
11
|
+
*/
|
|
12
|
+
getTextFormat?: (rowIndex: number, columnIndex: number) => any;
|
|
13
|
+
/**
|
|
14
|
+
* Visible rows when the grid is first visible, Since we do not know how many rows can fit
|
|
15
|
+
*/
|
|
16
|
+
initialVisibleRows?: number;
|
|
17
|
+
initialVisibleColumns?: number;
|
|
18
|
+
/**
|
|
19
|
+
* Restrict column width by this number
|
|
20
|
+
*/
|
|
21
|
+
minColumnDimension?: number;
|
|
22
|
+
minRowDimension?: number;
|
|
23
|
+
/**
|
|
24
|
+
* Cell padding, used for width calculation
|
|
25
|
+
*/
|
|
26
|
+
cellSpacing?: number;
|
|
27
|
+
/**
|
|
28
|
+
* Scroll timeout
|
|
29
|
+
*/
|
|
30
|
+
timeout?: number;
|
|
31
|
+
/**
|
|
32
|
+
* Calculate width and resize the grid on scroll
|
|
33
|
+
*/
|
|
34
|
+
resizeOnScroll?: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Font used to calculate width
|
|
37
|
+
*/
|
|
38
|
+
fontFamily?: string;
|
|
39
|
+
fontSize?: number;
|
|
40
|
+
fontWeight?: string;
|
|
41
|
+
fontStyle?: string;
|
|
42
|
+
/**
|
|
43
|
+
* Strategy used to calculate column width
|
|
44
|
+
* lazy = visible rows
|
|
45
|
+
* full = all rows
|
|
46
|
+
*
|
|
47
|
+
* columns are always lazy
|
|
48
|
+
*/
|
|
49
|
+
resizeStrategy?: ResizeStrategy;
|
|
50
|
+
/**
|
|
51
|
+
* No of rows in teh grid
|
|
52
|
+
*/
|
|
53
|
+
rowCount?: number;
|
|
54
|
+
columnCount?: number;
|
|
55
|
+
/**
|
|
56
|
+
* Enable autoresize
|
|
57
|
+
*/
|
|
58
|
+
autoResize?: boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Hidden rows
|
|
61
|
+
*/
|
|
62
|
+
isHiddenRow: HiddenType;
|
|
63
|
+
/**
|
|
64
|
+
* Hidden columns
|
|
65
|
+
*/
|
|
66
|
+
isHiddenColumn: HiddenType;
|
|
67
|
+
/**
|
|
68
|
+
* Number of frozen rows
|
|
69
|
+
*/
|
|
70
|
+
frozenRows?: number;
|
|
71
|
+
frozenColumns?: number;
|
|
72
|
+
/**
|
|
73
|
+
* Current scaling factor
|
|
74
|
+
*/
|
|
75
|
+
scale?: number;
|
|
76
|
+
/**
|
|
77
|
+
* Get text value
|
|
78
|
+
*/
|
|
79
|
+
getTextValue?: (rowIndex: number, columnIndex: number) => string | undefined;
|
|
80
|
+
}
|
|
81
|
+
export type ResizeStrategy = "lazy" | "full";
|
|
82
|
+
export interface TextDimensions {
|
|
83
|
+
width: number;
|
|
84
|
+
height: number;
|
|
85
|
+
}
|
|
86
|
+
export type SizeType = {
|
|
87
|
+
[key: number]: number;
|
|
88
|
+
};
|
|
89
|
+
export interface TextFormat {
|
|
90
|
+
bold?: boolean;
|
|
91
|
+
spacing?: number;
|
|
92
|
+
fontSize?: number;
|
|
93
|
+
fontFamily?: string;
|
|
94
|
+
italic?: boolean;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Auto sizer hook
|
|
98
|
+
* @param param
|
|
99
|
+
*
|
|
100
|
+
* TODO
|
|
101
|
+
* Dynamically resize columns after user has scrolled down/view port changed ?
|
|
102
|
+
*/
|
|
103
|
+
declare const useAutoSizer: ({ gridRef, getTextFormat, initialVisibleRows, initialVisibleColumns, cellSpacing, minColumnDimension, minRowDimension, timeout, resizeStrategy, rowCount, columnCount, resizeOnScroll, fontFamily, fontSize, fontWeight, fontStyle, autoResize, frozenRows, frozenColumns, scale, isHiddenRow, isHiddenColumn, getTextValue, }: IProps) => {
|
|
104
|
+
getColumnWidth: (columnIndex: number) => number;
|
|
105
|
+
getRowHeight: (rowIndex: number) => number;
|
|
106
|
+
onViewChange: (cells: ViewPortProps) => void;
|
|
107
|
+
getCellDimensions: (rowIndex: number, columnIndex: number, textOverride?: string) => {
|
|
108
|
+
width: number;
|
|
109
|
+
height: number;
|
|
110
|
+
};
|
|
111
|
+
columnWidth?: ((columnIndex: number) => number) | undefined;
|
|
112
|
+
};
|
|
113
|
+
export default useAutoSizer;
|
|
114
|
+
//# sourceMappingURL=useSizer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSizer.d.ts","sourceRoot":"","sources":["../../../hooks/useSizer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,OAAO,KAAK,EAAiB,OAAO,EAAC,aAAa,EAAE,MAAM,WAAW,CAAC;AACtE,OAAO,KAAK,EACV,UAAU,EAAC,MAAM,cAAc,CAAC;AAOlC,MAAM,WAAW,MAAM;IACrB;;OAEG;IACH,OAAO,EAAE,KAAK,CAAC,gBAAgB,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IAChD;;OAEG;IACH,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,GAAG,CAAC;IAC/D;;OAEG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B;;OAEG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;OAEG;IACH,WAAW,EAAE,UAAU,CAAC;IACxB;;OAEG;IACH,cAAc,EAAE,UAAU,CAAC;IAC3B;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;CAC9E;AAED,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,MAAM,CAAC;AAE7C,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,QAAQ,GAAG;IACrB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,WAAW,UAAU;IACzB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAID;;;;;;GAMG;AACH,QAAA,MAAM,YAAY,GAAI,gUAwBnB,MAAM;kCAgFS,MAAM;6BA8CT,MAAM;0BA0CT,aAAa;kCA/HV,MAAM,eAAe,MAAM,iBAAiB,MAAM;;;;iCAuC/C,MAAM;CAuHvB,CAAC;AAEF,eAAe,YAAY,CAAC"}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
2
|
+
import invariant from "tiny-invariant";
|
|
3
|
+
import { autoSizerCanvas, debounce, isNull, } from "./../helpers";
|
|
4
|
+
const defaultGetText = (text) => text;
|
|
5
|
+
/**
|
|
6
|
+
* Auto sizer hook
|
|
7
|
+
* @param param
|
|
8
|
+
*
|
|
9
|
+
* TODO
|
|
10
|
+
* Dynamically resize columns after user has scrolled down/view port changed ?
|
|
11
|
+
*/
|
|
12
|
+
const useAutoSizer = ({ gridRef, getTextFormat, initialVisibleRows = 20, initialVisibleColumns = 20, cellSpacing = 10, minColumnDimension = 60, minRowDimension = 60, timeout = 300, resizeStrategy = "lazy", rowCount, columnCount, resizeOnScroll = true, fontFamily = "Arial", fontSize = 12, fontWeight = "", fontStyle = "", autoResize = true, frozenRows = 0, frozenColumns = 0, scale = 1, isHiddenRow, isHiddenColumn, getTextValue = defaultGetText, }) => {
|
|
13
|
+
invariant(!(resizeStrategy === "full" && rowCount === void 0), "Row count should be specified if resize stragtegy is full");
|
|
14
|
+
const autoSizer = useRef(autoSizerCanvas);
|
|
15
|
+
const [viewport, setViewport] = useState({
|
|
16
|
+
rowStartIndex: 0,
|
|
17
|
+
rowStopIndex: 0,
|
|
18
|
+
columnStartIndex: 0,
|
|
19
|
+
columnStopIndex: 0,
|
|
20
|
+
visibleRowStartIndex: 0,
|
|
21
|
+
visibleRowStopIndex: 0,
|
|
22
|
+
visibleColumnStartIndex: 0,
|
|
23
|
+
visibleColumnStopIndex: 0,
|
|
24
|
+
});
|
|
25
|
+
const isMounted = useRef(false);
|
|
26
|
+
const handleResize = useCallback(({ rowIndex, columnIndex }) => {
|
|
27
|
+
gridRef.current &&
|
|
28
|
+
gridRef.current.resetAfterIndices({ rowIndex, columnIndex });
|
|
29
|
+
}, []);
|
|
30
|
+
const debounceResizer = useRef(null);
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
isMounted.current = true;
|
|
33
|
+
debounceResizer.current = debounce(handleResize, timeout);
|
|
34
|
+
}, []);
|
|
35
|
+
/* Update any styles, fonts if necessary */
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
autoSizer.current.setFont({ fontFamily, fontSize, fontWeight, fontStyle });
|
|
38
|
+
}, [fontFamily, fontSize, fontWeight, fontStyle]);
|
|
39
|
+
/**
|
|
40
|
+
* Get width of a single cell
|
|
41
|
+
*/
|
|
42
|
+
const getCellDimensions = useCallback((rowIndex, columnIndex, textOverride) => {
|
|
43
|
+
const cell = { rowIndex, columnIndex };
|
|
44
|
+
const textFormat = getTextFormat?.(cell.rowIndex, cell.columnIndex);
|
|
45
|
+
const text = textOverride ?? getTextValue(cell.rowIndex, cell.columnIndex);
|
|
46
|
+
let width = textFormat?.spacing ?? 0;
|
|
47
|
+
let height = textFormat?.spacing ?? 0;
|
|
48
|
+
/* Check if its null */
|
|
49
|
+
if (!isNull(text) && text !== void 0) {
|
|
50
|
+
/* Reset fonts */
|
|
51
|
+
autoSizer.current.reset();
|
|
52
|
+
if (textFormat) {
|
|
53
|
+
const isBold = textFormat.bold;
|
|
54
|
+
autoSizer.current.setFont({
|
|
55
|
+
fontWeight: isBold ? "bold" : "",
|
|
56
|
+
fontSize: (textFormat.fontSize ?? fontSize) * scale,
|
|
57
|
+
fontFamily: textFormat.fontFamily ?? fontFamily,
|
|
58
|
+
fontStyle: textFormat.italic ? "italic" : "",
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
const metrics = autoSizer.current.measureText(text);
|
|
62
|
+
if (metrics) {
|
|
63
|
+
width += Math.ceil(metrics.width) + cellSpacing;
|
|
64
|
+
height += Math.ceil(metrics.height) + cellSpacing;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return { width, height };
|
|
68
|
+
}, [scale, getTextFormat, cellSpacing, getTextValue]);
|
|
69
|
+
/**
|
|
70
|
+
* Calculate column width
|
|
71
|
+
*/
|
|
72
|
+
const getColumnWidth = useCallback((columnIndex) => {
|
|
73
|
+
const { rowStartIndex = 0, rowStopIndex = 0 } = viewport ?? {};
|
|
74
|
+
const visibleRows = resizeStrategy === "full"
|
|
75
|
+
? rowCount
|
|
76
|
+
: rowStopIndex || initialVisibleRows;
|
|
77
|
+
let start = resizeStrategy === "full" ? 0 : rowStartIndex;
|
|
78
|
+
let maxWidth = minColumnDimension;
|
|
79
|
+
/* Calculate for frozen rows */
|
|
80
|
+
for (let i = 0; i < frozenRows; i++) {
|
|
81
|
+
if (isHiddenRow(i)) {
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
const { width } = getCellDimensions(i, columnIndex);
|
|
85
|
+
if (width > maxWidth)
|
|
86
|
+
maxWidth = width;
|
|
87
|
+
}
|
|
88
|
+
/* Loop through all visible rows */
|
|
89
|
+
while (start < visibleRows) {
|
|
90
|
+
if (isHiddenRow(start)) {
|
|
91
|
+
start++;
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
const { width } = getCellDimensions(start, columnIndex);
|
|
95
|
+
if (width > maxWidth)
|
|
96
|
+
maxWidth = width;
|
|
97
|
+
start++;
|
|
98
|
+
}
|
|
99
|
+
return maxWidth / scale;
|
|
100
|
+
}, [
|
|
101
|
+
viewport,
|
|
102
|
+
initialVisibleRows,
|
|
103
|
+
minColumnDimension,
|
|
104
|
+
frozenRows,
|
|
105
|
+
scale,
|
|
106
|
+
getCellDimensions,
|
|
107
|
+
isHiddenRow,
|
|
108
|
+
]);
|
|
109
|
+
/**
|
|
110
|
+
* Calculate Row height
|
|
111
|
+
*/
|
|
112
|
+
const getRowHeight = useCallback((rowIndex) => {
|
|
113
|
+
const { columnStartIndex = 0, columnStopIndex = 0 } = viewport ?? {};
|
|
114
|
+
const visibleColumns = resizeStrategy === "full"
|
|
115
|
+
? columnCount
|
|
116
|
+
: columnStopIndex || initialVisibleColumns;
|
|
117
|
+
let start = resizeStrategy === "full" ? 0 : columnStartIndex;
|
|
118
|
+
let maxHeight = minRowDimension;
|
|
119
|
+
/* Calculate for frozen rows */
|
|
120
|
+
for (let i = 0; i < frozenColumns; i++) {
|
|
121
|
+
if (isHiddenColumn(i)) {
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
const { height } = getCellDimensions(i, rowIndex);
|
|
125
|
+
if (height > maxHeight)
|
|
126
|
+
maxHeight = height;
|
|
127
|
+
}
|
|
128
|
+
/* Loop through all visible rows */
|
|
129
|
+
while (start < visibleColumns) {
|
|
130
|
+
if (isHiddenRow(start)) {
|
|
131
|
+
start++;
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
const { height } = getCellDimensions(rowIndex, start);
|
|
135
|
+
if (height > maxHeight)
|
|
136
|
+
maxHeight = height;
|
|
137
|
+
start++;
|
|
138
|
+
}
|
|
139
|
+
return maxHeight / scale;
|
|
140
|
+
}, [
|
|
141
|
+
viewport,
|
|
142
|
+
initialVisibleColumns,
|
|
143
|
+
minRowDimension,
|
|
144
|
+
isHiddenColumn,
|
|
145
|
+
frozenColumns,
|
|
146
|
+
scale,
|
|
147
|
+
getCellDimensions,
|
|
148
|
+
]);
|
|
149
|
+
const handleViewChange = useCallback((cells) => {
|
|
150
|
+
/* Update viewport cells */
|
|
151
|
+
setViewport(cells);
|
|
152
|
+
/* Check if viewport has changed */
|
|
153
|
+
if (resizeStrategy === "full" ||
|
|
154
|
+
!resizeOnScroll ||
|
|
155
|
+
(cells.rowStartIndex === viewport.rowStartIndex &&
|
|
156
|
+
cells.columnStartIndex === viewport.columnStartIndex))
|
|
157
|
+
return;
|
|
158
|
+
if (gridRef.current) {
|
|
159
|
+
/* During first mount, column width is calculated. Do not re-calculate */
|
|
160
|
+
if (!isMounted.current)
|
|
161
|
+
return;
|
|
162
|
+
debounceResizer.current({
|
|
163
|
+
rowIndex: cells.rowStartIndex,
|
|
164
|
+
columnIndex: cells.columnStartIndex,
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
}, [resizeOnScroll, viewport, resizeStrategy]);
|
|
168
|
+
return {
|
|
169
|
+
...(autoResize ? { columnWidth: getColumnWidth } : undefined),
|
|
170
|
+
getColumnWidth,
|
|
171
|
+
getRowHeight,
|
|
172
|
+
onViewChange: handleViewChange,
|
|
173
|
+
getCellDimensions,
|
|
174
|
+
};
|
|
175
|
+
};
|
|
176
|
+
export default useAutoSizer;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { CellInterface, GridRef } from "../Grid";
|
|
3
|
+
export interface TooltipOptions {
|
|
4
|
+
/**
|
|
5
|
+
* Tooltip component
|
|
6
|
+
*/
|
|
7
|
+
getTooltip?: (cell: CellInterface | null) => React.ElementType | null;
|
|
8
|
+
/**
|
|
9
|
+
* Grid references
|
|
10
|
+
*/
|
|
11
|
+
gridRef: React.MutableRefObject<GridRef | null>;
|
|
12
|
+
}
|
|
13
|
+
export interface TooltipResults {
|
|
14
|
+
/**
|
|
15
|
+
* Tooltip component to inject into the page
|
|
16
|
+
*/
|
|
17
|
+
tooltipComponent: React.ReactElement | null;
|
|
18
|
+
/**
|
|
19
|
+
* Mousemove listener to align tooltip
|
|
20
|
+
*/
|
|
21
|
+
onMouseMove: ((e: React.MouseEvent<HTMLElement>) => void) | undefined;
|
|
22
|
+
/**
|
|
23
|
+
* Mouse leave listener to hide tooltip
|
|
24
|
+
*/
|
|
25
|
+
onMouseLeave: ((e: React.MouseEvent<HTMLElement>) => void) | undefined;
|
|
26
|
+
}
|
|
27
|
+
export interface DefaultTooltipProps {
|
|
28
|
+
/**
|
|
29
|
+
* Tooltip x position
|
|
30
|
+
*/
|
|
31
|
+
x?: number;
|
|
32
|
+
/**
|
|
33
|
+
* Tooltip y position
|
|
34
|
+
*/
|
|
35
|
+
y?: number;
|
|
36
|
+
width?: number;
|
|
37
|
+
height?: number;
|
|
38
|
+
scrollLeft?: number;
|
|
39
|
+
scrollTop?: number;
|
|
40
|
+
}
|
|
41
|
+
declare const useTooltip: ({ gridRef, getTooltip, }: TooltipOptions) => TooltipResults;
|
|
42
|
+
export default useTooltip;
|
|
43
|
+
//# sourceMappingURL=useTooltip.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useTooltip.d.ts","sourceRoot":"","sources":["../../../hooks/useTooltip.tsx"],"names":[],"mappings":"AAAA,OAAO,KAMN,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAGtD,MAAM,WAAW,cAAc;IAC7B;;OAEG;IACH,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI,KAAK,KAAK,CAAC,WAAW,GAAG,IAAI,CAAC;IACtE;;OAEG;IACH,OAAO,EAAE,KAAK,CAAC,gBAAgB,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;CACjD;AAED,MAAM,WAAW,cAAc;IAC7B;;OAEG;IACH,gBAAgB,EAAE,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC;IAC5C;;OAEG;IACH,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IACtE;;OAEG;IACH,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;CACxE;AAED,MAAM,WAAW,mBAAmB;IAClC;;OAEG;IACH,CAAC,CAAC,EAAE,MAAM,CAAC;IACX;;OAEG;IACH,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAmCD,QAAA,MAAM,UAAU,GAAI,0BAGjB,cAAc,KAAG,cAmFnB,CAAC;AAEF,eAAe,UAAU,CAAC"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import React, { useCallback, useEffect, useMemo, useRef, useState, } from "react";
|
|
2
|
+
import { debounce, throttle } from "../helpers";
|
|
3
|
+
const DefaultTooltipComponent = ({ x = 0, y = 0, scrollLeft = 0, scrollTop = 0, width = 0, height = 0, }) => {
|
|
4
|
+
const posX = x + width - scrollLeft;
|
|
5
|
+
const posY = y - scrollTop;
|
|
6
|
+
return (React.createElement("div", { style: {
|
|
7
|
+
position: "absolute",
|
|
8
|
+
left: 0,
|
|
9
|
+
top: 0,
|
|
10
|
+
transform: `translate(${posX}px, ${posY}px)`,
|
|
11
|
+
maxWidth: 200,
|
|
12
|
+
minWidth: 160,
|
|
13
|
+
background: "white",
|
|
14
|
+
boxShadow: "0 4px 8px 3px rgba(60,64,67,.15)",
|
|
15
|
+
padding: 12,
|
|
16
|
+
borderRadius: 4,
|
|
17
|
+
fontSize: 13,
|
|
18
|
+
} }, x));
|
|
19
|
+
};
|
|
20
|
+
const getDefaultTooltip = () => DefaultTooltipComponent;
|
|
21
|
+
const useTooltip = ({ gridRef, getTooltip = getDefaultTooltip, }) => {
|
|
22
|
+
const [activeCell, setActiveCell] = useState(null);
|
|
23
|
+
const isTooltipActive = useRef(false);
|
|
24
|
+
const activeCellRef = useRef(activeCell);
|
|
25
|
+
const [tooltipPosition, setTooltipPosition] = useState({});
|
|
26
|
+
const showTooltip = !!activeCell;
|
|
27
|
+
const TooltipComponent = useMemo(() => {
|
|
28
|
+
return getTooltip(activeCell);
|
|
29
|
+
}, [activeCell, getTooltip]);
|
|
30
|
+
const handleTooltipMouseEnter = useCallback(() => {
|
|
31
|
+
isTooltipActive.current = true;
|
|
32
|
+
}, []);
|
|
33
|
+
const handleTooltipMouseLeave = useCallback(() => {
|
|
34
|
+
isTooltipActive.current = false;
|
|
35
|
+
setActiveCell(null);
|
|
36
|
+
}, []);
|
|
37
|
+
const tooltipComponent = showTooltip && TooltipComponent ? (React.createElement(TooltipComponent, { ...tooltipPosition, onMouseEnter: handleTooltipMouseEnter, onMouseLeave: handleTooltipMouseLeave })) : null;
|
|
38
|
+
const handleMouseMove = useCallback((e) => {
|
|
39
|
+
if (!gridRef.current)
|
|
40
|
+
return;
|
|
41
|
+
const coords = gridRef.current.getCellCoordsFromOffset(e.clientX, e.clientY);
|
|
42
|
+
if (!coords)
|
|
43
|
+
return;
|
|
44
|
+
const { rowIndex, columnIndex } = coords;
|
|
45
|
+
/* Exit if its the same cell */
|
|
46
|
+
if (activeCellRef.current &&
|
|
47
|
+
activeCellRef.current.rowIndex === rowIndex &&
|
|
48
|
+
activeCellRef.current.columnIndex === columnIndex)
|
|
49
|
+
return;
|
|
50
|
+
const pos = gridRef.current.getCellOffsetFromCoords(coords);
|
|
51
|
+
const scrollPosition = gridRef.current.getScrollPosition();
|
|
52
|
+
setTooltipPosition({
|
|
53
|
+
...pos,
|
|
54
|
+
...scrollPosition,
|
|
55
|
+
});
|
|
56
|
+
setActiveCell({ rowIndex, columnIndex });
|
|
57
|
+
}, []);
|
|
58
|
+
const handleMouseLeave = useCallback(() => {
|
|
59
|
+
if (isTooltipActive.current)
|
|
60
|
+
return;
|
|
61
|
+
setActiveCell(null);
|
|
62
|
+
}, []);
|
|
63
|
+
/* Raf throttler */
|
|
64
|
+
const mouseMoveThrottler = useRef(undefined);
|
|
65
|
+
const mouseLeaveThrottler = useRef(undefined);
|
|
66
|
+
useEffect(() => {
|
|
67
|
+
mouseMoveThrottler.current = throttle(handleMouseMove, 100);
|
|
68
|
+
mouseLeaveThrottler.current = debounce(handleMouseLeave, 2000);
|
|
69
|
+
}, []);
|
|
70
|
+
/* Update activecell ref */
|
|
71
|
+
useEffect(() => {
|
|
72
|
+
activeCellRef.current = activeCell;
|
|
73
|
+
}, [activeCell]);
|
|
74
|
+
return {
|
|
75
|
+
tooltipComponent,
|
|
76
|
+
onMouseMove: mouseMoveThrottler.current,
|
|
77
|
+
onMouseLeave: mouseLeaveThrottler.current,
|
|
78
|
+
};
|
|
79
|
+
};
|
|
80
|
+
export default useTooltip;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type React from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Spec: https://tools.ietf.org/html/rfc6902
|
|
4
|
+
*
|
|
5
|
+
* add, { "op": "add", "path": ["data", "1,2"], "value": "hello world" }
|
|
6
|
+
* remove { "op": "remove", "path": ["data", "1,2"], "value": "hello world" }
|
|
7
|
+
* replace { "op": "replace", "path": ["data", "1,2"], "value": "hello world" }
|
|
8
|
+
* move { "op": "move", "from": "/a/b/c", "path": "/a/b/d" }
|
|
9
|
+
* copy
|
|
10
|
+
*/
|
|
11
|
+
export interface UndoProps {
|
|
12
|
+
enableGlobalKeyHandlers?: boolean;
|
|
13
|
+
onRedo?: (patches: any) => void;
|
|
14
|
+
onUndo?: (patches: any) => void;
|
|
15
|
+
identifier?: (patch: any) => any;
|
|
16
|
+
}
|
|
17
|
+
export interface UndoManager {
|
|
18
|
+
undo: () => void;
|
|
19
|
+
redo: () => void;
|
|
20
|
+
add: (patches: any) => void;
|
|
21
|
+
replace: (patches: any, inversePatches: any) => void;
|
|
22
|
+
canUndo: boolean;
|
|
23
|
+
canRedo: boolean;
|
|
24
|
+
onKeyDown?: (e: React.KeyboardEvent<HTMLDivElement>) => void;
|
|
25
|
+
}
|
|
26
|
+
export interface PatchInterface<T> {
|
|
27
|
+
patches: T[];
|
|
28
|
+
inversePatches: T[];
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Undo/Redo hook
|
|
32
|
+
* @param
|
|
33
|
+
*/
|
|
34
|
+
declare const useUndo: <T>(props?: UndoProps) => UndoManager;
|
|
35
|
+
export default useUndo;
|
|
36
|
+
//# sourceMappingURL=useUndo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useUndo.d.ts","sourceRoot":"","sources":["../../../hooks/useUndo.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B;;;;;;;;GAQG;AAEH,MAAM,WAAW,SAAS;IACxB,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,IAAI,CAAC;IAChC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,IAAI,CAAC;IAChC,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,GAAG,CAAC;CAClC;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,GAAG,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,IAAI,CAAC;IAC5B,OAAO,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,cAAc,EAAE,GAAG,KAAK,IAAI,CAAC;IACrD,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,cAAc,CAAC,KAAK,IAAI,CAAC;CAC9D;AAED,MAAM,WAAW,cAAc,CAAC,CAAC;IAC/B,OAAO,EAAE,CAAC,EAAE,CAAC;IACb,cAAc,EAAE,CAAC,EAAE,CAAC;CACrB;AAED;;;GAGG;AACH,QAAA,MAAM,OAAO,GAAI,CAAC,EAAE,QAAO,SAAc,KAAG,WAsF3C,CAAC;AAEF,eAAe,OAAO,CAAC"}
|