@dxos/lit-grid 0.6.10 → 0.6.11-staging.32b42e4

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,15 +1,23 @@
1
1
  // packages/ui/lit-grid/src/dx-grid.ts
2
2
  import { LitElement, html } from "lit";
3
- import { customElement, state, property } from "lit/decorators.js";
3
+ import { customElement, state, property, eventOptions } from "lit/decorators.js";
4
4
  import { ref, createRef } from "lit/directives/ref.js";
5
+
6
+ // packages/ui/lit-grid/src/types.ts
7
+ var DxAxisResize = class extends Event {
8
+ constructor(props) {
9
+ super("dx-axis-resize");
10
+ this.axis = props.axis;
11
+ this.index = props.index;
12
+ this.size = props.size;
13
+ }
14
+ };
15
+
16
+ // packages/ui/lit-grid/src/dx-grid.ts
5
17
  function _ts_decorate(decorators, target, key, desc) {
6
18
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
7
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
8
- r = Reflect.decorate(decorators, target, key, desc);
9
- else
10
- for (var i = decorators.length - 1; i >= 0; i--)
11
- if (d = decorators[i])
12
- r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
19
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
20
+ 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;
13
21
  return c > 3 && r && Object.defineProperty(target, key, r), r;
14
22
  }
15
23
  var gap = 1;
@@ -100,7 +108,15 @@ var DxGrid = class extends LitElement {
100
108
  }
101
109
  };
102
110
  this.handlePointerUp = (_event) => {
103
- this.resizing = null;
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;
119
+ }
104
120
  };
105
121
  this.handlePointerMove = (event) => {
106
122
  if (this.resizing) {
@@ -145,6 +161,12 @@ var DxGrid = class extends LitElement {
145
161
  this.updateVis();
146
162
  }
147
163
  };
164
+ // Focus handlers
165
+ this.focusedCell = {
166
+ col: 0,
167
+ row: 0
168
+ };
169
+ this.focusActive = false;
148
170
  }
149
171
  //
150
172
  // Accessors
@@ -174,11 +196,11 @@ var DxGrid = class extends LitElement {
174
196
  acc += this.colSize(this.visColMin + c0);
175
197
  return acc;
176
198
  }, 0) + gap * (overscanCol - 1);
177
- while (pxInline < this.binInlineMax + this.sizeInline) {
199
+ while (pxInline < this.binInlineMax + this.sizeInline + gap) {
178
200
  colIndex += 1;
179
201
  pxInline += this.colSize(colIndex) + gap;
180
202
  }
181
- this.visColMax = colIndex + overscanCol + 1;
203
+ this.visColMax = colIndex + overscanCol;
182
204
  this.templateColumns = [
183
205
  ...Array(this.visColMax - this.visColMin)
184
206
  ].map((_, c0) => `${this.colSize(this.visColMin + c0)}px`).join(" ");
@@ -203,7 +225,7 @@ var DxGrid = class extends LitElement {
203
225
  rowIndex += 1;
204
226
  pxBlock += this.rowSize(rowIndex) + gap;
205
227
  }
206
- this.visRowMax = rowIndex + overscanRow + 1;
228
+ this.visRowMax = rowIndex + overscanRow;
207
229
  this.templateRows = [
208
230
  ...Array(this.visRowMax - this.visRowMin)
209
231
  ].map((_, r0) => `${this.rowSize(this.visRowMin + r0)}px`).join(" ");
@@ -212,20 +234,124 @@ var DxGrid = class extends LitElement {
212
234
  this.updateVisInline();
213
235
  this.updateVisBlock();
214
236
  }
237
+ 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
+ };
247
+ this.focusActive = true;
248
+ }
249
+ }
250
+ handleBlur(event) {
251
+ if (!event.relatedTarget || event.relatedTarget.closest(".dx-grid__viewport") !== this.viewportRef.value) {
252
+ this.focusActive = false;
253
+ }
254
+ }
255
+ /**
256
+ * Moves focus to the cell with actual focus, otherwise moves focus to the viewport.
257
+ */
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({
260
+ preventScroll: true
261
+ });
262
+ }
263
+ /**
264
+ * Updates `pos` so that a cell in focus is fully within the viewport
265
+ */
266
+ snapPosToFocusedCell() {
267
+ if (this.focusedCell.col < this.visColMin || this.focusedCell.col > this.visColMax || this.focusedCell.row < this.visRowMin || this.focusedCell.row > this.visRowMax) {
268
+ } 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
+ } else {
270
+ if (this.focusedCell.col <= this.visColMin + overscanCol) {
271
+ this.posInline = this.binInlineMin;
272
+ this.updateVisInline();
273
+ } else if (this.focusedCell.col >= this.visColMax - overscanCol - 1) {
274
+ const sizeSumCol = [
275
+ ...Array(this.focusedCell.col - this.visColMin)
276
+ ].reduce((acc, _, c0) => {
277
+ acc += this.colSize(this.visColMin + overscanCol + c0) + gap;
278
+ return acc;
279
+ }, 0);
280
+ this.posInline = this.binInlineMin + sizeSumCol + gap * 2 - this.sizeInline;
281
+ this.updateVisInline();
282
+ }
283
+ if (this.focusedCell.row <= this.visRowMin + overscanRow) {
284
+ this.posBlock = this.binBlockMin;
285
+ this.updateVisBlock();
286
+ } else if (this.focusedCell.row >= this.visRowMax - overscanRow - 1) {
287
+ const sizeSumRow = [
288
+ ...Array(this.focusedCell.row - this.visRowMin)
289
+ ].reduce((acc, _, r0) => {
290
+ acc += this.rowSize(this.visRowMin + overscanRow + r0) + gap;
291
+ return acc;
292
+ }, 0);
293
+ this.posBlock = this.binBlockMin + sizeSumRow + gap * 2 - this.sizeBlock;
294
+ this.updateVisBlock();
295
+ }
296
+ }
297
+ }
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
+ }
336
+ }
337
+ }
215
338
  //
216
339
  // Render and other lifecycle methods
217
340
  //
218
341
  render() {
219
342
  const visibleCols = this.visColMax - this.visColMin;
220
343
  const visibleRows = this.visRowMax - this.visRowMin;
221
- const offsetInline = this.binInlineMin - this.posInline - this.overscanInline;
222
- const offsetBlock = this.binBlockMin - this.posBlock - this.overscanBlock;
344
+ const offsetInline = gap + this.binInlineMin - this.posInline - this.overscanInline;
345
+ const offsetBlock = gap + this.binBlockMin - this.posBlock - this.overscanBlock;
223
346
  return html`<div
224
347
  role="none"
225
348
  class="dx-grid"
226
349
  @pointerdown=${this.handlePointerDown}
227
350
  @pointerup=${this.handlePointerUp}
228
351
  @pointermove=${this.handlePointerMove}
352
+ @focus=${this.handleFocus}
353
+ @blur=${this.handleBlur}
354
+ @keydown=${this.handleKeydown}
229
355
  >
230
356
  <div role="none" class="dx-grid__corner"></div>
231
357
  <div role="none" class="dx-grid__columnheader">
@@ -241,7 +367,7 @@ var DxGrid = class extends LitElement {
241
367
  return html`<div
242
368
  role="columnheader"
243
369
  ?inert=${c < 0}
244
- style="inline-size:${this.colSize(c)}px;block-size:${this.rowDefault.size}px;grid-column:${c0 + 1}/${c0 + 2};"
370
+ style="block-size:${this.rowDefault.size}px;grid-column:${c0 + 1}/${c0 + 2};"
245
371
  >
246
372
  <span id=${localChId(c0)}>${colToA1Notation(c)}</span>
247
373
  ${(this.columns[c]?.resizeable ?? this.columnDefault.resizeable) && html`<button class="dx-grid__resize-handle" data-dx-grid-action=${`resize-col,${c}`}>
@@ -253,16 +379,16 @@ var DxGrid = class extends LitElement {
253
379
  </div>
254
380
  <div role="none" class="dx-grid__corner"></div>
255
381
  <div role="none" class="dx-grid__rowheader">
256
- <div role="none" class="dx-grid__rowheader__content" style="transform:translate3d(0,${offsetBlock}px,0);">
382
+ <div
383
+ role="none"
384
+ class="dx-grid__rowheader__content"
385
+ style="transform:translate3d(0,${offsetBlock}px,0);grid-template-rows:${this.templateRows};"
386
+ >
257
387
  ${[
258
388
  ...Array(visibleRows)
259
389
  ].map((_, r0) => {
260
390
  const r = this.visRowMin + r0;
261
- return html`<div
262
- role="rowheader"
263
- ?inert=${r < 0}
264
- style="block-size:${this.rowSize(r)}px;grid-row:${r0 + 1}/${r0 + 2}"
265
- >
391
+ return html`<div role="rowheader" ?inert=${r < 0} style="grid-row:${r0 + 1}/${r0 + 2}">
266
392
  <span id=${localRhId(r0)}>${rowToA1Notation(r)}</span>
267
393
  ${(this.rows[r]?.resizeable ?? this.rowDefault.resizeable) && html`<button class="dx-grid__resize-handle" data-dx-grid-action=${`resize-row,${r}`}>
268
394
  <span class="sr-only">Resize</span>
@@ -271,9 +397,9 @@ var DxGrid = class extends LitElement {
271
397
  })}
272
398
  </div>
273
399
  </div>
274
- <div role="none" class="dx-grid__viewport" @wheel="${this.handleWheel}" ${ref(this.viewportRef)}>
400
+ <div role="grid" class="dx-grid__viewport" tabindex="0" @wheel=${this.handleWheel} ${ref(this.viewportRef)}>
275
401
  <div
276
- role="grid"
402
+ role="none"
277
403
  class="dx-grid__content"
278
404
  style="transform:translate3d(${offsetInline}px,${offsetBlock}px,0);grid-template-columns:${this.templateColumns};grid-template-rows:${this.templateRows};"
279
405
  >
