@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.
Files changed (208) hide show
  1. package/LICENSE.md +100 -0
  2. package/Readme.md +53 -59
  3. package/dist/cjs/Cell.d.ts +35 -0
  4. package/dist/cjs/Cell.d.ts.map +1 -0
  5. package/dist/cjs/Cell.js +29 -0
  6. package/dist/{CellOverlay.d.ts → cjs/CellOverlay.d.ts} +5 -5
  7. package/dist/cjs/CellOverlay.d.ts.map +1 -0
  8. package/dist/cjs/CellOverlay.js +126 -0
  9. package/dist/cjs/Context.d.ts +8 -0
  10. package/dist/cjs/Context.d.ts.map +1 -0
  11. package/dist/cjs/Context.js +13 -0
  12. package/dist/{FillHandle.d.ts → cjs/FillHandle.d.ts} +2 -1
  13. package/dist/cjs/FillHandle.d.ts.map +1 -0
  14. package/dist/cjs/FillHandle.js +26 -0
  15. package/dist/cjs/Grid.d.ts +558 -0
  16. package/dist/cjs/Grid.d.ts.map +1 -0
  17. package/dist/cjs/Grid.js +2446 -0
  18. package/dist/{GridLine.d.ts → cjs/GridLine.d.ts} +2 -1
  19. package/dist/cjs/GridLine.d.ts.map +1 -0
  20. package/dist/cjs/GridLine.js +10 -0
  21. package/dist/cjs/Image.d.ts +11 -0
  22. package/dist/cjs/Image.d.ts.map +1 -0
  23. package/dist/cjs/Image.js +57 -0
  24. package/dist/cjs/MemoizedGrid.d.ts +49 -0
  25. package/dist/cjs/MemoizedGrid.d.ts.map +1 -0
  26. package/dist/cjs/MemoizedGrid.js +105 -0
  27. package/dist/cjs/Selection.d.ts +5 -0
  28. package/dist/cjs/Selection.d.ts.map +1 -0
  29. package/dist/cjs/Selection.js +10 -0
  30. package/dist/{helpers.d.ts → cjs/helpers.d.ts} +59 -39
  31. package/dist/cjs/helpers.d.ts.map +1 -0
  32. package/dist/cjs/helpers.js +1409 -0
  33. package/dist/{hooks → cjs/hooks}/useCopyPaste.d.ts +3 -2
  34. package/dist/cjs/hooks/useCopyPaste.d.ts.map +1 -0
  35. package/dist/cjs/hooks/useCopyPaste.js +230 -0
  36. package/dist/{hooks → cjs/hooks}/useEditable.d.ts +21 -8
  37. package/dist/cjs/hooks/useEditable.d.ts.map +1 -0
  38. package/dist/cjs/hooks/useEditable.js +491 -0
  39. package/dist/{hooks → cjs/hooks}/useFilter.d.ts +3 -2
  40. package/dist/cjs/hooks/useFilter.d.ts.map +1 -0
  41. package/dist/cjs/hooks/useFilter.js +97 -0
  42. package/dist/{hooks → cjs/hooks}/useImage.d.ts +1 -0
  43. package/dist/cjs/hooks/useImage.d.ts.map +1 -0
  44. package/dist/cjs/hooks/useImage.js +80 -0
  45. package/dist/{hooks → cjs/hooks}/usePagination.d.ts +3 -2
  46. package/dist/cjs/hooks/usePagination.d.ts.map +1 -0
  47. package/dist/cjs/hooks/usePagination.js +53 -0
  48. package/dist/{hooks → cjs/hooks}/useSizer.d.ts +28 -29
  49. package/dist/cjs/hooks/useSizer.d.ts.map +1 -0
  50. package/dist/cjs/hooks/useSizer.js +176 -0
  51. package/dist/{hooks → cjs/hooks}/useTooltip.d.ts +2 -1
  52. package/dist/cjs/hooks/useTooltip.d.ts.map +1 -0
  53. package/dist/cjs/hooks/useTooltip.js +82 -0
  54. package/dist/{hooks → cjs/hooks}/useUndo.d.ts +2 -1
  55. package/dist/cjs/hooks/useUndo.d.ts.map +1 -0
  56. package/dist/cjs/hooks/useUndo.js +87 -0
  57. package/dist/cjs/index.d.ts +19 -0
  58. package/dist/cjs/index.d.ts.map +1 -0
  59. package/dist/cjs/index.js +29 -0
  60. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -0
  61. package/dist/{types.d.ts → cjs/types.d.ts} +8 -3
  62. package/dist/cjs/types.d.ts.map +1 -0
  63. package/dist/{types.js → cjs/types.js} +7 -8
  64. package/dist/cjs/utils.d.ts +9 -0
  65. package/dist/cjs/utils.d.ts.map +1 -0
  66. package/dist/cjs/utils.js +58 -0
  67. package/dist/cjs/vitest.config.d.ts +3 -0
  68. package/dist/cjs/vitest.config.d.ts.map +1 -0
  69. package/dist/cjs/vitest.config.js +24 -0
  70. package/dist/esm/Cell.d.ts +35 -0
  71. package/dist/esm/Cell.d.ts.map +1 -0
  72. package/dist/esm/Cell.js +24 -0
  73. package/dist/esm/CellOverlay.d.ts +21 -0
  74. package/dist/esm/CellOverlay.d.ts.map +1 -0
  75. package/dist/esm/CellOverlay.js +120 -0
  76. package/dist/esm/Context.d.ts +8 -0
  77. package/dist/esm/Context.d.ts.map +1 -0
  78. package/dist/esm/Context.js +9 -0
  79. package/dist/esm/FillHandle.d.ts +8 -0
  80. package/dist/esm/FillHandle.d.ts.map +1 -0
  81. package/dist/{FillHandle.js → esm/FillHandle.js} +5 -11
  82. package/dist/esm/Grid.d.ts +558 -0
  83. package/dist/esm/Grid.d.ts.map +1 -0
  84. package/dist/esm/Grid.js +2451 -0
  85. package/dist/esm/GridLine.d.ts +5 -0
  86. package/dist/esm/GridLine.d.ts.map +1 -0
  87. package/dist/esm/GridLine.js +7 -0
  88. package/dist/esm/Image.d.ts +11 -0
  89. package/dist/esm/Image.d.ts.map +1 -0
  90. package/dist/esm/Image.js +53 -0
  91. package/dist/esm/MemoizedGrid.d.ts +49 -0
  92. package/dist/esm/MemoizedGrid.d.ts.map +1 -0
  93. package/dist/esm/MemoizedGrid.js +98 -0
  94. package/dist/esm/Selection.d.ts +5 -0
  95. package/dist/esm/Selection.d.ts.map +1 -0
  96. package/dist/esm/Selection.js +7 -0
  97. package/dist/esm/helpers.d.ts +281 -0
  98. package/dist/esm/helpers.d.ts.map +1 -0
  99. package/dist/esm/helpers.js +1260 -0
  100. package/dist/esm/hooks/useCopyPaste.d.ts +53 -0
  101. package/dist/esm/hooks/useCopyPaste.d.ts.map +1 -0
  102. package/dist/{hooks → esm/hooks}/useCopyPaste.js +40 -46
  103. package/dist/esm/hooks/useEditable.d.ts +253 -0
  104. package/dist/esm/hooks/useEditable.d.ts.map +1 -0
  105. package/dist/esm/hooks/useEditable.js +482 -0
  106. package/dist/esm/hooks/useFilter.d.ts +69 -0
  107. package/dist/esm/hooks/useFilter.d.ts.map +1 -0
  108. package/dist/{hooks → esm/hooks}/useFilter.js +22 -42
  109. package/dist/esm/hooks/useImage.d.ts +13 -0
  110. package/dist/esm/hooks/useImage.d.ts.map +1 -0
  111. package/dist/esm/hooks/useImage.js +76 -0
  112. package/dist/esm/hooks/usePagination.d.ts +69 -0
  113. package/dist/esm/hooks/usePagination.d.ts.map +1 -0
  114. package/dist/esm/hooks/usePagination.js +47 -0
  115. package/dist/esm/hooks/useSizer.d.ts +114 -0
  116. package/dist/esm/hooks/useSizer.d.ts.map +1 -0
  117. package/dist/esm/hooks/useSizer.js +176 -0
  118. package/dist/esm/hooks/useTooltip.d.ts +43 -0
  119. package/dist/esm/hooks/useTooltip.d.ts.map +1 -0
  120. package/dist/esm/hooks/useTooltip.js +80 -0
  121. package/dist/esm/hooks/useUndo.d.ts +36 -0
  122. package/dist/esm/hooks/useUndo.d.ts.map +1 -0
  123. package/dist/{hooks → esm/hooks}/useUndo.js +16 -25
  124. package/dist/esm/index.d.ts +19 -0
  125. package/dist/esm/index.d.ts.map +1 -0
  126. package/dist/esm/index.js +17 -0
  127. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -0
  128. package/dist/esm/types.d.ts +70 -0
  129. package/dist/esm/types.d.ts.map +1 -0
  130. package/dist/esm/types.js +68 -0
  131. package/dist/esm/utils.d.ts +9 -0
  132. package/dist/esm/utils.d.ts.map +1 -0
  133. package/dist/esm/utils.js +104 -0
  134. package/dist/esm/vitest.config.d.ts +3 -0
  135. package/dist/esm/vitest.config.d.ts.map +1 -0
  136. package/dist/esm/vitest.config.js +22 -0
  137. package/package.json +28 -29
  138. package/dist/Cell.d.ts +0 -23
  139. package/dist/Cell.js +0 -55
  140. package/dist/Cell.js.map +0 -1
  141. package/dist/CellOverlay.js +0 -116
  142. package/dist/CellOverlay.js.map +0 -1
  143. package/dist/FillHandle.js.map +0 -1
  144. package/dist/Grid.d.ts +0 -385
  145. package/dist/Grid.js +0 -1684
  146. package/dist/Grid.js.map +0 -1
  147. package/dist/GridLine.js +0 -13
  148. package/dist/GridLine.js.map +0 -1
  149. package/dist/Image.d.ts +0 -8
  150. package/dist/Image.js +0 -50
  151. package/dist/Image.js.map +0 -1
  152. package/dist/Selection.d.ts +0 -4
  153. package/dist/Selection.js +0 -9
  154. package/dist/Selection.js.map +0 -1
  155. package/dist/helpers.js +0 -1033
  156. package/dist/helpers.js.map +0 -1
  157. package/dist/hooks/useCopyPaste.js.map +0 -1
  158. package/dist/hooks/useEditable.js +0 -477
  159. package/dist/hooks/useEditable.js.map +0 -1
  160. package/dist/hooks/useFilter.js.map +0 -1
  161. package/dist/hooks/useImage.js +0 -42
  162. package/dist/hooks/useImage.js.map +0 -1
  163. package/dist/hooks/usePagination.js +0 -73
  164. package/dist/hooks/usePagination.js.map +0 -1
  165. package/dist/hooks/useSelection.d.ts +0 -175
  166. package/dist/hooks/useSelection.js +0 -980
  167. package/dist/hooks/useSelection.js.map +0 -1
  168. package/dist/hooks/useSizer.js +0 -150
  169. package/dist/hooks/useSizer.js.map +0 -1
  170. package/dist/hooks/useTooltip.js +0 -106
  171. package/dist/hooks/useTooltip.js.map +0 -1
  172. package/dist/hooks/useTouch.d.ts +0 -21
  173. package/dist/hooks/useTouch.js +0 -73
  174. package/dist/hooks/useTouch.js.map +0 -1
  175. package/dist/hooks/useUndo.js.map +0 -1
  176. package/dist/index.d.ts +0 -25
  177. package/dist/index.js +0 -61
  178. package/dist/index.js.map +0 -1
  179. package/dist/types.js.map +0 -1
  180. package/dist/utils.d.ts +0 -8
  181. package/dist/utils.js +0 -153
  182. package/dist/utils.js.map +0 -1
  183. package/src/Cell.tsx +0 -100
  184. package/src/CellOverlay.tsx +0 -191
  185. package/src/FillHandle.tsx +0 -37
  186. package/src/Grid.tsx +0 -2677
  187. package/src/GridLine.tsx +0 -23
  188. package/src/Image.tsx +0 -43
  189. package/src/Selection.tsx +0 -9
  190. package/src/helpers.ts +0 -1455
  191. package/src/hooks/useCopyPaste.ts +0 -265
  192. package/src/hooks/useEditable.tsx +0 -945
  193. package/src/hooks/useFilter.tsx +0 -233
  194. package/src/hooks/useImage.ts +0 -57
  195. package/src/hooks/usePagination.tsx +0 -153
  196. package/src/hooks/useSelection.ts +0 -1437
  197. package/src/hooks/useSizer.ts +0 -312
  198. package/src/hooks/useTooltip.tsx +0 -172
  199. package/src/hooks/useTouch.ts +0 -116
  200. package/src/hooks/useUndo.ts +0 -134
  201. package/src/index.tsx +0 -46
  202. package/src/tests/Grid.spec.tsx +0 -47
  203. package/src/tests/helpers.test.ts +0 -292
  204. package/src/tests/usePagination.test.ts +0 -28
  205. package/src/tests/useSelection.test.ts +0 -27
  206. package/src/tests/useUndo.test.ts +0 -73
  207. package/src/types.ts +0 -69
  208. package/src/utils.tsx +0 -287
