@alaarab/ogrid-vue 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 { injectGlobalStyles, Z_INDEX, getStatusBarParts, measureRange, flattenColumns, getMultiSelectFilterFields, deriveFilterOptionsFromData, processClientSideData, validateColumns, validateRowIds, computeRowSelectionState, buildCellIndex, UndoRedoStack, CHECKBOX_COLUMN_WIDTH, DEFAULT_MIN_COLUMN_WIDTH, CELL_PADDING, computeAggregations, getDataGridStatusBarConfig, validateVirtualScrollConfig, computeVisibleRange, computeTotalHeight, buildHeaderRows, ROW_NUMBER_COLUMN_WIDTH, getHeaderFilterConfig, getCellRenderDescriptor, buildInlineEditorProps, buildPopoverEditorProps, resolveCellDisplayContent, resolveCellStyle, rangesEqual, normalizeSelectionRange, formatSelectionAsTsv, parseTsvClipboard, applyPastedValues, applyCutClear, measureColumnContentWidth, getPinStateForColumn, parseValue, applyFillValues, applyCellDeletion, computeTabNavigation, computeArrowNavigation, computeNextSortState, mergeFilter, applyRangeRowSelection, getScrollTopForRow, getCellValue, calculateDropTarget, reorderColumnArray, computeAutoScrollSpeed } from '@alaarab/ogrid-core';
|
|
1
|
+
import { injectGlobalStyles, Z_INDEX, getStatusBarParts, measureRange, flattenColumns, getMultiSelectFilterFields, deriveFilterOptionsFromData, processClientSideData, processClientSideDataAsync, validateColumns, validateRowIds, computeRowSelectionState, buildCellIndex, UndoRedoStack, CHECKBOX_COLUMN_WIDTH, DEFAULT_MIN_COLUMN_WIDTH, CELL_PADDING, computeAggregations, getDataGridStatusBarConfig, validateVirtualScrollConfig, computeVisibleRange, computeTotalHeight, computeVisibleColumnRange, partitionColumnsForVirtualization, buildHeaderRows, ROW_NUMBER_COLUMN_WIDTH, getHeaderFilterConfig, getCellRenderDescriptor, buildInlineEditorProps, buildPopoverEditorProps, resolveCellDisplayContent, resolveCellStyle, rangesEqual, normalizeSelectionRange, formatSelectionAsTsv, parseTsvClipboard, applyPastedValues, applyCutClear, measureColumnContentWidth, getPinStateForColumn, parseValue, applyFillValues, applyCellDeletion, computeTabNavigation, computeArrowNavigation, computeNextSortState, mergeFilter, applyRangeRowSelection, getScrollTopForRow, getCellValue, calculateDropTarget, reorderColumnArray, computeAutoScrollSpeed } from '@alaarab/ogrid-core';
|
|
2
2
|
export * from '@alaarab/ogrid-core';
|
|
3
3
|
export { buildInlineEditorProps, buildPopoverEditorProps, getCellRenderDescriptor, getHeaderFilterConfig, isInSelectionRange, normalizeSelectionRange, resolveCellDisplayContent, resolveCellStyle, toUserLike } from '@alaarab/ogrid-core';
|
|
4
4
|
import { defineComponent, ref, computed, onMounted, watch, toValue, onUnmounted, h, shallowRef, triggerRef, nextTick, Teleport, isRef, isReadonly, unref, customRef } from 'vue';
|
|
@@ -331,7 +331,11 @@ function useOGrid(props) {
|
|
|
331
331
|
return new Set(visible.length > 0 ? visible : columns.value.map((c) => c.columnId));
|
|
332
332
|
})());
|
|
333
333
|
const columnWidthOverrides = ref({});
|
|
334
|
-
const
|
|
334
|
+
const initialPinned = {};
|
|
335
|
+
for (const col of flattenColumns(props.value.columns)) {
|
|
336
|
+
if (col.pinned) initialPinned[col.columnId] = col.pinned;
|
|
337
|
+
}
|
|
338
|
+
const pinnedOverrides = ref(initialPinned);
|
|
335
339
|
const page = computed(() => controlledState.value.page ?? internalPage.value);
|
|
336
340
|
const pageSize = computed(() => controlledState.value.pageSize ?? internalPageSize.value);
|
|
337
341
|
const sort = computed(() => controlledState.value.sort ?? internalSort.value);
|
|
@@ -389,8 +393,9 @@ function useOGrid(props) {
|
|
|
389
393
|
if (hasServerFilterOptions.value) return serverFilterOptions.value;
|
|
390
394
|
return deriveFilterOptionsFromData(displayData.value, columns.value);
|
|
391
395
|
});
|
|
396
|
+
const workerSortEnabled = computed(() => !!props.value.workerSort);
|
|
392
397
|
const clientItemsAndTotal = computed(() => {
|
|
393
|
-
if (!isClientSide.value) return null;
|
|
398
|
+
if (!isClientSide.value || workerSortEnabled.value) return null;
|
|
394
399
|
const rows = processClientSideData(
|
|
395
400
|
displayData.value,
|
|
396
401
|
columns.value,
|
|
@@ -403,6 +408,42 @@ function useOGrid(props) {
|
|
|
403
408
|
const paged = rows.slice(start, start + pageSize.value);
|
|
404
409
|
return { items: paged, totalCount: total };
|
|
405
410
|
});
|
|
411
|
+
const asyncClientItems = ref(null);
|
|
412
|
+
let workerSortAbortId = 0;
|
|
413
|
+
watch(
|
|
414
|
+
[isClientSide, workerSortEnabled, displayData, columns, filters, () => sort.value.field, () => sort.value.direction, page, pageSize],
|
|
415
|
+
() => {
|
|
416
|
+
if (!isClientSide.value || !workerSortEnabled.value) return;
|
|
417
|
+
const data = displayData.value;
|
|
418
|
+
const cols = columns.value;
|
|
419
|
+
const f = filters.value;
|
|
420
|
+
const sf = sort.value.field;
|
|
421
|
+
const sd = sort.value.direction;
|
|
422
|
+
const p = page.value;
|
|
423
|
+
const ps = pageSize.value;
|
|
424
|
+
const abortId = ++workerSortAbortId;
|
|
425
|
+
processClientSideDataAsync(data, cols, f, sf, sd).then((rows) => {
|
|
426
|
+
if (abortId !== workerSortAbortId || isDestroyed) return;
|
|
427
|
+
const total = rows.length;
|
|
428
|
+
const start = (p - 1) * ps;
|
|
429
|
+
const paged = rows.slice(start, start + ps);
|
|
430
|
+
asyncClientItems.value = { items: paged, totalCount: total };
|
|
431
|
+
}).catch(() => {
|
|
432
|
+
if (abortId !== workerSortAbortId || isDestroyed) return;
|
|
433
|
+
const rows = processClientSideData(data, cols, f, sf, sd);
|
|
434
|
+
const total = rows.length;
|
|
435
|
+
const start = (p - 1) * ps;
|
|
436
|
+
const paged = rows.slice(start, start + ps);
|
|
437
|
+
asyncClientItems.value = { items: paged, totalCount: total };
|
|
438
|
+
});
|
|
439
|
+
},
|
|
440
|
+
{ immediate: true }
|
|
441
|
+
);
|
|
442
|
+
const resolvedClientItems = computed(() => {
|
|
443
|
+
const syncResult = clientItemsAndTotal.value;
|
|
444
|
+
if (syncResult) return syncResult;
|
|
445
|
+
return asyncClientItems.value;
|
|
446
|
+
});
|
|
406
447
|
const serverItems = ref([]);
|
|
407
448
|
const serverTotalCount = ref(0);
|
|
408
449
|
const loading = ref(false);
|
|
@@ -448,10 +489,10 @@ function useOGrid(props) {
|
|
|
448
489
|
isDestroyed = true;
|
|
449
490
|
});
|
|
450
491
|
const displayItems = computed(
|
|
451
|
-
() => isClientSide.value &&
|
|
492
|
+
() => isClientSide.value && resolvedClientItems.value ? resolvedClientItems.value.items : serverItems.value
|
|
452
493
|
);
|
|
453
494
|
const displayTotalCount = computed(
|
|
454
|
-
() => isClientSide.value &&
|
|
495
|
+
() => isClientSide.value && resolvedClientItems.value ? resolvedClientItems.value.totalCount : serverTotalCount.value
|
|
455
496
|
);
|
|
456
497
|
let firstDataRendered = false;
|
|
457
498
|
let rowIdsValidated = false;
|
|
@@ -3104,13 +3145,24 @@ function useColumnReorder(params) {
|
|
|
3104
3145
|
}
|
|
3105
3146
|
var DEFAULT_PASSTHROUGH_THRESHOLD = 100;
|
|
3106
3147
|
function useVirtualScroll(params) {
|
|
3107
|
-
const {
|
|
3148
|
+
const {
|
|
3149
|
+
totalRows,
|
|
3150
|
+
rowHeight,
|
|
3151
|
+
enabled,
|
|
3152
|
+
overscan = 5,
|
|
3153
|
+
threshold = DEFAULT_PASSTHROUGH_THRESHOLD,
|
|
3154
|
+
columnsEnabled,
|
|
3155
|
+
columnWidths,
|
|
3156
|
+
columnOverscan = 2
|
|
3157
|
+
} = params;
|
|
3108
3158
|
onMounted(() => {
|
|
3109
3159
|
validateVirtualScrollConfig({ enabled: enabled.value, rowHeight });
|
|
3110
3160
|
});
|
|
3111
3161
|
const containerRef = ref(null);
|
|
3112
3162
|
const scrollTop = ref(0);
|
|
3163
|
+
const scrollLeft = ref(0);
|
|
3113
3164
|
const containerHeight = ref(0);
|
|
3165
|
+
const containerWidth = ref(0);
|
|
3114
3166
|
let rafId = 0;
|
|
3115
3167
|
let resizeObserver;
|
|
3116
3168
|
let prevObservedEl = null;
|
|
@@ -3131,6 +3183,17 @@ function useVirtualScroll(params) {
|
|
|
3131
3183
|
if (!enabled.value) return 0;
|
|
3132
3184
|
return computeTotalHeight(totalRows.value, rowHeight);
|
|
3133
3185
|
});
|
|
3186
|
+
const columnRange = computed(() => {
|
|
3187
|
+
if (!columnsEnabled?.value) return null;
|
|
3188
|
+
const widths = columnWidths?.value;
|
|
3189
|
+
if (!widths || widths.length === 0) return null;
|
|
3190
|
+
return computeVisibleColumnRange(
|
|
3191
|
+
scrollLeft.value,
|
|
3192
|
+
widths,
|
|
3193
|
+
containerWidth.value,
|
|
3194
|
+
columnOverscan
|
|
3195
|
+
);
|
|
3196
|
+
});
|
|
3134
3197
|
const onScroll = () => {
|
|
3135
3198
|
if (!rafId) {
|
|
3136
3199
|
rafId = requestAnimationFrame(() => {
|
|
@@ -3138,6 +3201,7 @@ function useVirtualScroll(params) {
|
|
|
3138
3201
|
const el = containerRef.value;
|
|
3139
3202
|
if (el) {
|
|
3140
3203
|
scrollTop.value = el.scrollTop;
|
|
3204
|
+
scrollLeft.value = el.scrollLeft;
|
|
3141
3205
|
}
|
|
3142
3206
|
});
|
|
3143
3207
|
}
|
|
@@ -3146,6 +3210,7 @@ function useVirtualScroll(params) {
|
|
|
3146
3210
|
const el = containerRef.value;
|
|
3147
3211
|
if (!el) return;
|
|
3148
3212
|
containerHeight.value = el.clientHeight;
|
|
3213
|
+
containerWidth.value = el.clientWidth;
|
|
3149
3214
|
};
|
|
3150
3215
|
watch(containerRef, (el) => {
|
|
3151
3216
|
if (el === prevObservedEl) return;
|
|
@@ -3165,6 +3230,7 @@ function useVirtualScroll(params) {
|
|
|
3165
3230
|
}
|
|
3166
3231
|
measure();
|
|
3167
3232
|
scrollTop.value = el.scrollTop;
|
|
3233
|
+
scrollLeft.value = el.scrollLeft;
|
|
3168
3234
|
}
|
|
3169
3235
|
});
|
|
3170
3236
|
onUnmounted(() => {
|
|
@@ -3183,7 +3249,7 @@ function useVirtualScroll(params) {
|
|
|
3183
3249
|
if (!el) return;
|
|
3184
3250
|
el.scrollTop = getScrollTopForRow(index, rowHeight, containerHeight.value, align);
|
|
3185
3251
|
};
|
|
3186
|
-
return { containerRef, visibleRange, totalHeight, scrollToRow };
|
|
3252
|
+
return { containerRef, visibleRange, totalHeight, scrollToRow, columnRange, scrollLeft };
|
|
3187
3253
|
}
|
|
3188
3254
|
function useDataGridTableSetup(params) {
|
|
3189
3255
|
const { props: propsRef } = params;
|
|
@@ -3207,11 +3273,45 @@ function useDataGridTableSetup(params) {
|
|
|
3207
3273
|
const totalRowsRef = computed(() => propsRef.value.items.length);
|
|
3208
3274
|
const rowHeight = propsRef.value.virtualScroll?.rowHeight ?? 36;
|
|
3209
3275
|
const overscan = propsRef.value.virtualScroll?.overscan ?? 5;
|
|
3276
|
+
const columnsVirtEnabled = computed(() => propsRef.value.virtualScroll?.columns === true);
|
|
3277
|
+
const columnOverscan = propsRef.value.virtualScroll?.columnOverscan ?? 2;
|
|
3278
|
+
const unpinnedColumnWidths = computed(() => {
|
|
3279
|
+
const layout = state.layout.value;
|
|
3280
|
+
const { visibleCols, columnSizingOverrides } = layout;
|
|
3281
|
+
const pinnedCols = propsRef.value.pinnedColumns ?? {};
|
|
3282
|
+
const widths = [];
|
|
3283
|
+
for (const col of visibleCols) {
|
|
3284
|
+
if (pinnedCols[col.columnId] || col.pinned) continue;
|
|
3285
|
+
const override = columnSizingOverrides[col.columnId];
|
|
3286
|
+
widths.push(override ? override.widthPx : col.defaultWidth ?? col.minWidth ?? DEFAULT_MIN_COLUMN_WIDTH);
|
|
3287
|
+
}
|
|
3288
|
+
return widths;
|
|
3289
|
+
});
|
|
3210
3290
|
const virtualScroll = useVirtualScroll({
|
|
3211
3291
|
totalRows: totalRowsRef,
|
|
3212
3292
|
rowHeight,
|
|
3213
3293
|
enabled: virtualScrollEnabled,
|
|
3214
|
-
overscan
|
|
3294
|
+
overscan,
|
|
3295
|
+
columnsEnabled: columnsVirtEnabled,
|
|
3296
|
+
columnWidths: unpinnedColumnWidths,
|
|
3297
|
+
columnOverscan
|
|
3298
|
+
});
|
|
3299
|
+
const columnPartition = computed(() => {
|
|
3300
|
+
if (!columnsVirtEnabled.value) return null;
|
|
3301
|
+
const layout = state.layout.value;
|
|
3302
|
+
const cols = layout.visibleCols;
|
|
3303
|
+
const range = virtualScroll.columnRange.value;
|
|
3304
|
+
const pinnedCols = propsRef.value.pinnedColumns;
|
|
3305
|
+
return partitionColumnsForVirtualization(cols, range, pinnedCols);
|
|
3306
|
+
});
|
|
3307
|
+
const globalColIndexMap = computed(() => {
|
|
3308
|
+
const layout = state.layout.value;
|
|
3309
|
+
const cols = layout.visibleCols;
|
|
3310
|
+
const map = /* @__PURE__ */ new Map();
|
|
3311
|
+
for (let i = 0; i < cols.length; i++) {
|
|
3312
|
+
map.set(cols[i].columnId, i);
|
|
3313
|
+
}
|
|
3314
|
+
return map;
|
|
3215
3315
|
});
|
|
3216
3316
|
const columnSizingOverridesRef = computed(() => state.layout.value.columnSizingOverrides);
|
|
3217
3317
|
const columnResize = useColumnResize({
|
|
@@ -3227,7 +3327,9 @@ function useDataGridTableSetup(params) {
|
|
|
3227
3327
|
columnReorder,
|
|
3228
3328
|
virtualScroll,
|
|
3229
3329
|
virtualScrollEnabled,
|
|
3230
|
-
columnResize
|
|
3330
|
+
columnResize,
|
|
3331
|
+
columnPartition,
|
|
3332
|
+
globalColIndexMap
|
|
3231
3333
|
};
|
|
3232
3334
|
}
|
|
3233
3335
|
function getCellInteractionProps(descriptor, columnId, handlers) {
|
|
@@ -3265,7 +3367,9 @@ function createDataGridTable(ui) {
|
|
|
3265
3367
|
columnReorder: { isDragging: isReorderDragging, dropIndicatorX, handleHeaderMouseDown: handleReorderMouseDown },
|
|
3266
3368
|
virtualScroll: { containerRef: vsContainerRef, visibleRange, totalHeight: _totalHeight, scrollToRow: _scrollToRow },
|
|
3267
3369
|
virtualScrollEnabled,
|
|
3268
|
-
columnResize: { handleResizeStart, handleResizeDoubleClick, getColumnWidth }
|
|
3370
|
+
columnResize: { handleResizeStart, handleResizeDoubleClick, getColumnWidth },
|
|
3371
|
+
columnPartition,
|
|
3372
|
+
globalColIndexMap
|
|
3269
3373
|
} = useDataGridTableSetup({ props: propsRef });
|
|
3270
3374
|
const onWrapperMousedown = (e) => {
|
|
3271
3375
|
lastMouseShift.value = e.shiftKey;
|
|
@@ -3457,11 +3561,25 @@ function createDataGridTable(ui) {
|
|
|
3457
3561
|
]);
|
|
3458
3562
|
};
|
|
3459
3563
|
const { cellStyles: colCellStyles, cellClasses: colCellClasses, hdrStyles: colHdrStyles, hdrClasses: colHdrClasses } = columnMetaCache.value;
|
|
3460
|
-
const
|
|
3564
|
+
const allColumnLayouts = visibleCols.map((col) => ({
|
|
3461
3565
|
col,
|
|
3462
3566
|
tdClasses: colCellClasses[col.columnId] || "ogrid-data-cell",
|
|
3463
3567
|
tdDynamicStyle: colCellStyles[col.columnId] || {}
|
|
3464
3568
|
}));
|
|
3569
|
+
const partition = columnPartition.value;
|
|
3570
|
+
let columnLayouts = allColumnLayouts;
|
|
3571
|
+
let leftSpacerWidth = 0;
|
|
3572
|
+
let rightSpacerWidth = 0;
|
|
3573
|
+
if (partition) {
|
|
3574
|
+
const visibleIds = /* @__PURE__ */ new Set();
|
|
3575
|
+
for (const col of partition.pinnedLeft) visibleIds.add(col.columnId);
|
|
3576
|
+
for (const col of partition.virtualizedUnpinned) visibleIds.add(col.columnId);
|
|
3577
|
+
for (const col of partition.pinnedRight) visibleIds.add(col.columnId);
|
|
3578
|
+
columnLayouts = allColumnLayouts.filter((cl) => visibleIds.has(cl.col.columnId));
|
|
3579
|
+
leftSpacerWidth = partition.leftSpacerWidth;
|
|
3580
|
+
rightSpacerWidth = partition.rightSpacerWidth;
|
|
3581
|
+
}
|
|
3582
|
+
const colIndexMap = globalColIndexMap.value;
|
|
3465
3583
|
const getHeaderClassAndStyle = (col) => {
|
|
3466
3584
|
const base = colHdrStyles[col.columnId] || {};
|
|
3467
3585
|
return {
|
|
@@ -3522,7 +3640,8 @@ function createDataGridTable(ui) {
|
|
|
3522
3640
|
},
|
|
3523
3641
|
class: "ogrid-table",
|
|
3524
3642
|
role: "grid",
|
|
3525
|
-
style: { minWidth: `${minTableWidth}px` }
|
|
3643
|
+
style: { minWidth: `${minTableWidth}px` },
|
|
3644
|
+
...virtualScrollEnabled.value ? { "data-virtual-scroll": "" } : {}
|
|
3526
3645
|
}, [
|
|
3527
3646
|
// Header
|
|
3528
3647
|
h(
|
|
@@ -3705,15 +3824,23 @@ function createDataGridTable(ui) {
|
|
|
3705
3824
|
}
|
|
3706
3825
|
}, String(rowNumberOffset + rowIndex + 1))
|
|
3707
3826
|
] : [],
|
|
3827
|
+
// Left spacer for column virtualization
|
|
3828
|
+
...leftSpacerWidth > 0 ? [
|
|
3829
|
+
h("td", { key: "__col-spacer-left", style: { width: `${leftSpacerWidth}px`, minWidth: `${leftSpacerWidth}px`, maxWidth: `${leftSpacerWidth}px`, padding: "0" } })
|
|
3830
|
+
] : [],
|
|
3708
3831
|
// Data cells
|
|
3709
3832
|
...columnLayouts.map(
|
|
3710
|
-
(cl
|
|
3833
|
+
(cl) => h("td", {
|
|
3711
3834
|
key: cl.col.columnId,
|
|
3712
3835
|
"data-column-id": cl.col.columnId,
|
|
3713
3836
|
class: cl.tdClasses,
|
|
3714
3837
|
style: cl.tdDynamicStyle
|
|
3715
|
-
}, [renderCellContent(item, cl.col, rowIndex,
|
|
3716
|
-
)
|
|
3838
|
+
}, [renderCellContent(item, cl.col, rowIndex, colIndexMap.get(cl.col.columnId) ?? 0)])
|
|
3839
|
+
),
|
|
3840
|
+
// Right spacer for column virtualization
|
|
3841
|
+
...rightSpacerWidth > 0 ? [
|
|
3842
|
+
h("td", { key: "__col-spacer-right", style: { width: `${rightSpacerWidth}px`, minWidth: `${rightSpacerWidth}px`, maxWidth: `${rightSpacerWidth}px`, padding: "0" } })
|
|
3843
|
+
] : []
|
|
3717
3844
|
]));
|
|
3718
3845
|
}
|
|
3719
3846
|
if (vsEnabled && vr.offsetBottom > 0) {
|
|
@@ -189,8 +189,16 @@
|
|
|
189
189
|
position: relative;
|
|
190
190
|
padding: 0;
|
|
191
191
|
height: 1px;
|
|
192
|
+
contain: content;
|
|
192
193
|
}
|
|
193
194
|
|
|
195
|
+
/* Pinned columns need contain: none because contain breaks position: sticky */
|
|
196
|
+
.ogrid-data-cell--pinned-left,
|
|
197
|
+
.ogrid-data-cell--pinned-right { contain: none; }
|
|
198
|
+
|
|
199
|
+
/* content-visibility: auto on rows for non-virtualized grids */
|
|
200
|
+
.ogrid-table:not([data-virtual-scroll]) tbody tr { content-visibility: auto; }
|
|
201
|
+
|
|
194
202
|
.ogrid-data-cell--pinned-left {
|
|
195
203
|
position: sticky;
|
|
196
204
|
z-index: var(--ogrid-z-pinned, 6);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type Ref } from 'vue';
|
|
2
|
-
import type { IOGridDataGridProps } from '../types';
|
|
2
|
+
import type { IOGridDataGridProps, IColumnDef } from '../types';
|
|
3
3
|
import { type UseDataGridStateResult } from './useDataGridState';
|
|
4
4
|
import { type UseColumnResizeResult } from './useColumnResize';
|
|
5
5
|
import { type UseColumnReorderResult } from './useColumnReorder';
|
|
@@ -27,6 +27,16 @@ export interface UseDataGridTableSetupResult<T> {
|
|
|
27
27
|
virtualScrollEnabled: Ref<boolean>;
|
|
28
28
|
/** Column resize handlers (handleResizeStart, getColumnWidth). */
|
|
29
29
|
columnResize: UseColumnResizeResult<T>;
|
|
30
|
+
/** Column virtualization partition (or null when column virtualization is off). */
|
|
31
|
+
columnPartition: Ref<{
|
|
32
|
+
pinnedLeft: IColumnDef<T>[];
|
|
33
|
+
virtualizedUnpinned: IColumnDef<T>[];
|
|
34
|
+
pinnedRight: IColumnDef<T>[];
|
|
35
|
+
leftSpacerWidth: number;
|
|
36
|
+
rightSpacerWidth: number;
|
|
37
|
+
} | null>;
|
|
38
|
+
/** Map from columnId to its global index in visibleCols. */
|
|
39
|
+
globalColIndexMap: Ref<Map<string, number>>;
|
|
30
40
|
}
|
|
31
41
|
/**
|
|
32
42
|
* Shared setup composable for Vue DataGridTable components.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type Ref } from 'vue';
|
|
2
|
-
import type { IVisibleRange } from '@alaarab/ogrid-core';
|
|
2
|
+
import type { IVisibleRange, IVisibleColumnRange } from '@alaarab/ogrid-core';
|
|
3
3
|
export interface UseVirtualScrollParams {
|
|
4
4
|
totalRows: Ref<number>;
|
|
5
5
|
rowHeight: number;
|
|
@@ -10,12 +10,22 @@ export interface UseVirtualScrollParams {
|
|
|
10
10
|
* When totalRows < threshold, all rows render without virtualization.
|
|
11
11
|
*/
|
|
12
12
|
threshold?: number;
|
|
13
|
+
/** Enable column virtualization. */
|
|
14
|
+
columnsEnabled?: Ref<boolean>;
|
|
15
|
+
/** Column widths array for unpinned columns. */
|
|
16
|
+
columnWidths?: Ref<number[]>;
|
|
17
|
+
/** Number of extra columns to render outside the visible area. Default: 2. */
|
|
18
|
+
columnOverscan?: number;
|
|
13
19
|
}
|
|
14
20
|
export interface UseVirtualScrollResult {
|
|
15
21
|
containerRef: Ref<HTMLElement | null>;
|
|
16
22
|
visibleRange: Ref<IVisibleRange>;
|
|
17
23
|
totalHeight: Ref<number>;
|
|
18
24
|
scrollToRow: (index: number, align?: 'start' | 'center' | 'end') => void;
|
|
25
|
+
/** Visible column range for horizontal virtualization, or null when column virtualization is off. */
|
|
26
|
+
columnRange: Ref<IVisibleColumnRange | null>;
|
|
27
|
+
/** Reactive scrollLeft value. */
|
|
28
|
+
scrollLeft: Ref<number>;
|
|
19
29
|
}
|
|
20
30
|
/**
|
|
21
31
|
* Manages virtual scrolling with RAF-throttled scroll handling and ResizeObserver
|
|
@@ -81,6 +81,8 @@ interface IOGridBaseProps<T> {
|
|
|
81
81
|
columnReorder?: boolean;
|
|
82
82
|
/** Virtual scrolling configuration. Set `enabled: true` with a fixed `rowHeight` to virtualize large datasets. */
|
|
83
83
|
virtualScroll?: IVirtualScrollConfig;
|
|
84
|
+
/** Offload sort/filter to a Web Worker for large datasets. Falls back to sync when sort column has a custom compare. */
|
|
85
|
+
workerSort?: boolean;
|
|
84
86
|
/** Fixed row height in pixels. Overrides default row height (36px). */
|
|
85
87
|
rowHeight?: number;
|
|
86
88
|
/** Cell spacing/density preset. Controls cell padding throughout the grid. Default: 'normal'. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alaarab/ogrid-vue",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "OGrid Vue – Vue 3 composables, headless components, and utilities for OGrid data grids.",
|
|
5
5
|
"main": "dist/esm/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"node": ">=18"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@alaarab/ogrid-core": "2.
|
|
39
|
+
"@alaarab/ogrid-core": "2.2.0"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
42
|
"vue": "^3.3.0"
|