@@ -288,6 +414,7 @@ var DxGrid = class extends LitElement {
288
414
  const cell = this.getCell(c, r);
289
415
  return html`<div
290
416
  role="gridcell"
417
+ tabindex="0"
291
418
  ?inert=${c < 0 || r < 0}
292
419
  aria-rowindex=${r}
293
420
  aria-colindex=${c}
@@ -325,6 +452,11 @@ var DxGrid = class extends LitElement {
325
452
  return acc;
326
453
  }, {});
327
454
  }
455
+ updated(changedProperties) {
456
+ if (this.focusActive && (changedProperties.has("visRowMin") || changedProperties.has("visColMin") || changedProperties.has("focusedCell"))) {
457
+ this.refocus();
458
+ }
459
+ }
328
460
  disconnectedCallback() {
329
461
  super.disconnectedCallback();
330
462
  if (this.viewportRef.value) {
@@ -420,10 +552,27 @@ _ts_decorate([
420
552
  _ts_decorate([
421
553
  state()
422
554
  ], DxGrid.prototype, "observer", void 0);
555
+ _ts_decorate([
556
+ state()
557
+ ], DxGrid.prototype, "focusedCell", void 0);
558
+ _ts_decorate([
559
+ state()
560
+ ], DxGrid.prototype, "focusActive", void 0);
561
+ _ts_decorate([
562
+ eventOptions({
563
+ capture: true
564
+ })
565
+ ], DxGrid.prototype, "handleFocus", null);
566
+ _ts_decorate([
567
+ eventOptions({
568
+ capture: true
569
+ })
570
+ ], DxGrid.prototype, "handleBlur", null);
423
571
  DxGrid = _ts_decorate([
424
572
  customElement("dx-grid")
425
573
  ], DxGrid);
426
574
  export {
575
+ DxAxisResize,
427
576
  DxGrid
428
577
  };
429
578
  //# sourceMappingURL=index.mjs.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../../src/dx-grid.ts"],
4
- "sourcesContent": ["//\n// Copyright 2024 DXOS.org\n//\n\nimport { LitElement, html } from 'lit';\nimport { customElement, state, property } from 'lit/decorators.js';\nimport { ref, createRef, type Ref } from 'lit/directives/ref.js';\n\n/**\n * The size in pixels of the gap between cells\n */\nconst gap = 1;\n\n/**\n * This should be about the width of the `1` numeral so resize is triggered as the row header column’s intrinsic size\n * changes when scrolling vertically.\n */\nconst resizeTolerance = 8;\n\n//\n// `overscan` is the number of columns or rows to render outside of the viewport\n//\nconst overscanCol = 1;\nconst overscanRow = 1;\n\n//\n// `size`, when suffixed with ‘row’ or ‘col’, are limits on size applied when resizing\n//\nconst sizeColMin = 32;\nconst sizeColMax = 1024;\nconst sizeRowMin = 16;\nconst sizeRowMax = 1024;\n\n/**\n * Separator for serializing cell position vectors\n */\nconst separator = ',';\n\n//\n// A1 notation is the fallback for numbering columns and rows.\n//\n\nconst colToA1Notation = (col: number): string => {\n return (\n (col >= 26 ? String.fromCharCode('A'.charCodeAt(0) + Math.floor(col / 26) - 1) : '') +\n String.fromCharCode('A'.charCodeAt(0) + (col % 26))\n );\n};\n\nconst rowToA1Notation = (row: number): string => {\n return `${row + 1}`;\n};\n\nexport type CellValue = {\n /**\n * The content value\n */\n value: string;\n /**\n * If this is a merged cell, the bottomright-most of the range in numeric notation, otherwise undefined.\n */\n end?: string;\n /**\n * CSS inline styles to apply to the gridcell element\n */\n style?: string;\n};\n\ntype AxisMeta = {\n size: number;\n description?: string;\n resizeable?: boolean;\n};\n\nexport type DxGridProps = Pick<DxGrid, 'cells' | 'rows' | 'columns' | 'rowDefault' | 'columnDefault'>;\n\nconst localChId = (c0: number) => `ch--${c0}`;\nconst localRhId = (r0: number) => `rh--${r0}`;\n\nconst getPage = (axis: string, event: PointerEvent) => (axis === 'col' ? event.pageX : event.pageY);\n\n@customElement('dx-grid')\nexport class DxGrid extends LitElement {\n @property({ type: Object })\n rowDefault: AxisMeta = { size: 32 };\n\n @property({ type: Object })\n columnDefault: AxisMeta = { size: 180 };\n\n @property({ type: Object })\n rows: Record<string, AxisMeta> = {};\n\n @property({ type: Object })\n columns: Record<string, AxisMeta> = {};\n\n @property({ type: Object })\n cells: Record<string, CellValue> = {};\n\n //\n // `pos`, short for ‘position’, is the position in pixels of the viewport from the origin.\n //\n\n @state()\n posInline = 0;\n\n @state()\n posBlock = 0;\n\n //\n // `size` (when not suffixed with ‘row’ or ‘col’, see above) is the size in pixels of the viewport.\n //\n\n @state()\n sizeInline = 0;\n\n @state()\n sizeBlock = 0;\n\n //\n // `overscan` is the amount in pixels to offset the grid content due to the number of overscanned columns or rows.\n //\n\n @state()\n overscanInline = 0;\n\n @state()\n overscanBlock = 0;\n\n //\n // `bin`, not short for anything, is the range in pixels within which virtualization does not need to reassess.\n //\n\n @state()\n binInlineMin = 0;\n\n @state()\n binInlineMax = this.colSize(0);\n\n @state()\n binBlockMin = 0;\n\n @state()\n binBlockMax = this.rowSize(0);\n\n //\n // `vis`, short for ‘visible’, is the range in numeric index of the columns or rows which should be rendered within\n // the viewport. These start with naïve values that are updated before first contentful render.\n //\n\n @state()\n visColMin = 0;\n\n @state()\n visColMax = 1;\n\n @state()\n visRowMin = 0;\n\n @state()\n visRowMax = 1;\n\n //\n // `template` is the rendered value of `grid-{axis}-template`.\n //\n @state()\n templateColumns = `${this.colSize(0)}px`;\n\n @state()\n templateRows = `${this.rowSize(0)}px`;\n\n //\n // Resize state and handlers\n //\n\n @state()\n colSizes: Record<string, number> = {};\n\n @state()\n rowSizes: Record<string, number> = {};\n\n @state()\n resizing: null | { axis: 'col' | 'row'; page: number; size: number; index: string } = null;\n\n handlePointerDown = (event: PointerEvent) => {\n const actionEl = (event.target as HTMLElement)?.closest('[data-dx-grid-action]');\n const action = actionEl?.getAttribute('data-dx-grid-action');\n if (action) {\n if (action.startsWith('resize')) {\n const [resize, index] = action.split(',');\n const [_, axis] = resize.split('-');\n this.resizing = {\n axis: axis as 'col' | 'row',\n size: axis === 'col' ? this.colSize(index) : this.rowSize(index),\n page: getPage(axis, event),\n index,\n };\n }\n }\n };\n\n handlePointerUp = (_event: PointerEvent) => {\n this.resizing = null;\n };\n\n handlePointerMove = (event: PointerEvent) => {\n if (this.resizing) {\n const delta = getPage(this.resizing.axis, event) - this.resizing.page;\n if (this.resizing.axis === 'col') {\n const nextSize = Math.max(sizeColMin, Math.min(sizeColMax, this.resizing.size + delta));\n this.colSizes = { ...this.colSizes, [this.resizing.index]: nextSize };\n this.updateVisInline();\n } else {\n const nextSize = Math.max(sizeRowMin, Math.min(sizeRowMax, this.resizing.size + delta));\n this.rowSizes = { ...this.rowSizes, [this.resizing.index]: nextSize };\n this.updateVisBlock();\n }\n }\n };\n\n //\n // Accessors\n //\n\n private colSize(c: number | string) {\n return this.colSizes?.[c] ?? this.columnDefault.size;\n }\n\n private rowSize(r: number | string) {\n return this.rowSizes?.[r] ?? this.rowDefault.size;\n }\n\n private getCell(c: number | string, r: number | string) {\n return this.cells[`${c}${separator}${r}`];\n }\n\n //\n // Resize & reposition handlers, observer, ref\n //\n\n @state()\n observer = new ResizeObserver((entries) => {\n const { inlineSize, blockSize } = entries?.[0]?.contentBoxSize?.[0] ?? {\n inlineSize: 0,\n blockSize: 0,\n };\n if (\n Math.abs(inlineSize - this.sizeInline) > resizeTolerance ||\n Math.abs(blockSize - this.sizeBlock) > resizeTolerance\n ) {\n // console.info('[updating bounds]', 'resize', [inlineSize - this.sizeInline, blockSize - this.sizeBlock]);\n this.sizeInline = inlineSize;\n this.sizeBlock = blockSize;\n this.updateVis();\n }\n });\n\n viewportRef: Ref<HTMLDivElement> = createRef();\n\n handleWheel = ({ deltaX, deltaY }: WheelEvent) => {\n this.posInline = Math.max(0, this.posInline + deltaX);\n this.posBlock = Math.max(0, this.posBlock + deltaY);\n if (\n this.posInline >= this.binInlineMin &&\n this.posInline < this.binInlineMax &&\n this.posBlock >= this.binBlockMin &&\n this.posBlock < this.binBlockMax\n ) {\n // do nothing\n } else {\n // console.info(\n // '[updating bounds]',\n // 'wheel',\n // [this.binInlineMin, this.posInline, this.binInlineMax],\n // [this.binBlockMin, this.posBlock, this.binBlockMax],\n // );\n this.updateVis();\n }\n };\n\n private updateVisInline() {\n // todo: avoid starting from zero\n let colIndex = 0;\n let pxInline = this.colSize(colIndex);\n\n while (pxInline < this.posInline) {\n colIndex += 1;\n pxInline += this.colSize(colIndex) + gap;\n }\n\n this.visColMin = colIndex - overscanCol;\n\n this.binInlineMin = pxInline - this.colSize(colIndex) - gap;\n this.binInlineMax = pxInline + gap;\n\n this.overscanInline =\n [...Array(overscanCol)].reduce((acc, _, c0) => {\n acc += this.colSize(this.visColMin + c0);\n return acc;\n }, 0) +\n gap * (overscanCol - 1);\n\n while (pxInline < this.binInlineMax + this.sizeInline) {\n colIndex += 1;\n pxInline += this.colSize(colIndex) + gap;\n }\n\n this.visColMax = colIndex + overscanCol + 1;\n\n this.templateColumns = [...Array(this.visColMax - this.visColMin)]\n .map((_, c0) => `${this.colSize(this.visColMin + c0)}px`)\n .join(' ');\n }\n\n private updateVisBlock() {\n // todo: avoid starting from zero\n let rowIndex = 0;\n let pxBlock = this.rowSize(rowIndex);\n\n while (pxBlock < this.posBlock) {\n rowIndex += 1;\n pxBlock += this.rowSize(rowIndex) + gap;\n }\n\n this.visRowMin = rowIndex - overscanRow;\n\n this.binBlockMin = pxBlock - this.rowSize(rowIndex) - gap;\n this.binBlockMax = pxBlock + gap;\n\n this.overscanBlock =\n [...Array(overscanRow)].reduce((acc, _, r0) => {\n acc += this.rowSize(this.visRowMin + r0);\n return acc;\n }, 0) +\n gap * (overscanRow - 1);\n\n while (pxBlock < this.binBlockMax + this.sizeBlock) {\n rowIndex += 1;\n pxBlock += this.rowSize(rowIndex) + gap;\n }\n\n this.visRowMax = rowIndex + overscanRow + 1;\n\n this.templateRows = [...Array(this.visRowMax - this.visRowMin)]\n .map((_, r0) => `${this.rowSize(this.visRowMin + r0)}px`)\n .join(' ');\n }\n\n private updateVis() {\n this.updateVisInline();\n this.updateVisBlock();\n }\n\n //\n // Render and other lifecycle methods\n //\n\n override render() {\n const visibleCols = this.visColMax - this.visColMin;\n const visibleRows = this.visRowMax - this.visRowMin;\n // TODO NEXT -> ensure offset is using the right components\n const offsetInline = this.binInlineMin - this.posInline - this.overscanInline;\n const offsetBlock = this.binBlockMin - this.posBlock - this.overscanBlock;\n\n return html`<div\n role=\"none\"\n class=\"dx-grid\"\n @pointerdown=${this.handlePointerDown}\n @pointerup=${this.handlePointerUp}\n @pointermove=${this.handlePointerMove}\n >\n <div role=\"none\" class=\"dx-grid__corner\"></div>\n <div role=\"none\" class=\"dx-grid__columnheader\">\n <div\n role=\"none\"\n class=\"dx-grid__columnheader__content\"\n style=\"transform:translate3d(${offsetInline}px,0,0);grid-template-columns:${this.templateColumns};\"\n >\n ${[...Array(visibleCols)].map((_, c0) => {\n const c = this.visColMin + c0;\n return html`<div\n role=\"columnheader\"\n ?inert=${c < 0}\n style=\"inline-size:${this.colSize(c)}px;block-size:${this.rowDefault.size}px;grid-column:${c0 + 1}/${c0 +\n 2};\"\n >\n <span id=${localChId(c0)}>${colToA1Notation(c)}</span>\n ${(this.columns[c]?.resizeable ?? this.columnDefault.resizeable) &&\n html`<button class=\"dx-grid__resize-handle\" data-dx-grid-action=${`resize-col,${c}`}>\n <span class=\"sr-only\">Resize</span>\n </button>`}\n </div>`;\n })}\n </div>\n </div>\n <div role=\"none\" class=\"dx-grid__corner\"></div>\n <div role=\"none\" class=\"dx-grid__rowheader\">\n <div role=\"none\" class=\"dx-grid__rowheader__content\" style=\"transform:translate3d(0,${offsetBlock}px,0);\">\n ${[...Array(visibleRows)].map((_, r0) => {\n const r = this.visRowMin + r0;\n return html`<div\n role=\"rowheader\"\n ?inert=${r < 0}\n style=\"block-size:${this.rowSize(r)}px;grid-row:${r0 + 1}/${r0 + 2}\"\n >\n <span id=${localRhId(r0)}>${rowToA1Notation(r)}</span>\n ${(this.rows[r]?.resizeable ?? this.rowDefault.resizeable) &&\n html`<button class=\"dx-grid__resize-handle\" data-dx-grid-action=${`resize-row,${r}`}>\n <span class=\"sr-only\">Resize</span>\n </button>`}\n </div>`;\n })}\n </div>\n </div>\n <div role=\"none\" class=\"dx-grid__viewport\" @wheel=\"${this.handleWheel}\" ${ref(this.viewportRef)}>\n <div\n role=\"grid\"\n class=\"dx-grid__content\"\n style=\"transform:translate3d(${offsetInline}px,${offsetBlock}px,0);grid-template-columns:${this\n .templateColumns};grid-template-rows:${this.templateRows};\"\n >\n ${[...Array(visibleCols)].map((_, c0) => {\n return [...Array(visibleRows)].map((_, r0) => {\n const c = c0 + this.visColMin;\n const r = r0 + this.visRowMin;\n const cell = this.getCell(c, r);\n return html`<div\n role=\"gridcell\"\n ?inert=${c < 0 || r < 0}\n aria-rowindex=${r}\n aria-colindex=${c}\n data-dx-grid-action=\"cell\"\n style=\"grid-column:${c0 + 1};grid-row:${r0 + 1}\"\n >\n ${cell?.value}\n </div>`;\n });\n })}\n </div>\n </div>\n <div role=\"none\" class=\"dx-grid__scrollbar\" aria-orientation=\"vertical\">\n <div role=\"none\" class=\"dx-grid__scrollbar__thumb\"></div>\n </div>\n <div role=\"none\" class=\"dx-grid__corner\"></div>\n <div role=\"none\" class=\"dx-grid__scrollbar\" aria-orientation=\"horizontal\">\n <div role=\"none\" class=\"dx-grid__scrollbar__thumb\"></div>\n </div>\n <div role=\"none\" class=\"dx-grid__corner\"></div>\n </div>`;\n }\n\n override firstUpdated() {\n this.observer.observe(this.viewportRef.value!);\n this.colSizes = Object.entries(this.columns).reduce((acc: Record<string, number>, [colId, colMeta]) => {\n if (colMeta?.size) {\n acc[colId] = colMeta.size;\n }\n return acc;\n }, {});\n this.rowSizes = Object.entries(this.rows).reduce((acc: Record<string, number>, [rowId, rowMeta]) => {\n if (rowMeta?.size) {\n acc[rowId] = rowMeta.size;\n }\n return acc;\n }, {});\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n // console.log('[disconnected]', this.viewportRef.value);\n // TODO(thure): Will this even work?\n if (this.viewportRef.value) {\n this.observer.unobserve(this.viewportRef.value);\n }\n }\n\n override createRenderRoot() {\n return this;\n }\n}\n"],
5
- "mappings": "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",
6
- "names": ["LitElement", "html", "customElement", "state", "property", "ref", "createRef", "gap", "resizeTolerance", "overscanCol", "overscanRow", "sizeColMin", "sizeColMax", "sizeRowMin", "sizeRowMax", "separator", "colToA1Notation", "col", "String", "fromCharCode", "charCodeAt", "Math", "floor", "rowToA1Notation", "row", "localChId", "c0", "localRhId", "r0", "getPage", "axis", "event", "pageX", "pageY", "DxGrid", "LitElement", "rowDefault", "size", "columnDefault", "rows", "columns", "cells", "posInline", "posBlock", "sizeInline", "sizeBlock", "overscanInline", "overscanBlock", "binInlineMin", "binInlineMax", "colSize", "binBlockMin", "binBlockMax", "rowSize", "visColMin", "visColMax", "visRowMin", "visRowMax", "templateColumns", "templateRows", "colSizes", "rowSizes", "resizing", "handlePointerDown", "actionEl", "target", "closest", "action", "getAttribute", "startsWith", "resize", "index", "split", "_", "page", "handlePointerUp", "_event", "handlePointerMove", "delta", "nextSize", "max", "min", "updateVisInline", "updateVisBlock", "observer", "ResizeObserver", "entries", "inlineSize", "blockSize", "contentBoxSize", "abs", "updateVis", "viewportRef", "createRef", "handleWheel", "deltaX", "deltaY", "c", "r", "getCell", "colIndex", "pxInline", "Array", "reduce", "acc", "map", "join", "rowIndex", "pxBlock", "render", "visibleCols", "visibleRows", "offsetInline", "offsetBlock", "html", "resizeable", "ref", "cell", "value", "firstUpdated", "observe", "Object", "colId", "colMeta", "rowId", "rowMeta", "disconnectedCallback", "unobserve", "createRenderRoot", "property", "type", "state", "customElement"]
3
+ "sources": ["../../../src/dx-grid.ts", "../../../src/types.ts"],
4
+ "sourcesContent": ["//\n// Copyright 2024 DXOS.org\n//\n\nimport { LitElement, html } from 'lit';\nimport { customElement, state, property, eventOptions } from 'lit/decorators.js';\nimport { ref, createRef, type Ref } from 'lit/directives/ref.js';\n\nimport { DxAxisResize, type DxAxisResizeProps, type DxGridAxis } from './types';\n\n/**\n * The size in pixels of the gap between cells\n */\nconst gap = 1;\n\n/**\n * This should be about the width of the `1` numeral so resize is triggered as the row header column’s intrinsic size\n * changes when scrolling vertically.\n */\nconst resizeTolerance = 8;\n\n//\n// `overscan` is the number of columns or rows to render outside of the viewport\n//\nconst overscanCol = 1;\nconst overscanRow = 1;\n\n//\n// `size`, when suffixed with ‘row’ or ‘col’, are limits on size applied when resizing\n//\nconst sizeColMin = 32;\nconst sizeColMax = 1024;\nconst sizeRowMin = 16;\nconst sizeRowMax = 1024;\n\n/**\n * Separator for serializing cell position vectors\n */\nconst separator = ',';\n\n//\n// A1 notation is the fallback for numbering columns and rows.\n//\n\nconst colToA1Notation = (col: number): string => {\n return (\n (col >= 26 ? String.fromCharCode('A'.charCodeAt(0) + Math.floor(col / 26) - 1) : '') +\n String.fromCharCode('A'.charCodeAt(0) + (col % 26))\n );\n};\n\nconst rowToA1Notation = (row: number): string => {\n return `${row + 1}`;\n};\n\nexport type CellValue = {\n /**\n * The content value\n */\n value: string;\n /**\n * If this is a merged cell, the bottomright-most of the range in numeric notation, otherwise undefined.\n */\n end?: string;\n /**\n * CSS inline styles to apply to the gridcell element\n */\n style?: string;\n};\n\ntype AxisMeta = {\n size: number;\n description?: string;\n resizeable?: boolean;\n};\n\nexport type DxGridProps = Partial<Pick<DxGrid, 'cells' | 'rows' | 'columns' | 'rowDefault' | 'columnDefault'>>;\n\nconst localChId = (c0: number) => `ch--${c0}`;\nconst localRhId = (r0: number) => `rh--${r0}`;\n\nconst getPage = (axis: string, event: PointerEvent) => (axis === 'col' ? event.pageX : event.pageY);\n\n@customElement('dx-grid')\nexport class DxGrid extends LitElement {\n @property({ type: Object })\n rowDefault: AxisMeta = { size: 32 };\n\n @property({ type: Object })\n columnDefault: AxisMeta = { size: 180 };\n\n @property({ type: Object })\n rows: Record<string, AxisMeta> = {};\n\n @property({ type: Object })\n columns: Record<string, AxisMeta> = {};\n\n @property({ type: Object })\n cells: Record<string, CellValue> = {};\n\n //\n // `pos`, short for ‘position’, is the position in pixels of the viewport from the origin.\n //\n\n @state()\n posInline = 0;\n\n @state()\n posBlock = 0;\n\n //\n // `size` (when not suffixed with ‘row’ or ‘col’, see above) is the size in pixels of the viewport.\n //\n\n @state()\n sizeInline = 0;\n\n @state()\n sizeBlock = 0;\n\n //\n // `overscan` is the amount in pixels to offset the grid content due to the number of overscanned columns or rows.\n //\n\n @state()\n overscanInline = 0;\n\n @state()\n overscanBlock = 0;\n\n //\n // `bin`, not short for anything, is the range in pixels within which virtualization does not need to reassess.\n //\n\n @state()\n binInlineMin = 0;\n\n @state()\n binInlineMax = this.colSize(0);\n\n @state()\n binBlockMin = 0;\n\n @state()\n binBlockMax = this.rowSize(0);\n\n //\n // `vis`, short for ‘visible’, is the range in numeric index of the columns or rows which should be rendered within\n // the viewport. These start with naïve values that are updated before first contentful render.\n //\n\n @state()\n visColMin = 0;\n\n @state()\n visColMax = 1;\n\n @state()\n visRowMin = 0;\n\n @state()\n visRowMax = 1;\n\n //\n // `template` is the rendered value of `grid-{axis}-template`.\n //\n @state()\n templateColumns = `${this.colSize(0)}px`;\n\n @state()\n templateRows = `${this.rowSize(0)}px`;\n\n //\n // Resize state and handlers\n //\n\n @state()\n colSizes: Record<string, number> = {};\n\n @state()\n rowSizes: Record<string, number> = {};\n\n @state()\n resizing: null | (DxAxisResizeProps & { page: number }) = null;\n\n handlePointerDown = (event: PointerEvent) => {\n const actionEl = (event.target as HTMLElement)?.closest('[data-dx-grid-action]');\n const action = actionEl?.getAttribute('data-dx-grid-action');\n if (action) {\n if (action.startsWith('resize')) {\n const [resize, index] = action.split(',');\n const [_, axis] = resize.split('-');\n this.resizing = {\n axis: axis as DxGridAxis,\n size: axis === 'col' ? this.colSize(index) : this.rowSize(index),\n page: getPage(axis, event),\n index,\n };\n }\n }\n };\n\n handlePointerUp = (_event: PointerEvent) => {\n if (this.resizing) {\n const resizeEvent = new DxAxisResize({\n axis: this.resizing.axis,\n index: this.resizing.index,\n size: this[this.resizing.axis === 'col' ? 'colSize' : 'rowSize'](this.resizing.index),\n });\n this.dispatchEvent(resizeEvent);\n this.resizing = null;\n }\n };\n\n handlePointerMove = (event: PointerEvent) => {\n if (this.resizing) {\n const delta = getPage(this.resizing.axis, event) - this.resizing.page;\n if (this.resizing.axis === 'col') {\n const nextSize = Math.max(sizeColMin, Math.min(sizeColMax, this.resizing.size + delta));\n this.colSizes = { ...this.colSizes, [this.resizing.index]: nextSize };\n this.updateVisInline();\n } else {\n const nextSize = Math.max(sizeRowMin, Math.min(sizeRowMax, this.resizing.size + delta));\n this.rowSizes = { ...this.rowSizes, [this.resizing.index]: nextSize };\n this.updateVisBlock();\n }\n }\n };\n\n //\n // Accessors\n //\n\n private colSize(c: number | string) {\n return this.colSizes?.[c] ?? this.columnDefault.size;\n }\n\n private rowSize(r: number | string) {\n return this.rowSizes?.[r] ?? this.rowDefault.size;\n }\n\n private getCell(c: number | string, r: number | string) {\n return this.cells[`${c}${separator}${r}`];\n }\n\n //\n // Resize & reposition handlers, observer, ref\n //\n\n @state()\n observer = new ResizeObserver((entries) => {\n const { inlineSize, blockSize } = entries?.[0]?.contentBoxSize?.[0] ?? {\n inlineSize: 0,\n blockSize: 0,\n };\n if (\n Math.abs(inlineSize - this.sizeInline) > resizeTolerance ||\n Math.abs(blockSize - this.sizeBlock) > resizeTolerance\n ) {\n // console.info('[updating bounds]', 'resize', [inlineSize - this.sizeInline, blockSize - this.sizeBlock]);\n this.sizeInline = inlineSize;\n this.sizeBlock = blockSize;\n this.updateVis();\n }\n });\n\n viewportRef: Ref<HTMLDivElement> = createRef();\n\n handleWheel = ({ deltaX, deltaY }: WheelEvent) => {\n this.posInline = Math.max(0, this.posInline + deltaX);\n this.posBlock = Math.max(0, this.posBlock + deltaY);\n if (\n this.posInline >= this.binInlineMin &&\n this.posInline < this.binInlineMax &&\n this.posBlock >= this.binBlockMin &&\n this.posBlock < this.binBlockMax\n ) {\n // do nothing\n } else {\n // console.info(\n // '[updating bounds]',\n // 'wheel',\n // [this.binInlineMin, this.posInline, this.binInlineMax],\n // [this.binBlockMin, this.posBlock, this.binBlockMax],\n // );\n this.updateVis();\n }\n };\n\n private updateVisInline() {\n // todo: avoid starting from zero\n let colIndex = 0;\n let pxInline = this.colSize(colIndex);\n\n while (pxInline < this.posInline) {\n colIndex += 1;\n pxInline += this.colSize(colIndex) + gap;\n }\n\n this.visColMin = colIndex - overscanCol;\n\n this.binInlineMin = pxInline - this.colSize(colIndex) - gap;\n this.binInlineMax = pxInline + gap;\n\n this.overscanInline =\n [...Array(overscanCol)].reduce((acc, _, c0) => {\n acc += this.colSize(this.visColMin + c0);\n return acc;\n }, 0) +\n gap * (overscanCol - 1);\n\n while (pxInline < this.binInlineMax + this.sizeInline + gap) {\n colIndex += 1;\n pxInline += this.colSize(colIndex) + gap;\n }\n\n this.visColMax = colIndex + overscanCol;\n\n this.templateColumns = [...Array(this.visColMax - this.visColMin)]\n .map((_, c0) => `${this.colSize(this.visColMin + c0)}px`)\n .join(' ');\n }\n\n private updateVisBlock() {\n // todo: avoid starting from zero\n let rowIndex = 0;\n let pxBlock = this.rowSize(rowIndex);\n\n while (pxBlock < this.posBlock) {\n rowIndex += 1;\n pxBlock += this.rowSize(rowIndex) + gap;\n }\n\n this.visRowMin = rowIndex - overscanRow;\n\n this.binBlockMin = pxBlock - this.rowSize(rowIndex) - gap;\n this.binBlockMax = pxBlock + gap;\n\n this.overscanBlock =\n [...Array(overscanRow)].reduce((acc, _, r0) => {\n acc += this.rowSize(this.visRowMin + r0);\n return acc;\n }, 0) +\n gap * (overscanRow - 1);\n\n while (pxBlock < this.binBlockMax + this.sizeBlock) {\n rowIndex += 1;\n pxBlock += this.rowSize(rowIndex) + gap;\n }\n\n this.visRowMax = rowIndex + overscanRow;\n\n this.templateRows = [...Array(this.visRowMax - this.visRowMin)]\n .map((_, r0) => `${this.rowSize(this.visRowMin + r0)}px`)\n .join(' ');\n }\n\n private updateVis() {\n this.updateVisInline();\n this.updateVisBlock();\n }\n\n // Focus handlers\n\n @state()\n focusedCell: Record<DxGridAxis, number> = { col: 0, row: 0 };\n\n @state()\n focusActive: boolean = false;\n\n @eventOptions({ capture: true })\n handleFocus(event: FocusEvent) {\n const target = event.target as HTMLElement;\n const action = target.getAttribute('data-dx-grid-action');\n if (action === 'cell') {\n const c = parseInt(target.getAttribute('aria-colindex') ?? 'never');\n const r = parseInt(target.getAttribute('aria-rowindex') ?? 'never');\n this.focusedCell = { col: c, row: r };\n this.focusActive = true;\n }\n }\n\n @eventOptions({ capture: true })\n handleBlur(event: FocusEvent) {\n // Only unset `focusActive` if focus is not moving to an element within the grid.\n if (\n !event.relatedTarget ||\n (event.relatedTarget as HTMLElement).closest('.dx-grid__viewport') !== this.viewportRef.value\n ) {\n this.focusActive = false;\n }\n }\n\n /**\n * Moves focus to the cell with actual focus, otherwise moves focus to the viewport.\n */\n refocus() {\n (this.focusedCell.row < this.visRowMin ||\n this.focusedCell.row > this.visRowMax ||\n this.focusedCell.col < this.visColMin ||\n this.focusedCell.col > this.visColMax\n ? this.viewportRef.value\n : (this.viewportRef.value?.querySelector(\n `[aria-colindex=\"${this.focusedCell.col}\"][aria-rowindex=\"${this.focusedCell.row}\"]`,\n ) as HTMLElement | null)\n )?.focus({ preventScroll: true });\n }\n\n /**\n * Updates `pos` so that a cell in focus is fully within the viewport\n */\n snapPosToFocusedCell() {\n if (\n this.focusedCell.col < this.visColMin ||\n this.focusedCell.col > this.visColMax ||\n this.focusedCell.row < this.visRowMin ||\n this.focusedCell.row > this.visRowMax\n ) {\n // console.warn('Snapping position to a focused cell that is not already mounted is unsupported.');\n } else if (\n this.focusedCell.col > this.visColMin + overscanCol &&\n this.focusedCell.col < this.visColMax - overscanCol - 1 &&\n this.focusedCell.row > this.visRowMin + overscanRow &&\n this.focusedCell.row < this.visRowMax - overscanRow - 1\n ) {\n // console.log(\n // '[within bounds]',\n // this.focusedCell,\n // [this.visColMin, this.visColMax, overscanCol],\n // [this.visRowMin, this.visRowMax, overscanRow],\n // );\n } else {\n if (this.focusedCell.col <= this.visColMin + overscanCol) {\n this.posInline = this.binInlineMin;\n this.updateVisInline();\n } else if (this.focusedCell.col >= this.visColMax - overscanCol - 1) {\n const sizeSumCol = [...Array(this.focusedCell.col - this.visColMin)].reduce((acc, _, c0) => {\n acc += this.colSize(this.visColMin + overscanCol + c0) + gap;\n return acc;\n }, 0);\n this.posInline = this.binInlineMin + sizeSumCol + gap * 2 - this.sizeInline;\n this.updateVisInline();\n }\n\n if (this.focusedCell.row <= this.visRowMin + overscanRow) {\n this.posBlock = this.binBlockMin;\n this.updateVisBlock();\n } else if (this.focusedCell.row >= this.visRowMax - overscanRow - 1) {\n const sizeSumRow = [...Array(this.focusedCell.row - this.visRowMin)].reduce((acc, _, r0) => {\n acc += this.rowSize(this.visRowMin + overscanRow + r0) + gap;\n return acc;\n }, 0);\n this.posBlock = this.binBlockMin + sizeSumRow + gap * 2 - this.sizeBlock;\n this.updateVisBlock();\n }\n }\n }\n\n // Keyboard interactions\n handleKeydown(event: KeyboardEvent) {\n if (this.focusActive) {\n // Adjust state\n switch (event.key) {\n case 'ArrowDown':\n this.focusedCell = { ...this.focusedCell, row: this.focusedCell.row + 1 };\n break;\n case 'ArrowUp':\n this.focusedCell = { ...this.focusedCell, row: Math.max(0, this.focusedCell.row - 1) };\n break;\n case 'ArrowRight':\n this.focusedCell = { ...this.focusedCell, col: this.focusedCell.col + 1 };\n break;\n case 'ArrowLeft':\n this.focusedCell = { ...this.focusedCell, col: Math.max(0, this.focusedCell.col - 1) };\n break;\n }\n // Handle virtualization & focus consequences\n switch (event.key) {\n case 'ArrowDown':\n case 'ArrowUp':\n case 'ArrowRight':\n case 'ArrowLeft':\n event.preventDefault();\n this.snapPosToFocusedCell();\n break;\n }\n }\n }\n\n //\n // Render and other lifecycle methods\n //\n\n override render() {\n const visibleCols = this.visColMax - this.visColMin;\n const visibleRows = this.visRowMax - this.visRowMin;\n const offsetInline = gap + this.binInlineMin - this.posInline - this.overscanInline;\n const offsetBlock = gap + this.binBlockMin - this.posBlock - this.overscanBlock;\n\n return html`<div\n role=\"none\"\n class=\"dx-grid\"\n @pointerdown=${this.handlePointerDown}\n @pointerup=${this.handlePointerUp}\n @pointermove=${this.handlePointerMove}\n @focus=${this.handleFocus}\n @blur=${this.handleBlur}\n @keydown=${this.handleKeydown}\n >\n <div role=\"none\" class=\"dx-grid__corner\"></div>\n <div role=\"none\" class=\"dx-grid__columnheader\">\n <div\n role=\"none\"\n class=\"dx-grid__columnheader__content\"\n style=\"transform:translate3d(${offsetInline}px,0,0);grid-template-columns:${this.templateColumns};\"\n >\n ${[...Array(visibleCols)].map((_, c0) => {\n const c = this.visColMin + c0;\n return html`<div\n role=\"columnheader\"\n ?inert=${c < 0}\n style=\"block-size:${this.rowDefault.size}px;grid-column:${c0 + 1}/${c0 + 2};\"\n >\n <span id=${localChId(c0)}>${colToA1Notation(c)}</span>\n ${(this.columns[c]?.resizeable ?? this.columnDefault.resizeable) &&\n html`<button class=\"dx-grid__resize-handle\" data-dx-grid-action=${`resize-col,${c}`}>\n <span class=\"sr-only\">Resize</span>\n </button>`}\n </div>`;\n })}\n </div>\n </div>\n <div role=\"none\" class=\"dx-grid__corner\"></div>\n <div role=\"none\" class=\"dx-grid__rowheader\">\n <div\n role=\"none\"\n class=\"dx-grid__rowheader__content\"\n style=\"transform:translate3d(0,${offsetBlock}px,0);grid-template-rows:${this.templateRows};\"\n >\n ${[...Array(visibleRows)].map((_, r0) => {\n const r = this.visRowMin + r0;\n return html`<div role=\"rowheader\" ?inert=${r < 0} style=\"grid-row:${r0 + 1}/${r0 + 2}\">\n <span id=${localRhId(r0)}>${rowToA1Notation(r)}</span>\n ${(this.rows[r]?.resizeable ?? this.rowDefault.resizeable) &&\n html`<button class=\"dx-grid__resize-handle\" data-dx-grid-action=${`resize-row,${r}`}>\n <span class=\"sr-only\">Resize</span>\n </button>`}\n </div>`;\n })}\n </div>\n </div>\n <div role=\"grid\" class=\"dx-grid__viewport\" tabindex=\"0\" @wheel=${this.handleWheel} ${ref(this.viewportRef)}>\n <div\n role=\"none\"\n class=\"dx-grid__content\"\n style=\"transform:translate3d(${offsetInline}px,${offsetBlock}px,0);grid-template-columns:${this\n .templateColumns};grid-template-rows:${this.templateRows};\"\n >\n ${[...Array(visibleCols)].map((_, c0) => {\n return [...Array(visibleRows)].map((_, r0) => {\n const c = c0 + this.visColMin;\n const r = r0 + this.visRowMin;\n const cell = this.getCell(c, r);\n return html`<div\n role=\"gridcell\"\n tabindex=\"0\"\n ?inert=${c < 0 || r < 0}\n aria-rowindex=${r}\n aria-colindex=${c}\n data-dx-grid-action=\"cell\"\n style=\"grid-column:${c0 + 1};grid-row:${r0 + 1}\"\n >\n ${cell?.value}\n </div>`;\n });\n })}\n </div>\n </div>\n <div role=\"none\" class=\"dx-grid__scrollbar\" aria-orientation=\"vertical\">\n <div role=\"none\" class=\"dx-grid__scrollbar__thumb\"></div>\n </div>\n <div role=\"none\" class=\"dx-grid__corner\"></div>\n <div role=\"none\" class=\"dx-grid__scrollbar\" aria-orientation=\"horizontal\">\n <div role=\"none\" class=\"dx-grid__scrollbar__thumb\"></div>\n </div>\n <div role=\"none\" class=\"dx-grid__corner\"></div>\n </div>`;\n }\n\n override firstUpdated() {\n this.observer.observe(this.viewportRef.value!);\n this.colSizes = Object.entries(this.columns).reduce((acc: Record<string, number>, [colId, colMeta]) => {\n if (colMeta?.size) {\n acc[colId] = colMeta.size;\n }\n return acc;\n }, {});\n this.rowSizes = Object.entries(this.rows).reduce((acc: Record<string, number>, [rowId, rowMeta]) => {\n if (rowMeta?.size) {\n acc[rowId] = rowMeta.size;\n }\n return acc;\n }, {});\n }\n\n override updated(changedProperties: Map<string, any>) {\n // Update the focused element if there is a change in bounds (otherwise Lit keeps focus on the relative element).\n if (\n this.focusActive &&\n (changedProperties.has('visRowMin') || changedProperties.has('visColMin') || changedProperties.has('focusedCell'))\n ) {\n this.refocus();\n }\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n // console.log('[disconnected]', this.viewportRef.value);\n // TODO(thure): Will this even work?\n if (this.viewportRef.value) {\n this.observer.unobserve(this.viewportRef.value);\n }\n }\n\n override createRenderRoot() {\n return this;\n }\n}\n", "//\n// Copyright 2024 DXOS.org\n//\n\nexport type DxGridAxis = 'row' | 'col';\n\nexport type DxAxisResizeProps = Pick<DxAxisResize, 'axis' | 'index' | 'size'>;\n\nexport class DxAxisResize extends Event {\n public readonly axis: DxGridAxis;\n public readonly index: string;\n public readonly size: number;\n constructor(props: DxAxisResizeProps) {\n super('dx-axis-resize');\n this.axis = props.axis;\n this.index = props.index;\n this.size = props.size;\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["LitElement", "html", "customElement", "state", "property", "eventOptions", "ref", "createRef", "DxAxisResize", "Event", "constructor", "props", "axis", "index", "size", "gap", "resizeTolerance", "overscanCol", "overscanRow", "sizeColMin", "sizeColMax", "sizeRowMin", "sizeRowMax", "separator", "colToA1Notation", "col", "String", "fromCharCode", "charCodeAt", "Math", "floor", "rowToA1Notation", "row", "localChId", "c0", "localRhId", "r0", "getPage", "axis", "event", "pageX", "pageY", "DxGrid", "LitElement", "rowDefault", "size", "columnDefault", "rows", "columns", "cells", "posInline", "posBlock", "sizeInline", "sizeBlock", "overscanInline", "overscanBlock", "binInlineMin", "binInlineMax", "colSize", "binBlockMin", "binBlockMax", "rowSize", "visColMin", "visColMax", "visRowMin", "visRowMax", "templateColumns", "templateRows", "colSizes", "rowSizes", "resizing", "handlePointerDown", "actionEl", "target", "closest", "action", "getAttribute", "startsWith", "resize", "index", "split", "_", "page", "handlePointerUp", "_event", "resizeEvent", "DxAxisResize", "dispatchEvent", "handlePointerMove", "delta", "nextSize", "max", "min", "updateVisInline", "updateVisBlock", "observer", "ResizeObserver", "entries", "inlineSize", "blockSize", "contentBoxSize", "abs", "updateVis", "viewportRef", "createRef", "handleWheel", "deltaX", "deltaY", "focusedCell", "focusActive", "c", "r", "getCell", "colIndex", "pxInline", "Array", "reduce", "acc", "map", "join", "rowIndex", "pxBlock", "handleFocus", "parseInt", "handleBlur", "relatedTarget", "value", "refocus", "querySelector", "focus", "preventScroll", "snapPosToFocusedCell", "sizeSumCol", "sizeSumRow", "handleKeydown", "key", "preventDefault", "render", "visibleCols", "visibleRows", "offsetInline", "offsetBlock", "html", "resizeable", "ref", "cell", "firstUpdated", "observe", "Object", "colId", "colMeta", "rowId", "rowMeta", "updated", "changedProperties", "has", "disconnectedCallback", "unobserve", "createRenderRoot", "property", "type", "state", "eventOptions", "capture", "customElement"]
7
7
  }