package/dist/Grid.js DELETED
@@ -1,1684 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
- var __importDefault = (this && this.__importDefault) || function (mod) {
26
- return (mod && mod.__esModule) ? mod : { "default": mod };
27
- };
28
- Object.defineProperty(exports, "__esModule", { value: true });
29
- exports.RESET_SCROLL_EVENTS_DEBOUNCE_INTERVAL = void 0;
30
- const react_1 = __importStar(require("react"));
31
- const react_konva_1 = require("react-konva");
32
- const helpers_1 = require("./helpers");
33
- const Cell_1 = require("./Cell");
34
- const CellOverlay_1 = require("./CellOverlay");
35
- const Selection_1 = __importDefault(require("./Selection"));
36
- const FillHandle_1 = __importDefault(require("./FillHandle"));
37
- const GridLine_1 = __importDefault(require("./GridLine"));
38
- const utils_1 = require("./utils");
39
- const tiny_invariant_1 = __importDefault(require("tiny-invariant"));
40
- const types_1 = require("./types");
41
- const DEFAULT_ESTIMATED_ITEM_SIZE = 50;
42
- const defaultShadowSettings = {
43
- strokeWidth: 1,
44
- };
45
- const defaultRowHeight = () => 20;
46
- const defaultColumnWidth = () => 60;
47
- const defaultSelectionRenderer = (props) => {
48
- return react_1.default.createElement(Selection_1.default, { ...props });
49
- };
50
- const defaultGridLineRenderer = (props) => {
51
- return react_1.default.createElement(GridLine_1.default, { ...props });
52
- };
53
- exports.RESET_SCROLL_EVENTS_DEBOUNCE_INTERVAL = 150;
54
- /* Placeholder for empty array -> Prevents re-render */
55
- const EMPTY_ARRAY = [];
56
- /**
57
- * Grid component using React Konva
58
- * @param props
59
- *
60
- * TODO: Fix bug with snapping, since onWheel is a global handler, rowCount, columnCount becomes state
61
- */
62
- const Grid = (0, react_1.memo)((0, react_1.forwardRef)((props, forwardedRef) => {
63
- const { width: containerWidth = 800, height: containerHeight = 600, estimatedColumnWidth, estimatedRowHeight, rowHeight = defaultRowHeight, columnWidth = defaultColumnWidth, rowCount = 0, columnCount = 0, scrollbarSize = 13, onScroll, onImmediateScroll, showScrollbar = true, selectionBackgroundColor = "rgb(14, 101, 235, 0.1)", selectionBorderColor = "#1a73e8", selectionStrokeWidth = 1, activeCellStrokeWidth = 2, activeCell, selections = EMPTY_ARRAY, frozenRows = 0, frozenColumns = 0, itemRenderer = Cell_1.CellRenderer, enableCellOverlay = false, overlayRenderer = CellOverlay_1.CellRenderer, mergedCells = EMPTY_ARRAY, snap = false, scrollThrottleTimeout = 80, onViewChange, selectionRenderer = defaultSelectionRenderer, onBeforeRenderRow, showFrozenShadow = false, shadowSettings = defaultShadowSettings, borderStyles = EMPTY_ARRAY, children, stageProps, wrapper = (children) => children, cellAreas = EMPTY_ARRAY, showFillHandle = false, fillSelection, overscanCount = 1, fillHandleProps, fillhandleBorderColor = "white", showGridLines = false, gridLineColor = "#E3E2E2", gridLineWidth = 1, gridLineRenderer = defaultGridLineRenderer, isHiddenRow, isHiddenColumn, isHiddenCell, scale = 1, enableSelectionDrag = false, isDraggingSelection = false, ...rest } = props;
64
- (0, tiny_invariant_1.default)(!(children && typeof children !== "function"), "Children should be a function");
65
- /* Expose some methods in ref */
66
- (0, react_1.useImperativeHandle)(forwardedRef, () => {
67
- return {
68
- scrollTo,
69
- scrollBy,
70
- scrollToItem,
71
- stage: stageRef.current,
72
- container: containerRef.current,
73
- resetAfterIndices,
74
- getScrollPosition,
75
- isMergedCell,
76
- getCellBounds,
77
- getCellCoordsFromOffset,
78
- getCellOffsetFromCoords,
79
- getActualCellCoords,
80
- focus: focusContainer,
81
- resizeColumns,
82
- resizeRows,
83
- getViewPort,
84
- getRelativePositionFromOffset,
85
- scrollToTop,
86
- scrollToBottom,
87
- getDimensions,
88
- getRowOffset,
89
- getColumnOffset,
90
- };
91
- });
92
- const instanceProps = (0, react_1.useRef)({
93
- columnMetadataMap: {},
94
- rowMetadataMap: {},
95
- lastMeasuredColumnIndex: -1,
96
- lastMeasuredRowIndex: -1,
97
- estimatedColumnWidth: estimatedColumnWidth || DEFAULT_ESTIMATED_ITEM_SIZE,
98
- estimatedRowHeight: estimatedRowHeight || DEFAULT_ESTIMATED_ITEM_SIZE,
99
- recalcColumnIndices: [],
100
- recalcRowIndices: [],
101
- });
102
- const stageRef = (0, react_1.useRef)(null);
103
- const containerRef = (0, react_1.useRef)(null);
104
- const scrollContainerRef = (0, react_1.useRef)(null);
105
- const verticalScrollRef = (0, react_1.useRef)(null);
106
- const wheelingRef = (0, react_1.useRef)(null);
107
- const horizontalScrollRef = (0, react_1.useRef)(null);
108
- const [_, forceRender] = (0, react_1.useReducer)((s) => s + 1, 0);
109
- const [scrollState, setScrollState] = (0, react_1.useState)({
110
- scrollTop: 0,
111
- scrollLeft: 0,
112
- isScrolling: false,
113
- verticalScrollDirection: types_1.Direction.Down,
114
- horizontalScrollDirection: types_1.Direction.Right,
115
- });
116
- const scrollSnapRefs = (0, react_1.useRef)(null);
117
- const { scrollTop, scrollLeft, isScrolling, verticalScrollDirection, horizontalScrollDirection, } = scrollState;
118
- const isMounted = (0, react_1.useRef)(false);
119
- /* Focus container */
120
- const focusContainer = (0, react_1.useCallback)(() => {
121
- var _a;
122
- if (helpers_1.canUseDOM && document.activeElement !== containerRef.current) {
123
- return (_a = containerRef.current) === null || _a === void 0 ? void 0 : _a.focus();
124
- }
125
- }, []);
126
- /**
127
- * Get top offset of rowIndex
128
- */
129
- const getRowOffset = (0, react_1.useCallback)((index) => {
130
- return (0, helpers_1.getRowOffset)({
131
- index,
132
- rowHeight,
133
- columnWidth,
134
- instanceProps: instanceProps.current,
135
- scale,
136
- });
137
- }, [rowHeight, columnWidth, instanceProps.current, scale]);
138
- /**
139
- * Get lefft offset of columnIndex
140
- */
141
- const getColumnOffset = (0, react_1.useCallback)((index) => {
142
- return (0, helpers_1.getColumnOffset)({
143
- index,
144
- rowHeight,
145
- columnWidth,
146
- instanceProps: instanceProps.current,
147
- scale,
148
- });
149
- }, [rowHeight, columnWidth, instanceProps.current, scale]);
150
- /**
151
- * Get height of rowIndex
152
- */
153
- const getRowHeight = (0, react_1.useCallback)((index) => {
154
- return (0, helpers_1.getRowHeight)(index, instanceProps.current);
155
- }, [instanceProps.current]);
156
- /**
157
- * Get height of columNiondex
158
- */
159
- const getColumnWidth = (0, react_1.useCallback)((index) => {
160
- return (0, helpers_1.getColumnWidth)(index, instanceProps.current);
161
- }, [instanceProps.current]);
162
- /**
163
- * onScroll callback
164
- */
165
- (0, react_1.useEffect)(() => {
166
- if (!isMounted.current)
167
- return;
168
- onScroll === null || onScroll === void 0 ? void 0 : onScroll({ scrollTop, scrollLeft });
169
- }, [scrollTop, scrollLeft]);
170
- /**
171
- * Handle mouse wheeel
172
- */
173
- (0, react_1.useEffect)(() => {
174
- var _a;
175
- (_a = scrollContainerRef.current) === null || _a === void 0 ? void 0 : _a.addEventListener("wheel", handleWheel, {
176
- passive: false,
177
- });
178
- isMounted.current = true;
179
- return () => {
180
- var _a;
181
- (_a = scrollContainerRef.current) === null || _a === void 0 ? void 0 : _a.removeEventListener("wheel", handleWheel);
182
- };
183
- }, []);
184
- /**
185
- * Imperatively get the current scroll position
186
- */
187
- const getScrollPosition = (0, react_1.useCallback)(() => {
188
- return {
189
- scrollTop,
190
- scrollLeft,
191
- };
192
- }, [scrollTop, scrollLeft]);
193
- /* Redraw grid imperatively */
194
- const resetAfterIndices = (0, react_1.useCallback)(({ columnIndex, rowIndex }, shouldForceUpdate = true) => {
195
- if (typeof columnIndex === "number") {
196
- instanceProps.current.recalcColumnIndices = [];
197
- instanceProps.current.lastMeasuredColumnIndex = Math.min(instanceProps.current.lastMeasuredColumnIndex, columnIndex - 1);
198
- }
199
- if (typeof rowIndex === "number") {
200
- instanceProps.current.recalcRowIndices = [];
201
- instanceProps.current.lastMeasuredRowIndex = Math.min(instanceProps.current.lastMeasuredRowIndex, rowIndex - 1);
202
- }
203
- if (shouldForceUpdate)
204
- forceRender();
205
- }, []);
206
- /**
207
- * Create a map of merged cells
208
- * [rowIndex, columnindex] => [parentRowIndex, parentColumnIndex]
209
- */
210
- const mergedCellMap = (0, react_1.useMemo)(() => {
211
- const mergedCellMap = new Map();
212
- for (let i = 0; i < mergedCells.length; i++) {
213
- const bounds = mergedCells[i];
214
- for (const cell of (0, helpers_1.getBoundedCells)(bounds)) {
215
- mergedCellMap.set(cell, bounds);
216
- }
217
- }
218
- return mergedCellMap;
219
- }, [mergedCells]);
220
- /* Check if a cell is part of a merged cell */
221
- const isMergedCell = (0, react_1.useCallback)(({ rowIndex, columnIndex }) => {
222
- return mergedCellMap.has((0, helpers_1.cellIdentifier)(rowIndex, columnIndex));
223
- }, [mergedCells]);
224
- /* Get top, left bounds of a cell */
225
- const getCellBounds = (0, react_1.useCallback)(({ rowIndex, columnIndex }, spanMerges = true) => {
226
- if (spanMerges) {
227
- const isMerged = isMergedCell({ rowIndex, columnIndex });
228
- if (isMerged)
229
- return mergedCellMap.get((0, helpers_1.cellIdentifier)(rowIndex, columnIndex));
230
- }
231
- return {
232
- top: rowIndex,
233
- left: columnIndex,
234
- right: columnIndex,
235
- bottom: rowIndex,
236
- };
237
- }, [mergedCellMap]);
238
- /* Get top, left bounds of a cell */
239
- const getActualCellCoords = (0, react_1.useCallback)(({ rowIndex, columnIndex }) => {
240
- const isMerged = isMergedCell({ rowIndex, columnIndex });
241
- if (isMerged) {
242
- const cell = mergedCellMap.get((0, helpers_1.cellIdentifier)(rowIndex, columnIndex));
243
- return {
244
- rowIndex: cell === null || cell === void 0 ? void 0 : cell.top,
245
- columnIndex: cell === null || cell === void 0 ? void 0 : cell.left,
246
- };
247
- }
248
- return {
249
- rowIndex,
250
- columnIndex,
251
- };
252
- }, [mergedCellMap]);
253
- const frozenColumnWidth = getColumnOffset(frozenColumns);
254
- const frozenRowHeight = getRowOffset(frozenRows);
255
- const [rowStartIndex, rowStopIndex, visibleRowStartIndex, visibleRowStopIndex,] = (0, react_1.useMemo)(() => {
256
- const startIndex = (0, helpers_1.getRowStartIndexForOffset)({
257
- rowHeight,
258
- columnWidth,
259
- rowCount,
260
- columnCount,
261
- instanceProps: instanceProps.current,
262
- offset: scrollTop + frozenRowHeight,
263
- scale,
264
- });
265
- const stopIndex = (0, helpers_1.getRowStopIndexForStartIndex)({
266
- startIndex,
267
- rowCount,
268
- rowHeight,
269
- columnWidth,
270
- scrollTop,
271
- containerHeight,
272
- instanceProps: instanceProps.current,
273
- scale,
274
- });
275
- // Overscan by one item in each direction so that tab/focus works.
276
- // If there isn't at least one extra item, tab loops back around.
277
- const overscanBackward = !isScrolling || verticalScrollDirection === types_1.Direction.Up
278
- ? Math.max(1, overscanCount)
279
- : 1;
280
- const overscanForward = !isScrolling || verticalScrollDirection === types_1.Direction.Down
281
- ? Math.max(1, overscanCount)
282
- : 1;
283
- return [
284
- Math.max(0, startIndex - overscanBackward),
285
- Math.max(0, Math.min(rowCount - 1, stopIndex + overscanForward)),
286
- startIndex,
287
- stopIndex,
288
- ];
289
- }, [
290
- rowHeight,
291
- columnWidth,
292
- rowCount,
293
- columnCount,
294
- scale,
295
- scrollTop,
296
- containerHeight,
297
- frozenRows,
298
- overscanCount,
299
- frozenRowHeight,
300
- ]);
301
- const [columnStartIndex, columnStopIndex, visibleColumnStartIndex, visibleColumnStopIndex,] = (0, react_1.useMemo)(() => {
302
- const startIndex = (0, helpers_1.getColumnStartIndexForOffset)({
303
- rowHeight,
304
- columnWidth,
305
- rowCount,
306
- columnCount,
307
- instanceProps: instanceProps.current,
308
- offset: scrollLeft + frozenColumnWidth,
309
- scale,
310
- });
311
- const stopIndex = (0, helpers_1.getColumnStopIndexForStartIndex)({
312
- startIndex,
313
- columnCount,
314
- rowHeight,
315
- columnWidth,
316
- scrollLeft,
317
- containerWidth,
318
- instanceProps: instanceProps.current,
319
- scale,
320
- });
321
- // Overscan by one item in each direction so that tab/focus works.
322
- // If there isn't at least one extra item, tab loops back around.
323
- const overscanBackward = !isScrolling || horizontalScrollDirection === types_1.Direction.Left
324
- ? Math.max(1, overscanCount)
325
- : 1;
326
- const overscanForward = !isScrolling || horizontalScrollDirection === types_1.Direction.Right
327
- ? Math.max(1, overscanCount)
328
- : 1;
329
- return [
330
- Math.max(0, startIndex - overscanBackward),
331
- Math.max(0, Math.min(columnCount - 1, stopIndex + overscanForward)),
332
- startIndex,
333
- stopIndex,
334
- ];
335
- }, [
336
- rowHeight,
337
- columnWidth,
338
- rowCount,
339
- columnCount,
340
- scale,
341
- frozenColumns,
342
- containerWidth,
343
- scrollLeft,
344
- frozenColumnWidth,
345
- ]);
346
- const estimatedTotalHeight = (0, helpers_1.getEstimatedTotalHeight)(rowCount, instanceProps.current);
347
- const estimatedTotalWidth = (0, helpers_1.getEstimatedTotalWidth)(columnCount, instanceProps.current);
348
- /* Method to get dimensions of the grid */
349
- const getDimensions = (0, react_1.useCallback)(() => {
350
- return {
351
- containerWidth,
352
- containerHeight,
353
- estimatedTotalWidth,
354
- estimatedTotalHeight,
355
- };
356
- }, [
357
- containerWidth,
358
- containerHeight,
359
- estimatedTotalWidth,
360
- estimatedTotalHeight,
361
- ]);
362
- /**
363
- * Update snap properties if its active
364
- * We need this because we are binding `onwheel` event to document
365
- * So props go stale
366
- */
367
- (0, react_1.useEffect)(() => {
368
- if (snap) {
369
- scrollSnapRefs.current = {
370
- visibleRowStartIndex,
371
- rowCount,
372
- frozenRows,
373
- visibleColumnStartIndex,
374
- columnCount,
375
- frozenColumns,
376
- isHiddenRow,
377
- isHiddenColumn,
378
- };
379
- }
380
- }, [
381
- snap,
382
- visibleRowStartIndex,
383
- rowCount,
384
- frozenRows,
385
- visibleColumnStartIndex,
386
- columnCount,
387
- frozenColumns,
388
- isHiddenRow,
389
- isHiddenColumn,
390
- ]);
391
- /**
392
- * Snaps vertical scrollbar to the next/prev visible row
393
- */
394
- const snapToRowFn = (0, react_1.useCallback)(({ deltaY }) => {
395
- if (!verticalScrollRef.current || !scrollSnapRefs.current)
396
- return;
397
- if (deltaY !== 0) {
398
- const direction = deltaY < 0 ? types_1.Direction.Up : types_1.Direction.Down;
399
- const { visibleRowStartIndex, rowCount, isHiddenRow } = scrollSnapRefs.current;
400
- let nextRowIndex = direction === types_1.Direction.Up
401
- ? // User is scrolling up
402
- Math.max(0, visibleRowStartIndex - 1)
403
- : Math.min(visibleRowStartIndex, rowCount - 1);
404
- /* Ignore hidden row */
405
- nextRowIndex = (0, helpers_1.clampIndex)(nextRowIndex, isHiddenRow, direction);
406
- const rowHeight = getRowHeight(nextRowIndex);
407
- verticalScrollRef.current.scrollTop +=
408
- (direction === types_1.Direction.Up ? -1 : 1) * rowHeight;
409
- }
410
- }, []);
411
- /**
412
- * Snaps horizontal scrollbar to the next/prev visible column
413
- */
414
- const snapToColumnFn = (0, react_1.useCallback)(({ deltaX }) => {
415
- if (!horizontalScrollRef.current || !scrollSnapRefs.current)
416
- return;
417
- if (deltaX !== 0) {
418
- const { visibleColumnStartIndex, columnCount, isHiddenColumn } = scrollSnapRefs.current;
419
- const direction = deltaX < 0 ? types_1.Direction.Left : types_1.Direction.Right;
420
- let nextColumnIndex = direction === types_1.Direction.Left
421
- ? Math.max(0, visibleColumnStartIndex - 1)
422
- : Math.min(visibleColumnStartIndex, columnCount - 1);
423
- /* Ignore hidden column */
424
- nextColumnIndex = (0, helpers_1.clampIndex)(nextColumnIndex, isHiddenColumn, direction);
425
- const columnWidth = getColumnWidth(nextColumnIndex);
426
- horizontalScrollRef.current.scrollLeft +=
427
- (direction === types_1.Direction.Left ? -1 : 1) * columnWidth;
428
- }
429
- }, []);
430
- const snapToRowThrottler = (0, react_1.useRef)();
431
- const snapToColumnThrottler = (0, react_1.useRef)();
432
- /**
433
- * Register snap throttlers
434
- */
435
- (0, react_1.useEffect)(() => {
436
- if (snap) {
437
- snapToRowThrottler.current = (0, helpers_1.throttle)(snapToRowFn, scrollThrottleTimeout);
438
- snapToColumnThrottler.current = (0, helpers_1.throttle)(snapToColumnFn, scrollThrottleTimeout);
439
- }
440
- return () => {
441
- snapToRowThrottler.current = undefined;
442
- snapToColumnThrottler.current = undefined;
443
- };
444
- }, [snap]);
445
- /* Find frozen column boundary */
446
- const isWithinFrozenColumnBoundary = (0, react_1.useCallback)((x) => {
447
- return frozenColumns > 0 && x < frozenColumnWidth;
448
- }, [frozenColumns, frozenColumnWidth]);
449
- /* Find frozen row boundary */
450
- const isWithinFrozenRowBoundary = (0, react_1.useCallback)((y) => {
451
- return frozenRows > 0 && y < frozenRowHeight;
452
- }, [frozenRows, frozenRowHeight]);
453
- /**
454
- * Get relative mouse position
455
- */
456
- const getRelativePositionFromOffset = (0, react_1.useCallback)((left, top) => {
457
- var _a;
458
- (0, tiny_invariant_1.default)(typeof left === "number" && typeof top === "number", "Top and left should be a number");
459
- if (!stageRef.current)
460
- return null;
461
- const stage = stageRef.current.getStage();
462
- const rect = (_a = containerRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
463
- if (rect) {
464
- left = left - rect.x;
465
- top = top - rect.y;
466
- }
467
- const { x, y } = stage
468
- .getAbsoluteTransform()
469
- .copy()
470
- .invert()
471
- .point({ x: left, y: top });
472
- return { x, y };
473
- }, []);
474
- /**
475
- * Get cell cordinates from current mouse x/y positions
476
- */
477
- const getCellCoordsFromOffset = (0, react_1.useCallback)((left, top, includeFrozen = true) => {
478
- const pos = getRelativePositionFromOffset(left, top);
479
- if (!pos)
480
- return null;
481
- const { x, y } = pos;
482
- const rowOffset = includeFrozen && isWithinFrozenRowBoundary(y) ? y : y + scrollTop;
483
- const columnOffset = includeFrozen && isWithinFrozenColumnBoundary(x) ? x : x + scrollLeft;
484
- if (rowOffset > estimatedTotalHeight ||
485
- columnOffset > estimatedTotalWidth) {
486
- return null;
487
- }
488
- const rowIndex = (0, helpers_1.getRowStartIndexForOffset)({
489
- rowHeight,
490
- columnWidth,
491
- rowCount,
492
- columnCount,
493
- instanceProps: instanceProps.current,
494
- offset: rowOffset,
495
- scale,
496
- });
497
- const columnIndex = (0, helpers_1.getColumnStartIndexForOffset)({
498
- rowHeight,
499
- columnWidth,
500
- rowCount,
501
- columnCount,
502
- instanceProps: instanceProps.current,
503
- offset: columnOffset,
504
- scale,
505
- });
506
- /* To be compatible with merged cells */
507
- const bounds = getCellBounds({ rowIndex, columnIndex });
508
- return { rowIndex: bounds.top, columnIndex: bounds.left };
509
- }, [
510
- scrollLeft,
511
- rowHeight,
512
- columnWidth,
513
- scrollTop,
514
- rowCount,
515
- estimatedTotalHeight,
516
- estimatedTotalWidth,
517
- columnCount,
518
- mergedCellMap,
519
- ]);
520
- /**
521
- * Get cell offset position from rowIndex, columnIndex
522
- */
523
- const getCellOffsetFromCoords = (0, react_1.useCallback)((cell) => {
524
- const { top: rowIndex, left: columnIndex, right, bottom, } = getCellBounds(cell);
525
- const x = getColumnOffset(columnIndex);
526
- const y = getRowOffset(rowIndex);
527
- const width = getColumnOffset(right + 1) - x;
528
- const height = getRowOffset(bottom + 1) - y;
529
- return {
530
- x,
531
- y,
532
- width,
533
- height,
534
- };
535
- }, [mergedCellMap]);
536
- /**
537
- * Resize one or more columns
538
- */
539
- const resizeColumns = (0, react_1.useCallback)((indices) => {
540
- const leftMost = Math.min(...indices);
541
- instanceProps.current.recalcColumnIndices = indices;
542
- resetAfterIndices({ columnIndex: leftMost }, false);
543
- forceRender();
544
- }, []);
545
- /**
546
- * Resize one or more rows
547
- */
548
- const resizeRows = (0, react_1.useCallback)((indices) => {
549
- const topMost = Math.min(...indices);
550
- instanceProps.current.recalcRowIndices = indices;
551
- resetAfterIndices({ rowIndex: topMost }, false);
552
- forceRender();
553
- }, []);
554
- /* Always if the viewport changes */
555
- (0, react_1.useEffect)(() => {
556
- if (instanceProps.current.recalcColumnIndices.length) {
557
- instanceProps.current.recalcColumnIndices.length = 0;
558
- }
559
- if (instanceProps.current.recalcRowIndices.length) {
560
- instanceProps.current.recalcRowIndices.length = 0;
561
- }
562
- }, [rowStopIndex, columnStopIndex, scale]);
563
- /* Get current view port of the grid */
564
- const getViewPort = (0, react_1.useCallback)(() => {
565
- return {
566
- rowStartIndex,
567
- rowStopIndex,
568
- columnStartIndex,
569
- columnStopIndex,
570
- visibleRowStartIndex,
571
- visibleRowStopIndex,
572
- visibleColumnStartIndex,
573
- visibleColumnStopIndex,
574
- };
575
- }, [
576
- rowStartIndex,
577
- rowStopIndex,
578
- columnStartIndex,
579
- columnStopIndex,
580
- visibleRowStartIndex,
581
- visibleRowStopIndex,
582
- visibleColumnStartIndex,
583
- visibleColumnStopIndex,
584
- ]);
585
- /**
586
- * When the grid is scrolling,
587
- * 1. Stage does not listen to any mouse events
588
- * 2. Div container does not listen to pointer events
589
- */
590
- const resetIsScrollingTimeoutID = (0, react_1.useRef)(null);
591
- const resetIsScrollingDebounced = (0, react_1.useCallback)(() => {
592
- if (resetIsScrollingTimeoutID.current !== null) {
593
- (0, helpers_1.cancelTimeout)(resetIsScrollingTimeoutID.current);
594
- }
595
- resetIsScrollingTimeoutID.current = (0, helpers_1.requestTimeout)(resetIsScrolling, exports.RESET_SCROLL_EVENTS_DEBOUNCE_INTERVAL);
596
- }, []);
597
- /* Reset isScrolling */
598
- const resetIsScrolling = (0, react_1.useCallback)(() => {
599
- resetIsScrollingTimeoutID.current = null;
600
- setScrollState((prev) => {
601
- return {
602
- ...prev,
603
- isScrolling: false,
604
- };
605
- });
606
- }, []);
607
- /* Handle vertical scroll */
608
- const handleScroll = (0, react_1.useCallback)((e) => {
609
- const { scrollTop } = e.currentTarget;
610
- setScrollState((prev) => ({
611
- ...prev,
612
- isScrolling: true,
613
- verticalScrollDirection: prev.scrollTop > scrollTop ? types_1.Direction.Up : types_1.Direction.Down,
614
- scrollTop,
615
- }));
616
- /* Scroll callbacks */
617
- onImmediateScroll === null || onImmediateScroll === void 0 ? void 0 : onImmediateScroll({ scrollTop, scrollLeft });
618
- /* Reset isScrolling if required */
619
- resetIsScrollingDebounced();
620
- }, [scrollLeft]);
621
- /* Handle horizontal scroll */
622
- const handleScrollLeft = (0, react_1.useCallback)((e) => {
623
- const { scrollLeft } = e.currentTarget;
624
- setScrollState((prev) => ({
625
- ...prev,
626
- isScrolling: true,
627
- horizontalScrollDirection: prev.scrollLeft > scrollLeft ? types_1.Direction.Left : types_1.Direction.Right,
628
- scrollLeft,
629
- }));
630
- /* Scroll callbacks */
631
- onImmediateScroll === null || onImmediateScroll === void 0 ? void 0 : onImmediateScroll({ scrollLeft, scrollTop });
632
- /* Reset isScrolling if required */
633
- resetIsScrollingDebounced();
634
- }, [scrollTop]);
635
- /* Scroll based on left, top position */
636
- const scrollTo = (0, react_1.useCallback)(({ scrollTop, scrollLeft }) => {
637
- /* If scrollbar is visible, lets update it which triggers a state change */
638
- if (showScrollbar) {
639
- if (horizontalScrollRef.current && scrollLeft !== void 0)
640
- horizontalScrollRef.current.scrollLeft = scrollLeft;
641
- if (verticalScrollRef.current && scrollTop !== void 0)
642
- verticalScrollRef.current.scrollTop = scrollTop;
643
- }
644
- else {
645
- setScrollState((prev) => {
646
- return {
647
- ...prev,
648
- scrollLeft: scrollLeft == void 0 ? prev.scrollLeft : scrollLeft,
649
- scrollTop: scrollTop == void 0 ? prev.scrollTop : scrollTop,
650
- };
651
- });
652
- }
653
- }, [showScrollbar]);
654
- /* Scroll grid to top */
655
- const scrollToTop = (0, react_1.useCallback)(() => {
656
- scrollTo({ scrollTop: 0, scrollLeft: 0 });
657
- }, []);
658
- /* Scroll grid to bottom */
659
- const scrollToBottom = (0, react_1.useCallback)(() => {
660
- scrollTo({ scrollTop: estimatedTotalHeight - containerHeight });
661
- }, [estimatedTotalHeight, containerHeight]);
662
- /**
663
- * Scrollby utility
664
- */
665
- const scrollBy = (0, react_1.useCallback)(({ x, y }) => {
666
- if (showScrollbar) {
667
- if (horizontalScrollRef.current && x !== void 0)
668
- horizontalScrollRef.current.scrollLeft += x;
669
- if (verticalScrollRef.current && y !== void 0)
670
- verticalScrollRef.current.scrollTop += y;
671
- }
672
- else {
673
- setScrollState((prev) => {
674
- return {
675
- ...prev,
676
- scrollLeft: x == void 0 ? prev.scrollLeft : prev.scrollLeft + x,
677
- scrollTop: y == void 0 ? prev.scrollTop : prev.scrollTop + y,
678
- };
679
- });
680
- }
681
- }, []);
682
- /**
683
- * Scrolls to cell
684
- * Respects frozen rows and columns
685
- */
686
- const scrollToItem = (0, react_1.useCallback)(({ rowIndex, columnIndex }, align = helpers_1.Align.smart) => {
687
- const isFrozenRow = rowIndex !== void 0 && rowIndex < frozenRows;
688
- const isFrozenColumn = columnIndex !== void 0 && columnIndex < frozenColumns;
689
- const frozenColumnOffset = getColumnOffset(frozenColumns);
690
- /* Making sure getColumnWidth works */
691
- const x = columnIndex !== void 0 ? getColumnOffset(columnIndex) : void 0;
692
- /* Making sure getRowHeight works */
693
- const y = rowIndex !== void 0 ? getRowOffset(rowIndex) : void 0;
694
- const width = columnIndex !== void 0 ? getColumnWidth(columnIndex) : 0;
695
- const height = rowIndex !== void 0 ? getRowHeight(rowIndex) : 0;
696
- const columnAlign = width > containerWidth ? helpers_1.Align.start : align;
697
- const rowAlign = height > containerHeight ? helpers_1.Align.start : align;
698
- const newScrollLeft = columnIndex !== void 0 && !isFrozenColumn
699
- ? (0, helpers_1.getOffsetForColumnAndAlignment)({
700
- index: columnIndex,
701
- containerHeight,
702
- containerWidth,
703
- columnCount,
704
- columnWidth,
705
- rowCount,
706
- rowHeight,
707
- scrollOffset: scrollLeft,
708
- instanceProps: instanceProps.current,
709
- scrollbarSize,
710
- frozenOffset: frozenColumnOffset,
711
- align: columnAlign,
712
- scale,
713
- estimatedTotalWidth,
714
- estimatedTotalHeight,
715
- })
716
- : void 0;
717
- const frozenRowOffset = getRowOffset(frozenRows);
718
- const newScrollTop = rowIndex !== void 0 && !isFrozenRow
719
- ? (0, helpers_1.getOffsetForRowAndAlignment)({
720
- index: rowIndex,
721
- containerHeight,
722
- containerWidth,
723
- columnCount,
724
- columnWidth,
725
- rowCount,
726
- rowHeight,
727
- scrollOffset: scrollTop,
728
- instanceProps: instanceProps.current,
729
- scrollbarSize,
730
- frozenOffset: frozenRowOffset,
731
- align: rowAlign,
732
- scale,
733
- estimatedTotalWidth,
734
- estimatedTotalHeight,
735
- })
736
- : void 0;
737
- const coords = {
738
- scrollLeft: newScrollLeft,
739
- scrollTop: newScrollTop,
740
- };
741
- const isOutsideViewport = (rowIndex !== void 0 &&
742
- rowIndex > rowStopIndex + (rowStopIndex - rowStartIndex)) ||
743
- (columnIndex !== void 0 &&
744
- columnIndex >
745
- columnStopIndex + (columnStopIndex - columnStartIndex));
746
- /* Scroll in the next frame, Useful when user wants to jump from 1st column to last */
747
- if (isOutsideViewport) {
748
- window.requestAnimationFrame(() => {
749
- scrollTo(coords);
750
- });
751
- }
752
- else
753
- scrollTo(coords);
754
- }, [
755
- containerHeight,
756
- containerWidth,
757
- estimatedTotalWidth,
758
- estimatedTotalHeight,
759
- rowCount,
760
- columnCount,
761
- scrollbarSize,
762
- scrollLeft,
763
- scrollTop,
764
- frozenRows,
765
- frozenColumns,
766
- ]);
767
- /**
768
- * Fired when user tries to scroll the canvas
769
- */
770
- const handleWheel = (0, react_1.useCallback)((event) => {
771
- var _a, _b, _c, _d;
772
- /* If user presses shift key, scroll horizontally */
773
- const isScrollingHorizontally = event.shiftKey;
774
- /* Prevent browser back in Mac */
775
- event.preventDefault();
776
- const { deltaX, deltaY, deltaMode } = event;
777
- /* Scroll natively */
778
- if (wheelingRef.current)
779
- return;
780
- let dx = isScrollingHorizontally ? deltaY : deltaX;
781
- let dy = deltaY;
782
- /* Scroll only in one direction */
783
- const isHorizontal = isScrollingHorizontally || Math.abs(dx) > Math.abs(dy);
784
- /* If snaps are active */
785
- if (snap) {
786
- if (isHorizontal) {
787
- (_a = snapToColumnThrottler.current) === null || _a === void 0 ? void 0 : _a.call(snapToColumnThrottler, {
788
- deltaX,
789
- });
790
- }
791
- else {
792
- (_b = snapToRowThrottler.current) === null || _b === void 0 ? void 0 : _b.call(snapToRowThrottler, {
793
- deltaY,
794
- });
795
- }
796
- return;
797
- }
798
- if (deltaMode === 1) {
799
- dy = dy * scrollbarSize;
800
- }
801
- if (!horizontalScrollRef.current || !verticalScrollRef.current)
802
- return;
803
- const currentScroll = isHorizontal
804
- ? (_c = horizontalScrollRef.current) === null || _c === void 0 ? void 0 : _c.scrollLeft
805
- : (_d = verticalScrollRef.current) === null || _d === void 0 ? void 0 : _d.scrollTop;
806
- wheelingRef.current = window.requestAnimationFrame(() => {
807
- wheelingRef.current = null;
808
- if (isHorizontal) {
809
- if (horizontalScrollRef.current)
810
- horizontalScrollRef.current.scrollLeft = currentScroll + dx;
811
- }
812
- else {
813
- if (verticalScrollRef.current)
814
- verticalScrollRef.current.scrollTop = currentScroll + dy;
815
- }
816
- });
817
- }, []);
818
- /* Callback when visible rows or columns have changed */
819
- (0, react_1.useEffect)(() => {
820
- onViewChange === null || onViewChange === void 0 ? void 0 : onViewChange({
821
- rowStartIndex,
822
- rowStopIndex,
823
- columnStartIndex,
824
- columnStopIndex,
825
- visibleRowStartIndex,
826
- visibleRowStopIndex,
827
- visibleColumnStartIndex,
828
- visibleColumnStopIndex,
829
- });
830
- }, [
831
- rowStartIndex,
832
- rowStopIndex,
833
- columnStartIndex,
834
- columnStopIndex,
835
- visibleRowStartIndex,
836
- visibleRowStopIndex,
837
- visibleColumnStartIndex,
838
- visibleColumnStopIndex,
839
- ]);
840
- /* Draw gridlines */
841
- const gridLines = [];
842
- const gridLinesFrozenRow = [];
843
- const gridLinesFrozenColumn = [];
844
- const gridLinesFrozenIntersection = [];
845
- if (showGridLines) {
846
- // Horizontal
847
- for (let rowIndex = rowStartIndex; rowIndex <= rowStopIndex; rowIndex++) {
848
- /* Ignore frozen rows */
849
- if (rowIndex < frozenRows || (isHiddenRow === null || isHiddenRow === void 0 ? void 0 : isHiddenRow(rowIndex)))
850
- continue;
851
- const x1 = getColumnOffset(frozenColumns);
852
- const x2 = getColumnOffset(Math.min(columnStopIndex + 1, columnCount));
853
- const y1 = getRowOffset(Math.min(rowIndex + 1, rowCount));
854
- const y2 = y1;
855
- gridLines.push(gridLineRenderer({
856
- points: [x1, y1, x2, y2],
857
- stroke: gridLineColor,
858
- strokeWidth: gridLineWidth,
859
- offsetY: -0.5,
860
- key: (0, helpers_1.itemKey)({ rowIndex: rowIndex, columnIndex: y1 }),
861
- }));
862
- gridLinesFrozenColumn.push(gridLineRenderer({
863
- points: [0, y1, x2, y2],
864
- stroke: gridLineColor,
865
- strokeWidth: gridLineWidth,
866
- offsetY: -0.5,
867
- key: (0, helpers_1.itemKey)({ rowIndex: rowIndex, columnIndex: y1 }),
868
- }));
869
- }
870
- // Vertical
871
- for (let columnIndex = columnStartIndex; columnIndex <= columnStopIndex; columnIndex++) {
872
- const x1 = getColumnOffset(Math.min(columnIndex + 1, columnCount));
873
- const x2 = x1;
874
- const y1 = getRowOffset(frozenRows);
875
- const y2 = getRowOffset(Math.min(rowStopIndex + 1, rowCount));
876
- gridLines.push(gridLineRenderer({
877
- points: [x1, y1, x2, y2],
878
- stroke: gridLineColor,
879
- strokeWidth: gridLineWidth,
880
- offsetX: -0.5,
881
- key: (0, helpers_1.itemKey)({ rowIndex: x1, columnIndex: columnIndex }),
882
- }));
883
- gridLinesFrozenRow.push(gridLineRenderer({
884
- points: [x1, 0, x2, y2],
885
- stroke: gridLineColor,
886
- strokeWidth: gridLineWidth,
887
- offsetX: -0.5,
888
- key: (0, helpers_1.itemKey)({ rowIndex: x1, columnIndex: columnIndex }),
889
- }));
890
- }
891
- for (let rowIndex = 0; rowIndex < Math.min(columnStopIndex, frozenRows); rowIndex++) {
892
- if (isHiddenRow === null || isHiddenRow === void 0 ? void 0 : isHiddenRow(rowIndex))
893
- continue;
894
- const x1 = 0;
895
- const x2 = getColumnOffset(Math.min(columnStopIndex + 1, columnCount));
896
- const y1 = getRowOffset(Math.min(rowIndex + 1, rowCount));
897
- const y2 = y1;
898
- gridLinesFrozenRow.push(gridLineRenderer({
899
- points: [x1, y1, x2, y2],
900
- stroke: gridLineColor,
901
- strokeWidth: gridLineWidth,
902
- offsetY: -0.5,
903
- key: (0, helpers_1.itemKey)({ rowIndex: rowIndex, columnIndex: y1 }),
904
- }));
905
- gridLinesFrozenIntersection.push(gridLineRenderer({
906
- points: [x1, y1, x2, y2],
907
- stroke: gridLineColor,
908
- strokeWidth: gridLineWidth,
909
- offsetY: -0.5,
910
- key: (0, helpers_1.itemKey)({ rowIndex: rowIndex, columnIndex: y1 }),
911
- }));
912
- }
913
- for (let columnIndex = 0; columnIndex < Math.min(columnStopIndex, frozenColumns); columnIndex++) {
914
- const x1 = getColumnOffset(Math.min(columnIndex + 1, columnCount));
915
- const x2 = x1;
916
- const y1 = 0;
917
- const y2 = getRowOffset(Math.min(rowStopIndex + 1, rowCount));
918
- gridLinesFrozenColumn.push(gridLineRenderer({
919
- points: [x1, y1, x2, y2],
920
- stroke: gridLineColor,
921
- strokeWidth: gridLineWidth,
922
- offsetX: -0.5,
923
- key: (0, helpers_1.itemKey)({ rowIndex: x1, columnIndex: columnIndex }),
924
- }));
925
- gridLinesFrozenIntersection.push(gridLineRenderer({
926
- points: [x1, y1, x2, y2],
927
- stroke: gridLineColor,
928
- strokeWidth: gridLineWidth,
929
- offsetX: -0.5,
930
- key: (0, helpers_1.itemKey)({ rowIndex: x1, columnIndex: columnIndex }),
931
- }));
932
- }
933
- }
934
- const mergedCellRenderMap = new Set();
935
- /* Draw all cells */
936
- const cells = [];
937
- /**
938
- * Lets users draw cells on top of existing canvas
939
- */
940
- const cellOverlays = [];
941
- if (columnCount > 0 && rowCount) {
942
- for (let rowIndex = rowStartIndex; rowIndex <= rowStopIndex; rowIndex++) {
943
- /* Skip frozen rows */
944
- if (rowIndex < frozenRows || (isHiddenRow === null || isHiddenRow === void 0 ? void 0 : isHiddenRow(rowIndex))) {
945
- continue;
946
- }
947
- /**
948
- * Do any pre-processing of the row before being renderered.
949
- * Useful for `react-table` to call `prepareRow(row)`
950
- */
951
- onBeforeRenderRow === null || onBeforeRenderRow === void 0 ? void 0 : onBeforeRenderRow(rowIndex);
952
- for (let columnIndex = columnStartIndex; columnIndex <= columnStopIndex; columnIndex++) {
953
- /**
954
- * Skip frozen columns
955
- * Skip merged cells that are out of bounds
956
- */
957
- if (columnIndex < frozenColumns) {
958
- continue;
959
- }
960
- const isMerged = isMergedCell({ rowIndex, columnIndex });
961
- const bounds = getCellBounds({ rowIndex, columnIndex });
962
- const actualRowIndex = isMerged ? bounds.top : rowIndex;
963
- const actualColumnIndex = isMerged ? bounds.left : columnIndex;
964
- const actualBottom = Math.max(rowIndex, bounds.bottom);
965
- const actualRight = Math.max(columnIndex, bounds.right);
966
- if (!isMerged && (isHiddenCell === null || isHiddenCell === void 0 ? void 0 : isHiddenCell(actualRowIndex, actualColumnIndex))) {
967
- continue;
968
- }
969
- if (isMerged) {
970
- const cellId = (0, helpers_1.cellIdentifier)(bounds.top, bounds.left);
971
- if (mergedCellRenderMap.has(cellId)) {
972
- continue;
973
- }
974
- mergedCellRenderMap.add(cellId);
975
- }
976
- const y = getRowOffset(actualRowIndex);
977
- const height = getRowOffset(actualBottom) - y + getRowHeight(actualBottom);
978
- const x = getColumnOffset(actualColumnIndex);
979
- const width = getColumnOffset(actualRight) - x + getColumnWidth(actualRight);
980
- cells.push(itemRenderer({
981
- x,
982
- y,
983
- width,
984
- height,
985
- rowIndex: actualRowIndex,
986
- columnIndex: actualColumnIndex,
987
- isMergedCell: isMerged,
988
- key: (0, helpers_1.itemKey)({
989
- rowIndex: actualRowIndex,
990
- columnIndex: actualColumnIndex,
991
- }),
992
- }));
993
- if (enableCellOverlay) {
994
- cellOverlays.push(overlayRenderer({
995
- x,
996
- y,
997
- width,
998
- height,
999
- rowIndex: actualRowIndex,
1000
- columnIndex: actualColumnIndex,
1001
- isMergedCell: isMerged,
1002
- key: (0, helpers_1.itemKey)({
1003
- rowIndex: actualRowIndex,
1004
- columnIndex: actualColumnIndex,
1005
- }),
1006
- }));
1007
- }
1008
- }
1009
- }
1010
- }
1011
- /**
1012
- * Extend certain cells.
1013
- * Mimics google sheets functionality where
1014
- * oevrflowed cell content can cover adjacent cells
1015
- */
1016
- const ranges = [];
1017
- for (const { rowIndex, columnIndex, toColumnIndex } of cellAreas) {
1018
- /* Skip merged cells, Merged cell cannot be extended */
1019
- if (rowIndex < frozenRows ||
1020
- columnIndex < frozenColumns ||
1021
- isMergedCell({ rowIndex, columnIndex }) ||
1022
- (isHiddenCell === null || isHiddenCell === void 0 ? void 0 : isHiddenCell(rowIndex, columnIndex))) {
1023
- continue;
1024
- }
1025
- const x = getColumnOffset(columnIndex);
1026
- const y = getRowOffset(rowIndex);
1027
- const height = getRowHeight(rowIndex);
1028
- const { x: offsetX = 0 } = getCellOffsetFromCoords({
1029
- rowIndex,
1030
- columnIndex: toColumnIndex + 1,
1031
- });
1032
- ranges.push(itemRenderer({
1033
- x,
1034
- y,
1035
- width: offsetX - x,
1036
- height,
1037
- rowIndex,
1038
- columnIndex,
1039
- key: `range:${(0, helpers_1.itemKey)({ rowIndex, columnIndex })}`,
1040
- }));
1041
- }
1042
- /* Draw frozen rows */
1043
- const frozenRowCells = [];
1044
- const frozenRowCellOverlays = [];
1045
- for (let rowIndex = 0; rowIndex < Math.min(rowStopIndex, frozenRows); rowIndex++) {
1046
- if (isHiddenRow === null || isHiddenRow === void 0 ? void 0 : isHiddenRow(rowIndex))
1047
- continue;
1048
- /**
1049
- * Do any pre-processing of the row before being renderered.
1050
- * Useful for `react-table` to call `prepareRow(row)`
1051
- */
1052
- onBeforeRenderRow === null || onBeforeRenderRow === void 0 ? void 0 : onBeforeRenderRow(rowIndex);
1053
- for (let columnIndex = columnStartIndex; columnIndex <= columnStopIndex; columnIndex++) {
1054
- /* Skip merged cells columns */
1055
- if (columnIndex < frozenColumns) {
1056
- continue;
1057
- }
1058
- const isMerged = isMergedCell({ rowIndex, columnIndex });
1059
- const bounds = getCellBounds({ rowIndex, columnIndex });
1060
- const actualRowIndex = isMerged ? bounds.top : rowIndex;
1061
- const actualColumnIndex = isMerged ? bounds.left : columnIndex;
1062
- const actualBottom = Math.max(rowIndex, bounds.bottom);
1063
- const actualRight = Math.max(columnIndex, bounds.right);
1064
- if (!isMerged && (isHiddenCell === null || isHiddenCell === void 0 ? void 0 : isHiddenCell(actualRowIndex, actualColumnIndex))) {
1065
- continue;
1066
- }
1067
- if (isMerged) {
1068
- const cellId = (0, helpers_1.cellIdentifier)(bounds.top, bounds.left);
1069
- if (mergedCellRenderMap.has(cellId)) {
1070
- continue;
1071
- }
1072
- mergedCellRenderMap.add(cellId);
1073
- }
1074
- const y = getRowOffset(actualRowIndex);
1075
- const height = getRowOffset(actualBottom) - y + getRowHeight(actualBottom);
1076
- const x = getColumnOffset(actualColumnIndex);
1077
- const width = getColumnOffset(actualRight) - x + getColumnWidth(actualRight);
1078
- frozenRowCells.push(itemRenderer({
1079
- x,
1080
- y,
1081
- width,
1082
- height,
1083
- rowIndex: actualRowIndex,
1084
- columnIndex: actualColumnIndex,
1085
- isMergedCell: isMerged,
1086
- key: (0, helpers_1.itemKey)({
1087
- rowIndex: actualRowIndex,
1088
- columnIndex: actualColumnIndex,
1089
- }),
1090
- }));
1091
- if (enableCellOverlay) {
1092
- frozenRowCellOverlays.push(overlayRenderer({
1093
- x,
1094
- y,
1095
- width,
1096
- height,
1097
- rowIndex: actualRowIndex,
1098
- columnIndex: actualColumnIndex,
1099
- isMergedCell: isMerged,
1100
- key: (0, helpers_1.itemKey)({
1101
- rowIndex: actualRowIndex,
1102
- columnIndex: actualColumnIndex,
1103
- }),
1104
- }));
1105
- }
1106
- }
1107
- }
1108
- /* Draw frozen columns */
1109
- const frozenColumnCells = [];
1110
- const frozenColumnCellOverlays = [];
1111
- for (let rowIndex = rowStartIndex; rowIndex <= rowStopIndex; rowIndex++) {
1112
- if (rowIndex < frozenRows || (isHiddenRow === null || isHiddenRow === void 0 ? void 0 : isHiddenRow(rowIndex))) {
1113
- continue;
1114
- }
1115
- /**
1116
- * Do any pre-processing of the row before being renderered.
1117
- * Useful for `react-table` to call `prepareRow(row)`
1118
- */
1119
- onBeforeRenderRow === null || onBeforeRenderRow === void 0 ? void 0 : onBeforeRenderRow(rowIndex);
1120
- for (let columnIndex = 0; columnIndex < Math.min(columnStopIndex, frozenColumns); columnIndex++) {
1121
- const isMerged = isMergedCell({ rowIndex, columnIndex });
1122
- const bounds = getCellBounds({ rowIndex, columnIndex });
1123
- const actualRowIndex = isMerged ? bounds.top : rowIndex;
1124
- const actualColumnIndex = isMerged ? bounds.left : columnIndex;
1125
- const actualBottom = Math.max(rowIndex, bounds.bottom);
1126
- const actualRight = Math.max(columnIndex, bounds.right);
1127
- if (!isMerged && (isHiddenCell === null || isHiddenCell === void 0 ? void 0 : isHiddenCell(actualRowIndex, actualColumnIndex))) {
1128
- continue;
1129
- }
1130
- if (isMerged) {
1131
- const cellId = (0, helpers_1.cellIdentifier)(bounds.top, bounds.left);
1132
- if (mergedCellRenderMap.has(cellId)) {
1133
- continue;
1134
- }
1135
- mergedCellRenderMap.add(cellId);
1136
- }
1137
- const y = getRowOffset(actualRowIndex);
1138
- const height = getRowOffset(actualBottom) - y + getRowHeight(actualBottom);
1139
- const x = getColumnOffset(actualColumnIndex);
1140
- const width = getColumnOffset(actualRight) - x + getColumnWidth(actualRight);
1141
- frozenColumnCells.push(itemRenderer({
1142
- x,
1143
- y,
1144
- width,
1145
- height,
1146
- rowIndex: actualRowIndex,
1147
- columnIndex: actualColumnIndex,
1148
- isMergedCell: isMerged,
1149
- key: (0, helpers_1.itemKey)({
1150
- rowIndex: actualRowIndex,
1151
- columnIndex: actualColumnIndex,
1152
- }),
1153
- }));
1154
- if (enableCellOverlay) {
1155
- frozenColumnCellOverlays.push(overlayRenderer({
1156
- x,
1157
- y,
1158
- width,
1159
- height,
1160
- rowIndex: actualRowIndex,
1161
- columnIndex: actualColumnIndex,
1162
- isMergedCell: isMerged,
1163
- key: (0, helpers_1.itemKey)({
1164
- rowIndex: actualRowIndex,
1165
- columnIndex: actualColumnIndex,
1166
- }),
1167
- }));
1168
- }
1169
- }
1170
- }
1171
- /**
1172
- * Frozen column shadow
1173
- */
1174
- const frozenColumnShadow = (0, react_1.useMemo)(() => {
1175
- const frozenColumnLineX = getColumnOffset(frozenColumns);
1176
- const frozenColumnLineY = getRowOffset(Math.min(rowStopIndex + 1, rowCount));
1177
- return (react_1.default.createElement(react_konva_1.Line, { points: [frozenColumnLineX, 0, frozenColumnLineX, frozenColumnLineY], offsetX: -0.5, strokeWidth: 1, shadowForStrokeEnabled: false, strokeScaleEnabled: false, hitStrokeWidth: 0, listening: false, perfectDrawEnabled: false, ...shadowSettings }));
1178
- }, [
1179
- shadowSettings,
1180
- frozenColumns,
1181
- rowStopIndex,
1182
- rowCount,
1183
- instanceProps.current.lastMeasuredColumnIndex,
1184
- instanceProps.current.recalcColumnIndices,
1185
- ]);
1186
- /**
1187
- * Frozen row shadow
1188
- */
1189
- const frozenRowShadow = (0, react_1.useMemo)(() => {
1190
- const frozenRowLineY = getRowOffset(frozenRows);
1191
- const frozenRowLineX = getColumnOffset(Math.min(columnStopIndex + 1, columnCount));
1192
- return (react_1.default.createElement(react_konva_1.Line, { points: [0, frozenRowLineY, frozenRowLineX, frozenRowLineY], offsetY: -0.5, strokeWidth: 1, shadowForStrokeEnabled: false, strokeScaleEnabled: false, hitStrokeWidth: 0, listening: false, perfectDrawEnabled: false, ...shadowSettings }));
1193
- }, [
1194
- shadowSettings,
1195
- frozenRows,
1196
- columnStopIndex,
1197
- columnCount,
1198
- instanceProps.current.lastMeasuredRowIndex,
1199
- instanceProps.current.recalcRowIndices,
1200
- ]);
1201
- /* Draw frozen intersection cells */
1202
- const frozenIntersectionCells = [];
1203
- const frozenIntersectionCellOverlays = [];
1204
- for (let rowIndex = 0; rowIndex < Math.min(rowStopIndex, frozenRows); rowIndex++) {
1205
- if (isHiddenRow === null || isHiddenRow === void 0 ? void 0 : isHiddenRow(rowIndex))
1206
- continue;
1207
- for (let columnIndex = 0; columnIndex < Math.min(columnStopIndex, frozenColumns); columnIndex++) {
1208
- const isMerged = isMergedCell({ rowIndex, columnIndex });
1209
- const bounds = getCellBounds({ rowIndex, columnIndex });
1210
- const actualRowIndex = isMerged ? bounds.top : rowIndex;
1211
- const actualColumnIndex = isMerged ? bounds.left : columnIndex;
1212
- const actualBottom = Math.max(rowIndex, bounds.bottom);
1213
- const actualRight = Math.max(columnIndex, bounds.right);
1214
- if (!isMerged && (isHiddenCell === null || isHiddenCell === void 0 ? void 0 : isHiddenCell(actualRowIndex, actualColumnIndex))) {
1215
- continue;
1216
- }
1217
- if (isMerged) {
1218
- const cellId = (0, helpers_1.cellIdentifier)(bounds.top, bounds.left);
1219
- if (mergedCellRenderMap.has(cellId)) {
1220
- continue;
1221
- }
1222
- mergedCellRenderMap.add(cellId);
1223
- }
1224
- const y = getRowOffset(actualRowIndex);
1225
- const height = getRowOffset(actualBottom) - y + getRowHeight(actualBottom);
1226
- const x = getColumnOffset(actualColumnIndex);
1227
- const width = getColumnOffset(actualRight) - x + getColumnWidth(actualRight);
1228
- frozenIntersectionCells.push(itemRenderer({
1229
- x,
1230
- y,
1231
- width,
1232
- height,
1233
- rowIndex: actualRowIndex,
1234
- columnIndex: actualColumnIndex,
1235
- isMergedCell: isMerged,
1236
- key: (0, helpers_1.itemKey)({
1237
- rowIndex: actualRowIndex,
1238
- columnIndex: actualColumnIndex,
1239
- }),
1240
- }));
1241
- if (enableCellOverlay) {
1242
- frozenIntersectionCellOverlays.push(overlayRenderer({
1243
- x,
1244
- y,
1245
- width,
1246
- height,
1247
- rowIndex: actualRowIndex,
1248
- columnIndex: actualColumnIndex,
1249
- isMergedCell: isMerged,
1250
- key: (0, helpers_1.itemKey)({
1251
- rowIndex: actualRowIndex,
1252
- columnIndex: actualColumnIndex,
1253
- }),
1254
- }));
1255
- }
1256
- }
1257
- }
1258
- /**
1259
- * Renders active cell
1260
- */
1261
- let fillHandleDimension = {};
1262
- let activeCellSelection = null;
1263
- let activeCellSelectionFrozenColumn = null;
1264
- let activeCellSelectionFrozenRow = null;
1265
- let activeCellSelectionFrozenIntersection = null;
1266
- if (activeCell) {
1267
- const bounds = getCellBounds(activeCell);
1268
- const { top, left, right, bottom } = bounds;
1269
- const actualBottom = Math.min(rowStopIndex, bottom);
1270
- const actualRight = Math.min(columnStopIndex, right);
1271
- const isInFrozenColumn = left < frozenColumns;
1272
- const isInFrozenRow = top < frozenRows;
1273
- const isInFrozenIntersection = isInFrozenRow && isInFrozenColumn;
1274
- const y = getRowOffset(top);
1275
- const height = getRowOffset(actualBottom) - y + getRowHeight(actualBottom);
1276
- const x = getColumnOffset(left);
1277
- const width = getColumnOffset(actualRight) - x + getColumnWidth(actualRight);
1278
- const cell = selectionRenderer({
1279
- stroke: selectionBorderColor,
1280
- strokeWidth: activeCellStrokeWidth,
1281
- fill: "transparent",
1282
- x: x,
1283
- y: y,
1284
- width: width,
1285
- height: height,
1286
- type: "activeCell",
1287
- key: 0,
1288
- activeCell,
1289
- isDragging: isDraggingSelection,
1290
- /* Active cell is draggable only there are no other selections */
1291
- draggable: enableSelectionDrag && !selections.length,
1292
- });
1293
- if (isInFrozenIntersection) {
1294
- activeCellSelectionFrozenIntersection = cell;
1295
- }
1296
- else if (isInFrozenRow) {
1297
- activeCellSelectionFrozenRow = cell;
1298
- }
1299
- else if (isInFrozenColumn) {
1300
- activeCellSelectionFrozenColumn = cell;
1301
- }
1302
- else {
1303
- activeCellSelection = cell;
1304
- }
1305
- fillHandleDimension = {
1306
- x: x + width,
1307
- y: y + height,
1308
- };
1309
- }
1310
- /**
1311
- * Convert selections to area
1312
- * Removed useMemo as changes to lastMeasureRowIndex, lastMeasuredColumnIndex,
1313
- * does not trigger useMemo
1314
- * Dependencies : [selections, rowStopIndex, columnStopIndex, instanceProps]
1315
- */
1316
- let isSelectionInProgress = false;
1317
- const selectionAreas = [];
1318
- const selectionAreasFrozenColumns = [];
1319
- const selectionAreasFrozenRows = [];
1320
- const selectionAreasIntersection = [];
1321
- for (let i = 0; i < selections.length; i++) {
1322
- const selection = selections[i];
1323
- const { bounds, inProgress, style } = selection;
1324
- const { top, left, right, bottom } = bounds;
1325
- const selectionBounds = { x: 0, y: 0, width: 0, height: 0 };
1326
- const actualBottom = Math.min(rowStopIndex, bottom);
1327
- const actualRight = Math.min(columnStopIndex, right);
1328
- const isLeftBoundFrozen = left < frozenColumns;
1329
- const isTopBoundFrozen = top < frozenRows;
1330
- const isIntersectionFrozen = top < frozenRows && left < frozenColumns;
1331
- const isLast = i === selections.length - 1;
1332
- const styles = {
1333
- stroke: inProgress ? selectionBackgroundColor : selectionBorderColor,
1334
- fill: selectionBackgroundColor,
1335
- strokeWidth: isDraggingSelection ? 0 : 1,
1336
- isDragging: isDraggingSelection,
1337
- draggable: inProgress ? false : enableSelectionDrag,
1338
- ...style,
1339
- };
1340
- /**
1341
- * If selection is in progress,
1342
- * use this variable to hide fill handle
1343
- */
1344
- if (inProgress) {
1345
- isSelectionInProgress = true;
1346
- }
1347
- selectionBounds.y = getRowOffset(top);
1348
- selectionBounds.height =
1349
- getRowOffset(actualBottom) -
1350
- selectionBounds.y +
1351
- getRowHeight(actualBottom);
1352
- selectionBounds.x = getColumnOffset(left);
1353
- selectionBounds.width =
1354
- getColumnOffset(actualRight) -
1355
- selectionBounds.x +
1356
- getColumnWidth(actualRight);
1357
- if (isLeftBoundFrozen) {
1358
- const frozenColumnSelectionWidth = getColumnOffset(Math.min(right + 1, frozenColumns)) -
1359
- getColumnOffset(left);
1360
- selectionAreasFrozenColumns.push(selectionRenderer({
1361
- ...styles,
1362
- type: "selection",
1363
- key: i,
1364
- x: selectionBounds.x,
1365
- y: selectionBounds.y,
1366
- width: frozenColumnSelectionWidth,
1367
- height: selectionBounds.height,
1368
- strokeRightWidth: frozenColumnSelectionWidth === selectionBounds.width &&
1369
- !isDraggingSelection
1370
- ? selectionStrokeWidth
1371
- : 0,
1372
- selection,
1373
- inProgress,
1374
- }));
1375
- }
1376
- if (isTopBoundFrozen) {
1377
- const frozenRowSelectionHeight = getRowOffset(Math.min(bottom + 1, frozenRows)) - getRowOffset(top);
1378
- selectionAreasFrozenRows.push(selectionRenderer({
1379
- ...styles,
1380
- type: "selection",
1381
- key: i,
1382
- x: selectionBounds.x,
1383
- y: selectionBounds.y,
1384
- width: selectionBounds.width,
1385
- height: frozenRowSelectionHeight,
1386
- strokeBottomWidth: frozenRowSelectionHeight === selectionBounds.height &&
1387
- !isDraggingSelection
1388
- ? selectionStrokeWidth
1389
- : 0,
1390
- selection,
1391
- inProgress,
1392
- }));
1393
- }
1394
- if (isIntersectionFrozen) {
1395
- const frozenIntersectionSelectionHeight = getRowOffset(Math.min(bottom + 1, frozenRows)) - getRowOffset(top);
1396
- const frozenIntersectionSelectionWidth = getColumnOffset(Math.min(right + 1, frozenColumns)) -
1397
- getColumnOffset(left);
1398
- selectionAreasIntersection.push(selectionRenderer({
1399
- ...styles,
1400
- type: "selection",
1401
- key: i,
1402
- x: selectionBounds.x,
1403
- y: selectionBounds.y,
1404
- width: frozenIntersectionSelectionWidth,
1405
- height: frozenIntersectionSelectionHeight,
1406
- strokeBottomWidth: frozenIntersectionSelectionHeight === selectionBounds.height &&
1407
- !isDraggingSelection
1408
- ? selectionStrokeWidth
1409
- : 0,
1410
- strokeRightWidth: frozenIntersectionSelectionWidth === selectionBounds.width &&
1411
- !isDraggingSelection
1412
- ? selectionStrokeWidth
1413
- : 0,
1414
- selection,
1415
- inProgress,
1416
- }));
1417
- }
1418
- selectionAreas.push(selectionRenderer({
1419
- ...styles,
1420
- type: "selection",
1421
- key: i,
1422
- x: selectionBounds.x,
1423
- y: selectionBounds.y,
1424
- width: selectionBounds.width,
1425
- height: selectionBounds.height,
1426
- selection,
1427
- inProgress,
1428
- }));
1429
- if (isLast) {
1430
- fillHandleDimension = {
1431
- x: selectionBounds.x + selectionBounds.width,
1432
- y: selectionBounds.y + selectionBounds.height,
1433
- };
1434
- }
1435
- }
1436
- /**
1437
- * Fillselection
1438
- */
1439
- let fillSelections = null;
1440
- if (fillSelection) {
1441
- const { bounds } = fillSelection;
1442
- const { top, left, right, bottom } = bounds;
1443
- const actualBottom = Math.min(rowStopIndex, bottom);
1444
- const actualRight = Math.min(columnStopIndex, right);
1445
- const x = getColumnOffset(left);
1446
- const y = getRowOffset(top);
1447
- const height = getRowOffset(actualBottom) - y + getRowHeight(actualBottom);
1448
- const width = getColumnOffset(actualRight) - x + getColumnWidth(actualRight);
1449
- fillSelections = selectionRenderer({
1450
- type: "fill",
1451
- x,
1452
- y,
1453
- width,
1454
- height,
1455
- key: -1,
1456
- stroke: "gray",
1457
- strokeStyle: "dashed",
1458
- });
1459
- }
1460
- const borderStyleCells = [];
1461
- const borderStyleCellsFrozenColumns = [];
1462
- const borderStyleCellsFrozenRows = [];
1463
- const borderStyleCellsIntersection = [];
1464
- for (let i = 0; i < borderStyles.length; i++) {
1465
- const { bounds, style, title, ...rest } = borderStyles[i];
1466
- const { top, right, bottom, left } = bounds;
1467
- const isLeftBoundFrozen = left < frozenColumns;
1468
- const isTopBoundFrozen = top < frozenRows;
1469
- const isIntersectionFrozen = top < frozenRows && left < frozenColumns;
1470
- const x = getColumnOffset(left);
1471
- const y = getRowOffset(top);
1472
- const width = getColumnOffset(Math.min(columnCount, right + 1)) - x;
1473
- const height = getRowOffset(Math.min(rowCount, bottom + 1)) - y;
1474
- borderStyleCells.push((0, utils_1.createHTMLBox)({
1475
- ...rest,
1476
- ...style,
1477
- x,
1478
- y,
1479
- key: i,
1480
- width,
1481
- height,
1482
- type: "border",
1483
- }));
1484
- if (isLeftBoundFrozen) {
1485
- const frozenColumnSelectionWidth = getColumnOffset(Math.min(right + 1, frozenColumns)) -
1486
- getColumnOffset(left);
1487
- borderStyleCellsFrozenColumns.push((0, utils_1.createHTMLBox)({
1488
- ...rest,
1489
- ...style,
1490
- type: "border",
1491
- x,
1492
- y,
1493
- key: i,
1494
- width: frozenColumnSelectionWidth,
1495
- height,
1496
- strokeRightWidth: frozenColumnSelectionWidth === width
1497
- ? (style === null || style === void 0 ? void 0 : style.strokeRightWidth) || (style === null || style === void 0 ? void 0 : style.strokeWidth)
1498
- : 0,
1499
- }));
1500
- }
1501
- if (isTopBoundFrozen) {
1502
- const frozenRowSelectionHeight = getRowOffset(Math.min(bottom + 1, frozenRows)) - getRowOffset(top);
1503
- borderStyleCellsFrozenRows.push((0, utils_1.createHTMLBox)({
1504
- ...rest,
1505
- ...style,
1506
- type: "border",
1507
- x,
1508
- y,
1509
- key: i,
1510
- width,
1511
- height: frozenRowSelectionHeight,
1512
- strokeBottomWidth: frozenRowSelectionHeight === height
1513
- ? (style === null || style === void 0 ? void 0 : style.strokeBottomWidth) || (style === null || style === void 0 ? void 0 : style.strokeWidth)
1514
- : 0,
1515
- }));
1516
- }
1517
- if (isIntersectionFrozen) {
1518
- const frozenIntersectionSelectionHeight = getRowOffset(Math.min(bottom + 1, frozenRows)) - getRowOffset(top);
1519
- const frozenIntersectionSelectionWidth = getColumnOffset(Math.min(right + 1, frozenColumns)) -
1520
- getColumnOffset(left);
1521
- borderStyleCellsIntersection.push((0, utils_1.createHTMLBox)({
1522
- ...rest,
1523
- ...style,
1524
- type: "border",
1525
- x,
1526
- y,
1527
- key: i,
1528
- width: frozenIntersectionSelectionWidth,
1529
- height: frozenIntersectionSelectionHeight,
1530
- strokeBottomWidth: frozenIntersectionSelectionHeight === height
1531
- ? selectionStrokeWidth
1532
- : 0,
1533
- strokeRightWidth: frozenIntersectionSelectionWidth === width
1534
- ? selectionStrokeWidth
1535
- : 0,
1536
- }));
1537
- }
1538
- }
1539
- /* Spacing for frozen row/column clip */
1540
- const frozenSpacing = 1;
1541
- /**
1542
- * Prevents drawing hit region when scrolling
1543
- */
1544
- const listenToEvents = !isScrolling;
1545
- /* Frozen row shadow */
1546
- const frozenRowShadowComponent = showFrozenShadow && frozenRows !== 0 ? frozenRowShadow : null;
1547
- /* Frozen column shadow */
1548
- const frozenColumnShadowComponent = showFrozenShadow && frozenColumns !== 0 ? frozenColumnShadow : null;
1549
- const stageChildren = (react_1.default.createElement(react_1.default.Fragment, null,
1550
- react_1.default.createElement(react_konva_1.Layer, null,
1551
- react_1.default.createElement(react_konva_1.Group, { clipX: frozenColumnWidth, clipY: frozenRowHeight, clipWidth: containerWidth - frozenColumnWidth, clipHeight: containerHeight - frozenRowHeight },
1552
- react_1.default.createElement(react_konva_1.Group, { offsetY: scrollTop, offsetX: scrollLeft },
1553
- gridLines,
1554
- cells,
1555
- cellOverlays,
1556
- ranges)),
1557
- react_1.default.createElement(react_konva_1.Group, { clipX: frozenColumnWidth, clipY: 0, clipWidth: containerWidth - frozenColumnWidth, clipHeight: frozenRowHeight + frozenSpacing },
1558
- react_1.default.createElement(react_konva_1.Group, { offsetY: 0, offsetX: scrollLeft },
1559
- gridLinesFrozenRow,
1560
- frozenRowCells,
1561
- frozenRowShadowComponent,
1562
- frozenRowCellOverlays)),
1563
- react_1.default.createElement(react_konva_1.Group, { clipX: 0, clipY: frozenRowHeight, clipWidth: frozenColumnWidth + frozenSpacing, clipHeight: containerHeight - frozenRowHeight },
1564
- react_1.default.createElement(react_konva_1.Group, { offsetY: scrollTop, offsetX: 0 },
1565
- gridLinesFrozenColumn,
1566
- frozenColumnCells,
1567
- frozenColumnShadowComponent,
1568
- frozenColumnCellOverlays)),
1569
- react_1.default.createElement(react_konva_1.Group, { offsetY: 0, offsetX: 0, clipX: 0, clipY: 0, clipWidth: frozenColumnWidth + frozenSpacing, clipHeight: frozenRowHeight + frozenSpacing },
1570
- gridLinesFrozenIntersection,
1571
- frozenIntersectionCells,
1572
- frozenRowShadowComponent,
1573
- frozenColumnShadowComponent,
1574
- frozenIntersectionCellOverlays)),
1575
- children && typeof children === "function"
1576
- ? children({
1577
- scrollLeft,
1578
- scrollTop,
1579
- })
1580
- : null));
1581
- const fillHandleWidth = 8;
1582
- const fillhandleComponent = showFillHandle && !isSelectionInProgress ? (react_1.default.createElement(FillHandle_1.default, { ...fillHandleDimension, stroke: selectionBorderColor, size: fillHandleWidth, borderColor: fillhandleBorderColor, ...fillHandleProps })) : null;
1583
- const selectionChildren = (react_1.default.createElement("div", { style: {
1584
- pointerEvents: "none",
1585
- } },
1586
- react_1.default.createElement("div", { style: {
1587
- position: "absolute",
1588
- left: frozenColumnWidth,
1589
- top: frozenRowHeight,
1590
- right: 0,
1591
- bottom: 0,
1592
- overflow: "hidden",
1593
- } },
1594
- react_1.default.createElement("div", { style: {
1595
- transform: `translate(-${scrollLeft + frozenColumnWidth}px, -${scrollTop + frozenRowHeight}px)`,
1596
- } },
1597
- borderStyleCells,
1598
- fillSelections,
1599
- selectionAreas,
1600
- activeCellSelection,
1601
- fillhandleComponent)),
1602
- frozenColumns ? (react_1.default.createElement("div", { style: {
1603
- position: "absolute",
1604
- width: frozenColumnWidth + fillHandleWidth,
1605
- top: frozenRowHeight,
1606
- left: 0,
1607
- bottom: 0,
1608
- overflow: "hidden",
1609
- } },
1610
- react_1.default.createElement("div", { style: {
1611
- transform: `translate(0, -${scrollTop + frozenRowHeight}px)`,
1612
- } },
1613
- borderStyleCellsFrozenColumns,
1614
- selectionAreasFrozenColumns,
1615
- activeCellSelectionFrozenColumn,
1616
- fillhandleComponent))) : null,
1617
- frozenRows ? (react_1.default.createElement("div", { style: {
1618
- position: "absolute",
1619
- height: frozenRowHeight + fillHandleWidth,
1620
- left: frozenColumnWidth,
1621
- right: 0,
1622
- top: 0,
1623
- overflow: "hidden",
1624
- } },
1625
- react_1.default.createElement("div", { style: {
1626
- transform: `translate(-${scrollLeft + frozenColumnWidth}px, 0)`,
1627
- } },
1628
- borderStyleCellsFrozenRows,
1629
- selectionAreasFrozenRows,
1630
- activeCellSelectionFrozenRow,
1631
- fillhandleComponent))) : null,
1632
- frozenRows && frozenColumns ? (react_1.default.createElement("div", { style: {
1633
- position: "absolute",
1634
- height: frozenRowHeight + fillHandleWidth,
1635
- width: frozenColumnWidth + fillHandleWidth,
1636
- left: 0,
1637
- top: 0,
1638
- overflow: "hidden",
1639
- pointerEvents: "none",
1640
- } },
1641
- borderStyleCellsIntersection,
1642
- selectionAreasIntersection,
1643
- activeCellSelectionFrozenIntersection,
1644
- fillhandleComponent)) : null));
1645
- return (react_1.default.createElement("div", { style: {
1646
- position: "relative",
1647
- width: containerWidth,
1648
- userSelect: "none",
1649
- }, className: "rowsncolumns-grid", ref: scrollContainerRef },
1650
- react_1.default.createElement("div", { className: "rowsncolumns-grid-container", tabIndex: 0, ref: containerRef, ...rest },
1651
- react_1.default.createElement(react_konva_1.Stage, { width: containerWidth, height: containerHeight, ref: stageRef, listening: listenToEvents, ...stageProps }, wrapper(stageChildren))),
1652
- selectionChildren,
1653
- showScrollbar ? (react_1.default.createElement(react_1.default.Fragment, null,
1654
- react_1.default.createElement("div", { className: "rowsncolumns-grid-scrollbar rowsncolumns-grid-scrollbar-y", tabIndex: -1, style: {
1655
- height: containerHeight,
1656
- overflow: "scroll",
1657
- position: "absolute",
1658
- right: 0,
1659
- top: 0,
1660
- width: scrollbarSize,
1661
- willChange: "transform",
1662
- }, onScroll: handleScroll, ref: verticalScrollRef },
1663
- react_1.default.createElement("div", { style: {
1664
- position: "absolute",
1665
- height: estimatedTotalHeight,
1666
- width: 1,
1667
- } })),
1668
- react_1.default.createElement("div", { className: "rowsncolumns-grid-scrollbar rowsncolumns-grid-scrollbar-x", tabIndex: -1, style: {
1669
- overflow: "scroll",
1670
- position: "absolute",
1671
- bottom: 0,
1672
- left: 0,
1673
- width: containerWidth,
1674
- height: scrollbarSize,
1675
- willChange: "transform",
1676
- }, onScroll: handleScrollLeft, ref: horizontalScrollRef },
1677
- react_1.default.createElement("div", { style: {
1678
- position: "absolute",
1679
- width: estimatedTotalWidth,
1680
- height: 1,
1681
- } })))) : null));
1682
- }));
1683
- exports.default = Grid;
1684
- //# sourceMappingURL=Grid.js.map