@dxos/lit-grid 0.8.4-main.67995b8 → 0.8.4-main.69d29f4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/defs.d.ts +1 -0
- package/dist/src/defs.d.ts.map +1 -1
- package/dist/src/defs.js +1 -0
- package/dist/src/defs.js.map +1 -1
- package/dist/src/dx-grid-axis-resize-handle.d.ts.map +1 -1
- package/dist/src/dx-grid-axis-resize-handle.js +3 -5
- package/dist/src/dx-grid-axis-resize-handle.js.map +1 -1
- package/dist/src/dx-grid-multiselect-cell.d.ts.map +1 -1
- package/dist/src/dx-grid-multiselect-cell.js +2 -1
- package/dist/src/dx-grid-multiselect-cell.js.map +1 -1
- package/dist/src/dx-grid.d.ts +12 -7
- package/dist/src/dx-grid.d.ts.map +1 -1
- package/dist/src/dx-grid.js +196 -162
- package/dist/src/dx-grid.js.map +1 -1
- package/dist/src/dx-grid.lit-stories.js +17 -20
- package/dist/src/dx-grid.lit-stories.js.map +1 -1
- package/dist/src/playwright/dx-grid.spec.js.map +1 -1
- package/dist/src/playwright/playwright.config.js +1 -1
- package/dist/src/testing/dx-grid-manager.d.ts.map +1 -1
- package/dist/src/testing/dx-grid-manager.js.map +1 -1
- package/dist/src/types.d.ts +9 -0
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/types.js.map +1 -1
- package/dist/src/util.d.ts +4 -1
- package/dist/src/util.d.ts.map +1 -1
- package/dist/src/util.js +11 -11
- package/dist/src/util.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +13 -6
- package/src/defs.ts +1 -0
- package/src/dx-grid-axis-resize-handle.pcss +6 -0
- package/src/dx-grid-axis-resize-handle.ts +1 -1
- package/src/dx-grid-multiselect-cell.ts +2 -1
- package/src/dx-grid.pcss +22 -9
- package/src/dx-grid.ts +190 -109
- package/src/playwright/dx-grid.spec.ts +1 -1
- package/src/playwright/playwright.config.ts +1 -1
- package/src/testing/dx-grid-manager.ts +1 -1
- package/src/types.ts +11 -0
- package/src/util.ts +13 -9
package/src/dx-grid.ts
CHANGED
|
@@ -3,73 +3,75 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { LitElement, html, nothing } from 'lit';
|
|
6
|
-
import { customElement,
|
|
7
|
-
import {
|
|
6
|
+
import { customElement, property, state } from 'lit/decorators.js';
|
|
7
|
+
import { type Ref, createRef, ref } from 'lit/directives/ref.js';
|
|
8
8
|
import { styleMap } from 'lit/directives/style-map.js';
|
|
9
|
-
import {
|
|
9
|
+
import { html as staticHtml, unsafeStatic } from 'lit/static-html.js';
|
|
10
10
|
|
|
11
|
-
import { defaultColSize, defaultRowSize } from './defs';
|
|
11
|
+
import { defaultColSize, defaultRowSize, focusUnfurlDefault } from './defs';
|
|
12
12
|
import './dx-grid-axis-resize-handle';
|
|
13
13
|
import {
|
|
14
|
-
type DxGridAxisMetaProps,
|
|
15
|
-
type DxGridAxisSizes,
|
|
16
|
-
type DxGridPlaneCellIndex,
|
|
17
|
-
type DxGridCellValue,
|
|
18
14
|
DxAxisResize,
|
|
19
15
|
type DxAxisResizeInternal,
|
|
20
16
|
DxEditRequest,
|
|
17
|
+
type DxGridAnnotatedPanEvent,
|
|
18
|
+
type DxGridAxis,
|
|
21
19
|
type DxGridAxisMeta,
|
|
20
|
+
type DxGridAxisMetaProps,
|
|
21
|
+
type DxGridAxisSizes,
|
|
22
|
+
type DxGridCellValue,
|
|
22
23
|
type DxGridCells,
|
|
23
24
|
DxGridCellsSelect,
|
|
24
25
|
type DxGridFixedPlane,
|
|
26
|
+
type DxGridFocusIndicatorVariant,
|
|
25
27
|
type DxGridFrozenAxes,
|
|
26
28
|
type DxGridFrozenColsPlane,
|
|
27
29
|
type DxGridFrozenPlane,
|
|
28
30
|
type DxGridFrozenRowsPlane,
|
|
29
31
|
type DxGridMode,
|
|
32
|
+
type DxGridOverscroll,
|
|
30
33
|
type DxGridPlane,
|
|
34
|
+
type DxGridPlaneCellIndex,
|
|
31
35
|
type DxGridPlaneCells,
|
|
32
36
|
type DxGridPlaneRange,
|
|
33
37
|
type DxGridPlaneRecord,
|
|
34
38
|
type DxGridPointer,
|
|
35
39
|
type DxGridPosition,
|
|
36
|
-
type DxGridAxis,
|
|
37
|
-
type DxGridSelectionProps,
|
|
38
|
-
type DxGridAnnotatedPanEvent,
|
|
39
40
|
type DxGridRange,
|
|
41
|
+
type DxGridSelectionProps,
|
|
40
42
|
separator,
|
|
41
43
|
} from './types';
|
|
42
44
|
import {
|
|
43
|
-
toCellIndex,
|
|
44
|
-
gap,
|
|
45
|
-
resizeTolerance,
|
|
46
|
-
sizeColMin,
|
|
47
|
-
sizeColMax,
|
|
48
|
-
sizeRowMin,
|
|
49
|
-
sizeRowMax,
|
|
50
|
-
shouldSelect,
|
|
51
|
-
selectionProps,
|
|
52
45
|
cellSelected,
|
|
53
46
|
closestAction,
|
|
54
47
|
closestCell,
|
|
55
|
-
|
|
56
|
-
|
|
48
|
+
gap,
|
|
49
|
+
isReadonly,
|
|
50
|
+
isSameCell,
|
|
51
|
+
resizeTolerance,
|
|
57
52
|
resolveColPlane,
|
|
58
53
|
resolveFrozenPlane,
|
|
59
|
-
|
|
60
|
-
|
|
54
|
+
resolveRowPlane,
|
|
55
|
+
selectionProps,
|
|
56
|
+
shouldSelect,
|
|
57
|
+
sizeColMax,
|
|
58
|
+
sizeColMin,
|
|
59
|
+
sizeRowMax,
|
|
60
|
+
sizeRowMin,
|
|
61
|
+
targetIsPlane,
|
|
62
|
+
toCellIndex,
|
|
61
63
|
} from './util';
|
|
62
64
|
|
|
63
65
|
@customElement('dx-grid')
|
|
64
66
|
export class DxGrid extends LitElement {
|
|
65
67
|
constructor() {
|
|
66
68
|
super();
|
|
67
|
-
// Wheel, top-level and element-level
|
|
69
|
+
// Wheel, top-level and element-level.
|
|
68
70
|
document.defaultView?.addEventListener('wheel', this.handleTopLevelWheel, { passive: false });
|
|
69
71
|
this.addEventListener('wheel', this.handleWheel);
|
|
70
|
-
// Custom event(s)
|
|
72
|
+
// Custom event(s).
|
|
71
73
|
this.addEventListener('dx-axis-resize-internal', this.handleAxisResizeInternal as EventListener);
|
|
72
|
-
// Standard events
|
|
74
|
+
// Standard events.
|
|
73
75
|
this.addEventListener('pointerdown', this.handlePointerDown);
|
|
74
76
|
this.addEventListener('pointermove', this.handlePointerMove);
|
|
75
77
|
this.addEventListener('pointerup', this.handlePointerUp);
|
|
@@ -83,12 +85,12 @@ export class DxGrid extends LitElement {
|
|
|
83
85
|
gridId: string = 'default-grid-id';
|
|
84
86
|
|
|
85
87
|
@property({ type: Object })
|
|
86
|
-
rowDefault: DxGridPlaneRecord<DxGridFrozenRowsPlane, DxGridAxisMetaProps
|
|
88
|
+
rowDefault: Partial<DxGridPlaneRecord<DxGridFrozenRowsPlane, Partial<DxGridAxisMetaProps>>> = {
|
|
87
89
|
grid: { size: defaultRowSize },
|
|
88
90
|
};
|
|
89
91
|
|
|
90
92
|
@property({ type: Object })
|
|
91
|
-
columnDefault: DxGridPlaneRecord<DxGridFrozenColsPlane, DxGridAxisMetaProps
|
|
93
|
+
columnDefault: Partial<DxGridPlaneRecord<DxGridFrozenColsPlane, Partial<DxGridAxisMetaProps>>> = {
|
|
92
94
|
grid: { size: defaultColSize },
|
|
93
95
|
};
|
|
94
96
|
|
|
@@ -114,11 +116,14 @@ export class DxGrid extends LitElement {
|
|
|
114
116
|
frozen: DxGridFrozenAxes = {};
|
|
115
117
|
|
|
116
118
|
@property({ type: String })
|
|
117
|
-
overscroll:
|
|
119
|
+
overscroll: DxGridOverscroll = undefined;
|
|
118
120
|
|
|
119
121
|
@property({ type: String })
|
|
120
122
|
activeRefs = '';
|
|
121
123
|
|
|
124
|
+
@property({ type: String })
|
|
125
|
+
focusIndicatorVariant: DxGridFocusIndicatorVariant = 'sheet';
|
|
126
|
+
|
|
122
127
|
/**
|
|
123
128
|
* When this function is defined, it is used first to try to get a value for a cell,
|
|
124
129
|
* and otherwise will fall back to `cells`.
|
|
@@ -194,6 +199,7 @@ export class DxGrid extends LitElement {
|
|
|
194
199
|
//
|
|
195
200
|
// `template` is the rendered value of `grid-{axis}-template`.
|
|
196
201
|
//
|
|
202
|
+
|
|
197
203
|
@state()
|
|
198
204
|
private templateGridColumns = '0';
|
|
199
205
|
|
|
@@ -212,6 +218,16 @@ export class DxGrid extends LitElement {
|
|
|
212
218
|
@state()
|
|
213
219
|
private templatefrozenRowsEnd = '';
|
|
214
220
|
|
|
221
|
+
//
|
|
222
|
+
// `frozen…Size` is used to measure space available for the non-fixed planes
|
|
223
|
+
//
|
|
224
|
+
|
|
225
|
+
@state()
|
|
226
|
+
private frozenColsSize = 0;
|
|
227
|
+
|
|
228
|
+
@state()
|
|
229
|
+
private frozenRowsSize = 0;
|
|
230
|
+
|
|
215
231
|
//
|
|
216
232
|
// Focus, selection, and resize states
|
|
217
233
|
//
|
|
@@ -307,7 +323,7 @@ export class DxGrid extends LitElement {
|
|
|
307
323
|
this.dispatchSelectionChange();
|
|
308
324
|
}
|
|
309
325
|
if (this.mode === 'edit-select') {
|
|
310
|
-
// Prevent focus moving when editing while selection is possible
|
|
326
|
+
// Prevent focus moving when editing while selection is possible.
|
|
311
327
|
event.preventDefault();
|
|
312
328
|
} else if (this.focusActive && isSameCell(this.focusedCell, cellCoords)) {
|
|
313
329
|
this.dispatchEditRequest();
|
|
@@ -415,15 +431,13 @@ export class DxGrid extends LitElement {
|
|
|
415
431
|
}
|
|
416
432
|
|
|
417
433
|
private moveFocusIntoPlane(plane: DxGridPlane): void {
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
};
|
|
426
|
-
}
|
|
434
|
+
const colPlane = resolveColPlane(plane);
|
|
435
|
+
const rowPlane = resolveRowPlane(plane);
|
|
436
|
+
this.focusedCell = {
|
|
437
|
+
plane,
|
|
438
|
+
col: colPlane === 'grid' ? this.visColMin : 0,
|
|
439
|
+
row: rowPlane === 'grid' ? this.visRowMin : 0,
|
|
440
|
+
};
|
|
427
441
|
this.focusedCellElement()?.focus({ preventScroll: true });
|
|
428
442
|
}
|
|
429
443
|
|
|
@@ -580,7 +594,7 @@ export class DxGrid extends LitElement {
|
|
|
580
594
|
}
|
|
581
595
|
|
|
582
596
|
//
|
|
583
|
-
// Resize & reposition handlers, observer, ref
|
|
597
|
+
// Resize & reposition handlers, observer, ref.
|
|
584
598
|
//
|
|
585
599
|
|
|
586
600
|
@state()
|
|
@@ -590,19 +604,18 @@ export class DxGrid extends LitElement {
|
|
|
590
604
|
blockSize: 0,
|
|
591
605
|
};
|
|
592
606
|
if (
|
|
593
|
-
Math.abs(inlineSize - this.sizeInline) > resizeTolerance ||
|
|
594
|
-
Math.abs(blockSize - this.sizeBlock) > resizeTolerance
|
|
607
|
+
Math.abs(inlineSize - this.frozenColsSize - this.sizeInline) > resizeTolerance ||
|
|
608
|
+
Math.abs(blockSize - this.frozenRowsSize - this.sizeBlock) > resizeTolerance
|
|
595
609
|
) {
|
|
596
610
|
// console.info('[updating bounds]', 'resize', [inlineSize - this.sizeInline, blockSize - this.sizeBlock]);
|
|
597
|
-
this.sizeInline = inlineSize;
|
|
598
|
-
this.sizeBlock = blockSize;
|
|
611
|
+
this.sizeInline = inlineSize - this.frozenColsSize;
|
|
612
|
+
this.sizeBlock = blockSize - this.frozenRowsSize;
|
|
599
613
|
this.updateVis();
|
|
600
614
|
queueMicrotask(() => this.updatePos());
|
|
601
615
|
}
|
|
602
616
|
});
|
|
603
617
|
|
|
604
618
|
private gridRef: Ref<HTMLDivElement> = createRef();
|
|
605
|
-
private viewportRef: Ref<HTMLDivElement> = createRef();
|
|
606
619
|
|
|
607
620
|
private maybeUpdateVisInline = () => {
|
|
608
621
|
if (this.posInline < this.binInlineMin || this.posInline >= this.binInlineMax) {
|
|
@@ -681,7 +694,7 @@ export class DxGrid extends LitElement {
|
|
|
681
694
|
};
|
|
682
695
|
|
|
683
696
|
private updateVisInline(): void {
|
|
684
|
-
// todo: avoid starting from zero
|
|
697
|
+
// todo: avoid starting from zero.
|
|
685
698
|
let axisCursor = 0;
|
|
686
699
|
let pxCursor = this.colSize(axisCursor, 'grid');
|
|
687
700
|
|
|
@@ -727,10 +740,19 @@ export class DxGrid extends LitElement {
|
|
|
727
740
|
this.templatefrozenColsEnd = [...Array(this.frozen.frozenColsEnd ?? 0)]
|
|
728
741
|
.map((_, c0) => `${this.colSize(c0, 'frozenColsEnd')}px`)
|
|
729
742
|
.join(' ');
|
|
743
|
+
|
|
744
|
+
this.frozenColsSize =
|
|
745
|
+
[...Array(this.frozen.frozenColsStart ?? 0)].reduce(
|
|
746
|
+
(sum, _, c0) => sum + this.colSize(c0, 'frozenColsStart'),
|
|
747
|
+
0,
|
|
748
|
+
) +
|
|
749
|
+
gap * Math.max(0, this.frozen.frozenColsStart ?? 0 - 1) +
|
|
750
|
+
[...Array(this.frozen.frozenColsEnd ?? 0)].reduce((sum, _, c0) => sum + this.colSize(c0, 'frozenColsEnd'), 0) +
|
|
751
|
+
gap * Math.max(0, this.frozen.frozenColsEnd ?? 0 - 1);
|
|
730
752
|
}
|
|
731
753
|
|
|
732
754
|
private updateVisBlock(): void {
|
|
733
|
-
// todo: avoid starting from zero
|
|
755
|
+
// todo: avoid starting from zero.
|
|
734
756
|
let axisCursor = 0;
|
|
735
757
|
let pxCursor = this.rowSize(axisCursor, 'grid');
|
|
736
758
|
|
|
@@ -776,6 +798,15 @@ export class DxGrid extends LitElement {
|
|
|
776
798
|
this.templatefrozenRowsEnd = [...Array(this.frozen.frozenRowsEnd ?? 0)]
|
|
777
799
|
.map((_, r0) => `${this.rowSize(r0, 'frozenRowsEnd')}px`)
|
|
778
800
|
.join(' ');
|
|
801
|
+
|
|
802
|
+
this.frozenRowsSize =
|
|
803
|
+
[...Array(this.frozen.frozenRowsStart ?? 0)].reduce(
|
|
804
|
+
(sum, _, r0) => sum + this.rowSize(r0, 'frozenRowsStart'),
|
|
805
|
+
0,
|
|
806
|
+
) +
|
|
807
|
+
gap * Math.max(0, this.frozen.frozenRowsStart ?? 0 - 1) +
|
|
808
|
+
[...Array(this.frozen.frozenRowsEnd ?? 0)].reduce((sum, _, r0) => sum + this.rowSize(r0, 'frozenRowsEnd'), 0) +
|
|
809
|
+
gap * Math.max(0, this.frozen.frozenRowsEnd ?? 0 - 1);
|
|
779
810
|
}
|
|
780
811
|
|
|
781
812
|
private updateVis(): void {
|
|
@@ -997,7 +1028,7 @@ export class DxGrid extends LitElement {
|
|
|
997
1028
|
}
|
|
998
1029
|
|
|
999
1030
|
/**
|
|
1000
|
-
* Updates `pos` so that a cell in focus is fully within the viewport
|
|
1031
|
+
* Updates `pos` so that a cell in focus is fully within the viewport.
|
|
1001
1032
|
*/
|
|
1002
1033
|
snapPosToFocusedCell(): void {
|
|
1003
1034
|
const outOfVis = this.focusedCellOutOfVis();
|
|
@@ -1074,16 +1105,40 @@ export class DxGrid extends LitElement {
|
|
|
1074
1105
|
: !!(this.rows[plane]?.[index]?.resizeable ?? this.rowDefault[plane as DxGridFrozenRowsPlane]?.resizeable);
|
|
1075
1106
|
}
|
|
1076
1107
|
|
|
1108
|
+
private clampAxisSize(
|
|
1109
|
+
plane: 'grid' | DxGridFrozenPlane,
|
|
1110
|
+
axis: DxGridAxis,
|
|
1111
|
+
index: number | string,
|
|
1112
|
+
requestedSize: number,
|
|
1113
|
+
): number {
|
|
1114
|
+
const minSize =
|
|
1115
|
+
axis === 'col'
|
|
1116
|
+
? (this.columns[plane]?.[index]?.minSize ??
|
|
1117
|
+
this.columnDefault[plane as DxGridFrozenColsPlane]?.minSize ??
|
|
1118
|
+
sizeColMin)
|
|
1119
|
+
: (this.rows[plane]?.[index]?.minSize ??
|
|
1120
|
+
this.rowDefault[plane as DxGridFrozenRowsPlane]?.minSize ??
|
|
1121
|
+
sizeRowMin);
|
|
1122
|
+
const maxSize =
|
|
1123
|
+
axis === 'col'
|
|
1124
|
+
? (this.columns[plane]?.[index]?.maxSize ??
|
|
1125
|
+
this.columnDefault[plane as DxGridFrozenColsPlane]?.maxSize ??
|
|
1126
|
+
sizeColMax)
|
|
1127
|
+
: (this.rows[plane]?.[index]?.maxSize ??
|
|
1128
|
+
this.rowDefault[plane as DxGridFrozenRowsPlane]?.maxSize ??
|
|
1129
|
+
sizeRowMax);
|
|
1130
|
+
return Math.max(minSize, Math.min(maxSize, requestedSize));
|
|
1131
|
+
}
|
|
1132
|
+
|
|
1077
1133
|
private handleAxisResizeInternal(event: DxAxisResizeInternal): void {
|
|
1078
1134
|
event.stopPropagation();
|
|
1079
1135
|
const { plane, axis, delta, size, index, state } = event;
|
|
1136
|
+
const nextSize = this.clampAxisSize(plane, axis, index, size + delta);
|
|
1080
1137
|
if (axis === 'col') {
|
|
1081
|
-
const nextSize = Math.max(sizeColMin, Math.min(sizeColMax, size + delta));
|
|
1082
1138
|
this.colSizes = { ...this.colSizes, [plane]: { ...this.colSizes[plane], [index]: nextSize } };
|
|
1083
1139
|
this.updateVisInline();
|
|
1084
1140
|
this.updateIntrinsicInlineSize();
|
|
1085
1141
|
} else {
|
|
1086
|
-
const nextSize = Math.max(sizeRowMin, Math.min(sizeRowMax, size + delta));
|
|
1087
1142
|
this.rowSizes = { ...this.colSizes, [plane]: { ...this.rowSizes[plane], [index]: nextSize } };
|
|
1088
1143
|
this.updateVisBlock();
|
|
1089
1144
|
this.updateIntrinsicBlockSize();
|
|
@@ -1101,7 +1156,7 @@ export class DxGrid extends LitElement {
|
|
|
1101
1156
|
}
|
|
1102
1157
|
|
|
1103
1158
|
//
|
|
1104
|
-
// Render and other lifecycle methods
|
|
1159
|
+
// Render and other lifecycle methods.
|
|
1105
1160
|
//
|
|
1106
1161
|
|
|
1107
1162
|
// TODO(thure): This is for rendering presentational objects superimposed onto the canonical grid (e.g. DnD drop line for #8108).
|
|
@@ -1184,7 +1239,7 @@ export class DxGrid extends LitElement {
|
|
|
1184
1239
|
) {
|
|
1185
1240
|
const rowPlane = resolveRowPlane(plane) as DxGridFrozenPlane;
|
|
1186
1241
|
const rows = this.frozen[rowPlane];
|
|
1187
|
-
return (rows ?? 0) > 0
|
|
1242
|
+
return (rows ?? 0) > 0 && this.limitColumns > 0
|
|
1188
1243
|
? html`<div
|
|
1189
1244
|
role="none"
|
|
1190
1245
|
class="dx-grid__plane--frozen-row"
|
|
@@ -1218,7 +1273,7 @@ export class DxGrid extends LitElement {
|
|
|
1218
1273
|
) {
|
|
1219
1274
|
const colPlane = resolveColPlane(plane) as DxGridFrozenPlane;
|
|
1220
1275
|
const cols = this.frozen[colPlane];
|
|
1221
|
-
return (cols ?? 0) > 0
|
|
1276
|
+
return (cols ?? 0) > 0 && this.limitRows > 0
|
|
1222
1277
|
? html`<div
|
|
1223
1278
|
role="none"
|
|
1224
1279
|
class="dx-grid__plane--frozen-col"
|
|
@@ -1244,6 +1299,40 @@ export class DxGrid extends LitElement {
|
|
|
1244
1299
|
: null;
|
|
1245
1300
|
}
|
|
1246
1301
|
|
|
1302
|
+
private renderMainGrid(
|
|
1303
|
+
visibleCols: number,
|
|
1304
|
+
visibleRows: number,
|
|
1305
|
+
offsetInline: number,
|
|
1306
|
+
offsetBlock: number,
|
|
1307
|
+
selection: DxGridSelectionProps,
|
|
1308
|
+
) {
|
|
1309
|
+
return this.limitRows > 0 && this.limitColumns > 0
|
|
1310
|
+
? html`<div
|
|
1311
|
+
role="grid"
|
|
1312
|
+
class="dx-grid__plane--grid"
|
|
1313
|
+
tabindex="0"
|
|
1314
|
+
data-dx-grid-plane="grid"
|
|
1315
|
+
data-dx-grid-plane-row="1"
|
|
1316
|
+
data-dx-grid-plane-col="1"
|
|
1317
|
+
>
|
|
1318
|
+
<div
|
|
1319
|
+
role="none"
|
|
1320
|
+
class="dx-grid__plane--grid__content"
|
|
1321
|
+
style="transform:translate3d(${offsetInline}px,${offsetBlock}px,0);grid-template-columns:${this
|
|
1322
|
+
.templateGridColumns};grid-template-rows:${this.templateGridRows};"
|
|
1323
|
+
>
|
|
1324
|
+
${[...Array(visibleRows)].map((_, r0) => {
|
|
1325
|
+
return [...Array(visibleCols)].map((_, c0) => {
|
|
1326
|
+
const c = c0 + this.visColMin;
|
|
1327
|
+
const r = r0 + this.visRowMin;
|
|
1328
|
+
return this.renderCell(c, r, 'grid', cellSelected(c, r, 'grid', selection), c0, r0);
|
|
1329
|
+
});
|
|
1330
|
+
})}
|
|
1331
|
+
</div>
|
|
1332
|
+
</div>`
|
|
1333
|
+
: null;
|
|
1334
|
+
}
|
|
1335
|
+
|
|
1247
1336
|
private cellReadonly(col: number, row: number, plane: DxGridPlane): boolean {
|
|
1248
1337
|
const colPlane = resolveColPlane(plane);
|
|
1249
1338
|
const rowPlane = resolveRowPlane(plane);
|
|
@@ -1261,6 +1350,23 @@ export class DxGrid extends LitElement {
|
|
|
1261
1350
|
return isReadonly(colReadOnly) || isReadonly(rowReadOnly);
|
|
1262
1351
|
}
|
|
1263
1352
|
|
|
1353
|
+
private cellFocusUnfurl(col: number, row: number, plane: DxGridPlane): boolean {
|
|
1354
|
+
const colPlane = resolveColPlane(plane);
|
|
1355
|
+
const rowPlane = resolveRowPlane(plane);
|
|
1356
|
+
|
|
1357
|
+
// Check cell-specific setting first.
|
|
1358
|
+
const cellUnfurl = this.cell(col, row, plane)?.focusUnfurl;
|
|
1359
|
+
if (cellUnfurl !== undefined) {
|
|
1360
|
+
return cellUnfurl;
|
|
1361
|
+
}
|
|
1362
|
+
|
|
1363
|
+
// Check column/row defaults.
|
|
1364
|
+
const colUnfurl = this.columns?.[colPlane]?.[col]?.focusUnfurl ?? this.columnDefault?.[colPlane]?.focusUnfurl;
|
|
1365
|
+
const rowUnfurl = this.rows?.[rowPlane]?.[row]?.focusUnfurl ?? this.rowDefault?.[rowPlane]?.focusUnfurl;
|
|
1366
|
+
|
|
1367
|
+
return colUnfurl ?? rowUnfurl ?? focusUnfurlDefault;
|
|
1368
|
+
}
|
|
1369
|
+
|
|
1264
1370
|
/**
|
|
1265
1371
|
* Determines if the cell's text content should be selectable based on its readonly value.
|
|
1266
1372
|
* @returns true if the cells text content is selectable, false otherwise.
|
|
@@ -1323,6 +1429,7 @@ export class DxGrid extends LitElement {
|
|
|
1323
1429
|
const cell = this.cell(col, row, plane);
|
|
1324
1430
|
const active = this.cellActive(col, row, plane);
|
|
1325
1431
|
const readonly = this.cellReadonly(col, row, plane);
|
|
1432
|
+
const focusUnfurl = this.cellFocusUnfurl(col, row, plane);
|
|
1326
1433
|
const textSelectable = this.cellTextSelectable(col, row, plane);
|
|
1327
1434
|
const resizeIndex = cell?.resizeHandle ? (cell.resizeHandle === 'col' ? col : row) : undefined;
|
|
1328
1435
|
const resizePlane = cell?.resizeHandle ? resolveFrozenPlane(cell.resizeHandle, plane) : undefined;
|
|
@@ -1334,11 +1441,13 @@ export class DxGrid extends LitElement {
|
|
|
1334
1441
|
aria-readonly=${readonly ? 'true' : nothing}
|
|
1335
1442
|
class=${cell?.className ?? nothing}
|
|
1336
1443
|
data-refs=${cell?.dataRefs ?? nothing}
|
|
1444
|
+
data-focus-unfurl=${focusUnfurl ? nothing : 'false'}
|
|
1337
1445
|
?data-dx-active=${active}
|
|
1338
1446
|
data-text-selectable=${textSelectable ? 'true' : 'false'}
|
|
1339
1447
|
data-dx-grid-action="cell"
|
|
1340
1448
|
aria-colindex=${col}
|
|
1341
1449
|
aria-rowindex=${row}
|
|
1450
|
+
data-testid=${`${plane}.${col}.${row}`}
|
|
1342
1451
|
style="grid-column:${visCol + 1};grid-row:${visRow + 1}"
|
|
1343
1452
|
>
|
|
1344
1453
|
<div role="none" class="dx-grid__cell__content">${cell?.value}${accessory}</div>
|
|
@@ -1376,13 +1485,24 @@ export class DxGrid extends LitElement {
|
|
|
1376
1485
|
<div
|
|
1377
1486
|
role="none"
|
|
1378
1487
|
class="dx-grid"
|
|
1488
|
+
data-arrow-keys="all"
|
|
1379
1489
|
style=${styleMap({
|
|
1380
|
-
'grid-template-columns':
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1490
|
+
'grid-template-columns': [
|
|
1491
|
+
this.templatefrozenColsStart ? 'min-content' : false,
|
|
1492
|
+
this.limitColumns > 0 &&
|
|
1493
|
+
`minmax(0, ${Number.isFinite(this.limitColumns) ? `${Math.max(0, this.intrinsicInlineSize)}px` : '1fr'})`,
|
|
1494
|
+
this.templatefrozenColsEnd ? 'min-content' : false,
|
|
1495
|
+
]
|
|
1496
|
+
.filter(Boolean)
|
|
1497
|
+
.join(' '),
|
|
1498
|
+
'grid-template-rows': [
|
|
1499
|
+
this.templatefrozenRowsStart ? 'min-content' : false,
|
|
1500
|
+
this.limitRows > 0 &&
|
|
1501
|
+
`minmax(0, ${Number.isFinite(this.limitRows) ? `${Math.max(0, this.intrinsicBlockSize)}px` : '1fr'})`,
|
|
1502
|
+
this.templatefrozenRowsEnd ? ' min-content' : false,
|
|
1503
|
+
]
|
|
1504
|
+
.filter(Boolean)
|
|
1505
|
+
.join(' '),
|
|
1386
1506
|
'--dx-grid-content-inline-size': Number.isFinite(this.limitColumns)
|
|
1387
1507
|
? `${Math.max(0, this.totalIntrinsicInlineSize)}px`
|
|
1388
1508
|
: 'max-content',
|
|
@@ -1392,6 +1512,7 @@ export class DxGrid extends LitElement {
|
|
|
1392
1512
|
})}
|
|
1393
1513
|
data-grid=${this.gridId}
|
|
1394
1514
|
data-grid-mode=${this.mode}
|
|
1515
|
+
data-grid-focus-indicator-variant=${this.focusIndicatorVariant}
|
|
1395
1516
|
?data-grid-select=${selection.visible}
|
|
1396
1517
|
${ref(this.gridRef)}
|
|
1397
1518
|
>
|
|
@@ -1406,30 +1527,7 @@ export class DxGrid extends LitElement {
|
|
|
1406
1527
|
offsetBlock,
|
|
1407
1528
|
selection,
|
|
1408
1529
|
)}
|
|
1409
|
-
|
|
1410
|
-
role="grid"
|
|
1411
|
-
class="dx-grid__plane--grid"
|
|
1412
|
-
tabindex="0"
|
|
1413
|
-
data-dx-grid-plane="grid"
|
|
1414
|
-
data-dx-grid-plane-row="1"
|
|
1415
|
-
data-dx-grid-plane-col="1"
|
|
1416
|
-
${ref(this.viewportRef)}
|
|
1417
|
-
>
|
|
1418
|
-
<div
|
|
1419
|
-
role="none"
|
|
1420
|
-
class="dx-grid__plane--grid__content"
|
|
1421
|
-
style="transform:translate3d(${offsetInline}px,${offsetBlock}px,0);grid-template-columns:${this
|
|
1422
|
-
.templateGridColumns};grid-template-rows:${this.templateGridRows};"
|
|
1423
|
-
>
|
|
1424
|
-
${[...Array(visibleRows)].map((_, r0) => {
|
|
1425
|
-
return [...Array(visibleCols)].map((_, c0) => {
|
|
1426
|
-
const c = c0 + this.visColMin;
|
|
1427
|
-
const r = r0 + this.visRowMin;
|
|
1428
|
-
return this.renderCell(c, r, 'grid', cellSelected(c, r, 'grid', selection), c0, r0);
|
|
1429
|
-
});
|
|
1430
|
-
})}
|
|
1431
|
-
</div>
|
|
1432
|
-
</div>
|
|
1530
|
+
${this.renderMainGrid(visibleCols, visibleRows, offsetInline, offsetBlock, selection)}
|
|
1433
1531
|
${this.renderFrozenColumns('frozenColsEnd', visibleRows, offsetBlock, selection)}${this.renderFixed(
|
|
1434
1532
|
'fixedEndStart',
|
|
1435
1533
|
selection,
|
|
@@ -1443,37 +1541,19 @@ export class DxGrid extends LitElement {
|
|
|
1443
1541
|
private updateIntrinsicInlineSize(): void {
|
|
1444
1542
|
this.intrinsicInlineSize = Number.isFinite(this.limitColumns)
|
|
1445
1543
|
? [...Array(this.limitColumns)].reduce((acc, _, c0) => acc + this.colSize(c0, 'grid'), 0) +
|
|
1446
|
-
gap * (this.limitColumns - 1)
|
|
1544
|
+
gap * Math.max(0, this.limitColumns - 1)
|
|
1447
1545
|
: Infinity;
|
|
1448
1546
|
this.totalIntrinsicInlineSize =
|
|
1449
|
-
this.intrinsicInlineSize +
|
|
1450
|
-
(Number.isFinite(this.frozen.frozenColsStart)
|
|
1451
|
-
? [...Array(this.frozen.frozenColsStart)].reduce(
|
|
1452
|
-
(acc, _, c0) => acc + gap + this.colSize(c0, 'frozenColsStart'),
|
|
1453
|
-
0,
|
|
1454
|
-
)
|
|
1455
|
-
: 0) +
|
|
1456
|
-
(Number.isFinite(this.frozen.frozenColsEnd)
|
|
1457
|
-
? [...Array(this.frozen.frozenColsEnd)].reduce((acc, _, c0) => acc + gap + this.colSize(c0, 'frozenColsEnd'), 0)
|
|
1458
|
-
: 0);
|
|
1547
|
+
this.limitColumns > 0 ? this.intrinsicInlineSize + this.frozenColsSize : this.frozenColsSize - gap;
|
|
1459
1548
|
}
|
|
1460
1549
|
|
|
1461
1550
|
private updateIntrinsicBlockSize(): void {
|
|
1462
1551
|
this.intrinsicBlockSize = Number.isFinite(this.limitRows)
|
|
1463
1552
|
? [...Array(this.limitRows)].reduce((acc, _, r0) => acc + this.rowSize(r0, 'grid'), 0) +
|
|
1464
|
-
gap * (this.limitRows - 1)
|
|
1553
|
+
gap * Math.max(0, this.limitRows - 1)
|
|
1465
1554
|
: Infinity;
|
|
1466
1555
|
this.totalIntrinsicBlockSize =
|
|
1467
|
-
this.intrinsicBlockSize +
|
|
1468
|
-
(Number.isFinite(this.frozen.frozenRowsStart)
|
|
1469
|
-
? [...Array(this.frozen.frozenRowsStart)].reduce(
|
|
1470
|
-
(acc, _, r0) => acc + gap + this.rowSize(r0, 'frozenRowsStart'),
|
|
1471
|
-
0,
|
|
1472
|
-
)
|
|
1473
|
-
: 0) +
|
|
1474
|
-
(Number.isFinite(this.frozen.frozenRowsEnd)
|
|
1475
|
-
? [...Array(this.frozen.frozenRowsEnd)].reduce((acc, _, r0) => acc + gap + this.rowSize(r0, 'frozenRowsEnd'), 0)
|
|
1476
|
-
: 0);
|
|
1556
|
+
this.limitRows > 0 ? this.intrinsicBlockSize + this.frozenRowsSize : this.frozenRowsSize - gap;
|
|
1477
1557
|
}
|
|
1478
1558
|
|
|
1479
1559
|
private updateIntrinsicSizes(): void {
|
|
@@ -1521,7 +1601,7 @@ export class DxGrid extends LitElement {
|
|
|
1521
1601
|
if (this.getCells) {
|
|
1522
1602
|
this.updateCells(true);
|
|
1523
1603
|
}
|
|
1524
|
-
this.observer.observe(this.
|
|
1604
|
+
this.observer.observe(this.gridRef.value!);
|
|
1525
1605
|
this.computeColSizes();
|
|
1526
1606
|
this.computeRowSizes();
|
|
1527
1607
|
this.updateIntrinsicSizes();
|
|
@@ -1595,8 +1675,8 @@ export class DxGrid extends LitElement {
|
|
|
1595
1675
|
|
|
1596
1676
|
override disconnectedCallback(): void {
|
|
1597
1677
|
super.disconnectedCallback();
|
|
1598
|
-
if (this.
|
|
1599
|
-
this.observer.unobserve(this.
|
|
1678
|
+
if (this.gridRef.value) {
|
|
1679
|
+
this.observer.unobserve(this.gridRef.value);
|
|
1600
1680
|
}
|
|
1601
1681
|
document.defaultView?.removeEventListener('wheel', this.handleTopLevelWheel);
|
|
1602
1682
|
}
|
|
@@ -1614,6 +1694,7 @@ export {
|
|
|
1614
1694
|
parseCellIndex,
|
|
1615
1695
|
toPlaneCellIndex,
|
|
1616
1696
|
cellQuery,
|
|
1697
|
+
accessoryHandlesPointerdownAttrs,
|
|
1617
1698
|
} from './util';
|
|
1618
1699
|
|
|
1619
1700
|
export const commentedClassName = 'dx-grid__cell--commented';
|
|
@@ -10,7 +10,7 @@ export default defineConfig({
|
|
|
10
10
|
...e2ePreset(import.meta.dirname),
|
|
11
11
|
// TODO(wittjosiah): Avoid hard-coding ports.
|
|
12
12
|
webServer: {
|
|
13
|
-
command: 'moon run lit
|
|
13
|
+
command: 'moon run storybook-lit:serve-e2e -- --port=9002',
|
|
14
14
|
port: 9002,
|
|
15
15
|
reuseExistingServer: false,
|
|
16
16
|
},
|
package/src/types.ts
CHANGED
|
@@ -83,6 +83,10 @@ export type DxGridCellValue = {
|
|
|
83
83
|
* Controls the read-only state of the cell.
|
|
84
84
|
*/
|
|
85
85
|
readonly?: DxGridReadonlyValue;
|
|
86
|
+
/**
|
|
87
|
+
* Controls whether the cell content should unfurl when the cell has focus.
|
|
88
|
+
*/
|
|
89
|
+
focusUnfurl?: boolean;
|
|
86
90
|
};
|
|
87
91
|
|
|
88
92
|
export type DxGridAxisMetaProps = {
|
|
@@ -90,6 +94,9 @@ export type DxGridAxisMetaProps = {
|
|
|
90
94
|
description?: string;
|
|
91
95
|
resizeable?: boolean;
|
|
92
96
|
readonly?: DxGridReadonlyValue;
|
|
97
|
+
focusUnfurl?: boolean;
|
|
98
|
+
minSize?: number;
|
|
99
|
+
maxSize?: number;
|
|
93
100
|
};
|
|
94
101
|
|
|
95
102
|
export type DxGridAxisSizes = DxGridPlaneRecord<DxGridFrozenPlane, Record<string, number>>;
|
|
@@ -121,6 +128,10 @@ export type DxGridSelectionProps = {
|
|
|
121
128
|
visible?: boolean;
|
|
122
129
|
};
|
|
123
130
|
|
|
131
|
+
export type DxGridFocusIndicatorVariant = 'sheet' | 'stack';
|
|
132
|
+
|
|
133
|
+
export type DxGridOverscroll = 'inline' | 'block' | 'trap' | undefined;
|
|
134
|
+
|
|
124
135
|
export class DxAxisResize extends Event {
|
|
125
136
|
public readonly axis: DxGridAxis;
|
|
126
137
|
public readonly plane: 'grid' | DxGridFrozenPlane;
|
package/src/util.ts
CHANGED
|
@@ -4,19 +4,19 @@
|
|
|
4
4
|
|
|
5
5
|
import { defaultRowSize } from './defs';
|
|
6
6
|
import {
|
|
7
|
-
type
|
|
7
|
+
type DxGridAxis,
|
|
8
8
|
type DxGridCellIndex,
|
|
9
|
-
type DxGridPosition,
|
|
10
|
-
type DxGridPointer,
|
|
11
|
-
type DxGridSelectionProps,
|
|
12
|
-
type DxGridPositionNullable,
|
|
13
|
-
type DxGridPlane,
|
|
14
|
-
type DxGridFrozenRowsPlane,
|
|
15
9
|
type DxGridFrozenColsPlane,
|
|
16
10
|
type DxGridFrozenPlane,
|
|
17
|
-
type
|
|
11
|
+
type DxGridFrozenRowsPlane,
|
|
12
|
+
type DxGridPlane,
|
|
13
|
+
type DxGridPlaneCellIndex,
|
|
18
14
|
type DxGridPlanePosition,
|
|
15
|
+
type DxGridPointer,
|
|
16
|
+
type DxGridPosition,
|
|
17
|
+
type DxGridPositionNullable,
|
|
19
18
|
type DxGridReadonlyValue,
|
|
19
|
+
type DxGridSelectionProps,
|
|
20
20
|
separator,
|
|
21
21
|
} from './types';
|
|
22
22
|
|
|
@@ -25,7 +25,7 @@ export const toPlaneCellIndex = (cellCoords: Partial<DxGridPosition> & DxGridPla
|
|
|
25
25
|
|
|
26
26
|
export function parseCellIndex(index: DxGridCellIndex): DxGridPosition;
|
|
27
27
|
export function parseCellIndex(index: DxGridPlaneCellIndex): DxGridPlanePosition;
|
|
28
|
-
|
|
28
|
+
|
|
29
29
|
export function parseCellIndex(index: DxGridPlaneCellIndex | DxGridCellIndex): DxGridPlanePosition | DxGridPosition {
|
|
30
30
|
const coords = index.split(separator);
|
|
31
31
|
if (coords.length === 3) {
|
|
@@ -123,6 +123,10 @@ export const closestAction = (target: EventTarget | null): { action: string | nu
|
|
|
123
123
|
return { actionEl, action: actionEl?.getAttribute('data-dx-grid-action') ?? null };
|
|
124
124
|
};
|
|
125
125
|
|
|
126
|
+
export const accessoryHandlesPointerdownAttrs = {
|
|
127
|
+
'data-dx-grid-action': 'accessory',
|
|
128
|
+
};
|
|
129
|
+
|
|
126
130
|
export const closestCell = (target: EventTarget | null, actionEl?: HTMLElement | null): DxGridPositionNullable => {
|
|
127
131
|
let cellElement = actionEl;
|
|
128
132
|
if (!cellElement) {
|