@@ -1 +1 @@
1
- {"inputs":{"packages/ui/lit-grid/src/dx-grid.ts":{"bytes":50156,"imports":[{"path":"lit","kind":"import-statement","external":true},{"path":"lit/decorators.js","kind":"import-statement","external":true},{"path":"lit/directives/ref.js","kind":"import-statement","external":true}],"format":"esm"},"packages/ui/lit-grid/src/index.ts":{"bytes":560,"imports":[{"path":"packages/ui/lit-grid/src/dx-grid.ts","kind":"import-statement","original":"./dx-grid"}],"format":"esm"}},"outputs":{"packages/ui/lit-grid/dist/lib/browser/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":23985},"packages/ui/lit-grid/dist/lib/browser/index.mjs":{"imports":[{"path":"lit","kind":"import-statement","external":true},{"path":"lit/decorators.js","kind":"import-statement","external":true},{"path":"lit/directives/ref.js","kind":"import-statement","external":true}],"exports":["DxGrid"],"entryPoint":"packages/ui/lit-grid/src/index.ts","inputs":{"packages/ui/lit-grid/src/dx-grid.ts":{"bytesInOutput":13730},"packages/ui/lit-grid/src/index.ts":{"bytesInOutput":0}},"bytes":13825}}}
1
+ {"inputs":{"packages/ui/lit-grid/src/types.ts":{"bytes":1636,"imports":[],"format":"esm"},"packages/ui/lit-grid/src/dx-grid.ts":{"bytes":69997,"imports":[{"path":"lit","kind":"import-statement","external":true},{"path":"lit/decorators.js","kind":"import-statement","external":true},{"path":"lit/directives/ref.js","kind":"import-statement","external":true},{"path":"packages/ui/lit-grid/src/types.ts","kind":"import-statement","original":"./types"}],"format":"esm"},"packages/ui/lit-grid/src/index.ts":{"bytes":572,"imports":[{"path":"packages/ui/lit-grid/src/dx-grid.ts","kind":"import-statement","original":"./dx-grid"},{"path":"packages/ui/lit-grid/src/types.ts","kind":"import-statement","original":"./types"}],"format":"esm"}},"outputs":{"packages/ui/lit-grid/dist/lib/browser/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":33648},"packages/ui/lit-grid/dist/lib/browser/index.mjs":{"imports":[{"path":"lit","kind":"import-statement","external":true},{"path":"lit/decorators.js","kind":"import-statement","external":true},{"path":"lit/directives/ref.js","kind":"import-statement","external":true}],"exports":["DxAxisResize","DxGrid"],"entryPoint":"packages/ui/lit-grid/src/index.ts","inputs":{"packages/ui/lit-grid/src/dx-grid.ts":{"bytesInOutput":18568},"packages/ui/lit-grid/src/types.ts":{"bytesInOutput":186},"packages/ui/lit-grid/src/index.ts":{"bytesInOutput":0}},"bytes":18943}}}
@@ -1,5 +1,6 @@
1
1
  import { LitElement } from 'lit';
