@dxos/lit-grid 0.8.4-main.3f58842 → 0.8.4-main.406dc2a
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 +202 -163
- package/dist/src/dx-grid.js.map +1 -1
- package/dist/src/dx-grid.lit-stories.js +15 -18
- 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/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 +4 -4
- 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 +196 -110
- package/src/playwright/dx-grid.spec.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,74 +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';
|
|
12
|
-
// eslint-disable-next-line unused-imports/no-unused-imports
|
|
11
|
+
import { defaultColSize, defaultRowSize, focusUnfurlDefault } from './defs';
|
|
13
12
|
import './dx-grid-axis-resize-handle';
|
|
14
13
|
import {
|
|
15
|
-
type DxGridAxisMetaProps,
|
|
16
|
-
type DxGridAxisSizes,
|
|
17
|
-
type DxGridPlaneCellIndex,
|
|
18
|
-
type DxGridCellValue,
|
|
19
14
|
DxAxisResize,
|
|
20
15
|
type DxAxisResizeInternal,
|
|
21
16
|
DxEditRequest,
|
|
17
|
+
type DxGridAnnotatedPanEvent,
|
|
18
|
+
type DxGridAxis,
|
|
22
19
|
type DxGridAxisMeta,
|
|
20
|
+
type DxGridAxisMetaProps,
|
|
21
|
+
type DxGridAxisSizes,
|
|
22
|
+
type DxGridCellValue,
|
|
23
23
|
type DxGridCells,
|
|
24
24
|
DxGridCellsSelect,
|
|
25
25
|
type DxGridFixedPlane,
|
|
26
|
+
type DxGridFocusIndicatorVariant,
|
|
26
27
|
type DxGridFrozenAxes,
|
|
27
28
|
type DxGridFrozenColsPlane,
|
|
28
29
|
type DxGridFrozenPlane,
|
|
29
30
|
type DxGridFrozenRowsPlane,
|
|
30
31
|
type DxGridMode,
|
|
32
|
+
type DxGridOverscroll,
|
|
31
33
|
type DxGridPlane,
|
|
34
|
+
type DxGridPlaneCellIndex,
|
|
32
35
|
type DxGridPlaneCells,
|
|
33
36
|
type DxGridPlaneRange,
|
|
34
37
|
type DxGridPlaneRecord,
|
|
35
38
|
type DxGridPointer,
|
|
36
39
|
type DxGridPosition,
|
|
37
|
-
type DxGridAxis,
|
|
38
|
-
type DxGridSelectionProps,
|
|
39
|
-
type DxGridAnnotatedPanEvent,
|
|
40
40
|
type DxGridRange,
|
|
41
|
+
type DxGridSelectionProps,
|
|
41
42
|
separator,
|
|
42
43
|
} from './types';
|
|
43
44
|
import {
|
|
44
|
-
toCellIndex,
|
|
45
|
-
gap,
|
|
46
|
-
resizeTolerance,
|
|
47
|
-
sizeColMin,
|
|
48
|
-
sizeColMax,
|
|
49
|
-
sizeRowMin,
|
|
50
|
-
sizeRowMax,
|
|
51
|
-
shouldSelect,
|
|
52
|
-
selectionProps,
|
|
53
45
|
cellSelected,
|
|
54
46
|
closestAction,
|
|
55
47
|
closestCell,
|
|
56
|
-
|
|
57
|
-
|
|
48
|
+
gap,
|
|
49
|
+
isReadonly,
|
|
50
|
+
isSameCell,
|
|
51
|
+
resizeTolerance,
|
|
58
52
|
resolveColPlane,
|
|
59
53
|
resolveFrozenPlane,
|
|
60
|
-
|
|
61
|
-
|
|
54
|
+
resolveRowPlane,
|
|
55
|
+
selectionProps,
|
|
56
|
+
shouldSelect,
|
|
57
|
+
sizeColMax,
|
|
58
|
+
sizeColMin,
|
|
59
|
+
sizeRowMax,
|
|
60
|
+
sizeRowMin,
|
|
61
|
+
targetIsPlane,
|
|
62
|
+
toCellIndex,
|
|
62
63
|
} from './util';
|
|
63
64
|
|
|
64
65
|
@customElement('dx-grid')
|
|
65
66
|
export class DxGrid extends LitElement {
|
|
66
67
|
constructor() {
|
|
67
68
|
super();
|
|
68
|
-
// Wheel, top-level and element-level
|
|
69
|
+
// Wheel, top-level and element-level.
|
|
69
70
|
document.defaultView?.addEventListener('wheel', this.handleTopLevelWheel, { passive: false });
|
|
70
71
|
this.addEventListener('wheel', this.handleWheel);
|
|
71
|
-
// Custom event(s)
|
|
72
|
+
// Custom event(s).
|
|
72
73
|
this.addEventListener('dx-axis-resize-internal', this.handleAxisResizeInternal as EventListener);
|
|
73
|
-
// Standard events
|
|
74
|
+
// Standard events.
|
|
74
75
|
this.addEventListener('pointerdown', this.handlePointerDown);
|
|
75
76
|
this.addEventListener('pointermove', this.handlePointerMove);
|
|
76
77
|
this.addEventListener('pointerup', this.handlePointerUp);
|
|
@@ -84,12 +85,12 @@ export class DxGrid extends LitElement {
|
|
|
84
85
|
gridId: string = 'default-grid-id';
|
|
85
86
|
|
|
86
87
|
@property({ type: Object })
|
|
87
|
-
rowDefault: DxGridPlaneRecord<DxGridFrozenRowsPlane, DxGridAxisMetaProps
|
|
88
|
+
rowDefault: Partial<DxGridPlaneRecord<DxGridFrozenRowsPlane, Partial<DxGridAxisMetaProps>>> = {
|
|
88
89
|
grid: { size: defaultRowSize },
|
|
89
90
|
};
|
|
90
91
|
|
|
91
92
|
@property({ type: Object })
|
|
92
|
-
columnDefault: DxGridPlaneRecord<DxGridFrozenColsPlane, DxGridAxisMetaProps
|
|
93
|
+
columnDefault: Partial<DxGridPlaneRecord<DxGridFrozenColsPlane, Partial<DxGridAxisMetaProps>>> = {
|
|
93
94
|
grid: { size: defaultColSize },
|
|
94
95
|
};
|
|
95
96
|
|
|
@@ -115,11 +116,14 @@ export class DxGrid extends LitElement {
|
|
|
115
116
|
frozen: DxGridFrozenAxes = {};
|
|
116
117
|
|
|
117
118
|
@property({ type: String })
|
|
118
|
-
overscroll:
|
|
119
|
+
overscroll: DxGridOverscroll = undefined;
|
|
119
120
|
|
|
120
121
|
@property({ type: String })
|
|
121
122
|
activeRefs = '';
|
|
122
123
|
|
|
124
|
+
@property({ type: String })
|
|
125
|
+
focusIndicatorVariant: DxGridFocusIndicatorVariant = 'sheet';
|
|
126
|
+
|
|
123
127
|
/**
|
|
124
128
|
* When this function is defined, it is used first to try to get a value for a cell,
|
|
125
129
|
* and otherwise will fall back to `cells`.
|
|
@@ -195,6 +199,7 @@ export class DxGrid extends LitElement {
|
|
|
195
199
|
//
|
|
196
200
|
// `template` is the rendered value of `grid-{axis}-template`.
|
|
197
201
|
//
|
|
202
|
+
|
|
198
203
|
@state()
|
|
199
204
|
private templateGridColumns = '0';
|
|
200
205
|
|
|
@@ -213,6 +218,16 @@ export class DxGrid extends LitElement {
|
|
|
213
218
|
@state()
|
|
214
219
|
private templatefrozenRowsEnd = '';
|
|
215
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
|
+
|
|
216
231
|
//
|
|
217
232
|
// Focus, selection, and resize states
|
|
218
233
|
//
|
|
@@ -308,7 +323,7 @@ export class DxGrid extends LitElement {
|
|
|
308
323
|
this.dispatchSelectionChange();
|
|
309
324
|
}
|
|
310
325
|
if (this.mode === 'edit-select') {
|
|
311
|
-
// Prevent focus moving when editing while selection is possible
|
|
326
|
+
// Prevent focus moving when editing while selection is possible.
|
|
312
327
|
event.preventDefault();
|
|
313
328
|
} else if (this.focusActive && isSameCell(this.focusedCell, cellCoords)) {
|
|
314
329
|
this.dispatchEditRequest();
|
|
@@ -416,15 +431,13 @@ export class DxGrid extends LitElement {
|
|
|
416
431
|
}
|
|
417
432
|
|
|
418
433
|
private moveFocusIntoPlane(plane: DxGridPlane): void {
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
};
|
|
427
|
-
}
|
|
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
|
+
};
|
|
428
441
|
this.focusedCellElement()?.focus({ preventScroll: true });
|
|
429
442
|
}
|
|
430
443
|
|
|
@@ -481,6 +494,13 @@ export class DxGrid extends LitElement {
|
|
|
481
494
|
event.preventDefault();
|
|
482
495
|
this.dispatchEditRequest();
|
|
483
496
|
break;
|
|
497
|
+
case 'Backspace':
|
|
498
|
+
case 'Delete':
|
|
499
|
+
if (!event.defaultPrevented) {
|
|
500
|
+
event.preventDefault();
|
|
501
|
+
this.dispatchEditRequest('');
|
|
502
|
+
}
|
|
503
|
+
break;
|
|
484
504
|
default:
|
|
485
505
|
if (event.key.length === 1 && event.key.match(/\P{Cc}/u) && !(event.metaKey || event.ctrlKey)) {
|
|
486
506
|
this.dispatchEditRequest(event.key);
|
|
@@ -574,7 +594,7 @@ export class DxGrid extends LitElement {
|
|
|
574
594
|
}
|
|
575
595
|
|
|
576
596
|
//
|
|
577
|
-
// Resize & reposition handlers, observer, ref
|
|
597
|
+
// Resize & reposition handlers, observer, ref.
|
|
578
598
|
//
|
|
579
599
|
|
|
580
600
|
@state()
|
|
@@ -584,19 +604,18 @@ export class DxGrid extends LitElement {
|
|
|
584
604
|
blockSize: 0,
|
|
585
605
|
};
|
|
586
606
|
if (
|
|
587
|
-
Math.abs(inlineSize - this.sizeInline) > resizeTolerance ||
|
|
588
|
-
Math.abs(blockSize - this.sizeBlock) > resizeTolerance
|
|
607
|
+
Math.abs(inlineSize - this.frozenColsSize - this.sizeInline) > resizeTolerance ||
|
|
608
|
+
Math.abs(blockSize - this.frozenRowsSize - this.sizeBlock) > resizeTolerance
|
|
589
609
|
) {
|
|
590
610
|
// console.info('[updating bounds]', 'resize', [inlineSize - this.sizeInline, blockSize - this.sizeBlock]);
|
|
591
|
-
this.sizeInline = inlineSize;
|
|
592
|
-
this.sizeBlock = blockSize;
|
|
611
|
+
this.sizeInline = inlineSize - this.frozenColsSize;
|
|
612
|
+
this.sizeBlock = blockSize - this.frozenRowsSize;
|
|
593
613
|
this.updateVis();
|
|
594
614
|
queueMicrotask(() => this.updatePos());
|
|
595
615
|
}
|
|
596
616
|
});
|
|
597
617
|
|
|
598
618
|
private gridRef: Ref<HTMLDivElement> = createRef();
|
|
599
|
-
private viewportRef: Ref<HTMLDivElement> = createRef();
|
|
600
619
|
|
|
601
620
|
private maybeUpdateVisInline = () => {
|
|
602
621
|
if (this.posInline < this.binInlineMin || this.posInline >= this.binInlineMax) {
|
|
@@ -675,7 +694,7 @@ export class DxGrid extends LitElement {
|
|
|
675
694
|
};
|
|
676
695
|
|
|
677
696
|
private updateVisInline(): void {
|
|
678
|
-
// todo: avoid starting from zero
|
|
697
|
+
// todo: avoid starting from zero.
|
|
679
698
|
let axisCursor = 0;
|
|
680
699
|
let pxCursor = this.colSize(axisCursor, 'grid');
|
|
681
700
|
|
|
@@ -721,10 +740,19 @@ export class DxGrid extends LitElement {
|
|
|
721
740
|
this.templatefrozenColsEnd = [...Array(this.frozen.frozenColsEnd ?? 0)]
|
|
722
741
|
.map((_, c0) => `${this.colSize(c0, 'frozenColsEnd')}px`)
|
|
723
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);
|
|
724
752
|
}
|
|
725
753
|
|
|
726
754
|
private updateVisBlock(): void {
|
|
727
|
-
// todo: avoid starting from zero
|
|
755
|
+
// todo: avoid starting from zero.
|
|
728
756
|
let axisCursor = 0;
|
|
729
757
|
let pxCursor = this.rowSize(axisCursor, 'grid');
|
|
730
758
|
|
|
@@ -770,6 +798,15 @@ export class DxGrid extends LitElement {
|
|
|
770
798
|
this.templatefrozenRowsEnd = [...Array(this.frozen.frozenRowsEnd ?? 0)]
|
|
771
799
|
.map((_, r0) => `${this.rowSize(r0, 'frozenRowsEnd')}px`)
|
|
772
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);
|
|
773
810
|
}
|
|
774
811
|
|
|
775
812
|
private updateVis(): void {
|
|
@@ -991,7 +1028,7 @@ export class DxGrid extends LitElement {
|
|
|
991
1028
|
}
|
|
992
1029
|
|
|
993
1030
|
/**
|
|
994
|
-
* 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.
|
|
995
1032
|
*/
|
|
996
1033
|
snapPosToFocusedCell(): void {
|
|
997
1034
|
const outOfVis = this.focusedCellOutOfVis();
|
|
@@ -1068,16 +1105,40 @@ export class DxGrid extends LitElement {
|
|
|
1068
1105
|
: !!(this.rows[plane]?.[index]?.resizeable ?? this.rowDefault[plane as DxGridFrozenRowsPlane]?.resizeable);
|
|
1069
1106
|
}
|
|
1070
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
|
+
|
|
1071
1133
|
private handleAxisResizeInternal(event: DxAxisResizeInternal): void {
|
|
1072
1134
|
event.stopPropagation();
|
|
1073
1135
|
const { plane, axis, delta, size, index, state } = event;
|
|
1136
|
+
const nextSize = this.clampAxisSize(plane, axis, index, size + delta);
|
|
1074
1137
|
if (axis === 'col') {
|
|
1075
|
-
const nextSize = Math.max(sizeColMin, Math.min(sizeColMax, size + delta));
|
|
1076
1138
|
this.colSizes = { ...this.colSizes, [plane]: { ...this.colSizes[plane], [index]: nextSize } };
|
|
1077
1139
|
this.updateVisInline();
|
|
1078
1140
|
this.updateIntrinsicInlineSize();
|
|
1079
1141
|
} else {
|
|
1080
|
-
const nextSize = Math.max(sizeRowMin, Math.min(sizeRowMax, size + delta));
|
|
1081
1142
|
this.rowSizes = { ...this.colSizes, [plane]: { ...this.rowSizes[plane], [index]: nextSize } };
|
|
1082
1143
|
this.updateVisBlock();
|
|
1083
1144
|
this.updateIntrinsicBlockSize();
|
|
@@ -1095,7 +1156,7 @@ export class DxGrid extends LitElement {
|
|
|
1095
1156
|
}
|
|
1096
1157
|
|
|
1097
1158
|
//
|
|
1098
|
-
// Render and other lifecycle methods
|
|
1159
|
+
// Render and other lifecycle methods.
|
|
1099
1160
|
//
|
|
1100
1161
|
|
|
1101
1162
|
// TODO(thure): This is for rendering presentational objects superimposed onto the canonical grid (e.g. DnD drop line for #8108).
|
|
@@ -1178,7 +1239,7 @@ export class DxGrid extends LitElement {
|
|
|
1178
1239
|
) {
|
|
1179
1240
|
const rowPlane = resolveRowPlane(plane) as DxGridFrozenPlane;
|
|
1180
1241
|
const rows = this.frozen[rowPlane];
|
|
1181
|
-
return (rows ?? 0) > 0
|
|
1242
|
+
return (rows ?? 0) > 0 && this.limitColumns > 0
|
|
1182
1243
|
? html`<div
|
|
1183
1244
|
role="none"
|
|
1184
1245
|
class="dx-grid__plane--frozen-row"
|
|
@@ -1212,7 +1273,7 @@ export class DxGrid extends LitElement {
|
|
|
1212
1273
|
) {
|
|
1213
1274
|
const colPlane = resolveColPlane(plane) as DxGridFrozenPlane;
|
|
1214
1275
|
const cols = this.frozen[colPlane];
|
|
1215
|
-
return (cols ?? 0) > 0
|
|
1276
|
+
return (cols ?? 0) > 0 && this.limitRows > 0
|
|
1216
1277
|
? html`<div
|
|
1217
1278
|
role="none"
|
|
1218
1279
|
class="dx-grid__plane--frozen-col"
|
|
@@ -1238,6 +1299,40 @@ export class DxGrid extends LitElement {
|
|
|
1238
1299
|
: null;
|
|
1239
1300
|
}
|
|
1240
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
|
+
|
|
1241
1336
|
private cellReadonly(col: number, row: number, plane: DxGridPlane): boolean {
|
|
1242
1337
|
const colPlane = resolveColPlane(plane);
|
|
1243
1338
|
const rowPlane = resolveRowPlane(plane);
|
|
@@ -1255,6 +1350,23 @@ export class DxGrid extends LitElement {
|
|
|
1255
1350
|
return isReadonly(colReadOnly) || isReadonly(rowReadOnly);
|
|
1256
1351
|
}
|
|
1257
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
|
+
|
|
1258
1370
|
/**
|
|
1259
1371
|
* Determines if the cell's text content should be selectable based on its readonly value.
|
|
1260
1372
|
* @returns true if the cells text content is selectable, false otherwise.
|
|
@@ -1317,6 +1429,7 @@ export class DxGrid extends LitElement {
|
|
|
1317
1429
|
const cell = this.cell(col, row, plane);
|
|
1318
1430
|
const active = this.cellActive(col, row, plane);
|
|
1319
1431
|
const readonly = this.cellReadonly(col, row, plane);
|
|
1432
|
+
const focusUnfurl = this.cellFocusUnfurl(col, row, plane);
|
|
1320
1433
|
const textSelectable = this.cellTextSelectable(col, row, plane);
|
|
1321
1434
|
const resizeIndex = cell?.resizeHandle ? (cell.resizeHandle === 'col' ? col : row) : undefined;
|
|
1322
1435
|
const resizePlane = cell?.resizeHandle ? resolveFrozenPlane(cell.resizeHandle, plane) : undefined;
|
|
@@ -1328,6 +1441,7 @@ export class DxGrid extends LitElement {
|
|
|
1328
1441
|
aria-readonly=${readonly ? 'true' : nothing}
|
|
1329
1442
|
class=${cell?.className ?? nothing}
|
|
1330
1443
|
data-refs=${cell?.dataRefs ?? nothing}
|
|
1444
|
+
data-focus-unfurl=${focusUnfurl ? nothing : 'false'}
|
|
1331
1445
|
?data-dx-active=${active}
|
|
1332
1446
|
data-text-selectable=${textSelectable ? 'true' : 'false'}
|
|
1333
1447
|
data-dx-grid-action="cell"
|
|
@@ -1370,13 +1484,24 @@ export class DxGrid extends LitElement {
|
|
|
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';
|
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) {
|