@alaarab/ogrid-angular 2.1.15 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/esm/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { flattenColumns, getMultiSelectFilterFields, deriveFilterOptionsFromData, processClientSideData, validateColumns, validateRowIds, computeNextSortState, mergeFilter, CHECKBOX_COLUMN_WIDTH, DEFAULT_MIN_COLUMN_WIDTH, CELL_PADDING, parseValue, UndoRedoStack, rangesEqual, normalizeSelectionRange, formatSelectionAsTsv, parseTsvClipboard, getCellValue, computeTabNavigation, applyFillValues, computeAggregations, getDataGridStatusBarConfig, computeVisibleRange, computeTotalHeight, getScrollTopForRow, validateVirtualScrollConfig, GRID_BORDER_RADIUS, getStatusBarParts, GRID_CONTEXT_MENU_ITEMS, formatShortcut, injectGlobalStyles, buildHeaderRows, getHeaderFilterConfig, getCellRenderDescriptor, resolveCellDisplayContent, resolveCellStyle, buildPopoverEditorProps, measureColumnContentWidth, getPaginationViewModel, ROW_NUMBER_COLUMN_WIDTH, reorderColumnArray, findCtrlArrowTarget, measureRange } from '@alaarab/ogrid-core';
|
|
1
|
+
import { flattenColumns, getMultiSelectFilterFields, deriveFilterOptionsFromData, processClientSideData, validateColumns, processClientSideDataAsync, validateRowIds, computeNextSortState, mergeFilter, CHECKBOX_COLUMN_WIDTH, DEFAULT_MIN_COLUMN_WIDTH, CELL_PADDING, parseValue, UndoRedoStack, rangesEqual, normalizeSelectionRange, formatSelectionAsTsv, parseTsvClipboard, getCellValue, computeTabNavigation, applyFillValues, computeAggregations, getDataGridStatusBarConfig, computeVisibleRange, computeTotalHeight, computeVisibleColumnRange, getScrollTopForRow, validateVirtualScrollConfig, GRID_BORDER_RADIUS, getStatusBarParts, GRID_CONTEXT_MENU_ITEMS, formatShortcut, injectGlobalStyles, partitionColumnsForVirtualization, buildHeaderRows, getHeaderFilterConfig, getCellRenderDescriptor, resolveCellDisplayContent, resolveCellStyle, buildPopoverEditorProps, measureColumnContentWidth, getPaginationViewModel, ROW_NUMBER_COLUMN_WIDTH, reorderColumnArray, findCtrlArrowTarget, measureRange } from '@alaarab/ogrid-core';
|
|
2
2
|
export * from '@alaarab/ogrid-core';
|
|
3
3
|
export { CELL_PADDING, CHECKBOX_COLUMN_WIDTH, DEFAULT_DEBOUNCE_MS, DEFAULT_MIN_COLUMN_WIDTH, GRID_BORDER_RADIUS, PEOPLE_SEARCH_DEBOUNCE_MS, ROW_NUMBER_COLUMN_WIDTH, SIDEBAR_TRANSITION_MS, Z_INDEX, debounce, getCellRenderDescriptor, getHeaderFilterConfig, isInSelectionRange, normalizeSelectionRange, resolveCellDisplayContent, resolveCellStyle, toUserLike } from '@alaarab/ogrid-core';
|
|
4
4
|
import { Injectable, Input, Component, ChangeDetectionStrategy, ViewEncapsulation, Output, ViewChild, inject, DestroyRef, signal, computed, effect, NgZone, EventEmitter, Injector, EnvironmentInjector, createComponent } from '@angular/core';
|
|
@@ -75,6 +75,7 @@ var OGridService = class {
|
|
|
75
75
|
this.virtualScroll = signal(void 0);
|
|
76
76
|
this.ariaLabel = signal(void 0);
|
|
77
77
|
this.ariaLabelledBy = signal(void 0);
|
|
78
|
+
this.workerSort = signal(false);
|
|
78
79
|
// --- Internal state signals ---
|
|
79
80
|
this.internalData = signal([]);
|
|
80
81
|
this.internalLoading = signal(false);
|
|
@@ -94,6 +95,9 @@ var OGridService = class {
|
|
|
94
95
|
this.filterAbortController = null;
|
|
95
96
|
this.refreshCounter = signal(0);
|
|
96
97
|
this.firstDataRendered = signal(false);
|
|
98
|
+
// Worker sort async state
|
|
99
|
+
this.asyncClientItems = signal(null);
|
|
100
|
+
this.workerSortAbortId = 0;
|
|
97
101
|
// Side bar state
|
|
98
102
|
this.sideBarActivePanel = signal(null);
|
|
99
103
|
// Filter options state
|
|
@@ -134,8 +138,9 @@ var OGridService = class {
|
|
|
134
138
|
if (this.hasServerFilterOptions()) return this.serverFilterOptions();
|
|
135
139
|
return deriveFilterOptionsFromData(this.displayData(), this.columns());
|
|
136
140
|
});
|
|
141
|
+
/** Sync path: used when workerSort is off. */
|
|
137
142
|
this.clientItemsAndTotal = computed(() => {
|
|
138
|
-
if (!this.isClientSide()) return null;
|
|
143
|
+
if (!this.isClientSide() || this.workerSort()) return null;
|
|
139
144
|
const rows = processClientSideData(
|
|
140
145
|
this.displayData(),
|
|
141
146
|
this.columns(),
|
|
@@ -148,12 +153,18 @@ var OGridService = class {
|
|
|
148
153
|
const paged = rows.slice(start, start + this.pageSize());
|
|
149
154
|
return { items: paged, totalCount: total };
|
|
150
155
|
});
|
|
156
|
+
/** Resolved client items — sync or async depending on workerSort. */
|
|
157
|
+
this.resolvedClientItems = computed(() => {
|
|
158
|
+
const syncResult = this.clientItemsAndTotal();
|
|
159
|
+
if (syncResult) return syncResult;
|
|
160
|
+
return this.asyncClientItems();
|
|
161
|
+
});
|
|
151
162
|
this.displayItems = computed(() => {
|
|
152
|
-
const cit = this.
|
|
163
|
+
const cit = this.resolvedClientItems();
|
|
153
164
|
return this.isClientSide() && cit ? cit.items : this.serverItems();
|
|
154
165
|
});
|
|
155
166
|
this.displayTotalCount = computed(() => {
|
|
156
|
-
const cit = this.
|
|
167
|
+
const cit = this.resolvedClientItems();
|
|
157
168
|
return this.isClientSide() && cit ? cit.totalCount : this.serverTotalCount();
|
|
158
169
|
});
|
|
159
170
|
this.hasActiveFilters = computed(() => {
|
|
@@ -323,6 +334,34 @@ var OGridService = class {
|
|
|
323
334
|
validateColumns(cols);
|
|
324
335
|
}
|
|
325
336
|
});
|
|
337
|
+
effect((onCleanup) => {
|
|
338
|
+
if (!this.isClientSide() || !this.workerSort()) return;
|
|
339
|
+
const data = this.displayData();
|
|
340
|
+
const cols = this.columns();
|
|
341
|
+
const filters = this.filters();
|
|
342
|
+
const sortField = this.sort().field;
|
|
343
|
+
const sortDir = this.sort().direction;
|
|
344
|
+
const page = this.page();
|
|
345
|
+
const ps = this.pageSize();
|
|
346
|
+
const abortId = ++this.workerSortAbortId;
|
|
347
|
+
processClientSideDataAsync(data, cols, filters, sortField, sortDir).then((rows) => {
|
|
348
|
+
if (abortId !== this.workerSortAbortId) return;
|
|
349
|
+
const total = rows.length;
|
|
350
|
+
const start = (page - 1) * ps;
|
|
351
|
+
const paged = rows.slice(start, start + ps);
|
|
352
|
+
this.asyncClientItems.set({ items: paged, totalCount: total });
|
|
353
|
+
}).catch(() => {
|
|
354
|
+
if (abortId !== this.workerSortAbortId) return;
|
|
355
|
+
const rows = processClientSideData(data, cols, filters, sortField, sortDir);
|
|
356
|
+
const total = rows.length;
|
|
357
|
+
const start = (page - 1) * ps;
|
|
358
|
+
const paged = rows.slice(start, start + ps);
|
|
359
|
+
this.asyncClientItems.set({ items: paged, totalCount: total });
|
|
360
|
+
});
|
|
361
|
+
onCleanup(() => {
|
|
362
|
+
this.workerSortAbortId++;
|
|
363
|
+
});
|
|
364
|
+
});
|
|
326
365
|
effect((onCleanup) => {
|
|
327
366
|
const ds = this.dataSource();
|
|
328
367
|
if (!this.isServerSide() || !ds) {
|
|
@@ -486,6 +525,13 @@ var OGridService = class {
|
|
|
486
525
|
// --- Configure from props ---
|
|
487
526
|
configure(props) {
|
|
488
527
|
this.columnsProp.set(props.columns);
|
|
528
|
+
if (Object.keys(this.pinnedOverrides()).length === 0) {
|
|
529
|
+
const initial = {};
|
|
530
|
+
for (const col of flattenColumns(props.columns)) {
|
|
531
|
+
if (col.pinned) initial[col.columnId] = col.pinned;
|
|
532
|
+
}
|
|
533
|
+
if (Object.keys(initial).length > 0) this.pinnedOverrides.set(initial);
|
|
534
|
+
}
|
|
489
535
|
this.getRowId.set(props.getRowId);
|
|
490
536
|
if ("data" in props && props.data !== void 0) this.data.set(props.data);
|
|
491
537
|
if ("dataSource" in props && props.dataSource !== void 0) this.dataSource.set(props.dataSource);
|
|
@@ -528,6 +574,7 @@ var OGridService = class {
|
|
|
528
574
|
if (props.columnChooser !== void 0) this.columnChooserProp.set(props.columnChooser);
|
|
529
575
|
if (props.columnReorder !== void 0) this.columnReorder.set(props.columnReorder);
|
|
530
576
|
if (props.virtualScroll !== void 0) this.virtualScroll.set(props.virtualScroll);
|
|
577
|
+
if (props.workerSort !== void 0) this.workerSort.set(props.workerSort);
|
|
531
578
|
if (props.entityLabelPlural !== void 0) this.entityLabelPlural.set(props.entityLabelPlural);
|
|
532
579
|
if (props.className !== void 0) this.className.set(props.className);
|
|
533
580
|
if (props.layoutMode !== void 0) this.layoutMode.set(props.layoutMode);
|
|
@@ -2229,6 +2276,10 @@ var VirtualScrollService = class {
|
|
|
2229
2276
|
this.containerHeight = signal(0);
|
|
2230
2277
|
// --- Internal state ---
|
|
2231
2278
|
this.scrollTop = signal(0);
|
|
2279
|
+
this.scrollLeft = signal(0);
|
|
2280
|
+
// --- Column virtualization inputs ---
|
|
2281
|
+
this.columnWidths = signal([]);
|
|
2282
|
+
this.containerWidth = signal(0);
|
|
2232
2283
|
// Scrollable container reference for programmatic scrolling
|
|
2233
2284
|
this.containerEl = null;
|
|
2234
2285
|
// --- Derived computed signals ---
|
|
@@ -2258,6 +2309,21 @@ var VirtualScrollService = class {
|
|
|
2258
2309
|
});
|
|
2259
2310
|
/** Total scrollable height in pixels. */
|
|
2260
2311
|
this.totalHeight = computed(() => computeTotalHeight(this.totalRows(), this.rowHeight()));
|
|
2312
|
+
// --- Column virtualization ---
|
|
2313
|
+
this.columnsEnabled = computed(() => this.config().columns === true);
|
|
2314
|
+
this.columnOverscan = computed(() => this.config().columnOverscan ?? 2);
|
|
2315
|
+
/** The visible column range with spacer widths, or null when column virtualization is off. */
|
|
2316
|
+
this.columnRange = computed(() => {
|
|
2317
|
+
if (!this.columnsEnabled()) return null;
|
|
2318
|
+
const widths = this.columnWidths();
|
|
2319
|
+
if (widths.length === 0) return null;
|
|
2320
|
+
return computeVisibleColumnRange(
|
|
2321
|
+
this.scrollLeft(),
|
|
2322
|
+
widths,
|
|
2323
|
+
this.containerWidth(),
|
|
2324
|
+
this.columnOverscan()
|
|
2325
|
+
);
|
|
2326
|
+
});
|
|
2261
2327
|
this.destroyRef.onDestroy(() => {
|
|
2262
2328
|
this.containerEl = null;
|
|
2263
2329
|
});
|
|
@@ -2271,10 +2337,12 @@ var VirtualScrollService = class {
|
|
|
2271
2337
|
}
|
|
2272
2338
|
/**
|
|
2273
2339
|
* Call this from the container's scroll event handler.
|
|
2340
|
+
* Tracks both vertical and horizontal scroll positions.
|
|
2274
2341
|
*/
|
|
2275
2342
|
onScroll(event) {
|
|
2276
2343
|
const target = event.target;
|
|
2277
2344
|
this.scrollTop.set(target.scrollTop);
|
|
2345
|
+
this.scrollLeft.set(target.scrollLeft);
|
|
2278
2346
|
}
|
|
2279
2347
|
/**
|
|
2280
2348
|
* Scroll to a specific row index.
|
|
@@ -3404,6 +3472,53 @@ var BaseDataGridTableComponent = class {
|
|
|
3404
3472
|
if (!this.vsEnabled()) return 0;
|
|
3405
3473
|
return this.vsVisibleRange().startIndex;
|
|
3406
3474
|
});
|
|
3475
|
+
// Column virtualization
|
|
3476
|
+
this.vsColumnsEnabled = computed(() => this.virtualScrollService.columnsEnabled());
|
|
3477
|
+
this.vsColumnRange = computed(() => this.virtualScrollService.columnRange());
|
|
3478
|
+
/** Partitioned columns for column virtualization: pinned-left, virtualized-unpinned, pinned-right, with spacer widths. */
|
|
3479
|
+
this.vsColumnPartition = computed(() => {
|
|
3480
|
+
if (!this.vsColumnsEnabled()) return null;
|
|
3481
|
+
const cols = this.visibleCols();
|
|
3482
|
+
const range = this.vsColumnRange();
|
|
3483
|
+
const props = this.getProps();
|
|
3484
|
+
const pinnedCols = props?.pinnedColumns;
|
|
3485
|
+
return partitionColumnsForVirtualization(cols, range, pinnedCols);
|
|
3486
|
+
});
|
|
3487
|
+
/** Column layouts filtered by column virtualization range (or all if column virt is off). */
|
|
3488
|
+
this.vsColumnLayouts = computed(() => {
|
|
3489
|
+
const allLayouts = this.columnLayouts();
|
|
3490
|
+
const partition = this.vsColumnPartition();
|
|
3491
|
+
if (!partition) return allLayouts;
|
|
3492
|
+
const visibleIds = /* @__PURE__ */ new Set();
|
|
3493
|
+
for (const col of partition.pinnedLeft) visibleIds.add(col.columnId);
|
|
3494
|
+
for (const col of partition.virtualizedUnpinned) visibleIds.add(col.columnId);
|
|
3495
|
+
for (const col of partition.pinnedRight) visibleIds.add(col.columnId);
|
|
3496
|
+
return allLayouts.filter((layout) => visibleIds.has(layout.col.columnId));
|
|
3497
|
+
});
|
|
3498
|
+
/** Visible columns filtered by column virtualization range (or all if column virt is off). */
|
|
3499
|
+
this.vsVisibleCols = computed(() => {
|
|
3500
|
+
const allCols = this.visibleCols();
|
|
3501
|
+
const partition = this.vsColumnPartition();
|
|
3502
|
+
if (!partition) return allCols;
|
|
3503
|
+
const visibleIds = /* @__PURE__ */ new Set();
|
|
3504
|
+
for (const col of partition.pinnedLeft) visibleIds.add(col.columnId);
|
|
3505
|
+
for (const col of partition.virtualizedUnpinned) visibleIds.add(col.columnId);
|
|
3506
|
+
for (const col of partition.pinnedRight) visibleIds.add(col.columnId);
|
|
3507
|
+
return allCols.filter((col) => visibleIds.has(col.columnId));
|
|
3508
|
+
});
|
|
3509
|
+
/** Left spacer width for column virtualization (in pixels). */
|
|
3510
|
+
this.vsLeftSpacerWidth = computed(() => this.vsColumnPartition()?.leftSpacerWidth ?? 0);
|
|
3511
|
+
/** Right spacer width for column virtualization (in pixels). */
|
|
3512
|
+
this.vsRightSpacerWidth = computed(() => this.vsColumnPartition()?.rightSpacerWidth ?? 0);
|
|
3513
|
+
/** Map from columnId to its global index in visibleCols. Used to maintain correct colIdx for cell descriptors during column virtualization. */
|
|
3514
|
+
this.globalColIndexMap = computed(() => {
|
|
3515
|
+
const cols = this.visibleCols();
|
|
3516
|
+
const map = /* @__PURE__ */ new Map();
|
|
3517
|
+
for (let i = 0; i < cols.length; i++) {
|
|
3518
|
+
map.set(cols[i].columnId, i);
|
|
3519
|
+
}
|
|
3520
|
+
return map;
|
|
3521
|
+
});
|
|
3407
3522
|
// Popover editing
|
|
3408
3523
|
this.popoverAnchorEl = computed(() => this.editingState().popoverAnchorEl);
|
|
3409
3524
|
this.pendingEditorValueForPopover = computed(() => this.editingState().pendingEditorValue);
|
|
@@ -3527,6 +3642,10 @@ var BaseDataGridTableComponent = class {
|
|
|
3527
3642
|
this.measuredColumnWidths.set(measured);
|
|
3528
3643
|
}
|
|
3529
3644
|
}
|
|
3645
|
+
/** Get global column index for a column (correct even during column virtualization). */
|
|
3646
|
+
getGlobalColIndex(col) {
|
|
3647
|
+
return this.globalColIndexMap().get(col.columnId) ?? 0;
|
|
3648
|
+
}
|
|
3530
3649
|
/**
|
|
3531
3650
|
* Initialize base wiring effects. Must be called from subclass constructor.
|
|
3532
3651
|
*
|
|
@@ -3577,16 +3696,26 @@ var BaseDataGridTableComponent = class {
|
|
|
3577
3696
|
this.virtualScrollService.updateConfig({
|
|
3578
3697
|
enabled: p.virtualScroll.enabled,
|
|
3579
3698
|
rowHeight: p.virtualScroll.rowHeight,
|
|
3580
|
-
overscan: p.virtualScroll.overscan
|
|
3699
|
+
overscan: p.virtualScroll.overscan,
|
|
3700
|
+
columns: p.virtualScroll.columns,
|
|
3701
|
+
columnOverscan: p.virtualScroll.columnOverscan
|
|
3581
3702
|
});
|
|
3582
3703
|
}
|
|
3583
3704
|
}
|
|
3584
3705
|
});
|
|
3706
|
+
effect(() => {
|
|
3707
|
+
const layouts = this.columnLayouts();
|
|
3708
|
+
const props = this.getProps();
|
|
3709
|
+
const pinnedCols = props?.pinnedColumns ?? {};
|
|
3710
|
+
const unpinnedWidths = layouts.filter((l) => !l.pinnedLeft && !l.pinnedRight && !pinnedCols[l.col.columnId]).map((l) => l.width);
|
|
3711
|
+
this.virtualScrollService.columnWidths.set(unpinnedWidths);
|
|
3712
|
+
});
|
|
3585
3713
|
effect(() => {
|
|
3586
3714
|
const el = this.wrapperElSignal();
|
|
3587
3715
|
if (el) {
|
|
3588
3716
|
this.virtualScrollService.setContainer(el);
|
|
3589
3717
|
this.virtualScrollService.containerHeight.set(el.clientHeight);
|
|
3718
|
+
this.virtualScrollService.containerWidth.set(el.clientWidth);
|
|
3590
3719
|
}
|
|
3591
3720
|
});
|
|
3592
3721
|
}
|
|
@@ -134,6 +134,34 @@ export declare abstract class BaseDataGridTableComponent<T = unknown> {
|
|
|
134
134
|
readonly vsBottomSpacerHeight: import("@angular/core").Signal<number>;
|
|
135
135
|
readonly vsVisibleItems: import("@angular/core").Signal<T[]>;
|
|
136
136
|
readonly vsStartIndex: import("@angular/core").Signal<number>;
|
|
137
|
+
readonly vsColumnsEnabled: import("@angular/core").Signal<boolean>;
|
|
138
|
+
readonly vsColumnRange: import("@angular/core").Signal<import("@alaarab/ogrid-core").IVisibleColumnRange | null>;
|
|
139
|
+
/** Partitioned columns for column virtualization: pinned-left, virtualized-unpinned, pinned-right, with spacer widths. */
|
|
140
|
+
readonly vsColumnPartition: import("@angular/core").Signal<{
|
|
141
|
+
pinnedLeft: import("@alaarab/ogrid-core").IColumnDef<T>[];
|
|
142
|
+
virtualizedUnpinned: import("@alaarab/ogrid-core").IColumnDef<T>[];
|
|
143
|
+
pinnedRight: import("@alaarab/ogrid-core").IColumnDef<T>[];
|
|
144
|
+
leftSpacerWidth: number;
|
|
145
|
+
rightSpacerWidth: number;
|
|
146
|
+
} | null>;
|
|
147
|
+
/** Column layouts filtered by column virtualization range (or all if column virt is off). */
|
|
148
|
+
readonly vsColumnLayouts: import("@angular/core").Signal<{
|
|
149
|
+
col: IColumnDef<T>;
|
|
150
|
+
pinnedLeft: boolean;
|
|
151
|
+
pinnedRight: boolean;
|
|
152
|
+
minWidth: number;
|
|
153
|
+
width: number;
|
|
154
|
+
}[]>;
|
|
155
|
+
/** Visible columns filtered by column virtualization range (or all if column virt is off). */
|
|
156
|
+
readonly vsVisibleCols: import("@angular/core").Signal<IColumnDef<T>[]>;
|
|
157
|
+
/** Left spacer width for column virtualization (in pixels). */
|
|
158
|
+
readonly vsLeftSpacerWidth: import("@angular/core").Signal<number>;
|
|
159
|
+
/** Right spacer width for column virtualization (in pixels). */
|
|
160
|
+
readonly vsRightSpacerWidth: import("@angular/core").Signal<number>;
|
|
161
|
+
/** Map from columnId to its global index in visibleCols. Used to maintain correct colIdx for cell descriptors during column virtualization. */
|
|
162
|
+
readonly globalColIndexMap: import("@angular/core").Signal<Map<string, number>>;
|
|
163
|
+
/** Get global column index for a column (correct even during column virtualization). */
|
|
164
|
+
getGlobalColIndex(col: IColumnDef<T>): number;
|
|
137
165
|
readonly popoverAnchorEl: import("@angular/core").Signal<HTMLElement | null>;
|
|
138
166
|
readonly pendingEditorValueForPopover: import("@angular/core").Signal<unknown>;
|
|
139
167
|
readonly allowOverflowX: import("@angular/core").Signal<boolean>;
|
|
@@ -108,6 +108,7 @@ export declare class OGridService<T> {
|
|
|
108
108
|
readonly virtualScroll: import("@angular/core").WritableSignal<IVirtualScrollConfig | undefined>;
|
|
109
109
|
readonly ariaLabel: import("@angular/core").WritableSignal<string | undefined>;
|
|
110
110
|
readonly ariaLabelledBy: import("@angular/core").WritableSignal<string | undefined>;
|
|
111
|
+
readonly workerSort: import("@angular/core").WritableSignal<boolean>;
|
|
111
112
|
private readonly internalData;
|
|
112
113
|
private readonly internalLoading;
|
|
113
114
|
private readonly internalPage;
|
|
@@ -125,6 +126,8 @@ export declare class OGridService<T> {
|
|
|
125
126
|
private filterAbortController;
|
|
126
127
|
private readonly refreshCounter;
|
|
127
128
|
private readonly firstDataRendered;
|
|
129
|
+
private readonly asyncClientItems;
|
|
130
|
+
private workerSortAbortId;
|
|
128
131
|
private readonly sideBarActivePanel;
|
|
129
132
|
private readonly serverFilterOptions;
|
|
130
133
|
private readonly loadingFilterOptions;
|
|
@@ -147,10 +150,16 @@ export declare class OGridService<T> {
|
|
|
147
150
|
readonly multiSelectFilterFields: import("@angular/core").Signal<string[]>;
|
|
148
151
|
readonly hasServerFilterOptions: import("@angular/core").Signal<boolean>;
|
|
149
152
|
readonly clientFilterOptions: import("@angular/core").Signal<Record<string, string[]>>;
|
|
153
|
+
/** Sync path: used when workerSort is off. */
|
|
150
154
|
readonly clientItemsAndTotal: import("@angular/core").Signal<{
|
|
151
155
|
items: T[];
|
|
152
156
|
totalCount: number;
|
|
153
157
|
} | null>;
|
|
158
|
+
/** Resolved client items — sync or async depending on workerSort. */
|
|
159
|
+
readonly resolvedClientItems: import("@angular/core").Signal<{
|
|
160
|
+
items: T[];
|
|
161
|
+
totalCount: number;
|
|
162
|
+
} | null>;
|
|
154
163
|
readonly displayItems: import("@angular/core").Signal<T[]>;
|
|
155
164
|
readonly displayTotalCount: import("@angular/core").Signal<number>;
|
|
156
165
|
readonly hasActiveFilters: import("@angular/core").Signal<boolean>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { IVisibleRange, IVirtualScrollConfig } from '@alaarab/ogrid-core';
|
|
1
|
+
import type { IVisibleRange, IVisibleColumnRange, IVirtualScrollConfig } from '@alaarab/ogrid-core';
|
|
2
2
|
/**
|
|
3
3
|
* Manages virtual scrolling state using Angular signals.
|
|
4
4
|
* Port of React's useVirtualScroll hook.
|
|
@@ -13,6 +13,9 @@ export declare class VirtualScrollService {
|
|
|
13
13
|
readonly config: import("@angular/core").WritableSignal<IVirtualScrollConfig>;
|
|
14
14
|
readonly containerHeight: import("@angular/core").WritableSignal<number>;
|
|
15
15
|
readonly scrollTop: import("@angular/core").WritableSignal<number>;
|
|
16
|
+
readonly scrollLeft: import("@angular/core").WritableSignal<number>;
|
|
17
|
+
readonly columnWidths: import("@angular/core").WritableSignal<number[]>;
|
|
18
|
+
readonly containerWidth: import("@angular/core").WritableSignal<number>;
|
|
16
19
|
private containerEl;
|
|
17
20
|
readonly rowHeight: import("@angular/core").Signal<number>;
|
|
18
21
|
readonly overscan: import("@angular/core").Signal<number>;
|
|
@@ -24,6 +27,10 @@ export declare class VirtualScrollService {
|
|
|
24
27
|
readonly visibleRange: import("@angular/core").Signal<IVisibleRange>;
|
|
25
28
|
/** Total scrollable height in pixels. */
|
|
26
29
|
readonly totalHeight: import("@angular/core").Signal<number>;
|
|
30
|
+
readonly columnsEnabled: import("@angular/core").Signal<boolean>;
|
|
31
|
+
readonly columnOverscan: import("@angular/core").Signal<number>;
|
|
32
|
+
/** The visible column range with spacer widths, or null when column virtualization is off. */
|
|
33
|
+
readonly columnRange: import("@angular/core").Signal<IVisibleColumnRange | null>;
|
|
27
34
|
constructor();
|
|
28
35
|
/**
|
|
29
36
|
* Set the scrollable container element.
|
|
@@ -32,6 +39,7 @@ export declare class VirtualScrollService {
|
|
|
32
39
|
setContainer(el: HTMLElement | null): void;
|
|
33
40
|
/**
|
|
34
41
|
* Call this from the container's scroll event handler.
|
|
42
|
+
* Tracks both vertical and horizontal scroll positions.
|
|
35
43
|
*/
|
|
36
44
|
onScroll(event: Event): void;
|
|
37
45
|
/**
|
|
@@ -63,6 +63,8 @@ interface IOGridBaseProps<T> {
|
|
|
63
63
|
sideBar?: boolean | ISideBarDef;
|
|
64
64
|
columnReorder?: boolean;
|
|
65
65
|
virtualScroll?: IVirtualScrollConfig;
|
|
66
|
+
/** Offload sort/filter to a Web Worker for large datasets. Falls back to sync when sort column has a custom compare. */
|
|
67
|
+
workerSort?: boolean;
|
|
66
68
|
/** Fixed row height in pixels. Overrides default row height (36px). */
|
|
67
69
|
rowHeight?: number;
|
|
68
70
|
pageSizeOptions?: number[];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alaarab/ogrid-angular",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "OGrid Angular – Angular services, signals, and headless components for OGrid data grids.",
|
|
5
5
|
"main": "dist/esm/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"node": ">=18"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@alaarab/ogrid-core": "2.
|
|
38
|
+
"@alaarab/ogrid-core": "2.2.0"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
41
41
|
"@angular/core": "^21.0.0",
|