grid-cell-selection 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +65 -0
- package/dist/App.d.ts +3 -0
- package/dist/example/App.d.ts +3 -0
- package/dist/example/main.d.ts +1 -0
- package/dist/hooks/selectionComponents.d.ts +0 -0
- package/dist/hooks/useCellSelection.d.ts +9 -0
- package/dist/hooks/useMouseDragSelection.d.ts +6 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.esm.js +119 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/index.js +124 -0
- package/dist/index.js.map +1 -0
- package/dist/main.d.ts +1 -0
- package/dist/types/index.d.ts +8 -0
- package/package.json +53 -0
package/README.md
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
# Grid Cell Selection
|
2
|
+
|
3
|
+
A React hook for grid cell selection. A simple headless hook that.
|
4
|
+
|
5
|
+
# Made by [Atticus](https://atticusthomson.com)
|
6
|
+
|
7
|
+
![Grid Cell Selection](https://github.com/attithom/grid-cell-selection/blob/main/example.gif)
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
```bash
|
12
|
+
npm install grid-cell-selection
|
13
|
+
```
|
14
|
+
|
15
|
+
## Usage
|
16
|
+
|
17
|
+
```tsx
|
18
|
+
import React from "react";
|
19
|
+
import { useGridCellSelection } from "grid-cell-selection";
|
20
|
+
|
21
|
+
function App() {
|
22
|
+
const columns = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L"];
|
23
|
+
const rows = 20;
|
24
|
+
|
25
|
+
const { isCellSelected, handleMouseDown, handleMouseEnter, handleMouseUp } = useGridCellSelection("multiple");
|
26
|
+
|
27
|
+
return (
|
28
|
+
<>
|
29
|
+
<table onMouseUp={handleMouseUp}>
|
30
|
+
<tbody>
|
31
|
+
{Array.from({ length: rows }, (_, row) => (
|
32
|
+
<tr key={row}>
|
33
|
+
{columns.map((column, col) => (
|
34
|
+
<td
|
35
|
+
onMouseEnter={(event) => handleMouseEnter({ row, col }, event)}
|
36
|
+
onMouseDown={(event) => handleMouseDown({ row, col }, event)}
|
37
|
+
className={`${isCellSelected({ row, col }) ? "selected" : ""}`}
|
38
|
+
>
|
39
|
+
{column}
|
40
|
+
{row}
|
41
|
+
</td>
|
42
|
+
))}
|
43
|
+
</tr>
|
44
|
+
))}
|
45
|
+
</tbody>
|
46
|
+
</table>
|
47
|
+
</>
|
48
|
+
);
|
49
|
+
}
|
50
|
+
```
|
51
|
+
|
52
|
+
## Cell Selection Behavior
|
53
|
+
|
54
|
+
### Single Cell Selection
|
55
|
+
|
56
|
+
- Click on a cell to select it.
|
57
|
+
- Clicking on a different cell deselects any previously selected cells.
|
58
|
+
|
59
|
+
### Range Selection
|
60
|
+
|
61
|
+
- Click and drag to select a range of cells
|
62
|
+
|
63
|
+
### Multiple Range Selection
|
64
|
+
|
65
|
+
- Hold Ctrl (or Cmd on Mac) or Shift to select multiple ranges
|
package/dist/App.d.ts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
import "./index.css";
|
File without changes
|
@@ -0,0 +1,9 @@
|
|
1
|
+
/// <reference types="react" />
|
2
|
+
import { CellIdentifier } from "../types";
|
3
|
+
export declare const useGridCellSelection: () => {
|
4
|
+
selectedCells: Set<string>;
|
5
|
+
isCellSelected: (cell: CellIdentifier) => boolean;
|
6
|
+
handleMouseDown: (cell: CellIdentifier, event: import("react").MouseEvent<Element, MouseEvent>) => void;
|
7
|
+
handleMouseEnter: (cell: CellIdentifier, event: import("react").MouseEvent<Element, MouseEvent>) => void;
|
8
|
+
handleMouseUp: () => void;
|
9
|
+
};
|
@@ -0,0 +1,6 @@
|
|
1
|
+
import { CellIdentifier } from "../types";
|
2
|
+
export declare const useMouseDragSelection: (toggleCellSelection: (cell: CellIdentifier, ctrlKey: boolean, shiftKey: boolean, newSelection: boolean) => void) => {
|
3
|
+
handleMouseDown: (cell: CellIdentifier, event: React.MouseEvent) => void;
|
4
|
+
handleMouseEnter: (cell: CellIdentifier, event: React.MouseEvent) => void;
|
5
|
+
handleMouseUp: () => void;
|
6
|
+
};
|
package/dist/index.d.ts
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
import { useState } from 'react';
|
2
|
+
|
3
|
+
/******************************************************************************
|
4
|
+
Copyright (c) Microsoft Corporation.
|
5
|
+
|
6
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
7
|
+
purpose with or without fee is hereby granted.
|
8
|
+
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
10
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
11
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
12
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
13
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
14
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
15
|
+
PERFORMANCE OF THIS SOFTWARE.
|
16
|
+
***************************************************************************** */
|
17
|
+
|
18
|
+
var __assign = function() {
|
19
|
+
__assign = Object.assign || function __assign(t) {
|
20
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
21
|
+
s = arguments[i];
|
22
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
|
23
|
+
}
|
24
|
+
return t;
|
25
|
+
};
|
26
|
+
return __assign.apply(this, arguments);
|
27
|
+
};
|
28
|
+
|
29
|
+
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
30
|
+
var e = new Error(message);
|
31
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
32
|
+
};
|
33
|
+
|
34
|
+
var useMouseDragSelection = function (toggleCellSelection) {
|
35
|
+
var _a = useState(false), isDragging = _a[0], setIsDragging = _a[1];
|
36
|
+
var handleMouseDown = function (cell, event) {
|
37
|
+
setIsDragging(true);
|
38
|
+
toggleCellSelection(cell, event.ctrlKey || event.metaKey, event.shiftKey, true);
|
39
|
+
};
|
40
|
+
var handleMouseEnter = function (cell, event) {
|
41
|
+
if (isDragging) {
|
42
|
+
toggleCellSelection(cell, event.ctrlKey || event.metaKey, event.shiftKey, false);
|
43
|
+
}
|
44
|
+
};
|
45
|
+
var handleMouseUp = function () {
|
46
|
+
setIsDragging(false);
|
47
|
+
};
|
48
|
+
return {
|
49
|
+
handleMouseDown: handleMouseDown,
|
50
|
+
handleMouseEnter: handleMouseEnter,
|
51
|
+
handleMouseUp: handleMouseUp,
|
52
|
+
};
|
53
|
+
};
|
54
|
+
|
55
|
+
var getCellKey = function (cell) {
|
56
|
+
return "".concat(cell.row, "-").concat(cell.col);
|
57
|
+
};
|
58
|
+
var useGridCellSelection = function () {
|
59
|
+
var _a = useState({
|
60
|
+
selectedCells: new Set(),
|
61
|
+
}), selectionState = _a[0], setSelectionState = _a[1];
|
62
|
+
var toggleCellSelection = function (cell, ctrlKey, shiftKey, newSelection) {
|
63
|
+
if (ctrlKey === void 0) { ctrlKey = false; }
|
64
|
+
if (shiftKey === void 0) { shiftKey = false; }
|
65
|
+
if (newSelection === void 0) { newSelection = false; }
|
66
|
+
setSelectionState(function (prevState) {
|
67
|
+
var selectedCells = new Set(prevState.selectedCells);
|
68
|
+
var cellKey = getCellKey(cell);
|
69
|
+
if (prevState.startCell && !newSelection) {
|
70
|
+
handleRangeSelection(selectedCells, prevState.startCell, cell);
|
71
|
+
}
|
72
|
+
else if ((shiftKey || ctrlKey) && newSelection) {
|
73
|
+
handleSingleOrMultipleSelection(selectedCells, cellKey);
|
74
|
+
}
|
75
|
+
else {
|
76
|
+
selectedCells.clear();
|
77
|
+
selectedCells.add(cellKey);
|
78
|
+
}
|
79
|
+
return __assign(__assign({}, prevState), { selectedCells: selectedCells, startCell: newSelection ? cell : prevState.startCell });
|
80
|
+
});
|
81
|
+
};
|
82
|
+
var isCellSelected = function (cell) {
|
83
|
+
return selectionState.selectedCells.has(getCellKey(cell));
|
84
|
+
};
|
85
|
+
var _b = useMouseDragSelection(toggleCellSelection), handleMouseDown = _b.handleMouseDown, handleMouseEnter = _b.handleMouseEnter, handleMouseUp = _b.handleMouseUp;
|
86
|
+
return {
|
87
|
+
selectedCells: selectionState.selectedCells,
|
88
|
+
isCellSelected: isCellSelected,
|
89
|
+
handleMouseDown: handleMouseDown,
|
90
|
+
handleMouseEnter: handleMouseEnter,
|
91
|
+
handleMouseUp: handleMouseUp,
|
92
|
+
};
|
93
|
+
};
|
94
|
+
// New helper functions
|
95
|
+
function handleRangeSelection(selectedCells, startCell, endCell) {
|
96
|
+
var action = selectedCells.has(getCellKey(startCell)) ? "add" : "delete";
|
97
|
+
var _a = [startCell.row, startCell.col], startRow = _a[0], startCol = _a[1];
|
98
|
+
var _b = [endCell.row, endCell.col], endRow = _b[0], endCol = _b[1];
|
99
|
+
var minRow = Math.min(startRow, endRow);
|
100
|
+
var maxRow = Math.max(startRow, endRow);
|
101
|
+
var minCol = Math.min(startCol, endCol);
|
102
|
+
var maxCol = Math.max(startCol, endCol);
|
103
|
+
for (var row = minRow; row <= maxRow; row++) {
|
104
|
+
for (var col = minCol; col <= maxCol; col++) {
|
105
|
+
selectedCells[action](getCellKey({ row: row, col: col }));
|
106
|
+
}
|
107
|
+
}
|
108
|
+
}
|
109
|
+
function handleSingleOrMultipleSelection(selectedCells, cellKey) {
|
110
|
+
if (selectedCells.has(cellKey)) {
|
111
|
+
selectedCells.delete(cellKey);
|
112
|
+
}
|
113
|
+
else {
|
114
|
+
selectedCells.add(cellKey);
|
115
|
+
}
|
116
|
+
}
|
117
|
+
|
118
|
+
export { useGridCellSelection, useMouseDragSelection };
|
119
|
+
//# sourceMappingURL=index.esm.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":["../src/hooks/useMouseDragSelection.ts","../src/hooks/useCellSelection.ts"],"sourcesContent":["import { useState } from \"react\";\nimport { CellIdentifier } from \"../types\";\n\nexport const useMouseDragSelection = (\n toggleCellSelection: (cell: CellIdentifier, ctrlKey: boolean, shiftKey: boolean, newSelection: boolean) => void\n) => {\n const [isDragging, setIsDragging] = useState(false);\n\n const handleMouseDown = (cell: CellIdentifier, event: React.MouseEvent) => {\n setIsDragging(true);\n toggleCellSelection(cell, event.ctrlKey || event.metaKey, event.shiftKey, true);\n };\n\n const handleMouseEnter = (cell: CellIdentifier, event: React.MouseEvent) => {\n if (isDragging) {\n toggleCellSelection(cell, event.ctrlKey || event.metaKey, event.shiftKey, false);\n }\n };\n\n const handleMouseUp = () => {\n setIsDragging(false);\n };\n\n return {\n handleMouseDown,\n handleMouseEnter,\n handleMouseUp,\n };\n};\n","import { useState } from \"react\";\nimport { CellIdentifier, SelectionState } from \"../types\";\nimport { useMouseDragSelection } from \"./useMouseDragSelection\";\n\nconst getCellKey = (cell: Omit<CellIdentifier, \"id\">): string => {\n return `${cell.row}-${cell.col}`;\n};\n\nexport const useGridCellSelection = () => {\n const [selectionState, setSelectionState] = useState<SelectionState>({\n selectedCells: new Set(),\n });\n\n const toggleCellSelection = (cell: CellIdentifier, ctrlKey = false, shiftKey = false, newSelection = false) => {\n setSelectionState((prevState) => {\n const selectedCells = new Set(prevState.selectedCells);\n const cellKey = getCellKey(cell);\n\n if (prevState.startCell && !newSelection) {\n handleRangeSelection(selectedCells, prevState.startCell, cell);\n } else if ((shiftKey || ctrlKey) && newSelection) {\n handleSingleOrMultipleSelection(selectedCells, cellKey);\n } else {\n selectedCells.clear();\n selectedCells.add(cellKey);\n }\n\n return {\n ...prevState,\n selectedCells,\n startCell: newSelection ? cell : prevState.startCell,\n };\n });\n };\n\n const isCellSelected = (cell: CellIdentifier) => {\n return selectionState.selectedCells.has(getCellKey(cell));\n };\n\n const { handleMouseDown, handleMouseEnter, handleMouseUp } = useMouseDragSelection(toggleCellSelection);\n\n return {\n selectedCells: selectionState.selectedCells,\n isCellSelected,\n handleMouseDown,\n handleMouseEnter,\n handleMouseUp,\n };\n};\n\n// New helper functions\nfunction handleRangeSelection(selectedCells: Set<string>, startCell: CellIdentifier, endCell: CellIdentifier) {\n const action = selectedCells.has(getCellKey(startCell)) ? \"add\" : \"delete\";\n const [startRow, startCol] = [startCell.row, startCell.col];\n const [endRow, endCol] = [endCell.row, endCell.col];\n\n const minRow = Math.min(startRow, endRow);\n const maxRow = Math.max(startRow, endRow);\n const minCol = Math.min(startCol, endCol);\n const maxCol = Math.max(startCol, endCol);\n\n for (let row = minRow; row <= maxRow; row++) {\n for (let col = minCol; col <= maxCol; col++) {\n selectedCells[action](getCellKey({ row, col }));\n }\n }\n}\n\nfunction handleSingleOrMultipleSelection(selectedCells: Set<string>, cellKey: string) {\n if (selectedCells.has(cellKey)) {\n selectedCells.delete(cellKey);\n } else {\n selectedCells.add(cellKey);\n }\n}\n"],"names":[],"mappings":"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"}
|
package/dist/index.js
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
4
|
+
|
5
|
+
var react = require('react');
|
6
|
+
|
7
|
+
/******************************************************************************
|
8
|
+
Copyright (c) Microsoft Corporation.
|
9
|
+
|
10
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
11
|
+
purpose with or without fee is hereby granted.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
14
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
15
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
16
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
17
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
18
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
19
|
+
PERFORMANCE OF THIS SOFTWARE.
|
20
|
+
***************************************************************************** */
|
21
|
+
|
22
|
+
var __assign = function() {
|
23
|
+
__assign = Object.assign || function __assign(t) {
|
24
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
25
|
+
s = arguments[i];
|
26
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
|
27
|
+
}
|
28
|
+
return t;
|
29
|
+
};
|
30
|
+
return __assign.apply(this, arguments);
|
31
|
+
};
|
32
|
+
|
33
|
+
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
34
|
+
var e = new Error(message);
|
35
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
36
|
+
};
|
37
|
+
|
38
|
+
var useMouseDragSelection = function (toggleCellSelection) {
|
39
|
+
var _a = react.useState(false), isDragging = _a[0], setIsDragging = _a[1];
|
40
|
+
var handleMouseDown = function (cell, event) {
|
41
|
+
setIsDragging(true);
|
42
|
+
toggleCellSelection(cell, event.ctrlKey || event.metaKey, event.shiftKey, true);
|
43
|
+
};
|
44
|
+
var handleMouseEnter = function (cell, event) {
|
45
|
+
if (isDragging) {
|
46
|
+
toggleCellSelection(cell, event.ctrlKey || event.metaKey, event.shiftKey, false);
|
47
|
+
}
|
48
|
+
};
|
49
|
+
var handleMouseUp = function () {
|
50
|
+
setIsDragging(false);
|
51
|
+
};
|
52
|
+
return {
|
53
|
+
handleMouseDown: handleMouseDown,
|
54
|
+
handleMouseEnter: handleMouseEnter,
|
55
|
+
handleMouseUp: handleMouseUp,
|
56
|
+
};
|
57
|
+
};
|
58
|
+
|
59
|
+
var getCellKey = function (cell) {
|
60
|
+
return "".concat(cell.row, "-").concat(cell.col);
|
61
|
+
};
|
62
|
+
var useGridCellSelection = function () {
|
63
|
+
var _a = react.useState({
|
64
|
+
selectedCells: new Set(),
|
65
|
+
}), selectionState = _a[0], setSelectionState = _a[1];
|
66
|
+
var toggleCellSelection = function (cell, ctrlKey, shiftKey, newSelection) {
|
67
|
+
if (ctrlKey === void 0) { ctrlKey = false; }
|
68
|
+
if (shiftKey === void 0) { shiftKey = false; }
|
69
|
+
if (newSelection === void 0) { newSelection = false; }
|
70
|
+
setSelectionState(function (prevState) {
|
71
|
+
var selectedCells = new Set(prevState.selectedCells);
|
72
|
+
var cellKey = getCellKey(cell);
|
73
|
+
if (prevState.startCell && !newSelection) {
|
74
|
+
handleRangeSelection(selectedCells, prevState.startCell, cell);
|
75
|
+
}
|
76
|
+
else if ((shiftKey || ctrlKey) && newSelection) {
|
77
|
+
handleSingleOrMultipleSelection(selectedCells, cellKey);
|
78
|
+
}
|
79
|
+
else {
|
80
|
+
selectedCells.clear();
|
81
|
+
selectedCells.add(cellKey);
|
82
|
+
}
|
83
|
+
return __assign(__assign({}, prevState), { selectedCells: selectedCells, startCell: newSelection ? cell : prevState.startCell });
|
84
|
+
});
|
85
|
+
};
|
86
|
+
var isCellSelected = function (cell) {
|
87
|
+
return selectionState.selectedCells.has(getCellKey(cell));
|
88
|
+
};
|
89
|
+
var _b = useMouseDragSelection(toggleCellSelection), handleMouseDown = _b.handleMouseDown, handleMouseEnter = _b.handleMouseEnter, handleMouseUp = _b.handleMouseUp;
|
90
|
+
return {
|
91
|
+
selectedCells: selectionState.selectedCells,
|
92
|
+
isCellSelected: isCellSelected,
|
93
|
+
handleMouseDown: handleMouseDown,
|
94
|
+
handleMouseEnter: handleMouseEnter,
|
95
|
+
handleMouseUp: handleMouseUp,
|
96
|
+
};
|
97
|
+
};
|
98
|
+
// New helper functions
|
99
|
+
function handleRangeSelection(selectedCells, startCell, endCell) {
|
100
|
+
var action = selectedCells.has(getCellKey(startCell)) ? "add" : "delete";
|
101
|
+
var _a = [startCell.row, startCell.col], startRow = _a[0], startCol = _a[1];
|
102
|
+
var _b = [endCell.row, endCell.col], endRow = _b[0], endCol = _b[1];
|
103
|
+
var minRow = Math.min(startRow, endRow);
|
104
|
+
var maxRow = Math.max(startRow, endRow);
|
105
|
+
var minCol = Math.min(startCol, endCol);
|
106
|
+
var maxCol = Math.max(startCol, endCol);
|
107
|
+
for (var row = minRow; row <= maxRow; row++) {
|
108
|
+
for (var col = minCol; col <= maxCol; col++) {
|
109
|
+
selectedCells[action](getCellKey({ row: row, col: col }));
|
110
|
+
}
|
111
|
+
}
|
112
|
+
}
|
113
|
+
function handleSingleOrMultipleSelection(selectedCells, cellKey) {
|
114
|
+
if (selectedCells.has(cellKey)) {
|
115
|
+
selectedCells.delete(cellKey);
|
116
|
+
}
|
117
|
+
else {
|
118
|
+
selectedCells.add(cellKey);
|
119
|
+
}
|
120
|
+
}
|
121
|
+
|
122
|
+
exports.useGridCellSelection = useGridCellSelection;
|
123
|
+
exports.useMouseDragSelection = useMouseDragSelection;
|
124
|
+
//# sourceMappingURL=index.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/hooks/useMouseDragSelection.ts","../src/hooks/useCellSelection.ts"],"sourcesContent":["import { useState } from \"react\";\nimport { CellIdentifier } from \"../types\";\n\nexport const useMouseDragSelection = (\n toggleCellSelection: (cell: CellIdentifier, ctrlKey: boolean, shiftKey: boolean, newSelection: boolean) => void\n) => {\n const [isDragging, setIsDragging] = useState(false);\n\n const handleMouseDown = (cell: CellIdentifier, event: React.MouseEvent) => {\n setIsDragging(true);\n toggleCellSelection(cell, event.ctrlKey || event.metaKey, event.shiftKey, true);\n };\n\n const handleMouseEnter = (cell: CellIdentifier, event: React.MouseEvent) => {\n if (isDragging) {\n toggleCellSelection(cell, event.ctrlKey || event.metaKey, event.shiftKey, false);\n }\n };\n\n const handleMouseUp = () => {\n setIsDragging(false);\n };\n\n return {\n handleMouseDown,\n handleMouseEnter,\n handleMouseUp,\n };\n};\n","import { useState } from \"react\";\nimport { CellIdentifier, SelectionState } from \"../types\";\nimport { useMouseDragSelection } from \"./useMouseDragSelection\";\n\nconst getCellKey = (cell: Omit<CellIdentifier, \"id\">): string => {\n return `${cell.row}-${cell.col}`;\n};\n\nexport const useGridCellSelection = () => {\n const [selectionState, setSelectionState] = useState<SelectionState>({\n selectedCells: new Set(),\n });\n\n const toggleCellSelection = (cell: CellIdentifier, ctrlKey = false, shiftKey = false, newSelection = false) => {\n setSelectionState((prevState) => {\n const selectedCells = new Set(prevState.selectedCells);\n const cellKey = getCellKey(cell);\n\n if (prevState.startCell && !newSelection) {\n handleRangeSelection(selectedCells, prevState.startCell, cell);\n } else if ((shiftKey || ctrlKey) && newSelection) {\n handleSingleOrMultipleSelection(selectedCells, cellKey);\n } else {\n selectedCells.clear();\n selectedCells.add(cellKey);\n }\n\n return {\n ...prevState,\n selectedCells,\n startCell: newSelection ? cell : prevState.startCell,\n };\n });\n };\n\n const isCellSelected = (cell: CellIdentifier) => {\n return selectionState.selectedCells.has(getCellKey(cell));\n };\n\n const { handleMouseDown, handleMouseEnter, handleMouseUp } = useMouseDragSelection(toggleCellSelection);\n\n return {\n selectedCells: selectionState.selectedCells,\n isCellSelected,\n handleMouseDown,\n handleMouseEnter,\n handleMouseUp,\n };\n};\n\n// New helper functions\nfunction handleRangeSelection(selectedCells: Set<string>, startCell: CellIdentifier, endCell: CellIdentifier) {\n const action = selectedCells.has(getCellKey(startCell)) ? \"add\" : \"delete\";\n const [startRow, startCol] = [startCell.row, startCell.col];\n const [endRow, endCol] = [endCell.row, endCell.col];\n\n const minRow = Math.min(startRow, endRow);\n const maxRow = Math.max(startRow, endRow);\n const minCol = Math.min(startCol, endCol);\n const maxCol = Math.max(startCol, endCol);\n\n for (let row = minRow; row <= maxRow; row++) {\n for (let col = minCol; col <= maxCol; col++) {\n selectedCells[action](getCellKey({ row, col }));\n }\n }\n}\n\nfunction handleSingleOrMultipleSelection(selectedCells: Set<string>, cellKey: string) {\n if (selectedCells.has(cellKey)) {\n selectedCells.delete(cellKey);\n } else {\n selectedCells.add(cellKey);\n }\n}\n"],"names":["useState"],"mappings":"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"}
|
package/dist/main.d.ts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
import "./index.css";
|
package/package.json
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
{
|
2
|
+
"name": "grid-cell-selection",
|
3
|
+
"version": "1.0.0",
|
4
|
+
"description": "A React hook for grid cell selection",
|
5
|
+
"main": "dist/index.js",
|
6
|
+
"module": "dist/index.esm.js",
|
7
|
+
"types": "dist/index.d.ts",
|
8
|
+
"files": [
|
9
|
+
"dist"
|
10
|
+
],
|
11
|
+
"scripts": {
|
12
|
+
"dev": "vite",
|
13
|
+
"build": "rollup -c && tsc --emitDeclarationOnly",
|
14
|
+
"lint": "eslint .",
|
15
|
+
"preview": "vite preview",
|
16
|
+
"prepublishOnly": "npm run build"
|
17
|
+
},
|
18
|
+
"dependencies": {
|
19
|
+
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
|
20
|
+
"react-dom": "^18.3.1"
|
21
|
+
},
|
22
|
+
"peerDependencies": {
|
23
|
+
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
24
|
+
},
|
25
|
+
"devDependencies": {
|
26
|
+
"@eslint/js": "^9.11.1",
|
27
|
+
"@types/react": "^18.0.0",
|
28
|
+
"@types/react-dom": "^18.3.0",
|
29
|
+
"@vitejs/plugin-react": "^4.3.2",
|
30
|
+
"eslint": "^9.11.1",
|
31
|
+
"eslint-plugin-react-hooks": "^5.1.0-rc.0",
|
32
|
+
"eslint-plugin-react-refresh": "^0.4.12",
|
33
|
+
"globals": "^15.9.0",
|
34
|
+
"rollup": "^2.79.1",
|
35
|
+
"rollup-plugin-typescript2": "^0.31.2",
|
36
|
+
"typescript": "^4.9.5",
|
37
|
+
"typescript-eslint": "^8.7.0",
|
38
|
+
"vite": "^5.4.8"
|
39
|
+
},
|
40
|
+
"keywords": [
|
41
|
+
"react",
|
42
|
+
"hook",
|
43
|
+
"grid",
|
44
|
+
"cell",
|
45
|
+
"selection"
|
46
|
+
],
|
47
|
+
"author": "Atticus Thomson",
|
48
|
+
"license": "MIT",
|
49
|
+
"repository": {
|
50
|
+
"type": "git",
|
51
|
+
"url": "https://github.com/attithom/grid-cell-selection.git"
|
52
|
+
}
|
53
|
+
}
|