@glideappsfinal/glide-data-grid-source 6.0.9
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 +21 -0
- package/README.md +13 -0
- package/dist/cjs/index.js +6 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/use-async-data-source.js +92 -0
- package/dist/cjs/use-async-data-source.js.map +1 -0
- package/dist/cjs/use-collapsing-groups.js +105 -0
- package/dist/cjs/use-collapsing-groups.js.map +1 -0
- package/dist/cjs/use-column-sort.js +134 -0
- package/dist/cjs/use-column-sort.js.map +1 -0
- package/dist/cjs/use-movable-columns.js +66 -0
- package/dist/cjs/use-movable-columns.js.map +1 -0
- package/dist/cjs/use-undo-redo.js +168 -0
- package/dist/cjs/use-undo-redo.js.map +1 -0
- package/dist/dts/index.d.ts +6 -0
- package/dist/dts/index.d.ts.map +1 -0
- package/dist/dts/use-async-data-source.d.ts +9 -0
- package/dist/dts/use-async-data-source.d.ts.map +1 -0
- package/dist/dts/use-collapsing-groups.d.ts +8 -0
- package/dist/dts/use-collapsing-groups.d.ts.map +1 -0
- package/dist/dts/use-column-sort.d.ts +17 -0
- package/dist/dts/use-column-sort.d.ts.map +1 -0
- package/dist/dts/use-movable-columns.d.ts +5 -0
- package/dist/dts/use-movable-columns.d.ts.map +1 -0
- package/dist/dts/use-undo-redo.d.ts +11 -0
- package/dist/dts/use-undo-redo.d.ts.map +1 -0
- package/dist/esm/index.js +6 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/use-async-data-source.js +92 -0
- package/dist/esm/use-async-data-source.js.map +1 -0
- package/dist/esm/use-collapsing-groups.js +105 -0
- package/dist/esm/use-collapsing-groups.js.map +1 -0
- package/dist/esm/use-column-sort.js +134 -0
- package/dist/esm/use-column-sort.js.map +1 -0
- package/dist/esm/use-movable-columns.js +66 -0
- package/dist/esm/use-movable-columns.js.map +1 -0
- package/dist/esm/use-undo-redo.js +168 -0
- package/dist/esm/use-undo-redo.js.map +1 -0
- package/dist/tsconfig.cjs.tsbuildinfo +1 -0
- package/dist/tsconfig.esm.tsbuildinfo +1 -0
- package/package.json +61 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2021 typeguard, Inc.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<h1 align="center">
|
|
2
|
+
<img src="https://raw.githubusercontent.com/glideapps/glide-data-grid/master/icon.png" width="224px"/><br/>
|
|
3
|
+
<b>Glide Data Grid Source</b>
|
|
4
|
+
</h1>
|
|
5
|
+
<p align="center">This provides an easy to use data source for the Glide Data Grid which supports many convenient features such as sorting and menus out of the box.</p>
|
|
6
|
+
|
|
7
|
+
[](https://github.com/glideapps/glide-data-grid/releases)
|
|
8
|
+
[](https://reactjs.org)
|
|
9
|
+
[](https://bundlephobia.com/package/@glideapps/glide-data-grid-source)
|
|
10
|
+
[](https://github.com/glideapps/glide-data-grid/blob/main/LICENSE)
|
|
11
|
+
[](https://www.glideapps.com/jobs)
|
|
12
|
+
|
|
13
|
+

|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { useCollapsingGroups } from "./use-collapsing-groups.js";
|
|
2
|
+
export { useMoveableColumns } from "./use-movable-columns.js";
|
|
3
|
+
export { useColumnSort } from "./use-column-sort.js";
|
|
4
|
+
export { useAsyncDataSource } from "./use-async-data-source.js";
|
|
5
|
+
export { useUndoRedo } from "./use-undo-redo.js";
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { CompactSelection, GridCellKind, } from "@glideapps/glide-data-grid";
|
|
2
|
+
import range from "lodash/range.js";
|
|
3
|
+
import chunk from "lodash/chunk.js";
|
|
4
|
+
import React from "react";
|
|
5
|
+
export function useAsyncDataSource(pageSize, maxConcurrency, getRowData, toCell, onEdited, gridRef) {
|
|
6
|
+
pageSize = Math.max(pageSize, 1);
|
|
7
|
+
const loadingRef = React.useRef(CompactSelection.empty());
|
|
8
|
+
const dataRef = React.useRef([]);
|
|
9
|
+
const [visiblePages, setVisiblePages] = React.useState({ x: 0, y: 0, width: 0, height: 0 });
|
|
10
|
+
const visiblePagesRef = React.useRef(visiblePages);
|
|
11
|
+
visiblePagesRef.current = visiblePages;
|
|
12
|
+
const onVisibleRegionChanged = React.useCallback(r => {
|
|
13
|
+
setVisiblePages(cv => {
|
|
14
|
+
if (r.x === cv.x && r.y === cv.y && r.width === cv.width && r.height === cv.height)
|
|
15
|
+
return cv;
|
|
16
|
+
return r;
|
|
17
|
+
});
|
|
18
|
+
}, []);
|
|
19
|
+
const getCellContent = React.useCallback(cell => {
|
|
20
|
+
const [col, row] = cell;
|
|
21
|
+
const rowData = dataRef.current[row];
|
|
22
|
+
if (rowData !== undefined) {
|
|
23
|
+
return toCell(rowData, col);
|
|
24
|
+
}
|
|
25
|
+
return {
|
|
26
|
+
kind: GridCellKind.Loading,
|
|
27
|
+
allowOverlay: false,
|
|
28
|
+
};
|
|
29
|
+
}, [toCell]);
|
|
30
|
+
const loadPage = React.useCallback(async (page) => {
|
|
31
|
+
loadingRef.current = loadingRef.current.add(page);
|
|
32
|
+
const startIndex = page * pageSize;
|
|
33
|
+
const d = await getRowData([startIndex, (page + 1) * pageSize]);
|
|
34
|
+
const vr = visiblePagesRef.current;
|
|
35
|
+
const damageList = [];
|
|
36
|
+
const data = dataRef.current;
|
|
37
|
+
for (let i = 0; i < d.length; i++) {
|
|
38
|
+
data[i + startIndex] = d[i];
|
|
39
|
+
for (let col = vr.x; col <= vr.x + vr.width; col++) {
|
|
40
|
+
damageList.push({
|
|
41
|
+
cell: [col, i + startIndex],
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
gridRef.current?.updateCells(damageList);
|
|
46
|
+
}, [getRowData, gridRef, pageSize]);
|
|
47
|
+
const getCellsForSelection = React.useCallback((r) => {
|
|
48
|
+
return async () => {
|
|
49
|
+
const firstPage = Math.max(0, Math.floor(r.y / pageSize));
|
|
50
|
+
const lastPage = Math.floor((r.y + r.height) / pageSize);
|
|
51
|
+
for (const pageChunk of chunk(range(firstPage, lastPage + 1).filter(i => !loadingRef.current.hasIndex(i)), maxConcurrency)) {
|
|
52
|
+
await Promise.all(pageChunk.map(loadPage));
|
|
53
|
+
}
|
|
54
|
+
const result = [];
|
|
55
|
+
for (let y = r.y; y < r.y + r.height; y++) {
|
|
56
|
+
const row = [];
|
|
57
|
+
for (let x = r.x; x < r.x + r.width; x++) {
|
|
58
|
+
row.push(getCellContent([x, y]));
|
|
59
|
+
}
|
|
60
|
+
result.push(row);
|
|
61
|
+
}
|
|
62
|
+
return result;
|
|
63
|
+
};
|
|
64
|
+
}, [getCellContent, loadPage, maxConcurrency, pageSize]);
|
|
65
|
+
React.useEffect(() => {
|
|
66
|
+
const r = visiblePages;
|
|
67
|
+
const firstPage = Math.max(0, Math.floor((r.y - pageSize / 2) / pageSize));
|
|
68
|
+
const lastPage = Math.floor((r.y + r.height + pageSize / 2) / pageSize);
|
|
69
|
+
for (const page of range(firstPage, lastPage + 1)) {
|
|
70
|
+
if (loadingRef.current.hasIndex(page))
|
|
71
|
+
continue;
|
|
72
|
+
void loadPage(page);
|
|
73
|
+
}
|
|
74
|
+
}, [loadPage, pageSize, visiblePages]);
|
|
75
|
+
const onCellEdited = React.useCallback((cell, newVal) => {
|
|
76
|
+
const [, row] = cell;
|
|
77
|
+
const current = dataRef.current[row];
|
|
78
|
+
if (current === undefined)
|
|
79
|
+
return;
|
|
80
|
+
const result = onEdited(cell, newVal, current);
|
|
81
|
+
if (result !== undefined) {
|
|
82
|
+
dataRef.current[row] = result;
|
|
83
|
+
}
|
|
84
|
+
}, [onEdited]);
|
|
85
|
+
return {
|
|
86
|
+
getCellContent,
|
|
87
|
+
onVisibleRegionChanged,
|
|
88
|
+
onCellEdited,
|
|
89
|
+
getCellsForSelection,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=use-async-data-source.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-async-data-source.js","sourceRoot":"","sources":["../../src/use-async-data-source.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
export function useCollapsingGroups(props) {
|
|
3
|
+
const [collapsed, setCollapsed] = React.useState([]);
|
|
4
|
+
const [gridSelectionInner, setGridSelectionsInner] = React.useState(undefined);
|
|
5
|
+
const { columns: columnsIn, onGroupHeaderClicked: onGroupHeaderClickedIn, onGridSelectionChange: onGridSelectionChangeIn, getGroupDetails: getGroupDetailsIn, gridSelection: gridSelectionIn, freezeColumns = 0, theme, } = props;
|
|
6
|
+
const gridSelection = gridSelectionIn ?? gridSelectionInner;
|
|
7
|
+
const spans = React.useMemo(() => {
|
|
8
|
+
const result = [];
|
|
9
|
+
let current = [-1, -1];
|
|
10
|
+
let lastGroup;
|
|
11
|
+
for (let i = freezeColumns; i < columnsIn.length; i++) {
|
|
12
|
+
const c = columnsIn[i];
|
|
13
|
+
const group = Array.isArray(c.group) ? (c.group[0] ?? "") : (c.group ?? "");
|
|
14
|
+
const isCollapsed = collapsed.includes(group);
|
|
15
|
+
if (lastGroup !== group && current[0] !== -1) {
|
|
16
|
+
result.push(current);
|
|
17
|
+
current = [-1, -1];
|
|
18
|
+
}
|
|
19
|
+
if (isCollapsed && current[0] !== -1) {
|
|
20
|
+
current[1] += 1;
|
|
21
|
+
}
|
|
22
|
+
else if (isCollapsed) {
|
|
23
|
+
current = [i, 1];
|
|
24
|
+
}
|
|
25
|
+
else if (current[0] !== -1) {
|
|
26
|
+
result.push(current);
|
|
27
|
+
current = [-1, -1];
|
|
28
|
+
}
|
|
29
|
+
lastGroup = group;
|
|
30
|
+
}
|
|
31
|
+
if (current[0] !== -1)
|
|
32
|
+
result.push(current);
|
|
33
|
+
return result;
|
|
34
|
+
}, [collapsed, columnsIn, freezeColumns]);
|
|
35
|
+
const columns = React.useMemo(() => {
|
|
36
|
+
if (spans.length === 0)
|
|
37
|
+
return columnsIn;
|
|
38
|
+
return columnsIn.map((c, index) => {
|
|
39
|
+
for (const [start, length] of spans) {
|
|
40
|
+
if (index >= start && index < start + length) {
|
|
41
|
+
let width = 8;
|
|
42
|
+
if (index === start + length - 1) {
|
|
43
|
+
width = 36;
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
...c,
|
|
47
|
+
width,
|
|
48
|
+
themeOverride: { bgCell: theme.bgCellMedium },
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return c;
|
|
53
|
+
});
|
|
54
|
+
}, [columnsIn, spans, theme.bgCellMedium]);
|
|
55
|
+
const onGroupHeaderClicked = React.useCallback((index, a) => {
|
|
56
|
+
onGroupHeaderClickedIn?.(index, a);
|
|
57
|
+
const groupRaw = columns[index]?.group;
|
|
58
|
+
const group = Array.isArray(groupRaw) ? (groupRaw[0] ?? "") : (groupRaw ?? "");
|
|
59
|
+
if (group === "")
|
|
60
|
+
return;
|
|
61
|
+
a.preventDefault();
|
|
62
|
+
setCollapsed(cv => (cv.includes(group) ? cv.filter(x => x !== group) : [...cv, group]));
|
|
63
|
+
}, [columns, onGroupHeaderClickedIn]);
|
|
64
|
+
const onGridSelectionChange = React.useCallback(s => {
|
|
65
|
+
if (s.current !== undefined) {
|
|
66
|
+
const col = s.current.cell[0];
|
|
67
|
+
const column = columns[col];
|
|
68
|
+
const groupRaw = column?.group;
|
|
69
|
+
const group = Array.isArray(groupRaw) ? (groupRaw[0] ?? "") : (groupRaw ?? "");
|
|
70
|
+
setCollapsed(cv => {
|
|
71
|
+
if (cv.includes(group)) {
|
|
72
|
+
return cv.filter(g => g !== group);
|
|
73
|
+
}
|
|
74
|
+
return cv;
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
if (onGridSelectionChangeIn !== undefined) {
|
|
78
|
+
onGridSelectionChangeIn(s);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
setGridSelectionsInner(s);
|
|
82
|
+
}
|
|
83
|
+
}, [columns, onGridSelectionChangeIn]);
|
|
84
|
+
const getGroupDetails = React.useCallback(group => {
|
|
85
|
+
const result = getGroupDetailsIn?.(group);
|
|
86
|
+
const groupStr = Array.isArray(group) ? (group[0] ?? "") : (group ?? "");
|
|
87
|
+
return {
|
|
88
|
+
...result,
|
|
89
|
+
name: groupStr,
|
|
90
|
+
overrideTheme: collapsed.includes(groupStr)
|
|
91
|
+
? {
|
|
92
|
+
bgHeader: theme.bgHeaderHasFocus,
|
|
93
|
+
}
|
|
94
|
+
: undefined,
|
|
95
|
+
};
|
|
96
|
+
}, [collapsed, getGroupDetailsIn, theme.bgHeaderHasFocus]);
|
|
97
|
+
return {
|
|
98
|
+
columns,
|
|
99
|
+
onGroupHeaderClicked,
|
|
100
|
+
onGridSelectionChange,
|
|
101
|
+
getGroupDetails,
|
|
102
|
+
gridSelection,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=use-collapsing-groups.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-collapsing-groups.js","sourceRoot":"","sources":["../../src/use-collapsing-groups.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { GridCellKind } from "@glideapps/glide-data-grid";
|
|
2
|
+
import range from "lodash/range.js";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
function cellToSortData(c) {
|
|
5
|
+
switch (c.kind) {
|
|
6
|
+
case GridCellKind.Number:
|
|
7
|
+
return c.data?.toString() ?? "";
|
|
8
|
+
case GridCellKind.Boolean:
|
|
9
|
+
return c.data?.toString() ?? "";
|
|
10
|
+
case GridCellKind.Markdown:
|
|
11
|
+
case GridCellKind.RowID:
|
|
12
|
+
case GridCellKind.Text:
|
|
13
|
+
case GridCellKind.Uri:
|
|
14
|
+
return c.data ?? "";
|
|
15
|
+
case GridCellKind.Bubble:
|
|
16
|
+
case GridCellKind.Image:
|
|
17
|
+
return c.data.join("");
|
|
18
|
+
case GridCellKind.Drilldown:
|
|
19
|
+
return c.data.map(x => x.text).join("");
|
|
20
|
+
case GridCellKind.Protected:
|
|
21
|
+
case GridCellKind.Loading:
|
|
22
|
+
return "";
|
|
23
|
+
case GridCellKind.Custom:
|
|
24
|
+
return c.copyData;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function tryParse(val) {
|
|
28
|
+
if (typeof val === "number")
|
|
29
|
+
return val;
|
|
30
|
+
if (val.length > 0) {
|
|
31
|
+
const x = Number(val);
|
|
32
|
+
if (!isNaN(x)) {
|
|
33
|
+
val = x;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return val;
|
|
37
|
+
}
|
|
38
|
+
export function compareSmart(a, b) {
|
|
39
|
+
a = tryParse(a);
|
|
40
|
+
b = tryParse(b);
|
|
41
|
+
if (typeof a === "string" && typeof b === "string") {
|
|
42
|
+
return a.localeCompare(b);
|
|
43
|
+
}
|
|
44
|
+
else if (typeof a === "number" && typeof b === "number") {
|
|
45
|
+
if (a === b)
|
|
46
|
+
return 0;
|
|
47
|
+
return a > b ? 1 : -1;
|
|
48
|
+
}
|
|
49
|
+
else if (a == b) {
|
|
50
|
+
return 0;
|
|
51
|
+
}
|
|
52
|
+
return a > b ? 1 : -1;
|
|
53
|
+
}
|
|
54
|
+
export function compareRaw(a, b) {
|
|
55
|
+
if (a > b)
|
|
56
|
+
return 1;
|
|
57
|
+
if (a === b)
|
|
58
|
+
return 0;
|
|
59
|
+
return -1;
|
|
60
|
+
}
|
|
61
|
+
export function useColumnSort(p) {
|
|
62
|
+
const { sort, rows, getCellContent: getCellContentIn } = p;
|
|
63
|
+
const sorts = React.useMemo(() => {
|
|
64
|
+
if (sort === undefined)
|
|
65
|
+
return [];
|
|
66
|
+
return Array.isArray(sort) ? sort : [sort];
|
|
67
|
+
}, [sort]);
|
|
68
|
+
const sortCols = React.useMemo(() => sorts.map(s => {
|
|
69
|
+
const c = p.columns.findIndex(col => s.column === col || (col.id !== undefined && s.column.id === col.id));
|
|
70
|
+
return c === -1 ? undefined : c;
|
|
71
|
+
}), [sorts, p.columns]);
|
|
72
|
+
// This scales to about 100k rows. Beyond that things take a pretty noticeable amount of time
|
|
73
|
+
// The performance "issue" from here on out seems to be the lookup to get the value. Not sure
|
|
74
|
+
// what to do there. We need the indirection to produce the final sort map. Perhaps someone
|
|
75
|
+
// more clever than me will wander in and save most of that time.
|
|
76
|
+
const sortMap = React.useMemo(() => {
|
|
77
|
+
const activeSorts = sorts
|
|
78
|
+
.map((s, i) => ({ sort: s, col: sortCols[i] }))
|
|
79
|
+
.filter((v) => v.col !== undefined);
|
|
80
|
+
if (activeSorts.length === 0)
|
|
81
|
+
return undefined;
|
|
82
|
+
const values = activeSorts.map(() => new Array(rows));
|
|
83
|
+
for (let sIndex = 0; sIndex < activeSorts.length; sIndex++) {
|
|
84
|
+
const { col } = activeSorts[sIndex];
|
|
85
|
+
const index = [col, 0];
|
|
86
|
+
for (let i = 0; i < rows; i++) {
|
|
87
|
+
index[1] = i;
|
|
88
|
+
values[sIndex][i] = cellToSortData(getCellContentIn(index));
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return range(rows).sort((a, b) => {
|
|
92
|
+
for (let sIndex = 0; sIndex < activeSorts.length; sIndex++) {
|
|
93
|
+
const { sort: colSort } = activeSorts[sIndex];
|
|
94
|
+
const va = values[sIndex][a];
|
|
95
|
+
const vb = values[sIndex][b];
|
|
96
|
+
let cmp;
|
|
97
|
+
if (colSort.mode === "raw") {
|
|
98
|
+
cmp = compareRaw(va, vb);
|
|
99
|
+
}
|
|
100
|
+
else if (colSort.mode === "smart") {
|
|
101
|
+
cmp = compareSmart(va, vb);
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
cmp = va.localeCompare(vb);
|
|
105
|
+
}
|
|
106
|
+
if (cmp !== 0) {
|
|
107
|
+
if ((colSort.direction ?? "asc") === "desc")
|
|
108
|
+
cmp = -cmp;
|
|
109
|
+
return cmp;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return 0;
|
|
113
|
+
});
|
|
114
|
+
}, [getCellContentIn, rows, sorts, sortCols]);
|
|
115
|
+
const getOriginalIndex = React.useCallback((index) => {
|
|
116
|
+
if (sortMap === undefined)
|
|
117
|
+
return index;
|
|
118
|
+
return sortMap[index];
|
|
119
|
+
}, [sortMap]);
|
|
120
|
+
const getCellContent = React.useCallback(([col, row]) => {
|
|
121
|
+
if (sortMap === undefined)
|
|
122
|
+
return getCellContentIn([col, row]);
|
|
123
|
+
row = sortMap[row];
|
|
124
|
+
return getCellContentIn([col, row]);
|
|
125
|
+
}, [getCellContentIn, sortMap]);
|
|
126
|
+
if (sortMap === undefined) {
|
|
127
|
+
return { getCellContent: p.getCellContent, getOriginalIndex };
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
getOriginalIndex,
|
|
131
|
+
getCellContent,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=use-column-sort.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-column-sort.js","sourceRoot":"","sources":["../../src/use-column-sort.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import orderBy from "lodash/orderBy.js";
|
|
3
|
+
function colToKey(c) {
|
|
4
|
+
return c.id ?? `${c.group ?? ""}/${c.title}`;
|
|
5
|
+
}
|
|
6
|
+
function looseCompareCol(a, b) {
|
|
7
|
+
if (typeof b === "string") {
|
|
8
|
+
return colToKey(a) === b;
|
|
9
|
+
}
|
|
10
|
+
return colToKey(a) === colToKey(b);
|
|
11
|
+
}
|
|
12
|
+
function getSortIndexByKey(needle, current, keys) {
|
|
13
|
+
const index = current.indexOf(needle);
|
|
14
|
+
if (index === -1)
|
|
15
|
+
return Number.MAX_SAFE_INTEGER; // should never happen
|
|
16
|
+
// if we can directly remap we will
|
|
17
|
+
const remapped = keys.findIndex(key => looseCompareCol(needle, key));
|
|
18
|
+
if (remapped !== -1)
|
|
19
|
+
return remapped;
|
|
20
|
+
// look for its nearlest lefthand neighbor we can remap, and give a partial index
|
|
21
|
+
for (let n = index; n >= 0; n--) {
|
|
22
|
+
const ind = keys.findIndex(key => looseCompareCol(current[n], key));
|
|
23
|
+
if (ind !== -1)
|
|
24
|
+
return ind + 0.5;
|
|
25
|
+
}
|
|
26
|
+
return -1;
|
|
27
|
+
}
|
|
28
|
+
// this cannot actually be made transparent to the user. Doing so would break things like
|
|
29
|
+
// selection rnages being rectangular. The mangled columns need to actually be returned to the
|
|
30
|
+
// user so they can be referenced and understood correctly in other callbacks they may provide
|
|
31
|
+
// Darn
|
|
32
|
+
export function useMoveableColumns(p) {
|
|
33
|
+
const { columns: columnsIn, getCellContent: getCellContentIn, onColumnMoved: onColumnMovedIn } = p;
|
|
34
|
+
const [keys, setKeys] = React.useState(() => columnsIn.map(colToKey));
|
|
35
|
+
const columns = React.useMemo(() => {
|
|
36
|
+
return orderBy(columnsIn, c => getSortIndexByKey(c, columnsIn, keys));
|
|
37
|
+
}, [keys, columnsIn]);
|
|
38
|
+
const onColumnMovedRef = React.useRef(onColumnMovedIn);
|
|
39
|
+
onColumnMovedRef.current = onColumnMovedIn;
|
|
40
|
+
const onColumnMoved = React.useCallback((startIndex, endIndex) => {
|
|
41
|
+
setKeys(old => {
|
|
42
|
+
const newCols = [...old];
|
|
43
|
+
const [toMove] = newCols.splice(startIndex, 1);
|
|
44
|
+
newCols.splice(endIndex, 0, toMove);
|
|
45
|
+
return newCols;
|
|
46
|
+
});
|
|
47
|
+
onColumnMovedRef.current?.(startIndex, endIndex);
|
|
48
|
+
}, []);
|
|
49
|
+
React.useEffect(() => {
|
|
50
|
+
setKeys(cv => {
|
|
51
|
+
return orderBy(columnsIn, x => getSortIndexByKey(x, columnsIn, cv)).map(colToKey);
|
|
52
|
+
});
|
|
53
|
+
}, [columnsIn]);
|
|
54
|
+
const getCellContent = React.useCallback(cell => {
|
|
55
|
+
const [col, row] = cell;
|
|
56
|
+
const needle = columns[col];
|
|
57
|
+
const index = columnsIn.indexOf(needle);
|
|
58
|
+
return getCellContentIn([index, row]);
|
|
59
|
+
}, [columns, columnsIn, getCellContentIn]);
|
|
60
|
+
return {
|
|
61
|
+
columns,
|
|
62
|
+
onColumnMoved,
|
|
63
|
+
getCellContent,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=use-movable-columns.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-movable-columns.js","sourceRoot":"","sources":["../../src/use-movable-columns.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { useCallback, useEffect, useMemo, useReducer, useRef, useState } from "react";
|
|
2
|
+
const initialState = {
|
|
3
|
+
undoHistory: [],
|
|
4
|
+
redoHistory: [],
|
|
5
|
+
canUndo: false,
|
|
6
|
+
canRedo: false,
|
|
7
|
+
isApplyingUndo: false,
|
|
8
|
+
isApplyingRedo: false,
|
|
9
|
+
};
|
|
10
|
+
function reducer(state, action) {
|
|
11
|
+
const newState = { ...state };
|
|
12
|
+
switch (action.type) {
|
|
13
|
+
case "undo":
|
|
14
|
+
if (state.canUndo) {
|
|
15
|
+
newState.undoHistory = [...state.undoHistory];
|
|
16
|
+
const operation = newState.undoHistory.pop();
|
|
17
|
+
newState.operation = operation;
|
|
18
|
+
newState.canUndo = newState.undoHistory.length > 0;
|
|
19
|
+
newState.isApplyingUndo = true;
|
|
20
|
+
return newState;
|
|
21
|
+
}
|
|
22
|
+
return state;
|
|
23
|
+
case "redo":
|
|
24
|
+
if (state.canRedo) {
|
|
25
|
+
newState.redoHistory = [...state.redoHistory];
|
|
26
|
+
const operation = newState.redoHistory.pop();
|
|
27
|
+
newState.operation = operation;
|
|
28
|
+
newState.canRedo = newState.redoHistory.length > 0;
|
|
29
|
+
newState.isApplyingRedo = true;
|
|
30
|
+
return newState;
|
|
31
|
+
}
|
|
32
|
+
return state;
|
|
33
|
+
case "operationApplied":
|
|
34
|
+
newState.operation = undefined;
|
|
35
|
+
newState.isApplyingRedo = false;
|
|
36
|
+
newState.isApplyingUndo = false;
|
|
37
|
+
return newState;
|
|
38
|
+
case "edit":
|
|
39
|
+
if (!state.isApplyingRedo && !state.isApplyingUndo) {
|
|
40
|
+
// general case
|
|
41
|
+
newState.undoHistory = [...state.undoHistory, action.batch];
|
|
42
|
+
newState.redoHistory = [];
|
|
43
|
+
newState.canUndo = true;
|
|
44
|
+
newState.canRedo = false;
|
|
45
|
+
}
|
|
46
|
+
if (state.isApplyingUndo) {
|
|
47
|
+
newState.redoHistory = [...state.redoHistory, action.batch];
|
|
48
|
+
newState.canRedo = true;
|
|
49
|
+
}
|
|
50
|
+
if (state.isApplyingRedo) {
|
|
51
|
+
newState.undoHistory = [...state.undoHistory, action.batch];
|
|
52
|
+
newState.canUndo = true;
|
|
53
|
+
}
|
|
54
|
+
return newState;
|
|
55
|
+
default:
|
|
56
|
+
throw new Error("Invalid action");
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
export function useUndoRedo(gridRef, getCellContent, onCellEdited, onGridSelectionChange) {
|
|
60
|
+
const [state, dispatch] = useReducer(reducer, initialState);
|
|
61
|
+
const currentBatch = useRef(null);
|
|
62
|
+
const timeout = useRef(null);
|
|
63
|
+
const isApplyingUndoRef = useRef(false);
|
|
64
|
+
const isApplyingRedoRef = useRef(false);
|
|
65
|
+
useEffect(() => {
|
|
66
|
+
isApplyingUndoRef.current = state.isApplyingUndo;
|
|
67
|
+
isApplyingRedoRef.current = state.isApplyingRedo;
|
|
68
|
+
}, [state.isApplyingUndo, state.isApplyingRedo]);
|
|
69
|
+
const [gridSelection, setGridSelection] = useState(null);
|
|
70
|
+
const gridSelectionRef = useRef(null);
|
|
71
|
+
const onGridSelectionChangedEdited = useCallback((newVal) => {
|
|
72
|
+
if (onGridSelectionChange) {
|
|
73
|
+
onGridSelectionChange(newVal);
|
|
74
|
+
}
|
|
75
|
+
setGridSelection(newVal);
|
|
76
|
+
gridSelectionRef.current = newVal;
|
|
77
|
+
}, [onGridSelectionChange]);
|
|
78
|
+
const wrappedOnCellEdited = useCallback((cell, newValue) => {
|
|
79
|
+
const isApplyingUpdate = isApplyingUndoRef.current || isApplyingRedoRef.current;
|
|
80
|
+
if (!isApplyingUpdate && gridSelectionRef.current) {
|
|
81
|
+
clearTimeout(timeout.current);
|
|
82
|
+
const previousValue = getCellContent(cell);
|
|
83
|
+
if (currentBatch.current === null) {
|
|
84
|
+
currentBatch.current = {
|
|
85
|
+
edits: [],
|
|
86
|
+
selection: gridSelectionRef.current,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
currentBatch.current.edits.push({ cell, newValue: previousValue });
|
|
90
|
+
// When pasting lots of edits arrive sequentially. Undo/redo should replay in a batch so using a timeout to kick to the end of the event loop
|
|
91
|
+
timeout.current = setTimeout(() => {
|
|
92
|
+
if (currentBatch.current) {
|
|
93
|
+
dispatch({
|
|
94
|
+
type: "edit",
|
|
95
|
+
batch: currentBatch.current,
|
|
96
|
+
});
|
|
97
|
+
currentBatch.current = null;
|
|
98
|
+
}
|
|
99
|
+
}, 0);
|
|
100
|
+
}
|
|
101
|
+
// Continue with the edit
|
|
102
|
+
onCellEdited(cell, newValue);
|
|
103
|
+
}, [onCellEdited, getCellContent]);
|
|
104
|
+
const undo = useCallback(() => {
|
|
105
|
+
dispatch({ type: "undo" });
|
|
106
|
+
}, [dispatch]);
|
|
107
|
+
const redo = useCallback(() => {
|
|
108
|
+
dispatch({ type: "redo" });
|
|
109
|
+
}, [dispatch]);
|
|
110
|
+
// Apply a batch of edits to the grid
|
|
111
|
+
useEffect(() => {
|
|
112
|
+
if (state.operation !== undefined && gridSelectionRef.current !== null && gridRef.current !== null) {
|
|
113
|
+
const cells = [];
|
|
114
|
+
const previousState = {
|
|
115
|
+
edits: [],
|
|
116
|
+
selection: gridSelectionRef.current,
|
|
117
|
+
};
|
|
118
|
+
for (const edit of state.operation.edits) {
|
|
119
|
+
const prevValue = getCellContent(edit.cell);
|
|
120
|
+
previousState.edits.push({ cell: edit.cell, newValue: prevValue });
|
|
121
|
+
onCellEdited(edit.cell, edit.newValue);
|
|
122
|
+
cells.push({ cell: edit.cell });
|
|
123
|
+
}
|
|
124
|
+
setGridSelection(state.operation.selection);
|
|
125
|
+
gridSelectionRef.current = state.operation.selection;
|
|
126
|
+
gridRef.current.updateCells(cells);
|
|
127
|
+
dispatch({
|
|
128
|
+
type: "edit",
|
|
129
|
+
batch: previousState,
|
|
130
|
+
});
|
|
131
|
+
dispatch({
|
|
132
|
+
type: "operationApplied",
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
}, [state.operation, gridRef, onCellEdited, setGridSelection, getCellContent]);
|
|
136
|
+
// Attach the keyboard shortcuts. CMD+Z and CMD+SHIFT+Z on mac, CTRL+Z and CTRL+Y on windows.
|
|
137
|
+
useEffect(() => {
|
|
138
|
+
const onKeyDown = (e) => {
|
|
139
|
+
if (e.key === "z" && (e.metaKey || e.ctrlKey)) {
|
|
140
|
+
if (e.shiftKey) {
|
|
141
|
+
redo();
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
undo();
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
if (e.key === "y" && (e.metaKey || e.ctrlKey)) {
|
|
148
|
+
redo();
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
window.addEventListener("keydown", onKeyDown);
|
|
152
|
+
return () => {
|
|
153
|
+
window.removeEventListener("keydown", onKeyDown);
|
|
154
|
+
};
|
|
155
|
+
}, [undo, redo]);
|
|
156
|
+
return useMemo(() => {
|
|
157
|
+
return {
|
|
158
|
+
undo,
|
|
159
|
+
redo,
|
|
160
|
+
canUndo: state.canUndo,
|
|
161
|
+
canRedo: state.canRedo,
|
|
162
|
+
onCellEdited: wrappedOnCellEdited,
|
|
163
|
+
onGridSelectionChange: onGridSelectionChangedEdited,
|
|
164
|
+
gridSelection,
|
|
165
|
+
};
|
|
166
|
+
}, [undo, redo, wrappedOnCellEdited, state.canUndo, state.canRedo, onGridSelectionChangedEdited, gridSelection]);
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=use-undo-redo.js.map
|