@reforgium/data-grid 3.2.0 → 3.2.3
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 +28 -0
- package/README.md +18 -16
- package/fesm2022/{reforgium-data-grid-grid-overlay-scroll.feature-6tkNtIuO.mjs → reforgium-data-grid-grid-overlay-scroll.feature-DQp-sU6c.mjs} +2 -2
- package/fesm2022/{reforgium-data-grid-reforgium-data-grid-Cb2oAQjG.mjs → reforgium-data-grid-reforgium-data-grid-DUpCJ9P0.mjs} +69 -23
- package/fesm2022/reforgium-data-grid.mjs +1 -1
- package/package.json +1 -1
- package/types/reforgium-data-grid.d.ts +15 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,31 @@
|
|
|
1
|
+
## [3.2.3]: 13.05.2026
|
|
2
|
+
|
|
3
|
+
### Fix:
|
|
4
|
+
- `DataGrid`: source/infinity — `totalRowCount` no longer collapses to `0` (empty state) after the internal page buffer evicts early pages on long scrolls when the source does not return `totalElements`; row-count knowledge is now tracked via a monotonic high-water mark (`knownRowCount`) plus end-of-data state (`endReached` / `confirmedTotal`) updated when each page lands, instead of walking the eviction-bound `sourcePages` map
|
|
5
|
+
- `DataGrid`: source/infinity — buffer eviction now anchors `pageBase` and never evicts it, so `localToAbsolutePage` and contiguous-loaded-row accounting stay correct after scrolling past `MAX_BUFFERED_PAGES`
|
|
6
|
+
|
|
7
|
+
### Test:
|
|
8
|
+
- added regression coverage: monotonic `totalRowCount` without `totalElements` (optimistic probe page, fixed end after short page, post-end full page does not unwind the total), 120-page scroll past `MAX_BUFFERED_PAGES` keeps `totalRowCount` stable, and anchor page survives eviction
|
|
9
|
+
|
|
10
|
+
### Docs:
|
|
11
|
+
- `GridPagedDataSource.version`: tightened JSDoc — without `totalElements` the grid pins end-of-data on the first short/empty page, so the source must bump `version` on dataset growth/replacement to clear the pin; mutating `items()` in place without a bump leaves the grid with a stale row count
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## [3.2.1]: 17.04.2026
|
|
16
|
+
|
|
17
|
+
### Fix:
|
|
18
|
+
- `DataGrid`: source/pagination now respects exact `totalElements` when it is provided instead of collapsing paginator state to the current page payload length
|
|
19
|
+
- `DataGrid`: source/pagination without `totalElements` now exposes one optimistic extra page when the current page is full (`items.length === pageSize`), so the consumer can perform the final probe request and detect the real end on the first short/empty page
|
|
20
|
+
|
|
21
|
+
### Docs:
|
|
22
|
+
- `README`: documented `GridPagedDataSource.totalElements` behavior for source-driven pagination without a known total
|
|
23
|
+
|
|
24
|
+
### Test:
|
|
25
|
+
- added regression coverage for source/pagination with exact `totalElements` and for the full-page-without-total probe flow
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
1
29
|
## [3.2.0]: 14.04.2026
|
|
2
30
|
|
|
3
31
|
### Feat:
|
package/README.md
CHANGED
|
@@ -303,7 +303,9 @@ Data source guidance:
|
|
|
303
303
|
- Use `data` when the parent already owns the full rendered collection.
|
|
304
304
|
- Use `source` for server-driven pagination or infinity flows where the parent should expose only the current page.
|
|
305
305
|
- In `mode="infinity"` + `source`, the grid uses `totalElements` for scroll height when available and stores loaded page chunks internally instead of forcing the parent to append rows into one large array.
|
|
306
|
-
- `GridPagedDataSource.totalElements` is optional for infinity
|
|
306
|
+
- `GridPagedDataSource.totalElements` is optional for source-driven infinity and pagination flows.
|
|
307
|
+
- In `mode="infinity"`, if `totalElements` is omitted, the grid keeps requesting pages until it receives a short page (`items.length < pageSize`) and then treats that page as the end of the dataset.
|
|
308
|
+
- In `mode="pagination"`, if `totalElements` is omitted, the grid exposes one optimistic extra page while the current page is full. The final size becomes known only after a short page is returned.
|
|
307
309
|
- In `source` mode, initialize the source from the parent after all filters / params are ready; the grid does not perform an automatic first fetch on mount.
|
|
308
310
|
- `GridPagedDataSource.error` is optional and can be used by consumers that want to project source-level error UI near the grid.
|
|
309
311
|
- `GridPagedDataSource.sort`, `updateSort(...)`, and `updateSorts(...)` let the grid use source-owned sort state instead of forcing a separate parent bridge.
|
|
@@ -388,21 +390,21 @@ Notes:
|
|
|
388
390
|
|
|
389
391
|
The optional `source` input accepts a page-oriented contract:
|
|
390
392
|
|
|
391
|
-
| Field / method
|
|
392
|
-
|
|
393
|
-
| `items`
|
|
394
|
-
| `loading`
|
|
395
|
-
| `error`
|
|
396
|
-
| `page`
|
|
397
|
-
| `pageSize`
|
|
398
|
-
| `totalElements`
|
|
399
|
-
| `sort`
|
|
400
|
-
| `version`
|
|
401
|
-
| `updatePage(page)`
|
|
402
|
-
| `updatePageSize(size)` | `((size: number) => Promise<unknown>) \| undefined`
|
|
403
|
-
| `updateSort(sort)`
|
|
404
|
-
| `updateSorts(sort)`
|
|
405
|
-
| `prefetchMode`
|
|
393
|
+
| Field / method | Type | Description |
|
|
394
|
+
|------------------------|--------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
395
|
+
| `items` | `Signal<T[]>` | Current page items |
|
|
396
|
+
| `loading` | `Signal<boolean>` | Source loading state |
|
|
397
|
+
| `error` | `Signal<unknown \| null>` | Optional source error state |
|
|
398
|
+
| `page` | `number` | Current page index |
|
|
399
|
+
| `pageSize` | `number` | Current page size |
|
|
400
|
+
| `totalElements` | `number \| undefined` | Optional exact total size; if omitted, `infinity` stops on the first short page and `pagination` exposes one optimistic extra page while the current page is full |
|
|
401
|
+
| `sort` | `ReadonlyArray<GridSortItem<T>> \| undefined` | Optional source-owned sort state |
|
|
402
|
+
| `version` | `Signal<number> \| undefined` | Dataset reset marker for local buffer invalidation |
|
|
403
|
+
| `updatePage(page)` | `(page: number) => Promise<unknown>` | Load a page |
|
|
404
|
+
| `updatePageSize(size)` | `((size: number) => Promise<unknown>) \| undefined` | Optional page-size handler |
|
|
405
|
+
| `updateSort(sort)` | `((sort?: GridSortItem<T> \| null) => Promise<unknown>) \| undefined` | Optional single-sort handler |
|
|
406
|
+
| `updateSorts(sort)` | `((sort?: ReadonlyArray<GridSortItem<T>> \| null) => Promise<unknown>) \| undefined` | Optional multi-sort handler |
|
|
407
|
+
| `prefetchMode` | `'sequential' \| 'parallel' \| undefined` | Infinity prefetch strategy |
|
|
406
408
|
|
|
407
409
|
This contract is intentionally grid-like, not `statum`-specific, but `PagedQueryStore` already matches it well enough to be used directly.
|
|
408
410
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as computeScrollbarState, a as clampThumbTop, m as mapThumbTopToScrollTop } from './reforgium-data-grid-reforgium-data-grid-
|
|
1
|
+
import { c as computeScrollbarState, a as clampThumbTop, m as mapThumbTopToScrollTop } from './reforgium-data-grid-reforgium-data-grid-DUpCJ9P0.mjs';
|
|
2
2
|
|
|
3
3
|
function createGridOverlayScrollFeature(ctx) {
|
|
4
4
|
const showScrollbar = () => {
|
|
@@ -76,4 +76,4 @@ function createGridOverlayScrollFeature(ctx) {
|
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
export { createGridOverlayScrollFeature };
|
|
79
|
-
//# sourceMappingURL=reforgium-data-grid-grid-overlay-scroll.feature-
|
|
79
|
+
//# sourceMappingURL=reforgium-data-grid-grid-overlay-scroll.feature-DQp-sU6c.mjs.map
|
|
@@ -2162,6 +2162,12 @@ function createGridSourceDataFeature(ctx) {
|
|
|
2162
2162
|
let requestGeneration = 0;
|
|
2163
2163
|
let hasReceivedData = false;
|
|
2164
2164
|
let pageBase = 0;
|
|
2165
|
+
// Row knowledge accounting. Decoupled from `sourcePages` so that buffer eviction
|
|
2166
|
+
// (MAX_BUFFERED_PAGES) cannot collapse totalRowCount back to 0 once a source
|
|
2167
|
+
// without `totalElements` has scrolled past the buffer window.
|
|
2168
|
+
let knownRowCount = 0;
|
|
2169
|
+
let endReached = false;
|
|
2170
|
+
let confirmedTotal = null;
|
|
2165
2171
|
const hasSessionState = () => sourcePages.size > 0 || pendingPages.size > 0 || queuedPages.length > 0 || activeRequests > 0 || hasReceivedData;
|
|
2166
2172
|
const resolvedLoading = () => ctx.getSource()?.loading() ?? ctx.getFallbackLoading();
|
|
2167
2173
|
const totalRowCount = () => {
|
|
@@ -2177,16 +2183,19 @@ function createGridSourceDataFeature(ctx) {
|
|
|
2177
2183
|
const shiftedTotal = Math.max(0, knownTotal - pageBase * pageSize);
|
|
2178
2184
|
return shiftedTotal > 0 ? shiftedTotal : (source.items()?.length ?? 0);
|
|
2179
2185
|
}
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
return 0;
|
|
2186
|
+
if (endReached) {
|
|
2187
|
+
return confirmedTotal ?? 0;
|
|
2183
2188
|
}
|
|
2184
|
-
if (
|
|
2185
|
-
return
|
|
2189
|
+
if (knownRowCount <= 0) {
|
|
2190
|
+
return 0;
|
|
2186
2191
|
}
|
|
2187
|
-
return
|
|
2192
|
+
return knownRowCount + Math.max(1, source.pageSize || ctx.getFallbackPageSize());
|
|
2188
2193
|
}
|
|
2189
|
-
|
|
2194
|
+
const knownTotal = resolvedTotalElements(source);
|
|
2195
|
+
if (knownTotal !== null) {
|
|
2196
|
+
return knownTotal;
|
|
2197
|
+
}
|
|
2198
|
+
return estimateOpenEndedPaginationTotal(source);
|
|
2190
2199
|
};
|
|
2191
2200
|
const selectionRows = () => {
|
|
2192
2201
|
const source = ctx.getSource();
|
|
@@ -2337,7 +2346,10 @@ function createGridSourceDataFeature(ctx) {
|
|
|
2337
2346
|
}
|
|
2338
2347
|
pageBase = sourcePages.size === 0 ? Math.max(0, source.page || 0) : pageBase;
|
|
2339
2348
|
const pageItems = source.items() ?? [];
|
|
2340
|
-
|
|
2349
|
+
const sourcePage = Math.max(0, source.page || 0);
|
|
2350
|
+
const pageSize = Math.max(1, source.pageSize || ctx.getFallbackPageSize());
|
|
2351
|
+
sourcePages.set(sourcePage, pageItems);
|
|
2352
|
+
recordPageKnowledge(sourcePage, pageItems, pageSize);
|
|
2341
2353
|
if (!hasReceivedData && pageItems.length > 0) {
|
|
2342
2354
|
hasReceivedData = true;
|
|
2343
2355
|
}
|
|
@@ -2359,8 +2371,37 @@ function createGridSourceDataFeature(ctx) {
|
|
|
2359
2371
|
pendingPages.clear();
|
|
2360
2372
|
activeRequests = 0;
|
|
2361
2373
|
sourcePages.clear();
|
|
2374
|
+
knownRowCount = 0;
|
|
2375
|
+
endReached = false;
|
|
2376
|
+
confirmedTotal = null;
|
|
2362
2377
|
bufferVersion.update((current) => current + 1);
|
|
2363
2378
|
};
|
|
2379
|
+
const recordPageKnowledge = (sourcePage, pageItems, pageSize) => {
|
|
2380
|
+
if (sourcePage < pageBase) {
|
|
2381
|
+
return;
|
|
2382
|
+
}
|
|
2383
|
+
const relPage = sourcePage - pageBase;
|
|
2384
|
+
if (pageItems.length === 0) {
|
|
2385
|
+
// Empty page at or beyond the first known page implies the dataset ends here.
|
|
2386
|
+
// For the initial empty sync (relPage === 0) we stay non-committal so that a
|
|
2387
|
+
// later in-place items() update can still surface real rows.
|
|
2388
|
+
if (relPage > 0) {
|
|
2389
|
+
endReached = true;
|
|
2390
|
+
const total = relPage * pageSize;
|
|
2391
|
+
confirmedTotal = confirmedTotal === null ? total : Math.min(confirmedTotal, total);
|
|
2392
|
+
}
|
|
2393
|
+
return;
|
|
2394
|
+
}
|
|
2395
|
+
if (pageItems.length < pageSize) {
|
|
2396
|
+
endReached = true;
|
|
2397
|
+
const total = relPage * pageSize + pageItems.length;
|
|
2398
|
+
confirmedTotal = confirmedTotal === null ? total : Math.min(confirmedTotal, total);
|
|
2399
|
+
return;
|
|
2400
|
+
}
|
|
2401
|
+
if (!endReached) {
|
|
2402
|
+
knownRowCount = Math.max(knownRowCount, (relPage + 1) * pageSize);
|
|
2403
|
+
}
|
|
2404
|
+
};
|
|
2364
2405
|
const pushPage = (pages, page, maxPage) => {
|
|
2365
2406
|
if (page < 0 || page > maxPage || pages.includes(page)) {
|
|
2366
2407
|
return;
|
|
@@ -2400,7 +2441,10 @@ function createGridSourceDataFeature(ctx) {
|
|
|
2400
2441
|
// только последнюю из страниц, если несколько запросов завершились до
|
|
2401
2442
|
// того, как эффект успел выполниться, и все промежуточные страницы теряются.
|
|
2402
2443
|
if (ctx.getMode() === 'infinity' && !sourcePages.has(nextPage)) {
|
|
2403
|
-
|
|
2444
|
+
const capturedItems = activeSource.items() ?? [];
|
|
2445
|
+
const pageSize = Math.max(1, activeSource.pageSize || ctx.getFallbackPageSize());
|
|
2446
|
+
sourcePages.set(nextPage, capturedItems);
|
|
2447
|
+
recordPageKnowledge(nextPage, capturedItems, pageSize);
|
|
2404
2448
|
}
|
|
2405
2449
|
})
|
|
2406
2450
|
.finally(() => {
|
|
@@ -2427,24 +2471,20 @@ function createGridSourceDataFeature(ctx) {
|
|
|
2427
2471
|
}
|
|
2428
2472
|
return loaded;
|
|
2429
2473
|
};
|
|
2430
|
-
const hasReachedInfinityEnd = (source) => {
|
|
2431
|
-
const pageSize = Math.max(1, source.pageSize || ctx.getFallbackPageSize());
|
|
2432
|
-
let page = pageBase;
|
|
2433
|
-
while (sourcePages.has(page)) {
|
|
2434
|
-
const items = sourcePages.get(page) ?? [];
|
|
2435
|
-
if (items.length < pageSize) {
|
|
2436
|
-
return true;
|
|
2437
|
-
}
|
|
2438
|
-
page++;
|
|
2439
|
-
}
|
|
2440
|
-
return false;
|
|
2441
|
-
};
|
|
2442
2474
|
const resolvedTotalElements = (source) => {
|
|
2443
2475
|
if (typeof source.totalElements !== 'number' || !Number.isFinite(source.totalElements)) {
|
|
2444
2476
|
return null;
|
|
2445
2477
|
}
|
|
2446
2478
|
return Math.max(0, source.totalElements);
|
|
2447
2479
|
};
|
|
2480
|
+
const estimateOpenEndedPaginationTotal = (source) => {
|
|
2481
|
+
const pageSize = Math.max(1, source.pageSize || ctx.getFallbackPageSize());
|
|
2482
|
+
const page = Math.max(0, source.page || 0);
|
|
2483
|
+
const itemsCount = source.items()?.length ?? 0;
|
|
2484
|
+
const loadedBefore = page * pageSize;
|
|
2485
|
+
const hasUnknownNextPage = itemsCount === pageSize;
|
|
2486
|
+
return loadedBefore + itemsCount + (hasUnknownNextPage ? pageSize : 0);
|
|
2487
|
+
};
|
|
2448
2488
|
const evictExcessPages = (keepPages) => {
|
|
2449
2489
|
if (sourcePages.size <= MAX_BUFFERED_PAGES) {
|
|
2450
2490
|
return;
|
|
@@ -2453,6 +2493,12 @@ function createGridSourceDataFeature(ctx) {
|
|
|
2453
2493
|
if (sourcePages.size <= MAX_BUFFERED_PAGES) {
|
|
2454
2494
|
break;
|
|
2455
2495
|
}
|
|
2496
|
+
// Never evict the anchor page: `localToAbsolutePage` and the contiguous-loaded
|
|
2497
|
+
// walk both start from `pageBase`, so dropping it would cascade into wrong
|
|
2498
|
+
// request-progress numbers even though totalRowCount is now buffer-independent.
|
|
2499
|
+
if (page === pageBase) {
|
|
2500
|
+
continue;
|
|
2501
|
+
}
|
|
2456
2502
|
if (!keepPages.has(page)) {
|
|
2457
2503
|
sourcePages.delete(page);
|
|
2458
2504
|
}
|
|
@@ -4075,7 +4121,7 @@ class DataGrid {
|
|
|
4075
4121
|
if (this.overlayScrollFeaturePromise) {
|
|
4076
4122
|
return this.overlayScrollFeaturePromise;
|
|
4077
4123
|
}
|
|
4078
|
-
this.overlayScrollFeaturePromise = import('./reforgium-data-grid-grid-overlay-scroll.feature-
|
|
4124
|
+
this.overlayScrollFeaturePromise = import('./reforgium-data-grid-grid-overlay-scroll.feature-DQp-sU6c.mjs').then(({ createGridOverlayScrollFeature }) => {
|
|
4079
4125
|
const feature = createGridOverlayScrollFeature({
|
|
4080
4126
|
getScrollElement: () => this.scrollEl()?.nativeElement ?? null,
|
|
4081
4127
|
getThumbTop: () => this.vm.thumbTopPx(),
|
|
@@ -4200,4 +4246,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImpor
|
|
|
4200
4246
|
*/
|
|
4201
4247
|
|
|
4202
4248
|
export { DataGridTypeCellTemplateDirective as D, clampThumbTop as a, DataGridCellTemplateDirective as b, computeScrollbarState as c, DataGridHeaderTemplateDirective as d, DataGridRowDirective as e, DataGridDeclarativeColumn as f, DataGridDeclarativeHeaderDirective as g, DataGridDeclarativeCellDirective as h, DataGridCellEmptyDirective as i, DataGridCellLoadingDirective as j, DataGridStickyRowDirective as k, DataGridSortIconDirective as l, mapThumbTopToScrollTop as m, DataGridExpanderIconDirective as n, DATA_GRID_CONFIG as o, DATA_GRID_HEADER_TEXT_RESOLVER as p, DATA_GRID_TYPE_RENDERERS as q, DATA_GRID_TYPE_TRANSFORMERS as r, DEFAULT_DATA_GRID_DEFAULTS as s, provideDataGridDefaults as t, provideDataGridHeaderTextResolver as u, provideDataGridHeaderTextResolverWithParent as v, provideDataGridTypeRenderers as w, provideDataGridTypeTransformers as x, DataGrid as y };
|
|
4203
|
-
//# sourceMappingURL=reforgium-data-grid-reforgium-data-grid-
|
|
4249
|
+
//# sourceMappingURL=reforgium-data-grid-reforgium-data-grid-DUpCJ9P0.mjs.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { o as DATA_GRID_CONFIG, p as DATA_GRID_HEADER_TEXT_RESOLVER, q as DATA_GRID_TYPE_RENDERERS, r as DATA_GRID_TYPE_TRANSFORMERS, s as DEFAULT_DATA_GRID_DEFAULTS, y as DataGrid, i as DataGridCellEmptyDirective, j as DataGridCellLoadingDirective, b as DataGridCellTemplateDirective, h as DataGridDeclarativeCellDirective, f as DataGridDeclarativeColumn, g as DataGridDeclarativeHeaderDirective, n as DataGridExpanderIconDirective, d as DataGridHeaderTemplateDirective, e as DataGridRowDirective, l as DataGridSortIconDirective, k as DataGridStickyRowDirective, D as DataGridTypeCellTemplateDirective, t as provideDataGridDefaults, u as provideDataGridHeaderTextResolver, v as provideDataGridHeaderTextResolverWithParent, w as provideDataGridTypeRenderers, x as provideDataGridTypeTransformers } from './reforgium-data-grid-reforgium-data-grid-
|
|
1
|
+
export { o as DATA_GRID_CONFIG, p as DATA_GRID_HEADER_TEXT_RESOLVER, q as DATA_GRID_TYPE_RENDERERS, r as DATA_GRID_TYPE_TRANSFORMERS, s as DEFAULT_DATA_GRID_DEFAULTS, y as DataGrid, i as DataGridCellEmptyDirective, j as DataGridCellLoadingDirective, b as DataGridCellTemplateDirective, h as DataGridDeclarativeCellDirective, f as DataGridDeclarativeColumn, g as DataGridDeclarativeHeaderDirective, n as DataGridExpanderIconDirective, d as DataGridHeaderTemplateDirective, e as DataGridRowDirective, l as DataGridSortIconDirective, k as DataGridStickyRowDirective, D as DataGridTypeCellTemplateDirective, t as provideDataGridDefaults, u as provideDataGridHeaderTextResolver, v as provideDataGridHeaderTextResolverWithParent, w as provideDataGridTypeRenderers, x as provideDataGridTypeTransformers } from './reforgium-data-grid-reforgium-data-grid-DUpCJ9P0.mjs';
|
|
2
2
|
//# sourceMappingURL=reforgium-data-grid.mjs.map
|
package/package.json
CHANGED
|
@@ -759,11 +759,23 @@ interface GridPagedDataSource<Data extends AnyDict = AnyDict> {
|
|
|
759
759
|
/**
|
|
760
760
|
* Total number of rows available in the dataset.
|
|
761
761
|
*
|
|
762
|
-
* Optional in infinity mode.
|
|
763
|
-
*
|
|
762
|
+
* Optional in source-driven pagination/infinity mode.
|
|
763
|
+
*
|
|
764
|
+
* - In `infinity`, the grid treats the dataset as open-ended until it receives
|
|
765
|
+
* a short page (`items.length < pageSize`) and then fixes the final size.
|
|
766
|
+
* - In `pagination`, the grid exposes one optimistic extra page while the current
|
|
767
|
+
* page is full, because without `totalElements` the end can only be detected
|
|
768
|
+
* after the next request returns a short page.
|
|
764
769
|
*/
|
|
765
770
|
totalElements?: number;
|
|
766
|
-
/**
|
|
771
|
+
/**
|
|
772
|
+
* Optional dataset revision signal. Increment to force the grid to clear its local page buffer.
|
|
773
|
+
*
|
|
774
|
+
* Required (when present) to be incremented on any dataset growth, replacement, or filter/sort change:
|
|
775
|
+
* in `infinity` mode without `totalElements` the grid pins end-of-data state on the first short/empty
|
|
776
|
+
* page it sees, and only a version bump clears that pin. Mutating `items()` in place without bumping
|
|
777
|
+
* `version` will leave the grid with a stale row count.
|
|
778
|
+
*/
|
|
767
779
|
version?: Signal<number>;
|
|
768
780
|
/** Current source-side sort state. */
|
|
769
781
|
sort?: ReadonlyArray<GridSortItem<Data>>;
|