2
2
  import { type Ref } from 'lit/directives/ref.js';
3
+ import { type DxAxisResizeProps, type DxGridAxis } from './types';
3
4
  export type CellValue = {
4
5
  /**
5
6
  * The content value
@@ -19,7 +20,7 @@ type AxisMeta = {
19
20
  description?: string;
20
21
  resizeable?: boolean;
21
22
  };
22
- export type DxGridProps = Pick<DxGrid, 'cells' | 'rows' | 'columns' | 'rowDefault' | 'columnDefault'>;
23
+ export type DxGridProps = Partial<Pick<DxGrid, 'cells' | 'rows' | 'columns' | 'rowDefault' | 'columnDefault'>>;
23
24
  export declare class DxGrid extends LitElement {
24
25
  rowDefault: AxisMeta;
25
26
  columnDefault: AxisMeta;
@@ -44,12 +45,9 @@ export declare class DxGrid extends LitElement {
44
45
  templateRows: string;
45
46
  colSizes: Record<string, number>;
46
47
  rowSizes: Record<string, number>;
47
- resizing: null | {
48
- axis: 'col' | 'row';
48
+ resizing: null | (DxAxisResizeProps & {
49
49
  page: number;
50
- size: number;
51
- index: string;
52
- };
50
+ });
53
51
  handlePointerDown: (event: PointerEvent) => void;
54
52
  handlePointerUp: (_event: PointerEvent) => void;
55
53
  handlePointerMove: (event: PointerEvent) => void;
@@ -62,8 +60,22 @@ export declare class DxGrid extends LitElement {
62
60
  private updateVisInline;
63
61
  private updateVisBlock;
64
62
  private updateVis;
63
+ focusedCell: Record<DxGridAxis, number>;
64
+ focusActive: boolean;
65
+ handleFocus(event: FocusEvent): void;
66
+ handleBlur(event: FocusEvent): void;
67
+ /**
68
+ * Moves focus to the cell with actual focus, otherwise moves focus to the viewport.
69
+ */
70
+ refocus(): void;
71
+ /**
72
+ * Updates `pos` so that a cell in focus is fully within the viewport
73
+ */
74
+ snapPosToFocusedCell(): void;
75
+ handleKeydown(event: KeyboardEvent): void;
65
76
  render(): import("lit").TemplateResult<1>;
66
77
  firstUpdated(): void;
78
+ updated(changedProperties: Map<string, any>): void;
67
79
  disconnectedCallback(): void;
68
80
  createRenderRoot(): this;
69
81
  }
