@deephaven/grid 1.27.5-alpha-nodehttp2-config3.276eddc.0 → 1.29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Grid.d.ts +102 -43
- package/dist/Grid.d.ts.map +1 -1
- package/dist/Grid.js +442 -390
- package/dist/Grid.js.map +1 -1
- package/dist/GridA11yFallback.d.ts +26 -0
- package/dist/GridA11yFallback.d.ts.map +1 -0
- package/dist/GridA11yFallback.js +115 -0
- package/dist/GridA11yFallback.js.map +1 -0
- package/dist/GridA11yUtils.d.ts +89 -0
- package/dist/GridA11yUtils.d.ts.map +1 -0
- package/dist/GridA11yUtils.js +321 -0
- package/dist/GridA11yUtils.js.map +1 -0
- package/dist/GridRenderer.d.ts +9 -0
- package/dist/GridRenderer.d.ts.map +1 -1
- package/dist/GridRenderer.js +187 -39
- package/dist/GridRenderer.js.map +1 -1
- package/dist/GridRendererTypes.d.ts +3 -4
- package/dist/GridRendererTypes.d.ts.map +1 -1
- package/dist/GridRendererTypes.js.map +1 -1
- package/dist/GridSelectionUtils.d.ts +98 -0
- package/dist/GridSelectionUtils.d.ts.map +1 -0
- package/dist/GridSelectionUtils.js +180 -0
- package/dist/GridSelectionUtils.js.map +1 -0
- package/dist/RangedSelection.d.ts +120 -0
- package/dist/RangedSelection.d.ts.map +1 -0
- package/dist/RangedSelection.js +375 -0
- package/dist/RangedSelection.js.map +1 -0
- package/dist/Selection.d.ts +221 -0
- package/dist/Selection.d.ts.map +1 -0
- package/dist/Selection.js +71 -0
- package/dist/Selection.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/key-handlers/EditKeyHandler.js +3 -3
- package/dist/key-handlers/EditKeyHandler.js.map +1 -1
- package/dist/key-handlers/SelectionKeyHandler.d.ts +1 -0
- package/dist/key-handlers/SelectionKeyHandler.d.ts.map +1 -1
- package/dist/key-handlers/SelectionKeyHandler.js +144 -138
- package/dist/key-handlers/SelectionKeyHandler.js.map +1 -1
- package/dist/key-handlers/TreeKeyHandler.d.ts.map +1 -1
- package/dist/key-handlers/TreeKeyHandler.js +6 -3
- package/dist/key-handlers/TreeKeyHandler.js.map +1 -1
- package/dist/mouse-handlers/GridRowTreeMouseHandler.d.ts +1 -0
- package/dist/mouse-handlers/GridRowTreeMouseHandler.d.ts.map +1 -1
- package/dist/mouse-handlers/GridRowTreeMouseHandler.js +7 -0
- package/dist/mouse-handlers/GridRowTreeMouseHandler.js.map +1 -1
- package/dist/mouse-handlers/GridSelectionMouseHandler.d.ts +0 -9
- package/dist/mouse-handlers/GridSelectionMouseHandler.d.ts.map +1 -1
- package/dist/mouse-handlers/GridSelectionMouseHandler.js +41 -39
- package/dist/mouse-handlers/GridSelectionMouseHandler.js.map +1 -1
- package/dist/mouse-handlers/GridTokenMouseHandler.js +4 -1
- package/dist/mouse-handlers/GridTokenMouseHandler.js.map +1 -1
- package/package.json +3 -3
package/dist/Grid.js
CHANGED
|
@@ -25,6 +25,9 @@ import { isExpandableGridModel } from "./ExpandableGridModel.js";
|
|
|
25
25
|
import { assertIsEditableGridModel, isEditableGridModel } from "./EditableGridModel.js";
|
|
26
26
|
import { assertIsDefined } from "./errors/index.js";
|
|
27
27
|
import ThemeContext from "./ThemeContext.js";
|
|
28
|
+
import { RangedSelection, assertIsRangedSelection, isRangedSelection, selectionToRanges } from "./RangedSelection.js";
|
|
29
|
+
import GridA11yFallback from "./GridA11yFallback.js";
|
|
30
|
+
/** Selection-related slice of `GridState`. Returned by gesture entry points. */
|
|
28
31
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
29
32
|
/**
|
|
30
33
|
* High performance, extendible, themeable grid component.
|
|
@@ -89,6 +92,8 @@ class Grid extends PureComponent {
|
|
|
89
92
|
_defineProperty(this, "prevMetrics", void 0);
|
|
90
93
|
_defineProperty(this, "metrics", void 0);
|
|
91
94
|
_defineProperty(this, "renderState", void 0);
|
|
95
|
+
// Listeners for when the grid draws its canvas.
|
|
96
|
+
_defineProperty(this, "drawListeners", void 0);
|
|
92
97
|
// Track the cursor that is currently added to the document
|
|
93
98
|
// Add to document so that when dragging the cursor stays, even if mouse leaves the canvas
|
|
94
99
|
// Note: on document, not body so that cursor styling can be combined with
|
|
@@ -118,7 +123,9 @@ class Grid extends PureComponent {
|
|
|
118
123
|
this.handleMouseUp = this.handleMouseUp.bind(this);
|
|
119
124
|
this.handleResize = this.handleResize.bind(this);
|
|
120
125
|
this.handleWheel = this.handleWheel.bind(this);
|
|
126
|
+
this.registerDrawListener = this.registerDrawListener.bind(this);
|
|
121
127
|
this.getSelectedRanges = this.getSelectedRanges.bind(this);
|
|
128
|
+
this.getModel = this.getModel.bind(this);
|
|
122
129
|
var isStuckToBottom = props.isStuckToBottom,
|
|
123
130
|
isStuckToRight = props.isStuckToRight,
|
|
124
131
|
metricCalculator = props.metricCalculator,
|
|
@@ -134,7 +141,8 @@ class Grid extends PureComponent {
|
|
|
134
141
|
this.animationFrame = null;
|
|
135
142
|
this.prevMetrics = null;
|
|
136
143
|
this.metrics = null;
|
|
137
|
-
this.renderState =
|
|
144
|
+
this.renderState = null;
|
|
145
|
+
this.drawListeners = new Set();
|
|
138
146
|
|
|
139
147
|
// Track the cursor that is currently added to the document
|
|
140
148
|
// Add to document so that when dragging the cursor stays, even if mouse leaves the canvas
|
|
@@ -147,6 +155,10 @@ class Grid extends PureComponent {
|
|
|
147
155
|
// specify handler ordering, such that any extensions can insert handlers in between
|
|
148
156
|
this.keyHandlers = [new EditKeyHandler(400), new PasteKeyHandler(450), new SelectionKeyHandler(500), new TreeKeyHandler(900)];
|
|
149
157
|
this.mouseHandlers = [new GridRowSeparatorMouseHandler(100), new GridColumnSeparatorMouseHandler(200), new GridRowMoveMouseHandler(300), new GridColumnMoveMouseHandler(400), new EditMouseHandler(450), new GridVerticalScrollBarMouseHandler(500), new GridHorizontalScrollBarMouseHandler(600), new GridScrollBarCornerMouseHandler(700), new GridRowTreeMouseHandler(800), new GridTokenMouseHandler(875), new GridSelectionMouseHandler(900)];
|
|
158
|
+
|
|
159
|
+
// Selections are immutable, so a single instance can back both selection
|
|
160
|
+
// and lastSelection until the first commit produces a fresh committed value.
|
|
161
|
+
var emptySelection = props.createEmptySelection(this.getModel);
|
|
150
162
|
this.state = {
|
|
151
163
|
// Top/left visible cell in the grid. Note that it's visible row/column index, not the model index (ie. if columns are re-ordered)
|
|
152
164
|
top: 0,
|
|
@@ -173,18 +185,13 @@ class Grid extends PureComponent {
|
|
|
173
185
|
// Move operations the user has performed on this grids columns/rows
|
|
174
186
|
movedColumns,
|
|
175
187
|
movedRows,
|
|
176
|
-
// Cursor (highlighted cell) location and active selected range
|
|
177
|
-
cursorRow: null,
|
|
178
|
-
cursorColumn: null,
|
|
179
|
-
selectionStartRow: null,
|
|
180
|
-
selectionStartColumn: null,
|
|
181
|
-
selectionEndRow: null,
|
|
182
|
-
selectionEndColumn: null,
|
|
183
188
|
// Currently selected ranges and previously selected ranges
|
|
184
189
|
// Store the previously selected ranges to determine if the new selection should
|
|
185
190
|
// deselect again (if it's the same range)
|
|
186
|
-
|
|
187
|
-
|
|
191
|
+
selection: emptySelection,
|
|
192
|
+
lastSelection: emptySelection,
|
|
193
|
+
selectedRanges: [],
|
|
194
|
+
gestureMode: null,
|
|
188
195
|
// The mouse cursor style to use when hovering over the grid element
|
|
189
196
|
cursor: null,
|
|
190
197
|
// { column: number, row: number, selectionRange: [number, number], value: string | null, isQuickEdit?: boolean }
|
|
@@ -247,7 +254,8 @@ class Grid extends PureComponent {
|
|
|
247
254
|
onMovedRowsChanged = _this$props2.onMovedRowsChanged,
|
|
248
255
|
onMoveRowComplete = _this$props2.onMoveRowComplete,
|
|
249
256
|
renderer = _this$props2.renderer,
|
|
250
|
-
metricCalculator = _this$props2.metricCalculator
|
|
257
|
+
metricCalculator = _this$props2.metricCalculator,
|
|
258
|
+
createEmptySelection = _this$props2.createEmptySelection;
|
|
251
259
|
var prevIsStickyBottom = prevProps.isStickyBottom,
|
|
252
260
|
prevIsStickyRight = prevProps.isStickyRight,
|
|
253
261
|
prevPropMovedColumns = prevProps.movedColumns,
|
|
@@ -294,6 +302,12 @@ class Grid extends PureComponent {
|
|
|
294
302
|
if (metricCalculator !== prevProps.metricCalculator) {
|
|
295
303
|
this.metricCalculator = metricCalculator !== null && metricCalculator !== void 0 ? metricCalculator : new GridMetricCalculator();
|
|
296
304
|
}
|
|
305
|
+
if (prevProps.createEmptySelection !== createEmptySelection) {
|
|
306
|
+
var empty = createEmptySelection(this.getModel);
|
|
307
|
+
stateUpdates.selection = empty;
|
|
308
|
+
stateUpdates.lastSelection = empty;
|
|
309
|
+
stateUpdates.selectedRanges = EMPTY_ARRAY;
|
|
310
|
+
}
|
|
297
311
|
var updatedState = _objectSpread(_objectSpread({}, this.state), stateUpdates);
|
|
298
312
|
this.updateMetrics(updatedState);
|
|
299
313
|
this.requestUpdateCanvas();
|
|
@@ -425,12 +439,18 @@ class Grid extends PureComponent {
|
|
|
425
439
|
if (isExpandableGridModel(model) && model.isRowExpandable(modelRow)) {
|
|
426
440
|
model.setRowExpanded(modelRow, !model.isRowExpanded(modelRow), expandDescendants);
|
|
427
441
|
}
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
this.
|
|
431
|
-
|
|
432
|
-
this.setState({
|
|
433
|
-
|
|
442
|
+
// Programmatic install so we bypass gesture-driven deselect-on-reclick
|
|
443
|
+
// when the caller re-toggles the currently-selected row.
|
|
444
|
+
var theme = this.props.theme;
|
|
445
|
+
var range = theme.autoSelectRow === true ? new GridRange(null, row, null, row) : GridRange.makeCell(0, row);
|
|
446
|
+
this.setState(state => {
|
|
447
|
+
var newSel = state.selection.clear().withCommittedRanges([range]).withCursor(row, 0).withSelectionEnd(row, 0);
|
|
448
|
+
return {
|
|
449
|
+
selection: newSel,
|
|
450
|
+
lastSelection: newSel,
|
|
451
|
+
selectedRanges: selectionToRanges(newSel),
|
|
452
|
+
isStuckToBottom: false
|
|
453
|
+
};
|
|
434
454
|
});
|
|
435
455
|
}
|
|
436
456
|
getStickyScrollPosition(isStickyBottom, isStickyRight) {
|
|
@@ -471,32 +491,36 @@ class Grid extends PureComponent {
|
|
|
471
491
|
var model = this.props.model;
|
|
472
492
|
var columnCount = model.columnCount,
|
|
473
493
|
rowCount = model.rowCount;
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
494
|
+
this.setState(state => {
|
|
495
|
+
var _state$selection = state.selection,
|
|
496
|
+
cursorRow = _state$selection.cursorRow,
|
|
497
|
+
cursorColumn = _state$selection.cursorColumn;
|
|
498
|
+
var selectionEndRow = null;
|
|
499
|
+
var selectionEndColumn = null;
|
|
500
|
+
var anchorRow = null;
|
|
501
|
+
var anchorColumn = null;
|
|
502
|
+
if (gridRanges.length > 0) {
|
|
503
|
+
var range = GridRange.boundedRange(gridRanges[0], columnCount, rowCount);
|
|
504
|
+
if (!range.containsCell(cursorColumn, cursorRow)) {
|
|
505
|
+
var _range$startCell = range.startCell();
|
|
506
|
+
cursorRow = _range$startCell.row;
|
|
507
|
+
cursorColumn = _range$startCell.column;
|
|
508
|
+
}
|
|
509
|
+
anchorColumn = range.startColumn;
|
|
510
|
+
anchorRow = range.startRow;
|
|
511
|
+
selectionEndColumn = range.endColumn;
|
|
512
|
+
selectionEndRow = range.endRow;
|
|
490
513
|
}
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
514
|
+
var selection = state.selection.withCommittedRanges(gridRanges, {
|
|
515
|
+
row: anchorRow,
|
|
516
|
+
column: anchorColumn
|
|
517
|
+
}).withCursor(cursorRow, cursorColumn).withSelectionEnd(selectionEndRow, selectionEndColumn);
|
|
518
|
+
return {
|
|
519
|
+
selection,
|
|
520
|
+
selectedRanges: selectionToRanges(selection),
|
|
521
|
+
lastSelection: state.selection
|
|
522
|
+
};
|
|
523
|
+
});
|
|
500
524
|
}
|
|
501
525
|
initContext() {
|
|
502
526
|
var canvas = this.canvas;
|
|
@@ -568,9 +592,9 @@ class Grid extends PureComponent {
|
|
|
568
592
|
}
|
|
569
593
|
updateScrollBounds() {
|
|
570
594
|
if (!this.metrics) throw new Error('metrics not set');
|
|
571
|
-
var _this$
|
|
572
|
-
left = _this$
|
|
573
|
-
top = _this$
|
|
595
|
+
var _this$state2 = this.state,
|
|
596
|
+
left = _this$state2.left,
|
|
597
|
+
top = _this$state2.top;
|
|
574
598
|
var _this$metrics4 = this.metrics,
|
|
575
599
|
lastLeft = _this$metrics4.lastLeft,
|
|
576
600
|
lastTop = _this$metrics4.lastTop;
|
|
@@ -634,11 +658,13 @@ class Grid extends PureComponent {
|
|
|
634
658
|
* @param prevState The previous grid state
|
|
635
659
|
*/
|
|
636
660
|
checkSelectionChange(prevState) {
|
|
637
|
-
var
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
661
|
+
var selection = this.state.selection;
|
|
662
|
+
if (selection !== prevState.selection) {
|
|
663
|
+
var _this$props4 = this.props,
|
|
664
|
+
onSelectionChanged = _this$props4.onSelectionChanged,
|
|
665
|
+
onSelectionChange = _this$props4.onSelectionChange;
|
|
666
|
+
onSelectionChanged(selectionToRanges(selection));
|
|
667
|
+
onSelectionChange(selection);
|
|
642
668
|
}
|
|
643
669
|
}
|
|
644
670
|
|
|
@@ -647,20 +673,19 @@ class Grid extends PureComponent {
|
|
|
647
673
|
* @returns True if the selection is valid, false if the selection was invalid and has been reset
|
|
648
674
|
*/
|
|
649
675
|
validateSelection() {
|
|
650
|
-
var
|
|
651
|
-
var
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
}
|
|
676
|
+
var createEmptySelection = this.props.createEmptySelection;
|
|
677
|
+
var selection = this.state.selection;
|
|
678
|
+
|
|
679
|
+
// Validate that a RangedSelection is within the bounds of the grid model
|
|
680
|
+
if (isRangedSelection(selection) && !selection.isInBounds()) {
|
|
681
|
+
// Just clear the selection rather than trying to trim it.
|
|
682
|
+
var empty = createEmptySelection(this.getModel);
|
|
683
|
+
this.setState({
|
|
684
|
+
selection: empty,
|
|
685
|
+
lastSelection: empty,
|
|
686
|
+
selectedRanges: EMPTY_ARRAY
|
|
687
|
+
});
|
|
688
|
+
return false;
|
|
664
689
|
}
|
|
665
690
|
return true;
|
|
666
691
|
}
|
|
@@ -669,186 +694,304 @@ class Grid extends PureComponent {
|
|
|
669
694
|
* Clears all selected ranges
|
|
670
695
|
*/
|
|
671
696
|
clearSelectedRanges() {
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
});
|
|
697
|
+
this.setState(state => ({
|
|
698
|
+
selection: state.selection.clear(),
|
|
699
|
+
lastSelection: state.selection,
|
|
700
|
+
selectedRanges: EMPTY_ARRAY
|
|
701
|
+
}));
|
|
677
702
|
}
|
|
678
703
|
|
|
679
704
|
/** Clears all but the last selected range */
|
|
680
705
|
trimSelectedRanges() {
|
|
681
|
-
var
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
}
|
|
706
|
+
var selection = this.state.selection;
|
|
707
|
+
var trimmed = selection.trimmed();
|
|
708
|
+
this.setState({
|
|
709
|
+
selection: trimmed,
|
|
710
|
+
selectedRanges: selectionToRanges(trimmed)
|
|
711
|
+
});
|
|
687
712
|
}
|
|
688
713
|
|
|
689
|
-
/**
|
|
714
|
+
/** Sets the selection directly, bypassing mouse/keyboard gesture state. */
|
|
715
|
+
setSelection(selection) {
|
|
716
|
+
// Sync lastSelection so the next gesture compares against the just-installed
|
|
717
|
+
// committed state; otherwise a pending → resolved swap would leave the next
|
|
718
|
+
// ctrl+click's toggle referencing the pending selection's empty keys.
|
|
719
|
+
this.setState({
|
|
720
|
+
selection,
|
|
721
|
+
lastSelection: selection,
|
|
722
|
+
selectedRanges: selectionToRanges(selection)
|
|
723
|
+
});
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
/** Gets the current selection */
|
|
727
|
+
getSelection() {
|
|
728
|
+
var selection = this.state.selection;
|
|
729
|
+
return selection;
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
/** @deprecated Use getSelection() instead */
|
|
690
733
|
getSelectedRanges() {
|
|
691
|
-
var
|
|
692
|
-
|
|
734
|
+
var selection = this.state.selection;
|
|
735
|
+
// toRanges() is RangedSelection-only; returns [] for keyed selections
|
|
736
|
+
return selectionToRanges(selection);
|
|
693
737
|
}
|
|
694
738
|
|
|
695
739
|
/**
|
|
696
|
-
*
|
|
697
|
-
* @
|
|
698
|
-
* @param row Row where the selection is beginning
|
|
740
|
+
* Queries the current grid model.
|
|
741
|
+
* @returns The current GridModel instance.
|
|
699
742
|
*/
|
|
700
|
-
|
|
701
|
-
this.
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
743
|
+
getModel() {
|
|
744
|
+
var model = this.props.model;
|
|
745
|
+
return model;
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
/**
|
|
749
|
+
* Extend + commit a gesture at `cursor` and return the resulting partial
|
|
750
|
+
* state. Shared by mouse click-and-release and keyboard commits.
|
|
751
|
+
*
|
|
752
|
+
* @param selection Pre-gesture selection to fold against. Cursor landing
|
|
753
|
+
* reads its extended (pre-commit) form so `KeyedSelection`'s overlay is
|
|
754
|
+
* still available.
|
|
755
|
+
* @param cursor Gesture target cell.
|
|
756
|
+
* @param mode Modifier-derived gesture mode.
|
|
757
|
+
* @param opts.moveCursor Snap the cursor to `cursor` (default true).
|
|
758
|
+
* Pass false for keyboard extend / maximize / add so the cursor stays put.
|
|
759
|
+
* @param opts.allowDeselect Whether committing on top of the same
|
|
760
|
+
* single-row / single-cell selection should deselect (mouse affordance,
|
|
761
|
+
* default true). Keyboard callers pass false so arrowing onto an
|
|
762
|
+
* already-selected cell just moves the cursor.
|
|
763
|
+
* @param opts.settle Whether the commit should finalize (deselect check,
|
|
764
|
+
* hole-punch, consolidation). Mouse-down passes false so a drag can grow
|
|
765
|
+
* the last range before mouse-up finalizes.
|
|
766
|
+
*/
|
|
767
|
+
applyGestureAt(selection, cursor, mode) {
|
|
768
|
+
var _theme$autoSelectRow, _theme$autoSelectColu;
|
|
769
|
+
var opts = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
|
|
770
|
+
var theme = this.props.theme;
|
|
771
|
+
var _opts$moveCursor = opts.moveCursor,
|
|
772
|
+
moveCursor = _opts$moveCursor === void 0 ? true : _opts$moveCursor,
|
|
773
|
+
_opts$allowDeselect = opts.allowDeselect,
|
|
774
|
+
allowDeselect = _opts$allowDeselect === void 0 ? true : _opts$allowDeselect,
|
|
775
|
+
_opts$settle = opts.settle,
|
|
776
|
+
settle = _opts$settle === void 0 ? true : _opts$settle;
|
|
777
|
+
var lastSelection = selection;
|
|
778
|
+
var extendOpts = {
|
|
779
|
+
mode,
|
|
780
|
+
autoSelectRow: (_theme$autoSelectRow = theme.autoSelectRow) !== null && _theme$autoSelectRow !== void 0 ? _theme$autoSelectRow : false,
|
|
781
|
+
autoSelectColumn: (_theme$autoSelectColu = theme.autoSelectColumn) !== null && _theme$autoSelectColu !== void 0 ? _theme$autoSelectColu : false
|
|
782
|
+
};
|
|
783
|
+
var extended = selection.withGestureExtend(cursor, extendOpts);
|
|
784
|
+
// `replace` snaps the cursor to the gesture; extend/maximize/add keep it put.
|
|
785
|
+
var cursorTarget = moveCursor ? cursor : {
|
|
786
|
+
row: selection.cursorRow,
|
|
787
|
+
column: selection.cursorColumn
|
|
788
|
+
};
|
|
789
|
+
var settled = extended.commitGesture(lastSelection, {
|
|
790
|
+
autoSelectRow: extendOpts.autoSelectRow,
|
|
791
|
+
cursor: cursorTarget,
|
|
792
|
+
allowDeselect,
|
|
793
|
+
settle
|
|
794
|
+
}).withSelectionEnd(cursor.row, cursor.column);
|
|
795
|
+
return {
|
|
796
|
+
selection: settled,
|
|
797
|
+
lastSelection,
|
|
798
|
+
selectedRanges: selectionToRanges(settled)
|
|
799
|
+
};
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
/**
|
|
803
|
+
* Start a mouse-driven selection gesture at `cursor` with the given
|
|
804
|
+
* modifier-derived `mode`. Extends the selection per `mode` semantics
|
|
805
|
+
* and commits immediately so a click without drag settles the state.
|
|
806
|
+
*/
|
|
807
|
+
handleMouseSelectStart(cursor, mode) {
|
|
808
|
+
this.setState(state => _objectSpread(_objectSpread({}, this.applyGestureAt(state.selection, cursor, mode, {
|
|
809
|
+
settle: false
|
|
810
|
+
})), {}, {
|
|
811
|
+
gestureMode: mode
|
|
812
|
+
}));
|
|
709
813
|
}
|
|
710
814
|
|
|
711
815
|
/**
|
|
712
|
-
*
|
|
713
|
-
*
|
|
714
|
-
* @param row The row index to move the cursor to
|
|
715
|
-
* @param extendSelection Whether to extend the current selection (eg. holding Shift)
|
|
716
|
-
* @param maximizePreviousRange When true, maximize/add to the previous range only, ignoring where the selection was started.
|
|
816
|
+
* Extend the current mouse selection gesture to `cursor`. Transient
|
|
817
|
+
* overlay only; the settled commit runs on `handleMouseSelectEnd`.
|
|
717
818
|
*/
|
|
718
|
-
|
|
719
|
-
var
|
|
720
|
-
var maximizePreviousRange = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
|
|
819
|
+
handleMouseSelectDrag(cursor) {
|
|
820
|
+
var theme = this.props.theme;
|
|
721
821
|
this.setState(state => {
|
|
722
|
-
var
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
if (maximizePreviousRange) {
|
|
735
|
-
var _lastSelectedRange$st, _lastSelectedRange$st2, _lastSelectedRange$en, _lastSelectedRange$en2;
|
|
736
|
-
left = autoSelectRow !== undefined && autoSelectRow ? null : Math.min(column !== null && column !== void 0 ? column : 0, (_lastSelectedRange$st = lastSelectedRange.startColumn) !== null && _lastSelectedRange$st !== void 0 ? _lastSelectedRange$st : 0);
|
|
737
|
-
top = autoSelectColumn !== undefined && autoSelectColumn ? null : Math.min(row !== null && row !== void 0 ? row : 0, (_lastSelectedRange$st2 = lastSelectedRange.startRow) !== null && _lastSelectedRange$st2 !== void 0 ? _lastSelectedRange$st2 : 0);
|
|
738
|
-
right = autoSelectRow !== undefined && autoSelectRow ? null : Math.max(column !== null && column !== void 0 ? column : 0, (_lastSelectedRange$en = lastSelectedRange.endColumn) !== null && _lastSelectedRange$en !== void 0 ? _lastSelectedRange$en : 0);
|
|
739
|
-
bottom = autoSelectColumn !== undefined && autoSelectColumn ? null : Math.max(row !== null && row !== void 0 ? row : 0, (_lastSelectedRange$en2 = lastSelectedRange.endRow) !== null && _lastSelectedRange$en2 !== void 0 ? _lastSelectedRange$en2 : 0);
|
|
740
|
-
} else {
|
|
741
|
-
left = lastSelectedRange.startColumn;
|
|
742
|
-
top = lastSelectedRange.startRow;
|
|
743
|
-
if (selectionStartColumn != null || selectionStartRow != null) {
|
|
744
|
-
if (autoSelectRow === undefined || !autoSelectRow) {
|
|
745
|
-
left = selectionStartColumn;
|
|
746
|
-
}
|
|
747
|
-
if (autoSelectColumn === undefined || !autoSelectColumn) {
|
|
748
|
-
top = selectionStartRow;
|
|
749
|
-
}
|
|
750
|
-
}
|
|
751
|
-
right = autoSelectRow !== undefined && autoSelectRow ? null : column;
|
|
752
|
-
bottom = autoSelectColumn !== undefined && autoSelectColumn ? null : row;
|
|
753
|
-
}
|
|
754
|
-
var selectedRange = GridRange.makeNormalized(left, top, right, bottom);
|
|
755
|
-
if (lastSelectedRange.equals(selectedRange)) {
|
|
756
|
-
return null;
|
|
757
|
-
}
|
|
758
|
-
var _newRanges = [...selectedRanges];
|
|
759
|
-
_newRanges[_newRanges.length - 1] = selectedRange;
|
|
760
|
-
return {
|
|
761
|
-
selectedRanges: _newRanges,
|
|
762
|
-
selectionEndColumn: column,
|
|
763
|
-
selectionEndRow: row
|
|
764
|
-
};
|
|
765
|
-
}
|
|
766
|
-
var newRanges = [...selectedRanges];
|
|
767
|
-
var selectedColumn = autoSelectRow !== undefined && autoSelectRow ? null : column;
|
|
768
|
-
var selectedRow = autoSelectColumn !== undefined && autoSelectColumn ? null : row;
|
|
769
|
-
newRanges.push(GridRange.makeNormalized(selectedColumn, selectedRow, selectedColumn, selectedRow));
|
|
822
|
+
var _theme$autoSelectRow2, _theme$autoSelectColu2;
|
|
823
|
+
// Additive gestures (ctrl+click, ctrl+shift+click) grow the last range
|
|
824
|
+
// via `maximize` so the prior committed selection survives the drag.
|
|
825
|
+
// Replace and shift-extend continue as `extend`, trimming to the last
|
|
826
|
+
// range.
|
|
827
|
+
var isAdditive = state.gestureMode === 'add' || state.gestureMode === 'maximize';
|
|
828
|
+
var opts = {
|
|
829
|
+
mode: isAdditive ? 'maximize' : 'extend',
|
|
830
|
+
autoSelectRow: (_theme$autoSelectRow2 = theme.autoSelectRow) !== null && _theme$autoSelectRow2 !== void 0 ? _theme$autoSelectRow2 : false,
|
|
831
|
+
autoSelectColumn: (_theme$autoSelectColu2 = theme.autoSelectColumn) !== null && _theme$autoSelectColu2 !== void 0 ? _theme$autoSelectColu2 : false
|
|
832
|
+
};
|
|
833
|
+
var extended = state.selection.withGestureExtend(cursor, opts).withSelectionEnd(cursor.row, cursor.column);
|
|
770
834
|
return {
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
selectionEndRow: row
|
|
835
|
+
selection: extended,
|
|
836
|
+
selectedRanges: selectionToRanges(extended)
|
|
774
837
|
};
|
|
775
838
|
});
|
|
839
|
+
this.moveViewToCell(cursor.column, cursor.row);
|
|
776
840
|
}
|
|
777
841
|
|
|
778
|
-
/**
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
* is then it blows those ranges apart.
|
|
782
|
-
* Then it consolidates all the selected ranges, reducing them.
|
|
783
|
-
*/
|
|
784
|
-
commitSelection() {
|
|
842
|
+
/** Settle the current mouse selection gesture. Called on mouse-up. */
|
|
843
|
+
handleMouseSelectEnd() {
|
|
844
|
+
var theme = this.props.theme;
|
|
785
845
|
this.setState(state => {
|
|
786
|
-
var
|
|
787
|
-
var
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
return {
|
|
796
|
-
selectedRanges: EMPTY_ARRAY,
|
|
797
|
-
lastSelectedRanges: EMPTY_ARRAY,
|
|
798
|
-
cursorColumn: null,
|
|
799
|
-
cursorRow: null
|
|
800
|
-
};
|
|
801
|
-
}
|
|
802
|
-
var newSelectedRanges = selectedRanges.slice();
|
|
803
|
-
if (newSelectedRanges.length > 1) {
|
|
804
|
-
// Check if the latest selection is entirely within a previously selected range
|
|
805
|
-
// If that's the case, then deselect that section instead
|
|
806
|
-
var lastRange = newSelectedRanges[newSelectedRanges.length - 1];
|
|
807
|
-
for (var i = 0; i < newSelectedRanges.length - 1; i += 1) {
|
|
808
|
-
var selectedRange = newSelectedRanges[i];
|
|
809
|
-
if (selectedRange.contains(lastRange)) {
|
|
810
|
-
// We found a match, now remove the two matching ranges, and add back
|
|
811
|
-
// the remainder of the two
|
|
812
|
-
var remainder = selectedRange.subtract(lastRange);
|
|
813
|
-
newSelectedRanges.pop();
|
|
814
|
-
newSelectedRanges.splice(i, 1);
|
|
815
|
-
newSelectedRanges = newSelectedRanges.concat(remainder);
|
|
816
|
-
break;
|
|
817
|
-
}
|
|
818
|
-
}
|
|
819
|
-
newSelectedRanges = GridRange.consolidate(newSelectedRanges);
|
|
820
|
-
}
|
|
821
|
-
var newCursorColumn = cursorColumn;
|
|
822
|
-
var newCursorRow = cursorRow;
|
|
823
|
-
if (!GridRange.containsCell(newSelectedRanges, cursorColumn, cursorRow)) {
|
|
824
|
-
var model = this.props.model;
|
|
825
|
-
var columnCount = model.columnCount,
|
|
826
|
-
rowCount = model.rowCount;
|
|
827
|
-
var nextCursor = GridRange.nextCell(GridRange.boundedRanges(selectedRanges, columnCount, rowCount));
|
|
828
|
-
if (nextCursor != null) {
|
|
829
|
-
newCursorColumn = nextCursor.column;
|
|
830
|
-
newCursorRow = nextCursor.row;
|
|
831
|
-
} else {
|
|
832
|
-
newCursorColumn = null;
|
|
833
|
-
newCursorRow = null;
|
|
846
|
+
var _theme$autoSelectRow3;
|
|
847
|
+
var selection = state.selection,
|
|
848
|
+
lastSelection = state.lastSelection;
|
|
849
|
+
var settled = selection.commitGesture(lastSelection, {
|
|
850
|
+
autoSelectRow: (_theme$autoSelectRow3 = theme.autoSelectRow) !== null && _theme$autoSelectRow3 !== void 0 ? _theme$autoSelectRow3 : false,
|
|
851
|
+
// Mouse-up commit preserves the current cursor position.
|
|
852
|
+
cursor: {
|
|
853
|
+
row: selection.cursorRow,
|
|
854
|
+
column: selection.cursorColumn
|
|
834
855
|
}
|
|
835
|
-
}
|
|
836
|
-
if (
|
|
837
|
-
newCursorColumn = null;
|
|
838
|
-
newCursorRow = null;
|
|
839
|
-
}
|
|
840
|
-
var selectionChanged = newSelectedRanges.length !== selectedRanges.length || newSelectedRanges.some((range, index) => !range.equals(selectedRanges[index]));
|
|
856
|
+
});
|
|
857
|
+
if (settled === selection) return null;
|
|
841
858
|
return {
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
859
|
+
selection: settled,
|
|
860
|
+
lastSelection: settled,
|
|
861
|
+
selectedRanges: selectionToRanges(settled)
|
|
862
|
+
};
|
|
863
|
+
});
|
|
864
|
+
// Always clear the in-flight gesture mode on mouse-up. Kept as a
|
|
865
|
+
// separate setState so the settled-update above stays in a single Pick
|
|
866
|
+
// shape that React's typing narrows cleanly.
|
|
867
|
+
this.setState(_ref5 => {
|
|
868
|
+
var gestureMode = _ref5.gestureMode;
|
|
869
|
+
return gestureMode == null ? null : {
|
|
870
|
+
gestureMode: null
|
|
849
871
|
};
|
|
850
872
|
});
|
|
851
873
|
}
|
|
874
|
+
|
|
875
|
+
/**
|
|
876
|
+
* Apply a keyboard-driven selection gesture at `cursor` with `mode`, then
|
|
877
|
+
* optionally scroll the viewport to bring the cursor into view. Shared
|
|
878
|
+
* entry point for arrow keys, Home/End, and page-key movements.
|
|
879
|
+
*
|
|
880
|
+
* Only `replace` moves the cursor to `cursor`; extend/maximize/add
|
|
881
|
+
* preserve the existing cursor and update `selectionEnd` only. This
|
|
882
|
+
* matches long-standing Shift+Arrow semantics where the cursor stays put
|
|
883
|
+
* as the selection grows.
|
|
884
|
+
*/
|
|
885
|
+
handleKeySelectAt(cursor, mode) {
|
|
886
|
+
var opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
887
|
+
var _opts$keepCursorInVie = opts.keepCursorInView,
|
|
888
|
+
keepCursorInView = _opts$keepCursorInVie === void 0 ? true : _opts$keepCursorInVie;
|
|
889
|
+
var moveCursor = mode === 'replace';
|
|
890
|
+
this.setState(state => this.applyGestureAt(state.selection, cursor, mode, {
|
|
891
|
+
moveCursor,
|
|
892
|
+
allowDeselect: false
|
|
893
|
+
}));
|
|
894
|
+
if (keepCursorInView && cursor.column != null && cursor.row != null) {
|
|
895
|
+
this.moveViewToCell(cursor.column, cursor.row);
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
/**
|
|
900
|
+
* Listen for the grid finishing a draw of its canvas. Called immediately with
|
|
901
|
+
* the most recent draw if the grid has already drawn.
|
|
902
|
+
* @param listener Called with the state that was drawn
|
|
903
|
+
* @returns A function to stop listening
|
|
904
|
+
*/
|
|
905
|
+
registerDrawListener(listener) {
|
|
906
|
+
this.drawListeners.add(listener);
|
|
907
|
+
if (this.renderState !== null) {
|
|
908
|
+
listener(this.renderState);
|
|
909
|
+
}
|
|
910
|
+
return () => {
|
|
911
|
+
this.drawListeners.delete(listener);
|
|
912
|
+
};
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
/**
|
|
916
|
+
* Advance the cursor in `direction` through the current selection. Used
|
|
917
|
+
* by Tab/Enter — cycles within the selected ranges when there are
|
|
918
|
+
* multiple, wraps at grid edges when there is only a single cell.
|
|
919
|
+
* When the resulting cursor falls outside the current selection (e.g.
|
|
920
|
+
* from an initial empty state), installs a fresh single-cell selection.
|
|
921
|
+
*/
|
|
922
|
+
handleKeyAdvanceCursor(direction) {
|
|
923
|
+
var selection = this.state.selection;
|
|
924
|
+
var next = selection.getNextCursorInDirection({
|
|
925
|
+
column: selection.cursorColumn,
|
|
926
|
+
row: selection.cursorRow
|
|
927
|
+
}, direction);
|
|
928
|
+
if (next == null) return;
|
|
929
|
+
var column = next.column,
|
|
930
|
+
row = next.row;
|
|
931
|
+
if (column == null || row == null) return;
|
|
932
|
+
if (selection.isCellSelected(column, row)) {
|
|
933
|
+
this.setState(state => ({
|
|
934
|
+
selection: state.selection.withCursor(row, column)
|
|
935
|
+
}));
|
|
936
|
+
} else {
|
|
937
|
+
this.setState(state => this.applyGestureAt(state.selection, {
|
|
938
|
+
column,
|
|
939
|
+
row
|
|
940
|
+
}, 'replace', {
|
|
941
|
+
allowDeselect: false
|
|
942
|
+
}));
|
|
943
|
+
}
|
|
944
|
+
this.moveViewToCell(column, row);
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
/**
|
|
948
|
+
* Page-move gesture. `direction` is +1 (page-down) or -1 (page-up). Reads
|
|
949
|
+
* viewport metrics to compute the target cell, applies the gesture without
|
|
950
|
+
* auto-scrolling, then pins the viewport top so the cursor lands where it
|
|
951
|
+
* was on screen before.
|
|
952
|
+
*/
|
|
953
|
+
handleKeyPage(mode, direction) {
|
|
954
|
+
var selection = this.state.selection;
|
|
955
|
+
var cursorColumn = selection.cursorColumn,
|
|
956
|
+
selectionEndRow = selection.selectionEndRow;
|
|
957
|
+
if (selectionEndRow == null) return;
|
|
958
|
+
var row = selectionEndRow;
|
|
959
|
+
var metricState = this.getMetricState();
|
|
960
|
+
var _this$metricCalculato = this.metricCalculator.getMetrics(metricState),
|
|
961
|
+
bottomVisible = _this$metricCalculato.bottomVisible,
|
|
962
|
+
topVisible = _this$metricCalculato.topVisible,
|
|
963
|
+
hasHorizontalBar = _this$metricCalculato.hasHorizontalBar,
|
|
964
|
+
rowCount = _this$metricCalculato.rowCount,
|
|
965
|
+
lastTop = _this$metricCalculato.lastTop;
|
|
966
|
+
var pageSize = bottomVisible - topVisible + (hasHorizontalBar ? 0 : 1);
|
|
967
|
+
var target = clamp(row + direction * pageSize, 0, rowCount - 1);
|
|
968
|
+
var viewportPosition = clamp(target - (row - topVisible), 0, lastTop);
|
|
969
|
+
this.handleKeySelectAt({
|
|
970
|
+
column: cursorColumn,
|
|
971
|
+
row: target
|
|
972
|
+
}, mode, {
|
|
973
|
+
keepCursorInView: false
|
|
974
|
+
});
|
|
975
|
+
this.setViewState({
|
|
976
|
+
top: viewportPosition
|
|
977
|
+
});
|
|
978
|
+
}
|
|
979
|
+
handleKeyPageUp(mode) {
|
|
980
|
+
this.handleKeyPage(mode, -1);
|
|
981
|
+
}
|
|
982
|
+
handleKeyPageDown(mode) {
|
|
983
|
+
this.handleKeyPage(mode, 1);
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
/**
|
|
987
|
+
* Move the cursor to a cell without touching the selection.
|
|
988
|
+
*/
|
|
989
|
+
handleKeyMoveCursor(column, row) {
|
|
990
|
+
this.setState(state => ({
|
|
991
|
+
selection: state.selection.withCursor(row, column).withSelectionEnd(row, column)
|
|
992
|
+
}));
|
|
993
|
+
this.moveViewToCell(column, row);
|
|
994
|
+
}
|
|
852
995
|
setFocusRow(focusedRow) {
|
|
853
996
|
var _userRowHeights$get;
|
|
854
997
|
if (!this.metrics || !this.prevMetrics) {
|
|
@@ -864,123 +1007,31 @@ class Grid extends PureComponent {
|
|
|
864
1007
|
var halfViewportHeight = Math.round(tableHeight / 2) + ((_userRowHeights$get = userRowHeights.get(focusedRow)) !== null && _userRowHeights$get !== void 0 ? _userRowHeights$get : rowHeight);
|
|
865
1008
|
var metricState = this.getMetricState();
|
|
866
1009
|
var newTop = this.metricCalculator.getLastTop(metricState, focusedRow + 1, halfViewportHeight);
|
|
867
|
-
this.setState({
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
1010
|
+
this.setState(state => {
|
|
1011
|
+
var cursorColumn = state.selection.cursorColumn;
|
|
1012
|
+
var newSel = state.selection.withCommittedRanges([new GridRange(null, focusedRow, null, focusedRow)]).withCursor(focusedRow, cursorColumn).withSelectionEnd(focusedRow, cursorColumn);
|
|
1013
|
+
return {
|
|
1014
|
+
top: Math.min(lastTop, newTop),
|
|
1015
|
+
selection: newSel,
|
|
1016
|
+
lastSelection: newSel,
|
|
1017
|
+
selectedRanges: selectionToRanges(newSel),
|
|
1018
|
+
isStuckToBottom: false
|
|
1019
|
+
};
|
|
871
1020
|
});
|
|
872
|
-
var cursorColumn = this.state.cursorColumn;
|
|
873
|
-
this.moveCursorToPosition(cursorColumn, focusedRow, false, false);
|
|
874
1021
|
}
|
|
875
1022
|
|
|
876
1023
|
/**
|
|
877
1024
|
* Set the selection to the entire grid
|
|
878
1025
|
*/
|
|
879
1026
|
selectAll() {
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
var right = autoSelectRow !== undefined && autoSelectRow ? null : model.columnCount - 1;
|
|
889
|
-
this.setSelectedRanges([new GridRange(left, top, right, bottom)]);
|
|
890
|
-
}
|
|
891
|
-
|
|
892
|
-
/**
|
|
893
|
-
* Move the cursor in relation to the current cursor position
|
|
894
|
-
* @param deltaColumn Number of columns to move the cursor
|
|
895
|
-
* @param deltaRow Number of rows to move the cursor
|
|
896
|
-
* @param extendSelection True if the current selection should be extended, false to start a new selection
|
|
897
|
-
*/
|
|
898
|
-
moveCursor(deltaColumn, deltaRow, extendSelection) {
|
|
899
|
-
var _this$state4 = this.state,
|
|
900
|
-
cursorRow = _this$state4.cursorRow,
|
|
901
|
-
cursorColumn = _this$state4.cursorColumn,
|
|
902
|
-
selectionEndColumn = _this$state4.selectionEndColumn,
|
|
903
|
-
selectionEndRow = _this$state4.selectionEndRow;
|
|
904
|
-
var column = extendSelection ? selectionEndColumn : cursorColumn;
|
|
905
|
-
var row = extendSelection ? selectionEndRow : cursorRow;
|
|
906
|
-
if (row === null || column === null) {
|
|
907
|
-
var _this$state5 = this.state,
|
|
908
|
-
left = _this$state5.left,
|
|
909
|
-
top = _this$state5.top;
|
|
910
|
-
this.moveCursorToPosition(left, top, extendSelection);
|
|
911
|
-
} else {
|
|
912
|
-
var model = this.props.model;
|
|
913
|
-
var columnCount = model.columnCount,
|
|
914
|
-
rowCount = model.rowCount;
|
|
915
|
-
var _left = clamp(column + deltaColumn, 0, columnCount - 1);
|
|
916
|
-
var _top = clamp(row + deltaRow, 0, rowCount - 1);
|
|
917
|
-
this.moveCursorToPosition(_left, _top, extendSelection);
|
|
918
|
-
}
|
|
919
|
-
}
|
|
920
|
-
|
|
921
|
-
/**
|
|
922
|
-
* Move the cursor in the provided selection direction
|
|
923
|
-
* @param direction The direction to move the cursor in
|
|
924
|
-
*/
|
|
925
|
-
moveCursorInDirection() {
|
|
926
|
-
var direction = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : GridRange.SELECTION_DIRECTION.DOWN;
|
|
927
|
-
var model = this.props.model;
|
|
928
|
-
var columnCount = model.columnCount,
|
|
929
|
-
rowCount = model.rowCount;
|
|
930
|
-
var _this$state6 = this.state,
|
|
931
|
-
cursorRow = _this$state6.cursorRow,
|
|
932
|
-
cursorColumn = _this$state6.cursorColumn,
|
|
933
|
-
selectedRanges = _this$state6.selectedRanges;
|
|
934
|
-
var ranges = selectedRanges.length > 0 ? selectedRanges : [GridRange.makeCell(cursorColumn, cursorRow)];
|
|
935
|
-
var nextCursor = null;
|
|
936
|
-
if (ranges.length === 1 && GridRange.cellCount(ranges) === 1) {
|
|
937
|
-
var _gridRange$nextCell;
|
|
938
|
-
// If we only have one cell selected, we want to update the cursor and we want to update the selected cells
|
|
939
|
-
var gridRange = new GridRange(0, 0, columnCount - 1, rowCount - 1);
|
|
940
|
-
nextCursor = (_gridRange$nextCell = gridRange.nextCell(cursorColumn, cursorRow, direction)) !== null && _gridRange$nextCell !== void 0 ? _gridRange$nextCell : gridRange.startCell(direction);
|
|
941
|
-
} else {
|
|
942
|
-
nextCursor = GridRange.nextCell(GridRange.boundedRanges(ranges, columnCount, rowCount), cursorColumn, cursorRow, direction);
|
|
943
|
-
}
|
|
944
|
-
if (nextCursor != null) {
|
|
945
|
-
var _nextCursor = nextCursor,
|
|
946
|
-
column = _nextCursor.column,
|
|
947
|
-
row = _nextCursor.row;
|
|
948
|
-
this.setState({
|
|
949
|
-
cursorColumn: column,
|
|
950
|
-
cursorRow: row
|
|
951
|
-
});
|
|
952
|
-
if (!GridRange.containsCell(selectedRanges, column, row)) {
|
|
953
|
-
this.setState({
|
|
954
|
-
selectedRanges: [GridRange.makeCell(column, row)],
|
|
955
|
-
selectionStartColumn: column,
|
|
956
|
-
selectionStartRow: row,
|
|
957
|
-
selectionEndColumn: column,
|
|
958
|
-
selectionEndRow: row
|
|
959
|
-
});
|
|
960
|
-
}
|
|
961
|
-
this.moveViewToCell(nextCursor.column, nextCursor.row);
|
|
962
|
-
}
|
|
963
|
-
}
|
|
964
|
-
|
|
965
|
-
/**
|
|
966
|
-
* Move a cursor to the specified position in the grid.
|
|
967
|
-
* @param column The column index to move the cursor to
|
|
968
|
-
* @param row The row index to move the cursor to
|
|
969
|
-
* @param extendSelection Whether to extend the current selection (eg. holding Shift)
|
|
970
|
-
* @param keepCursorInView Whether to move the viewport so that the cursor is in view
|
|
971
|
-
* @param maximizePreviousRange With this and `extendSelection` true, it will maximize/add to the previous range only, ignoring where the selection was started
|
|
972
|
-
*/
|
|
973
|
-
moveCursorToPosition(column, row) {
|
|
974
|
-
var extendSelection = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
|
975
|
-
var keepCursorInView = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;
|
|
976
|
-
var maximizePreviousRange = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
|
|
977
|
-
if (!extendSelection) {
|
|
978
|
-
this.beginSelection(column, row);
|
|
979
|
-
}
|
|
980
|
-
this.moveSelection(column, row, extendSelection, maximizePreviousRange);
|
|
981
|
-
if (keepCursorInView) {
|
|
982
|
-
this.moveViewToCell(column, row);
|
|
983
|
-
}
|
|
1027
|
+
this.setState(state => {
|
|
1028
|
+
var newSelection = state.selection.selectAll();
|
|
1029
|
+
return {
|
|
1030
|
+
selection: newSelection,
|
|
1031
|
+
lastSelection: newSelection,
|
|
1032
|
+
selectedRanges: selectionToRanges(newSelection)
|
|
1033
|
+
};
|
|
1034
|
+
});
|
|
984
1035
|
}
|
|
985
1036
|
|
|
986
1037
|
/**
|
|
@@ -998,11 +1049,11 @@ class Grid extends PureComponent {
|
|
|
998
1049
|
topVisible = _this$metrics7.topVisible,
|
|
999
1050
|
leftVisible = _this$metrics7.leftVisible;
|
|
1000
1051
|
var metricState = this.getMetricState(this.state);
|
|
1001
|
-
var _this$
|
|
1002
|
-
top = _this$
|
|
1003
|
-
left = _this$
|
|
1004
|
-
topOffset = _this$
|
|
1005
|
-
leftOffset = _this$
|
|
1052
|
+
var _this$state3 = this.state,
|
|
1053
|
+
top = _this$state3.top,
|
|
1054
|
+
left = _this$state3.left,
|
|
1055
|
+
topOffset = _this$state3.topOffset,
|
|
1056
|
+
leftOffset = _this$state3.leftOffset;
|
|
1006
1057
|
if (row != null && !GridUtils.isFloatingRow(row, this.metrics)) {
|
|
1007
1058
|
if (row < topVisible) {
|
|
1008
1059
|
top = metricCalculator.getTopForTopVisible(metricState, row);
|
|
@@ -1088,11 +1139,10 @@ class Grid extends PureComponent {
|
|
|
1088
1139
|
value: value !== undefined ? value : model.editValueForCell(modelColumn, modelRow),
|
|
1089
1140
|
isQuickEdit
|
|
1090
1141
|
};
|
|
1091
|
-
this.setState({
|
|
1142
|
+
this.setState(state => ({
|
|
1092
1143
|
editingCell: cell,
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
});
|
|
1144
|
+
selection: state.selection.withCursor(row, column)
|
|
1145
|
+
}));
|
|
1096
1146
|
this.moveViewToCell(column, row);
|
|
1097
1147
|
}
|
|
1098
1148
|
|
|
@@ -1120,16 +1170,19 @@ class Grid extends PureComponent {
|
|
|
1120
1170
|
var _this = this;
|
|
1121
1171
|
return _asyncToGenerator(function* () {
|
|
1122
1172
|
var model = _this.props.model;
|
|
1123
|
-
var _this$
|
|
1124
|
-
movedColumns = _this$
|
|
1125
|
-
movedRows = _this$
|
|
1126
|
-
|
|
1173
|
+
var _this$state4 = _this.state,
|
|
1174
|
+
movedColumns = _this$state4.movedColumns,
|
|
1175
|
+
movedRows = _this$state4.movedRows,
|
|
1176
|
+
selection = _this$state4.selection;
|
|
1177
|
+
// pasteValue is only reachable for editable (non-keyed) tables
|
|
1178
|
+
assertIsRangedSelection(selection);
|
|
1179
|
+
var selectedRanges = selection.toRanges();
|
|
1127
1180
|
try {
|
|
1128
1181
|
assertIsEditableGridModel(model);
|
|
1129
1182
|
if (!model.isEditable || !selectedRanges.every(range => model.isEditableRange(range))) {
|
|
1130
1183
|
throw new PasteError("Can't paste in to read-only area.");
|
|
1131
1184
|
}
|
|
1132
|
-
if (
|
|
1185
|
+
if (selection.isEmpty()) {
|
|
1133
1186
|
throw new PasteError('Select an area to paste to.');
|
|
1134
1187
|
}
|
|
1135
1188
|
if (typeof value === 'string') {
|
|
@@ -1223,9 +1276,9 @@ class Grid extends PureComponent {
|
|
|
1223
1276
|
var _this$props7 = this.props,
|
|
1224
1277
|
model = _this$props7.model,
|
|
1225
1278
|
onError = _this$props7.onError;
|
|
1226
|
-
var _this$
|
|
1227
|
-
movedColumns = _this$
|
|
1228
|
-
movedRows = _this$
|
|
1279
|
+
var _this$state5 = this.state,
|
|
1280
|
+
movedColumns = _this$state5.movedColumns,
|
|
1281
|
+
movedRows = _this$state5.movedRows;
|
|
1229
1282
|
var modelRanges = GridUtils.getModelRanges(ranges, movedColumns, movedRows);
|
|
1230
1283
|
if (isEditableGridModel(model)) {
|
|
1231
1284
|
model.setValueForRanges(modelRanges, value).catch(err => {
|
|
@@ -1241,17 +1294,8 @@ class Grid extends PureComponent {
|
|
|
1241
1294
|
* @returns True if the cell is in the current selection, false otherwise
|
|
1242
1295
|
*/
|
|
1243
1296
|
isSelected(row, column) {
|
|
1244
|
-
var
|
|
1245
|
-
|
|
1246
|
-
var _selectedRange$endRow, _selectedRange$endCol;
|
|
1247
|
-
var selectedRange = selectedRanges[i];
|
|
1248
|
-
var rowSelected = selectedRange.startRow === null || selectedRange.startRow <= row && row <= ((_selectedRange$endRow = selectedRange.endRow) !== null && _selectedRange$endRow !== void 0 ? _selectedRange$endRow : 0);
|
|
1249
|
-
var columnSelected = selectedRange.startColumn === null || selectedRange.startColumn <= column && column <= ((_selectedRange$endCol = selectedRange.endColumn) !== null && _selectedRange$endCol !== void 0 ? _selectedRange$endCol : 0);
|
|
1250
|
-
if (rowSelected && columnSelected) {
|
|
1251
|
-
return true;
|
|
1252
|
-
}
|
|
1253
|
-
}
|
|
1254
|
-
return false;
|
|
1297
|
+
var selection = this.state.selection;
|
|
1298
|
+
return selection.isCellSelected(column, row);
|
|
1255
1299
|
}
|
|
1256
1300
|
addDocumentCursor() {
|
|
1257
1301
|
var cursor = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
|
|
@@ -1303,9 +1347,13 @@ class Grid extends PureComponent {
|
|
|
1303
1347
|
var renderer = this.renderer,
|
|
1304
1348
|
context = this.canvasContext,
|
|
1305
1349
|
renderState = this.renderState;
|
|
1350
|
+
assertNotNull(renderState);
|
|
1306
1351
|
context.save();
|
|
1307
1352
|
renderer.drawCanvas(renderState);
|
|
1308
1353
|
context.restore();
|
|
1354
|
+
this.drawListeners.forEach(listener => {
|
|
1355
|
+
listener(renderState);
|
|
1356
|
+
});
|
|
1309
1357
|
}
|
|
1310
1358
|
|
|
1311
1359
|
/**
|
|
@@ -1505,9 +1553,9 @@ class Grid extends PureComponent {
|
|
|
1505
1553
|
this.forceUpdate();
|
|
1506
1554
|
}
|
|
1507
1555
|
forceUpdate(callback) {
|
|
1508
|
-
this.setState(
|
|
1509
|
-
var
|
|
1510
|
-
updateRevision =
|
|
1556
|
+
this.setState(_ref6 => {
|
|
1557
|
+
var _ref6$updateRevision = _ref6.updateRevision,
|
|
1558
|
+
updateRevision = _ref6$updateRevision === void 0 ? 0 : _ref6$updateRevision;
|
|
1511
1559
|
return {
|
|
1512
1560
|
updateRevision: (updateRevision + 1) % Number.MAX_SAFE_INTEGER
|
|
1513
1561
|
};
|
|
@@ -1684,8 +1732,8 @@ class Grid extends PureComponent {
|
|
|
1684
1732
|
* @param value New value set
|
|
1685
1733
|
*/
|
|
1686
1734
|
handleEditCellChange(value) {
|
|
1687
|
-
this.setState(
|
|
1688
|
-
var editingCell =
|
|
1735
|
+
this.setState(_ref7 => {
|
|
1736
|
+
var editingCell = _ref7.editingCell;
|
|
1689
1737
|
try {
|
|
1690
1738
|
assertIsDefined(editingCell);
|
|
1691
1739
|
return {
|
|
@@ -1708,14 +1756,14 @@ class Grid extends PureComponent {
|
|
|
1708
1756
|
* @param options Options for committing
|
|
1709
1757
|
*/
|
|
1710
1758
|
handleEditCellCommit(value) {
|
|
1711
|
-
var
|
|
1712
|
-
|
|
1713
|
-
direction =
|
|
1714
|
-
|
|
1715
|
-
fillRange =
|
|
1716
|
-
var _this$
|
|
1717
|
-
editingCell = _this$
|
|
1718
|
-
|
|
1759
|
+
var _ref8 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
|
|
1760
|
+
_ref8$direction = _ref8.direction,
|
|
1761
|
+
direction = _ref8$direction === void 0 ? SELECTION_DIRECTION.DOWN : _ref8$direction,
|
|
1762
|
+
_ref8$fillRange = _ref8.fillRange,
|
|
1763
|
+
fillRange = _ref8$fillRange === void 0 ? false : _ref8$fillRange;
|
|
1764
|
+
var _this$state6 = this.state,
|
|
1765
|
+
editingCell = _this$state6.editingCell,
|
|
1766
|
+
selection = _this$state6.selection;
|
|
1719
1767
|
if (!editingCell) throw new Error('editingCell not set');
|
|
1720
1768
|
var column = editingCell.column,
|
|
1721
1769
|
row = editingCell.row;
|
|
@@ -1730,12 +1778,14 @@ class Grid extends PureComponent {
|
|
|
1730
1778
|
return;
|
|
1731
1779
|
}
|
|
1732
1780
|
if (fillRange) {
|
|
1733
|
-
|
|
1781
|
+
// fillRange is only reachable for editable (non-keyed) tables
|
|
1782
|
+
assertIsRangedSelection(selection);
|
|
1783
|
+
this.setValueForRanges(selection.toRanges(), value);
|
|
1734
1784
|
} else {
|
|
1735
1785
|
this.setValueForCell(column, row, value);
|
|
1736
1786
|
}
|
|
1737
1787
|
if (direction !== null) {
|
|
1738
|
-
this.
|
|
1788
|
+
this.handleKeyAdvanceCursor(direction);
|
|
1739
1789
|
}
|
|
1740
1790
|
this.setState({
|
|
1741
1791
|
editingCell: null
|
|
@@ -1851,21 +1901,20 @@ class Grid extends PureComponent {
|
|
|
1851
1901
|
updateRenderState() {
|
|
1852
1902
|
if (!this.canvas) throw new Error('canvas is not set');
|
|
1853
1903
|
if (!this.canvasContext) throw new Error('context not set');
|
|
1854
|
-
var _this$
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
selectedRanges = _this$state1.selectedRanges;
|
|
1904
|
+
var _this$state7 = this.state,
|
|
1905
|
+
draggingColumn = _this$state7.draggingColumn,
|
|
1906
|
+
draggingColumnSeparator = _this$state7.draggingColumnSeparator,
|
|
1907
|
+
draggingRow = _this$state7.draggingRow,
|
|
1908
|
+
draggingRowOffset = _this$state7.draggingRowOffset,
|
|
1909
|
+
draggingRowSeparator = _this$state7.draggingRowSeparator,
|
|
1910
|
+
editingCell = _this$state7.editingCell,
|
|
1911
|
+
gestureMode = _this$state7.gestureMode,
|
|
1912
|
+
isDraggingHorizontalScrollBar = _this$state7.isDraggingHorizontalScrollBar,
|
|
1913
|
+
isDraggingVerticalScrollBar = _this$state7.isDraggingVerticalScrollBar,
|
|
1914
|
+
isDragging = _this$state7.isDragging,
|
|
1915
|
+
mouseX = _this$state7.mouseX,
|
|
1916
|
+
mouseY = _this$state7.mouseY,
|
|
1917
|
+
selection = _this$state7.selection;
|
|
1869
1918
|
var _this$props8 = this.props,
|
|
1870
1919
|
model = _this$props8.model,
|
|
1871
1920
|
stateOverride = _this$props8.stateOverride;
|
|
@@ -1884,7 +1933,7 @@ class Grid extends PureComponent {
|
|
|
1884
1933
|
metrics,
|
|
1885
1934
|
mouseX,
|
|
1886
1935
|
mouseY,
|
|
1887
|
-
|
|
1936
|
+
selection,
|
|
1888
1937
|
draggingColumn,
|
|
1889
1938
|
draggingColumnSeparator,
|
|
1890
1939
|
draggingRow,
|
|
@@ -1894,8 +1943,7 @@ class Grid extends PureComponent {
|
|
|
1894
1943
|
isDraggingHorizontalScrollBar,
|
|
1895
1944
|
isDraggingVerticalScrollBar,
|
|
1896
1945
|
isDragging,
|
|
1897
|
-
|
|
1898
|
-
cursorRow
|
|
1946
|
+
gestureMode
|
|
1899
1947
|
}, stateOverride);
|
|
1900
1948
|
return this.renderState;
|
|
1901
1949
|
}
|
|
@@ -1919,7 +1967,9 @@ class Grid extends PureComponent {
|
|
|
1919
1967
|
onMouseMove: this.handleMouseMove,
|
|
1920
1968
|
onMouseLeave: this.handleMouseLeave,
|
|
1921
1969
|
tabIndex: 0,
|
|
1922
|
-
children:
|
|
1970
|
+
children: /*#__PURE__*/_jsx(GridA11yFallback, {
|
|
1971
|
+
registerDrawListener: this.registerDrawListener
|
|
1972
|
+
})
|
|
1923
1973
|
}), this.renderInputField(), children]
|
|
1924
1974
|
});
|
|
1925
1975
|
}
|
|
@@ -1939,6 +1989,7 @@ _defineProperty(Grid, "defaultProps", {
|
|
|
1939
1989
|
movedRows: EMPTY_ARRAY,
|
|
1940
1990
|
onError: () => undefined,
|
|
1941
1991
|
onSelectionChanged: () => undefined,
|
|
1992
|
+
onSelectionChange: _selection => undefined,
|
|
1942
1993
|
onMovedColumnsChanged: moveOperations => undefined,
|
|
1943
1994
|
onMoveColumnComplete: () => undefined,
|
|
1944
1995
|
onMovedRowsChanged: () => undefined,
|
|
@@ -1954,7 +2005,8 @@ _defineProperty(Grid, "defaultProps", {
|
|
|
1954
2005
|
theme: {
|
|
1955
2006
|
autoSelectColumn: false,
|
|
1956
2007
|
autoSelectRow: false
|
|
1957
|
-
}
|
|
2008
|
+
},
|
|
2009
|
+
createEmptySelection: RangedSelection.empty
|
|
1958
2010
|
});
|
|
1959
2011
|
// use same constant as chrome source for windows
|
|
1960
2012
|
// https://github.com/chromium/chromium/blob/973af9d461b6b5dc60208c8d3d66adc27e53da78/ui/events/blink/web_input_event_builders_win.cc#L285
|