@deephaven/grid 1.27.5-alpha-nodehttp2-config2.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.
Files changed (55) hide show
  1. package/dist/Grid.d.ts +102 -43
  2. package/dist/Grid.d.ts.map +1 -1
  3. package/dist/Grid.js +442 -390
  4. package/dist/Grid.js.map +1 -1
  5. package/dist/GridA11yFallback.d.ts +26 -0
  6. package/dist/GridA11yFallback.d.ts.map +1 -0
  7. package/dist/GridA11yFallback.js +115 -0
  8. package/dist/GridA11yFallback.js.map +1 -0
  9. package/dist/GridA11yUtils.d.ts +89 -0
  10. package/dist/GridA11yUtils.d.ts.map +1 -0
  11. package/dist/GridA11yUtils.js +321 -0
  12. package/dist/GridA11yUtils.js.map +1 -0
  13. package/dist/GridRenderer.d.ts +9 -0
  14. package/dist/GridRenderer.d.ts.map +1 -1
  15. package/dist/GridRenderer.js +187 -39
  16. package/dist/GridRenderer.js.map +1 -1
  17. package/dist/GridRendererTypes.d.ts +3 -4
  18. package/dist/GridRendererTypes.d.ts.map +1 -1
  19. package/dist/GridRendererTypes.js.map +1 -1
  20. package/dist/GridSelectionUtils.d.ts +98 -0
  21. package/dist/GridSelectionUtils.d.ts.map +1 -0
  22. package/dist/GridSelectionUtils.js +180 -0
  23. package/dist/GridSelectionUtils.js.map +1 -0
  24. package/dist/RangedSelection.d.ts +120 -0
  25. package/dist/RangedSelection.d.ts.map +1 -0
  26. package/dist/RangedSelection.js +375 -0
  27. package/dist/RangedSelection.js.map +1 -0
  28. package/dist/Selection.d.ts +221 -0
  29. package/dist/Selection.d.ts.map +1 -0
  30. package/dist/Selection.js +71 -0
  31. package/dist/Selection.js.map +1 -0
  32. package/dist/index.d.ts +6 -0
  33. package/dist/index.d.ts.map +1 -1
  34. package/dist/index.js +6 -0
  35. package/dist/index.js.map +1 -1
  36. package/dist/key-handlers/EditKeyHandler.js +3 -3
  37. package/dist/key-handlers/EditKeyHandler.js.map +1 -1
  38. package/dist/key-handlers/SelectionKeyHandler.d.ts +1 -0
  39. package/dist/key-handlers/SelectionKeyHandler.d.ts.map +1 -1
  40. package/dist/key-handlers/SelectionKeyHandler.js +144 -138
  41. package/dist/key-handlers/SelectionKeyHandler.js.map +1 -1
  42. package/dist/key-handlers/TreeKeyHandler.d.ts.map +1 -1
  43. package/dist/key-handlers/TreeKeyHandler.js +6 -3
  44. package/dist/key-handlers/TreeKeyHandler.js.map +1 -1
  45. package/dist/mouse-handlers/GridRowTreeMouseHandler.d.ts +1 -0
  46. package/dist/mouse-handlers/GridRowTreeMouseHandler.d.ts.map +1 -1
  47. package/dist/mouse-handlers/GridRowTreeMouseHandler.js +7 -0
  48. package/dist/mouse-handlers/GridRowTreeMouseHandler.js.map +1 -1
  49. package/dist/mouse-handlers/GridSelectionMouseHandler.d.ts +0 -9
  50. package/dist/mouse-handlers/GridSelectionMouseHandler.d.ts.map +1 -1
  51. package/dist/mouse-handlers/GridSelectionMouseHandler.js +41 -39
  52. package/dist/mouse-handlers/GridSelectionMouseHandler.js.map +1 -1
  53. package/dist/mouse-handlers/GridTokenMouseHandler.js +4 -1
  54. package/dist/mouse-handlers/GridTokenMouseHandler.js.map +1 -1
  55. 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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"}