@dxos/lit-grid 0.6.12-staging.0b4bb48 → 0.6.12-staging.e11e696

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,20 @@
1
1
  // packages/ui/lit-grid/src/dx-grid.ts
2
- import { LitElement, html } from "lit";
3
- import { customElement, state, property, eventOptions } from "lit/decorators.js";
4
- import { ref, createRef } from "lit/directives/ref.js";
2
+ import { LitElement as LitElement2, html as html2, nothing } from "lit";
3
+ import { customElement as customElement2, state, property as property2, eventOptions } from "lit/decorators.js";
4
+ import { ref as ref2, createRef } from "lit/directives/ref.js";
5
+ import { styleMap } from "lit/directives/style-map.js";
6
+
7
+ // packages/ui/lit-grid/src/dx-grid-axis-resize-handle.ts
8
+ import { draggable } from "@atlaskit/pragmatic-drag-and-drop/element/adapter";
9
+ import { disableNativeDragPreview } from "@atlaskit/pragmatic-drag-and-drop/element/disable-native-drag-preview";
10
+ import { preventUnhandled } from "@atlaskit/pragmatic-drag-and-drop/prevent-unhandled";
11
+ import { html, LitElement } from "lit";
12
+ import { customElement, property } from "lit/decorators.js";
13
+ import { ref } from "lit/directives/ref.js";
14
+
15
+ // packages/ui/lit-grid/src/util.ts
16
+ var separator = ",";
17
+ var toCellIndex = (cellCoords) => `${cellCoords.col}${separator}${cellCoords.row}`;
5
18
 
6
19
  // packages/ui/lit-grid/src/types.ts
7
20
  var DxAxisResize = class extends Event {
@@ -12,35 +25,177 @@ var DxAxisResize = class extends Event {
12
25
  this.size = props.size;
13
26
  }
14
27
  };
28
+ var DxAxisResizeInternal = class extends Event {
29
+ constructor(props) {
30
+ super("dx-axis-resize-internal", {
31
+ composed: true,
32
+ bubbles: true
33
+ });
34
+ this.axis = props.axis;
35
+ this.index = props.index;
36
+ this.size = props.size;
37
+ this.delta = props.delta;
38
+ this.state = props.state;
39
+ }
40
+ };
41
+ var DxEditRequest = class extends Event {
42
+ constructor(props) {
43
+ super("dx-edit-request");
44
+ this.cellIndex = props.cellIndex;
45
+ this.cellBox = props.cellBox;
46
+ this.initialContent = props.initialContent;
47
+ }
48
+ };
49
+ var DxGridCellsSelect = class extends Event {
50
+ constructor({ start, end }) {
51
+ super("dx-grid-cells-select");
52
+ this.start = toCellIndex(start);
53
+ this.end = toCellIndex(end);
54
+ this.minCol = Math.min(start.col, end.col);
55
+ this.maxCol = Math.max(start.col, end.col);
56
+ this.minRow = Math.min(start.row, end.row);
57
+ this.maxRow = Math.max(start.row, end.row);
58
+ }
59
+ };
15
60
 
16
- // packages/ui/lit-grid/src/dx-grid.ts
61
+ // packages/ui/lit-grid/src/dx-grid-axis-resize-handle.ts
17
62
  function _ts_decorate(decorators, target, key, desc) {
18
63
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
19
64
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
20
65
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
21
66
  return c > 3 && r && Object.defineProperty(target, key, r), r;
22
67
  }
68
+ var DxGridAxisResizeHandle = class extends LitElement {
69
+ constructor() {
70
+ super(...arguments);
71
+ this.axis = "row";
72
+ this.index = "-1";
73
+ this.size = 128;
74
+ this.dragStartSize = 128;
75
+ this.cleanup = null;
76
+ }
77
+ render() {
78
+ return html`<button class="dx-grid__resize-handle" ${ref(this.mount)}>
79
+ <span class="sr-only">Resize</span>
80
+ </button>`;
81
+ }
82
+ dispatchResize(location, state2) {
83
+ const client = this.axis === "row" ? "clientY" : "clientX";
84
+ const event = new DxAxisResizeInternal({
85
+ axis: this.axis,
86
+ size: this.dragStartSize,
87
+ index: this.index,
88
+ delta: location.current.input[client] - location.initial.input[client],
89
+ state: state2
90
+ });
91
+ this.dispatchEvent(event);
92
+ }
93
+ mount(element) {
94
+ this.cleanup?.();
95
+ const host = this;
96
+ if (element) {
97
+ this.cleanup = draggable({
98
+ element,
99
+ onGenerateDragPreview: ({ nativeSetDragImage }) => {
100
+ disableNativeDragPreview({
101
+ nativeSetDragImage
102
+ });
103
+ preventUnhandled.start();
104
+ },
105
+ onDragStart() {
106
+ host.dragStartSize = host.size;
107
+ },
108
+ onDrag({ location }) {
109
+ host.dispatchResize(location, "dragging");
110
+ },
111
+ onDrop({ location }) {
112
+ host.dispatchResize(location, "dropped");
113
+ }
114
+ });
115
+ }
116
+ }
117
+ disconnectedCallback() {
118
+ super.disconnectedCallback();
119
+ this.cleanup?.();
120
+ }
121
+ createRenderRoot() {
122
+ return this;
123
+ }
124
+ };
125
+ _ts_decorate([
126
+ property({
127
+ type: String
128
+ })
129
+ ], DxGridAxisResizeHandle.prototype, "axis", void 0);
130
+ _ts_decorate([
131
+ property({
132
+ type: String
133
+ })
134
+ ], DxGridAxisResizeHandle.prototype, "index", void 0);
135
+ _ts_decorate([
136
+ property({
137
+ type: Number
138
+ })
139
+ ], DxGridAxisResizeHandle.prototype, "size", void 0);
140
+ DxGridAxisResizeHandle = _ts_decorate([
141
+ customElement("dx-grid-axis-resize-handle")
142
+ ], DxGridAxisResizeHandle);
143
+
144
+ // packages/ui/lit-grid/src/dx-grid.ts
145
+ function _ts_decorate2(decorators, target, key, desc) {
146
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
147
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
148
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
149
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
150
+ }
23
151
  var gap = 1;
