@dxos/lit-grid 0.8.3 → 0.8.4-main.1da679c
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 +11 -6
- package/dist/src/dx-grid.d.ts.map +1 -1
- package/dist/src/dx-grid.js +229 -150
- package/dist/src/dx-grid.js.map +1 -1
- package/dist/src/dx-grid.lit-stories.d.ts +1 -0
- package/dist/src/dx-grid.lit-stories.d.ts.map +1 -1
- package/dist/src/dx-grid.lit-stories.js +19 -20
- package/dist/src/dx-grid.lit-stories.js.map +1 -1
- package/dist/src/playwright/dx-grid.spec.d.ts.map +1 -0
- package/dist/src/{testing/playwright → playwright}/dx-grid.spec.js +3 -3
- package/dist/src/playwright/dx-grid.spec.js.map +1 -0
- package/dist/src/playwright/playwright.config.d.ts +3 -0
- package/dist/src/playwright/playwright.config.d.ts.map +1 -0
- package/dist/src/playwright/playwright.config.js +15 -0
- package/dist/src/playwright/playwright.config.js.map +1 -0
- package/dist/src/testing/{playwright/dx-grid-manager.d.ts → dx-grid-manager.d.ts} +1 -1
- package/dist/src/testing/dx-grid-manager.d.ts.map +1 -0
- package/dist/src/testing/dx-grid-manager.js.map +1 -0
- package/dist/src/testing/index.d.ts +1 -1
- package/dist/src/testing/index.d.ts.map +1 -1
- package/dist/src/testing/index.js +1 -1
- package/dist/src/testing/index.js.map +1 -1
- package/dist/src/types.d.ts +7 -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 +6 -5
- package/src/defs.ts +1 -0
- package/src/dx-grid-axis-resize-handle.pcss +7 -0
- package/src/dx-grid-axis-resize-handle.ts +1 -1
- package/src/dx-grid-multiselect-cell.pcss +2 -2
- package/src/dx-grid-multiselect-cell.ts +2 -1
- package/src/dx-grid.lit-stories.ts +6 -2
- package/src/dx-grid.pcss +133 -15
- package/src/dx-grid.ts +240 -100
- package/src/{testing/playwright → playwright}/dx-grid.spec.ts +5 -5
- package/src/playwright/playwright.config.ts +17 -0
- package/src/testing/{playwright/dx-grid-manager.ts → dx-grid-manager.ts} +2 -2
- package/src/testing/index.ts +1 -1
- package/src/types.ts +7 -0
- package/src/util.ts +13 -9
- package/dist/src/testing/playwright/dx-grid-manager.d.ts.map +0 -1
- package/dist/src/testing/playwright/dx-grid-manager.js.map +0 -1
- package/dist/src/testing/playwright/dx-grid.spec.d.ts.map +0 -1
- package/dist/src/testing/playwright/dx-grid.spec.js.map +0 -1
- package/dist/types/src/defs.d.ts +0 -3
- package/dist/types/src/defs.d.ts.map +0 -1
- package/dist/types/src/defs.js +0 -6
- package/dist/types/src/defs.js.map +0 -1
- package/dist/types/src/dx-grid-axis-resize-handle.d.ts +0 -16
- package/dist/types/src/dx-grid-axis-resize-handle.d.ts.map +0 -1
- package/dist/types/src/dx-grid-axis-resize-handle.js +0 -100
- package/dist/types/src/dx-grid-axis-resize-handle.js.map +0 -1
- package/dist/types/src/dx-grid-multiselect-cell.d.ts +0 -13
- package/dist/types/src/dx-grid-multiselect-cell.d.ts.map +0 -1
- package/dist/types/src/dx-grid-multiselect-cell.js +0 -56
- package/dist/types/src/dx-grid-multiselect-cell.js.map +0 -1
- package/dist/types/src/dx-grid.d.ts +0 -170
- package/dist/types/src/dx-grid.d.ts.map +0 -1
- package/dist/types/src/dx-grid.js +0 -1347
- package/dist/types/src/dx-grid.js.map +0 -1
- package/dist/types/src/dx-grid.lit-stories.d.ts +0 -46
- package/dist/types/src/dx-grid.lit-stories.d.ts.map +0 -1
- package/dist/types/src/dx-grid.lit-stories.js +0 -179
- package/dist/types/src/dx-grid.lit-stories.js.map +0 -1
- package/dist/types/src/index.d.ts +0 -5
- package/dist/types/src/index.d.ts.map +0 -1
- package/dist/types/src/index.js +0 -8
- package/dist/types/src/index.js.map +0 -1
- package/dist/types/src/testing/index.d.ts +0 -2
- package/dist/types/src/testing/index.d.ts.map +0 -1
- package/dist/types/src/testing/index.js +0 -5
- package/dist/types/src/testing/index.js.map +0 -1
- package/dist/types/src/testing/playwright/dx-grid-manager.d.ts +0 -24
- package/dist/types/src/testing/playwright/dx-grid-manager.d.ts.map +0 -1
- package/dist/types/src/testing/playwright/dx-grid-manager.js +0 -79
- package/dist/types/src/testing/playwright/dx-grid-manager.js.map +0 -1
- package/dist/types/src/testing/playwright/dx-grid.spec.d.ts +0 -2
- package/dist/types/src/testing/playwright/dx-grid.spec.d.ts.map +0 -1
- package/dist/types/src/testing/playwright/dx-grid.spec.js +0 -92
- package/dist/types/src/testing/playwright/dx-grid.spec.js.map +0 -1
- package/dist/types/src/types.d.ts +0 -137
- package/dist/types/src/types.d.ts.map +0 -1
- package/dist/types/src/types.js +0 -46
- package/dist/types/src/types.js.map +0 -1
- package/dist/types/src/util.d.ts +0 -39
- package/dist/types/src/util.d.ts.map +0 -1
- package/dist/types/src/util.js +0 -165
- package/dist/types/src/util.js.map +0 -1
- package/dist/types/tsconfig.tsbuildinfo +0 -1
- package/src/testing/playwright/playwright.config.cts +0 -18
- /package/dist/src/{testing/playwright → playwright}/dx-grid.spec.d.ts +0 -0
- /package/dist/src/testing/{playwright/dx-grid-manager.js → dx-grid-manager.js} +0 -0
package/src/dx-grid.ts
CHANGED
|
@@ -3,23 +3,23 @@
|
|
|
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,
|
|
@@ -29,36 +29,35 @@ import {
|
|
|
29
29
|
type DxGridFrozenRowsPlane,
|
|
30
30
|
type DxGridMode,
|
|
31
31
|
type DxGridPlane,
|
|
32
|
+
type DxGridPlaneCellIndex,
|
|
32
33
|
type DxGridPlaneCells,
|
|
33
34
|
type DxGridPlaneRange,
|
|
34
35
|
type DxGridPlaneRecord,
|
|
35
36
|
type DxGridPointer,
|
|
36
37
|
type DxGridPosition,
|
|
37
|
-
type DxGridAxis,
|
|
38
|
-
type DxGridSelectionProps,
|
|
39
|
-
type DxGridAnnotatedPanEvent,
|
|
40
38
|
type DxGridRange,
|
|
39
|
+
type DxGridSelectionProps,
|
|
41
40
|
separator,
|
|
42
41
|
} from './types';
|
|
43
42
|
import {
|
|
44
|
-
toCellIndex,
|
|
45
|
-
gap,
|
|
46
|
-
resizeTolerance,
|
|
47
|
-
sizeColMin,
|
|
48
|
-
sizeColMax,
|
|
49
|
-
sizeRowMin,
|
|
50
|
-
sizeRowMax,
|
|
51
|
-
shouldSelect,
|
|
52
|
-
selectionProps,
|
|
53
43
|
cellSelected,
|
|
54
44
|
closestAction,
|
|
55
45
|
closestCell,
|
|
56
|
-
|
|
57
|
-
|
|
46
|
+
gap,
|
|
47
|
+
isReadonly,
|
|
48
|
+
isSameCell,
|
|
49
|
+
resizeTolerance,
|
|
58
50
|
resolveColPlane,
|
|
59
51
|
resolveFrozenPlane,
|
|
60
|
-
|
|
61
|
-
|
|
52
|
+
resolveRowPlane,
|
|
53
|
+
selectionProps,
|
|
54
|
+
shouldSelect,
|
|
55
|
+
sizeColMax,
|
|
56
|
+
sizeColMin,
|
|
57
|
+
sizeRowMax,
|
|
58
|
+
sizeRowMin,
|
|
59
|
+
targetIsPlane,
|
|
60
|
+
toCellIndex,
|
|
62
61
|
} from './util';
|
|
63
62
|
|
|
64
63
|
@customElement('dx-grid')
|
|
@@ -84,12 +83,12 @@ export class DxGrid extends LitElement {
|
|
|
84
83
|
gridId: string = 'default-grid-id';
|
|
85
84
|
|
|
86
85
|
@property({ type: Object })
|
|
87
|
-
rowDefault: DxGridPlaneRecord<DxGridFrozenRowsPlane, DxGridAxisMetaProps
|
|
86
|
+
rowDefault: Partial<DxGridPlaneRecord<DxGridFrozenRowsPlane, Partial<DxGridAxisMetaProps>>> = {
|
|
88
87
|
grid: { size: defaultRowSize },
|
|
89
88
|
};
|
|
90
89
|
|
|
91
90
|
@property({ type: Object })
|
|
92
|
-
columnDefault: DxGridPlaneRecord<DxGridFrozenColsPlane, DxGridAxisMetaProps
|
|
91
|
+
columnDefault: Partial<DxGridPlaneRecord<DxGridFrozenColsPlane, Partial<DxGridAxisMetaProps>>> = {
|
|
93
92
|
grid: { size: defaultColSize },
|
|
94
93
|
};
|
|
95
94
|
|
|
@@ -213,6 +212,16 @@ export class DxGrid extends LitElement {
|
|
|
213
212
|
@state()
|
|
214
213
|
private templatefrozenRowsEnd = '';
|
|
215
214
|
|
|
215
|
+
//
|
|
216
|
+
// `frozen…Size` is used to measure space available for the non-fixed planes
|
|
217
|
+
//
|
|
218
|
+
|
|
219
|
+
@state()
|
|
220
|
+
private frozenColsSize = 0;
|
|
221
|
+
|
|
222
|
+
@state()
|
|
223
|
+
private frozenRowsSize = 0;
|
|
224
|
+
|
|
216
225
|
//
|
|
217
226
|
// Focus, selection, and resize states
|
|
218
227
|
//
|
|
@@ -481,6 +490,13 @@ export class DxGrid extends LitElement {
|
|
|
481
490
|
event.preventDefault();
|
|
482
491
|
this.dispatchEditRequest();
|
|
483
492
|
break;
|
|
493
|
+
case 'Backspace':
|
|
494
|
+
case 'Delete':
|
|
495
|
+
if (!event.defaultPrevented) {
|
|
496
|
+
event.preventDefault();
|
|
497
|
+
this.dispatchEditRequest('');
|
|
498
|
+
}
|
|
499
|
+
break;
|
|
484
500
|
default:
|
|
485
501
|
if (event.key.length === 1 && event.key.match(/\P{Cc}/u) && !(event.metaKey || event.ctrlKey)) {
|
|
486
502
|
this.dispatchEditRequest(event.key);
|
|
@@ -584,19 +600,18 @@ export class DxGrid extends LitElement {
|
|
|
584
600
|
blockSize: 0,
|
|
585
601
|
};
|
|
586
602
|
if (
|
|
587
|
-
Math.abs(inlineSize - this.sizeInline) > resizeTolerance ||
|
|
588
|
-
Math.abs(blockSize - this.sizeBlock) > resizeTolerance
|
|
603
|
+
Math.abs(inlineSize - this.frozenColsSize - this.sizeInline) > resizeTolerance ||
|
|
604
|
+
Math.abs(blockSize - this.frozenRowsSize - this.sizeBlock) > resizeTolerance
|
|
589
605
|
) {
|
|
590
606
|
// console.info('[updating bounds]', 'resize', [inlineSize - this.sizeInline, blockSize - this.sizeBlock]);
|
|
591
|
-
this.sizeInline = inlineSize;
|
|
592
|
-
this.sizeBlock = blockSize;
|
|
607
|
+
this.sizeInline = inlineSize - this.frozenColsSize;
|
|
608
|
+
this.sizeBlock = blockSize - this.frozenRowsSize;
|
|
593
609
|
this.updateVis();
|
|
594
610
|
queueMicrotask(() => this.updatePos());
|
|
595
611
|
}
|
|
596
612
|
});
|
|
597
613
|
|
|
598
614
|
private gridRef: Ref<HTMLDivElement> = createRef();
|
|
599
|
-
private viewportRef: Ref<HTMLDivElement> = createRef();
|
|
600
615
|
|
|
601
616
|
private maybeUpdateVisInline = () => {
|
|
602
617
|
if (this.posInline < this.binInlineMin || this.posInline >= this.binInlineMax) {
|
|
@@ -640,16 +655,29 @@ export class DxGrid extends LitElement {
|
|
|
640
655
|
(this.overscroll === 'inline' && event.overscrollInline === 0) ||
|
|
641
656
|
(this.overscroll === 'block' && event.overscrollBlock === 0)
|
|
642
657
|
) {
|
|
643
|
-
event.
|
|
644
|
-
|
|
658
|
+
const element = event.target as HTMLElement;
|
|
659
|
+
const activeCell = element.closest('[data-dx-active]');
|
|
660
|
+
const contentEl = element.closest('.dx-grid__cell__content');
|
|
661
|
+
if (
|
|
662
|
+
!(
|
|
663
|
+
element &&
|
|
664
|
+
activeCell &&
|
|
665
|
+
contentEl &&
|
|
666
|
+
(contentEl.scrollWidth > contentEl.clientWidth || contentEl.scrollHeight > contentEl.clientHeight)
|
|
667
|
+
)
|
|
668
|
+
) {
|
|
669
|
+
event.preventDefault();
|
|
670
|
+
event.stopPropagation();
|
|
671
|
+
}
|
|
645
672
|
}
|
|
646
673
|
}
|
|
647
674
|
};
|
|
648
675
|
|
|
649
676
|
private handleWheel = (event: DxGridAnnotatedPanEvent) => {
|
|
650
677
|
if (this.mode === 'browse') {
|
|
651
|
-
const
|
|
652
|
-
const
|
|
678
|
+
const { deltaX, deltaY } = this.getOverflowingCellModifiedDeltas(event);
|
|
679
|
+
const nextPosInline = this.posInline + deltaX;
|
|
680
|
+
const nextPosBlock = this.posBlock + deltaY;
|
|
653
681
|
const maxPosInline = this.maxPosInline();
|
|
654
682
|
const maxPosBlock = this.maxPosBlock();
|
|
655
683
|
this.updatePos(nextPosInline, nextPosBlock, maxPosInline, maxPosBlock);
|
|
@@ -708,6 +736,15 @@ export class DxGrid extends LitElement {
|
|
|
708
736
|
this.templatefrozenColsEnd = [...Array(this.frozen.frozenColsEnd ?? 0)]
|
|
709
737
|
.map((_, c0) => `${this.colSize(c0, 'frozenColsEnd')}px`)
|
|
710
738
|
.join(' ');
|
|
739
|
+
|
|
740
|
+
this.frozenColsSize =
|
|
741
|
+
[...Array(this.frozen.frozenColsStart ?? 0)].reduce(
|
|
742
|
+
(sum, _, c0) => sum + this.colSize(c0, 'frozenColsStart'),
|
|
743
|
+
0,
|
|
744
|
+
) +
|
|
745
|
+
gap * Math.max(0, this.frozen.frozenColsStart ?? 0 - 1) +
|
|
746
|
+
[...Array(this.frozen.frozenColsEnd ?? 0)].reduce((sum, _, c0) => sum + this.colSize(c0, 'frozenColsEnd'), 0) +
|
|
747
|
+
gap * Math.max(0, this.frozen.frozenColsEnd ?? 0 - 1);
|
|
711
748
|
}
|
|
712
749
|
|
|
713
750
|
private updateVisBlock(): void {
|
|
@@ -757,6 +794,15 @@ export class DxGrid extends LitElement {
|
|
|
757
794
|
this.templatefrozenRowsEnd = [...Array(this.frozen.frozenRowsEnd ?? 0)]
|
|
758
795
|
.map((_, r0) => `${this.rowSize(r0, 'frozenRowsEnd')}px`)
|
|
759
796
|
.join(' ');
|
|
797
|
+
|
|
798
|
+
this.frozenRowsSize =
|
|
799
|
+
[...Array(this.frozen.frozenRowsStart ?? 0)].reduce(
|
|
800
|
+
(sum, _, r0) => sum + this.rowSize(r0, 'frozenRowsStart'),
|
|
801
|
+
0,
|
|
802
|
+
) +
|
|
803
|
+
gap * Math.max(0, this.frozen.frozenRowsStart ?? 0 - 1) +
|
|
804
|
+
[...Array(this.frozen.frozenRowsEnd ?? 0)].reduce((sum, _, r0) => sum + this.rowSize(r0, 'frozenRowsEnd'), 0) +
|
|
805
|
+
gap * Math.max(0, this.frozen.frozenRowsEnd ?? 0 - 1);
|
|
760
806
|
}
|
|
761
807
|
|
|
762
808
|
private updateVis(): void {
|
|
@@ -1055,16 +1101,40 @@ export class DxGrid extends LitElement {
|
|
|
1055
1101
|
: !!(this.rows[plane]?.[index]?.resizeable ?? this.rowDefault[plane as DxGridFrozenRowsPlane]?.resizeable);
|
|
1056
1102
|
}
|
|
1057
1103
|
|
|
1104
|
+
private clampAxisSize(
|
|
1105
|
+
plane: 'grid' | DxGridFrozenPlane,
|
|
1106
|
+
axis: DxGridAxis,
|
|
1107
|
+
index: number | string,
|
|
1108
|
+
requestedSize: number,
|
|
1109
|
+
): number {
|
|
1110
|
+
const minSize =
|
|
1111
|
+
axis === 'col'
|
|
1112
|
+
? (this.columns[plane]?.[index]?.minSize ??
|
|
1113
|
+
this.columnDefault[plane as DxGridFrozenColsPlane]?.minSize ??
|
|
1114
|
+
sizeColMin)
|
|
1115
|
+
: (this.rows[plane]?.[index]?.minSize ??
|
|
1116
|
+
this.rowDefault[plane as DxGridFrozenRowsPlane]?.minSize ??
|
|
1117
|
+
sizeRowMin);
|
|
1118
|
+
const maxSize =
|
|
1119
|
+
axis === 'col'
|
|
1120
|
+
? (this.columns[plane]?.[index]?.maxSize ??
|
|
1121
|
+
this.columnDefault[plane as DxGridFrozenColsPlane]?.maxSize ??
|
|
1122
|
+
sizeColMax)
|
|
1123
|
+
: (this.rows[plane]?.[index]?.maxSize ??
|
|
1124
|
+
this.rowDefault[plane as DxGridFrozenRowsPlane]?.maxSize ??
|
|
1125
|
+
sizeRowMax);
|
|
1126
|
+
return Math.max(minSize, Math.min(maxSize, requestedSize));
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1058
1129
|
private handleAxisResizeInternal(event: DxAxisResizeInternal): void {
|
|
1059
1130
|
event.stopPropagation();
|
|
1060
1131
|
const { plane, axis, delta, size, index, state } = event;
|
|
1132
|
+
const nextSize = this.clampAxisSize(plane, axis, index, size + delta);
|
|
1061
1133
|
if (axis === 'col') {
|
|
1062
|
-
const nextSize = Math.max(sizeColMin, Math.min(sizeColMax, size + delta));
|
|
1063
1134
|
this.colSizes = { ...this.colSizes, [plane]: { ...this.colSizes[plane], [index]: nextSize } };
|
|
1064
1135
|
this.updateVisInline();
|
|
1065
1136
|
this.updateIntrinsicInlineSize();
|
|
1066
1137
|
} else {
|
|
1067
|
-
const nextSize = Math.max(sizeRowMin, Math.min(sizeRowMax, size + delta));
|
|
1068
1138
|
this.rowSizes = { ...this.colSizes, [plane]: { ...this.rowSizes[plane], [index]: nextSize } };
|
|
1069
1139
|
this.updateVisBlock();
|
|
1070
1140
|
this.updateIntrinsicBlockSize();
|
|
@@ -1165,7 +1235,7 @@ export class DxGrid extends LitElement {
|
|
|
1165
1235
|
) {
|
|
1166
1236
|
const rowPlane = resolveRowPlane(plane) as DxGridFrozenPlane;
|
|
1167
1237
|
const rows = this.frozen[rowPlane];
|
|
1168
|
-
return (rows ?? 0) > 0
|
|
1238
|
+
return (rows ?? 0) > 0 && this.limitColumns > 0
|
|
1169
1239
|
? html`<div
|
|
1170
1240
|
role="none"
|
|
1171
1241
|
class="dx-grid__plane--frozen-row"
|
|
@@ -1199,7 +1269,7 @@ export class DxGrid extends LitElement {
|
|
|
1199
1269
|
) {
|
|
1200
1270
|
const colPlane = resolveColPlane(plane) as DxGridFrozenPlane;
|
|
1201
1271
|
const cols = this.frozen[colPlane];
|
|
1202
|
-
return (cols ?? 0) > 0
|
|
1272
|
+
return (cols ?? 0) > 0 && this.limitRows > 0
|
|
1203
1273
|
? html`<div
|
|
1204
1274
|
role="none"
|
|
1205
1275
|
class="dx-grid__plane--frozen-col"
|
|
@@ -1225,6 +1295,40 @@ export class DxGrid extends LitElement {
|
|
|
1225
1295
|
: null;
|
|
1226
1296
|
}
|
|
1227
1297
|
|
|
1298
|
+
private renderMainGrid(
|
|
1299
|
+
visibleCols: number,
|
|
1300
|
+
visibleRows: number,
|
|
1301
|
+
offsetInline: number,
|
|
1302
|
+
offsetBlock: number,
|
|
1303
|
+
selection: DxGridSelectionProps,
|
|
1304
|
+
) {
|
|
1305
|
+
return this.limitRows > 0 && this.limitColumns > 0
|
|
1306
|
+
? html`<div
|
|
1307
|
+
role="grid"
|
|
1308
|
+
class="dx-grid__plane--grid"
|
|
1309
|
+
tabindex="0"
|
|
1310
|
+
data-dx-grid-plane="grid"
|
|
1311
|
+
data-dx-grid-plane-row="1"
|
|
1312
|
+
data-dx-grid-plane-col="1"
|
|
1313
|
+
>
|
|
1314
|
+
<div
|
|
1315
|
+
role="none"
|
|
1316
|
+
class="dx-grid__plane--grid__content"
|
|
1317
|
+
style="transform:translate3d(${offsetInline}px,${offsetBlock}px,0);grid-template-columns:${this
|
|
1318
|
+
.templateGridColumns};grid-template-rows:${this.templateGridRows};"
|
|
1319
|
+
>
|
|
1320
|
+
${[...Array(visibleRows)].map((_, r0) => {
|
|
1321
|
+
return [...Array(visibleCols)].map((_, c0) => {
|
|
1322
|
+
const c = c0 + this.visColMin;
|
|
1323
|
+
const r = r0 + this.visRowMin;
|
|
1324
|
+
return this.renderCell(c, r, 'grid', cellSelected(c, r, 'grid', selection), c0, r0);
|
|
1325
|
+
});
|
|
1326
|
+
})}
|
|
1327
|
+
</div>
|
|
1328
|
+
</div>`
|
|
1329
|
+
: null;
|
|
1330
|
+
}
|
|
1331
|
+
|
|
1228
1332
|
private cellReadonly(col: number, row: number, plane: DxGridPlane): boolean {
|
|
1229
1333
|
const colPlane = resolveColPlane(plane);
|
|
1230
1334
|
const rowPlane = resolveRowPlane(plane);
|
|
@@ -1242,6 +1346,23 @@ export class DxGrid extends LitElement {
|
|
|
1242
1346
|
return isReadonly(colReadOnly) || isReadonly(rowReadOnly);
|
|
1243
1347
|
}
|
|
1244
1348
|
|
|
1349
|
+
private cellFocusUnfurl(col: number, row: number, plane: DxGridPlane): boolean {
|
|
1350
|
+
const colPlane = resolveColPlane(plane);
|
|
1351
|
+
const rowPlane = resolveRowPlane(plane);
|
|
1352
|
+
|
|
1353
|
+
// Check cell-specific setting first.
|
|
1354
|
+
const cellUnfurl = this.cell(col, row, plane)?.focusUnfurl;
|
|
1355
|
+
if (cellUnfurl !== undefined) {
|
|
1356
|
+
return cellUnfurl;
|
|
1357
|
+
}
|
|
1358
|
+
|
|
1359
|
+
// Check column/row defaults.
|
|
1360
|
+
const colUnfurl = this.columns?.[colPlane]?.[col]?.focusUnfurl ?? this.columnDefault?.[colPlane]?.focusUnfurl;
|
|
1361
|
+
const rowUnfurl = this.rows?.[rowPlane]?.[row]?.focusUnfurl ?? this.rowDefault?.[rowPlane]?.focusUnfurl;
|
|
1362
|
+
|
|
1363
|
+
return colUnfurl ?? rowUnfurl ?? focusUnfurlDefault;
|
|
1364
|
+
}
|
|
1365
|
+
|
|
1245
1366
|
/**
|
|
1246
1367
|
* Determines if the cell's text content should be selectable based on its readonly value.
|
|
1247
1368
|
* @returns true if the cells text content is selectable, false otherwise.
|
|
@@ -1262,10 +1383,49 @@ export class DxGrid extends LitElement {
|
|
|
1262
1383
|
return colReadonly === 'text-select' || rowReadonly === 'text-select';
|
|
1263
1384
|
}
|
|
1264
1385
|
|
|
1386
|
+
private getOverflowingCellModifiedDeltas(
|
|
1387
|
+
event: DxGridAnnotatedPanEvent,
|
|
1388
|
+
): Pick<DxGridAnnotatedPanEvent, 'deltaX' | 'deltaY'> {
|
|
1389
|
+
if (!event.target) {
|
|
1390
|
+
return event;
|
|
1391
|
+
}
|
|
1392
|
+
const element = event.target as HTMLElement;
|
|
1393
|
+
const activeCell = element.closest('[data-dx-active]');
|
|
1394
|
+
const contentEl = element.closest('.dx-grid__cell__content');
|
|
1395
|
+
|
|
1396
|
+
if (!activeCell || !contentEl || !document.activeElement?.contains(element)) {
|
|
1397
|
+
return event;
|
|
1398
|
+
}
|
|
1399
|
+
|
|
1400
|
+
// Commented-out code will let the event delta through unmodified if the cell can scroll but is scrolled to the end
|
|
1401
|
+
// in the same direction as the wheel event, a.k.a. “overscroll”; this is probably undesirable, though.
|
|
1402
|
+
|
|
1403
|
+
const { scrollWidth, clientWidth, scrollHeight, clientHeight /*, scrollLeft, scrollTop */ } = contentEl;
|
|
1404
|
+
|
|
1405
|
+
if (scrollWidth <= clientWidth && scrollHeight <= clientHeight) {
|
|
1406
|
+
return event;
|
|
1407
|
+
}
|
|
1408
|
+
|
|
1409
|
+
const deltaX =
|
|
1410
|
+
scrollWidth > clientWidth /* &&
|
|
1411
|
+
((event.deltaX < 0 && scrollLeft > 0) || (event.deltaX > 0 && scrollLeft < scrollWidth - clientWidth)) */
|
|
1412
|
+
? 0
|
|
1413
|
+
: event.deltaX;
|
|
1414
|
+
|
|
1415
|
+
const deltaY =
|
|
1416
|
+
scrollHeight > clientHeight /* &&
|
|
1417
|
+
((event.deltaY < 0 && scrollTop > 0) || (event.deltaY > 0 && scrollTop < scrollHeight - clientHeight)) */
|
|
1418
|
+
? 0
|
|
1419
|
+
: event.deltaY;
|
|
1420
|
+
|
|
1421
|
+
return { deltaX, deltaY };
|
|
1422
|
+
}
|
|
1423
|
+
|
|
1265
1424
|
private renderCell(col: number, row: number, plane: DxGridPlane, selected?: boolean, visCol = col, visRow = row) {
|
|
1266
1425
|
const cell = this.cell(col, row, plane);
|
|
1267
1426
|
const active = this.cellActive(col, row, plane);
|
|
1268
1427
|
const readonly = this.cellReadonly(col, row, plane);
|
|
1428
|
+
const focusUnfurl = this.cellFocusUnfurl(col, row, plane);
|
|
1269
1429
|
const textSelectable = this.cellTextSelectable(col, row, plane);
|
|
1270
1430
|
const resizeIndex = cell?.resizeHandle ? (cell.resizeHandle === 'col' ? col : row) : undefined;
|
|
1271
1431
|
const resizePlane = cell?.resizeHandle ? resolveFrozenPlane(cell.resizeHandle, plane) : undefined;
|
|
@@ -1277,6 +1437,7 @@ export class DxGrid extends LitElement {
|
|
|
1277
1437
|
aria-readonly=${readonly ? 'true' : nothing}
|
|
1278
1438
|
class=${cell?.className ?? nothing}
|
|
1279
1439
|
data-refs=${cell?.dataRefs ?? nothing}
|
|
1440
|
+
data-focus-unfurl=${focusUnfurl ? nothing : 'false'}
|
|
1280
1441
|
?data-dx-active=${active}
|
|
1281
1442
|
data-text-selectable=${textSelectable ? 'true' : 'false'}
|
|
1282
1443
|
data-dx-grid-action="cell"
|
|
@@ -1284,9 +1445,8 @@ export class DxGrid extends LitElement {
|
|
|
1284
1445
|
aria-rowindex=${row}
|
|
1285
1446
|
style="grid-column:${visCol + 1};grid-row:${visRow + 1}"
|
|
1286
1447
|
>
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
: accessory}${cell?.resizeHandle &&
|
|
1448
|
+
<div role="none" class="dx-grid__cell__content">${cell?.value}${accessory}</div>
|
|
1449
|
+
${cell?.resizeHandle &&
|
|
1290
1450
|
this.mode === 'browse' &&
|
|
1291
1451
|
this.axisResizeable(resizePlane!, cell.resizeHandle, resizeIndex!)
|
|
1292
1452
|
? html`<dx-grid-axis-resize-handle
|
|
@@ -1320,13 +1480,24 @@ export class DxGrid extends LitElement {
|
|
|
1320
1480
|
<div
|
|
1321
1481
|
role="none"
|
|
1322
1482
|
class="dx-grid"
|
|
1483
|
+
data-arrow-keys="all"
|
|
1323
1484
|
style=${styleMap({
|
|
1324
|
-
'grid-template-columns':
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1485
|
+
'grid-template-columns': [
|
|
1486
|
+
this.templatefrozenColsStart ? 'min-content' : false,
|
|
1487
|
+
this.limitColumns > 0 &&
|
|
1488
|
+
`minmax(0, ${Number.isFinite(this.limitColumns) ? `${Math.max(0, this.intrinsicInlineSize)}px` : '1fr'})`,
|
|
1489
|
+
this.templatefrozenColsEnd ? 'min-content' : false,
|
|
1490
|
+
]
|
|
1491
|
+
.filter(Boolean)
|
|
1492
|
+
.join(' '),
|
|
1493
|
+
'grid-template-rows': [
|
|
1494
|
+
this.templatefrozenRowsStart ? 'min-content' : false,
|
|
1495
|
+
this.limitRows > 0 &&
|
|
1496
|
+
`minmax(0, ${Number.isFinite(this.limitRows) ? `${Math.max(0, this.intrinsicBlockSize)}px` : '1fr'})`,
|
|
1497
|
+
this.templatefrozenRowsEnd ? ' min-content' : false,
|
|
1498
|
+
]
|
|
1499
|
+
.filter(Boolean)
|
|
1500
|
+
.join(' '),
|
|
1330
1501
|
'--dx-grid-content-inline-size': Number.isFinite(this.limitColumns)
|
|
1331
1502
|
? `${Math.max(0, this.totalIntrinsicInlineSize)}px`
|
|
1332
1503
|
: 'max-content',
|
|
@@ -1350,30 +1521,7 @@ export class DxGrid extends LitElement {
|
|
|
1350
1521
|
offsetBlock,
|
|
1351
1522
|
selection,
|
|
1352
1523
|
)}
|
|
1353
|
-
|
|
1354
|
-
role="grid"
|
|
1355
|
-
class="dx-grid__plane--grid"
|
|
1356
|
-
tabindex="0"
|
|
1357
|
-
data-dx-grid-plane="grid"
|
|
1358
|
-
data-dx-grid-plane-row="1"
|
|
1359
|
-
data-dx-grid-plane-col="1"
|
|
1360
|
-
${ref(this.viewportRef)}
|
|
1361
|
-
>
|
|
1362
|
-
<div
|
|
1363
|
-
role="none"
|
|
1364
|
-
class="dx-grid__plane--grid__content"
|
|
1365
|
-
style="transform:translate3d(${offsetInline}px,${offsetBlock}px,0);grid-template-columns:${this
|
|
1366
|
-
.templateGridColumns};grid-template-rows:${this.templateGridRows};"
|
|
1367
|
-
>
|
|
1368
|
-
${[...Array(visibleRows)].map((_, r0) => {
|
|
1369
|
-
return [...Array(visibleCols)].map((_, c0) => {
|
|
1370
|
-
const c = c0 + this.visColMin;
|
|
1371
|
-
const r = r0 + this.visRowMin;
|
|
1372
|
-
return this.renderCell(c, r, 'grid', cellSelected(c, r, 'grid', selection), c0, r0);
|
|
1373
|
-
});
|
|
1374
|
-
})}
|
|
1375
|
-
</div>
|
|
1376
|
-
</div>
|
|
1524
|
+
${this.renderMainGrid(visibleCols, visibleRows, offsetInline, offsetBlock, selection)}
|
|
1377
1525
|
${this.renderFrozenColumns('frozenColsEnd', visibleRows, offsetBlock, selection)}${this.renderFixed(
|
|
1378
1526
|
'fixedEndStart',
|
|
1379
1527
|
selection,
|
|
@@ -1387,37 +1535,19 @@ export class DxGrid extends LitElement {
|
|
|
1387
1535
|
private updateIntrinsicInlineSize(): void {
|
|
1388
1536
|
this.intrinsicInlineSize = Number.isFinite(this.limitColumns)
|
|
1389
1537
|
? [...Array(this.limitColumns)].reduce((acc, _, c0) => acc + this.colSize(c0, 'grid'), 0) +
|
|
1390
|
-
gap * (this.limitColumns - 1)
|
|
1538
|
+
gap * Math.max(0, this.limitColumns - 1)
|
|
1391
1539
|
: Infinity;
|
|
1392
1540
|
this.totalIntrinsicInlineSize =
|
|
1393
|
-
this.intrinsicInlineSize +
|
|
1394
|
-
(Number.isFinite(this.frozen.frozenColsStart)
|
|
1395
|
-
? [...Array(this.frozen.frozenColsStart)].reduce(
|
|
1396
|
-
(acc, _, c0) => acc + gap + this.colSize(c0, 'frozenColsStart'),
|
|
1397
|
-
0,
|
|
1398
|
-
)
|
|
1399
|
-
: 0) +
|
|
1400
|
-
(Number.isFinite(this.frozen.frozenColsEnd)
|
|
1401
|
-
? [...Array(this.frozen.frozenColsEnd)].reduce((acc, _, c0) => acc + gap + this.colSize(c0, 'frozenColsEnd'), 0)
|
|
1402
|
-
: 0);
|
|
1541
|
+
this.limitColumns > 0 ? this.intrinsicInlineSize + this.frozenColsSize : this.frozenColsSize - gap;
|
|
1403
1542
|
}
|
|
1404
1543
|
|
|
1405
1544
|
private updateIntrinsicBlockSize(): void {
|
|
1406
1545
|
this.intrinsicBlockSize = Number.isFinite(this.limitRows)
|
|
1407
1546
|
? [...Array(this.limitRows)].reduce((acc, _, r0) => acc + this.rowSize(r0, 'grid'), 0) +
|
|
1408
|
-
gap * (this.limitRows - 1)
|
|
1547
|
+
gap * Math.max(0, this.limitRows - 1)
|
|
1409
1548
|
: Infinity;
|
|
1410
1549
|
this.totalIntrinsicBlockSize =
|
|
1411
|
-
this.intrinsicBlockSize +
|
|
1412
|
-
(Number.isFinite(this.frozen.frozenRowsStart)
|
|
1413
|
-
? [...Array(this.frozen.frozenRowsStart)].reduce(
|
|
1414
|
-
(acc, _, r0) => acc + gap + this.rowSize(r0, 'frozenRowsStart'),
|
|
1415
|
-
0,
|
|
1416
|
-
)
|
|
1417
|
-
: 0) +
|
|
1418
|
-
(Number.isFinite(this.frozen.frozenRowsEnd)
|
|
1419
|
-
? [...Array(this.frozen.frozenRowsEnd)].reduce((acc, _, r0) => acc + gap + this.rowSize(r0, 'frozenRowsEnd'), 0)
|
|
1420
|
-
: 0);
|
|
1550
|
+
this.limitRows > 0 ? this.intrinsicBlockSize + this.frozenRowsSize : this.frozenRowsSize - gap;
|
|
1421
1551
|
}
|
|
1422
1552
|
|
|
1423
1553
|
private updateIntrinsicSizes(): void {
|
|
@@ -1465,7 +1595,7 @@ export class DxGrid extends LitElement {
|
|
|
1465
1595
|
if (this.getCells) {
|
|
1466
1596
|
this.updateCells(true);
|
|
1467
1597
|
}
|
|
1468
|
-
this.observer.observe(this.
|
|
1598
|
+
this.observer.observe(this.gridRef.value!);
|
|
1469
1599
|
this.computeColSizes();
|
|
1470
1600
|
this.computeRowSizes();
|
|
1471
1601
|
this.updateIntrinsicSizes();
|
|
@@ -1490,6 +1620,13 @@ export class DxGrid extends LitElement {
|
|
|
1490
1620
|
this.updateVisInline();
|
|
1491
1621
|
}
|
|
1492
1622
|
|
|
1623
|
+
if (changedProperties.has('frozen')) {
|
|
1624
|
+
this.updateIntrinsicBlockSize();
|
|
1625
|
+
this.updateIntrinsicInlineSize();
|
|
1626
|
+
this.updateVisBlock();
|
|
1627
|
+
this.updateVisInline();
|
|
1628
|
+
}
|
|
1629
|
+
|
|
1493
1630
|
if (
|
|
1494
1631
|
this.getCells &&
|
|
1495
1632
|
(changedProperties.has('initialCells') ||
|
|
@@ -1500,7 +1637,8 @@ export class DxGrid extends LitElement {
|
|
|
1500
1637
|
changedProperties.has('columns') ||
|
|
1501
1638
|
changedProperties.has('rows') ||
|
|
1502
1639
|
changedProperties.has('limitColumns') ||
|
|
1503
|
-
changedProperties.has('limitRows')
|
|
1640
|
+
changedProperties.has('limitRows') ||
|
|
1641
|
+
changedProperties.has('frozen'))
|
|
1504
1642
|
) {
|
|
1505
1643
|
this.updateCells(true);
|
|
1506
1644
|
}
|
|
@@ -1520,8 +1658,9 @@ export class DxGrid extends LitElement {
|
|
|
1520
1658
|
}
|
|
1521
1659
|
}
|
|
1522
1660
|
|
|
1523
|
-
public updateIfWithinBounds({ col, row }: { col: number; row: number }): boolean {
|
|
1661
|
+
public updateIfWithinBounds({ col, row }: { col: number; row: number }, includeFixed?: boolean): boolean {
|
|
1524
1662
|
if (col >= this.visColMin && col <= this.visColMax && row >= this.visRowMin && row <= this.visRowMax) {
|
|
1663
|
+
this.updateCells(includeFixed);
|
|
1525
1664
|
this.requestUpdate();
|
|
1526
1665
|
return true;
|
|
1527
1666
|
}
|
|
@@ -1530,8 +1669,8 @@ export class DxGrid extends LitElement {
|
|
|
1530
1669
|
|
|
1531
1670
|
override disconnectedCallback(): void {
|
|
1532
1671
|
super.disconnectedCallback();
|
|
1533
|
-
if (this.
|
|
1534
|
-
this.observer.unobserve(this.
|
|
1672
|
+
if (this.gridRef.value) {
|
|
1673
|
+
this.observer.unobserve(this.gridRef.value);
|
|
1535
1674
|
}
|
|
1536
1675
|
document.defaultView?.removeEventListener('wheel', this.handleTopLevelWheel);
|
|
1537
1676
|
}
|
|
@@ -1549,6 +1688,7 @@ export {
|
|
|
1549
1688
|
parseCellIndex,
|
|
1550
1689
|
toPlaneCellIndex,
|
|
1551
1690
|
cellQuery,
|
|
1691
|
+
accessoryHandlesPointerdownAttrs,
|
|
1552
1692
|
} from './util';
|
|
1553
1693
|
|
|
1554
1694
|
export const commentedClassName = 'dx-grid__cell--commented';
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
// Copyright 2021 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { expect, test
|
|
5
|
+
import { type Page, expect, test } from '@playwright/test';
|
|
6
6
|
|
|
7
7
|
import { setupPage, storybookUrl } from '@dxos/test-utils/playwright';
|
|
8
8
|
|
|
9
|
-
import { DxGridManager } from '
|
|
10
|
-
import { type DxGridCellsSelect } from '
|
|
11
|
-
import { toPlaneCellIndex } from '
|
|
9
|
+
import { DxGridManager } from '../testing';
|
|
10
|
+
import { type DxGridCellsSelect } from '../types';
|
|
11
|
+
import { toPlaneCellIndex } from '../util';
|
|
12
12
|
|
|
13
13
|
const gridPlaneCellSize = 31;
|
|
14
14
|
const gap = 1;
|
|
@@ -21,7 +21,7 @@ test.describe('dx-grid', () => {
|
|
|
21
21
|
|
|
22
22
|
test.beforeEach(async ({ browser }) => {
|
|
23
23
|
const setup = await setupPage(browser, {
|
|
24
|
-
url: storybookUrl('dx-grid--spec'),
|
|
24
|
+
url: storybookUrl('dx-grid--spec', 9002),
|
|
25
25
|
viewportSize: {
|
|
26
26
|
width: (gridPlaneCellSize + gap) * (nCols + 1.5),
|
|
27
27
|
height: (gridPlaneCellSize + gap) * (nRows + 1.5),
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2023 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { defineConfig } from '@playwright/test';
|
|
6
|
+
|
|
7
|
+
import { e2ePreset } from '@dxos/test-utils/playwright';
|
|
8
|
+
|
|
9
|
+
export default defineConfig({
|
|
10
|
+
...e2ePreset(import.meta.dirname),
|
|
11
|
+
// TODO(wittjosiah): Avoid hard-coding ports.
|
|
12
|
+
webServer: {
|
|
13
|
+
command: 'moon run lit-storybook:serve-e2e -- --port=9002',
|
|
14
|
+
port: 9002,
|
|
15
|
+
reuseExistingServer: false,
|
|
16
|
+
},
|
|
17
|
+
});
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { type Locator, type Page, expect } from '@playwright/test';
|
|
6
6
|
|
|
7
|
-
import type { DxGridPlanePosition } from '
|
|
7
|
+
import type { DxGridPlanePosition } from '../types';
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Test helper for managing dx-grid interactions and assertions in Playwright tests.
|
package/src/testing/index.ts
CHANGED
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>>;
|