sheet-happens 0.0.35 → 0.0.37

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.
@@ -1,4 +1,4 @@
1
1
  import { CellPropertyFunction, Change, Rectangle } from './types';
2
2
  import { RefObject } from 'react';
3
3
  export declare const useClipboardCopy: (textAreaRef: RefObject<HTMLTextAreaElement>, selection: Rectangle, editMode: boolean, editData: CellPropertyFunction<string>) => void;
4
- export declare const useClipboardPaste: (textAreaRef: RefObject<HTMLTextAreaElement>, selection: Rectangle, onSelectionChange?: ((selection: Rectangle) => void) | undefined, onChange?: ((changes: Array<Change>) => void) | undefined) => void;
4
+ export declare const useClipboardPaste: (textAreaRef: RefObject<HTMLTextAreaElement>, selection: Rectangle, onSelectionChange?: ((selection: Rectangle) => void) | undefined, onChange?: ((changes: Array<Change>) => void) | undefined, isReadOnly?: CellPropertyFunction<boolean> | undefined) => void;
@@ -22,6 +22,7 @@ export declare const COLORS: {
22
22
  headerActiveText: string;
23
23
  headerSelected: string;
24
24
  headerSelectedText: string;
25
+ shadowColor: string;
25
26
  };
26
27
  export declare const SIZES: {
27
28
  knobArea: number;
@@ -32,6 +33,8 @@ export declare const SIZES: {
32
33
  resizeZone: number;
33
34
  scrollZone: number;
34
35
  scrollSpeed: number;
36
+ shadowBlur: number;
37
+ shadowOpacity: number;
35
38
  };
36
39
  export declare const DEFAULT_CELL_STYLE: Required<Style>;
37
40
  export declare const DEFAULT_COLUMN_HEADER_STYLE: Required<Style>;
@@ -16,3 +16,4 @@ export declare const isCellSelection: (selection: Rectangle) => boolean;
16
16
  export declare const isEmptySelection: (selection: Rectangle) => boolean;
17
17
  export declare const isPointInsideSelection: (selection: Rectangle, point: XY) => boolean;
18
18
  export declare const normalizeSelection: (selection: Rectangle) => Rectangle;
19
+ export declare const orientSelection: (normalized: Rectangle, to: Rectangle) => Rectangle;
@@ -0,0 +1,4 @@
1
+ import { Rectangle, RowOrColumnPropertyFunction } from './types';
2
+ export declare const expandSelectionToColumnGroups: (selection: Rectangle, columnGroupKeys: RowOrColumnPropertyFunction<string | number | null>) => Rectangle;
3
+ export declare const expandSelectionToRowGroups: (selection: Rectangle, rowGroupKeys: RowOrColumnPropertyFunction<string | number | null>) => Rectangle;
4
+ export declare const isBoundaryInsideGroup: (index: number, rowOrColumnGroupKeys: RowOrColumnPropertyFunction<string | number | null>) => boolean;
package/dist/index.css CHANGED
@@ -1,18 +1,21 @@
1
1
  ._PxIi8::-webkit-scrollbar {
2
- -webkit-appearance: none;
2
+ -webkit-appearance: none;
3
3
  }
4
4
  ._PxIi8::-webkit-scrollbar:vertical {
5
- width: 13px;
5
+ width: 13px;
6
6
  }
7
7
  ._PxIi8::-webkit-scrollbar:horizontal {
8
- height: 13px;
8
+ height: 13px;
9
+ }
10
+ ._PxIi8::-webkit-scrollbar-corner {
11
+ background: #fff;
9
12
  }
10
13
  ._PxIi8::-webkit-scrollbar-thumb {
11
- border-radius: 8px;
12
- background-color: #c1c1c1;
13
- border: 2px solid #fff;
14
+ border-radius: 8px;
15
+ background-color: #c1c1c1;
16
+ border: 2px solid #fff;
14
17
  }
15
18
  ._PxIi8::-webkit-scrollbar-track {
16
- background-color: #fff;
17
- border-radius: 0px;
18
- }
19
+ background-color: #fff;
20
+ border-radius: 0px;
21
+ }
package/dist/index.js CHANGED
@@ -78,7 +78,7 @@ var MAX_SEARCHABLE_INDEX = 65536;
78
78
  var MAX_XY = [MAX_SEARCHABLE_INDEX, MAX_SEARCHABLE_INDEX];
