apex-grid 3.6.0 → 4.0.0-beta.2
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/CHANGELOG.md +301 -0
- package/LICENSE.md +2 -1
- package/README.md +117 -18
- package/components/cell.d.ts +13 -1
- package/components/cell.js +28 -13
- package/components/cell.js.map +1 -1
- package/components/grid.d.ts +175 -28
- package/components/grid.js +183 -63
- package/components/grid.js.map +1 -1
- package/components/header-row.d.ts +0 -6
- package/components/header-row.js +1 -19
- package/components/header-row.js.map +1 -1
- package/components/header.js +39 -2
- package/components/header.js.map +1 -1
- package/components/paginator.d.ts +20 -5
- package/components/paginator.js +54 -17
- package/components/paginator.js.map +1 -1
- package/components/row.js +149 -40
- package/components/row.js.map +1 -1
- package/components/toolbar.d.ts +5 -1
- package/components/toolbar.js +4 -1
- package/components/toolbar.js.map +1 -1
- package/components/virtualize-rows.d.ts +38 -0
- package/components/virtualize-rows.js +286 -0
- package/components/virtualize-rows.js.map +1 -0
- package/components/virtualizer.d.ts +71 -1
- package/components/virtualizer.js +105 -29
- package/components/virtualizer.js.map +1 -1
- package/controllers/dom.d.ts +10 -3
- package/controllers/dom.js +5 -5
- package/controllers/dom.js.map +1 -1
- package/controllers/navigation.d.ts +63 -0
- package/controllers/navigation.js +295 -21
- package/controllers/navigation.js.map +1 -1
- package/controllers/pagination.d.ts +7 -6
- package/controllers/pagination.js +27 -28
- package/controllers/pagination.js.map +1 -1
- package/controllers/row-pin.d.ts +6 -0
- package/controllers/row-pin.js +8 -2
- package/controllers/row-pin.js.map +1 -1
- package/controllers/row-reorder.d.ts +12 -4
- package/controllers/row-reorder.js +20 -6
- package/controllers/row-reorder.js.map +1 -1
- package/controllers/selection.d.ts +32 -10
- package/controllers/selection.js +33 -10
- package/controllers/selection.js.map +1 -1
- package/controllers/sort.js +2 -3
- package/controllers/sort.js.map +1 -1
- package/controllers/state.d.ts +18 -5
- package/controllers/state.js +53 -46
- package/controllers/state.js.map +1 -1
- package/custom-elements.json +1762 -339
- package/docs/assets/hierarchy.js +1 -1
- package/docs/assets/search.js +1 -1
- package/docs/classes/ApexGrid.html +166 -66
- package/docs/classes/ApexGridPaginator.html +39 -8
- package/docs/classes/ApexGridToolbar.html +9 -5
- package/docs/functions/localize.html +2 -2
- package/docs/hierarchy.html +1 -1
- package/docs/index.html +123 -20
- package/docs/interfaces/ApexPageChangedEvent.html +3 -1
- package/docs/interfaces/BaseApexCellContext.html +18 -5
- package/docs/interfaces/BaseApexEditorContext.html +20 -5
- package/docs/interfaces/BaseFilterExpression.html +1 -1
- package/docs/interfaces/CSVExportOptions.html +1 -1
- package/docs/interfaces/DataPipelineConfiguration.html +4 -9
- package/docs/interfaces/ExportOptions.html +1 -1
- package/docs/interfaces/GridSelectionConfiguration.html +19 -4
- package/docs/interfaces/PaginationConfiguration.html +11 -4
- package/docs/interfaces/PaginationState.html +4 -2
- package/docs/media/_token-values.scss +42 -16
- package/docs/media/package.json +12 -4
- package/docs/types/DataPipelineParams.html +2 -2
- package/docs/types/PaginationMode.html +5 -4
- package/docs/variables/EN_LOCALE.html +2 -2
- package/i18n/en.d.ts +2 -0
- package/i18n/en.js +2 -0
- package/i18n/en.js.map +1 -1
- package/i18n/es.js +2 -0
- package/i18n/es.js.map +1 -1
- package/ignite-ui.d.ts +1 -0
- package/ignite-ui.js +4 -0
- package/ignite-ui.js.map +1 -0
- package/internal/column-types.d.ts +11 -1
- package/internal/column-types.js +8 -6
- package/internal/column-types.js.map +1 -1
- package/internal/design-system.d.ts +32 -0
- package/internal/design-system.js +66 -0
- package/internal/design-system.js.map +1 -0
- package/internal/export.d.ts +6 -0
- package/internal/export.js +4 -0
- package/internal/export.js.map +1 -1
- package/internal/feature-module.d.ts +7 -0
- package/internal/feature-module.js.map +1 -1
- package/internal/flip.d.ts +28 -16
- package/internal/flip.js +42 -10
- package/internal/flip.js.map +1 -1
- package/internal/icons.d.ts +2 -16
- package/internal/icons.js +0 -8
- package/internal/icons.js.map +1 -1
- package/internal/ignite-ui.d.ts +10 -0
- package/internal/ignite-ui.js +118 -0
- package/internal/ignite-ui.js.map +1 -0
- package/internal/index.d.ts +4 -2
- package/internal/index.js +3 -2
- package/internal/index.js.map +1 -1
- package/internal/types.d.ts +75 -19
- package/internal/types.js.map +1 -1
- package/operations/filter/types.d.ts +1 -1
- package/operations/filter/types.js.map +1 -1
- package/package.json +7 -2
- package/styles/_token-blocks.css.d.ts +1 -0
- package/styles/_token-blocks.css.js +3 -0
- package/styles/_token-blocks.css.js.map +1 -0
- package/styles/_tokens.css.js +1 -1
- package/styles/_tokens.css.js.map +1 -1
- package/styles/body-cell/body-cell.css.js +1 -1
- package/styles/body-cell/body-cell.css.js.map +1 -1
- package/styles/body-cell/cell-renderers.css.js +1 -1
- package/styles/body-cell/cell-renderers.css.js.map +1 -1
- package/styles/body-row/body-row.css.js +1 -1
- package/styles/body-row/body-row.css.js.map +1 -1
- package/styles/document-tokens.css.js +1 -1
- package/styles/document-tokens.css.js.map +1 -1
- package/styles/grid/_grid.base.css.js +1 -1
- package/styles/grid/_grid.base.css.js.map +1 -1
- package/styles/grid/grid.css.js +1 -1
- package/styles/grid/grid.css.js.map +1 -1
- package/styles/group-header-row/group-header-row.css.js +1 -1
- package/styles/group-header-row/group-header-row.css.js.map +1 -1
- package/styles/header-cell/header-cell.css.js +1 -1
- package/styles/header-cell/header-cell.css.js.map +1 -1
- package/styles/header-row/header-row.base.css.js +1 -1
- package/styles/header-row/header-row.base.css.js.map +1 -1
- package/styles/ignite-ui/ignite-ui-dark.css.d.ts +1 -0
- package/styles/ignite-ui/ignite-ui-dark.css.js +3 -0
- package/styles/ignite-ui/ignite-ui-dark.css.js.map +1 -0
- package/styles/ignite-ui/ignite-ui-document.css.d.ts +1 -0
- package/styles/ignite-ui/ignite-ui-document.css.js +3 -0
- package/styles/ignite-ui/ignite-ui-document.css.js.map +1 -0
- package/styles/ignite-ui/ignite-ui.css.d.ts +1 -0
- package/styles/ignite-ui/ignite-ui.css.js +3 -0
- package/styles/ignite-ui/ignite-ui.css.js.map +1 -0
- package/styles/paginator/paginator.css.js +1 -1
- package/styles/paginator/paginator.css.js.map +1 -1
- package/styles/toolbar/toolbar.css.js +1 -1
- package/styles/toolbar/toolbar.css.js.map +1 -1
- package/tokens.css +14 -15
- package/operations/pagination.d.ts +0 -19
- package/operations/pagination.js +0 -12
- package/operations/pagination.js.map +0 -1
|
@@ -1,9 +1,33 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
1
7
|
import { LitVirtualizer } from '@lit-labs/virtualizer/LitVirtualizer.js';
|
|
8
|
+
import { html } from 'lit';
|
|
9
|
+
import { property } from 'lit/decorators.js';
|
|
2
10
|
import { registerComponent } from '../internal/register.js';
|
|
3
11
|
import { GRID_BODY } from '../internal/tags.js';
|
|
12
|
+
import { virtualizedRows, virtualizeRows } from './virtualize-rows.js';
|
|
4
13
|
const SIZER_ATTRIBUTE = 'virtualizer-sizer';
|
|
5
14
|
const MAX_RECOVERY_ATTEMPTS = 3;
|
|
15
|
+
let loopNoticeQuieted = false;
|
|
16
|
+
export function quietResizeObserverLoopNotice() {
|
|
17
|
+
if (loopNoticeQuieted)
|
|
18
|
+
return;
|
|
19
|
+
loopNoticeQuieted = true;
|
|
20
|
+
window.addEventListener('error', (event) => {
|
|
21
|
+
if (String(event.message).includes('ResizeObserver loop')) {
|
|
22
|
+
event.preventDefault();
|
|
23
|
+
event.stopImmediatePropagation();
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
}
|
|
6
27
|
const SETTLE_TIMEOUT_MS = 250;
|
|
28
|
+
const MAX_REVEAL_ATTEMPTS = 4;
|
|
29
|
+
const SPIKE_SLOTS = 128;
|
|
30
|
+
const spikeKey = (_item, index) => index % SPIKE_SLOTS;
|
|
7
31
|
export function revealWithin(scroller, el, { insets, ...options }) {
|
|
8
32
|
const style = insets && scroller?.style;
|
|
9
33
|
const previous = style ? style.scrollPadding : '';
|
|
@@ -16,27 +40,55 @@ export function revealWithin(scroller, el, { insets, ...options }) {
|
|
|
16
40
|
style.scrollPadding = previous;
|
|
17
41
|
}
|
|
18
42
|
export default class ApexVirtualizer extends LitVirtualizer {
|
|
43
|
+
static { this.rowKeying = 'item'; }
|
|
19
44
|
#viewportObserver;
|
|
20
45
|
#visibleHeight;
|
|
21
46
|
#pendingCheck;
|
|
22
47
|
#recoveryAttempts;
|
|
23
48
|
#first;
|
|
24
49
|
#last;
|
|
50
|
+
#reveal;
|
|
25
51
|
constructor() {
|
|
26
52
|
super();
|
|
53
|
+
this.rowMode = 'item';
|
|
27
54
|
this.#viewportObserver = null;
|
|
28
55
|
this.#visibleHeight = 0;
|
|
29
56
|
this.#pendingCheck = 0;
|
|
30
57
|
this.#recoveryAttempts = 0;
|
|
31
58
|
this.#first = -1;
|
|
32
59
|
this.#last = -1;
|
|
60
|
+
this.#reveal = 0;
|
|
61
|
+
this.#revealing = Promise.resolve();
|
|
33
62
|
this.scroller = false;
|
|
63
|
+
if (ApexVirtualizer.rowKeying === 'spike')
|
|
64
|
+
this.keyFunction = spikeKey;
|
|
34
65
|
this.addEventListener('rangeChanged', (event) => {
|
|
35
66
|
const { first, last } = event;
|
|
36
67
|
this.#first = first;
|
|
37
68
|
this.#last = last;
|
|
38
69
|
});
|
|
39
70
|
}
|
|
71
|
+
render() {
|
|
72
|
+
const { items, renderItem, keyFunction, layout, scroller, rowMode: mode } = this;
|
|
73
|
+
return html `${virtualizeRows({ items, renderItem, keyFunction, layout, scroller, mode })}`;
|
|
74
|
+
}
|
|
75
|
+
dispatchEvent(event) {
|
|
76
|
+
const rows = event.type === 'rangeChanged' ? virtualizedRows(this) : undefined;
|
|
77
|
+
return rows ? rows.holdRender(() => super.dispatchEvent(event)) : super.dispatchEvent(event);
|
|
78
|
+
}
|
|
79
|
+
get layoutComplete() {
|
|
80
|
+
const promise = super.layoutComplete;
|
|
81
|
+
if (promise)
|
|
82
|
+
virtualizedRows(this)?.armLayoutComplete(this.isUpdatePending);
|
|
83
|
+
return promise;
|
|
84
|
+
}
|
|
85
|
+
async rendered() {
|
|
86
|
+
if (this.isUpdatePending)
|
|
87
|
+
await this.updateComplete;
|
|
88
|
+
if (!this.isConnected)
|
|
89
|
+
return;
|
|
90
|
+
await virtualizedRows(this)?.rendered();
|
|
91
|
+
}
|
|
40
92
|
settled() {
|
|
41
93
|
const layout = this.layoutComplete;
|
|
42
94
|
const timeout = new Promise((resolve) => setTimeout(resolve, SETTLE_TIMEOUT_MS));
|
|
@@ -51,11 +103,12 @@ export default class ApexVirtualizer extends LitVirtualizer {
|
|
|
51
103
|
return undefined;
|
|
52
104
|
return {
|
|
53
105
|
scrollIntoView: (options = {}) => {
|
|
106
|
+
const reveal = ++this.#reveal;
|
|
54
107
|
const row = this.#renderedChild(target);
|
|
55
108
|
if (row)
|
|
56
109
|
revealWithin(this.#scroller(), row, options);
|
|
57
110
|
else
|
|
58
|
-
this.#scrollToUnrendered(target, options);
|
|
111
|
+
this.#scrollToUnrendered(target, options, reveal);
|
|
59
112
|
},
|
|
60
113
|
};
|
|
61
114
|
}
|
|
@@ -83,49 +136,69 @@ export default class ApexVirtualizer extends LitVirtualizer {
|
|
|
83
136
|
}
|
|
84
137
|
return null;
|
|
85
138
|
}
|
|
86
|
-
#
|
|
139
|
+
#revealing;
|
|
140
|
+
revealed() {
|
|
141
|
+
return this.#revealing;
|
|
142
|
+
}
|
|
143
|
+
#scrollToUnrendered(index, options, reveal) {
|
|
87
144
|
const scroller = this.#scroller();
|
|
88
|
-
|
|
89
|
-
if (!scroller || !count)
|
|
145
|
+
if (!scroller || !this.items.length)
|
|
90
146
|
return;
|
|
91
|
-
|
|
147
|
+
this.#revealing = this.#chase(scroller, index, options, reveal);
|
|
148
|
+
}
|
|
149
|
+
async #chase(scroller, index, options, reveal) {
|
|
150
|
+
for (let attempt = 0; attempt < MAX_REVEAL_ATTEMPTS; attempt++) {
|
|
151
|
+
const top = this.#estimateScroll(scroller, index, options);
|
|
152
|
+
if (top === null)
|
|
153
|
+
return;
|
|
154
|
+
scroller.scrollTo({ top, behavior: options.behavior });
|
|
155
|
+
await this.settled();
|
|
156
|
+
if (reveal !== this.#reveal)
|
|
157
|
+
return;
|
|
158
|
+
const row = this.#renderedChild(index);
|
|
159
|
+
if (row) {
|
|
160
|
+
revealWithin(scroller, row, options);
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
#estimateScroll(scroller, index, options) {
|
|
166
|
+
const size = this.offsetHeight / this.items.length;
|
|
92
167
|
if (!size)
|
|
93
|
-
return;
|
|
168
|
+
return null;
|
|
94
169
|
const padStart = options.insets?.top ?? 0;
|
|
95
170
|
const padEnd = options.insets?.bottom ?? 0;
|
|
96
171
|
const viewport = scroller.clientHeight - padStart - padEnd;
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
172
|
+
const base = scroller.getBoundingClientRect().top + scroller.clientTop - scroller.scrollTop;
|
|
173
|
+
const offsetOf = (el) => el.getBoundingClientRect().top - base;
|
|
174
|
+
const after = index > this.#last ? this.#renderedChild(this.#last) : null;
|
|
175
|
+
const before = index < this.#first ? this.#renderedChild(this.#first) : null;
|
|
176
|
+
let start;
|
|
177
|
+
if (after) {
|
|
178
|
+
start = offsetOf(after) + after.offsetHeight + (index - this.#last - 1) * size;
|
|
179
|
+
}
|
|
180
|
+
else if (before) {
|
|
181
|
+
start = offsetOf(before) - (this.#first - index) * size;
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
start = offsetOf(this) + index * size;
|
|
185
|
+
}
|
|
102
186
|
const end = start + size;
|
|
103
187
|
const current = scroller.scrollTop;
|
|
104
|
-
let top;
|
|
105
188
|
switch (options.block ?? 'start') {
|
|
106
189
|
case 'start':
|
|
107
|
-
|
|
108
|
-
break;
|
|
190
|
+
return start - padStart;
|
|
109
191
|
case 'end':
|
|
110
|
-
|
|
111
|
-
break;
|
|
192
|
+
return end - padStart - viewport;
|
|
112
193
|
case 'center':
|
|
113
|
-
|
|
114
|
-
break;
|
|
194
|
+
return (start + end) / 2 - padStart - viewport / 2;
|
|
115
195
|
default:
|
|
116
196
|
if (start < current + padStart)
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
return;
|
|
197
|
+
return start - padStart;
|
|
198
|
+
if (end > current + padStart + viewport)
|
|
199
|
+
return end - padStart - viewport;
|
|
200
|
+
return null;
|
|
122
201
|
}
|
|
123
|
-
scroller.scrollTo({ top, behavior: options.behavior });
|
|
124
|
-
void this.settled().then(() => {
|
|
125
|
-
const row = this.#renderedChild(index);
|
|
126
|
-
if (row)
|
|
127
|
-
revealWithin(scroller, row, options);
|
|
128
|
-
});
|
|
129
202
|
}
|
|
130
203
|
static get tagName() {
|
|
131
204
|
return GRID_BODY;
|
|
@@ -199,4 +272,7 @@ export default class ApexVirtualizer extends LitVirtualizer {
|
|
|
199
272
|
return false;
|
|
200
273
|
}
|
|
201
274
|
}
|
|
275
|
+
__decorate([
|
|
276
|
+
property({ attribute: false })
|
|
277
|
+
], ApexVirtualizer.prototype, "rowMode", void 0);
|
|
202
278
|
//# sourceMappingURL=virtualizer.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"virtualizer.js","sourceRoot":"","sources":["../../src/components/virtualizer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAOhD,MAAM,eAAe,GAAG,mBAAmB,CAAC;AAO5C,MAAM,qBAAqB,GAAG,CAAC,CAAC;AAchC,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAS9B,MAAM,UAAU,YAAY,CAC1B,QAA4B,EAC5B,EAAW,EACX,EAAE,MAAM,EAAE,GAAG,OAAO,EAAiB;IAErC,MAAM,KAAK,GAAG,MAAM,IAAI,QAAQ,EAAE,KAAK,CAAC;IACxC,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC;IAClD,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC;QAC5C,KAAK,CAAC,aAAa,GAAG,GAAG,GAAG,MAAM,KAAK,MAAM,MAAM,MAAM,IAAI,IAAI,CAAC;IACpE,CAAC;IACD,EAAE,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;IAC3B,IAAI,KAAK;QAAE,KAAK,CAAC,aAAa,GAAG,QAAQ,CAAC;AAC5C,CAAC;AAED,MAAM,CAAC,OAAO,OAAO,eAAgB,SAAQ,cAAc;IAMzD,iBAAiB,CAAqC;IAOtD,cAAc,CAAK;IAEnB,aAAa,CAAK;IAElB,iBAAiB,CAAK;IAGtB,MAAM,CAAM;IACZ,KAAK,CAAM;IAEX;QACE,KAAK,EAAE,CAAC;QAlBV,sBAAiB,GAAgC,IAAI,CAAC;QAOtD,mBAAc,GAAG,CAAC,CAAC;QAEnB,kBAAa,GAAG,CAAC,CAAC;QAElB,sBAAiB,GAAG,CAAC,CAAC;QAGtB,WAAM,GAAG,CAAC,CAAC,CAAC;QACZ,UAAK,GAAG,CAAC,CAAC,CAAC;QAuIK,aAAQ,GAAG,KAAK,CAAC;QAjI/B,IAAI,CAAC,gBAAgB,CAAC,cAAc,EAAE,CAAC,KAAK,EAAE,EAAE;YAC9C,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,KAAgD,CAAC;YACzE,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;YACpB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QACpB,CAAC,CAAC,CAAC;IACL,CAAC;IAMM,OAAO;QACZ,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc,CAAC;QACnC,MAAM,OAAO,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAAC,CAAC;QACvF,OAAO,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IACnF,CAAC;IAGM,UAAU,CAAC,KAAa;QAC7B,OAAO,KAAK,IAAI,CAAC,IAAI,KAAK,IAAI,IAAI,CAAC,MAAM,IAAI,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC;IACnE,CAAC;IAYe,OAAO,CACrB,KAAa;QAEb,MAAM,MAAM,GAAG,KAAK,KAAK,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;QAClF,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;YAAE,OAAO,SAAS,CAAC;QAC7C,OAAO;YACL,cAAc,EAAE,CAAC,UAAyB,EAAE,EAAE,EAAE;gBAC9C,MAAM,GAAG,GAAG,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;gBACxC,IAAI,GAAG;oBAAE,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;;oBACjD,IAAI,CAAC,mBAAmB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YACjD,CAAC;SACF,CAAC;IACJ,CAAC;IAED,cAAc,CAAC,KAAa;QAC1B,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QACzC,KAAK,IAAI,KAAK,GAAG,IAAI,CAAC,iBAAiB,EAAE,KAAK,EAAE,KAAK,GAAG,KAAK,CAAC,kBAAkB,EAAE,CAAC;YACjF,IAAK,KAAsC,CAAC,KAAK,KAAK,KAAK;gBAAE,OAAO,KAAoB,CAAC;QAC3F,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAGD,SAAS;QACP,IAAI,IAAI,GAAgB,IAAI,CAAC,UAAU,CAAC;QACxC,OAAO,IAAI,EAAE,CAAC;YACZ,IAAI,IAAI,YAAY,UAAU,EAAE,CAAC;gBAC/B,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;YACnB,CAAC;iBAAM,CAAC;gBACN,IAAI,IAAI,YAAY,WAAW,IAAI,gBAAgB,CAAC,IAAI,CAAC,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;oBAClF,OAAO,IAAI,CAAC;gBACd,CAAC;gBACD,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC;YACzB,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,mBAAmB,CAAC,KAAa,EAAE,OAAsB;QACvD,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QAClC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;QAChC,IAAI,CAAC,QAAQ,IAAI,CAAC,KAAK;YAAE,OAAO;QAIhC,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;QACvC,IAAI,CAAC,IAAI;YAAE,OAAO;QAElB,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC;QAC1C,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,MAAM,IAAI,CAAC,CAAC;QAC3C,MAAM,QAAQ,GAAG,QAAQ,CAAC,YAAY,GAAG,QAAQ,GAAG,MAAM,CAAC;QAC3D,MAAM,MAAM,GACV,IAAI,CAAC,qBAAqB,EAAE,CAAC,GAAG;YAChC,QAAQ,CAAC,qBAAqB,EAAE,CAAC,GAAG;YACpC,QAAQ,CAAC,SAAS;YAClB,QAAQ,CAAC,SAAS,CAAC;QACrB,MAAM,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,IAAI,CAAC;QACpC,MAAM,GAAG,GAAG,KAAK,GAAG,IAAI,CAAC;QACzB,MAAM,OAAO,GAAG,QAAQ,CAAC,SAAS,CAAC;QAEnC,IAAI,GAAW,CAAC;QAChB,QAAQ,OAAO,CAAC,KAAK,IAAI,OAAO,EAAE,CAAC;YACjC,KAAK,OAAO;gBACV,GAAG,GAAG,KAAK,GAAG,QAAQ,CAAC;gBACvB,MAAM;YACR,KAAK,KAAK;gBACR,GAAG,GAAG,GAAG,GAAG,QAAQ,GAAG,QAAQ,CAAC;gBAChC,MAAM;YACR,KAAK,QAAQ;gBACX,GAAG,GAAG,CAAC,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,QAAQ,GAAG,QAAQ,GAAG,CAAC,CAAC;gBAClD,MAAM;YACR;gBACE,IAAI,KAAK,GAAG,OAAO,GAAG,QAAQ;oBAAE,GAAG,GAAG,KAAK,GAAG,QAAQ,CAAC;qBAClD,IAAI,GAAG,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ;oBAAE,GAAG,GAAG,GAAG,GAAG,QAAQ,GAAG,QAAQ,CAAC;;oBACzE,OAAO;QAChB,CAAC;QACD,QAAQ,CAAC,QAAQ,CAAC,EAAE,GAAG,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;QAEvD,KAAK,IAAI,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE;YAC5B,MAAM,GAAG,GAAG,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;YACvC,IAAI,GAAG;gBAAE,YAAY,CAAC,QAAQ,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;QAChD,CAAC,CAAC,CAAC;IACL,CAAC;IAEM,MAAM,KAAK,OAAO;QACvB,OAAO,SAAS,CAAC;IACnB,CAAC;IAEM,MAAM,CAAC,QAAQ;QACpB,iBAAiB,CAAC,eAAe,CAAC,CAAC;IACrC,CAAC;IASe,iBAAiB;QAM/B,KAAK,CAAC,iBAAiB,EAAE,CAAC;QAC1B,IAAI,CAAC,YAAY,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;QACnC,IAAI,CAAC,gBAAgB,EAAE,CAAC;IAC1B,CAAC;IAEe,oBAAoB;QAClC,IAAI,CAAC,iBAAiB,EAAE,UAAU,EAAE,CAAC;QACrC,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;QAE9B,IAAI,CAAC,cAAc,GAAG,CAAC,CAAC;QACxB,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACvB,oBAAoB,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YACzC,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC;QACzB,CAAC;QACD,KAAK,CAAC,oBAAoB,EAAE,CAAC;IAC/B,CAAC;IAEkB,OAAO,CAAC,OAAuB;QAChD,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACvB,IAAI,CAAC,sBAAsB,EAAE,CAAC;IAChC,CAAC;IAuBD,gBAAgB;QACd,IAAI,IAAI,CAAC,iBAAiB,IAAI,OAAO,oBAAoB,KAAK,WAAW;YAAE,OAAO;QAClF,IAAI,CAAC,iBAAiB,GAAG,IAAI,oBAAoB,CAAC,CAAC,OAAO,EAAE,EAAE;YAC5D,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,gBAAgB,CAAC,MAAM,IAAI,CAAC,CAAC;YAEnE,IAAI,CAAC,iBAAiB,GAAG,CAAC,CAAC;YAC3B,IAAI,CAAC,sBAAsB,EAAE,CAAC;QAChC,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,CAAC;IAED,sBAAsB;QAEpB,IAAI,IAAI,CAAC,aAAa,IAAI,CAAC,IAAI,CAAC,WAAW;YAAE,OAAO;QACpD,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,IAAI,IAAI,CAAC,gBAAgB,EAAE;YAAE,OAAO;QAG3D,IAAI,CAAC,aAAa,GAAG,qBAAqB,CAAC,GAAG,EAAE;YAC9C,IAAI,CAAC,aAAa,GAAG,qBAAqB,CAAC,GAAG,EAAE;gBAC9C,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC;gBACvB,IAAI,CAAC,eAAe,EAAE,CAAC;YACzB,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;IAED,eAAe;QACb,IAAI,CAAC,IAAI,CAAC,WAAW;YAAE,OAAO;QAE9B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACzB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAExD,IAAI,IAAI,CAAC,gBAAgB,EAAE,EAAE,CAAC;YAC5B,IAAI,CAAC,iBAAiB,GAAG,CAAC,CAAC;YAC3B,OAAO;QACT,CAAC;QAID,IAAI,IAAI,CAAC,cAAc,IAAI,CAAC;YAAE,OAAO;QACrC,IAAI,IAAI,CAAC,iBAAiB,IAAI,qBAAqB;YAAE,OAAO;QAE5D,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAKzB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC;IAC7B,CAAC;IAED,gBAAgB;QACd,KAAK,IAAI,KAAK,GAAG,IAAI,CAAC,iBAAiB,EAAE,KAAK,EAAE,KAAK,GAAG,KAAK,CAAC,kBAAkB,EAAE,CAAC;YACjF,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,eAAe,CAAC;gBAAE,OAAO,IAAI,CAAC;QACxD,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;CACF","sourcesContent":["import { LitVirtualizer } from '@lit-labs/virtualizer/LitVirtualizer.js';\nimport type { PropertyValues } from 'lit';\nimport { registerComponent } from '../internal/register.js';\nimport { GRID_BODY } from '../internal/tags.js';\n\n/**\n * Attribute the upstream virtualizer stamps on the spacer element it appends in\n * scroller mode. It is not a rendered row, so it is skipped when asking whether\n * the body rendered anything.\n */\nconst SIZER_ATTRIBUTE = 'virtualizer-sizer';\n\n/**\n * Re-measure attempts allowed per geometry change. A grid that still renders\n * nothing after this many tries has a cause we cannot fix by re-measuring, so\n * we stop rather than spin.\n */\nconst MAX_RECOVERY_ATTEMPTS = 3;\n\n/** Space, in px, that sticky chrome covers on each side of the scrollport. */\nexport interface ScrollInsets {\n top: number;\n right: number;\n bottom: number;\n left: number;\n}\n\n/** `scrollIntoView` options plus the sticky chrome to keep the target clear of. */\nexport type RevealOptions = ScrollIntoViewOptions & { insets?: ScrollInsets };\n\n/** Longest wait for the layout to settle after a scroll to an unrendered row. */\nconst SETTLE_TIMEOUT_MS = 250;\n\n/**\n * Scrolls `el` into view as if `scroller` had `insets` as its scroll-padding.\n * The padding is set only for the duration of the call. Left in place, the\n * browser would apply it to every later scroll into view, including focus\n * moving onto the sticky chrome itself (a header button, the paginator),\n * which sits inside the padding and would drag the body along.\n */\nexport function revealWithin(\n scroller: HTMLElement | null,\n el: Element,\n { insets, ...options }: RevealOptions\n): void {\n const style = insets && scroller?.style;\n const previous = style ? style.scrollPadding : '';\n if (style) {\n const { top, right, bottom, left } = insets;\n style.scrollPadding = `${top}px ${right}px ${bottom}px ${left}px`;\n }\n el.scrollIntoView(options);\n if (style) style.scrollPadding = previous;\n}\n\nexport default class ApexVirtualizer extends LitVirtualizer {\n /**\n * Watches the host's intersection with the window, which is the one input to\n * the upstream viewport measurement that has no invalidation signal of its\n * own. See the note on `#observeViewport`.\n */\n #viewportObserver: IntersectionObserver | null = null;\n\n /**\n * Height of the host's last observed intersection with the window: the\n * viewport height the layout should be working from. Zero means an empty\n * range is the *correct* render and there is nothing to recover.\n */\n #visibleHeight = 0;\n\n #pendingCheck = 0;\n\n #recoveryAttempts = 0;\n\n /** Item indexes currently rendered, as last reported by `rangeChanged`. */\n #first = -1;\n #last = -1;\n\n constructor() {\n super();\n // Registered before the upstream directive's own listener (added on first\n // render), so the range is current before the rows are re-rendered.\n this.addEventListener('rangeChanged', (event) => {\n const { first, last } = event as Event & { first: number; last: number };\n this.#first = first;\n this.#last = last;\n });\n }\n\n /**\n * Resolves once the layout has settled, or after a bounded wait when no\n * layout is pending (upstream `layoutComplete` only settles on a layout).\n */\n public settled(): Promise<void> {\n const layout = this.layoutComplete;\n const timeout = new Promise<void>((resolve) => setTimeout(resolve, SETTLE_TIMEOUT_MS));\n return layout ? Promise.race([layout.catch(() => undefined), timeout]) : timeout;\n }\n\n /** Whether the item at `index` is in the rendered range. */\n public isRendered(index: number): boolean {\n return index >= 0 && index >= this.#first && index <= this.#last;\n }\n\n /**\n * Scroll handle for item `index`, rendered or not.\n *\n * Upstream scrolls an unrendered item into view by pinning the layout to it,\n * and that pin path assumes the window is the scroller: with the grid host\n * scrolling (`scroller = false`) it overshoots every item once the host has\n * scrolled, leaving the body empty at the maximum scroll offset. An\n * unrendered item is instead reached with a real scroll of the host, to its\n * estimated offset, which the layout then follows like any user scroll.\n */\n public override element(\n index: number\n ): { scrollIntoView: (options?: RevealOptions) => void } | undefined {\n const target = index === Number.POSITIVE_INFINITY ? this.items.length - 1 : index;\n if (!super.element(target)) return undefined;\n return {\n scrollIntoView: (options: RevealOptions = {}) => {\n const row = this.#renderedChild(target);\n if (row) revealWithin(this.#scroller(), row, options);\n else this.#scrollToUnrendered(target, options);\n },\n };\n }\n\n #renderedChild(index: number): HTMLElement | null {\n if (!this.isRendered(index)) return null;\n for (let child = this.firstElementChild; child; child = child.nextElementSibling) {\n if ((child as Element & { index?: number }).index === index) return child as HTMLElement;\n }\n return null;\n }\n\n /** The nearest ancestor that scrolls this element (the grid host). */\n #scroller(): HTMLElement | null {\n let node: Node | null = this.parentNode;\n while (node) {\n if (node instanceof ShadowRoot) {\n node = node.host;\n } else {\n if (node instanceof HTMLElement && getComputedStyle(node).overflowY !== 'visible') {\n return node;\n }\n node = node.parentNode;\n }\n }\n return null;\n }\n\n #scrollToUnrendered(index: number, options: RevealOptions): void {\n const scroller = this.#scroller();\n const count = this.items.length;\n if (!scroller || !count) return;\n // The upstream layout sizes this element to its estimate of the total\n // extent, so the average item size here matches its own estimates for\n // items it has not measured.\n const size = this.offsetHeight / count;\n if (!size) return;\n\n const padStart = options.insets?.top ?? 0;\n const padEnd = options.insets?.bottom ?? 0;\n const viewport = scroller.clientHeight - padStart - padEnd;\n const origin =\n this.getBoundingClientRect().top -\n scroller.getBoundingClientRect().top -\n scroller.clientTop +\n scroller.scrollTop;\n const start = origin + index * size;\n const end = start + size;\n const current = scroller.scrollTop;\n\n let top: number;\n switch (options.block ?? 'start') {\n case 'start':\n top = start - padStart;\n break;\n case 'end':\n top = end - padStart - viewport;\n break;\n case 'center':\n top = (start + end) / 2 - padStart - viewport / 2;\n break;\n default:\n if (start < current + padStart) top = start - padStart;\n else if (end > current + padStart + viewport) top = end - padStart - viewport;\n else return;\n }\n scroller.scrollTo({ top, behavior: options.behavior });\n // The offset was an estimate; once the target is rendered, align the real row.\n void this.settled().then(() => {\n const row = this.#renderedChild(index);\n if (row) revealWithin(scroller, row, options);\n });\n }\n\n public static get tagName() {\n return GRID_BODY;\n }\n\n public static register(): void {\n registerComponent(ApexVirtualizer);\n }\n\n // The virtualizer used to own vertical scrolling, which made it a scroll container\n // and broke `position: sticky` for body cells in pinned columns (cells would anchor\n // to the virtualizer instead of the horizontally-scrolling grid host). With\n // `scroller = false` the grid host owns both axes, so headers and pinned body cells\n // share a single sticky containing block.\n public override scroller = false;\n\n public override connectedCallback() {\n // Nothing may be awaited before this call. The upstream virtualizer is only\n // created (and reconnected) from the element's own Lit update cycle, which\n // `super.connectedCallback()` is what starts. Deferring it past an await on\n // any virtualizer state deadlocks on a reconnect: the promise waits for a\n // layout that waits for the update that this call would have scheduled.\n super.connectedCallback();\n this.setAttribute('tabindex', '0');\n this.#observeViewport();\n }\n\n public override disconnectedCallback() {\n this.#viewportObserver?.disconnect();\n this.#viewportObserver = null;\n // Geometry is meaningless while detached; the observer re-reports on connect.\n this.#visibleHeight = 0;\n if (this.#pendingCheck) {\n cancelAnimationFrame(this.#pendingCheck);\n this.#pendingCheck = 0;\n }\n super.disconnectedCallback();\n }\n\n protected override updated(changed: PropertyValues) {\n super.updated(changed);\n this.#scheduleViewportCheck();\n }\n\n /**\n * The upstream virtualizer derives its viewport from the intersection of the\n * host, its clipping ancestors and the window, and clears the rendered range\n * outright when that intersection is zero-height, while still sizing the\n * scroll extent from the full item count. A grid that is laid out while it\n * sits outside the window (an iframe not yet sized by its host page, a panel\n * still settling, content above it that has not finished loading) therefore\n * ends up reporting a correct row count and scroll extent with no rows in it.\n *\n * That state is not self-correcting, because the only invalidation signals\n * upstream listens for are `ResizeObserver` size changes and scroll events:\n * an element that *moves* into view, or a window that resizes around a\n * fixed-size host, fires neither. The grid then stays empty until something\n * unrelated forces a re-render, which is why the failure reads as a race and\n * heals on the first interaction.\n *\n * `IntersectionObserver` fires on exactly the missing signal, so it is what\n * arms the recovery check.\n *\n * @see https://github.com/apexcharts/apex-grid/issues/31\n */\n #observeViewport(): void {\n if (this.#viewportObserver || typeof IntersectionObserver === 'undefined') return;\n this.#viewportObserver = new IntersectionObserver((entries) => {\n this.#visibleHeight = entries.at(-1)?.intersectionRect.height ?? 0;\n // Fresh geometry, so the attempt budget starts over.\n this.#recoveryAttempts = 0;\n this.#scheduleViewportCheck();\n });\n this.#viewportObserver.observe(this);\n }\n\n #scheduleViewportCheck(): void {\n // Healthy path: one element lookup and out, no frame scheduled.\n if (this.#pendingCheck || !this.isConnected) return;\n if (!this.items?.length || this.#hasRenderedRows()) return;\n // Two frames, matching what the virtualizer itself waits before calling a\n // layout settled. Checking sooner would flag a first paint still in flight.\n this.#pendingCheck = requestAnimationFrame(() => {\n this.#pendingCheck = requestAnimationFrame(() => {\n this.#pendingCheck = 0;\n this.#recoverIfStale();\n });\n });\n }\n\n #recoverIfStale(): void {\n if (!this.isConnected) return;\n\n const items = this.items;\n if (!Array.isArray(items) || items.length === 0) return;\n\n if (this.#hasRenderedRows()) {\n this.#recoveryAttempts = 0;\n return;\n }\n\n // No visible slice means rendering nothing is correct: the grid is scrolled\n // out of view, inside a collapsed panel, or hidden. Leave it alone.\n if (this.#visibleHeight <= 0) return;\n if (this.#recoveryAttempts >= MAX_RECOVERY_ATTEMPTS) return;\n\n this.#recoveryAttempts++;\n // Re-assigning `items` with a new array identity is the public lever that\n // makes the virtualizer re-run its layout, and so re-measure the viewport.\n // Unlike a synthetic scroll event it cannot disturb a pending\n // `scrollIntoView`, which the layout holds as a pin until a real scroll.\n this.items = items.slice();\n }\n\n #hasRenderedRows(): boolean {\n for (let child = this.firstElementChild; child; child = child.nextElementSibling) {\n if (!child.hasAttribute(SIZER_ATTRIBUTE)) return true;\n }\n return false;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n [ApexVirtualizer.tagName]: ApexVirtualizer;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"virtualizer.js","sourceRoot":"","sources":["../../src/components/virtualizer.ts"],"names":[],"mappings":"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","sourcesContent":["import { LitVirtualizer } from '@lit-labs/virtualizer/LitVirtualizer.js';\nimport { html, type PropertyValues } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { registerComponent } from '../internal/register.js';\nimport { GRID_BODY } from '../internal/tags.js';\nimport { type RowMode, virtualizedRows, virtualizeRows } from './virtualize-rows.js';\n\n/**\n * Attribute the upstream virtualizer stamps on the spacer element it appends in\n * scroller mode. It is not a rendered row, so it is skipped when asking whether\n * the body rendered anything.\n */\nconst SIZER_ATTRIBUTE = 'virtualizer-sizer';\n\n/**\n * Re-measure attempts allowed per geometry change. A grid that still renders\n * nothing after this many tries has a cause we cannot fix by re-measuring, so\n * we stop rather than spin.\n */\nconst MAX_RECOVERY_ATTEMPTS = 3;\n\n/** Set once the window listener is in place: one per loaded copy of the grid. */\nlet loopNoticeQuieted = false;\n\n/**\n * Rows whose text wraps change height while the grid resizes or scrolls, and\n * the upstream virtualizer answers each measurement by resizing its own host\n * within the same round of resize observations (it also keeps observing the\n * rows it drops, which then report from outside the document). The browser\n * defers those observations to the next frame, where the layout settles, and\n * reports the deferral as an error on the window: Safari logs it, Chrome hands\n * it to page error listeners and error monitoring. It is benign, so the first\n * grid to connect cancels that message (and the older \"loop limit exceeded\"\n * wording) for the window and keeps it from the listeners added after it\n * (listeners added earlier still see it). Every other error is left alone.\n *\n * @see https://github.com/apexcharts/apex-grid/issues/32\n */\nexport function quietResizeObserverLoopNotice(): void {\n if (loopNoticeQuieted) return;\n loopNoticeQuieted = true;\n window.addEventListener('error', (event) => {\n if (String((event as ErrorEvent).message).includes('ResizeObserver loop')) {\n event.preventDefault();\n event.stopImmediatePropagation();\n }\n });\n}\n\n/** Space, in px, that sticky chrome covers on each side of the scrollport. */\nexport interface ScrollInsets {\n top: number;\n right: number;\n bottom: number;\n left: number;\n}\n\n/** `scrollIntoView` options plus the sticky chrome to keep the target clear of. */\nexport type RevealOptions = ScrollIntoViewOptions & { insets?: ScrollInsets };\n\n/** Longest wait for the layout to settle after a scroll to an unrendered row. */\nconst SETTLE_TIMEOUT_MS = 250;\n\n/** Estimated scrolls to an unrendered row before giving up on rendering it. */\nconst MAX_REVEAL_ATTEMPTS = 4;\n\n/**\n * How the item branch keys its rows. `'item'` is upstream's default (the\n * record itself). `'spike'` keys by slot, `index % 128`, so a rebind reuses\n * the row elements in place: the measured reference the slot reconciler\n * replaced, kept for the benchmark.\n *\n * @internal Benchmark-only. Not public API.\n */\nexport type RowKeying = 'item' | 'spike';\n\n/** Number of slots the spike key cycles through. */\nconst SPIKE_SLOTS = 128;\n\nconst spikeKey = (_item: unknown, index: number) => index % SPIKE_SLOTS;\n\n/**\n * Scrolls `el` into view as if `scroller` had `insets` as its scroll-padding.\n * The padding is set only for the duration of the call. Left in place, the\n * browser would apply it to every later scroll into view, including focus\n * moving onto the sticky chrome itself (a header button, the paginator),\n * which sits inside the padding and would drag the body along.\n */\nexport function revealWithin(\n scroller: HTMLElement | null,\n el: Element,\n { insets, ...options }: RevealOptions\n): void {\n const style = insets && scroller?.style;\n const previous = style ? style.scrollPadding : '';\n if (style) {\n const { top, right, bottom, left } = insets;\n style.scrollPadding = `${top}px ${right}px ${bottom}px ${left}px`;\n }\n el.scrollIntoView(options);\n if (style) style.scrollPadding = previous;\n}\n\nexport default class ApexVirtualizer extends LitVirtualizer {\n /**\n * Row keying every body built afterwards starts with. Anything other than\n * `'spike'` leaves upstream's item key untouched.\n *\n * @internal Benchmark-only, for its spike reference mode. Not public API.\n */\n public static rowKeying: RowKeying = 'item';\n\n /**\n * How rows map to elements: `'item'` keys each row by its record,\n * `'slot'` re-binds row elements by position (the grid's `rowRecycling`).\n * A switch rebuilds the rendered rows once.\n *\n * @internal Set by the grid. Not public API.\n */\n @property({ attribute: false })\n public rowMode: RowMode = 'item';\n\n /**\n * Watches the host's intersection with the window, which is the one input to\n * the upstream viewport measurement that has no invalidation signal of its\n * own. See the note on `#observeViewport`.\n */\n #viewportObserver: IntersectionObserver | null = null;\n\n /**\n * Height of the host's last observed intersection with the window: the\n * viewport height the layout should be working from. Zero means an empty\n * range is the *correct* render and there is nothing to recover.\n */\n #visibleHeight = 0;\n\n #pendingCheck = 0;\n\n #recoveryAttempts = 0;\n\n /** Item indexes currently rendered, as last reported by `rangeChanged`. */\n #first = -1;\n #last = -1;\n\n /**\n * The latest scroll asked of {@link element}. A reveal deferred until the\n * layout settles runs only while it is still the latest, so a slow settle\n * cannot pull the body back from a newer jump.\n */\n #reveal = 0;\n\n constructor() {\n super();\n // The upstream constructor has just assigned its default key, so the\n // switch has to be applied per instance, after it.\n if (ApexVirtualizer.rowKeying === 'spike') this.keyFunction = spikeKey;\n // Rows re-render only after every `rangeChanged` listener has run (see\n // `dispatchEvent`), so the range is current before they do.\n this.addEventListener('rangeChanged', (event) => {\n const { first, last } = event as Event & { first: number; last: number };\n this.#first = first;\n this.#last = last;\n });\n }\n\n /** Upstream's own render, with the body's fork of its directive. */\n public override render() {\n const { items, renderItem, keyFunction, layout, scroller, rowMode: mode } = this;\n return html`${virtualizeRows({ items, renderItem, keyFunction, layout, scroller, mode })}`;\n }\n\n /**\n * Holds the rows' re-render until every `rangeChanged` listener has run, so\n * a listener sees the rows of the previous range whatever its registration\n * order. The grid's `bodyRangeChanged` relies on this: it reads which index\n * the focused row showed before the range moved.\n */\n public override dispatchEvent(event: Event): boolean {\n const rows = event.type === 'rangeChanged' ? virtualizedRows(this) : undefined;\n return rows ? rows.holdRender(() => super.dispatchEvent(event)) : super.dispatchEvent(event);\n }\n\n /**\n * Upstream's promise, which settles only from its children ResizeObserver.\n * A render that re-binds rows in place (a sort or a move under slot keys)\n * resizes nothing, so it would never settle; when nothing has happened for\n * two frames since the last render, the rows directive settles it instead.\n * Anything else is left to upstream untouched.\n */\n public override get layoutComplete(): Promise<void> | undefined {\n const promise = super.layoutComplete;\n if (promise) virtualizedRows(this)?.armLayoutComplete(this.isUpdatePending);\n return promise;\n }\n\n /**\n * Resolves once the rows reflect this element's latest state: a pending\n * update, the render it leads to (new items render a few microtasks later,\n * once the layout reports the range) and every rendered row's own update.\n *\n * @internal For the row FLIP settle step. Not public API.\n */\n public async rendered(): Promise<void> {\n if (this.isUpdatePending) await this.updateComplete;\n if (!this.isConnected) return;\n await virtualizedRows(this)?.rendered();\n }\n\n /**\n * Resolves once the layout has settled, or after a bounded wait when no\n * layout is pending (upstream `layoutComplete` only settles on a layout).\n */\n public settled(): Promise<void> {\n const layout = this.layoutComplete;\n const timeout = new Promise<void>((resolve) => setTimeout(resolve, SETTLE_TIMEOUT_MS));\n return layout ? Promise.race([layout.catch(() => undefined), timeout]) : timeout;\n }\n\n /** Whether the item at `index` is in the rendered range. */\n public isRendered(index: number): boolean {\n return index >= 0 && index >= this.#first && index <= this.#last;\n }\n\n /**\n * Scroll handle for item `index`, rendered or not.\n *\n * Upstream scrolls an unrendered item into view by pinning the layout to it,\n * and that pin path assumes the window is the scroller: with the grid host\n * scrolling (`scroller = false`) it overshoots every item once the host has\n * scrolled, leaving the body empty at the maximum scroll offset. An\n * unrendered item is instead reached with a real scroll of the host, to its\n * estimated offset, which the layout then follows like any user scroll.\n */\n public override element(\n index: number\n ): { scrollIntoView: (options?: RevealOptions) => void } | undefined {\n const target = index === Number.POSITIVE_INFINITY ? this.items.length - 1 : index;\n if (!super.element(target)) return undefined;\n return {\n scrollIntoView: (options: RevealOptions = {}) => {\n const reveal = ++this.#reveal;\n const row = this.#renderedChild(target);\n if (row) revealWithin(this.#scroller(), row, options);\n else this.#scrollToUnrendered(target, options, reveal);\n },\n };\n }\n\n #renderedChild(index: number): HTMLElement | null {\n if (!this.isRendered(index)) return null;\n for (let child = this.firstElementChild; child; child = child.nextElementSibling) {\n if ((child as Element & { index?: number }).index === index) return child as HTMLElement;\n }\n return null;\n }\n\n /** The nearest ancestor that scrolls this element (the grid host). */\n #scroller(): HTMLElement | null {\n let node: Node | null = this.parentNode;\n while (node) {\n if (node instanceof ShadowRoot) {\n node = node.host;\n } else {\n if (node instanceof HTMLElement && getComputedStyle(node).overflowY !== 'visible') {\n return node;\n }\n node = node.parentNode;\n }\n }\n return null;\n }\n\n /** The scroll that reaches an unrendered item, until it has revealed it or given up. */\n #revealing: Promise<void> = Promise.resolve();\n\n /**\n * Resolves once the latest scroll to an unrendered item (see\n * {@link element}) has rendered and revealed it, or given up.\n */\n public revealed(): Promise<void> {\n return this.#revealing;\n }\n\n #scrollToUnrendered(index: number, options: RevealOptions, reveal: number): void {\n const scroller = this.#scroller();\n if (!scroller || !this.items.length) return;\n this.#revealing = this.#chase(scroller, index, options, reveal);\n }\n\n /**\n * Scrolls to the estimated offset of item `index` until the item is\n * rendered, then aligns the real row. Each estimate starts from the rows\n * rendered by then, so a miss is corrected from where the last scroll\n * landed. Stops when a newer scroll has been asked for.\n */\n async #chase(\n scroller: HTMLElement,\n index: number,\n options: RevealOptions,\n reveal: number\n ): Promise<void> {\n for (let attempt = 0; attempt < MAX_REVEAL_ATTEMPTS; attempt++) {\n const top = this.#estimateScroll(scroller, index, options);\n if (top === null) return;\n scroller.scrollTo({ top, behavior: options.behavior });\n await this.settled();\n if (reveal !== this.#reveal) return;\n const row = this.#renderedChild(index);\n if (row) {\n revealWithin(scroller, row, options);\n return;\n }\n }\n }\n\n /**\n * The scroll offset that brings unrendered item `index` into view as\n * `options` asks, or `null` when no scroll is needed or possible.\n *\n * The upstream layout sizes this element to its estimate of the total\n * extent, so the average item size matches its own estimates for items it\n * has not measured. That average can be stale (rows that grew after they\n * were measured, an expanded detail panel), so it is applied only across\n * the gap from the nearest rendered row, whose position is real: an item\n * just past the rendered range lands where the layout will draw it, and a\n * scroll never jumps back past a correct position.\n */\n #estimateScroll(scroller: HTMLElement, index: number, options: RevealOptions): number | null {\n const size = this.offsetHeight / this.items.length;\n if (!size) return null;\n\n const padStart = options.insets?.top ?? 0;\n const padEnd = options.insets?.bottom ?? 0;\n const viewport = scroller.clientHeight - padStart - padEnd;\n const base = scroller.getBoundingClientRect().top + scroller.clientTop - scroller.scrollTop;\n const offsetOf = (el: Element) => el.getBoundingClientRect().top - base;\n\n const after = index > this.#last ? this.#renderedChild(this.#last) : null;\n const before = index < this.#first ? this.#renderedChild(this.#first) : null;\n let start: number;\n if (after) {\n start = offsetOf(after) + after.offsetHeight + (index - this.#last - 1) * size;\n } else if (before) {\n start = offsetOf(before) - (this.#first - index) * size;\n } else {\n start = offsetOf(this) + index * size;\n }\n const end = start + size;\n const current = scroller.scrollTop;\n\n switch (options.block ?? 'start') {\n case 'start':\n return start - padStart;\n case 'end':\n return end - padStart - viewport;\n case 'center':\n return (start + end) / 2 - padStart - viewport / 2;\n default:\n if (start < current + padStart) return start - padStart;\n if (end > current + padStart + viewport) return end - padStart - viewport;\n return null;\n }\n }\n\n public static get tagName() {\n return GRID_BODY;\n }\n\n public static register(): void {\n registerComponent(ApexVirtualizer);\n }\n\n // The virtualizer used to own vertical scrolling, which made it a scroll container\n // and broke `position: sticky` for body cells in pinned columns (cells would anchor\n // to the virtualizer instead of the horizontally-scrolling grid host). With\n // `scroller = false` the grid host owns both axes, so headers and pinned body cells\n // share a single sticky containing block.\n public override scroller = false;\n\n public override connectedCallback() {\n // Nothing may be awaited before this call. The upstream virtualizer is only\n // created (and reconnected) from the element's own Lit update cycle, which\n // `super.connectedCallback()` is what starts. Deferring it past an await on\n // any virtualizer state deadlocks on a reconnect: the promise waits for a\n // layout that waits for the update that this call would have scheduled.\n super.connectedCallback();\n this.setAttribute('tabindex', '0');\n this.#observeViewport();\n }\n\n public override disconnectedCallback() {\n this.#viewportObserver?.disconnect();\n this.#viewportObserver = null;\n // Geometry is meaningless while detached; the observer re-reports on connect.\n this.#visibleHeight = 0;\n if (this.#pendingCheck) {\n cancelAnimationFrame(this.#pendingCheck);\n this.#pendingCheck = 0;\n }\n super.disconnectedCallback();\n }\n\n protected override updated(changed: PropertyValues) {\n super.updated(changed);\n this.#scheduleViewportCheck();\n }\n\n /**\n * The upstream virtualizer derives its viewport from the intersection of the\n * host, its clipping ancestors and the window, and clears the rendered range\n * outright when that intersection is zero-height, while still sizing the\n * scroll extent from the full item count. A grid that is laid out while it\n * sits outside the window (an iframe not yet sized by its host page, a panel\n * still settling, content above it that has not finished loading) therefore\n * ends up reporting a correct row count and scroll extent with no rows in it.\n *\n * That state is not self-correcting, because the only invalidation signals\n * upstream listens for are `ResizeObserver` size changes and scroll events:\n * an element that *moves* into view, or a window that resizes around a\n * fixed-size host, fires neither. The grid then stays empty until something\n * unrelated forces a re-render, which is why the failure reads as a race and\n * heals on the first interaction.\n *\n * `IntersectionObserver` fires on exactly the missing signal, so it is what\n * arms the recovery check.\n *\n * @see https://github.com/apexcharts/apex-grid/issues/31\n */\n #observeViewport(): void {\n if (this.#viewportObserver || typeof IntersectionObserver === 'undefined') return;\n this.#viewportObserver = new IntersectionObserver((entries) => {\n this.#visibleHeight = entries.at(-1)?.intersectionRect.height ?? 0;\n // Fresh geometry, so the attempt budget starts over.\n this.#recoveryAttempts = 0;\n this.#scheduleViewportCheck();\n });\n this.#viewportObserver.observe(this);\n }\n\n #scheduleViewportCheck(): void {\n // Healthy path: one element lookup and out, no frame scheduled.\n if (this.#pendingCheck || !this.isConnected) return;\n if (!this.items?.length || this.#hasRenderedRows()) return;\n // Two frames, matching what the virtualizer itself waits before calling a\n // layout settled. Checking sooner would flag a first paint still in flight.\n this.#pendingCheck = requestAnimationFrame(() => {\n this.#pendingCheck = requestAnimationFrame(() => {\n this.#pendingCheck = 0;\n this.#recoverIfStale();\n });\n });\n }\n\n #recoverIfStale(): void {\n if (!this.isConnected) return;\n\n const items = this.items;\n if (!Array.isArray(items) || items.length === 0) return;\n\n if (this.#hasRenderedRows()) {\n this.#recoveryAttempts = 0;\n return;\n }\n\n // No visible slice means rendering nothing is correct: the grid is scrolled\n // out of view, inside a collapsed panel, or hidden. Leave it alone.\n if (this.#visibleHeight <= 0) return;\n if (this.#recoveryAttempts >= MAX_RECOVERY_ATTEMPTS) return;\n\n this.#recoveryAttempts++;\n // Re-assigning `items` with a new array identity is the public lever that\n // makes the virtualizer re-run its layout, and so re-measure the viewport.\n // Unlike a synthetic scroll event it cannot disturb a pending\n // `scrollIntoView`, which the layout holds as a pin until a real scroll.\n this.items = items.slice();\n }\n\n #hasRenderedRows(): boolean {\n for (let child = this.firstElementChild; child; child = child.nextElementSibling) {\n if (!child.hasAttribute(SIZER_ATTRIBUTE)) return true;\n }\n return false;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n [ApexVirtualizer.tagName]: ApexVirtualizer;\n }\n}\n"]}
|
package/controllers/dom.d.ts
CHANGED
|
@@ -12,8 +12,14 @@ export declare class GridDOMController<T extends object> implements ReactiveCont
|
|
|
12
12
|
/**
|
|
13
13
|
* Visual render order: `'start'`-pinned columns first, then unpinned, then
|
|
14
14
|
* `'end'`-pinned. The user-supplied `columns` array is never mutated.
|
|
15
|
+
*
|
|
16
|
+
* Resolved once per host update, so a virtualizer range change between
|
|
17
|
+
* updates hands the rows still in range the same array and only the rows
|
|
18
|
+
* that scrolled in render. A host update resolves a new array on purpose:
|
|
19
|
+
* rows read selection, expansion and the like from the state, and the new
|
|
20
|
+
* array is what re-renders them.
|
|
15
21
|
*/
|
|
16
|
-
|
|
22
|
+
displayColumns: Array<ColumnConfiguration<T>>;
|
|
17
23
|
columnSizes: StyleInfo;
|
|
18
24
|
/**
|
|
19
25
|
* The resolved inline-start (for `'start'` pin) or inline-end (for `'end'` pin)
|
|
@@ -24,9 +30,10 @@ export declare class GridDOMController<T extends object> implements ReactiveCont
|
|
|
24
30
|
/**
|
|
25
31
|
* Number of chrome rows above the body for `aria-rowindex`: an optional group
|
|
26
32
|
* header row and the column header (always present). The filter panel is a
|
|
27
|
-
* floating overlay rather than a table row, so it is not counted here.
|
|
33
|
+
* floating overlay rather than a table row, so it is not counted here. The
|
|
34
|
+
* one count behind `aria-rowcount`, the body rows and both pinned bands.
|
|
28
35
|
*/
|
|
29
|
-
|
|
36
|
+
get headerRowCount(): number;
|
|
30
37
|
rowRenderer: RenderItemFunction<T>;
|
|
31
38
|
/**
|
|
32
39
|
* Renders a single pinned row for a sticky band. Reuses {@link ApexGridRow}
|
package/controllers/dom.js
CHANGED
|
@@ -16,6 +16,7 @@ export class GridDOMController {
|
|
|
16
16
|
this.#observedHeaders = new Set();
|
|
17
17
|
this.#stickyRowObserver = null;
|
|
18
18
|
this.#observedStickyRows = new Set();
|
|
19
|
+
this.displayColumns = [];
|
|
19
20
|
this.columnSizes = {};
|
|
20
21
|
this.pinOffsets = new Map();
|
|
21
22
|
this.rowRenderer = (data, index) => {
|
|
@@ -60,9 +61,6 @@ export class GridDOMController {
|
|
|
60
61
|
get container() {
|
|
61
62
|
return this.host.scrollContainer;
|
|
62
63
|
}
|
|
63
|
-
get displayColumns() {
|
|
64
|
-
return getDisplayColumns(this.host.columns);
|
|
65
|
-
}
|
|
66
64
|
get headerRowCount() {
|
|
67
65
|
return this.host.columnGroupDepth + 1;
|
|
68
66
|
}
|
|
@@ -130,6 +128,7 @@ export class GridDOMController {
|
|
|
130
128
|
this.#lastHostWidth = width;
|
|
131
129
|
}
|
|
132
130
|
setGridColumnSizes() {
|
|
131
|
+
this.displayColumns = getDisplayColumns(this.host.columns);
|
|
133
132
|
const chrome = leadingChromeTracks(this.state);
|
|
134
133
|
this.columnSizes = applyColumnWidths(this.displayColumns, chrome);
|
|
135
134
|
this.#publishChromeOffsets(chrome);
|
|
@@ -230,8 +229,9 @@ export class GridDOMController {
|
|
|
230
229
|
const filter = root.querySelector('apex-filter-row');
|
|
231
230
|
const paginator = root.querySelector('apex-grid-paginator');
|
|
232
231
|
const toolbarH = toolbar?.offsetHeight ?? 0;
|
|
233
|
-
const
|
|
234
|
-
const
|
|
232
|
+
const shown = this.host.showHeader;
|
|
233
|
+
const groupH = shown ? (groupHeader?.offsetHeight ?? 0) : 0;
|
|
234
|
+
const headerH = shown ? (header?.offsetHeight ?? 0) : 0;
|
|
235
235
|
const filterH = filter?.offsetHeight ?? 0;
|
|
236
236
|
const paginatorH = paginator?.offsetHeight ?? 0;
|
|
237
237
|
const groupTop = toolbarH;
|
package/controllers/dom.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dom.js","sourceRoot":"","sources":["../../src/controllers/dom.ts"],"names":[],"mappings":"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","sourcesContent":["import type { RenderItemFunction } from '@lit-labs/virtualizer/virtualize.js';\nimport { html, type ReactiveController } from 'lit';\nimport { type StyleInfo, styleMap } from 'lit/directives/style-map.js';\nimport { SENTINEL_NODE } from '../internal/constants.js';\nimport type { ActiveNode, ColumnConfiguration, GridHost, Keys } from '../internal/types.js';\nimport {\n applyColumnWidths,\n type ChromeTrack,\n getDisplayColumns,\n leadingChromeTracks,\n} from '../internal/utils.js';\nimport type { StateController } from './state.js';\n\nexport class GridDOMController<T extends object> implements ReactiveController {\n constructor(\n protected host: GridHost<T>,\n protected state: StateController<T>\n ) {\n this.host.addController(this);\n }\n\n #initialSize = () => {\n setTimeout(() => {\n this.recomputePinOffsets();\n this.recomputeStickyRowOffsets();\n });\n };\n\n #resizeObserver: ResizeObserver | null = null;\n #observedHeaders = new Set<Element>();\n #stickyRowObserver: ResizeObserver | null = null;\n #observedStickyRows = new Set<Element>();\n\n public get container() {\n // @ts-expect-error: protected member access\n return this.host.scrollContainer;\n }\n\n /**\n * Visual render order: `'start'`-pinned columns first, then unpinned, then\n * `'end'`-pinned. The user-supplied `columns` array is never mutated.\n */\n public get displayColumns(): Array<ColumnConfiguration<T>> {\n return getDisplayColumns(this.host.columns);\n }\n\n public columnSizes: StyleInfo = {};\n\n /**\n * The resolved inline-start (for `'start'` pin) or inline-end (for `'end'` pin)\n * pixel offset per pinned column key. Populated after layout by\n * {@link recomputePinOffsets}.\n */\n public pinOffsets = new Map<Keys<T>, number>();\n\n /**\n * Number of chrome rows above the body for `aria-rowindex`: an optional group\n * header row and the column header (always present). The filter panel is a\n * floating overlay rather than a table row, so it is not counted here.\n */\n protected get headerRowCount(): number {\n return this.host.columnGroupDepth + 1;\n }\n\n public rowRenderer: RenderItemFunction<T> = (data: T, index: number) => {\n const editingKey = this.#editingKey(data);\n // Body rows follow the chrome rows and any pinned-top rows in the\n // aria-rowindex sequence.\n const ariaRowOffset = this.headerRowCount + this.state.rowPin.pinnedRows.top.length;\n return html`\n <apex-grid-row\n part=\"row\"\n style=${styleMap({ ...this.columnSizes, ...this.getActiveRowStyles(index) })}\n .index=${index}\n .activeNode=${this.state.active}\n .data=${data}\n .columns=${this.displayColumns}\n .pinOffsets=${this.pinOffsets}\n .editingKey=${editingKey}\n .ariaRowOffset=${ariaRowOffset}\n .decorationVersion=${this.state.decorationVersion}\n .dataVersion=${this.state.dataVersion}\n .validationVersion=${this.state.editing.validationVersion}\n .dragging=${this.state.rowReorder.dragging === data}\n .grabbed=${this.state.rowReorder.grabbed === data}\n .coordinateHints=${Boolean(this.host.coordinateHints)}\n >\n </apex-grid-row>\n `;\n };\n\n /**\n * The column whose editor the row showing `data` renders, or `null`. Bound\n * to the edited record, never to a view index, so a view change (sort,\n * filter, paging, live data, pinning) cannot move the editor onto another\n * record.\n */\n #editingKey(data: T): Keys<T> | null {\n const editingCell = this.state.editing.activeCell;\n return editingCell && editingCell.data === data ? editingCell.columnKey : null;\n }\n\n /**\n * Renders a single pinned row for a sticky band. Reuses {@link ApexGridRow}\n * so selection / expansion / decoration / editing all work by data\n * reference, but pins a sentinel {@link ActiveNode} (pinned rows are\n * presentation, selection and pointer-edit surfaces in v1, never the\n * keyboard-active cell).\n *\n * @param localIndex - position within the band (drives the active sentinel id).\n * @param ariaRowOffset - so `aria-rowindex` continues the unified sequence.\n */\n public pinnedRowRenderer(data: T, localIndex: number, ariaRowOffset: number) {\n return html`\n <apex-grid-row\n part=\"row pinned-row\"\n style=${styleMap(this.columnSizes)}\n .index=${localIndex}\n .activeNode=${SENTINEL_NODE as ActiveNode<T>}\n .data=${data}\n .columns=${this.displayColumns}\n .pinOffsets=${this.pinOffsets}\n .editingKey=${this.#editingKey(data)}\n .ariaRowOffset=${ariaRowOffset}\n .decorationVersion=${this.state.decorationVersion}\n .dataVersion=${this.state.dataVersion}\n .validationVersion=${this.state.editing.validationVersion}\n .coordinateHints=${Boolean(this.host.coordinateHints)}\n >\n </apex-grid-row>\n `;\n }\n\n public async hostConnected() {\n this.setGridColumnSizes();\n // Wait for the initial paint of the virtualizer, then measure the pinned\n // columns and sticky rows it laid out.\n await this.host.updateComplete;\n this.#initialSize();\n if (typeof ResizeObserver !== 'undefined' && !this.#hostWidthObserver) {\n this.#hostWidthObserver = new ResizeObserver(() => {\n requestAnimationFrame(() => this.recomputeHostWidth());\n });\n this.#hostWidthObserver.observe(this.host as HTMLElement);\n }\n this.recomputeHostWidth();\n }\n\n public hostUpdate(): void {\n this.setGridColumnSizes();\n }\n\n public hostUpdated(): void {\n this.recomputePinOffsets();\n this.observeHeaderCells();\n this.recomputeStickyRowOffsets();\n this.observeStickyRows();\n }\n\n public hostDisconnected(): void {\n this.#resizeObserver?.disconnect();\n this.#resizeObserver = null;\n this.#observedHeaders.clear();\n this.#stickyRowObserver?.disconnect();\n this.#stickyRowObserver = null;\n this.#observedStickyRows.clear();\n this.#hostWidthObserver?.disconnect();\n this.#hostWidthObserver = null;\n }\n\n /**\n * Writes the grid host's `clientWidth` into `--apex-host-width`. Used by the\n * toolbar and paginator to clamp their width to the visible viewport so\n * horizontal scrolling doesn't drag them off-screen.\n */\n public recomputeHostWidth(): void {\n const host = this.host as HTMLElement;\n const width = host.clientWidth;\n if (width === this.#lastHostWidth) return;\n host.style.setProperty('--apex-host-width', `${width}px`);\n this.#lastHostWidth = width;\n }\n\n protected setGridColumnSizes() {\n const chrome = leadingChromeTracks(this.state);\n this.columnSizes = applyColumnWidths(this.displayColumns, chrome);\n this.#publishChromeOffsets(chrome);\n }\n\n /** Total width (CSS px) of the leading chrome tracks; start pins stack after it. */\n #chromeWidth = 0;\n\n /**\n * Writes each leading chrome cell's sticky inline-start offset into\n * `--apex-chrome-offset-<track>` on the host (the stylesheets of the header,\n * group header and body rows read it), so the gutter, grip, checkbox and\n * chevron stay side by side during a horizontal scroll instead of all\n * sticking at 0. Every track is written, absent ones as 0, so a grid nested\n * in another grid's row never inherits its parent's offsets. Written on\n * every update, not deduped, so they come back after something replaces\n * the host's style attribute (a string style binding, setAttribute).\n */\n #publishChromeOffsets(chrome: Array<[ChromeTrack, number]>): void {\n const offsets: Record<ChromeTrack, number> = {\n 'row-number': 0,\n reorder: 0,\n selection: 0,\n expansion: 0,\n };\n let accum = 0;\n for (const [track, width] of chrome) {\n offsets[track] = accum;\n accum += width;\n }\n this.#chromeWidth = accum;\n for (const [track, offset] of Object.entries(offsets)) {\n this.host.style.setProperty(`--apex-chrome-offset-${track}`, `${offset}px`);\n }\n }\n\n public getActiveRowStyles(index: number): StyleInfo {\n const { row } = this.state.active;\n return row === index ? { 'z-index': '3' } : {};\n }\n\n /**\n * Measures the rendered widths of pinned header cells and writes cumulative\n * inline-start / inline-end pixel offsets into {@link pinOffsets}. Called after\n * each grid update and whenever a header cell is resized.\n */\n public recomputePinOffsets(): void {\n // @ts-expect-error - protected member access\n const headerRow = this.host.headerRow as\n | {\n headers?: Array<{\n column: ColumnConfiguration<T>;\n getBoundingClientRect: () => DOMRect;\n }>;\n }\n | undefined;\n if (!headerRow?.headers) return;\n\n const next = new Map<Keys<T>, number>();\n const widths = new Map<Keys<T>, number>();\n // Rects are visual px (after any ancestor transform) but the offsets are\n // applied as CSS px, so divide out the scale. Rects rather than\n // offsetWidth keep subpixel widths; offsetWidth is rounded to whole px, so\n // a difference under 1px is that rounding, not a transform.\n const host = this.host as HTMLElement;\n const visual = host.getBoundingClientRect().width;\n const layout = host.offsetWidth;\n const scale = visual && layout && Math.abs(visual - layout) >= 1 ? visual / layout : 1;\n for (const header of headerRow.headers) {\n widths.set(header.column.key as Keys<T>, header.getBoundingClientRect().width / scale);\n }\n\n // Start pins stack after the leading chrome cells, which stick first.\n let leftAccum = this.#chromeWidth;\n for (const column of this.displayColumns) {\n if (column.hidden) continue;\n if (column.pinned !== 'start') break;\n next.set(column.key as Keys<T>, leftAccum);\n leftAccum += widths.get(column.key as Keys<T>) ?? 0;\n }\n\n let rightAccum = 0;\n for (let i = this.displayColumns.length - 1; i >= 0; i--) {\n const column = this.displayColumns[i];\n if (column.hidden) continue;\n if (column.pinned !== 'end') break;\n next.set(column.key as Keys<T>, rightAccum);\n rightAccum += widths.get(column.key as Keys<T>) ?? 0;\n }\n\n if (!offsetsEqual(this.pinOffsets, next)) {\n this.pinOffsets = next;\n this.host.requestUpdate();\n }\n }\n\n protected observeHeaderCells(): void {\n // @ts-expect-error - protected member access\n const headerRow = this.host.headerRow as { headers?: Array<Element> } | undefined;\n if (!headerRow?.headers) return;\n\n if (!this.#resizeObserver) {\n this.#resizeObserver = new ResizeObserver(() => {\n // Defer to a new frame so any layout writes can't synchronously feed back\n // into this observer (which makes the browser raise the benign\n // \"ResizeObserver loop completed\" warning).\n requestAnimationFrame(() => this.recomputePinOffsets());\n });\n }\n\n const next = new Set<Element>(headerRow.headers);\n for (const element of this.#observedHeaders) {\n if (!next.has(element)) this.#resizeObserver.unobserve(element);\n }\n for (const element of next) {\n if (!this.#observedHeaders.has(element)) this.#resizeObserver.observe(element);\n }\n this.#observedHeaders = next;\n }\n\n #lastGroupTop = -1;\n #lastHeaderTop = -1;\n #lastFilterTop = -1;\n #lastPinnedTop = -1;\n #lastPinnedBottom = -1;\n #lastHostWidth = -1;\n #hostWidthObserver: ResizeObserver | null = null;\n\n /**\n * Writes the cumulative heights of the sticky chrome rows into CSS custom\n * properties used for their `inset-block-start` / `inset-block-end` offsets.\n * The toolbar is at `top: 0`; the header sits below it\n * (`--apex-row-top-header`), the filter below the header\n * (`--apex-row-top-filter`), and the pinned-top band below the filter\n * (`--apex-row-top-pinned`). The pinned-bottom band sticks above the\n * paginator (`--apex-row-bottom-pinned`). Writes are skipped when values are\n * unchanged so the ResizeObserver feedback loop terminates.\n */\n public recomputeStickyRowOffsets(): void {\n const root = (this.host as HTMLElement).shadowRoot;\n if (!root) return;\n const toolbar = root.querySelector('apex-grid-toolbar') as HTMLElement | null;\n const groupHeader = root.querySelector('apex-grid-group-header-row') as HTMLElement | null;\n const header = root.querySelector('apex-grid-header-row') as HTMLElement | null;\n const filter = root.querySelector('apex-filter-row') as HTMLElement | null;\n const paginator = root.querySelector('apex-grid-paginator') as HTMLElement | null;\n\n const toolbarH = toolbar?.offsetHeight ?? 0;\n const groupH = groupHeader?.offsetHeight ?? 0;\n const headerH = header?.offsetHeight ?? 0;\n const filterH = filter?.offsetHeight ?? 0;\n const paginatorH = paginator?.offsetHeight ?? 0;\n // The group header (when present) sits below the toolbar; the column header\n // sits below the group header; filter below header; pinned-top below filter.\n const groupTop = toolbarH;\n const headerTop = toolbarH + groupH;\n const filterTop = toolbarH + groupH + headerH;\n const pinnedTop = toolbarH + groupH + headerH + filterH;\n\n if (groupTop !== this.#lastGroupTop) {\n this.host.style.setProperty('--apex-row-top-group', `${groupTop}px`);\n this.#lastGroupTop = groupTop;\n }\n if (headerTop !== this.#lastHeaderTop) {\n this.host.style.setProperty('--apex-row-top-header', `${headerTop}px`);\n this.#lastHeaderTop = headerTop;\n }\n if (filterTop !== this.#lastFilterTop) {\n this.host.style.setProperty('--apex-row-top-filter', `${filterTop}px`);\n this.#lastFilterTop = filterTop;\n }\n if (pinnedTop !== this.#lastPinnedTop) {\n this.host.style.setProperty('--apex-row-top-pinned', `${pinnedTop}px`);\n this.#lastPinnedTop = pinnedTop;\n }\n if (paginatorH !== this.#lastPinnedBottom) {\n this.host.style.setProperty('--apex-row-bottom-pinned', `${paginatorH}px`);\n this.#lastPinnedBottom = paginatorH;\n }\n }\n\n protected observeStickyRows(): void {\n const root = (this.host as HTMLElement).shadowRoot;\n if (!root) return;\n const toolbar = root.querySelector('apex-grid-toolbar') as HTMLElement | null;\n const groupHeader = root.querySelector('apex-grid-group-header-row') as HTMLElement | null;\n const header = root.querySelector('apex-grid-header-row') as HTMLElement | null;\n const filter = root.querySelector('apex-filter-row') as HTMLElement | null;\n const paginator = root.querySelector('apex-grid-paginator') as HTMLElement | null;\n\n if (!this.#stickyRowObserver) {\n this.#stickyRowObserver = new ResizeObserver(() => {\n requestAnimationFrame(() => this.recomputeStickyRowOffsets());\n });\n }\n\n const next = new Set<Element>(\n [toolbar, groupHeader, header, filter, paginator].filter((el): el is HTMLElement => !!el)\n );\n for (const element of this.#observedStickyRows) {\n if (!next.has(element)) this.#stickyRowObserver.unobserve(element);\n }\n for (const element of next) {\n if (!this.#observedStickyRows.has(element)) this.#stickyRowObserver.observe(element);\n }\n this.#observedStickyRows = next;\n }\n}\n\nfunction offsetsEqual<K>(a: Map<K, number>, b: Map<K, number>): boolean {\n if (a.size !== b.size) return false;\n for (const [key, value] of a) {\n if (b.get(key) !== value) return false;\n }\n return true;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"dom.js","sourceRoot":"","sources":["../../src/controllers/dom.ts"],"names":[],"mappings":"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","sourcesContent":["import type { RenderItemFunction } from '@lit-labs/virtualizer/virtualize.js';\nimport { html, type ReactiveController } from 'lit';\nimport { type StyleInfo, styleMap } from 'lit/directives/style-map.js';\nimport { SENTINEL_NODE } from '../internal/constants.js';\nimport type { ActiveNode, ColumnConfiguration, GridHost, Keys } from '../internal/types.js';\nimport {\n applyColumnWidths,\n type ChromeTrack,\n getDisplayColumns,\n leadingChromeTracks,\n} from '../internal/utils.js';\nimport type { StateController } from './state.js';\n\nexport class GridDOMController<T extends object> implements ReactiveController {\n constructor(\n protected host: GridHost<T>,\n protected state: StateController<T>\n ) {\n this.host.addController(this);\n }\n\n #initialSize = () => {\n setTimeout(() => {\n this.recomputePinOffsets();\n this.recomputeStickyRowOffsets();\n });\n };\n\n #resizeObserver: ResizeObserver | null = null;\n #observedHeaders = new Set<Element>();\n #stickyRowObserver: ResizeObserver | null = null;\n #observedStickyRows = new Set<Element>();\n\n public get container() {\n // @ts-expect-error: protected member access\n return this.host.scrollContainer;\n }\n\n /**\n * Visual render order: `'start'`-pinned columns first, then unpinned, then\n * `'end'`-pinned. The user-supplied `columns` array is never mutated.\n *\n * Resolved once per host update, so a virtualizer range change between\n * updates hands the rows still in range the same array and only the rows\n * that scrolled in render. A host update resolves a new array on purpose:\n * rows read selection, expansion and the like from the state, and the new\n * array is what re-renders them.\n */\n public displayColumns: Array<ColumnConfiguration<T>> = [];\n\n public columnSizes: StyleInfo = {};\n\n /**\n * The resolved inline-start (for `'start'` pin) or inline-end (for `'end'` pin)\n * pixel offset per pinned column key. Populated after layout by\n * {@link recomputePinOffsets}.\n */\n public pinOffsets = new Map<Keys<T>, number>();\n\n /**\n * Number of chrome rows above the body for `aria-rowindex`: an optional group\n * header row and the column header (always present). The filter panel is a\n * floating overlay rather than a table row, so it is not counted here. The\n * one count behind `aria-rowcount`, the body rows and both pinned bands.\n */\n public get headerRowCount(): number {\n return this.host.columnGroupDepth + 1;\n }\n\n public rowRenderer: RenderItemFunction<T> = (data: T, index: number) => {\n const editingKey = this.#editingKey(data);\n // Body rows follow the chrome rows and any pinned-top rows in the\n // aria-rowindex sequence.\n const ariaRowOffset = this.headerRowCount + this.state.rowPin.pinnedRows.top.length;\n return html`\n <apex-grid-row\n part=\"row\"\n style=${styleMap({ ...this.columnSizes, ...this.getActiveRowStyles(index) })}\n .index=${index}\n .activeNode=${this.state.active}\n .data=${data}\n .columns=${this.displayColumns}\n .pinOffsets=${this.pinOffsets}\n .editingKey=${editingKey}\n .ariaRowOffset=${ariaRowOffset}\n .decorationVersion=${this.state.decorationVersion}\n .dataVersion=${this.state.dataVersion}\n .validationVersion=${this.state.editing.validationVersion}\n .dragging=${this.state.rowReorder.dragging === data}\n .grabbed=${this.state.rowReorder.grabbed === data}\n .coordinateHints=${Boolean(this.host.coordinateHints)}\n >\n </apex-grid-row>\n `;\n };\n\n /**\n * The column whose editor the row showing `data` renders, or `null`. Bound\n * to the edited record, never to a view index, so a view change (sort,\n * filter, paging, live data, pinning) cannot move the editor onto another\n * record.\n */\n #editingKey(data: T): Keys<T> | null {\n const editingCell = this.state.editing.activeCell;\n return editingCell && editingCell.data === data ? editingCell.columnKey : null;\n }\n\n /**\n * Renders a single pinned row for a sticky band. Reuses {@link ApexGridRow}\n * so selection / expansion / decoration / editing all work by data\n * reference, but pins a sentinel {@link ActiveNode} (pinned rows are\n * presentation, selection and pointer-edit surfaces in v1, never the\n * keyboard-active cell).\n *\n * @param localIndex - position within the band (drives the active sentinel id).\n * @param ariaRowOffset - so `aria-rowindex` continues the unified sequence.\n */\n public pinnedRowRenderer(data: T, localIndex: number, ariaRowOffset: number) {\n return html`\n <apex-grid-row\n part=\"row pinned-row\"\n style=${styleMap(this.columnSizes)}\n .index=${localIndex}\n .activeNode=${SENTINEL_NODE as ActiveNode<T>}\n .data=${data}\n .columns=${this.displayColumns}\n .pinOffsets=${this.pinOffsets}\n .editingKey=${this.#editingKey(data)}\n .ariaRowOffset=${ariaRowOffset}\n .decorationVersion=${this.state.decorationVersion}\n .dataVersion=${this.state.dataVersion}\n .validationVersion=${this.state.editing.validationVersion}\n .coordinateHints=${Boolean(this.host.coordinateHints)}\n >\n </apex-grid-row>\n `;\n }\n\n public async hostConnected() {\n this.setGridColumnSizes();\n // Wait for the initial paint of the virtualizer, then measure the pinned\n // columns and sticky rows it laid out.\n await this.host.updateComplete;\n this.#initialSize();\n if (typeof ResizeObserver !== 'undefined' && !this.#hostWidthObserver) {\n this.#hostWidthObserver = new ResizeObserver(() => {\n requestAnimationFrame(() => this.recomputeHostWidth());\n });\n this.#hostWidthObserver.observe(this.host as HTMLElement);\n }\n this.recomputeHostWidth();\n }\n\n public hostUpdate(): void {\n this.setGridColumnSizes();\n }\n\n public hostUpdated(): void {\n this.recomputePinOffsets();\n this.observeHeaderCells();\n this.recomputeStickyRowOffsets();\n this.observeStickyRows();\n }\n\n public hostDisconnected(): void {\n this.#resizeObserver?.disconnect();\n this.#resizeObserver = null;\n this.#observedHeaders.clear();\n this.#stickyRowObserver?.disconnect();\n this.#stickyRowObserver = null;\n this.#observedStickyRows.clear();\n this.#hostWidthObserver?.disconnect();\n this.#hostWidthObserver = null;\n }\n\n /**\n * Writes the grid host's `clientWidth` into `--apex-host-width`. Used by the\n * toolbar and paginator to clamp their width to the visible viewport so\n * horizontal scrolling doesn't drag them off-screen.\n */\n public recomputeHostWidth(): void {\n const host = this.host as HTMLElement;\n const width = host.clientWidth;\n if (width === this.#lastHostWidth) return;\n host.style.setProperty('--apex-host-width', `${width}px`);\n this.#lastHostWidth = width;\n }\n\n protected setGridColumnSizes() {\n this.displayColumns = getDisplayColumns(this.host.columns);\n const chrome = leadingChromeTracks(this.state);\n this.columnSizes = applyColumnWidths(this.displayColumns, chrome);\n this.#publishChromeOffsets(chrome);\n }\n\n /** Total width (CSS px) of the leading chrome tracks; start pins stack after it. */\n #chromeWidth = 0;\n\n /**\n * Writes each leading chrome cell's sticky inline-start offset into\n * `--apex-chrome-offset-<track>` on the host (the stylesheets of the header,\n * group header and body rows read it), so the gutter, grip, checkbox and\n * chevron stay side by side during a horizontal scroll instead of all\n * sticking at 0. Every track is written, absent ones as 0, so a grid nested\n * in another grid's row never inherits its parent's offsets. Written on\n * every update, not deduped, so they come back after something replaces\n * the host's style attribute (a string style binding, setAttribute).\n */\n #publishChromeOffsets(chrome: Array<[ChromeTrack, number]>): void {\n const offsets: Record<ChromeTrack, number> = {\n 'row-number': 0,\n reorder: 0,\n selection: 0,\n expansion: 0,\n };\n let accum = 0;\n for (const [track, width] of chrome) {\n offsets[track] = accum;\n accum += width;\n }\n this.#chromeWidth = accum;\n for (const [track, offset] of Object.entries(offsets)) {\n this.host.style.setProperty(`--apex-chrome-offset-${track}`, `${offset}px`);\n }\n }\n\n public getActiveRowStyles(index: number): StyleInfo {\n const { row } = this.state.active;\n return row === index ? { 'z-index': '3' } : {};\n }\n\n /**\n * Measures the rendered widths of pinned header cells and writes cumulative\n * inline-start / inline-end pixel offsets into {@link pinOffsets}. Called after\n * each grid update and whenever a header cell is resized.\n */\n public recomputePinOffsets(): void {\n // @ts-expect-error - protected member access\n const headerRow = this.host.headerRow as\n | {\n headers?: Array<{\n column: ColumnConfiguration<T>;\n getBoundingClientRect: () => DOMRect;\n }>;\n }\n | undefined;\n if (!headerRow?.headers) return;\n\n const next = new Map<Keys<T>, number>();\n const widths = new Map<Keys<T>, number>();\n // Rects are visual px (after any ancestor transform) but the offsets are\n // applied as CSS px, so divide out the scale. Rects rather than\n // offsetWidth keep subpixel widths; offsetWidth is rounded to whole px, so\n // a difference under 1px is that rounding, not a transform.\n const host = this.host as HTMLElement;\n const visual = host.getBoundingClientRect().width;\n const layout = host.offsetWidth;\n const scale = visual && layout && Math.abs(visual - layout) >= 1 ? visual / layout : 1;\n for (const header of headerRow.headers) {\n widths.set(header.column.key as Keys<T>, header.getBoundingClientRect().width / scale);\n }\n\n // Start pins stack after the leading chrome cells, which stick first.\n let leftAccum = this.#chromeWidth;\n for (const column of this.displayColumns) {\n if (column.hidden) continue;\n if (column.pinned !== 'start') break;\n next.set(column.key as Keys<T>, leftAccum);\n leftAccum += widths.get(column.key as Keys<T>) ?? 0;\n }\n\n let rightAccum = 0;\n for (let i = this.displayColumns.length - 1; i >= 0; i--) {\n const column = this.displayColumns[i];\n if (column.hidden) continue;\n if (column.pinned !== 'end') break;\n next.set(column.key as Keys<T>, rightAccum);\n rightAccum += widths.get(column.key as Keys<T>) ?? 0;\n }\n\n if (!offsetsEqual(this.pinOffsets, next)) {\n this.pinOffsets = next;\n this.host.requestUpdate();\n }\n }\n\n protected observeHeaderCells(): void {\n // @ts-expect-error - protected member access\n const headerRow = this.host.headerRow as { headers?: Array<Element> } | undefined;\n if (!headerRow?.headers) return;\n\n if (!this.#resizeObserver) {\n this.#resizeObserver = new ResizeObserver(() => {\n // Defer to a new frame so any layout writes can't synchronously feed back\n // into this observer (which makes the browser raise the benign\n // \"ResizeObserver loop completed\" warning).\n requestAnimationFrame(() => this.recomputePinOffsets());\n });\n }\n\n const next = new Set<Element>(headerRow.headers);\n for (const element of this.#observedHeaders) {\n if (!next.has(element)) this.#resizeObserver.unobserve(element);\n }\n for (const element of next) {\n if (!this.#observedHeaders.has(element)) this.#resizeObserver.observe(element);\n }\n this.#observedHeaders = next;\n }\n\n #lastGroupTop = -1;\n #lastHeaderTop = -1;\n #lastFilterTop = -1;\n #lastPinnedTop = -1;\n #lastPinnedBottom = -1;\n #lastHostWidth = -1;\n #hostWidthObserver: ResizeObserver | null = null;\n\n /**\n * Writes the cumulative heights of the sticky chrome rows into CSS custom\n * properties used for their `inset-block-start` / `inset-block-end` offsets.\n * The toolbar is at `top: 0`; the header sits below it\n * (`--apex-row-top-header`), the filter below the header\n * (`--apex-row-top-filter`), and the pinned-top band below the filter\n * (`--apex-row-top-pinned`). The pinned-bottom band sticks above the\n * paginator (`--apex-row-bottom-pinned`). Writes are skipped when values are\n * unchanged so the ResizeObserver feedback loop terminates.\n */\n public recomputeStickyRowOffsets(): void {\n const root = (this.host as HTMLElement).shadowRoot;\n if (!root) return;\n const toolbar = root.querySelector('apex-grid-toolbar') as HTMLElement | null;\n const groupHeader = root.querySelector('apex-grid-group-header-row') as HTMLElement | null;\n const header = root.querySelector('apex-grid-header-row') as HTMLElement | null;\n const filter = root.querySelector('apex-filter-row') as HTMLElement | null;\n const paginator = root.querySelector('apex-grid-paginator') as HTMLElement | null;\n\n const toolbarH = toolbar?.offsetHeight ?? 0;\n // A hidden header (`showHeader` off) is a 1px clipped row with a matching\n // negative margin: it stays for assistive technology but takes no room.\n const shown = this.host.showHeader;\n const groupH = shown ? (groupHeader?.offsetHeight ?? 0) : 0;\n const headerH = shown ? (header?.offsetHeight ?? 0) : 0;\n const filterH = filter?.offsetHeight ?? 0;\n const paginatorH = paginator?.offsetHeight ?? 0;\n // The group header (when present) sits below the toolbar; the column header\n // sits below the group header; filter below header; pinned-top below filter.\n const groupTop = toolbarH;\n const headerTop = toolbarH + groupH;\n const filterTop = toolbarH + groupH + headerH;\n const pinnedTop = toolbarH + groupH + headerH + filterH;\n\n if (groupTop !== this.#lastGroupTop) {\n this.host.style.setProperty('--apex-row-top-group', `${groupTop}px`);\n this.#lastGroupTop = groupTop;\n }\n if (headerTop !== this.#lastHeaderTop) {\n this.host.style.setProperty('--apex-row-top-header', `${headerTop}px`);\n this.#lastHeaderTop = headerTop;\n }\n if (filterTop !== this.#lastFilterTop) {\n this.host.style.setProperty('--apex-row-top-filter', `${filterTop}px`);\n this.#lastFilterTop = filterTop;\n }\n if (pinnedTop !== this.#lastPinnedTop) {\n this.host.style.setProperty('--apex-row-top-pinned', `${pinnedTop}px`);\n this.#lastPinnedTop = pinnedTop;\n }\n if (paginatorH !== this.#lastPinnedBottom) {\n this.host.style.setProperty('--apex-row-bottom-pinned', `${paginatorH}px`);\n this.#lastPinnedBottom = paginatorH;\n }\n }\n\n protected observeStickyRows(): void {\n const root = (this.host as HTMLElement).shadowRoot;\n if (!root) return;\n const toolbar = root.querySelector('apex-grid-toolbar') as HTMLElement | null;\n const groupHeader = root.querySelector('apex-grid-group-header-row') as HTMLElement | null;\n const header = root.querySelector('apex-grid-header-row') as HTMLElement | null;\n const filter = root.querySelector('apex-filter-row') as HTMLElement | null;\n const paginator = root.querySelector('apex-grid-paginator') as HTMLElement | null;\n\n if (!this.#stickyRowObserver) {\n this.#stickyRowObserver = new ResizeObserver(() => {\n requestAnimationFrame(() => this.recomputeStickyRowOffsets());\n });\n }\n\n const next = new Set<Element>(\n [toolbar, groupHeader, header, filter, paginator].filter((el): el is HTMLElement => !!el)\n );\n for (const element of this.#observedStickyRows) {\n if (!next.has(element)) this.#stickyRowObserver.unobserve(element);\n }\n for (const element of next) {\n if (!this.#observedStickyRows.has(element)) this.#stickyRowObserver.observe(element);\n }\n this.#observedStickyRows = next;\n }\n}\n\nfunction offsetsEqual<K>(a: Map<K, number>, b: Map<K, number>): boolean {\n if (a.size !== b.size) return false;\n for (const [key, value] of a) {\n if (b.get(key) !== value) return false;\n }\n return true;\n}\n"]}
|
|
@@ -77,6 +77,63 @@ export declare class NavigationController<T extends object> implements ReactiveC
|
|
|
77
77
|
get active(): ActiveNode<T>;
|
|
78
78
|
set active(node: ActiveNode<T>);
|
|
79
79
|
constructor(host: GridHost<T>);
|
|
80
|
+
/**
|
|
81
|
+
* Whether this grid's body holds focus: the body itself, one of its cells
|
|
82
|
+
* or an editor in one, not a grid nested in a detail panel. Tracked from
|
|
83
|
+
* the body's focus events ({@link focusEntered}, {@link focusLeft}). A
|
|
84
|
+
* focus loss a re-bind caused (it removed the focused editor while a
|
|
85
|
+
* reconcile is running) keeps it until that reconcile has run, so it can
|
|
86
|
+
* put focus back under row recycling. Any other loss clears it: a click
|
|
87
|
+
* elsewhere, the window losing focus, a template removing its own focused
|
|
88
|
+
* element, the grid leaving the document. Focus is never taken back once
|
|
89
|
+
* it left the grid.
|
|
90
|
+
*/
|
|
91
|
+
get ownsFocus(): boolean;
|
|
92
|
+
/**
|
|
93
|
+
* Whether focus arriving on the body itself should move on to the active
|
|
94
|
+
* cell (the roving tab stop). Not while a page change holds focus in the
|
|
95
|
+
* body, or while this controller puts it there.
|
|
96
|
+
*/
|
|
97
|
+
get forwardsBodyFocus(): boolean;
|
|
98
|
+
/**
|
|
99
|
+
* Focus arrived in the body. `owned` is whether the event is this grid's
|
|
100
|
+
* rather than a nested grid's (the grid's `ownsEvent`).
|
|
101
|
+
*/
|
|
102
|
+
focusEntered(event: FocusEvent, owned: boolean): void;
|
|
103
|
+
/**
|
|
104
|
+
* Focus left something in the body. Focus moving to another element is
|
|
105
|
+
* followed by its `focusin`, which sets {@link ownsFocus} again when that
|
|
106
|
+
* element is this body's. Focus going nowhere is a blur when the element
|
|
107
|
+
* is still in the document a microtask later, and a removal otherwise. A
|
|
108
|
+
* removal keeps {@link ownsFocus} only while a reconcile is running, which
|
|
109
|
+
* then decides; with none, nothing would repair it, so a later reconcile
|
|
110
|
+
* must not either.
|
|
111
|
+
*/
|
|
112
|
+
focusLeft(event: FocusEvent, owned: boolean): void;
|
|
113
|
+
/**
|
|
114
|
+
* Row recycling: after the rows re-render, puts focus back in the body when
|
|
115
|
+
* the render took it away. A re-bind keeps every row element in place, so
|
|
116
|
+
* focus usually stays where it was, on the cell at the active position; it
|
|
117
|
+
* is lost only when the focused element left the document (an editor whose
|
|
118
|
+
* slot now shows another record) or stands on a row that now shows another
|
|
119
|
+
* record without being active. Then focus goes to the edited record's
|
|
120
|
+
* editor when it is rendered, else the active cell when its row is, else
|
|
121
|
+
* the body. Acts only while the body owns focus, so it never takes focus
|
|
122
|
+
* back from outside the grid or off a nested grid. A loss it leaves
|
|
123
|
+
* unrepaired clears {@link ownsFocus}.
|
|
124
|
+
*/
|
|
125
|
+
reconcileFocus(): void;
|
|
126
|
+
/**
|
|
127
|
+
* Row recycling: a page change re-binds every row to the new page's
|
|
128
|
+
* records, so a focused cell would stay focused on another record. Holds
|
|
129
|
+
* focus in the body across the change: the body does not forward focus to
|
|
130
|
+
* the active cell, and the post-render reconcile waits. Returns what to
|
|
131
|
+
* call once the change has run its pipeline: focus then moves to the body
|
|
132
|
+
* unless it rests on an editor or on a cell still showing the record it
|
|
133
|
+
* showed before. Returns `null`, holding nothing, without row recycling or
|
|
134
|
+
* while the body does not own focus.
|
|
135
|
+
*/
|
|
136
|
+
parkFocus(): (() => Promise<void>) | null;
|
|
80
137
|
/**
|
|
81
138
|
* Keeps the active cell pointing at something that exists. Runs before
|
|
82
139
|
* every grid render, so after a data swap, sort, filter, page change or a
|
|
@@ -112,6 +169,11 @@ export declare class NavigationController<T extends object> implements ReactiveC
|
|
|
112
169
|
hostConnected(): void;
|
|
113
170
|
hostDisconnected(): void;
|
|
114
171
|
protected get editing(): {
|
|
172
|
+
activeCell: {
|
|
173
|
+
data: T;
|
|
174
|
+
columnKey: Keys<T>;
|
|
175
|
+
rowIndex: number;
|
|
176
|
+
} | null;
|
|
115
177
|
enabled: boolean;
|
|
116
178
|
isEditable(column: ColumnConfiguration<T>): boolean;
|
|
117
179
|
editCell(rowIndex: number, columnKey: Keys<T>): Promise<boolean>;
|
|
@@ -124,6 +186,7 @@ export declare class NavigationController<T extends object> implements ReactiveC
|
|
|
124
186
|
protected get rowReorder(): {
|
|
125
187
|
enabled: boolean;
|
|
126
188
|
isGrabbing: boolean;
|
|
189
|
+
grabbed: T | null;
|
|
127
190
|
grab(rowIndex: number): boolean;
|
|
128
191
|
moveGrabbed(direction: -1 | 1): number;
|
|
129
192
|
drop(): void;
|