@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
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
2
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
3
|
+
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
4
|
+
import { EMPTY_ARRAY, assertNotNaN, assertNotNull } from '@deephaven/utils';
|
|
5
|
+
import GridRange from "./GridRange.js";
|
|
6
|
+
import GridUtils from "./GridUtils.js";
|
|
7
|
+
import { computeGestureExtend, cursorLandingCellForRanges, nextCursorInRanges, withCommittedCursor } from "./GridSelectionUtils.js";
|
|
8
|
+
/**
|
|
9
|
+
* Immutable `Selection` for standard (row-indexed) grids. Each entry in
|
|
10
|
+
* `ranges` describes a rectangle of cells; consumers iterate/consolidate
|
|
11
|
+
* as needed.
|
|
12
|
+
*/
|
|
13
|
+
export class RangedSelection {
|
|
14
|
+
static empty(getModel) {
|
|
15
|
+
return new RangedSelection(EMPTY_ARRAY, getModel);
|
|
16
|
+
}
|
|
17
|
+
constructor(/** Committed selection rectangles; may be empty for a cleared selection. */
|
|
18
|
+
ranges,
|
|
19
|
+
/**
|
|
20
|
+
* Deferred lookup for the current `GridModel`. Passed as a closure
|
|
21
|
+
* (not a direct reference) so this Selection always reads the model
|
|
22
|
+
* currently on `Grid.props.model` — surviving prop swaps without
|
|
23
|
+
* holding a stale reference.
|
|
24
|
+
*/
|
|
25
|
+
getModel) {
|
|
26
|
+
var gestureStartRow = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
|
|
27
|
+
var gestureStartColumn = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
|
|
28
|
+
var cursorRow = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null;
|
|
29
|
+
var cursorColumn = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : null;
|
|
30
|
+
var selectionEndRow = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : null;
|
|
31
|
+
var selectionEndColumn = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : null;
|
|
32
|
+
_defineProperty(this, "cachedColumnTickRanges", void 0);
|
|
33
|
+
_defineProperty(this, "cachedRowTickRanges", void 0);
|
|
34
|
+
this.ranges = ranges;
|
|
35
|
+
this.getModel = getModel;
|
|
36
|
+
this.gestureStartRow = gestureStartRow;
|
|
37
|
+
this.gestureStartColumn = gestureStartColumn;
|
|
38
|
+
this.cursorRow = cursorRow;
|
|
39
|
+
this.cursorColumn = cursorColumn;
|
|
40
|
+
this.selectionEndRow = selectionEndRow;
|
|
41
|
+
this.selectionEndColumn = selectionEndColumn;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Returns a copy with the given fields overridden. Unspecified fields
|
|
46
|
+
* carry through from `this`, so mutations that only touch ranges /
|
|
47
|
+
* anchor keep cursor + endpoint intact without extra bookkeeping at
|
|
48
|
+
* every call site.
|
|
49
|
+
*/
|
|
50
|
+
copyWith(overrides) {
|
|
51
|
+
var _overrides$gestureSta, _overrides$cursor, _overrides$selectionE, _overrides$ranges;
|
|
52
|
+
var gestureStart = (_overrides$gestureSta = overrides.gestureStart) !== null && _overrides$gestureSta !== void 0 ? _overrides$gestureSta : {
|
|
53
|
+
row: this.gestureStartRow,
|
|
54
|
+
column: this.gestureStartColumn
|
|
55
|
+
};
|
|
56
|
+
var cursor = (_overrides$cursor = overrides.cursor) !== null && _overrides$cursor !== void 0 ? _overrides$cursor : {
|
|
57
|
+
row: this.cursorRow,
|
|
58
|
+
column: this.cursorColumn
|
|
59
|
+
};
|
|
60
|
+
var selectionEnd = (_overrides$selectionE = overrides.selectionEnd) !== null && _overrides$selectionE !== void 0 ? _overrides$selectionE : {
|
|
61
|
+
row: this.selectionEndRow,
|
|
62
|
+
column: this.selectionEndColumn
|
|
63
|
+
};
|
|
64
|
+
return new RangedSelection((_overrides$ranges = overrides.ranges) !== null && _overrides$ranges !== void 0 ? _overrides$ranges : this.ranges, this.getModel, gestureStart.row, gestureStart.column, cursor.row, cursor.column, selectionEnd.row, selectionEnd.column);
|
|
65
|
+
}
|
|
66
|
+
isEmpty() {
|
|
67
|
+
return this.ranges.length === 0;
|
|
68
|
+
}
|
|
69
|
+
describe() {
|
|
70
|
+
if (this.ranges.length === 0) return 'No selection.';
|
|
71
|
+
var cellCount = GridRange.cellCount(this.ranges);
|
|
72
|
+
if (!Number.isNaN(cellCount)) {
|
|
73
|
+
return cellCount === 1 ? '1 cell selected.' : "".concat(cellCount, " cells selected.");
|
|
74
|
+
}
|
|
75
|
+
// A range with no countable cells is unbounded in one direction, i.e. whole
|
|
76
|
+
// rows or whole columns, which is what clicking a row or column header gives.
|
|
77
|
+
var rowCount = GridRange.rowCount(this.ranges);
|
|
78
|
+
if (!Number.isNaN(rowCount)) {
|
|
79
|
+
return rowCount === 1 ? '1 row selected.' : "".concat(rowCount, " rows selected.");
|
|
80
|
+
}
|
|
81
|
+
var columnCount = GridRange.columnCount(this.ranges);
|
|
82
|
+
if (!Number.isNaN(columnCount)) {
|
|
83
|
+
return columnCount === 1 ? '1 column selected.' : "".concat(columnCount, " columns selected.");
|
|
84
|
+
}
|
|
85
|
+
return this.ranges.length === 1 ? 'Everything selected.' : "".concat(this.ranges.length, " selection ranges selected.");
|
|
86
|
+
}
|
|
87
|
+
isCellSelected(column, row) {
|
|
88
|
+
for (var i = 0; i < this.ranges.length; i += 1) {
|
|
89
|
+
if (this.ranges[i].containsCell(column, row)) {
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
isRowSelected(row) {
|
|
96
|
+
var _this$getModel = this.getModel(),
|
|
97
|
+
columnCount = _this$getModel.columnCount;
|
|
98
|
+
for (var i = 0; i < this.ranges.length; i += 1) {
|
|
99
|
+
var range = this.ranges[i];
|
|
100
|
+
// A range covers the whole row when it contains both column endpoints
|
|
101
|
+
// at `row` — `GridRange` is a contiguous rectangle, so hitting both
|
|
102
|
+
// ends implies spanning the entire axis.
|
|
103
|
+
if (range.containsCell(0, row) && range.containsCell(columnCount - 1, row)) {
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
isColumnSelected(column) {
|
|
110
|
+
var _this$getModel2 = this.getModel(),
|
|
111
|
+
rowCount = _this$getModel2.rowCount;
|
|
112
|
+
for (var i = 0; i < this.ranges.length; i += 1) {
|
|
113
|
+
var range = this.ranges[i];
|
|
114
|
+
if (range.containsCell(column, 0) && range.containsCell(column, rowCount - 1)) {
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Checks if all ranges are within the bounds of the grid model.
|
|
123
|
+
* @returns True if all ranges are within bounds, false otherwise.
|
|
124
|
+
*/
|
|
125
|
+
isInBounds() {
|
|
126
|
+
var _this$getModel3 = this.getModel(),
|
|
127
|
+
columnCount = _this$getModel3.columnCount,
|
|
128
|
+
rowCount = _this$getModel3.rowCount;
|
|
129
|
+
for (var i = 0; i < this.ranges.length; i += 1) {
|
|
130
|
+
var range = this.ranges[i];
|
|
131
|
+
if (range.endColumn != null && range.endColumn >= columnCount || range.endRow != null && range.endRow >= rowCount) {
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return true;
|
|
136
|
+
}
|
|
137
|
+
toRanges() {
|
|
138
|
+
return this.ranges;
|
|
139
|
+
}
|
|
140
|
+
getColumnTickRanges() {
|
|
141
|
+
if (this.cachedColumnTickRanges !== undefined) {
|
|
142
|
+
return this.cachedColumnTickRanges;
|
|
143
|
+
}
|
|
144
|
+
var raw = [];
|
|
145
|
+
for (var i = 0; i < this.ranges.length; i += 1) {
|
|
146
|
+
var _this$ranges$i = this.ranges[i],
|
|
147
|
+
startColumn = _this$ranges$i.startColumn,
|
|
148
|
+
endColumn = _this$ranges$i.endColumn;
|
|
149
|
+
if (startColumn != null && endColumn != null) {
|
|
150
|
+
raw.push([startColumn, endColumn]);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
raw.sort(GridUtils.compareRanges);
|
|
154
|
+
this.cachedColumnTickRanges = GridUtils.mergeSortedRanges(raw);
|
|
155
|
+
return this.cachedColumnTickRanges;
|
|
156
|
+
}
|
|
157
|
+
getRowTickRanges() {
|
|
158
|
+
if (this.cachedRowTickRanges !== undefined) {
|
|
159
|
+
return this.cachedRowTickRanges;
|
|
160
|
+
}
|
|
161
|
+
var raw = [];
|
|
162
|
+
for (var i = 0; i < this.ranges.length; i += 1) {
|
|
163
|
+
var _this$ranges$i2 = this.ranges[i],
|
|
164
|
+
startRow = _this$ranges$i2.startRow,
|
|
165
|
+
endRow = _this$ranges$i2.endRow;
|
|
166
|
+
if (startRow != null && endRow != null) {
|
|
167
|
+
raw.push([startRow, endRow]);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
raw.sort(GridUtils.compareRanges);
|
|
171
|
+
this.cachedRowTickRanges = GridUtils.mergeSortedRanges(raw);
|
|
172
|
+
return this.cachedRowTickRanges;
|
|
173
|
+
}
|
|
174
|
+
withCommittedRanges(ranges, anchor) {
|
|
175
|
+
var result = ranges === this.ranges ? this : this.copyWith({
|
|
176
|
+
ranges,
|
|
177
|
+
gestureStart: {
|
|
178
|
+
row: null,
|
|
179
|
+
column: null
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
if (anchor === undefined) return result;
|
|
183
|
+
return result.withGestureAnchor(anchor.row, anchor.column);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Sets the gesture anchor (extend-from position for shift-click and
|
|
188
|
+
* keyboard extend) to the given cell. Passing `null` for both clears it.
|
|
189
|
+
*/
|
|
190
|
+
withGestureAnchor(row, column) {
|
|
191
|
+
if (row === this.gestureStartRow && column === this.gestureStartColumn) {
|
|
192
|
+
return this;
|
|
193
|
+
}
|
|
194
|
+
return this.copyWith({
|
|
195
|
+
gestureStart: {
|
|
196
|
+
row,
|
|
197
|
+
column
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* The current `{row, column}` of the gesture anchor, or `null` if none is set.
|
|
204
|
+
*/
|
|
205
|
+
getGestureAnchor() {
|
|
206
|
+
if (this.gestureStartRow == null && this.gestureStartColumn == null) {
|
|
207
|
+
return null;
|
|
208
|
+
}
|
|
209
|
+
return {
|
|
210
|
+
row: this.gestureStartRow,
|
|
211
|
+
column: this.gestureStartColumn
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
selectAll() {
|
|
215
|
+
var _this$getModel4 = this.getModel(),
|
|
216
|
+
rowCount = _this$getModel4.rowCount;
|
|
217
|
+
return this.withCommittedRanges([new GridRange(null, 0, null, rowCount - 1)]);
|
|
218
|
+
}
|
|
219
|
+
getNextCursorInDirection(current, direction) {
|
|
220
|
+
var _this$getModel5 = this.getModel(),
|
|
221
|
+
columnCount = _this$getModel5.columnCount,
|
|
222
|
+
rowCount = _this$getModel5.rowCount;
|
|
223
|
+
return nextCursorInRanges(this.ranges, current, direction, {
|
|
224
|
+
columnCount,
|
|
225
|
+
rowCount
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
getCursorLandingCell() {
|
|
229
|
+
var _this$getModel6 = this.getModel(),
|
|
230
|
+
columnCount = _this$getModel6.columnCount,
|
|
231
|
+
rowCount = _this$getModel6.rowCount;
|
|
232
|
+
return cursorLandingCellForRanges(this.ranges, {
|
|
233
|
+
columnCount,
|
|
234
|
+
rowCount
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
withCursor(row, column) {
|
|
238
|
+
if (row === this.cursorRow && column === this.cursorColumn) return this;
|
|
239
|
+
return this.copyWith({
|
|
240
|
+
cursor: {
|
|
241
|
+
row,
|
|
242
|
+
column
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
withSelectionEnd(row, column) {
|
|
247
|
+
if (row === this.selectionEndRow && column === this.selectionEndColumn) {
|
|
248
|
+
return this;
|
|
249
|
+
}
|
|
250
|
+
return this.copyWith({
|
|
251
|
+
selectionEnd: {
|
|
252
|
+
row,
|
|
253
|
+
column
|
|
254
|
+
}
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
withGestureExtend(cursor, opts) {
|
|
258
|
+
var _computeGestureExtend = computeGestureExtend(this.ranges, this.getGestureAnchor(), cursor, opts),
|
|
259
|
+
newRanges = _computeGestureExtend.newRanges,
|
|
260
|
+
trimBefore = _computeGestureExtend.trimBefore,
|
|
261
|
+
resetAnchor = _computeGestureExtend.resetAnchor;
|
|
262
|
+
// Trim is a no-op wrapper for RangedSelection when `newRanges` already
|
|
263
|
+
// reflects the single-remaining-range shape returned by computeGestureExtend,
|
|
264
|
+
// but call it explicitly so anchor / other state stays consistent with the
|
|
265
|
+
// existing shift-click path.
|
|
266
|
+
var base = trimBefore ? this.trimmed() : this;
|
|
267
|
+
var result = newRanges === base.ranges ? base : base.copyWith({
|
|
268
|
+
ranges: newRanges
|
|
269
|
+
});
|
|
270
|
+
if (resetAnchor) {
|
|
271
|
+
result = result.withGestureAnchor(cursor.row, cursor.column);
|
|
272
|
+
}
|
|
273
|
+
return result;
|
|
274
|
+
}
|
|
275
|
+
commitGesture(lastCommitted, opts) {
|
|
276
|
+
var autoSelectRow = opts.autoSelectRow,
|
|
277
|
+
_opts$settle = opts.settle,
|
|
278
|
+
settle = _opts$settle === void 0 ? true : _opts$settle;
|
|
279
|
+
var selectedRanges = this.ranges;
|
|
280
|
+
// lastCommitted is always a RangedSelection when this method is called
|
|
281
|
+
assertIsRangedSelection(lastCommitted);
|
|
282
|
+
var lastRanges = lastCommitted.toRanges();
|
|
283
|
+
if (!settle) {
|
|
284
|
+
// Mouse-down: leave ranges as-is so the drag can grow the last range.
|
|
285
|
+
// Deselect / hole-punch / consolidation run on mouse-up.
|
|
286
|
+
return withCommittedCursor(this, this.getCursorLandingCell(), opts);
|
|
287
|
+
}
|
|
288
|
+
if (opts.allowDeselect !== false && selectedRanges.length === 1 && (autoSelectRow ? GridRange.rowCount(selectedRanges) === 1 : GridRange.cellCount(selectedRanges) === 1) && GridRange.rangeArraysEqual(selectedRanges, lastRanges)) {
|
|
289
|
+
return withCommittedCursor(this.copyWith({
|
|
290
|
+
ranges: EMPTY_ARRAY
|
|
291
|
+
}), this.getCursorLandingCell(), opts);
|
|
292
|
+
}
|
|
293
|
+
var newRanges = selectedRanges.slice();
|
|
294
|
+
if (newRanges.length > 1) {
|
|
295
|
+
var lastRange = newRanges[newRanges.length - 1];
|
|
296
|
+
for (var i = 0; i < newRanges.length - 1; i += 1) {
|
|
297
|
+
if (newRanges[i].contains(lastRange)) {
|
|
298
|
+
var remainder = newRanges[i].subtract(lastRange);
|
|
299
|
+
newRanges.pop();
|
|
300
|
+
newRanges.splice(i, 1);
|
|
301
|
+
newRanges = newRanges.concat(remainder);
|
|
302
|
+
break;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
newRanges = GridRange.consolidate(newRanges);
|
|
306
|
+
}
|
|
307
|
+
var changed = newRanges.length !== selectedRanges.length || newRanges.some((r, i) => !r.equals(selectedRanges[i]));
|
|
308
|
+
return withCommittedCursor(changed ? this.copyWith({
|
|
309
|
+
ranges: newRanges
|
|
310
|
+
}) : this, this.getCursorLandingCell(), opts);
|
|
311
|
+
}
|
|
312
|
+
clear() {
|
|
313
|
+
return this.copyWith({
|
|
314
|
+
ranges: EMPTY_ARRAY,
|
|
315
|
+
gestureStart: {
|
|
316
|
+
row: null,
|
|
317
|
+
column: null
|
|
318
|
+
},
|
|
319
|
+
selectionEnd: {
|
|
320
|
+
row: null,
|
|
321
|
+
column: null
|
|
322
|
+
}
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
trimmed() {
|
|
326
|
+
if (this.ranges.length > 0) {
|
|
327
|
+
return this.copyWith({
|
|
328
|
+
ranges: this.ranges.slice(this.ranges.length - 1)
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
return this;
|
|
332
|
+
}
|
|
333
|
+
truncate(maxRows) {
|
|
334
|
+
var rowCount = GridRange.rowCount(this.ranges);
|
|
335
|
+
if (rowCount <= maxRows) return this;
|
|
336
|
+
var ranges = [...this.ranges];
|
|
337
|
+
while (rowCount > maxRows) {
|
|
338
|
+
var lastRow = ranges.pop();
|
|
339
|
+
// should never occur, sanity check
|
|
340
|
+
assertNotNull(lastRow, 'Selected ranges should not be empty');
|
|
341
|
+
var lastRowSize = GridRange.rowCount([lastRow]);
|
|
342
|
+
// should never occur, sanity check
|
|
343
|
+
assertNotNaN(lastRowSize, 'Selected ranges should not be unbounded');
|
|
344
|
+
if (rowCount - lastRowSize < maxRows) {
|
|
345
|
+
var _lastRow$endRow;
|
|
346
|
+
ranges.push(new GridRange(lastRow.startColumn, lastRow.startRow, lastRow.endColumn, ((_lastRow$endRow = lastRow.endRow) !== null && _lastRow$endRow !== void 0 ? _lastRow$endRow : 0) - (rowCount - maxRows)));
|
|
347
|
+
break;
|
|
348
|
+
}
|
|
349
|
+
rowCount -= lastRowSize;
|
|
350
|
+
}
|
|
351
|
+
return this.copyWith({
|
|
352
|
+
ranges
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
export function isRangedSelection(selection) {
|
|
357
|
+
return selection instanceof RangedSelection;
|
|
358
|
+
}
|
|
359
|
+
export function assertIsRangedSelection(selection) {
|
|
360
|
+
if (!(selection instanceof RangedSelection)) {
|
|
361
|
+
throw new Error("Expected a RangedSelection but got ".concat(selection.constructor.name));
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* Returns `selection.toRanges()` when `selection` is a `RangedSelection`,
|
|
367
|
+
* otherwise `EMPTY_ARRAY`. Handy for consumers that only care about the
|
|
368
|
+
* range-form projection of a selection (e.g. legacy `selectedRanges`
|
|
369
|
+
* callbacks) and want a stable empty array for keyed / null selections.
|
|
370
|
+
*/
|
|
371
|
+
export function selectionToRanges(selection) {
|
|
372
|
+
return selection != null && isRangedSelection(selection) ? selection.toRanges() : EMPTY_ARRAY;
|
|
373
|
+
}
|
|
374
|
+
export default RangedSelection;
|
|
375
|
+
//# sourceMappingURL=RangedSelection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RangedSelection.js","names":["EMPTY_ARRAY","assertNotNaN","assertNotNull","GridRange","GridUtils","computeGestureExtend","cursorLandingCellForRanges","nextCursorInRanges","withCommittedCursor","RangedSelection","empty","getModel","constructor","ranges","gestureStartRow","arguments","length","undefined","gestureStartColumn","cursorRow","cursorColumn","selectionEndRow","selectionEndColumn","_defineProperty","copyWith","overrides","_overrides$gestureSta","_overrides$cursor","_overrides$selectionE","_overrides$ranges","gestureStart","row","column","cursor","selectionEnd","isEmpty","describe","cellCount","Number","isNaN","concat","rowCount","columnCount","isCellSelected","i","containsCell","isRowSelected","_this$getModel","range","isColumnSelected","_this$getModel2","isInBounds","_this$getModel3","endColumn","endRow","toRanges","getColumnTickRanges","cachedColumnTickRanges","raw","_this$ranges$i","startColumn","push","sort","compareRanges","mergeSortedRanges","getRowTickRanges","cachedRowTickRanges","_this$ranges$i2","startRow","withCommittedRanges","anchor","result","withGestureAnchor","getGestureAnchor","selectAll","_this$getModel4","getNextCursorInDirection","current","direction","_this$getModel5","getCursorLandingCell","_this$getModel6","withCursor","withSelectionEnd","withGestureExtend","opts","_computeGestureExtend","newRanges","trimBefore","resetAnchor","base","trimmed","commitGesture","lastCommitted","autoSelectRow","_opts$settle","settle","selectedRanges","assertIsRangedSelection","lastRanges","allowDeselect","rangeArraysEqual","slice","lastRange","contains","remainder","subtract","pop","splice","consolidate","changed","some","r","equals","clear","truncate","maxRows","lastRow","lastRowSize","_lastRow$endRow","isRangedSelection","selection","Error","name","selectionToRanges"],"sources":["../src/RangedSelection.ts"],"sourcesContent":["import { EMPTY_ARRAY, assertNotNaN, assertNotNull } from '@deephaven/utils';\nimport GridRange, {\n type GridRangeIndex,\n type SELECTION_DIRECTION,\n} from './GridRange';\nimport type { VisibleIndex } from './GridMetrics';\nimport { type BoundedAxisRange } from './GridAxisRange';\nimport GridUtils from './GridUtils';\nimport type {\n CommitGestureOptions,\n GestureExtendOptions,\n GetModel,\n Selection,\n TickRangeSelection,\n} from './Selection';\nimport {\n computeGestureExtend,\n cursorLandingCellForRanges,\n nextCursorInRanges,\n withCommittedCursor,\n} from './GridSelectionUtils';\n\n/**\n * Immutable `Selection` for standard (row-indexed) grids. Each entry in\n * `ranges` describes a rectangle of cells; consumers iterate/consolidate\n * as needed.\n */\nexport class RangedSelection implements Selection, TickRangeSelection {\n static empty(getModel: GetModel): RangedSelection {\n return new RangedSelection(EMPTY_ARRAY, getModel);\n }\n\n constructor(\n /** Committed selection rectangles; may be empty for a cleared selection. */\n readonly ranges: readonly GridRange[],\n /**\n * Deferred lookup for the current `GridModel`. Passed as a closure\n * (not a direct reference) so this Selection always reads the model\n * currently on `Grid.props.model` — surviving prop swaps without\n * holding a stale reference.\n */\n private readonly getModel: GetModel,\n /** Anchor row for shift-click / keyboard extend; null when no anchor is set. */\n private readonly gestureStartRow: GridRangeIndex = null,\n /** Anchor column for shift-click / keyboard extend; null when no anchor is set. */\n private readonly gestureStartColumn: GridRangeIndex = null,\n /** Focus row; null when no cursor is set. */\n readonly cursorRow: VisibleIndex | null = null,\n /** Focus column; null when no cursor is set. */\n readonly cursorColumn: VisibleIndex | null = null,\n /** Last shift/drag endpoint row; null when unset. */\n readonly selectionEndRow: VisibleIndex | null = null,\n /** Last shift/drag endpoint column; null when unset. */\n readonly selectionEndColumn: VisibleIndex | null = null\n ) {}\n\n /**\n * Returns a copy with the given fields overridden. Unspecified fields\n * carry through from `this`, so mutations that only touch ranges /\n * anchor keep cursor + endpoint intact without extra bookkeeping at\n * every call site.\n */\n private copyWith(overrides: {\n ranges?: readonly GridRange[];\n gestureStart?: { row: GridRangeIndex; column: GridRangeIndex };\n cursor?: { row: VisibleIndex | null; column: VisibleIndex | null };\n selectionEnd?: { row: VisibleIndex | null; column: VisibleIndex | null };\n }): RangedSelection {\n const gestureStart = overrides.gestureStart ?? {\n row: this.gestureStartRow,\n column: this.gestureStartColumn,\n };\n const cursor = overrides.cursor ?? {\n row: this.cursorRow,\n column: this.cursorColumn,\n };\n const selectionEnd = overrides.selectionEnd ?? {\n row: this.selectionEndRow,\n column: this.selectionEndColumn,\n };\n return new RangedSelection(\n overrides.ranges ?? this.ranges,\n this.getModel,\n gestureStart.row,\n gestureStart.column,\n cursor.row,\n cursor.column,\n selectionEnd.row,\n selectionEnd.column\n );\n }\n\n isEmpty(): boolean {\n return this.ranges.length === 0;\n }\n\n describe(): string {\n if (this.ranges.length === 0) return 'No selection.';\n const cellCount = GridRange.cellCount(this.ranges);\n if (!Number.isNaN(cellCount)) {\n return cellCount === 1\n ? '1 cell selected.'\n : `${cellCount} cells selected.`;\n }\n // A range with no countable cells is unbounded in one direction, i.e. whole\n // rows or whole columns, which is what clicking a row or column header gives.\n const rowCount = GridRange.rowCount(this.ranges);\n if (!Number.isNaN(rowCount)) {\n return rowCount === 1 ? '1 row selected.' : `${rowCount} rows selected.`;\n }\n const columnCount = GridRange.columnCount(this.ranges);\n if (!Number.isNaN(columnCount)) {\n return columnCount === 1\n ? '1 column selected.'\n : `${columnCount} columns selected.`;\n }\n return this.ranges.length === 1\n ? 'Everything selected.'\n : `${this.ranges.length} selection ranges selected.`;\n }\n\n isCellSelected(column: VisibleIndex, row: VisibleIndex): boolean {\n for (let i = 0; i < this.ranges.length; i += 1) {\n if (this.ranges[i].containsCell(column, row)) {\n return true;\n }\n }\n return false;\n }\n\n isRowSelected(row: VisibleIndex): boolean {\n const { columnCount } = this.getModel();\n for (let i = 0; i < this.ranges.length; i += 1) {\n const range = this.ranges[i];\n // A range covers the whole row when it contains both column endpoints\n // at `row` — `GridRange` is a contiguous rectangle, so hitting both\n // ends implies spanning the entire axis.\n if (\n range.containsCell(0, row) &&\n range.containsCell(columnCount - 1, row)\n ) {\n return true;\n }\n }\n return false;\n }\n\n isColumnSelected(column: VisibleIndex): boolean {\n const { rowCount } = this.getModel();\n for (let i = 0; i < this.ranges.length; i += 1) {\n const range = this.ranges[i];\n if (\n range.containsCell(column, 0) &&\n range.containsCell(column, rowCount - 1)\n ) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Checks if all ranges are within the bounds of the grid model.\n * @returns True if all ranges are within bounds, false otherwise.\n */\n isInBounds(): boolean {\n const { columnCount, rowCount } = this.getModel();\n for (let i = 0; i < this.ranges.length; i += 1) {\n const range = this.ranges[i];\n if (\n (range.endColumn != null && range.endColumn >= columnCount) ||\n (range.endRow != null && range.endRow >= rowCount)\n ) {\n return false;\n }\n }\n return true;\n }\n\n toRanges(): readonly GridRange[] {\n return this.ranges;\n }\n\n getColumnTickRanges(): readonly BoundedAxisRange[] {\n if (this.cachedColumnTickRanges !== undefined) {\n return this.cachedColumnTickRanges;\n }\n const raw: BoundedAxisRange[] = [];\n for (let i = 0; i < this.ranges.length; i += 1) {\n const { startColumn, endColumn } = this.ranges[i];\n if (startColumn != null && endColumn != null) {\n raw.push([startColumn, endColumn]);\n }\n }\n raw.sort(GridUtils.compareRanges);\n this.cachedColumnTickRanges = GridUtils.mergeSortedRanges(raw);\n return this.cachedColumnTickRanges;\n }\n\n getRowTickRanges(): readonly BoundedAxisRange[] {\n if (this.cachedRowTickRanges !== undefined) {\n return this.cachedRowTickRanges;\n }\n const raw: BoundedAxisRange[] = [];\n for (let i = 0; i < this.ranges.length; i += 1) {\n const { startRow, endRow } = this.ranges[i];\n if (startRow != null && endRow != null) {\n raw.push([startRow, endRow]);\n }\n }\n raw.sort(GridUtils.compareRanges);\n this.cachedRowTickRanges = GridUtils.mergeSortedRanges(raw);\n return this.cachedRowTickRanges;\n }\n\n private cachedColumnTickRanges: readonly BoundedAxisRange[] | undefined;\n\n private cachedRowTickRanges: readonly BoundedAxisRange[] | undefined;\n\n withCommittedRanges(\n ranges: readonly GridRange[],\n anchor?: { row: GridRangeIndex; column: GridRangeIndex }\n ): RangedSelection {\n const result =\n ranges === this.ranges\n ? this\n : this.copyWith({\n ranges,\n gestureStart: { row: null, column: null },\n });\n if (anchor === undefined) return result;\n return result.withGestureAnchor(anchor.row, anchor.column);\n }\n\n /**\n * Sets the gesture anchor (extend-from position for shift-click and\n * keyboard extend) to the given cell. Passing `null` for both clears it.\n */\n private withGestureAnchor(\n row: GridRangeIndex,\n column: GridRangeIndex\n ): RangedSelection {\n if (row === this.gestureStartRow && column === this.gestureStartColumn) {\n return this;\n }\n return this.copyWith({ gestureStart: { row, column } });\n }\n\n /**\n * The current `{row, column}` of the gesture anchor, or `null` if none is set.\n */\n private getGestureAnchor(): {\n row: GridRangeIndex;\n column: GridRangeIndex;\n } | null {\n if (this.gestureStartRow == null && this.gestureStartColumn == null) {\n return null;\n }\n return { row: this.gestureStartRow, column: this.gestureStartColumn };\n }\n\n selectAll(): RangedSelection {\n const { rowCount } = this.getModel();\n return this.withCommittedRanges([\n new GridRange(null, 0, null, rowCount - 1),\n ]);\n }\n\n getNextCursorInDirection(\n current: { row: GridRangeIndex; column: GridRangeIndex },\n direction: SELECTION_DIRECTION\n ): { row: GridRangeIndex; column: GridRangeIndex } | null {\n const { columnCount, rowCount } = this.getModel();\n return nextCursorInRanges(this.ranges, current, direction, {\n columnCount,\n rowCount,\n });\n }\n\n private getCursorLandingCell(): {\n row: GridRangeIndex;\n column: GridRangeIndex;\n } | null {\n const { columnCount, rowCount } = this.getModel();\n return cursorLandingCellForRanges(this.ranges, { columnCount, rowCount });\n }\n\n withCursor(\n row: VisibleIndex | null,\n column: VisibleIndex | null\n ): RangedSelection {\n if (row === this.cursorRow && column === this.cursorColumn) return this;\n return this.copyWith({ cursor: { row, column } });\n }\n\n withSelectionEnd(\n row: VisibleIndex | null,\n column: VisibleIndex | null\n ): RangedSelection {\n if (row === this.selectionEndRow && column === this.selectionEndColumn) {\n return this;\n }\n return this.copyWith({ selectionEnd: { row, column } });\n }\n\n withGestureExtend(\n cursor: { row: GridRangeIndex; column: GridRangeIndex },\n opts: GestureExtendOptions\n ): RangedSelection {\n const { newRanges, trimBefore, resetAnchor } = computeGestureExtend(\n this.ranges,\n this.getGestureAnchor(),\n cursor,\n opts\n );\n // Trim is a no-op wrapper for RangedSelection when `newRanges` already\n // reflects the single-remaining-range shape returned by computeGestureExtend,\n // but call it explicitly so anchor / other state stays consistent with the\n // existing shift-click path.\n const base = trimBefore ? this.trimmed() : this;\n let result: RangedSelection =\n newRanges === base.ranges ? base : base.copyWith({ ranges: newRanges });\n if (resetAnchor) {\n result = result.withGestureAnchor(cursor.row, cursor.column);\n }\n return result;\n }\n\n commitGesture(\n lastCommitted: Selection,\n opts: CommitGestureOptions\n ): RangedSelection {\n const { autoSelectRow, settle = true } = opts;\n const selectedRanges = this.ranges;\n // lastCommitted is always a RangedSelection when this method is called\n assertIsRangedSelection(lastCommitted);\n const lastRanges = lastCommitted.toRanges();\n\n if (!settle) {\n // Mouse-down: leave ranges as-is so the drag can grow the last range.\n // Deselect / hole-punch / consolidation run on mouse-up.\n return withCommittedCursor(this, this.getCursorLandingCell(), opts);\n }\n\n if (\n opts.allowDeselect !== false &&\n selectedRanges.length === 1 &&\n (autoSelectRow\n ? GridRange.rowCount(selectedRanges) === 1\n : GridRange.cellCount(selectedRanges) === 1) &&\n GridRange.rangeArraysEqual(selectedRanges, lastRanges)\n ) {\n return withCommittedCursor(\n this.copyWith({ ranges: EMPTY_ARRAY }),\n this.getCursorLandingCell(),\n opts\n );\n }\n\n let newRanges = selectedRanges.slice();\n if (newRanges.length > 1) {\n const lastRange = newRanges[newRanges.length - 1];\n for (let i = 0; i < newRanges.length - 1; i += 1) {\n if (newRanges[i].contains(lastRange)) {\n const remainder = newRanges[i].subtract(lastRange);\n newRanges.pop();\n newRanges.splice(i, 1);\n newRanges = newRanges.concat(remainder);\n break;\n }\n }\n newRanges = GridRange.consolidate(newRanges);\n }\n\n const changed =\n newRanges.length !== selectedRanges.length ||\n newRanges.some((r, i) => !r.equals(selectedRanges[i]));\n return withCommittedCursor(\n changed ? this.copyWith({ ranges: newRanges }) : this,\n this.getCursorLandingCell(),\n opts\n );\n }\n\n clear(): RangedSelection {\n return this.copyWith({\n ranges: EMPTY_ARRAY,\n gestureStart: { row: null, column: null },\n selectionEnd: { row: null, column: null },\n });\n }\n\n trimmed(): RangedSelection {\n if (this.ranges.length > 0) {\n return this.copyWith({\n ranges: this.ranges.slice(this.ranges.length - 1),\n });\n }\n return this;\n }\n\n truncate(maxRows: number): RangedSelection {\n let rowCount = GridRange.rowCount(this.ranges);\n if (rowCount <= maxRows) return this;\n const ranges = [...this.ranges];\n while (rowCount > maxRows) {\n const lastRow = ranges.pop();\n // should never occur, sanity check\n assertNotNull(lastRow, 'Selected ranges should not be empty');\n const lastRowSize = GridRange.rowCount([lastRow]);\n // should never occur, sanity check\n assertNotNaN(lastRowSize, 'Selected ranges should not be unbounded');\n if (rowCount - lastRowSize < maxRows) {\n ranges.push(\n new GridRange(\n lastRow.startColumn,\n lastRow.startRow,\n lastRow.endColumn,\n (lastRow.endRow ?? 0) - (rowCount - maxRows)\n )\n );\n break;\n }\n rowCount -= lastRowSize;\n }\n return this.copyWith({ ranges });\n }\n}\n\nexport function isRangedSelection(\n selection: Selection\n): selection is RangedSelection {\n return selection instanceof RangedSelection;\n}\n\nexport function assertIsRangedSelection(\n selection: Selection\n): asserts selection is RangedSelection {\n if (!(selection instanceof RangedSelection)) {\n throw new Error(\n `Expected a RangedSelection but got ${selection.constructor.name}`\n );\n }\n}\n\n/**\n * Returns `selection.toRanges()` when `selection` is a `RangedSelection`,\n * otherwise `EMPTY_ARRAY`. Handy for consumers that only care about the\n * range-form projection of a selection (e.g. legacy `selectedRanges`\n * callbacks) and want a stable empty array for keyed / null selections.\n */\nexport function selectionToRanges(\n selection: Selection | null | undefined\n): readonly GridRange[] {\n return selection != null && isRangedSelection(selection)\n ? selection.toRanges()\n : EMPTY_ARRAY;\n}\n\nexport default RangedSelection;\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import type GridRange from './GridRange';
|
|
2
|
+
import type { GridRangeIndex, SELECTION_DIRECTION } from './GridRange';
|
|
3
|
+
import type GridModel from './GridModel';
|
|
4
|
+
import type { VisibleIndex } from './GridMetrics';
|
|
5
|
+
import type { BoundedAxisRange } from './GridAxisRange';
|
|
6
|
+
/** Provides current model data to Selection instances without holding a stale reference. */
|
|
7
|
+
export type GetModel = () => GridModel;
|
|
8
|
+
/**
|
|
9
|
+
* Immutable value object representing the current selection state of the grid.
|
|
10
|
+
* Mutations return new instances; Grid stores the result in React state.
|
|
11
|
+
*
|
|
12
|
+
* Composed from five sub-interfaces:
|
|
13
|
+
* - `SelectionQueries` — read-only inspection.
|
|
14
|
+
* - `SelectionTransforms` — immutable transforms with no external dependencies.
|
|
15
|
+
* - `ProgrammaticSelection` — programmatic write path (`Grid.setSelectedRanges`).
|
|
16
|
+
* - `MouseSelection` — mouse-driven gestures (click, shift-click, drag).
|
|
17
|
+
* - `KeyboardSelection` — keyboard-driven queries (Tab/Enter advance, cursor
|
|
18
|
+
* landing after commit).
|
|
19
|
+
*/
|
|
20
|
+
export interface Selection extends SelectionQueries, SelectionTransforms, ProgrammaticSelection, MouseSelection, KeyboardSelection {
|
|
21
|
+
}
|
|
22
|
+
/** Read-only inspection of a `Selection`. Every method is side-effect-free. */
|
|
23
|
+
export interface SelectionQueries {
|
|
24
|
+
/** True when the selection contains no cells and no in-progress gesture. */
|
|
25
|
+
isEmpty: () => boolean;
|
|
26
|
+
/** True when `(column, row)` is part of the selection. */
|
|
27
|
+
isCellSelected: (column: VisibleIndex, row: VisibleIndex) => boolean;
|
|
28
|
+
/** True when the entire row is part of the selection. */
|
|
29
|
+
isRowSelected: (row: VisibleIndex) => boolean;
|
|
30
|
+
/** True when the entire column is part of the selection. */
|
|
31
|
+
isColumnSelected: (column: VisibleIndex) => boolean;
|
|
32
|
+
/** The focus cell's row, or `null` when there is no cursor set. */
|
|
33
|
+
readonly cursorRow: VisibleIndex | null;
|
|
34
|
+
/** The focus cell's column, or `null` when there is no cursor set. */
|
|
35
|
+
readonly cursorColumn: VisibleIndex | null;
|
|
36
|
+
/** Row of the last shift/drag endpoint, or `null` when unset. */
|
|
37
|
+
readonly selectionEndRow: VisibleIndex | null;
|
|
38
|
+
/** Column of the last shift/drag endpoint, or `null` when unset. */
|
|
39
|
+
readonly selectionEndColumn: VisibleIndex | null;
|
|
40
|
+
/** Brief human-readable summary of the selection. Used for a11y status. */
|
|
41
|
+
describe: () => string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Optional capability implemented by selections that can project onto
|
|
45
|
+
* scrollbar tick marks. Ranges are returned sorted by start and merged so
|
|
46
|
+
* consumers can iterate directly without re-normalizing per frame.
|
|
47
|
+
*/
|
|
48
|
+
export interface TickRangeSelection {
|
|
49
|
+
/**
|
|
50
|
+
* Sorted, non-overlapping column `[start, end]` pairs for scrollbar tick
|
|
51
|
+
* rendering.
|
|
52
|
+
*/
|
|
53
|
+
getColumnTickRanges: () => readonly BoundedAxisRange[];
|
|
54
|
+
/**
|
|
55
|
+
* Sorted, non-overlapping row `[start, end]` pairs for scrollbar tick
|
|
56
|
+
* rendering.
|
|
57
|
+
*/
|
|
58
|
+
getRowTickRanges: () => readonly BoundedAxisRange[];
|
|
59
|
+
}
|
|
60
|
+
export declare function isTickRangeSelection(selection: Selection): selection is Selection & TickRangeSelection;
|
|
61
|
+
/**
|
|
62
|
+
* Immutable transformations of a `Selection` that need no external context.
|
|
63
|
+
* Each method returns a new `Selection`; the receiver is never modified.
|
|
64
|
+
*/
|
|
65
|
+
export interface SelectionTransforms {
|
|
66
|
+
/** A fresh empty selection with no committed state, overlay, or anchor. */
|
|
67
|
+
clear: () => Selection;
|
|
68
|
+
/**
|
|
69
|
+
* A new selection keeping only the last committed range (for
|
|
70
|
+
* `RangedSelection`) or clearing committed keys (for `KeyedSelection`).
|
|
71
|
+
* Called by `Grid.trimSelectedRanges` immediately before shift-based
|
|
72
|
+
* extend so the anchor is preserved.
|
|
73
|
+
*/
|
|
74
|
+
trimmed: () => Selection;
|
|
75
|
+
/** A new selection covering the entire grid. */
|
|
76
|
+
selectAll: () => Selection;
|
|
77
|
+
/** A new selection containing at most `maxRows` rows. */
|
|
78
|
+
truncate: (maxRows: number) => Selection;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Programmatic write path: install a caller-supplied set of ranges as the
|
|
82
|
+
* committed selection. Used by `Grid.setSelectedRanges`, `setFocusRow`, and
|
|
83
|
+
* `moveCursorInDirection`. Distinct from gesture-driven writes, which are
|
|
84
|
+
* being reworked in the `MouseSelection` / `KeyboardSelection` interfaces.
|
|
85
|
+
*/
|
|
86
|
+
export interface ProgrammaticSelection {
|
|
87
|
+
/**
|
|
88
|
+
* Replaces the committed selection with the given ranges and clears any
|
|
89
|
+
* transient overlay state. When `anchor` is provided, sets the gesture
|
|
90
|
+
* anchor (extend-from position for shift-click and keyboard extend) to
|
|
91
|
+
* the given cell; otherwise clears it.
|
|
92
|
+
*/
|
|
93
|
+
withCommittedRanges: (ranges: readonly GridRange[], anchor?: {
|
|
94
|
+
row: GridRangeIndex;
|
|
95
|
+
column: GridRangeIndex;
|
|
96
|
+
}) => Selection;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Modifier-key-derived mode for a mouse gesture:
|
|
100
|
+
* - `replace` — plain click: clear the current selection and install a
|
|
101
|
+
* single cell at the cursor.
|
|
102
|
+
* - `add` — ctrl/meta click: keep the current selection and add a single
|
|
103
|
+
* cell at the cursor.
|
|
104
|
+
* - `extend` — shift click / drag: trim to the last range and extend it
|
|
105
|
+
* from the gesture anchor to the cursor.
|
|
106
|
+
* - `maximize` — ctrl+shift click: keep all ranges, grow the last range
|
|
107
|
+
* to include the cursor.
|
|
108
|
+
*/
|
|
109
|
+
export type GestureMode = 'replace' | 'add' | 'extend' | 'maximize';
|
|
110
|
+
/** Options for `MouseSelection.withGestureExtend`. */
|
|
111
|
+
export type GestureExtendOptions = {
|
|
112
|
+
/** How the current selection should be combined with the incoming cursor. */
|
|
113
|
+
mode: GestureMode;
|
|
114
|
+
/** Full-row selection mode (theme `autoSelectRow`). */
|
|
115
|
+
autoSelectRow: boolean;
|
|
116
|
+
/** Full-column selection mode (theme `autoSelectColumn`). */
|
|
117
|
+
autoSelectColumn: boolean;
|
|
118
|
+
};
|
|
119
|
+
/** Options for `MouseSelection.commitGesture`. */
|
|
120
|
+
export type CommitGestureOptions = {
|
|
121
|
+
/**
|
|
122
|
+
* When true, a single-row commit that repeats the previous single-row
|
|
123
|
+
* selection is treated as a deselect. Matches the `autoSelectRow` theme
|
|
124
|
+
* flag semantic.
|
|
125
|
+
*/
|
|
126
|
+
autoSelectRow: boolean;
|
|
127
|
+
/**
|
|
128
|
+
* Post-commit cursor position. When `settled` is non-empty and this
|
|
129
|
+
* cursor falls outside it, `commitGesture` substitutes a landing cell
|
|
130
|
+
* from the pre-commit selection. When `settled` is empty, this cursor
|
|
131
|
+
* is preserved on the returned selection (matches Escape semantics).
|
|
132
|
+
* Omit for no-op commits that shouldn't touch cursor.
|
|
133
|
+
*/
|
|
134
|
+
cursor?: {
|
|
135
|
+
row: GridRangeIndex;
|
|
136
|
+
column: GridRangeIndex;
|
|
137
|
+
};
|
|
138
|
+
/**
|
|
139
|
+
* When true (default), a commit whose settled ranges match the previous
|
|
140
|
+
* single-row / single-cell committed selection is treated as a deselect.
|
|
141
|
+
* This is the mouse click-to-deselect affordance. Keyboard callers pass
|
|
142
|
+
* `false` so arrowing onto an already-selected cell just moves the cursor
|
|
143
|
+
* instead of clearing the selection.
|
|
144
|
+
*/
|
|
145
|
+
allowDeselect?: boolean;
|
|
146
|
+
/**
|
|
147
|
+
* When true (default), the commit finalizes the gesture: deselect check,
|
|
148
|
+
* hole-punch on overlap, and range consolidation all run. Pass `false`
|
|
149
|
+
* from mouse-down so those steps defer to mouse-up; between them the
|
|
150
|
+
* drag can grow the last range without eagerly fragmenting the prior
|
|
151
|
+
* selection.
|
|
152
|
+
*/
|
|
153
|
+
settle?: boolean;
|
|
154
|
+
};
|
|
155
|
+
/**
|
|
156
|
+
* Mouse-driven selection updates. Both `withGestureExtend` and
|
|
157
|
+
* `commitGesture` are called by `Grid`'s mouse handlers.
|
|
158
|
+
*
|
|
159
|
+
* A gesture starts on mouse-down, may extend across drag frames, and settles
|
|
160
|
+
* on mouse-up. Each drag frame calls `withGestureExtend` to update the
|
|
161
|
+
* transient overlay; `commitGesture` folds the overlay into the committed
|
|
162
|
+
* selection.
|
|
163
|
+
*/
|
|
164
|
+
export interface MouseSelection {
|
|
165
|
+
/**
|
|
166
|
+
* Applies a mouse gesture that moves the selection to `cursor` per `opts`.
|
|
167
|
+
* `mode` chooses replace / add / extend / maximize semantics based on the
|
|
168
|
+
* modifier keys the caller observed.
|
|
169
|
+
*
|
|
170
|
+
* Returns a transient overlay-updated selection. Caller controls when to
|
|
171
|
+
* `commitGesture` — mouse handlers commit on mouse-up only; a plain click
|
|
172
|
+
* commits immediately.
|
|
173
|
+
*/
|
|
174
|
+
withGestureExtend: (cursor: {
|
|
175
|
+
row: GridRangeIndex;
|
|
176
|
+
column: GridRangeIndex;
|
|
177
|
+
}, opts: GestureExtendOptions) => Selection;
|
|
178
|
+
/**
|
|
179
|
+
* Settles the current transient overlay into the committed selection.
|
|
180
|
+
* Handles consolidation, deselect-on-reclick, and subtract logic. Returns
|
|
181
|
+
* identity (`this`) when there is nothing to commit.
|
|
182
|
+
*
|
|
183
|
+
* `lastCommitted` is the selection state as it was BEFORE the current
|
|
184
|
+
* gesture began. Grid pins this in state at gesture-start so the
|
|
185
|
+
* deselect-on-reclick comparison stays stable across drag frames.
|
|
186
|
+
*/
|
|
187
|
+
commitGesture: (lastCommitted: Selection, opts: CommitGestureOptions) => Selection;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Keyboard-driven selection queries. Grid's key handlers use these to advance
|
|
191
|
+
* the cursor within the current selection (Tab/Enter) and to place the cursor
|
|
192
|
+
* after a commit or programmatic install.
|
|
193
|
+
*/
|
|
194
|
+
export interface KeyboardSelection {
|
|
195
|
+
/**
|
|
196
|
+
* Returns the next cursor cell in `direction` starting from `current`.
|
|
197
|
+
* When the selection is empty or has exactly one cell, walks the whole
|
|
198
|
+
* grid (wrapping at edges) so a lone Tab still moves the cursor.
|
|
199
|
+
* Otherwise cycles through the currently selected ranges.
|
|
200
|
+
*/
|
|
201
|
+
getNextCursorInDirection: (current: {
|
|
202
|
+
row: GridRangeIndex;
|
|
203
|
+
column: GridRangeIndex;
|
|
204
|
+
}, direction: SELECTION_DIRECTION) => {
|
|
205
|
+
row: GridRangeIndex;
|
|
206
|
+
column: GridRangeIndex;
|
|
207
|
+
} | null;
|
|
208
|
+
/**
|
|
209
|
+
* A new selection with the cursor set to `(column, row)`. Passing `null`
|
|
210
|
+
* for both clears the cursor. Non-cursor state (ranges, keys, anchor,
|
|
211
|
+
* selection endpoint) is preserved.
|
|
212
|
+
*/
|
|
213
|
+
withCursor: (row: VisibleIndex | null, column: VisibleIndex | null) => Selection;
|
|
214
|
+
/**
|
|
215
|
+
* A new selection with the shift/drag endpoint set to `(column, row)`.
|
|
216
|
+
* Passing `null` for both clears the endpoint. Non-endpoint state
|
|
217
|
+
* (ranges, keys, anchor, cursor) is preserved.
|
|
218
|
+
*/
|
|
219
|
+
withSelectionEnd: (row: VisibleIndex | null, column: VisibleIndex | null) => Selection;
|
|
220
|
+
}
|
|
221
|
+
//# sourceMappingURL=Selection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Selection.d.ts","sourceRoot":"","sources":["../src/Selection.ts"],"names":[],"mappings":"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"}
|