24
- var resizeTolerance = 8;
152
+ var resizeTolerance = 1;
25
153
  var overscanCol = 1;
26
154
  var overscanRow = 1;
27
155
  var sizeColMin = 32;
28
156
  var sizeColMax = 1024;
29
157
  var sizeRowMin = 16;
30
158
  var sizeRowMax = 1024;
31
- var separator = ",";
32
159
  var colToA1Notation = (col) => {
33
160
  return (col >= 26 ? String.fromCharCode("A".charCodeAt(0) + Math.floor(col / 26) - 1) : "") + String.fromCharCode("A".charCodeAt(0) + col % 26);
34
161
  };
35
162
  var rowToA1Notation = (row) => {
36
163
  return `${row + 1}`;
37
164
  };
165
+ var closestAction = (target) => {
166
+ const actionEl = target?.closest("[data-dx-grid-action]") ?? null;
167
+ return {
168
+ actionEl,
169
+ action: actionEl?.getAttribute("data-dx-grid-action") ?? null
170
+ };
171
+ };
172
+ var closestCell = (target, actionEl) => {
173
+ let cellElement = actionEl;
174
+ if (!cellElement) {
175
+ const { action, actionEl: actionEl2 } = closestAction(target);
176
+ if (action === "cell") {
177
+ cellElement = actionEl2;
178
+ }
179
+ }
180
+ if (cellElement) {
181
+ const col = parseInt(cellElement.getAttribute("aria-colindex") ?? "never");
182
+ const row = parseInt(cellElement.getAttribute("aria-rowindex") ?? "never");
183
+ return {
184
+ col,
185
+ row
186
+ };
187
+ } else {
188
+ return null;
189
+ }
190
+ };
191
+ var isSameCell = (a, b) => a && b && Number.isFinite(a.col) && Number.isFinite(a.row) && a.col === b.col && a.row === b.row;
38
192
  var localChId = (c0) => `ch--${c0}`;
39
193
  var localRhId = (r0) => `rh--${r0}`;
40
194
  var getPage = (axis, event) => axis === "col" ? event.pageX : event.pageY;