79
79
  var COLORS = {
80
80
  selectionBorder: '#1a66ff',
81
- selectionBackground: '#e8f0ff',
81
+ selectionBackground: '#d8e6ff80',
82
82
  gridLine: '#0000001f',
83
83
  dragGhost: '#1a66ff30',
84
84
  dropTarget: '#1a66ff',
@@ -88,7 +88,8 @@ var COLORS = {
88
88
  headerActive: '#e8f0ff',
89
89
  headerActiveText: '#1a66ff',
90
90
  headerSelected: '#1a66ff',
91
- headerSelectedText: '#ffffff'
91
+ headerSelectedText: '#ffffff',
92
+ shadowColor: '#000000'
92
93
  };
93
94
  var SIZES = {
94
95
  knobArea: 6,
@@ -98,7 +99,9 @@ var SIZES = {
98
99
  minimumHeight: 22,
99
100
  resizeZone: 4,
100
101
  scrollZone: 50,
101
- scrollSpeed: 30
102
+ scrollSpeed: 30,
103
+ shadowBlur: 12,
104
+ shadowOpacity: 0.05
102
105
  };
103
106
  var DEFAULT_CELL_STYLE = {
104
107
  textAlign: 'left',
@@ -130,10 +133,10 @@ var HEADER_SELECTED_STYLE = {
130
133
  color: COLORS.headerSelectedText
131
134
  };
132
135
  var ARROW_KEYS = {
133
- 'ArrowRight': 'right',
134
- 'ArrowLeft': 'left',
135
- 'ArrowUp': 'up',
136
- 'ArrowDown': 'down'
136
+ ArrowRight: 'right',
137
+ ArrowLeft: 'left',
138
+ ArrowUp: 'up',
139
+ ArrowDown: 'down'
137
140
  };
138
141
 
139
142
  var clamp = function clamp(x, min, max) {
@@ -264,26 +267,88 @@ var isPointInsideSelection = function isPointInsideSelection(selection, point) {
264
267
  return x >= left && x <= right && y >= top && y <= bottom;
265
268
  };
266
269
  var normalizeSelection = function normalizeSelection(selection) {
267
- var _selection$13 = selection[0],
268
- left = _selection$13[0],
269
- top = _selection$13[1],
270
- _selection$14 = selection[1],
271
- right = _selection$14[0],
272
- bottom = _selection$14[1];
273
-
274
- if (left > right) {
275
- var _ref = [right, left];
276
- left = _ref[0];
277
- right = _ref[1];
278
- }
270
+ var anchor = selection[0],
271
+ head = selection[1];
272
+ var ax = anchor[0],
273
+ ay = anchor[1];
274
+ var hx = head[0],
275
+ hy = head[1];
276
+ var left = Math.min(ax, hx);
277
+ var right = Math.max(ax, hx);
278
+ var top = Math.min(ay, hy);
279
+ var bottom = Math.max(ay, hy);
280
+ return [[left, top], [right, bottom]];
281
+ };
282
+ var orientSelection = function orientSelection(normalized, to) {
283
+ var _normalized$ = normalized[0],
284
+ left = _normalized$[0],
285
+ top = _normalized$[1],
286
+ _normalized$2 = normalized[1],
287
+ right = _normalized$2[0],
288
+ bottom = _normalized$2[1];
289
+ var anchor = to[0],
290
+ head = to[1];
291
+ var ax = anchor[0],
292
+ ay = anchor[1];
293
+ var hx = head[0],
294
+ hy = head[1];
295
+ var swapX = (ax - hx || 1) * (left - right || 1) < 0;
296
+ var swapY = (ay - hy || 1) * (top - bottom || 1) < 0;
297
+ return [[swapX ? right : left, swapY ? bottom : top], [swapX ? left : right, swapY ? top : bottom]];
298
+ };
279
299
 
280
- if (top > bottom) {
281
- var _ref2 = [bottom, top];
282
- top = _ref2[0];
283
- bottom = _ref2[1];
300
+ var LIMIT = 1000;
301
+
302
+ var scanGroup = function scanGroup(keys, index, direction, match) {
303
+ if (match == null) return index;
304
+ var i = 0;
305
+ var limit = direction > 0 ? LIMIT : Math.min(LIMIT, index + 1);
306
+
307
+ for (; i < limit; i++) {
308
+ if (keys(index + i * direction) !== match) break;
284
309
  }
285
310
 
286
- return [[left, top], [right, bottom]];
311
+ return index + (i - 1) * direction;
312
+ };
313
+
314
+ var expandSelectionToColumnGroups = function expandSelectionToColumnGroups(selection, columnGroupKeys) {
315
+ var _normalizeSelection = normalizeSelection(selection),
316
+ _normalizeSelection$ = _normalizeSelection[0],
317
+ left = _normalizeSelection$[0],
318
+ top = _normalizeSelection$[1],
319
+ _normalizeSelection$2 = _normalizeSelection[1],
320
+ right = _normalizeSelection$2[0],
321
+ bottom = _normalizeSelection$2[1];
322
+
323
+ var leftKey = columnGroupKeys(left);
324
+ var rightKey = columnGroupKeys(right);
325
+ var startColumn = scanGroup(columnGroupKeys, left, -1, leftKey);
326
+ var endColumn = scanGroup(columnGroupKeys, right, 1, rightKey);
327
+ var expanded = [[startColumn, top], [endColumn, bottom]];
328
+ var oriented = orientSelection(expanded, selection);
329
+ return oriented;
330
+ };
331
+ var expandSelectionToRowGroups = function expandSelectionToRowGroups(selection, rowGroupKeys) {
332
+ var _normalizeSelection2 = normalizeSelection(selection),
333
+ _normalizeSelection2$ = _normalizeSelection2[0],
334
+ left = _normalizeSelection2$[0],
335
+ top = _normalizeSelection2$[1],
336
+ _normalizeSelection2$2 = _normalizeSelection2[1],
337
+ right = _normalizeSelection2$2[0],
338
+ bottom = _normalizeSelection2$2[1];
339
+
340
+ var topKey = rowGroupKeys(top);
341
+ var bottomKey = rowGroupKeys(bottom);
342
+ var startRow = scanGroup(rowGroupKeys, top, -1, topKey);
343
+ var endRow = scanGroup(rowGroupKeys, bottom, 1, bottomKey);
344
+ var expanded = [[left, startRow], [right, endRow]];
345
+ var oriented = orientSelection(expanded, selection);
346
+ return oriented;
347
+ };
348
+ var isBoundaryInsideGroup = function isBoundaryInsideGroup(index, rowOrColumnGroupKeys) {
349
+ var before = rowOrColumnGroupKeys(index - 1);
350
+ var after = rowOrColumnGroupKeys(index);
351
+ return before != null && after != null && before === after;
287
352
  };
288
353
 
289
354
  var createRowOrColumnProp = function createRowOrColumnProp(rowColProp, defaultValue) {
@@ -429,7 +494,7 @@ var findInDisplayData = function findInDisplayData(displayData, start, direction
429
494
  return maxXY(cell, [0, 0]);
430
495
  };
431
496
 
432
- var useMouse = function useMouse(hitmapRef, selection, knobArea, editMode, editData, sourceData, cellReadOnly, canSizeColumn, canSizeRow, canOrderColumn, canOrderRow, cellLayout, visibleCells, sheetStyle, onEdit, onCommit, onKnobAreaChange, onDragOffsetChange, onDropTargetChange, onSelectionChange, onInvalidateColumn, onInvalidateRow, onChange, onColumnOrderChange, onRowOrderChange, onCellWidthChange, onCellHeightChange, onRightClick, dontCommitEditOnSelectionChange) {
497
+ var useMouse = function useMouse(hitmapRef, selection, knobArea, editMode, editData, sourceData, cellReadOnly, canSizeColumn, canSizeRow, canOrderColumn, canOrderRow, cellLayout, visibleCells, sheetStyle, columnGroupKeys, rowGroupKeys, onEdit, onCommit, onKnobAreaChange, onDragOffsetChange, onDropTargetChange, onSelectionChange, onInvalidateColumn, onInvalidateRow, onChange, onColumnOrderChange, onRowOrderChange, onCellWidthChange, onCellHeightChange, onRightClick, dontCommitEditOnSelectionChange) {
433
498
  var _useState = React.useState(null),
434
499
  hitTarget = _useState[0],
435
500
  setHitTarget = _useState[1];
@@ -765,7 +830,7 @@ var useMouse = function useMouse(hitmapRef, selection, knobArea, editMode, editD
765
830
 
766
831
  setDraggingSelection(true);
767
832
  onSelectionChange === null || onSelectionChange === void 0 ? void 0 : onSelectionChange([anchor, head], scrollTo, true);
768
- }, [getMousePosition, getScrollPosition, getMouseHit, onColumnOrderChange, onRowOrderChange, onCellWidthChange, onCellHeightChange, onKnobAreaChange, onSelectionChange, onCommit, canSizeColumn, canSizeRow, canOrderColumn, canOrderRow]);
833
+ }, [getMousePosition, getScrollPosition, getMouseHit, onColumnOrderChange, onRowOrderChange, onCellWidthChange, onCellHeightChange, onKnobAreaChange, onSelectionChange, onCommit, canSizeColumn, canSizeRow, canOrderColumn, canOrderRow, dontCommitEditOnSelectionChange]);
769
834
  var onPointerUp = React.useCallback(function (e) {
770
835
  var _getMouseHit;
771
836
 
@@ -817,7 +882,7 @@ var useMouse = function useMouse(hitmapRef, selection, knobArea, editMode, editD
817
882
 
818
883
  if (!insideSelection) {
819
884
  var order = cellX > minX ? cellX - indices.length : cellX;
820
- onSelectionChange === null || onSelectionChange === void 0 ? void 0 : onSelectionChange([[order, minY], [order + maxX - minX, maxY]]);
885
+ onSelectionChange === null || onSelectionChange === void 0 ? void 0 : onSelectionChange([[order, minY], [order + maxX - minX, maxY]], false, false, true);
821
886
  onColumnOrderChange === null || onColumnOrderChange === void 0 ? void 0 : onColumnOrderChange(indices, order);
822
887
  onInvalidateColumn === null || onInvalidateColumn === void 0 ? void 0 : onInvalidateColumn(Math.min(minX, order));
823
888
  }
@@ -831,7 +896,7 @@ var useMouse = function useMouse(hitmapRef, selection, knobArea, editMode, editD
831
896
  if (!_insideSelection) {
832
897
  var _order = cellY > minY ? cellY - _indices4.length : cellY;
833
898
 
834
- onSelectionChange === null || onSelectionChange === void 0 ? void 0 : onSelectionChange([[minX, _order], [maxX, _order + maxY - minY]]);
899
+ onSelectionChange === null || onSelectionChange === void 0 ? void 0 : onSelectionChange([[minX, _order], [maxX, _order + maxY - minY]], false, false, true);
835
900
  onRowOrderChange === null || onRowOrderChange === void 0 ? void 0 : onRowOrderChange(_indices4, _order);
836
901
  onInvalidateRow === null || onInvalidateRow === void 0 ? void 0 : onInvalidateRow(Math.min(minY, _order));
837
902
  }
@@ -1091,6 +1156,7 @@ var useMouse = function useMouse(hitmapRef, selection, knobArea, editMode, editD
1091
1156
  var _cellX = pixelToColumn(Math.max(_x, getIndentX()), 0.5);
1092
1157
 
1093
1158
  var insideSelection = _cellX >= minX && _cellX <= maxX + 1;
1159
+ var insideGroup = isBoundaryInsideGroup(_cellX, columnGroupKeys);
1094
1160
  var _anchor3 = columnDrag.anchor,
1095
1161
  _scroll5 = columnDrag.scroll;
1096
1162
  var shift = _x - _anchor3;
@@ -1099,7 +1165,7 @@ var useMouse = function useMouse(hitmapRef, selection, knobArea, editMode, editD
1099
1165
  _currentScroll2 = _getScrollPosition7[0];
1100
1166
 
1101
1167
  onDragOffsetChange === null || onDragOffsetChange === void 0 ? void 0 : onDragOffsetChange([shift + _currentScroll2 - _scroll5, 0]);
1102
- onDropTargetChange === null || onDropTargetChange === void 0 ? void 0 : onDropTargetChange(insideSelection ? null : [[_cellX, -1], [_cellX, -1]]);
1168
+ onDropTargetChange === null || onDropTargetChange === void 0 ? void 0 : onDropTargetChange(insideSelection || insideGroup ? null : [[_cellX, -1], [_cellX, -1]]);
1103
1169
  }
1104
1170
 
1105
1171
  if (rowDrag) {
@@ -1107,6 +1173,8 @@ var useMouse = function useMouse(hitmapRef, selection, knobArea, editMode, editD
1107
1173
 
1108
1174
  var _insideSelection2 = _cellY >= minY && _cellY <= maxY + 1;
1109
1175
 
1176
+ var _insideGroup = isBoundaryInsideGroup(_cellY, rowGroupKeys);
1177
+
1110
1178
  var _anchor4 = rowDrag.anchor,
1111
1179
  _scroll6 = rowDrag.scroll;
1112
1180
 
@@ -1116,10 +1184,10 @@ var useMouse = function useMouse(hitmapRef, selection, knobArea, editMode, editD
1116
1184
  _currentScroll3 = _getScrollPosition8[1];
1117
1185
 
1118
1186
  onDragOffsetChange === null || onDragOffsetChange === void 0 ? void 0 : onDragOffsetChange([0, _shift + _currentScroll3 - _scroll6]);
1119
- onDropTargetChange === null || onDropTargetChange === void 0 ? void 0 : onDropTargetChange(_insideSelection2 ? null : [[-1, _cellY], [-1, _cellY]]);
1187
+ onDropTargetChange === null || onDropTargetChange === void 0 ? void 0 : onDropTargetChange(_insideSelection2 || _insideGroup ? null : [[-1, _cellY], [-1, _cellY]]);
1120
1188
  }
1121
1189
  }
1122
- }, [getMousePosition, getScrollPosition, getMouseHit, onCellWidthChange, onCellHeightChange]);
1190
+ }, [getMousePosition, getScrollPosition, getMouseHit, onCellWidthChange, onCellHeightChange, onDragOffsetChange, onDropTargetChange, onSelectionChange, onKnobAreaChange, onInvalidateRow, onInvalidateColumn]);
1123
1191
  var onDoubleClick = React.useCallback(function (e) {
1124
1192
  var pixelToCell = ref.current.cellLayout.pixelToCell;
1125
1193
  e.preventDefault();
@@ -1422,7 +1490,7 @@ var useClipboardCopy = function useClipboardCopy(textAreaRef, selection, editMod
1422
1490
  }
1423
1491
  });
1424
1492
  };
1425
- var useClipboardPaste = function useClipboardPaste(textAreaRef, selection, onSelectionChange, onChange) {
1493
+ var useClipboardPaste = function useClipboardPaste(textAreaRef, selection, onSelectionChange, onChange, isReadOnly) {
1426
1494
  React.useEffect(function () {
1427
1495
  var onPaste = function onPaste(e) {
1428
1496
  var textArea = textAreaRef.current;
@@ -1435,10 +1503,10 @@ var useClipboardPaste = function useClipboardPaste(textAreaRef, selection, onSel
1435
1503
 
1436
1504
  if (types.includes('text/html')) {
1437
1505
  var pastedHtml = clipboardData.getData('text/html');
1438
- parsed = parsePastedHtml(selection, pastedHtml);
1506
+ parsed = parsePastedHtml(selection, pastedHtml, isReadOnly);
1439
1507
  } else if (types.includes('text/plain')) {
1440
1508
  var text = clipboardData.getData('text/plain');
1441
- parsed = parsePastedText(selection, text);
1509
+ parsed = parsePastedText(selection, text, isReadOnly);
1442
1510
  }
1443
1511
 
1444
1512
  if (!parsed) return;
@@ -1524,7 +1592,7 @@ var findTable = function findTable(element) {
1524
1592
  }
1525
1593
  };
1526
1594
 
1527
- var parsePastedHtml = function parsePastedHtml(selection, html) {
1595
+ var parsePastedHtml = function parsePastedHtml(selection, html, isReadOnly) {
1528
1596
  var div = document.createElement('div');
1529
1597
  div.innerHTML = html.trim();
1530
1598
 
@@ -1575,7 +1643,7 @@ var parsePastedHtml = function parsePastedHtml(selection, html) {
1575
1643
 
1576
1644
  str = str.replaceAll('\n', '');
1577
1645
  str = str.replaceAll(/\s\s+/g, ' ');
1578
- changes.push({
1646
+ if (!(isReadOnly !== null && isReadOnly !== void 0 && isReadOnly(x, y))) changes.push({
1579
1647
  x: x,
1580
1648
  y: y,
1581
1649
  value: str
@@ -1599,7 +1667,7 @@ var parsePastedHtml = function parsePastedHtml(selection, html) {
1599
1667
  };
1600
1668
  };
1601
1669
 
1602
- var parsePastedText = function parsePastedText(selection, text) {
1670
+ var parsePastedText = function parsePastedText(selection, text, isReadOnly) {
1603
1671
  var _normalizeSelection3 = normalizeSelection(selection),
1604
1672
  _normalizeSelection3$ = _normalizeSelection3[0],
1605
1673
  minX = _normalizeSelection3$[0],
@@ -1617,9 +1685,11 @@ var parsePastedText = function parsePastedText(selection, text) {
1617
1685
  right = Math.max(right, left + cols.length - 1);
1618
1686
 
1619
1687
  for (var x = 0; x < cols.length; x++) {
1620
- changes.push({
1621
- x: left + x,
1622
- y: top + y,
1688
+ var X = left + x;
1689
+ var Y = top + y;
1690
+ if (!(isReadOnly !== null && isReadOnly !== void 0 && isReadOnly(X, Y))) changes.push({
1691
+ x: X,
1692
+ y: Y,
1623
1693
  value: cols[x]
1624
1694
  });
1625
1695
  }
@@ -2009,6 +2079,8 @@ var makeIntMap = function makeIntMap(initialSize) {
2009
2079
  };
2010
2080
 
2011
2081
  var resolveSheetStyle = function resolveSheetStyle(sheetStyle) {
2082
+ var _sheetStyle$shadowBlu, _sheetStyle$shadowOpa, _sheetStyle$shadowCol;
2083
+
2012
2084
  return {
2013
2085
  freezeColumns: (sheetStyle === null || sheetStyle === void 0 ? void 0 : sheetStyle.freezeColumns) || 0,
2014
2086
  freezeRows: (sheetStyle === null || sheetStyle === void 0 ? void 0 : sheetStyle.freezeRows) || 0,
@@ -2017,7 +2089,10 @@ var resolveSheetStyle = function resolveSheetStyle(sheetStyle) {
2017
2089
  hideGridlines: (sheetStyle === null || sheetStyle === void 0 ? void 0 : sheetStyle.hideGridlines) || false,
2018
2090
  hideScrollBars: (sheetStyle === null || sheetStyle === void 0 ? void 0 : sheetStyle.hideScrollBars) || false,
2019
2091
  columnHeaderHeight: sheetStyle !== null && sheetStyle !== void 0 && sheetStyle.hideColumnHeaders ? 1 : SIZES.headerHeight,
2020
- rowHeaderWidth: sheetStyle !== null && sheetStyle !== void 0 && sheetStyle.hideRowHeaders ? 1 : SIZES.headerWidth
2092
+ rowHeaderWidth: sheetStyle !== null && sheetStyle !== void 0 && sheetStyle.hideRowHeaders ? 1 : SIZES.headerWidth,
2093
+ shadowBlur: (_sheetStyle$shadowBlu = sheetStyle === null || sheetStyle === void 0 ? void 0 : sheetStyle.shadowBlur) != null ? _sheetStyle$shadowBlu : SIZES.shadowBlur,
2094
+ shadowOpacity: (_sheetStyle$shadowOpa = sheetStyle === null || sheetStyle === void 0 ? void 0 : sheetStyle.shadowOpacity) != null ? _sheetStyle$shadowOpa : SIZES.shadowOpacity,
2095
+ shadowColor: (_sheetStyle$shadowCol = sheetStyle === null || sheetStyle === void 0 ? void 0 : sheetStyle.shadowColor) != null ? _sheetStyle$shadowCol : COLORS.shadowColor
2021
2096
  };
2022
2097
  };
2023
2098
  var resolveCellStyle = function resolveCellStyle(optionalStyle, defaultStyle) {
@@ -2049,11 +2124,16 @@ var renderSheet = function renderSheet(context, cellLayout, visibleCells, sheetS
2049
2124
  rowHeaderWidth = sheetStyle.rowHeaderWidth,
2050
2125
  columnHeaderHeight = sheetStyle.columnHeaderHeight,
2051
2126
  freezeColumns = sheetStyle.freezeColumns,
2052
- freezeRows = sheetStyle.freezeRows;
2127
+ freezeRows = sheetStyle.freezeRows,
2128
+ shadowBlur = sheetStyle.shadowBlur,
2129
+ shadowColor = sheetStyle.shadowColor,
2130
+ shadowOpacity = sheetStyle.shadowOpacity;
2053
2131
  var columns = visibleCells.columns,
2054
2132
  rows = visibleCells.rows;
2055
2133
  var columnToPixel = cellLayout.columnToPixel,
2056
- rowToPixel = cellLayout.rowToPixel;
2134
+ rowToPixel = cellLayout.rowToPixel,
2135
+ columnToAbsolute = cellLayout.columnToAbsolute,
2136
+ rowToAbsolute = cellLayout.rowToAbsolute;
2057
2137
  var clickables = [];
2058
2138
  var freeze = [freezeColumns, freezeRows];
2059
2139
  var indent = [rowHeaderWidth, columnHeaderHeight];
@@ -2061,6 +2141,7 @@ var renderSheet = function renderSheet(context, cellLayout, visibleCells, sheetS
2061
2141
  context.clearRect(0, 0, width, height);
2062
2142
  context.fillStyle = 'white';
2063
2143
  context.fillRect(0, 0, width, height);
2144
+ context.shadowColor = '#00000080';
2064
2145
 
2065
2146
  for (var _iterator = _createForOfIteratorHelperLoose(rows), _step; !(_step = _iterator()).done;) {
2066
2147
  var y = _step.value;
@@ -2140,15 +2221,15 @@ var renderSheet = function renderSheet(context, cellLayout, visibleCells, sheetS
2140
2221
 
2141
2222
  var drawGridLineX = function drawGridLineX(x, height) {
2142
2223
  context.beginPath();
2143
- context.moveTo(x - .5, 0);
2144
- context.lineTo(x - .5, height);
2224
+ context.moveTo(x - 0.5, 0);
2225
+ context.lineTo(x - 0.5, height);
2145
2226
  context.stroke();
2146
2227
  };
2147
2228
 
2148
2229
  var drawGridLineY = function drawGridLineY(y, width) {
2149
2230
  context.beginPath();
2150
- context.moveTo(0, y - .5);
2151
- context.lineTo(width, y - .5);
2231
+ context.moveTo(0, y - 0.5);
2232
+ context.lineTo(width, y - 0.5);
2152
2233
  context.stroke();
2153
2234
  };
2154
2235
 
@@ -2328,6 +2409,31 @@ var renderSheet = function renderSheet(context, cellLayout, visibleCells, sheetS
2328
2409
  context.strokeRect(_left6 - 1, _top6 - 1, _right6 - _left6, _bottom6 - _top6);
2329
2410
  }
2330
2411
 
2412
+ var scrollX = dataOffset[0],
2413
+ scrollY = dataOffset[1];
2414
+ var hasRowShadow = freezeRows > 0 && scrollY > 0;
2415
+ var hasColumnShadow = freezeColumns > 0 && scrollX > 0;
2416
+
2417
+ if (hasRowShadow || hasColumnShadow) {
2418
+ if (hasRowShadow) {
2419
+ var h = columnHeaderHeight + rowToAbsolute(freezeRows);
2420
+ var gradient = context.createLinearGradient(0, h, 0, h + shadowBlur);
2421
+ halfShadowGradient(gradient, shadowColor, shadowOpacity);
2422
+ context.fillStyle = gradient;
2423
+ context.fillRect(0, h, width, shadowBlur);
2424
+ }
2425
+
2426
+ if (hasColumnShadow) {
2427
+ var w = rowHeaderWidth + columnToAbsolute(freezeColumns);
2428
+
2429
+ var _gradient = context.createLinearGradient(w, 0, w + shadowBlur, 0);
2430
+
2431
+ halfShadowGradient(_gradient, shadowColor, shadowOpacity);
2432
+ context.fillStyle = _gradient;
2433
+ context.fillRect(w, 0, shadowBlur, height);
2434
+ }
2435
+ }
2436
+
2331
2437
  context.textBaseline = 'middle';
2332
2438
 
2333
2439
  for (var _iterator7 = _createForOfIteratorHelperLoose(rows), _step7; !(_step7 = _iterator7()).done;) {
@@ -2593,8 +2699,27 @@ var excelHeaderString = function excelHeaderString(num) {
2593
2699
  return s || '';
2594
2700
  };
2595
2701
 
2702
+ var halfShadowGradient = function halfShadowGradient(gradient, rgb, opacity) {
2703
+ var hex = function hex(x) {
2704
+ return ('0' + Math.round(x).toString(16)).slice(-2);
2705
+ };
2706
+
2707
+ var ease = function ease(x) {
2708
+ return 1.0 - Math.sin(x * Math.PI / 2);
2709
+ };
2710
+
2711
+ var adjust = function adjust(x) {
2712
+ return 1.0 - Math.pow(1.0 - x, 2.2);
2713
+ };
2714
+
2715
+ for (var i = 0; i <= 16; ++i) {
2716
+ var f = i / 16;
2717
+ gradient.addColorStop(f, rgb + hex(adjust(opacity * ease(f) * 0.5) * 255));
2718
+ }
2719
+ };
2720
+
2596
2721
  var Sheet = React.forwardRef(function (props, ref) {
2597
- var _props$selection, _props$secondarySelec, _props$inputComponent;
2722
+ var _props$selection, _props$secondarySelec, _props$cacheLayout, _props$inputComponent;
2598
2723
 
2599
2724
  var canvasRef = React.useRef(null);
2600
2725
  var overlayRef = React.useRef(null);
@@ -2678,6 +2803,12 @@ var Sheet = React.forwardRef(function (props, ref) {
2678
2803
  var canOrderRow = React.useMemo(function () {
2679
2804
  return createRowOrColumnProp(props.canOrderRow, true);
2680
2805
  }, [props.canOrderRow]);
2806
+ var rowGroupKeys = React.useMemo(function () {
2807
+ return createRowOrColumnProp(props.rowGroupKeys, null);
2808
+ }, [props.rowGroupKeys]);
2809
+ var columnGroupKeys = React.useMemo(function () {
2810
+ return createRowOrColumnProp(props.columnGroupKeys, null);
2811
+ }, [props.columnGroupKeys]);
2681
2812
  var cellReadOnly = React.useMemo(function () {
2682
2813
  return createCellProp(props.readOnly, false);
2683
2814
  }, [props.readOnly]);
@@ -2705,17 +2836,19 @@ var Sheet = React.forwardRef(function (props, ref) {
2705
2836
  var editCellX = editCell[0],
2706
2837
  editCellY = editCell[1];
2707
2838
  var editMode = editCellX !== -1 && editCellY !== -1;
2839
+ var shouldCacheLayout = ((_props$cacheLayout = props.cacheLayout) != null ? _props$cacheLayout : false) !== false;
2840
+ var layoutVersion = typeof props.cacheLayout === 'number' ? props.cacheLayout : 0;
2708
2841
  var columnLayout = React.useMemo(function () {
2709
2842
  return makeLayoutCache(cellWidth);
2710
- }, [props.cacheLayout ? null : cellWidth]);
2843
+ }, [shouldCacheLayout ? layoutVersion : cellWidth]);
2711
2844
  var rowLayout = React.useMemo(function () {
2712
2845
  return makeLayoutCache(cellHeight);
2713
- }, [props.cacheLayout ? null : cellHeight]);
2846
+ }, [shouldCacheLayout ? layoutVersion : cellHeight]);
2714
2847
  React.useMemo(function () {
2715
- if (!props.cacheLayout) return;
2848
+ if (!shouldCacheLayout) return;
2716
2849
  columnLayout.setSizer(cellWidth);
2717
2850
  rowLayout.setSizer(cellHeight);
2718
- }, [props.cacheLayout, cellWidth, cellHeight]);
2851
+ }, [shouldCacheLayout, layoutVersion, cellWidth, cellHeight]);
2719
2852
  var freezeColumns = sheetStyle.freezeColumns,
2720
2853
  freezeRows = sheetStyle.freezeRows,
2721
2854
  rowHeaderWidth = sheetStyle.rowHeaderWidth,
@@ -2735,7 +2868,7 @@ var Sheet = React.forwardRef(function (props, ref) {
2735
2868
  }
2736
2869
  }, [visibleCells, props.onScrollChange]);
2737
2870
 
2738
- var changeSelection = function changeSelection(newSelection, scrollTo, toHead) {
2871
+ var changeSelection = function changeSelection(newSelection, scrollTo, toHead, dragOperation) {
2739
2872
  if (scrollTo === void 0) {
2740
2873
  scrollTo = true;
2741
2874
  }
@@ -2744,6 +2877,20 @@ var Sheet = React.forwardRef(function (props, ref) {
2744
2877
  toHead = false;
2745
2878
  }
2746
2879
 
2880
+ if (dragOperation === void 0) {
2881
+ dragOperation = false;
2882
+ }
2883
+
2884
+ if (!dragOperation) {
2885
+ if (isColumnSelection(newSelection) && columnGroupKeys) {
2886
+ newSelection = expandSelectionToColumnGroups(newSelection, columnGroupKeys);
2887
+ }
2888
+
2889
+ if (isRowSelection(newSelection) && rowGroupKeys) {
2890
+ newSelection = expandSelectionToRowGroups(newSelection, rowGroupKeys);
2891
+ }
2892
+ }
2893
+
2747
2894
  if (!isSameSelection(selection, newSelection)) {
2748
2895
  setSelection(newSelection);
2749
2896
  }
@@ -2752,8 +2899,9 @@ var Sheet = React.forwardRef(function (props, ref) {
2752
2899
  if (!overlay) return;
2753
2900
 
2754
2901
  if (scrollTo) {
2755
- var anchor = newSelection[0],
2756
- head = newSelection[1];
2902
+ var _newSelection = newSelection,
2903
+ anchor = _newSelection[0],
2904
+ head = _newSelection[1];
2757
2905
  scrollToCell(overlay, toHead ? head : anchor, [canvasWidth, canvasHeight], [freezeColumns, freezeRows], dataOffset, maxScroll, cellLayout, function (dataOffset, maxScroll) {
2758
2906
  setDataOffset(dataOffset);
2759
2907
  setMaxScroll(maxScroll);
@@ -2815,10 +2963,10 @@ var Sheet = React.forwardRef(function (props, ref) {
2815
2963
  var hitmapRef = React.useRef(NO_CLICKABLES);
2816
2964
  var textAreaRef = React.useRef(null);
2817
2965
  useClipboardCopy(textAreaRef, selection, editMode, editData);
2818
- useClipboardPaste(textAreaRef, selection, changeSelection, props.onChange);
2966
+ useClipboardPaste(textAreaRef, selection, changeSelection, props.onChange, cellReadOnly);
2819
2967
  var onScroll = useScroll(dataOffset, maxScroll, cellLayout, setDataOffset, setMaxScroll);
2820
2968
 
2821
- var _useMouse = useMouse(hitmapRef, selection, knobArea, editMode, editData, sourceData, cellReadOnly, canSizeColumn, canSizeRow, canOrderColumn, canOrderRow, cellLayout, visibleCells, sheetStyle, startEditingCell, commitEditingCell, setKnobArea, setDragOffset, setDropTarget, changeSelection, props.cacheLayout ? columnLayout.clearAfter : undefined, props.cacheLayout ? rowLayout.clearAfter : undefined, props.onChange, props.onColumnOrderChange, props.onRowOrderChange, props.onCellWidthChange, props.onCellHeightChange, props.onRightClick, props.dontCommitEditOnSelectionChange),
2969
+ var _useMouse = useMouse(hitmapRef, selection, knobArea, editMode, editData, sourceData, cellReadOnly, canSizeColumn, canSizeRow, canOrderColumn, canOrderRow, cellLayout, visibleCells, sheetStyle, columnGroupKeys, rowGroupKeys, startEditingCell, commitEditingCell, setKnobArea, setDragOffset, setDropTarget, changeSelection, props.cacheLayout ? columnLayout.clearAfter : undefined, props.cacheLayout ? rowLayout.clearAfter : undefined, props.onChange, props.onColumnOrderChange, props.onRowOrderChange, props.onCellWidthChange, props.onCellHeightChange, props.onRightClick, props.dontCommitEditOnSelectionChange),
2822
2970
  mouseHandlers = _useMouse.mouseHandlers,
2823
2971
  knobPosition = _useMouse.knobPosition;
2824
2972
 
@@ -3017,8 +3165,8 @@ var Sheet = React.forwardRef(function (props, ref) {
3017
3165
  borderBottom: '1px solid #ddd'
3018
3166
  };
3019
3167
  var canvasStyles = {
3020
- width: 'calc(100% - 14px)',
3021
- height: 'calc(100% - 15px)',
3168
+ width: canvasWidth,
3169
+ height: canvasHeight,
3022
3170
  outline: '1px solid #ddd'
3023
3171
  };
3024
3172
 
@@ -3026,7 +3174,6 @@ var Sheet = React.forwardRef(function (props, ref) {
3026
3174
  delete canvasStyles['outline'];
3027
3175
  delete overlayDivStyles['borderBottom'];
3028
3176
  overlayDivClassName = '';
3029
- canvasStyles.width = 'calc(100%)';
3030
3177
  }
3031
3178
 
3032
3179
  var renderedInside = React.useMemo(function () {