@@ -1 +1 @@
1
- {"version":3,"file":"dx-grid.d.ts","sourceRoot":"","sources":["../../../src/dx-grid.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,UAAU,EAAQ,MAAM,KAAK,CAAC;AAEvC,OAAO,EAAkB,KAAK,GAAG,EAAE,MAAM,uBAAuB,CAAC;AA+CjE,MAAM,MAAM,SAAS,GAAG;IACtB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,KAAK,QAAQ,GAAG;IACd,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,GAAG,YAAY,GAAG,eAAe,CAAC,CAAC;AAOtG,qBACa,MAAO,SAAQ,UAAU;IAEpC,UAAU,EAAE,QAAQ,CAAgB;IAGpC,aAAa,EAAE,QAAQ,CAAiB;IAGxC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAM;IAGpC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAM;IAGvC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAM;IAOtC,SAAS,SAAK;IAGd,QAAQ,SAAK;IAOb,UAAU,SAAK;IAGf,SAAS,SAAK;IAOd,cAAc,SAAK;IAGnB,aAAa,SAAK;IAOlB,YAAY,SAAK;IAGjB,YAAY,SAAmB;IAG/B,WAAW,SAAK;IAGhB,WAAW,SAAmB;IAQ9B,SAAS,SAAK;IAGd,SAAS,SAAK;IAGd,SAAS,SAAK;IAGd,SAAS,SAAK;IAMd,eAAe,SAA0B;IAGzC,YAAY,SAA0B;IAOtC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAM;IAGtC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAM;IAGtC,QAAQ,EAAE,IAAI,GAAG;QAAE,IAAI,EAAE,KAAK,GAAG,KAAK,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAQ;IAE3F,iBAAiB,UAAW,YAAY,UAetC;IAEF,eAAe,WAAY,YAAY,UAErC;IAEF,iBAAiB,UAAW,YAAY,UAatC;IAMF,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,OAAO;IASf,QAAQ,iBAcL;IAEH,WAAW,EAAE,GAAG,CAAC,cAAc,CAAC,CAAe;IAE/C,WAAW,uBAAwB,UAAU,UAmB3C;IAEF,OAAO,CAAC,eAAe;IAkCvB,OAAO,CAAC,cAAc;IAkCtB,OAAO,CAAC,SAAS;IASR,MAAM;IA8FN,YAAY;IAgBZ,oBAAoB;IASpB,gBAAgB;CAG1B"}
1
+ {"version":3,"file":"dx-grid.d.ts","sourceRoot":"","sources":["../../../src/dx-grid.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,UAAU,EAAQ,MAAM,KAAK,CAAC;AAEvC,OAAO,EAAkB,KAAK,GAAG,EAAE,MAAM,uBAAuB,CAAC;AAEjE,OAAO,EAAgB,KAAK,iBAAiB,EAAE,KAAK,UAAU,EAAE,MAAM,SAAS,CAAC;AA+ChF,MAAM,MAAM,SAAS,GAAG;IACtB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,KAAK,QAAQ,GAAG;IACd,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,GAAG,YAAY,GAAG,eAAe,CAAC,CAAC,CAAC;AAO/G,qBACa,MAAO,SAAQ,UAAU;IAEpC,UAAU,EAAE,QAAQ,CAAgB;IAGpC,aAAa,EAAE,QAAQ,CAAiB;IAGxC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAM;IAGpC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAM;IAGvC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAM;IAOtC,SAAS,SAAK;IAGd,QAAQ,SAAK;IAOb,UAAU,SAAK;IAGf,SAAS,SAAK;IAOd,cAAc,SAAK;IAGnB,aAAa,SAAK;IAOlB,YAAY,SAAK;IAGjB,YAAY,SAAmB;IAG/B,WAAW,SAAK;IAGhB,WAAW,SAAmB;IAQ9B,SAAS,SAAK;IAGd,SAAS,SAAK;IAGd,SAAS,SAAK;IAGd,SAAS,SAAK;IAMd,eAAe,SAA0B;IAGzC,YAAY,SAA0B;IAOtC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAM;IAGtC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAM;IAGtC,QAAQ,EAAE,IAAI,GAAG,CAAC,iBAAiB,GAAG;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAQ;IAE/D,iBAAiB,UAAW,YAAY,UAetC;IAEF,eAAe,WAAY,YAAY,UAUrC;IAEF,iBAAiB,UAAW,YAAY,UAatC;IAMF,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,OAAO;IASf,QAAQ,iBAcL;IAEH,WAAW,EAAE,GAAG,CAAC,cAAc,CAAC,CAAe;IAE/C,WAAW,uBAAwB,UAAU,UAmB3C;IAEF,OAAO,CAAC,eAAe;IAkCvB,OAAO,CAAC,cAAc;IAkCtB,OAAO,CAAC,SAAS;IAQjB,WAAW,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAAsB;IAG7D,WAAW,EAAE,OAAO,CAAS;IAG7B,WAAW,CAAC,KAAK,EAAE,UAAU;IAY7B,UAAU,CAAC,KAAK,EAAE,UAAU;IAU5B;;OAEG;IACH,OAAO;IAYP;;OAEG;IACH,oBAAoB;IAgDpB,aAAa,CAAC,KAAK,EAAE,aAAa;IAkCzB,MAAM;IAgGN,YAAY;IAgBZ,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC;IAU3C,oBAAoB;IASpB,gBAAgB;CAG1B"}
@@ -1,2 +1,3 @@
1
- export { DxGrid, type DxGridProps } from './dx-grid';
1
+ export * from './dx-grid';
2
+ export * from './types';
2
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAIA,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC"}
@@ -0,0 +1,9 @@
1
+ export type DxGridAxis = 'row' | 'col';
2
+ export type DxAxisResizeProps = Pick<DxAxisResize, 'axis' | 'index' | 'size'>;
3
+ export declare class DxAxisResize extends Event {
4
+ readonly axis: DxGridAxis;
5
+ readonly index: string;
6
+ readonly size: number;
7
+ constructor(props: DxAxisResizeProps);
8
+ }
9
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,KAAK,CAAC;AAEvC,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC,CAAC;AAE9E,qBAAa,YAAa,SAAQ,KAAK;IACrC,SAAgB,IAAI,EAAE,UAAU,CAAC;IACjC,SAAgB,KAAK,EAAE,MAAM,CAAC;IAC9B,SAAgB,IAAI,EAAE,MAAM,CAAC;gBACjB,KAAK,EAAE,iBAAiB;CAMrC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@dxos/lit-grid",
3
- "version": "0.6.10",
4
- "description": "A grid webcomponent using Lit",
3
+ "version": "0.6.11-staging.32b42e4",
4
+ "description": "A grid Web Component using Lit",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
7
7
  "license": "MIT",
@@ -13,7 +13,10 @@
13
13
  },
14
14
  "./dx-grid.pcss": "./src/dx-grid.pcss"
15
15
  },
