gp-grid-react 0.1.2 → 0.1.4
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 +203 -0
- package/README.md +593 -520
- package/dist/index.d.ts +89 -6
- package/dist/index.js +35 -15
- package/dist/index.js.map +1 -1
- package/package.json +50 -10
- package/src/Grid.tsx +0 -1334
- package/src/SlotRow.tsx +0 -258
- package/src/index.ts +0 -47
- package/src/styles.ts +0 -440
- package/tsconfig.json +0 -29
- package/tsdown.config.ts +0 -11
- package/vitest.config.ts +0 -16
package/dist/index.d.ts
CHANGED
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
3
2
|
|
|
4
3
|
//#region ../core/src/types.d.ts
|
|
4
|
+
/** Cell data type primitive types */
|
|
5
5
|
type CellDataType = "text" | "number" | "boolean" | "date" | "dateString" | "dateTime" | "dateTimeString" | "object";
|
|
6
|
+
/** Cell value type */
|
|
6
7
|
type CellValue = string | number | boolean | Date | object | null;
|
|
8
|
+
/** Row type */
|
|
7
9
|
type Row = unknown;
|
|
10
|
+
/** Sort direction type */
|
|
8
11
|
type SortDirection = "asc" | "desc";
|
|
12
|
+
/** Sort model type */
|
|
9
13
|
type SortModel = {
|
|
10
14
|
colId: string;
|
|
11
15
|
direction: SortDirection;
|
|
12
16
|
};
|
|
17
|
+
/** Filter model type */
|
|
13
18
|
type FilterModel = Record<string, string>;
|
|
14
19
|
interface ColumnDefinition {
|
|
15
20
|
field: string;
|
|
@@ -33,68 +38,88 @@ interface CellRange {
|
|
|
33
38
|
endRow: number;
|
|
34
39
|
endCol: number;
|
|
35
40
|
}
|
|
41
|
+
/** Data source request */
|
|
36
42
|
interface DataSourceRequest {
|
|
43
|
+
/** Pagination */
|
|
37
44
|
pagination: {
|
|
45
|
+
/** Page index */
|
|
38
46
|
pageIndex: number;
|
|
47
|
+
/** Page size */
|
|
39
48
|
pageSize: number;
|
|
40
49
|
};
|
|
50
|
+
/** Sort */
|
|
41
51
|
sort?: SortModel[];
|
|
52
|
+
/** Filter */
|
|
42
53
|
filter?: FilterModel;
|
|
43
54
|
}
|
|
55
|
+
/** Data source response */
|
|
44
56
|
interface DataSourceResponse<TData = Row> {
|
|
57
|
+
/** Rows */
|
|
45
58
|
rows: TData[];
|
|
59
|
+
/** Total rows */
|
|
46
60
|
totalRows: number;
|
|
47
61
|
}
|
|
48
62
|
interface DataSource<TData = Row> {
|
|
49
63
|
fetch(request: DataSourceRequest): Promise<DataSourceResponse<TData>>;
|
|
50
64
|
}
|
|
65
|
+
/** Slot lifecycle instructions */
|
|
51
66
|
interface CreateSlotInstruction {
|
|
52
67
|
type: "CREATE_SLOT";
|
|
53
68
|
slotId: string;
|
|
54
69
|
}
|
|
70
|
+
/** Destroy slot instruction */
|
|
55
71
|
interface DestroySlotInstruction {
|
|
56
72
|
type: "DESTROY_SLOT";
|
|
57
73
|
slotId: string;
|
|
58
74
|
}
|
|
75
|
+
/** Assign slot instruction */
|
|
59
76
|
interface AssignSlotInstruction {
|
|
60
77
|
type: "ASSIGN_SLOT";
|
|
61
78
|
slotId: string;
|
|
62
79
|
rowIndex: number;
|
|
63
80
|
rowData: Row;
|
|
64
81
|
}
|
|
82
|
+
/** Move slot instruction */
|
|
65
83
|
interface MoveSlotInstruction {
|
|
66
84
|
type: "MOVE_SLOT";
|
|
67
85
|
slotId: string;
|
|
68
86
|
translateY: number;
|
|
69
87
|
}
|
|
88
|
+
/** Selection instructions */
|
|
70
89
|
interface SetActiveCellInstruction {
|
|
71
90
|
type: "SET_ACTIVE_CELL";
|
|
72
91
|
position: CellPosition | null;
|
|
73
92
|
}
|
|
93
|
+
/** Set selection range instruction */
|
|
74
94
|
interface SetSelectionRangeInstruction {
|
|
75
95
|
type: "SET_SELECTION_RANGE";
|
|
76
96
|
range: CellRange | null;
|
|
77
97
|
}
|
|
98
|
+
/** Edit instructions */
|
|
78
99
|
interface StartEditInstruction {
|
|
79
100
|
type: "START_EDIT";
|
|
80
101
|
row: number;
|
|
81
102
|
col: number;
|
|
82
103
|
initialValue: CellValue;
|
|
83
104
|
}
|
|
105
|
+
/** Stop edit instruction */
|
|
84
106
|
interface StopEditInstruction {
|
|
85
107
|
type: "STOP_EDIT";
|
|
86
108
|
}
|
|
109
|
+
/** Commit edit instruction */
|
|
87
110
|
interface CommitEditInstruction {
|
|
88
111
|
type: "COMMIT_EDIT";
|
|
89
112
|
row: number;
|
|
90
113
|
col: number;
|
|
91
114
|
value: CellValue;
|
|
92
115
|
}
|
|
116
|
+
/** Layout instructions */
|
|
93
117
|
interface SetContentSizeInstruction {
|
|
94
118
|
type: "SET_CONTENT_SIZE";
|
|
95
119
|
width: number;
|
|
96
120
|
height: number;
|
|
97
121
|
}
|
|
122
|
+
/** Update header instruction */
|
|
98
123
|
interface UpdateHeaderInstruction {
|
|
99
124
|
type: "UPDATE_HEADER";
|
|
100
125
|
colIndex: number;
|
|
@@ -102,15 +127,18 @@ interface UpdateHeaderInstruction {
|
|
|
102
127
|
sortDirection?: SortDirection;
|
|
103
128
|
sortIndex?: number;
|
|
104
129
|
}
|
|
130
|
+
/** Fill handle instructions */
|
|
105
131
|
interface StartFillInstruction {
|
|
106
132
|
type: "START_FILL";
|
|
107
133
|
sourceRange: CellRange;
|
|
108
134
|
}
|
|
135
|
+
/** Update fill instruction */
|
|
109
136
|
interface UpdateFillInstruction {
|
|
110
137
|
type: "UPDATE_FILL";
|
|
111
138
|
targetRow: number;
|
|
112
139
|
targetCol: number;
|
|
113
140
|
}
|
|
141
|
+
/** Commit fill instruction */
|
|
114
142
|
interface CommitFillInstruction {
|
|
115
143
|
type: "COMMIT_FILL";
|
|
116
144
|
filledCells: Array<{
|
|
@@ -119,42 +147,73 @@ interface CommitFillInstruction {
|
|
|
119
147
|
value: CellValue;
|
|
120
148
|
}>;
|
|
121
149
|
}
|
|
150
|
+
/** Cancel fill instruction */
|
|
122
151
|
interface CancelFillInstruction {
|
|
123
152
|
type: "CANCEL_FILL";
|
|
124
153
|
}
|
|
154
|
+
/** Data loading instruction */
|
|
125
155
|
interface DataLoadingInstruction {
|
|
126
156
|
type: "DATA_LOADING";
|
|
127
157
|
}
|
|
158
|
+
/** Data loaded instruction */
|
|
128
159
|
interface DataLoadedInstruction {
|
|
129
160
|
type: "DATA_LOADED";
|
|
130
161
|
totalRows: number;
|
|
131
162
|
}
|
|
163
|
+
/** Data error instruction */
|
|
132
164
|
interface DataErrorInstruction {
|
|
133
165
|
type: "DATA_ERROR";
|
|
134
166
|
error: string;
|
|
135
167
|
}
|
|
136
|
-
|
|
168
|
+
/** Union type of all instructions */
|
|
169
|
+
type GridInstruction = /** Slot lifecycle */
|
|
170
|
+
CreateSlotInstruction | DestroySlotInstruction | AssignSlotInstruction | MoveSlotInstruction
|
|
171
|
+
/** Selection */ | SetActiveCellInstruction | SetSelectionRangeInstruction
|
|
172
|
+
/** Editing */ | StartEditInstruction | StopEditInstruction | CommitEditInstruction
|
|
173
|
+
/** Layout */ | SetContentSizeInstruction | UpdateHeaderInstruction
|
|
174
|
+
/** Fill handle */ | StartFillInstruction | UpdateFillInstruction | CommitFillInstruction | CancelFillInstruction
|
|
175
|
+
/** Data */ | DataLoadingInstruction | DataLoadedInstruction | DataErrorInstruction;
|
|
176
|
+
/** Cell renderer params */
|
|
137
177
|
interface CellRendererParams {
|
|
178
|
+
/** Cell value */
|
|
138
179
|
value: CellValue;
|
|
180
|
+
/** Row data */
|
|
139
181
|
rowData: Row;
|
|
182
|
+
/** Column definition */
|
|
140
183
|
column: ColumnDefinition;
|
|
184
|
+
/** Row index */
|
|
141
185
|
rowIndex: number;
|
|
186
|
+
/** Column index */
|
|
142
187
|
colIndex: number;
|
|
188
|
+
/** Is active cell */
|
|
143
189
|
isActive: boolean;
|
|
190
|
+
/** Is selected cell */
|
|
144
191
|
isSelected: boolean;
|
|
192
|
+
/** Is editing cell */
|
|
145
193
|
isEditing: boolean;
|
|
146
194
|
}
|
|
195
|
+
/** Edit renderer params */
|
|
147
196
|
interface EditRendererParams extends CellRendererParams {
|
|
197
|
+
/** Initial value */
|
|
148
198
|
initialValue: CellValue;
|
|
199
|
+
/** On value change */
|
|
149
200
|
onValueChange: (newValue: CellValue) => void;
|
|
201
|
+
/** On commit */
|
|
150
202
|
onCommit: () => void;
|
|
203
|
+
/** On cancel */
|
|
151
204
|
onCancel: () => void;
|
|
152
205
|
}
|
|
206
|
+
/** Header renderer params */
|
|
153
207
|
interface HeaderRendererParams {
|
|
208
|
+
/** Column definition */
|
|
154
209
|
column: ColumnDefinition;
|
|
210
|
+
/** Column index */
|
|
155
211
|
colIndex: number;
|
|
212
|
+
/** Sort direction */
|
|
156
213
|
sortDirection?: SortDirection;
|
|
214
|
+
/** Sort index */
|
|
157
215
|
sortIndex?: number;
|
|
216
|
+
/** On sort */
|
|
158
217
|
onSort: (direction: SortDirection | null, addToExisting: boolean) => void;
|
|
159
218
|
}
|
|
160
219
|
//#endregion
|
|
@@ -162,10 +221,13 @@ interface HeaderRendererParams {
|
|
|
162
221
|
/**
|
|
163
222
|
* Creates a client-side data source that holds all data in memory.
|
|
164
223
|
* Sorting and filtering are performed client-side.
|
|
224
|
+
* For large datasets (10k+ rows), sorting is automatically offloaded to a Web Worker.
|
|
165
225
|
*/
|
|
166
226
|
declare function createClientDataSource<TData extends Row = Row>(data: TData[], options?: {
|
|
167
227
|
/** Custom field accessor for nested properties */
|
|
168
228
|
getFieldValue?: (row: TData, field: string) => CellValue;
|
|
229
|
+
/** Use Web Worker for sorting large datasets (default: true) */
|
|
230
|
+
useWorker?: boolean;
|
|
169
231
|
}): DataSource<TData>;
|
|
170
232
|
type ServerFetchFunction<TData> = (request: DataSourceRequest) => Promise<DataSourceResponse<TData>>;
|
|
171
233
|
/**
|
|
@@ -180,32 +242,53 @@ declare function createServerDataSource<TData extends Row = Row>(fetchFn: Server
|
|
|
180
242
|
declare function createDataSourceFromArray<TData extends Row = Row>(data: TData[]): DataSource<TData>;
|
|
181
243
|
//#endregion
|
|
182
244
|
//#region src/Grid.d.ts
|
|
245
|
+
/** React cell renderer: A function that renders a cell */
|
|
183
246
|
type ReactCellRenderer = (params: CellRendererParams) => React.ReactNode;
|
|
247
|
+
/** React edit renderer: A function that renders the cell while in edit mode */
|
|
184
248
|
type ReactEditRenderer = (params: EditRendererParams) => React.ReactNode;
|
|
249
|
+
/** React header renderer: A function that renders a header cell */
|
|
185
250
|
type ReactHeaderRenderer = (params: HeaderRendererParams) => React.ReactNode;
|
|
251
|
+
/** Grid component props */
|
|
186
252
|
interface GridProps<TData extends Row = Row> {
|
|
253
|
+
/** Column definitions */
|
|
187
254
|
columns: ColumnDefinition[];
|
|
188
255
|
/** Data source for the grid */
|
|
189
256
|
dataSource?: DataSource<TData>;
|
|
190
257
|
/** Legacy: Raw row data (will be wrapped in a client data source) */
|
|
191
258
|
rowData?: TData[];
|
|
259
|
+
/** Row height in pixels */
|
|
192
260
|
rowHeight: number;
|
|
261
|
+
/** Header height in pixels: Default to row height */
|
|
193
262
|
headerHeight?: number;
|
|
263
|
+
/** Overscan: How many rows to render outside the viewport */
|
|
194
264
|
overscan?: number;
|
|
195
|
-
/** Show filter row below headers */
|
|
265
|
+
/** Show filter row below headers: Default to false */
|
|
196
266
|
showFilters?: boolean;
|
|
197
|
-
/** Debounce time for filter input (ms) */
|
|
267
|
+
/** Debounce time for filter input (ms): Default to 300 */
|
|
198
268
|
filterDebounce?: number;
|
|
199
|
-
/** Enable dark mode styling */
|
|
269
|
+
/** Enable dark mode styling: Default to false */
|
|
200
270
|
darkMode?: boolean;
|
|
271
|
+
/** Wheel scroll dampening factor when virtual scrolling is active (0-1): Default 0.1 */
|
|
272
|
+
wheelDampening?: number;
|
|
273
|
+
/** Renderer registries */
|
|
201
274
|
cellRenderers?: Record<string, ReactCellRenderer>;
|
|
275
|
+
/** Edit renderer registries */
|
|
202
276
|
editRenderers?: Record<string, ReactEditRenderer>;
|
|
277
|
+
/** Header renderer registries */
|
|
203
278
|
headerRenderers?: Record<string, ReactHeaderRenderer>;
|
|
279
|
+
/** Global cell renderer */
|
|
204
280
|
cellRenderer?: ReactCellRenderer;
|
|
281
|
+
/** Global edit renderer */
|
|
205
282
|
editRenderer?: ReactEditRenderer;
|
|
283
|
+
/** Global header renderer */
|
|
206
284
|
headerRenderer?: ReactHeaderRenderer;
|
|
207
285
|
}
|
|
208
|
-
|
|
286
|
+
/**
|
|
287
|
+
* Grid component
|
|
288
|
+
* @param props - Grid component props
|
|
289
|
+
* @returns Grid React component
|
|
290
|
+
*/
|
|
291
|
+
declare function Grid<TData extends Row = Row>(props: GridProps<TData>): React.ReactNode;
|
|
209
292
|
//#endregion
|
|
210
293
|
export { type CellDataType, type CellPosition, type CellRange, type CellRendererParams, type CellValue, type ColumnDefinition, type DataSource, type DataSourceRequest, type DataSourceResponse, type EditRendererParams, type FilterModel, Grid, type GridInstruction, type GridProps, type HeaderRendererParams, type ReactCellRenderer, type ReactEditRenderer, type ReactHeaderRenderer, type Row, type SortDirection, type SortModel, createClientDataSource, createDataSourceFromArray, createServerDataSource };
|
|
211
294
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -540,9 +540,14 @@ function createInitialState() {
|
|
|
540
540
|
totalRows: 0
|
|
541
541
|
};
|
|
542
542
|
}
|
|
543
|
+
/**
|
|
544
|
+
* Grid component
|
|
545
|
+
* @param props - Grid component props
|
|
546
|
+
* @returns Grid React component
|
|
547
|
+
*/
|
|
543
548
|
function Grid(props) {
|
|
544
549
|
injectStyles();
|
|
545
|
-
const { columns, dataSource: providedDataSource, rowData, rowHeight, headerHeight = rowHeight, overscan = 3, showFilters = false, filterDebounce = 300, darkMode = false, cellRenderers = {}, editRenderers = {}, headerRenderers = {}, cellRenderer, editRenderer, headerRenderer } = props;
|
|
550
|
+
const { columns, dataSource: providedDataSource, rowData, rowHeight, headerHeight = rowHeight, overscan = 3, showFilters = false, filterDebounce = 300, darkMode = false, wheelDampening = .1, cellRenderers = {}, editRenderers = {}, headerRenderers = {}, cellRenderer, editRenderer, headerRenderer } = props;
|
|
546
551
|
const containerRef = useRef(null);
|
|
547
552
|
const coreRef = useRef(null);
|
|
548
553
|
const [state, dispatch] = useReducer(gridReducer, null, createInitialState);
|
|
@@ -603,6 +608,15 @@ function Grid(props) {
|
|
|
603
608
|
if (!container || !core) return;
|
|
604
609
|
core.setViewport(container.scrollTop, container.scrollLeft, container.clientWidth, container.clientHeight);
|
|
605
610
|
}, []);
|
|
611
|
+
const handleWheel = useCallback((e) => {
|
|
612
|
+
const container = containerRef.current;
|
|
613
|
+
const core = coreRef.current;
|
|
614
|
+
if (!container || !core) return;
|
|
615
|
+
if (!core.isScalingActive()) return;
|
|
616
|
+
e.preventDefault();
|
|
617
|
+
container.scrollTop += e.deltaY * wheelDampening;
|
|
618
|
+
container.scrollLeft += e.deltaX * wheelDampening;
|
|
619
|
+
}, [wheelDampening]);
|
|
606
620
|
useEffect(() => {
|
|
607
621
|
const container = containerRef.current;
|
|
608
622
|
const core = coreRef.current;
|
|
@@ -696,23 +710,24 @@ function Grid(props) {
|
|
|
696
710
|
if (!state.activeCell || !containerRef.current || state.editingCell) return;
|
|
697
711
|
const { row, col } = state.activeCell;
|
|
698
712
|
const container = containerRef.current;
|
|
699
|
-
const
|
|
700
|
-
|
|
713
|
+
const core = coreRef.current;
|
|
714
|
+
if (!core) return;
|
|
715
|
+
const { start: visibleStart, end: visibleEnd } = core.getVisibleRowRange();
|
|
716
|
+
if (row < visibleStart) container.scrollTop = core.getScrollTopForRow(row);
|
|
717
|
+
else if (row > visibleEnd) {
|
|
718
|
+
const visibleRows = Math.max(1, visibleEnd - visibleStart);
|
|
719
|
+
const targetFirstRow = Math.max(0, row - visibleRows);
|
|
720
|
+
container.scrollTop = core.getScrollTopForRow(targetFirstRow);
|
|
721
|
+
}
|
|
701
722
|
const cellLeft = columnPositions[col] ?? 0;
|
|
702
723
|
const cellRight = cellLeft + (columns[col]?.width ?? 0);
|
|
703
|
-
const visibleTop = container.scrollTop + totalHeaderHeight;
|
|
704
|
-
const visibleBottom = container.scrollTop + container.clientHeight;
|
|
705
724
|
const visibleLeft = container.scrollLeft;
|
|
706
725
|
const visibleRight = container.scrollLeft + container.clientWidth;
|
|
707
|
-
if (cellTop < visibleTop) container.scrollTop = cellTop - totalHeaderHeight;
|
|
708
|
-
else if (cellBottom > visibleBottom) container.scrollTop = cellBottom - container.clientHeight;
|
|
709
726
|
if (cellLeft < visibleLeft) container.scrollLeft = cellLeft;
|
|
710
727
|
else if (cellRight > visibleRight) container.scrollLeft = cellRight - container.clientWidth;
|
|
711
728
|
}, [
|
|
712
729
|
state.activeCell,
|
|
713
730
|
state.editingCell,
|
|
714
|
-
rowHeight,
|
|
715
|
-
totalHeaderHeight,
|
|
716
731
|
columnPositions,
|
|
717
732
|
columns
|
|
718
733
|
]);
|
|
@@ -782,7 +797,7 @@ function Grid(props) {
|
|
|
782
797
|
const scrollTop = container.scrollTop;
|
|
783
798
|
const mouseX = e.clientX - rect.left + scrollLeft;
|
|
784
799
|
const mouseY = e.clientY - rect.top + scrollTop - totalHeaderHeight;
|
|
785
|
-
const targetRow = Math.max(0,
|
|
800
|
+
const targetRow = Math.max(0, core.getRowIndexAtDisplayY(mouseY, scrollTop));
|
|
786
801
|
let targetCol = 0;
|
|
787
802
|
for (let i = 0; i < columnPositions.length - 1; i++) {
|
|
788
803
|
if (mouseX >= columnPositions[i] && mouseX < columnPositions[i + 1]) {
|
|
@@ -858,7 +873,7 @@ function Grid(props) {
|
|
|
858
873
|
const scrollTop = container.scrollTop;
|
|
859
874
|
const mouseX = e.clientX - rect.left + scrollLeft;
|
|
860
875
|
const mouseY = e.clientY - rect.top + scrollTop - totalHeaderHeight;
|
|
861
|
-
const targetRow = Math.max(0, Math.min(
|
|
876
|
+
const targetRow = Math.max(0, Math.min(core.getRowIndexAtDisplayY(mouseY, scrollTop), core.getRowCount() - 1));
|
|
862
877
|
let targetCol = 0;
|
|
863
878
|
for (let i = 0; i < columnPositions.length - 1; i++) {
|
|
864
879
|
if (mouseX >= columnPositions[i] && mouseX < columnPositions[i + 1]) {
|
|
@@ -911,7 +926,6 @@ function Grid(props) {
|
|
|
911
926
|
}, [
|
|
912
927
|
isDraggingSelection,
|
|
913
928
|
totalHeaderHeight,
|
|
914
|
-
rowHeight,
|
|
915
929
|
columnPositions,
|
|
916
930
|
columns.length
|
|
917
931
|
]);
|
|
@@ -1060,7 +1074,7 @@ function Grid(props) {
|
|
|
1060
1074
|
}, [headerRenderers, headerRenderer]);
|
|
1061
1075
|
const slotsArray = useMemo(() => Array.from(state.slots.values()), [state.slots]);
|
|
1062
1076
|
const fillHandlePosition = useMemo(() => {
|
|
1063
|
-
const { activeCell, selectionRange } = state;
|
|
1077
|
+
const { activeCell, selectionRange, slots } = state;
|
|
1064
1078
|
if (!activeCell && !selectionRange) return null;
|
|
1065
1079
|
let row, col;
|
|
1066
1080
|
let minCol, maxCol;
|
|
@@ -1079,7 +1093,12 @@ function Grid(props) {
|
|
|
1079
1093
|
const column = columns[c];
|
|
1080
1094
|
if (!column || column.editable !== true) return null;
|
|
1081
1095
|
}
|
|
1082
|
-
|
|
1096
|
+
let cellTop = null;
|
|
1097
|
+
for (const slot of slots.values()) if (slot.rowIndex === row) {
|
|
1098
|
+
cellTop = slot.translateY;
|
|
1099
|
+
break;
|
|
1100
|
+
}
|
|
1101
|
+
if (cellTop === null) return null;
|
|
1083
1102
|
const cellLeft = columnPositions[col] ?? 0;
|
|
1084
1103
|
const cellWidth = columns[col]?.width ?? 0;
|
|
1085
1104
|
return {
|
|
@@ -1089,8 +1108,8 @@ function Grid(props) {
|
|
|
1089
1108
|
}, [
|
|
1090
1109
|
state.activeCell,
|
|
1091
1110
|
state.selectionRange,
|
|
1111
|
+
state.slots,
|
|
1092
1112
|
rowHeight,
|
|
1093
|
-
totalHeaderHeight,
|
|
1094
1113
|
columnPositions,
|
|
1095
1114
|
columns
|
|
1096
1115
|
]);
|
|
@@ -1104,6 +1123,7 @@ function Grid(props) {
|
|
|
1104
1123
|
position: "relative"
|
|
1105
1124
|
},
|
|
1106
1125
|
onScroll: handleScroll,
|
|
1126
|
+
onWheel: handleWheel,
|
|
1107
1127
|
onKeyDown: handleKeyDown,
|
|
1108
1128
|
tabIndex: 0,
|
|
1109
1129
|
children: /* @__PURE__ */ jsxs("div", {
|