41
- var DxGrid = class extends LitElement {
195
+ var DxGrid = class extends LitElement2 {
42
196
  constructor() {
43
- super(...arguments);
197
+ super();
198
+ this.gridId = "default-grid-id";
44
199
  this.rowDefault = {
45
200
  size: 32
46
201
  };
@@ -49,6 +204,15 @@ var DxGrid = class extends LitElement {
49
204
  };
50
205
  this.rows = {};
51
206
  this.columns = {};
207
+ this.initialCells = {};
208
+ this.mode = "browse";
209
+ this.limitColumns = Infinity;
210
+ this.limitRows = Infinity;
211
+ /**
212
+ * When this function is defined, it is used first to try to get a value for a cell, and otherwise will fall back
213
+ * to `cells`.
214
+ */
215
+ this.getCells = null;
52
216
  this.cells = {};
53
217
  //
54
218
  // `pos`, short for ‘position’, is the position in pixels of the viewport from the origin.
@@ -86,55 +250,81 @@ var DxGrid = class extends LitElement {
86
250
  this.templateColumns = `${this.colSize(0)}px`;
87
251
  this.templateRows = `${this.rowSize(0)}px`;
88
252
  //
89
- // Resize state and handlers
253
+ // Focus, selection, and resize states
90
254
  //
255
+ this.pointer = null;
91
256
  this.colSizes = {};
92
257
  this.rowSizes = {};
93
- this.resizing = null;
258
+ this.focusActive = false;
259
+ this.focusedCell = {
260
+ col: 0,
261
+ row: 0
262
+ };
263
+ this.selectionStart = {
264
+ col: 0,
265
+ row: 0
266
+ };
267
+ this.selectionEnd = {
268
+ col: 0,
269
+ row: 0
270
+ };
271
+ //
272
+ // Limits
273
+ //
274
+ this.intrinsicInlineSize = Infinity;
275
+ this.intrinsicBlockSize = Infinity;
94
276
  this.handlePointerDown = (event) => {
95
- const actionEl = event.target?.closest("[data-dx-grid-action]");
96
- const action = actionEl?.getAttribute("data-dx-grid-action");
97
- if (action) {
98
- if (action.startsWith("resize")) {
99
- const [resize, index] = action.split(",");
100
- const [_, axis] = resize.split("-");
101
- this.resizing = {
102
- axis,
103
- size: axis === "col" ? this.colSize(index) : this.rowSize(index),
104
- page: getPage(axis, event),
105
- index
106
- };
277
+ if (event.isPrimary) {
278
+ const { action, actionEl } = closestAction(event.target);
279
+ if (action) {
280
+ if (action.startsWith("resize") && this.mode === "browse") {
281
+ const [resize, index] = action.split(",");
282
+ const [_, axis] = resize.split("-");
283
+ this.pointer = {
284
+ state: "resizing",
285
+ axis,
286
+ size: axis === "col" ? this.colSize(index) : this.rowSize(index),
287
+ page: getPage(axis, event),
288
+ index
289
+ };
290
+ } else if (action === "cell") {
291
+ const cellCoords = closestCell(event.target, actionEl);
292
+ if (cellCoords) {
293
+ this.pointer = {
294
+ state: "selecting"
295
+ };
296
+ this.selectionStart = cellCoords;
297
+ }
298
+ if (this.mode === "edit") {
299
+ event.preventDefault();
300
+ } else {
301
+ if (this.focusActive && isSameCell(this.focusedCell, cellCoords)) {
302
+ this.dispatchEditRequest();
303
+ }
304
+ }
305
+ }
107
306
  }
108
307
  }
109
308
  };
110
- this.handlePointerUp = (_event) => {
111
- if (this.resizing) {
112
- const resizeEvent = new DxAxisResize({
113
- axis: this.resizing.axis,
114
- index: this.resizing.index,
115
- size: this[this.resizing.axis === "col" ? "colSize" : "rowSize"](this.resizing.index)
116
- });
117
- this.dispatchEvent(resizeEvent);
118
- this.resizing = null;
309
+ this.handlePointerUp = (event) => {
310
+ if (this.pointer?.state === "resizing") {
311
+ } else {
312
+ const cell = closestCell(event.target);
313
+ if (cell) {
314
+ this.selectionEnd = cell;
315
+ this.dispatchEvent(new DxGridCellsSelect({
316
+ start: this.selectionStart,
317
+ end: this.selectionEnd
318
+ }));
319
+ }
119
320
  }
321
+ this.pointer = null;
120
322
  };
121
323
  this.handlePointerMove = (event) => {
122
- if (this.resizing) {
123
- const delta = getPage(this.resizing.axis, event) - this.resizing.page;
124
- if (this.resizing.axis === "col") {
125
- const nextSize = Math.max(sizeColMin, Math.min(sizeColMax, this.resizing.size + delta));
126
- this.colSizes = {
127
- ...this.colSizes,
128
- [this.resizing.index]: nextSize
129
- };
130
- this.updateVisInline();
131
- } else {
132
- const nextSize = Math.max(sizeRowMin, Math.min(sizeRowMax, this.resizing.size + delta));
133
- this.rowSizes = {
134
- ...this.rowSizes,
135
- [this.resizing.index]: nextSize
136
- };
137
- this.updateVisBlock();
324
+ if (this.pointer?.state === "selecting") {
325
+ const cell = closestCell(event.target);
326
+ if (cell && (cell.col !== this.selectionEnd.col || cell.row !== this.selectionEnd.row)) {
327
+ this.selectionEnd = cell;
138
328
  }
139
329
  }
140
330
  };
@@ -150,23 +340,96 @@ var DxGrid = class extends LitElement {
150
340
  this.sizeInline = inlineSize;
151
341
  this.sizeBlock = blockSize;
152
342
  this.updateVis();
343
+ queueMicrotask(() => this.updatePos());
153
344
  }
154
345
  });
155
346
  this.viewportRef = createRef();
156
- this.handleWheel = ({ deltaX, deltaY }) => {
157
- this.posInline = Math.max(0, this.posInline + deltaX);
158
- this.posBlock = Math.max(0, this.posBlock + deltaY);
347
+ this.maybeUpdateVis = () => {
159
348
  if (this.posInline >= this.binInlineMin && this.posInline < this.binInlineMax && this.posBlock >= this.binBlockMin && this.posBlock < this.binBlockMax) {
160
349
  } else {
161
350
  this.updateVis();
162
351
  }
163
352
  };
164
- // Focus handlers
165
- this.focusedCell = {
166
- col: 0,
167
- row: 0
353
+ this.handleWheel = ({ deltaX, deltaY }) => {
354
+ if (this.mode === "browse") {
355
+ this.updatePos(this.posInline + deltaX, this.posBlock + deltaY);
356
+ }
168
357
  };
169
- this.focusActive = false;
358
+ this.addEventListener("dx-axis-resize-internal", this.handleAxisResizeInternal);
359
+ this.addEventListener("wheel", this.handleWheel, {
360
+ passive: true
361
+ });
362
+ this.addEventListener("pointerdown", this.handlePointerDown);
363
+ this.addEventListener("pointermove", this.handlePointerMove);
364
+ this.addEventListener("pointerup", this.handlePointerUp);
365
+ this.addEventListener("pointerleave", this.handlePointerUp);
366
+ this.addEventListener("focus", this.handleFocus, {
367
+ capture: true
368
+ });
369
+ this.addEventListener("blur", this.handleBlur, {
370
+ capture: true
371
+ });
372
+ this.addEventListener("keydown", this.handleKeydown);
373
+ }
374
+ //
375
+ // Primary pointer and keyboard handlers
376
+ //
377
+ dispatchEditRequest(initialContent) {
378
+ this.snapPosToFocusedCell();
379
+ queueMicrotask(() => this.dispatchEvent(new DxEditRequest({
380
+ cellIndex: toCellIndex(this.focusedCell),
381
+ cellBox: this.focusedCellBox(),
382
+ initialContent
383
+ })));
384
+ }
385
+ handleKeydown(event) {
386
+ if (this.focusActive && this.mode === "browse") {
387
+ switch (event.key) {
388
+ case "ArrowDown":
389
+ this.focusedCell = {
390
+ ...this.focusedCell,
391
+ row: Math.min(this.limitRows - 1, this.focusedCell.row + 1)
392
+ };
393
+ break;
394
+ case "ArrowUp":
395
+ this.focusedCell = {
396
+ ...this.focusedCell,
397
+ row: Math.max(0, this.focusedCell.row - 1)
398
+ };
399
+ break;
400
+ case "ArrowRight":
401
+ this.focusedCell = {
402
+ ...this.focusedCell,
403
+ col: Math.min(this.limitColumns - 1, this.focusedCell.col + 1)
404
+ };
405
+ break;
406
+ case "ArrowLeft":
407
+ this.focusedCell = {
408
+ ...this.focusedCell,
409
+ col: Math.max(0, this.focusedCell.col - 1)
410
+ };
411
+ break;
412
+ }
413
+ switch (event.key) {
414
+ case "Enter":
415
+ this.dispatchEditRequest();
416
+ break;
417
+ default:
418
+ if (event.key.length === 1 && event.key.match(/\P{Cc}/u)) {
419
+ this.dispatchEditRequest(event.key);
420
+ }
421
+ break;
422
+ }
423
+ switch (event.key) {
424
+ case "ArrowDown":
425
+ case "ArrowUp":
426
+ case "ArrowRight":
427
+ case "ArrowLeft":
428
+ event.preventDefault();
429
+ this.snapPosToFocusedCell();
430
+ break;
431
+ }
432
+ }
170
433
  }
171
434
  //
172
435
  // Accessors
@@ -177,8 +440,38 @@ var DxGrid = class extends LitElement {
177
440
  rowSize(r) {
178
441
  return this.rowSizes?.[r] ?? this.rowDefault.size;
179
442
  }
180
- getCell(c, r) {
181
- return this.cells[`${c}${separator}${r}`];
443
+ cell(c, r) {
444
+ const index = `${c}${separator}${r}`;
445
+ return this.cells[index] ?? this.initialCells[index];
446
+ }
447
+ focusedCellBox() {
448
+ const cellElement = this.focusedCellElement();
449
+ const cellSize = {
450
+ inlineSize: this.colSize(this.focusedCell.col),
451
+ blockSize: this.rowSize(this.focusedCell.row)
452
+ };
453
+ if (!cellElement) {
454
+ return {
455
+ insetInlineStart: NaN,
456
+ insetBlockStart: NaN,
457
+ ...cellSize
458
+ };
459
+ }
460
+ const contentElement = cellElement.offsetParent;
461
+ const [_translate3d, inlineStr, blockStr] = contentElement.style.transform.split(/[()]|px,?\s?/);
462
+ const contentOffsetInline = parseFloat(inlineStr);
463
+ const contentOffsetBlock = parseFloat(blockStr);
464
+ const offsetParent = contentElement.offsetParent;
465
+ return {
466
+ insetInlineStart: cellElement.offsetLeft + contentOffsetInline + offsetParent.offsetLeft,
467
+ insetBlockStart: cellElement.offsetTop + contentOffsetBlock + offsetParent.offsetTop,
468
+ ...cellSize
469
+ };
470
+ }
471
+ updatePos(inline, block) {
472
+ this.posInline = Math.max(0, Math.min(this.intrinsicInlineSize - this.sizeInline, inline ?? this.posInline));
473
+ this.posBlock = Math.max(0, Math.min(this.intrinsicBlockSize - this.sizeBlock, block ?? this.posBlock));
474
+ this.maybeUpdateVis();
182
475
  }
183
476
  updateVisInline() {
184
477
  let colIndex = 0;
@@ -200,7 +493,7 @@ var DxGrid = class extends LitElement {
200
493
  colIndex += 1;
201
494
  pxInline += this.colSize(colIndex) + gap;
202
495
  }
203
- this.visColMax = colIndex + overscanCol;
496
+ this.visColMax = Math.min(this.limitColumns, colIndex + overscanCol);
204
497
  this.templateColumns = [
205
498
  ...Array(this.visColMax - this.visColMin)
206
499
  ].map((_, c0) => `${this.colSize(this.visColMin + c0)}px`).join(" ");
@@ -225,7 +518,7 @@ var DxGrid = class extends LitElement {
225
518
  rowIndex += 1;
226
519
  pxBlock += this.rowSize(rowIndex) + gap;
227
520
  }
228
- this.visRowMax = rowIndex + overscanRow;
521
+ this.visRowMax = Math.min(this.limitRows, rowIndex + overscanRow);
229
522
  this.templateRows = [
230
523
  ...Array(this.visRowMax - this.visRowMin)
231
524
  ].map((_, r0) => `${this.rowSize(this.visRowMin + r0)}px`).join(" ");
@@ -234,31 +527,45 @@ var DxGrid = class extends LitElement {
234
527
  this.updateVisInline();
235
528
  this.updateVisBlock();
236
529
  }
530
+ // Focus handlers
237
531
  handleFocus(event) {
238
- const target = event.target;
239
- const action = target.getAttribute("data-dx-grid-action");
240
- if (action === "cell") {
241
- const c = parseInt(target.getAttribute("aria-colindex") ?? "never");
242
- const r = parseInt(target.getAttribute("aria-rowindex") ?? "never");
243
- this.focusedCell = {
244
- col: c,
245
- row: r
246
- };
532
+ const cellCoords = closestCell(event.target);
533
+ if (cellCoords) {
534
+ this.focusedCell = cellCoords;
247
535
  this.focusActive = true;
248
536
  }
249
537
  }
250
538
  handleBlur(event) {
251
- if (!event.relatedTarget || event.relatedTarget.closest(".dx-grid__viewport") !== this.viewportRef.value) {
539
+ if (!event.relatedTarget || !event.relatedTarget.closest(`[data-grid="${this.gridId}"]`)) {
252
540
  this.focusActive = false;
253
541
  }
254
542
  }
543
+ focusedCellElement() {
544
+ return this.viewportRef.value?.querySelector(`[aria-colindex="${this.focusedCell.col}"][aria-rowindex="${this.focusedCell.row}"]`);
545
+ }
255
546
  /**
256
547
  * Moves focus to the cell with actual focus, otherwise moves focus to the viewport.
257
548
  */
258
- refocus() {
259
- (this.focusedCell.row < this.visRowMin || this.focusedCell.row > this.visRowMax || this.focusedCell.col < this.visColMin || this.focusedCell.col > this.visColMax ? this.viewportRef.value : this.viewportRef.value?.querySelector(`[aria-colindex="${this.focusedCell.col}"][aria-rowindex="${this.focusedCell.row}"]`))?.focus({
549
+ refocus(increment, delta = 1) {
550
+ switch (increment) {
551
+ case "row":
552
+ this.focusedCell = {
553
+ ...this.focusedCell,
554
+ row: this.focusedCell.row + delta
555
+ };
556
+ break;
557
+ case "col":
558
+ this.focusedCell = {
559
+ ...this.focusedCell,
560
+ col: this.focusedCell.col + delta
561
+ };
562
+ }
563
+ (this.focusedCell.row < this.visRowMin || this.focusedCell.row > this.visRowMax || this.focusedCell.col < this.visColMin || this.focusedCell.col > this.visColMax ? this.viewportRef.value : this.focusedCellElement())?.focus({
260
564
  preventScroll: true
261
565
  });
566
+ if (increment) {
567
+ this.snapPosToFocusedCell();
568
+ }
262
569
  }
263
570
  /**
264
571
  * Updates `pos` so that a cell in focus is fully within the viewport
@@ -268,7 +575,7 @@ var DxGrid = class extends LitElement {
268
575
  } else if (this.focusedCell.col > this.visColMin + overscanCol && this.focusedCell.col < this.visColMax - overscanCol - 1 && this.focusedCell.row > this.visRowMin + overscanRow && this.focusedCell.row < this.visRowMax - overscanRow - 1) {
269
576
  } else {
270
577
  if (this.focusedCell.col <= this.visColMin + overscanCol) {
271
- this.posInline = this.binInlineMin;
578
+ this.posInline = this.binInlineMin + gap;
272
579
  this.updateVisInline();
273
580
  } else if (this.focusedCell.col >= this.visColMax - overscanCol - 1) {
274
581
  const sizeSumCol = [
@@ -277,11 +584,11 @@ var DxGrid = class extends LitElement {
277
584
  acc += this.colSize(this.visColMin + overscanCol + c0) + gap;
278
585
  return acc;
279
586
  }, 0);
280
- this.posInline = this.binInlineMin + sizeSumCol + gap * 2 - this.sizeInline;
587
+ this.posInline = Math.max(0, Math.min(this.intrinsicInlineSize - this.sizeInline, this.binInlineMin + sizeSumCol + gap * 2 - this.sizeInline));
281
588
  this.updateVisInline();
282
589
  }
283
590
  if (this.focusedCell.row <= this.visRowMin + overscanRow) {
284
- this.posBlock = this.binBlockMin;
591
+ this.posBlock = this.binBlockMin + gap;
285
592
  this.updateVisBlock();
286
593
  } else if (this.focusedCell.row >= this.visRowMax - overscanRow - 1) {
287
594
  const sizeSumRow = [
@@ -290,49 +597,57 @@ var DxGrid = class extends LitElement {
290
597
  acc += this.rowSize(this.visRowMin + overscanRow + r0) + gap;
291
598
  return acc;
292
599
  }, 0);
293
- this.posBlock = this.binBlockMin + sizeSumRow + gap * 2 - this.sizeBlock;
600
+ this.posBlock = Math.max(0, Math.min(this.intrinsicBlockSize - this.sizeBlock, this.binBlockMin + sizeSumRow + gap * 2 - this.sizeBlock));
294
601
  this.updateVisBlock();
295
602
  }
296
603
  }
297
604
  }
298
- // Keyboard interactions
299
- handleKeydown(event) {
300
- if (this.focusActive) {
301
- switch (event.key) {
302
- case "ArrowDown":
303
- this.focusedCell = {
304
- ...this.focusedCell,
305
- row: this.focusedCell.row + 1
306
- };
307
- break;
308
- case "ArrowUp":
309
- this.focusedCell = {
310
- ...this.focusedCell,
311
- row: Math.max(0, this.focusedCell.row - 1)
312
- };
313
- break;
314
- case "ArrowRight":
315
- this.focusedCell = {
316
- ...this.focusedCell,
317
- col: this.focusedCell.col + 1
318
- };
319
- break;
320
- case "ArrowLeft":
321
- this.focusedCell = {
322
- ...this.focusedCell,
323
- col: Math.max(0, this.focusedCell.col - 1)
324
- };
325
- break;
326
- }
327
- switch (event.key) {
328
- case "ArrowDown":
329
- case "ArrowUp":
330
- case "ArrowRight":
331
- case "ArrowLeft":
332
- event.preventDefault();
333
- this.snapPosToFocusedCell();
334
- break;
335
- }
605
+ //
606
+ // Map scroll DOM methods to virtualized value.
607
+ //
608
+ get scrollLeft() {
609
+ return this.posInline;
610
+ }
611
+ set scrollLeft(nextValue) {
612
+ this.posInline = nextValue;
613
+ this.maybeUpdateVis();
614
+ }
615
+ get scrollTop() {
616
+ return this.posBlock;
617
+ }
618
+ set scrollTop(nextValue) {
619
+ this.posBlock = nextValue;
620
+ this.maybeUpdateVis();
621
+ }
622
+ //
623
+ // Resize handlers
624
+ //
625
+ handleAxisResizeInternal(event) {
626
+ event.stopPropagation();
627
+ const { axis, delta, size, index, type } = event;
628
+ if (axis === "col") {
629
+ const nextSize = Math.max(sizeColMin, Math.min(sizeColMax, size + delta));
630
+ this.colSizes = {
631
+ ...this.colSizes,
632
+ [index]: nextSize
633
+ };
634
+ this.updateVisInline();
635
+ this.updateIntrinsicInlineSize();
636
+ } else {
637
+ const nextSize = Math.max(sizeRowMin, Math.min(sizeRowMax, size + delta));
638
+ this.rowSizes = {
639
+ ...this.rowSizes,
640
+ [index]: nextSize
641
+ };
642
+ this.updateVisBlock();
643
+ this.updateIntrinsicBlockSize();
644
+ }
645
+ if (type === "dropped") {
646
+ this.dispatchEvent(new DxAxisResize({
647
+ axis,
648
+ index,
649
+ size: this[axis === "col" ? "colSize" : "rowSize"](index)
650
+ }));
336
651
  }
337
652
  }
338
653
  //
@@ -341,17 +656,23 @@ var DxGrid = class extends LitElement {
341
656
  render() {
342
657
  const visibleCols = this.visColMax - this.visColMin;
343
658
  const visibleRows = this.visRowMax - this.visRowMin;
344
- const offsetInline = gap + this.binInlineMin - this.posInline - this.overscanInline;
345
- const offsetBlock = gap + this.binBlockMin - this.posBlock - this.overscanBlock;
346
- return html`<div
659
+ const offsetInline = this.binInlineMin - this.posInline - this.overscanInline;
660
+ const offsetBlock = this.binBlockMin - this.posBlock - this.overscanBlock;
661
+ const selectColMin = Math.min(this.selectionStart.col, this.selectionEnd.col);
662
+ const selectColMax = Math.max(this.selectionStart.col, this.selectionEnd.col);
663
+ const selectRowMin = Math.min(this.selectionStart.row, this.selectionEnd.row);
664
+ const selectRowMax = Math.max(this.selectionStart.row, this.selectionEnd.row);
665
+ const selectVisible = selectColMin !== selectColMax || selectRowMin !== selectRowMax;
666
+ return html2`<div
347
667
  role="none"
348
668
  class="dx-grid"
349
- @pointerdown=${this.handlePointerDown}
350
- @pointerup=${this.handlePointerUp}
351
- @pointermove=${this.handlePointerMove}
352
- @focus=${this.handleFocus}
353
- @blur=${this.handleBlur}
354
- @keydown=${this.handleKeydown}
669
+ style=${styleMap({
670
+ "--dx-viewport-inline-size": Number.isFinite(this.limitColumns) ? `${this.intrinsicInlineSize}px` : "1fr",
671
+ "--dx-viewport-block-size": Number.isFinite(this.limitRows) ? `${this.intrinsicBlockSize}px` : "1fr"
672
+ })}
673
+ data-grid=${this.gridId}
674
+ data-grid-mode=${this.mode}
675
+ ?data-grid-select=${selectVisible}
355
676
  >
356
677
  <div role="none" class="dx-grid__corner"></div>
357
678
  <div role="none" class="dx-grid__columnheader">
@@ -364,15 +685,17 @@ var DxGrid = class extends LitElement {
364
685
  ...Array(visibleCols)
365
686
  ].map((_, c0) => {
366
687
  const c = this.visColMin + c0;
367
- return html`<div
688
+ return html2`<div
368
689
  role="columnheader"
369
690
  ?inert=${c < 0}
370
691
  style="block-size:${this.rowDefault.size}px;grid-column:${c0 + 1}/${c0 + 2};"
371
692
  >
372
693
  <span id=${localChId(c0)}>${colToA1Notation(c)}</span>
373
- ${(this.columns[c]?.resizeable ?? this.columnDefault.resizeable) && html`<button class="dx-grid__resize-handle" data-dx-grid-action=${`resize-col,${c}`}>
374
- <span class="sr-only">Resize</span>
375
- </button>`}
694
+ ${(this.columns[c]?.resizeable ?? this.columnDefault.resizeable) && html2`<dx-grid-axis-resize-handle
695
+ axis="col"
696
+ index=${c}
697
+ size=${this.colSize(c)}
698
+ ></dx-grid-axis-resize-handle>`}
376
699
  </div>`;
377
700
  })}
378
701
  </div>
@@ -388,16 +711,18 @@ var DxGrid = class extends LitElement {
388
711
  ...Array(visibleRows)
389
712
  ].map((_, r0) => {
390
713
  const r = this.visRowMin + r0;
391
- return html`<div role="rowheader" ?inert=${r < 0} style="grid-row:${r0 + 1}/${r0 + 2}">
714
+ return html2`<div role="rowheader" ?inert=${r < 0} style="grid-row:${r0 + 1}/${r0 + 2}">
392
715
  <span id=${localRhId(r0)}>${rowToA1Notation(r)}</span>
393
- ${(this.rows[r]?.resizeable ?? this.rowDefault.resizeable) && html`<button class="dx-grid__resize-handle" data-dx-grid-action=${`resize-row,${r}`}>
394
- <span class="sr-only">Resize</span>
395
- </button>`}
716
+ ${(this.rows[r]?.resizeable ?? this.rowDefault.resizeable) && html2`<dx-grid-axis-resize-handle
717
+ axis="row"
718
+ index=${r}
719
+ size=${this.rowSize(r)}
720
+ ></dx-grid-axis-resize-handle>`}
396
721
  </div>`;
397
722
  })}
398
723
  </div>
399
724
  </div>
400
- <div role="grid" class="dx-grid__viewport" tabindex="0" @wheel=${this.handleWheel} ${ref(this.viewportRef)}>
725
+ <div role="grid" class="dx-grid__viewport" tabindex="0" ${ref2(this.viewportRef)}>
401
726
  <div
402
727
  role="none"
403
728
  class="dx-grid__content"
@@ -411,11 +736,15 @@ var DxGrid = class extends LitElement {
411
736
  ].map((_2, r0) => {
412
737
  const c = c0 + this.visColMin;
413
738
  const r = r0 + this.visRowMin;
414
- const cell = this.getCell(c, r);
415
- return html`<div
739
+ const cell = this.cell(c, r);
740
+ const active = this.focusActive && this.focusedCell.col === c && this.focusedCell.row === r;
741
+ const selected = c >= selectColMin && c <= selectColMax && r >= selectRowMin && r <= selectRowMax;
742
+ return html2`<div
416
743
  role="gridcell"
417
744
  tabindex="0"
418
745
  ?inert=${c < 0 || r < 0}
746
+ ?aria-selected=${selected}
747
+ class=${cell || active ? (cell?.className ? cell.className + " " : "") + (active ? "dx-grid__cell--active" : "") : nothing}
419
748
  aria-rowindex=${r}
420
749
  aria-colindex=${c}
421
750
  data-dx-grid-action="cell"
@@ -437,7 +766,33 @@ var DxGrid = class extends LitElement {
437
766
  <div role="none" class="dx-grid__corner"></div>
438
767
  </div>`;
439
768
  }
769
+ updateIntrinsicInlineSize() {
770
+ this.intrinsicInlineSize = Number.isFinite(this.limitColumns) ? [
771
+ ...Array(this.limitColumns)
772
+ ].reduce((acc, _, c0) => acc + this.colSize(c0), 0) + gap * (this.limitColumns - 1) : Infinity;
773
+ }
774
+ updateIntrinsicBlockSize() {
775
+ this.intrinsicBlockSize = Number.isFinite(this.limitRows) ? [
776
+ ...Array(this.limitRows)
777
+ ].reduce((acc, _, r0) => acc + this.rowSize(r0), 0) + gap * (this.limitRows - 1) : Infinity;
778
+ }
779
+ updateIntrinsicSizes() {
780
+ this.updateIntrinsicInlineSize();
781
+ this.updateIntrinsicBlockSize();
782
+ }
440
783
  firstUpdated() {
784
+ if (this.getCells) {
785
+ this.cells = this.getCells({
786
+ start: {
787
+ col: this.visColMin,
788
+ row: this.visRowMin
789
+ },
790
+ end: {
791
+ col: this.visColMax,
792
+ row: this.visRowMax
793
+ }
794
+ });
795
+ }
441
796
  this.observer.observe(this.viewportRef.value);
442
797
  this.colSizes = Object.entries(this.columns).reduce((acc, [colId, colMeta]) => {
443
798
  if (colMeta?.size) {
@@ -451,6 +806,21 @@ var DxGrid = class extends LitElement {
451
806
  }
452
807
  return acc;
453
808
  }, {});
809
+ this.updateIntrinsicSizes();
810
+ }
811
+ willUpdate(changedProperties) {
812
+ if (this.getCells && (changedProperties.has("initialCells") || changedProperties.has("visColMin") || changedProperties.has("visColMax") || changedProperties.has("visRowMin") || changedProperties.has("visRowMax"))) {
813
+ this.cells = this.getCells({
814
+ start: {
815
+ col: this.visColMin,
816
+ row: this.visRowMin
817
+ },
818
+ end: {
819
+ col: this.visColMax,
820
+ row: this.visRowMax
821
+ }
822
+ });
823
+ }
454
824
  }
455
825
  updated(changedProperties) {
456
826
  if (this.focusActive && (changedProperties.has("visRowMin") || changedProperties.has("visColMin") || changedProperties.has("focusedCell"))) {
@@ -467,112 +837,150 @@ var DxGrid = class extends LitElement {
467
837
  return this;
468
838
  }
469
839
  };
470
- _ts_decorate([
471
- property({
840
+ _ts_decorate2([
841
+ property2({
842
+ type: String
843
+ })
844
+ ], DxGrid.prototype, "gridId", void 0);
845
+ _ts_decorate2([
846
+ property2({
472
847
  type: Object
473
848
  })
474
849
  ], DxGrid.prototype, "rowDefault", void 0);
475
- _ts_decorate([
476
- property({
850
+ _ts_decorate2([
851
+ property2({
477
852
  type: Object
478
853
  })
479
854
  ], DxGrid.prototype, "columnDefault", void 0);
480
- _ts_decorate([
481
- property({
855
+ _ts_decorate2([
856
+ property2({
482
857
  type: Object
483
858
  })
484
859
  ], DxGrid.prototype, "rows", void 0);
485
- _ts_decorate([
486
- property({
860
+ _ts_decorate2([
861
+ property2({
487
862
  type: Object
488
863
  })
489
864
  ], DxGrid.prototype, "columns", void 0);
490
- _ts_decorate([
491
- property({
865
+ _ts_decorate2([
866
+ property2({
492
867
  type: Object
493
868
  })
869
+ ], DxGrid.prototype, "initialCells", void 0);
870
+ _ts_decorate2([
871
+ property2({
872
+ type: String
873
+ })
874
+ ], DxGrid.prototype, "mode", void 0);
875
+ _ts_decorate2([
876
+ property2({
877
+ type: Number
878
+ })
879
+ ], DxGrid.prototype, "limitColumns", void 0);
880
+ _ts_decorate2([
881
+ property2({
882
+ type: Number
883
+ })
884
+ ], DxGrid.prototype, "limitRows", void 0);
885
+ _ts_decorate2([
886
+ state()
494
887
  ], DxGrid.prototype, "cells", void 0);
495
- _ts_decorate([
888
+ _ts_decorate2([
496
889
  state()
497
890
  ], DxGrid.prototype, "posInline", void 0);
498
- _ts_decorate([
891
+ _ts_decorate2([
499
892
  state()
500
893
  ], DxGrid.prototype, "posBlock", void 0);
501
- _ts_decorate([
894
+ _ts_decorate2([
502
895
  state()
503
896
  ], DxGrid.prototype, "sizeInline", void 0);
504
- _ts_decorate([
897
+ _ts_decorate2([
505
898
  state()
506
899
  ], DxGrid.prototype, "sizeBlock", void 0);
507
- _ts_decorate([
900
+ _ts_decorate2([
508
901
  state()
509
902
  ], DxGrid.prototype, "overscanInline", void 0);
510
- _ts_decorate([
903
+ _ts_decorate2([
511
904
  state()
512
905
  ], DxGrid.prototype, "overscanBlock", void 0);
513
- _ts_decorate([
906
+ _ts_decorate2([
514
907
  state()
515
908
  ], DxGrid.prototype, "binInlineMin", void 0);
516
- _ts_decorate([
909
+ _ts_decorate2([
517
910
  state()
518
911
  ], DxGrid.prototype, "binInlineMax", void 0);
519
- _ts_decorate([
912
+ _ts_decorate2([
520
913
  state()
521
914
  ], DxGrid.prototype, "binBlockMin", void 0);
522
- _ts_decorate([
915
+ _ts_decorate2([
523
916
  state()
524
917
  ], DxGrid.prototype, "binBlockMax", void 0);
525
- _ts_decorate([
918
+ _ts_decorate2([
526
919
  state()
527
920
  ], DxGrid.prototype, "visColMin", void 0);
528
- _ts_decorate([
921
+ _ts_decorate2([
529
922
  state()
530
923
  ], DxGrid.prototype, "visColMax", void 0);
531
- _ts_decorate([
924
+ _ts_decorate2([
532
925
  state()
533
926
  ], DxGrid.prototype, "visRowMin", void 0);
534
- _ts_decorate([
927
+ _ts_decorate2([
535
928
  state()
536
929
  ], DxGrid.prototype, "visRowMax", void 0);
537
- _ts_decorate([
930
+ _ts_decorate2([
538
931
  state()
539
932
  ], DxGrid.prototype, "templateColumns", void 0);
540
- _ts_decorate([
933
+ _ts_decorate2([
541
934
  state()
542
935
  ], DxGrid.prototype, "templateRows", void 0);
543
- _ts_decorate([
936
+ _ts_decorate2([
937
+ state()
938
+ ], DxGrid.prototype, "pointer", void 0);
939
+ _ts_decorate2([
544
940
  state()
545
941
  ], DxGrid.prototype, "colSizes", void 0);
546
- _ts_decorate([
942
+ _ts_decorate2([
547
943
  state()
548
944
  ], DxGrid.prototype, "rowSizes", void 0);
549
- _ts_decorate([
550
- state()
551
- ], DxGrid.prototype, "resizing", void 0);
552
- _ts_decorate([
945
+ _ts_decorate2([
553
946
  state()
554
- ], DxGrid.prototype, "observer", void 0);
555
- _ts_decorate([
947
+ ], DxGrid.prototype, "focusActive", void 0);
948
+ _ts_decorate2([
556
949
  state()
557
950
  ], DxGrid.prototype, "focusedCell", void 0);
558
- _ts_decorate([
951
+ _ts_decorate2([
559
952
  state()
560
- ], DxGrid.prototype, "focusActive", void 0);
561
- _ts_decorate([
953
+ ], DxGrid.prototype, "selectionStart", void 0);
954
+ _ts_decorate2([
955
+ state()
956
+ ], DxGrid.prototype, "selectionEnd", void 0);
957
+ _ts_decorate2([
958
+ state()
959
+ ], DxGrid.prototype, "intrinsicInlineSize", void 0);
960
+ _ts_decorate2([
961
+ state()
962
+ ], DxGrid.prototype, "intrinsicBlockSize", void 0);
963
+ _ts_decorate2([
964
+ state()
965
+ ], DxGrid.prototype, "observer", void 0);
966
+ _ts_decorate2([
562
967
  eventOptions({
563
968
  capture: true
564
969
  })
565
970
  ], DxGrid.prototype, "handleFocus", null);
566
- _ts_decorate([
971
+ _ts_decorate2([
567
972
  eventOptions({
568
973
  capture: true
569
974
  })
570
975
  ], DxGrid.prototype, "handleBlur", null);
571
- DxGrid = _ts_decorate([
572
- customElement("dx-grid")
976
+ DxGrid = _ts_decorate2([
977
+ customElement2("dx-grid")
573
978
  ], DxGrid);
574
979
  export {
575
980
  DxAxisResize,
576
- DxGrid
981
+ DxAxisResizeInternal,
982
+ DxEditRequest,
983
+ DxGrid,
984
+ DxGridCellsSelect
577
985
  };
578
986
  //# sourceMappingURL=index.mjs.map