16
- "main": "src/index.ts",
16
+ "types": "dist/types/src/index.d.ts",
17
+ "typesVersions": {
18
+ "*": {}
19
+ },
17
20
  "files": [
18
21
  "src",
19
22
  "dist"
package/src/dx-grid.pcss CHANGED
@@ -21,6 +21,7 @@ dx-grid {
21
21
  grid-template-columns: min-content 1fr min-content;
22
22
  grid-template-rows: min-content 1fr min-content;
23
23
  font-variant-numeric: tabular-nums;
24
+ --dx-grid-gap: 1px;
24
25
  }
25
26
 
26
27
  .dx-grid__scrollbar__thumb {
@@ -38,8 +39,8 @@ dx-grid {
38
39
  .dx-grid__rowheader__content,
39
40
  .dx-grid__content {
40
41
  display: grid;
41
- gap: 1px;
42
- background: var(--dx-separator);
42
+ gap: var(--dx-grid-gap);
43
+ background: var(--dx-grid-lines, var(--dx-separator));
43
44
  inline-size: min-content;
44
45
  block-size: min-content;
45
46
  }
@@ -48,27 +49,46 @@ dx-grid {
48
49
  .dx-grid__rowheader,
49
50
  .dx-grid__viewport {
50
51
  overflow: hidden;
52
+ position: relative;
53
+ &:focus-visible {
54
+ outline: none;
55
+ }
56
+ &:focus-visible::after {
57
+ content: "";
58
+ position: absolute;
59
+ inset: 0;
60
+ pointer-events: none;
61
+ border: 1px solid var(--dx-accentSurface);
62
+ }
51
63
  }
52
64
 
53
65
  .dx-grid__columnheader__content {
54
- border-block-end: 2px solid var(--dx-separator);
55
- grid-template-columns: repeat(99, 64px);
66
+ border-block-end: 2px solid var(--dx-grid-lines, var(--dx-separator));
56
67
  }
57
68
 
58
69
  .dx-grid__rowheader__content {
59
- border-inline-end: 2px solid var(--dx-separator);
70
+ border-inline-end: 2px solid var(--dx-grid-lines, var(--dx-separator));
60
71
  grid-template-columns: min-content;
61
72
  text-align: end;
62
73
  }
63
74
 
64
75
  .dx-grid {
65
76
  [role='gridcell'], [role='columnheader'], [role='rowheader'] {
66
- background: var(--dx-base);
77
+ background: var(--dx-grid-base, var(--dx-base));
67
78
  padding: 2px;
68
79
  box-sizing: border-box;
80
+ cursor: pointer;
81
+ border: 1px solid transparent;
69
82
  &[inert] {
70
83
  visibility: hidden;
71
84
  }
85
+ &:focus, &:focus-visible {
86
+ cursor: text;
87
+ position: relative;
88
+ z-index: 2;
89
+ border-color: var(--dx-accentSurface);
90
+ outline: none;
91
+ }
72
92
  }
73
93
  }
74
94
 
@@ -80,7 +100,7 @@ dx-grid {
80
100
  position: absolute;
81
101
  background: transparent;
82
102
  &:hover {
83
- background: var(--dx-hoverSurface)
103
+ background: var(--dx-grid-resizeHandleHover, var(--dx-hoverSurface));
84
104
  }
85
105
  }
86
106
  }
package/src/dx-grid.ts CHANGED
@@ -3,9 +3,11 @@
3
3
  //
4
4
 
5
5
  import { LitElement, html } from 'lit';
6
- import { customElement, state, property } from 'lit/decorators.js';
6
+ import { customElement, state, property, eventOptions } from 'lit/decorators.js';
7
7
  import { ref, createRef, type Ref } from 'lit/directives/ref.js';
8
8
 
9
+ import { DxAxisResize, type DxAxisResizeProps, type DxGridAxis } from './types';
10
+
9
11
  /**
10
12
  * The size in pixels of the gap between cells
11
13
  */
@@ -72,7 +74,7 @@ type AxisMeta = {
72
74
  resizeable?: boolean;
73
75
  };
74
76
 
75
- export type DxGridProps = Pick<DxGrid, 'cells' | 'rows' | 'columns' | 'rowDefault' | 'columnDefault'>;
77
+ export type DxGridProps = Partial<Pick<DxGrid, 'cells' | 'rows' | 'columns' | 'rowDefault' | 'columnDefault'>>;
76
78
 
77
79
  const localChId = (c0: number) => `ch--${c0}`;
78
80
  const localRhId = (r0: number) => `rh--${r0}`;
@@ -179,7 +181,7 @@ export class DxGrid extends LitElement {
179
181
  rowSizes: Record<string, number> = {};
180
182
 
181
183
  @state()
182
- resizing: null | { axis: 'col' | 'row'; page: number; size: number; index: string } = null;
184
+ resizing: null | (DxAxisResizeProps & { page: number }) = null;
183
185
 
184
186
  handlePointerDown = (event: PointerEvent) => {
185
187
  const actionEl = (event.target as HTMLElement)?.closest('[data-dx-grid-action]');
@@ -189,7 +191,7 @@ export class DxGrid extends LitElement {
189
191
  const [resize, index] = action.split(',');
190
192
  const [_, axis] = resize.split('-');
191
193
  this.resizing = {
192
- axis: axis as 'col' | 'row',
194
+ axis: axis as DxGridAxis,
193
195
  size: axis === 'col' ? this.colSize(index) : this.rowSize(index),
194
196
  page: getPage(axis, event),
195
197
  index,
@@ -199,7 +201,15 @@ export class DxGrid extends LitElement {
199
201
  };
200
202
 
201
203
  handlePointerUp = (_event: PointerEvent) => {
202
- this.resizing = null;
204
+ if (this.resizing) {
205
+ const resizeEvent = new DxAxisResize({
206
+ axis: this.resizing.axis,
207
+ index: this.resizing.index,
208
+ size: this[this.resizing.axis === 'col' ? 'colSize' : 'rowSize'](this.resizing.index),
209
+ });
210
+ this.dispatchEvent(resizeEvent);
211
+ this.resizing = null;
212
+ }
203
213
  };
204
214
 
205
215
  handlePointerMove = (event: PointerEvent) => {
@@ -299,12 +309,12 @@ export class DxGrid extends LitElement {
299
309
  }, 0) +
300
310
  gap * (overscanCol - 1);
301
311
 
302
- while (pxInline < this.binInlineMax + this.sizeInline) {
312
+ while (pxInline < this.binInlineMax + this.sizeInline + gap) {
303
313
  colIndex += 1;
304
314
  pxInline += this.colSize(colIndex) + gap;
305
315
  }
306
316
 
307
- this.visColMax = colIndex + overscanCol + 1;
317
+ this.visColMax = colIndex + overscanCol;
308
318
 
309
319
  this.templateColumns = [...Array(this.visColMax - this.visColMin)]
310
320
  .map((_, c0) => `${this.colSize(this.visColMin + c0)}px`)
@@ -338,7 +348,7 @@ export class DxGrid extends LitElement {
338
348
  pxBlock += this.rowSize(rowIndex) + gap;
339
349
  }
340
350
 
341
- this.visRowMax = rowIndex + overscanRow + 1;
351
+ this.visRowMax = rowIndex + overscanRow;
342
352
 
343
353
  this.templateRows = [...Array(this.visRowMax - this.visRowMin)]
344
354
  .map((_, r0) => `${this.rowSize(this.visRowMin + r0)}px`)
@@ -350,6 +360,133 @@ export class DxGrid extends LitElement {
350
360
  this.updateVisBlock();
351
361
  }
352
362
 
363
+ // Focus handlers
364
+
365
+ @state()
366
+ focusedCell: Record<DxGridAxis, number> = { col: 0, row: 0 };
367
+
368
+ @state()
369
+ focusActive: boolean = false;
370
+
371
+ @eventOptions({ capture: true })
372
+ handleFocus(event: FocusEvent) {
373
+ const target = event.target as HTMLElement;
374
+ const action = target.getAttribute('data-dx-grid-action');
375
+ if (action === 'cell') {
376
+ const c = parseInt(target.getAttribute('aria-colindex') ?? 'never');
377
+ const r = parseInt(target.getAttribute('aria-rowindex') ?? 'never');
378
+ this.focusedCell = { col: c, row: r };
379
+ this.focusActive = true;
380
+ }
381
+ }
382
+
383
+ @eventOptions({ capture: true })
384
+ handleBlur(event: FocusEvent) {
385
+ // Only unset `focusActive` if focus is not moving to an element within the grid.
386
+ if (
387
+ !event.relatedTarget ||
388
+ (event.relatedTarget as HTMLElement).closest('.dx-grid__viewport') !== this.viewportRef.value
389
+ ) {
390
+ this.focusActive = false;
391
+ }
392
+ }
393
+
394
+ /**
395
+ * Moves focus to the cell with actual focus, otherwise moves focus to the viewport.
396
+ */
397
+ refocus() {
398
+ (this.focusedCell.row < this.visRowMin ||
399
+ this.focusedCell.row > this.visRowMax ||
400
+ this.focusedCell.col < this.visColMin ||
401
+ this.focusedCell.col > this.visColMax
402
+ ? this.viewportRef.value
403
+ : (this.viewportRef.value?.querySelector(
404
+ `[aria-colindex="${this.focusedCell.col}"][aria-rowindex="${this.focusedCell.row}"]`,
405
+ ) as HTMLElement | null)
406
+ )?.focus({ preventScroll: true });
407
+ }
408
+
409
+ /**
410
+ * Updates `pos` so that a cell in focus is fully within the viewport
411
+ */
412
+ snapPosToFocusedCell() {
413
+ if (
414
+ this.focusedCell.col < this.visColMin ||
415
+ this.focusedCell.col > this.visColMax ||
416
+ this.focusedCell.row < this.visRowMin ||
417
+ this.focusedCell.row > this.visRowMax
418
+ ) {
419
+ // console.warn('Snapping position to a focused cell that is not already mounted is unsupported.');
420
+ } else if (
421
+ this.focusedCell.col > this.visColMin + overscanCol &&
422
+ this.focusedCell.col < this.visColMax - overscanCol - 1 &&
423
+ this.focusedCell.row > this.visRowMin + overscanRow &&
424
+ this.focusedCell.row < this.visRowMax - overscanRow - 1
425
+ ) {
426
+ // console.log(
427
+ // '[within bounds]',
428
+ // this.focusedCell,
429
+ // [this.visColMin, this.visColMax, overscanCol],
430
+ // [this.visRowMin, this.visRowMax, overscanRow],
431
+ // );
432
+ } else {
433
+ if (this.focusedCell.col <= this.visColMin + overscanCol) {
434
+ this.posInline = this.binInlineMin;
435
+ this.updateVisInline();
436
+ } else if (this.focusedCell.col >= this.visColMax - overscanCol - 1) {
437
+ const sizeSumCol = [...Array(this.focusedCell.col - this.visColMin)].reduce((acc, _, c0) => {
438
+ acc += this.colSize(this.visColMin + overscanCol + c0) + gap;
439
+ return acc;
440
+ }, 0);
441
+ this.posInline = this.binInlineMin + sizeSumCol + gap * 2 - this.sizeInline;
442
+ this.updateVisInline();
443
+ }
444
+
445
+ if (this.focusedCell.row <= this.visRowMin + overscanRow) {
446
+ this.posBlock = this.binBlockMin;
447
+ this.updateVisBlock();
448
+ } else if (this.focusedCell.row >= this.visRowMax - overscanRow - 1) {
449
+ const sizeSumRow = [...Array(this.focusedCell.row - this.visRowMin)].reduce((acc, _, r0) => {
450
+ acc += this.rowSize(this.visRowMin + overscanRow + r0) + gap;
451
+ return acc;
452
+ }, 0);
453
+ this.posBlock = this.binBlockMin + sizeSumRow + gap * 2 - this.sizeBlock;
454
+ this.updateVisBlock();
455
+ }
456
+ }
457
+ }
458
+
459
+ // Keyboard interactions
460
+ handleKeydown(event: KeyboardEvent) {
461
+ if (this.focusActive) {
462
+ // Adjust state
463
+ switch (event.key) {
464
+ case 'ArrowDown':
465
+ this.focusedCell = { ...this.focusedCell, row: this.focusedCell.row + 1 };
466
+ break;
467
+ case 'ArrowUp':
468
+ this.focusedCell = { ...this.focusedCell, row: Math.max(0, this.focusedCell.row - 1) };
469
+ break;
470
+ case 'ArrowRight':
471
+ this.focusedCell = { ...this.focusedCell, col: this.focusedCell.col + 1 };
472
+ break;
473
+ case 'ArrowLeft':
474
+ this.focusedCell = { ...this.focusedCell, col: Math.max(0, this.focusedCell.col - 1) };
475
+ break;
476
+ }
477
+ // Handle virtualization & focus consequences
478
+ switch (event.key) {
479
+ case 'ArrowDown':
480
+ case 'ArrowUp':
481
+ case 'ArrowRight':
482
+ case 'ArrowLeft':
483
+ event.preventDefault();
484
+ this.snapPosToFocusedCell();
485
+ break;
486
+ }
487
+ }
488
+ }
489
+
353
490
  //
354
491
  // Render and other lifecycle methods
355
492
  //
@@ -357,9 +494,8 @@ export class DxGrid extends LitElement {
357
494
  override render() {
358
495
  const visibleCols = this.visColMax - this.visColMin;
359
496
  const visibleRows = this.visRowMax - this.visRowMin;
360
- // TODO NEXT -> ensure offset is using the right components
361
- const offsetInline = this.binInlineMin - this.posInline - this.overscanInline;
362
- const offsetBlock = this.binBlockMin - this.posBlock - this.overscanBlock;
497
+ const offsetInline = gap + this.binInlineMin - this.posInline - this.overscanInline;
498
+ const offsetBlock = gap + this.binBlockMin - this.posBlock - this.overscanBlock;
363
499
 
364
500
  return html`<div
365
501
  role="none"
@@ -367,6 +503,9 @@ export class DxGrid extends LitElement {
367
503
  @pointerdown=${this.handlePointerDown}
368
504
  @pointerup=${this.handlePointerUp}
369
505
  @pointermove=${this.handlePointerMove}
506
+ @focus=${this.handleFocus}
507
+ @blur=${this.handleBlur}
508
+ @keydown=${this.handleKeydown}
370
509
  >
371
510
  <div role="none" class="dx-grid__corner"></div>
372
511
  <div role="none" class="dx-grid__columnheader">
@@ -380,8 +519,7 @@ export class DxGrid extends LitElement {
380
519
  return html`<div
381
520
  role="columnheader"
382
521
  ?inert=${c < 0}
383
- style="inline-size:${this.colSize(c)}px;block-size:${this.rowDefault.size}px;grid-column:${c0 + 1}/${c0 +
384
- 2};"
522
+ style="block-size:${this.rowDefault.size}px;grid-column:${c0 + 1}/${c0 + 2};"
385
523
  >
386
524
  <span id=${localChId(c0)}>${colToA1Notation(c)}</span>
387
525
  ${(this.columns[c]?.resizeable ?? this.columnDefault.resizeable) &&
@@ -394,14 +532,14 @@ export class DxGrid extends LitElement {
394
532
  </div>
395
533
  <div role="none" class="dx-grid__corner"></div>
396
534
  <div role="none" class="dx-grid__rowheader">
397
- <div role="none" class="dx-grid__rowheader__content" style="transform:translate3d(0,${offsetBlock}px,0);">
535
+ <div
536
+ role="none"
537
+ class="dx-grid__rowheader__content"
538
+ style="transform:translate3d(0,${offsetBlock}px,0);grid-template-rows:${this.templateRows};"
539
+ >
398
540
  ${[...Array(visibleRows)].map((_, r0) => {
399
541
  const r = this.visRowMin + r0;
400
- return html`<div
401
- role="rowheader"
402
- ?inert=${r < 0}
403
- style="block-size:${this.rowSize(r)}px;grid-row:${r0 + 1}/${r0 + 2}"
404
- >
542
+ return html`<div role="rowheader" ?inert=${r < 0} style="grid-row:${r0 + 1}/${r0 + 2}">
405
543
  <span id=${localRhId(r0)}>${rowToA1Notation(r)}</span>
406
544
  ${(this.rows[r]?.resizeable ?? this.rowDefault.resizeable) &&
407
545
  html`<button class="dx-grid__resize-handle" data-dx-grid-action=${`resize-row,${r}`}>
@@ -411,9 +549,9 @@ export class DxGrid extends LitElement {
411
549
  })}
412
550
  </div>
413
551
  </div>
414
- <div role="none" class="dx-grid__viewport" @wheel="${this.handleWheel}" ${ref(this.viewportRef)}>
552
+ <div role="grid" class="dx-grid__viewport" tabindex="0" @wheel=${this.handleWheel} ${ref(this.viewportRef)}>
415
553
  <div
416
- role="grid"
554
+ role="none"
417
555
  class="dx-grid__content"
418
556
  style="transform:translate3d(${offsetInline}px,${offsetBlock}px,0);grid-template-columns:${this
419
557
  .templateColumns};grid-template-rows:${this.templateRows};"
@@ -425,6 +563,7 @@ export class DxGrid extends LitElement {
425
563
  const cell = this.getCell(c, r);
426
564
  return html`<div
427
565
  role="gridcell"
566
+ tabindex="0"
428
567
  ?inert=${c < 0 || r < 0}
429
568
  aria-rowindex=${r}
430
569
  aria-colindex=${c}
@@ -464,6 +603,16 @@ export class DxGrid extends LitElement {
464
603
  }, {});
465
604
  }
466
605
 
606
+ override updated(changedProperties: Map<string, any>) {
607
+ // Update the focused element if there is a change in bounds (otherwise Lit keeps focus on the relative element).
608
+ if (
609
+ this.focusActive &&
610
+ (changedProperties.has('visRowMin') || changedProperties.has('visColMin') || changedProperties.has('focusedCell'))
611
+ ) {
612
+ this.refocus();
613
+ }
614
+ }
615
+
467
616
  override disconnectedCallback() {
468
617
  super.disconnectedCallback();
469
618
  // console.log('[disconnected]', this.viewportRef.value);
package/src/index.ts CHANGED
@@ -2,4 +2,5 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- export { DxGrid, type DxGridProps } from './dx-grid';
5
+ export * from './dx-grid';
6
+ export * from './types';
package/src/types.ts ADDED
@@ -0,0 +1,19 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ export type DxGridAxis = 'row' | 'col';
6
+
7
+ export type DxAxisResizeProps = Pick<DxAxisResize, 'axis' | 'index' | 'size'>;
8
+
9
+ export class DxAxisResize extends Event {
10
+ public readonly axis: DxGridAxis;
11
+ public readonly index: string;
12
+ public readonly size: number;
13
+ constructor(props: DxAxisResizeProps) {
14
+ super('dx-axis-resize');
15
+ this.axis = props.axis;
16
+ this.index = props.index;
17
+ this.size = props.size;
18
+ }
19
+ }