@dxos/lit-grid 0.8.4-main.b97322e → 0.8.4-main.bbf232bc24
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 +13 -8
- package/dist/src/dx-grid.d.ts.map +1 -1
- package/dist/src/dx-grid.js +205 -167
- package/dist/src/dx-grid.js.map +1 -1
- package/dist/src/dx-grid.lit-stories.d.ts +12 -15
- package/dist/src/dx-grid.lit-stories.d.ts.map +1 -1
- package/dist/src/dx-grid.lit-stories.js +20 -23
- 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.d.ts.map +1 -1
- package/dist/src/playwright/playwright.config.js +1 -1
- package/dist/src/playwright/playwright.config.js.map +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 +10 -1
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/types.js.map +1 -1
- package/dist/src/util.d.ts +8 -5
- 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 -13
- package/src/defs.ts +1 -0
- package/src/dx-grid-axis-resize-handle.pcss +9 -3
- package/src/dx-grid-axis-resize-handle.ts +1 -1
- package/src/dx-grid-multiselect-cell.pcss +7 -5
- package/src/dx-grid-multiselect-cell.ts +2 -1
- package/src/dx-grid.lit-stories.ts +3 -5
- package/src/dx-grid.pcss +42 -21
- package/src/dx-grid.ts +200 -114
- 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
|
@@ -2,75 +2,77 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
+
import './dx-grid-axis-resize-handle';
|
|
6
|
+
|
|
5
7
|
import { LitElement, html, nothing } from 'lit';
|
|
6
|
-
import { customElement,
|
|
7
|
-
import {
|
|
8
|
+
import { customElement, property, state } from 'lit/decorators.js';
|
|
9
|
+
import { type Ref, createRef, ref } from 'lit/directives/ref.js';
|
|
8
10
|
import { styleMap } from 'lit/directives/style-map.js';
|
|
9
|
-
import {
|
|
11
|
+
import { html as staticHtml, unsafeStatic } from 'lit/static-html.js';
|
|
10
12
|
|
|
11
|
-
import { defaultColSize, defaultRowSize } from './defs';
|
|
12
|
-
// eslint-disable-next-line unused-imports/no-unused-imports
|
|
13
|
-
import './dx-grid-axis-resize-handle';
|
|
13
|
+
import { defaultColSize, defaultRowSize, focusUnfurlDefault } from './defs';
|
|
14
14
|
import {
|
|
15
|
-
type DxGridAxisMetaProps,
|
|
16
|
-
type DxGridAxisSizes,
|
|
17
|
-
type DxGridPlaneCellIndex,
|
|
18
|
-
type DxGridCellValue,
|
|
19
15
|
DxAxisResize,
|
|
20
16
|
type DxAxisResizeInternal,
|
|
21
17
|
DxEditRequest,
|
|
18
|
+
type DxGridAnnotatedPanEvent,
|
|
19
|
+
type DxGridAxis,
|
|
22
20
|
type DxGridAxisMeta,
|
|
21
|
+
type DxGridAxisMetaProps,
|
|
22
|
+
type DxGridAxisSizes,
|
|
23
|
+
type DxGridCellValue,
|
|
23
24
|
type DxGridCells,
|
|
24
25
|
DxGridCellsSelect,
|
|
25
26
|
type DxGridFixedPlane,
|
|
27
|
+
type DxGridFocusIndicatorVariant,
|
|
26
28
|
type DxGridFrozenAxes,
|
|
27
29
|
type DxGridFrozenColsPlane,
|
|
28
30
|
type DxGridFrozenPlane,
|
|
29
31
|
type DxGridFrozenRowsPlane,
|
|
30
32
|
type DxGridMode,
|
|
33
|
+
type DxGridOverscroll,
|
|
31
34
|
type DxGridPlane,
|
|
35
|
+
type DxGridPlaneCellIndex,
|
|
32
36
|
type DxGridPlaneCells,
|
|
33
37
|
type DxGridPlaneRange,
|
|
34
38
|
type DxGridPlaneRecord,
|
|
35
39
|
type DxGridPointer,
|
|
36
40
|
type DxGridPosition,
|
|
37
|
-
type DxGridAxis,
|
|
38
|
-
type DxGridSelectionProps,
|
|
39
|
-
type DxGridAnnotatedPanEvent,
|
|
40
41
|
type DxGridRange,
|
|
42
|
+
type DxGridSelectionProps,
|
|
41
43
|
separator,
|
|
42
44
|
} from './types';
|
|
43
45
|
import {
|
|
44
|
-
toCellIndex,
|
|
45
|
-
gap,
|
|
46
|
-
resizeTolerance,
|
|
47
|
-
sizeColMin,
|
|
48
|
-
sizeColMax,
|
|
49
|
-
sizeRowMin,
|
|
50
|
-
sizeRowMax,
|
|
51
|
-
shouldSelect,
|
|
52
|
-
selectionProps,
|
|
53
46
|
cellSelected,
|
|
54
47
|
closestAction,
|
|
55
48
|
closestCell,
|
|
56
|
-
|
|
57
|
-
|
|
49
|
+
gap,
|
|
50
|
+
isReadonly,
|
|
51
|
+
isSameCell,
|
|
52
|
+
resizeTolerance,
|
|
58
53
|
resolveColPlane,
|
|
59
54
|
resolveFrozenPlane,
|
|
60
|
-
|
|
61
|
-
|
|
55
|
+
resolveRowPlane,
|
|
56
|
+
selectionProps,
|
|
57
|
+
shouldSelect,
|
|
58
|
+
sizeColMax,
|
|
59
|
+
sizeColMin,
|
|
60
|
+
sizeRowMax,
|
|
61
|
+
sizeRowMin,
|
|
62
|
+
targetIsPlane,
|
|
63
|
+
toCellIndex,
|
|
62
64
|
} from './util';
|
|
63
65
|
|
|
64
66
|
@customElement('dx-grid')
|
|
65
67
|
export class DxGrid extends LitElement {
|
|
66
68
|
constructor() {
|
|
67
69
|
super();
|
|
68
|
-
// Wheel, top-level and element-level
|
|
70
|
+
// Wheel, top-level and element-level.
|
|
69
71
|
document.defaultView?.addEventListener('wheel', this.handleTopLevelWheel, { passive: false });
|
|
70
72
|
this.addEventListener('wheel', this.handleWheel);
|
|
71
|
-
// Custom event(s)
|
|
73
|
+
// Custom event(s).
|
|
72
74
|
this.addEventListener('dx-axis-resize-internal', this.handleAxisResizeInternal as EventListener);
|
|
73
|
-
// Standard events
|
|
75
|
+
// Standard events.
|
|
74
76
|
this.addEventListener('pointerdown', this.handlePointerDown);
|
|
75
77
|
this.addEventListener('pointermove', this.handlePointerMove);
|
|
76
78
|
this.addEventListener('pointerup', this.handlePointerUp);
|
|
@@ -84,12 +86,12 @@ export class DxGrid extends LitElement {
|
|
|
84
86
|
gridId: string = 'default-grid-id';
|
|
85
87
|
|
|
86
88
|
@property({ type: Object })
|
|
87
|
-
rowDefault: DxGridPlaneRecord<DxGridFrozenRowsPlane, DxGridAxisMetaProps
|
|
89
|
+
rowDefault: Partial<DxGridPlaneRecord<DxGridFrozenRowsPlane, Partial<DxGridAxisMetaProps>>> = {
|
|
88
90
|
grid: { size: defaultRowSize },
|
|
89
91
|
};
|
|
90
92
|
|
|
91
93
|
@property({ type: Object })
|
|
92
|
-
columnDefault: DxGridPlaneRecord<DxGridFrozenColsPlane, DxGridAxisMetaProps
|
|
94
|
+
columnDefault: Partial<DxGridPlaneRecord<DxGridFrozenColsPlane, Partial<DxGridAxisMetaProps>>> = {
|
|
93
95
|
grid: { size: defaultColSize },
|
|
94
96
|
};
|
|
95
97
|
|
|
@@ -115,11 +117,14 @@ export class DxGrid extends LitElement {
|
|
|
115
117
|
frozen: DxGridFrozenAxes = {};
|
|
116
118
|
|
|
117
119
|
@property({ type: String })
|
|
118
|
-
overscroll:
|
|
120
|
+
overscroll: DxGridOverscroll = undefined;
|
|
119
121
|
|
|
120
122
|
@property({ type: String })
|
|
121
123
|
activeRefs = '';
|
|
122
124
|
|
|
125
|
+
@property({ type: String })
|
|
126
|
+
focusIndicatorVariant: DxGridFocusIndicatorVariant = 'sheet';
|
|
127
|
+
|
|
123
128
|
/**
|
|
124
129
|
* When this function is defined, it is used first to try to get a value for a cell,
|
|
125
130
|
* and otherwise will fall back to `cells`.
|
|
@@ -195,6 +200,7 @@ export class DxGrid extends LitElement {
|
|
|
195
200
|
//
|
|
196
201
|
// `template` is the rendered value of `grid-{axis}-template`.
|
|
197
202
|
//
|
|
203
|
+
|
|
198
204
|
@state()
|
|
199
205
|
private templateGridColumns = '0';
|
|
200
206
|
|
|
@@ -213,6 +219,16 @@ export class DxGrid extends LitElement {
|
|
|
213
219
|
@state()
|
|
214
220
|
private templatefrozenRowsEnd = '';
|
|
215
221
|
|
|
222
|
+
//
|
|
223
|
+
// `frozen…Size` is used to measure space available for the non-fixed planes
|
|
224
|
+
//
|
|
225
|
+
|
|
226
|
+
@state()
|
|
227
|
+
private frozenColsSize = 0;
|
|
228
|
+
|
|
229
|
+
@state()
|
|
230
|
+
private frozenRowsSize = 0;
|
|
231
|
+
|
|
216
232
|
//
|
|
217
233
|
// Focus, selection, and resize states
|
|
218
234
|
//
|
|
@@ -308,7 +324,7 @@ export class DxGrid extends LitElement {
|
|
|
308
324
|
this.dispatchSelectionChange();
|
|
309
325
|
}
|
|
310
326
|
if (this.mode === 'edit-select') {
|
|
311
|
-
// Prevent focus moving when editing while selection is possible
|
|
327
|
+
// Prevent focus moving when editing while selection is possible.
|
|
312
328
|
event.preventDefault();
|
|
313
329
|
} else if (this.focusActive && isSameCell(this.focusedCell, cellCoords)) {
|
|
314
330
|
this.dispatchEditRequest();
|
|
@@ -416,15 +432,13 @@ export class DxGrid extends LitElement {
|
|
|
416
432
|
}
|
|
417
433
|
|
|
418
434
|
private moveFocusIntoPlane(plane: DxGridPlane): void {
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
};
|
|
427
|
-
}
|
|
435
|
+
const colPlane = resolveColPlane(plane);
|
|
436
|
+
const rowPlane = resolveRowPlane(plane);
|
|
437
|
+
this.focusedCell = {
|
|
438
|
+
plane,
|
|
439
|
+
col: colPlane === 'grid' ? this.visColMin : 0,
|
|
440
|
+
row: rowPlane === 'grid' ? this.visRowMin : 0,
|
|
441
|
+
};
|
|
428
442
|
this.focusedCellElement()?.focus({ preventScroll: true });
|
|
429
443
|
}
|
|
430
444
|
|
|
@@ -481,6 +495,13 @@ export class DxGrid extends LitElement {
|
|
|
481
495
|
event.preventDefault();
|
|
482
496
|
this.dispatchEditRequest();
|
|
483
497
|
break;
|
|
498
|
+
case 'Backspace':
|
|
499
|
+
case 'Delete':
|
|
500
|
+
if (!event.defaultPrevented) {
|
|
501
|
+
event.preventDefault();
|
|
502
|
+
this.dispatchEditRequest('');
|
|
503
|
+
}
|
|
504
|
+
break;
|
|
484
505
|
default:
|
|
485
506
|
if (event.key.length === 1 && event.key.match(/\P{Cc}/u) && !(event.metaKey || event.ctrlKey)) {
|
|
486
507
|
this.dispatchEditRequest(event.key);
|
|
@@ -574,7 +595,7 @@ export class DxGrid extends LitElement {
|
|
|
574
595
|
}
|
|
575
596
|
|
|
576
597
|
//
|
|
577
|
-
// Resize & reposition handlers, observer, ref
|
|
598
|
+
// Resize & reposition handlers, observer, ref.
|
|
578
599
|
//
|
|
579
600
|
|
|
580
601
|
@state()
|
|
@@ -584,19 +605,18 @@ export class DxGrid extends LitElement {
|
|
|
584
605
|
blockSize: 0,
|
|
585
606
|
};
|
|
586
607
|
if (
|
|
587
|
-
Math.abs(inlineSize - this.sizeInline) > resizeTolerance ||
|
|
588
|
-
Math.abs(blockSize - this.sizeBlock) > resizeTolerance
|
|
608
|
+
Math.abs(inlineSize - this.frozenColsSize - this.sizeInline) > resizeTolerance ||
|
|
609
|
+
Math.abs(blockSize - this.frozenRowsSize - this.sizeBlock) > resizeTolerance
|
|
589
610
|
) {
|
|
590
611
|
// console.info('[updating bounds]', 'resize', [inlineSize - this.sizeInline, blockSize - this.sizeBlock]);
|
|
591
|
-
this.sizeInline = inlineSize;
|
|
592
|
-
this.sizeBlock = blockSize;
|
|
612
|
+
this.sizeInline = inlineSize - this.frozenColsSize;
|
|
613
|
+
this.sizeBlock = blockSize - this.frozenRowsSize;
|
|
593
614
|
this.updateVis();
|
|
594
615
|
queueMicrotask(() => this.updatePos());
|
|
595
616
|
}
|
|
596
617
|
});
|
|
597
618
|
|
|
598
619
|
private gridRef: Ref<HTMLDivElement> = createRef();
|
|
599
|
-
private viewportRef: Ref<HTMLDivElement> = createRef();
|
|
600
620
|
|
|
601
621
|
private maybeUpdateVisInline = () => {
|
|
602
622
|
if (this.posInline < this.binInlineMin || this.posInline >= this.binInlineMax) {
|
|
@@ -675,7 +695,7 @@ export class DxGrid extends LitElement {
|
|
|
675
695
|
};
|
|
676
696
|
|
|
677
697
|
private updateVisInline(): void {
|
|
678
|
-
// todo: avoid starting from zero
|
|
698
|
+
// todo: avoid starting from zero.
|
|
679
699
|
let axisCursor = 0;
|
|
680
700
|
let pxCursor = this.colSize(axisCursor, 'grid');
|
|
681
701
|
|
|
@@ -721,10 +741,19 @@ export class DxGrid extends LitElement {
|
|
|
721
741
|
this.templatefrozenColsEnd = [...Array(this.frozen.frozenColsEnd ?? 0)]
|
|
722
742
|
.map((_, c0) => `${this.colSize(c0, 'frozenColsEnd')}px`)
|
|
723
743
|
.join(' ');
|
|
744
|
+
|
|
745
|
+
this.frozenColsSize =
|
|
746
|
+
[...Array(this.frozen.frozenColsStart ?? 0)].reduce(
|
|
747
|
+
(sum, _, c0) => sum + this.colSize(c0, 'frozenColsStart'),
|
|
748
|
+
0,
|
|
749
|
+
) +
|
|
750
|
+
gap * Math.max(0, this.frozen.frozenColsStart ?? 0 - 1) +
|
|
751
|
+
[...Array(this.frozen.frozenColsEnd ?? 0)].reduce((sum, _, c0) => sum + this.colSize(c0, 'frozenColsEnd'), 0) +
|
|
752
|
+
gap * Math.max(0, this.frozen.frozenColsEnd ?? 0 - 1);
|
|
724
753
|
}
|
|
725
754
|
|
|
726
755
|
private updateVisBlock(): void {
|
|
727
|
-
// todo: avoid starting from zero
|
|
756
|
+
// todo: avoid starting from zero.
|
|
728
757
|
let axisCursor = 0;
|
|
729
758
|
let pxCursor = this.rowSize(axisCursor, 'grid');
|
|
730
759
|
|
|
@@ -770,6 +799,15 @@ export class DxGrid extends LitElement {
|
|
|
770
799
|
this.templatefrozenRowsEnd = [...Array(this.frozen.frozenRowsEnd ?? 0)]
|
|
771
800
|
.map((_, r0) => `${this.rowSize(r0, 'frozenRowsEnd')}px`)
|
|
772
801
|
.join(' ');
|
|
802
|
+
|
|
803
|
+
this.frozenRowsSize =
|
|
804
|
+
[...Array(this.frozen.frozenRowsStart ?? 0)].reduce(
|
|
805
|
+
(sum, _, r0) => sum + this.rowSize(r0, 'frozenRowsStart'),
|
|
806
|
+
0,
|
|
807
|
+
) +
|
|
808
|
+
gap * Math.max(0, this.frozen.frozenRowsStart ?? 0 - 1) +
|
|
809
|
+
[...Array(this.frozen.frozenRowsEnd ?? 0)].reduce((sum, _, r0) => sum + this.rowSize(r0, 'frozenRowsEnd'), 0) +
|
|
810
|
+
gap * Math.max(0, this.frozen.frozenRowsEnd ?? 0 - 1);
|
|
773
811
|
}
|
|
774
812
|
|
|
775
813
|
private updateVis(): void {
|
|
@@ -991,7 +1029,7 @@ export class DxGrid extends LitElement {
|
|
|
991
1029
|
}
|
|
992
1030
|
|
|
993
1031
|
/**
|
|
994
|
-
* Updates `pos` so that a cell in focus is fully within the viewport
|
|
1032
|
+
* Updates `pos` so that a cell in focus is fully within the viewport.
|
|
995
1033
|
*/
|
|
996
1034
|
snapPosToFocusedCell(): void {
|
|
997
1035
|
const outOfVis = this.focusedCellOutOfVis();
|
|
@@ -1068,16 +1106,40 @@ export class DxGrid extends LitElement {
|
|
|
1068
1106
|
: !!(this.rows[plane]?.[index]?.resizeable ?? this.rowDefault[plane as DxGridFrozenRowsPlane]?.resizeable);
|
|
1069
1107
|
}
|
|
1070
1108
|
|
|
1109
|
+
private clampAxisSize(
|
|
1110
|
+
plane: 'grid' | DxGridFrozenPlane,
|
|
1111
|
+
axis: DxGridAxis,
|
|
1112
|
+
index: number | string,
|
|
1113
|
+
requestedSize: number,
|
|
1114
|
+
): number {
|
|
1115
|
+
const minSize =
|
|
1116
|
+
axis === 'col'
|
|
1117
|
+
? (this.columns[plane]?.[index]?.minSize ??
|
|
1118
|
+
this.columnDefault[plane as DxGridFrozenColsPlane]?.minSize ??
|
|
1119
|
+
sizeColMin)
|
|
1120
|
+
: (this.rows[plane]?.[index]?.minSize ??
|
|
1121
|
+
this.rowDefault[plane as DxGridFrozenRowsPlane]?.minSize ??
|
|
1122
|
+
sizeRowMin);
|
|
1123
|
+
const maxSize =
|
|
1124
|
+
axis === 'col'
|
|
1125
|
+
? (this.columns[plane]?.[index]?.maxSize ??
|
|
1126
|
+
this.columnDefault[plane as DxGridFrozenColsPlane]?.maxSize ??
|
|
1127
|
+
sizeColMax)
|
|
1128
|
+
: (this.rows[plane]?.[index]?.maxSize ??
|
|
1129
|
+
this.rowDefault[plane as DxGridFrozenRowsPlane]?.maxSize ??
|
|
1130
|
+
sizeRowMax);
|
|
1131
|
+
return Math.max(minSize, Math.min(maxSize, requestedSize));
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1071
1134
|
private handleAxisResizeInternal(event: DxAxisResizeInternal): void {
|
|
1072
1135
|
event.stopPropagation();
|
|
1073
1136
|
const { plane, axis, delta, size, index, state } = event;
|
|
1137
|
+
const nextSize = this.clampAxisSize(plane, axis, index, size + delta);
|
|
1074
1138
|
if (axis === 'col') {
|
|
1075
|
-
const nextSize = Math.max(sizeColMin, Math.min(sizeColMax, size + delta));
|
|
1076
1139
|
this.colSizes = { ...this.colSizes, [plane]: { ...this.colSizes[plane], [index]: nextSize } };
|
|
1077
1140
|
this.updateVisInline();
|
|
1078
1141
|
this.updateIntrinsicInlineSize();
|
|
1079
1142
|
} else {
|
|
1080
|
-
const nextSize = Math.max(sizeRowMin, Math.min(sizeRowMax, size + delta));
|
|
1081
1143
|
this.rowSizes = { ...this.colSizes, [plane]: { ...this.rowSizes[plane], [index]: nextSize } };
|
|
1082
1144
|
this.updateVisBlock();
|
|
1083
1145
|
this.updateIntrinsicBlockSize();
|
|
@@ -1095,7 +1157,7 @@ export class DxGrid extends LitElement {
|
|
|
1095
1157
|
}
|
|
1096
1158
|
|
|
1097
1159
|
//
|
|
1098
|
-
// Render and other lifecycle methods
|
|
1160
|
+
// Render and other lifecycle methods.
|
|
1099
1161
|
//
|
|
1100
1162
|
|
|
1101
1163
|
// TODO(thure): This is for rendering presentational objects superimposed onto the canonical grid (e.g. DnD drop line for #8108).
|
|
@@ -1178,7 +1240,7 @@ export class DxGrid extends LitElement {
|
|
|
1178
1240
|
) {
|
|
1179
1241
|
const rowPlane = resolveRowPlane(plane) as DxGridFrozenPlane;
|
|
1180
1242
|
const rows = this.frozen[rowPlane];
|
|
1181
|
-
return (rows ?? 0) > 0
|
|
1243
|
+
return (rows ?? 0) > 0 && this.limitColumns > 0
|
|
1182
1244
|
? html`<div
|
|
1183
1245
|
role="none"
|
|
1184
1246
|
class="dx-grid__plane--frozen-row"
|
|
@@ -1212,7 +1274,7 @@ export class DxGrid extends LitElement {
|
|
|
1212
1274
|
) {
|
|
1213
1275
|
const colPlane = resolveColPlane(plane) as DxGridFrozenPlane;
|
|
1214
1276
|
const cols = this.frozen[colPlane];
|
|
1215
|
-
return (cols ?? 0) > 0
|
|
1277
|
+
return (cols ?? 0) > 0 && this.limitRows > 0
|
|
1216
1278
|
? html`<div
|
|
1217
1279
|
role="none"
|
|
1218
1280
|
class="dx-grid__plane--frozen-col"
|
|
@@ -1238,6 +1300,40 @@ export class DxGrid extends LitElement {
|
|
|
1238
1300
|
: null;
|
|
1239
1301
|
}
|
|
1240
1302
|
|
|
1303
|
+
private renderMainGrid(
|
|
1304
|
+
visibleCols: number,
|
|
1305
|
+
visibleRows: number,
|
|
1306
|
+
offsetInline: number,
|
|
1307
|
+
offsetBlock: number,
|
|
1308
|
+
selection: DxGridSelectionProps,
|
|
1309
|
+
) {
|
|
1310
|
+
return this.limitRows > 0 && this.limitColumns > 0
|
|
1311
|
+
? html`<div
|
|
1312
|
+
role="grid"
|
|
1313
|
+
class="dx-grid__plane--grid"
|
|
1314
|
+
tabindex="0"
|
|
1315
|
+
data-dx-grid-plane="grid"
|
|
1316
|
+
data-dx-grid-plane-row="1"
|
|
1317
|
+
data-dx-grid-plane-col="1"
|
|
1318
|
+
>
|
|
1319
|
+
<div
|
|
1320
|
+
role="none"
|
|
1321
|
+
class="dx-grid__plane--grid__content"
|
|
1322
|
+
style="transform:translate3d(${offsetInline}px,${offsetBlock}px,0);grid-template-columns:${this
|
|
1323
|
+
.templateGridColumns};grid-template-rows:${this.templateGridRows};"
|
|
1324
|
+
>
|
|
1325
|
+
${[...Array(visibleRows)].map((_, r0) => {
|
|
1326
|
+
return [...Array(visibleCols)].map((_, c0) => {
|
|
1327
|
+
const c = c0 + this.visColMin;
|
|
1328
|
+
const r = r0 + this.visRowMin;
|
|
1329
|
+
return this.renderCell(c, r, 'grid', cellSelected(c, r, 'grid', selection), c0, r0);
|
|
1330
|
+
});
|
|
1331
|
+
})}
|
|
1332
|
+
</div>
|
|
1333
|
+
</div>`
|
|
1334
|
+
: null;
|
|
1335
|
+
}
|
|
1336
|
+
|
|
1241
1337
|
private cellReadonly(col: number, row: number, plane: DxGridPlane): boolean {
|
|
1242
1338
|
const colPlane = resolveColPlane(plane);
|
|
1243
1339
|
const rowPlane = resolveRowPlane(plane);
|
|
@@ -1255,6 +1351,23 @@ export class DxGrid extends LitElement {
|
|
|
1255
1351
|
return isReadonly(colReadOnly) || isReadonly(rowReadOnly);
|
|
1256
1352
|
}
|
|
1257
1353
|
|
|
1354
|
+
private cellFocusUnfurl(col: number, row: number, plane: DxGridPlane): boolean {
|
|
1355
|
+
const colPlane = resolveColPlane(plane);
|
|
1356
|
+
const rowPlane = resolveRowPlane(plane);
|
|
1357
|
+
|
|
1358
|
+
// Check cell-specific setting first.
|
|
1359
|
+
const cellUnfurl = this.cell(col, row, plane)?.focusUnfurl;
|
|
1360
|
+
if (cellUnfurl !== undefined) {
|
|
1361
|
+
return cellUnfurl;
|
|
1362
|
+
}
|
|
1363
|
+
|
|
1364
|
+
// Check column/row defaults.
|
|
1365
|
+
const colUnfurl = this.columns?.[colPlane]?.[col]?.focusUnfurl ?? this.columnDefault?.[colPlane]?.focusUnfurl;
|
|
1366
|
+
const rowUnfurl = this.rows?.[rowPlane]?.[row]?.focusUnfurl ?? this.rowDefault?.[rowPlane]?.focusUnfurl;
|
|
1367
|
+
|
|
1368
|
+
return colUnfurl ?? rowUnfurl ?? focusUnfurlDefault;
|
|
1369
|
+
}
|
|
1370
|
+
|
|
1258
1371
|
/**
|
|
1259
1372
|
* Determines if the cell's text content should be selectable based on its readonly value.
|
|
1260
1373
|
* @returns true if the cells text content is selectable, false otherwise.
|
|
@@ -1317,6 +1430,7 @@ export class DxGrid extends LitElement {
|
|
|
1317
1430
|
const cell = this.cell(col, row, plane);
|
|
1318
1431
|
const active = this.cellActive(col, row, plane);
|
|
1319
1432
|
const readonly = this.cellReadonly(col, row, plane);
|
|
1433
|
+
const focusUnfurl = this.cellFocusUnfurl(col, row, plane);
|
|
1320
1434
|
const textSelectable = this.cellTextSelectable(col, row, plane);
|
|
1321
1435
|
const resizeIndex = cell?.resizeHandle ? (cell.resizeHandle === 'col' ? col : row) : undefined;
|
|
1322
1436
|
const resizePlane = cell?.resizeHandle ? resolveFrozenPlane(cell.resizeHandle, plane) : undefined;
|
|
@@ -1328,11 +1442,13 @@ export class DxGrid extends LitElement {
|
|
|
1328
1442
|
aria-readonly=${readonly ? 'true' : nothing}
|
|
1329
1443
|
class=${cell?.className ?? nothing}
|
|
1330
1444
|
data-refs=${cell?.dataRefs ?? nothing}
|
|
1445
|
+
data-focus-unfurl=${focusUnfurl ? nothing : 'false'}
|
|
1331
1446
|
?data-dx-active=${active}
|
|
1332
1447
|
data-text-selectable=${textSelectable ? 'true' : 'false'}
|
|
1333
1448
|
data-dx-grid-action="cell"
|
|
1334
1449
|
aria-colindex=${col}
|
|
1335
1450
|
aria-rowindex=${row}
|
|
1451
|
+
data-testid=${`${plane}.${col}.${row}`}
|
|
1336
1452
|
style="grid-column:${visCol + 1};grid-row:${visRow + 1}"
|
|
1337
1453
|
>
|
|
1338
1454
|
<div role="none" class="dx-grid__cell__content">${cell?.value}${accessory}</div>
|
|
@@ -1361,22 +1477,31 @@ export class DxGrid extends LitElement {
|
|
|
1361
1477
|
.split(' ')
|
|
1362
1478
|
.filter((value) => value)
|
|
1363
1479
|
.map(
|
|
1364
|
-
|
|
1365
|
-
(activeRef) =>
|
|
1366
|
-
`[data-refs~="${activeRef}"] { background: var(--dx-grid-commented-active, var(--dx-gridCommentedActive)) !important; }`,
|
|
1480
|
+
(activeRef) => `[data-refs~="${activeRef}"] { background: var(--color-grid-comment-active) !important; }`,
|
|
1367
1481
|
)
|
|
1368
1482
|
.join('\n')}
|
|
1369
1483
|
</style>
|
|
1370
1484
|
<div
|
|
1371
1485
|
role="none"
|
|
1372
1486
|
class="dx-grid"
|
|
1487
|
+
data-arrow-keys="all"
|
|
1373
1488
|
style=${styleMap({
|
|
1374
|
-
'grid-template-columns':
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1489
|
+
'grid-template-columns': [
|
|
1490
|
+
this.templatefrozenColsStart ? 'min-content' : false,
|
|
1491
|
+
this.limitColumns > 0 &&
|
|
1492
|
+
`minmax(0, ${Number.isFinite(this.limitColumns) ? `${Math.max(0, this.intrinsicInlineSize)}px` : '1fr'})`,
|
|
1493
|
+
this.templatefrozenColsEnd ? 'min-content' : false,
|
|
1494
|
+
]
|
|
1495
|
+
.filter(Boolean)
|
|
1496
|
+
.join(' '),
|
|
1497
|
+
'grid-template-rows': [
|
|
1498
|
+
this.templatefrozenRowsStart ? 'min-content' : false,
|
|
1499
|
+
this.limitRows > 0 &&
|
|
1500
|
+
`minmax(0, ${Number.isFinite(this.limitRows) ? `${Math.max(0, this.intrinsicBlockSize)}px` : '1fr'})`,
|
|
1501
|
+
this.templatefrozenRowsEnd ? ' min-content' : false,
|
|
1502
|
+
]
|
|
1503
|
+
.filter(Boolean)
|
|
1504
|
+
.join(' '),
|
|
1380
1505
|
'--dx-grid-content-inline-size': Number.isFinite(this.limitColumns)
|
|
1381
1506
|
? `${Math.max(0, this.totalIntrinsicInlineSize)}px`
|
|
1382
1507
|
: 'max-content',
|
|
@@ -1386,6 +1511,7 @@ export class DxGrid extends LitElement {
|
|
|
1386
1511
|
})}
|
|
1387
1512
|
data-grid=${this.gridId}
|
|
1388
1513
|
data-grid-mode=${this.mode}
|
|
1514
|
+
data-grid-focus-indicator-variant=${this.focusIndicatorVariant}
|
|
1389
1515
|
?data-grid-select=${selection.visible}
|
|
1390
1516
|
${ref(this.gridRef)}
|
|
1391
1517
|
>
|
|
@@ -1400,30 +1526,7 @@ export class DxGrid extends LitElement {
|
|
|
1400
1526
|
offsetBlock,
|
|
1401
1527
|
selection,
|
|
1402
1528
|
)}
|
|
1403
|
-
|
|
1404
|
-
role="grid"
|
|
1405
|
-
class="dx-grid__plane--grid"
|
|
1406
|
-
tabindex="0"
|
|
1407
|
-
data-dx-grid-plane="grid"
|
|
1408
|
-
data-dx-grid-plane-row="1"
|
|
1409
|
-
data-dx-grid-plane-col="1"
|
|
1410
|
-
${ref(this.viewportRef)}
|
|
1411
|
-
>
|
|
1412
|
-
<div
|
|
1413
|
-
role="none"
|
|
1414
|
-
class="dx-grid__plane--grid__content"
|
|
1415
|
-
style="transform:translate3d(${offsetInline}px,${offsetBlock}px,0);grid-template-columns:${this
|
|
1416
|
-
.templateGridColumns};grid-template-rows:${this.templateGridRows};"
|
|
1417
|
-
>
|
|
1418
|
-
${[...Array(visibleRows)].map((_, r0) => {
|
|
1419
|
-
return [...Array(visibleCols)].map((_, c0) => {
|
|
1420
|
-
const c = c0 + this.visColMin;
|
|
1421
|
-
const r = r0 + this.visRowMin;
|
|
1422
|
-
return this.renderCell(c, r, 'grid', cellSelected(c, r, 'grid', selection), c0, r0);
|
|
1423
|
-
});
|
|
1424
|
-
})}
|
|
1425
|
-
</div>
|
|
1426
|
-
</div>
|
|
1529
|
+
${this.renderMainGrid(visibleCols, visibleRows, offsetInline, offsetBlock, selection)}
|
|
1427
1530
|
${this.renderFrozenColumns('frozenColsEnd', visibleRows, offsetBlock, selection)}${this.renderFixed(
|
|
1428
1531
|
'fixedEndStart',
|
|
1429
1532
|
selection,
|
|
@@ -1437,37 +1540,19 @@ export class DxGrid extends LitElement {
|
|
|
1437
1540
|
private updateIntrinsicInlineSize(): void {
|
|
1438
1541
|
this.intrinsicInlineSize = Number.isFinite(this.limitColumns)
|
|
1439
1542
|
? [...Array(this.limitColumns)].reduce((acc, _, c0) => acc + this.colSize(c0, 'grid'), 0) +
|
|
1440
|
-
gap * (this.limitColumns - 1)
|
|
1543
|
+
gap * Math.max(0, this.limitColumns - 1)
|
|
1441
1544
|
: Infinity;
|
|
1442
1545
|
this.totalIntrinsicInlineSize =
|
|
1443
|
-
this.intrinsicInlineSize +
|
|
1444
|
-
(Number.isFinite(this.frozen.frozenColsStart)
|
|
1445
|
-
? [...Array(this.frozen.frozenColsStart)].reduce(
|
|
1446
|
-
(acc, _, c0) => acc + gap + this.colSize(c0, 'frozenColsStart'),
|
|
1447
|
-
0,
|
|
1448
|
-
)
|
|
1449
|
-
: 0) +
|
|
1450
|
-
(Number.isFinite(this.frozen.frozenColsEnd)
|
|
1451
|
-
? [...Array(this.frozen.frozenColsEnd)].reduce((acc, _, c0) => acc + gap + this.colSize(c0, 'frozenColsEnd'), 0)
|
|
1452
|
-
: 0);
|
|
1546
|
+
this.limitColumns > 0 ? this.intrinsicInlineSize + this.frozenColsSize : this.frozenColsSize - gap;
|
|
1453
1547
|
}
|
|
1454
1548
|
|
|
1455
1549
|
private updateIntrinsicBlockSize(): void {
|
|
1456
1550
|
this.intrinsicBlockSize = Number.isFinite(this.limitRows)
|
|
1457
1551
|
? [...Array(this.limitRows)].reduce((acc, _, r0) => acc + this.rowSize(r0, 'grid'), 0) +
|
|
1458
|
-
gap * (this.limitRows - 1)
|
|
1552
|
+
gap * Math.max(0, this.limitRows - 1)
|
|
1459
1553
|
: Infinity;
|
|
1460
1554
|
this.totalIntrinsicBlockSize =
|
|
1461
|
-
this.intrinsicBlockSize +
|
|
1462
|
-
(Number.isFinite(this.frozen.frozenRowsStart)
|
|
1463
|
-
? [...Array(this.frozen.frozenRowsStart)].reduce(
|
|
1464
|
-
(acc, _, r0) => acc + gap + this.rowSize(r0, 'frozenRowsStart'),
|
|
1465
|
-
0,
|
|
1466
|
-
)
|
|
1467
|
-
: 0) +
|
|
1468
|
-
(Number.isFinite(this.frozen.frozenRowsEnd)
|
|
1469
|
-
? [...Array(this.frozen.frozenRowsEnd)].reduce((acc, _, r0) => acc + gap + this.rowSize(r0, 'frozenRowsEnd'), 0)
|
|
1470
|
-
: 0);
|
|
1555
|
+
this.limitRows > 0 ? this.intrinsicBlockSize + this.frozenRowsSize : this.frozenRowsSize - gap;
|
|
1471
1556
|
}
|
|
1472
1557
|
|
|
1473
1558
|
private updateIntrinsicSizes(): void {
|
|
@@ -1515,7 +1600,7 @@ export class DxGrid extends LitElement {
|
|
|
1515
1600
|
if (this.getCells) {
|
|
1516
1601
|
this.updateCells(true);
|
|
1517
1602
|
}
|
|
1518
|
-
this.observer.observe(this.
|
|
1603
|
+
this.observer.observe(this.gridRef.value!);
|
|
1519
1604
|
this.computeColSizes();
|
|
1520
1605
|
this.computeRowSizes();
|
|
1521
1606
|
this.updateIntrinsicSizes();
|
|
@@ -1589,8 +1674,8 @@ export class DxGrid extends LitElement {
|
|
|
1589
1674
|
|
|
1590
1675
|
override disconnectedCallback(): void {
|
|
1591
1676
|
super.disconnectedCallback();
|
|
1592
|
-
if (this.
|
|
1593
|
-
this.observer.unobserve(this.
|
|
1677
|
+
if (this.gridRef.value) {
|
|
1678
|
+
this.observer.unobserve(this.gridRef.value);
|
|
1594
1679
|
}
|
|
1595
1680
|
document.defaultView?.removeEventListener('wheel', this.handleTopLevelWheel);
|
|
1596
1681
|
}
|
|
@@ -1608,6 +1693,7 @@ export {
|
|
|
1608
1693
|
parseCellIndex,
|
|
1609
1694
|
toPlaneCellIndex,
|
|
1610
1695
|
cellQuery,
|
|
1696
|
+
accessoryHandlesPointerdownAttrs,
|
|
1611
1697
|
} from './util';
|
|
1612
1698
|
|
|
1613
1699
|
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: '
|
|
13
|
+
command: 'pnpm storybook dev --ci --quiet --port=9002 --config-dir=.storybook',
|
|
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;
|