@alaarab/ogrid-vue 2.1.10 → 2.1.11
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 +76 -29
- package/dist/esm/styles/ogrid-layout.css +28 -24
- package/dist/esm/styles/ogrid-theme.css +7 -0
- package/dist/types/composables/useFillHandle.d.ts +2 -0
- package/dist/types/composables/useKeyboardNavigation.d.ts +2 -0
- package/dist/types/composables/useVirtualScroll.d.ts +5 -0
- package/dist/types/types/dataGridTypes.d.ts +2 -0
- package/package.json +2 -2
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, 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, 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';
|
|
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';
|
|
@@ -1254,6 +1254,12 @@ function useKeyboardNavigation(params) {
|
|
|
1254
1254
|
const rowSelection = features.rowSelection.value;
|
|
1255
1255
|
const wrapperRef = features.wrapperRef;
|
|
1256
1256
|
const scrollToRow = features.scrollToRow;
|
|
1257
|
+
const { fillDown } = features;
|
|
1258
|
+
const onKeyDown = features.onKeyDown?.value;
|
|
1259
|
+
if (onKeyDown) {
|
|
1260
|
+
onKeyDown(e);
|
|
1261
|
+
if (e.defaultPrevented) return;
|
|
1262
|
+
}
|
|
1257
1263
|
const maxRowIndex = items.length - 1;
|
|
1258
1264
|
const maxColIndex = visibleColumnCount - 1 + colOffset;
|
|
1259
1265
|
if (items.length === 0) return;
|
|
@@ -1294,6 +1300,15 @@ function useKeyboardNavigation(params) {
|
|
|
1294
1300
|
void handlePaste();
|
|
1295
1301
|
}
|
|
1296
1302
|
break;
|
|
1303
|
+
case "d":
|
|
1304
|
+
if (e.ctrlKey || e.metaKey) {
|
|
1305
|
+
if (editingCell != null) break;
|
|
1306
|
+
if (editable !== false && fillDown) {
|
|
1307
|
+
e.preventDefault();
|
|
1308
|
+
fillDown();
|
|
1309
|
+
}
|
|
1310
|
+
}
|
|
1311
|
+
break;
|
|
1297
1312
|
case "ArrowDown":
|
|
1298
1313
|
case "ArrowUp":
|
|
1299
1314
|
case "ArrowRight":
|
|
@@ -1622,7 +1637,21 @@ function useFillHandle(params) {
|
|
|
1622
1637
|
if (!range) return;
|
|
1623
1638
|
fillDrag.value = { startRow: range.startRow, startCol: range.startCol };
|
|
1624
1639
|
};
|
|
1625
|
-
|
|
1640
|
+
const fillDown = () => {
|
|
1641
|
+
const range = selectionRange.value;
|
|
1642
|
+
if (!range || editable.value === false || !onCellValueChanged.value) return;
|
|
1643
|
+
const norm = normalizeSelectionRange(range);
|
|
1644
|
+
const currentItems = items.value;
|
|
1645
|
+
const currentCols = visibleCols.value;
|
|
1646
|
+
const callback = onCellValueChanged.value;
|
|
1647
|
+
const fillEvents = applyFillValues(norm, norm.startRow, norm.startCol, currentItems, currentCols);
|
|
1648
|
+
if (fillEvents.length > 0) {
|
|
1649
|
+
beginBatch?.();
|
|
1650
|
+
for (const evt of fillEvents) callback(evt);
|
|
1651
|
+
endBatch?.();
|
|
1652
|
+
}
|
|
1653
|
+
};
|
|
1654
|
+
return { fillDrag, setFillDrag, handleFillHandleMouseDown, fillDown };
|
|
1626
1655
|
}
|
|
1627
1656
|
function useUndoRedo(params) {
|
|
1628
1657
|
const { onCellValueChanged, maxUndoDepth = 100 } = params;
|
|
@@ -2034,6 +2063,19 @@ function useDataGridState(params) {
|
|
|
2034
2063
|
clearClipboardRanges();
|
|
2035
2064
|
handleCellMouseDownBase(e, rowIndex, globalColIndex);
|
|
2036
2065
|
};
|
|
2066
|
+
const { handleFillHandleMouseDown, fillDown } = useFillHandle({
|
|
2067
|
+
items,
|
|
2068
|
+
visibleCols,
|
|
2069
|
+
editable: editableProp,
|
|
2070
|
+
onCellValueChanged,
|
|
2071
|
+
selectionRange,
|
|
2072
|
+
setSelectionRange,
|
|
2073
|
+
setActiveCell,
|
|
2074
|
+
colOffset,
|
|
2075
|
+
wrapperRef,
|
|
2076
|
+
beginBatch: undoRedo.beginBatch,
|
|
2077
|
+
endBatch: undoRedo.endBatch
|
|
2078
|
+
});
|
|
2037
2079
|
const { handleGridKeyDown } = useKeyboardNavigation({
|
|
2038
2080
|
data: { items, visibleCols, colOffset, hasCheckboxCol, visibleColumnCount, getRowId },
|
|
2039
2081
|
state: { activeCell, selectionRange, editingCell, selectedRowIds: rowSelectionResult.selectedRowIds },
|
|
@@ -2054,22 +2096,11 @@ function useDataGridState(params) {
|
|
|
2054
2096
|
editable: editableProp,
|
|
2055
2097
|
onCellValueChanged,
|
|
2056
2098
|
rowSelection: rowSelectionProp,
|
|
2057
|
-
wrapperRef
|
|
2099
|
+
wrapperRef,
|
|
2100
|
+
fillDown,
|
|
2101
|
+
onKeyDown: computed(() => props.value.onKeyDown)
|
|
2058
2102
|
}
|
|
2059
2103
|
});
|
|
2060
|
-
const { handleFillHandleMouseDown } = useFillHandle({
|
|
2061
|
-
items,
|
|
2062
|
-
visibleCols,
|
|
2063
|
-
editable: editableProp,
|
|
2064
|
-
onCellValueChanged,
|
|
2065
|
-
selectionRange,
|
|
2066
|
-
setSelectionRange,
|
|
2067
|
-
setActiveCell,
|
|
2068
|
-
colOffset,
|
|
2069
|
-
wrapperRef,
|
|
2070
|
-
beginBatch: undoRedo.beginBatch,
|
|
2071
|
-
endBatch: undoRedo.endBatch
|
|
2072
|
-
});
|
|
2073
2104
|
const {
|
|
2074
2105
|
containerWidth,
|
|
2075
2106
|
minTableWidth,
|
|
@@ -3050,17 +3081,22 @@ function useColumnReorder(params) {
|
|
|
3050
3081
|
};
|
|
3051
3082
|
return { isDragging, dropIndicatorX, handleHeaderMouseDown };
|
|
3052
3083
|
}
|
|
3084
|
+
var DEFAULT_PASSTHROUGH_THRESHOLD = 100;
|
|
3053
3085
|
function useVirtualScroll(params) {
|
|
3054
|
-
const { totalRows, rowHeight, enabled, overscan = 5 } = params;
|
|
3086
|
+
const { totalRows, rowHeight, enabled, overscan = 5, threshold = DEFAULT_PASSTHROUGH_THRESHOLD } = params;
|
|
3087
|
+
onMounted(() => {
|
|
3088
|
+
validateVirtualScrollConfig({ enabled: enabled.value, rowHeight });
|
|
3089
|
+
});
|
|
3055
3090
|
const containerRef = ref(null);
|
|
3056
3091
|
const scrollTop = ref(0);
|
|
3057
3092
|
const containerHeight = ref(0);
|
|
3058
3093
|
let rafId = 0;
|
|
3059
3094
|
let resizeObserver;
|
|
3060
3095
|
let prevObservedEl = null;
|
|
3096
|
+
const isActive = computed(() => enabled.value && totalRows.value >= threshold);
|
|
3061
3097
|
const visibleRange = computed(() => {
|
|
3062
|
-
if (!
|
|
3063
|
-
return { startIndex: 0, endIndex: totalRows.value - 1, offsetTop: 0, offsetBottom: 0 };
|
|
3098
|
+
if (!isActive.value) {
|
|
3099
|
+
return { startIndex: 0, endIndex: Math.max(0, totalRows.value - 1), offsetTop: 0, offsetBottom: 0 };
|
|
3064
3100
|
}
|
|
3065
3101
|
return computeVisibleRange(
|
|
3066
3102
|
scrollTop.value,
|
|
@@ -3278,10 +3314,7 @@ function createDataGridTable(ui) {
|
|
|
3278
3314
|
visibleCols,
|
|
3279
3315
|
hasCheckboxCol,
|
|
3280
3316
|
hasRowNumbersCol,
|
|
3281
|
-
colOffset: _colOffset
|
|
3282
|
-
containerWidth,
|
|
3283
|
-
minTableWidth,
|
|
3284
|
-
desiredTableWidth
|
|
3317
|
+
colOffset: _colOffset
|
|
3285
3318
|
} = layout;
|
|
3286
3319
|
const currentPage = p.currentPage ?? 1;
|
|
3287
3320
|
const pageSize = p.pageSize ?? 25;
|
|
@@ -3309,7 +3342,7 @@ function createDataGridTable(ui) {
|
|
|
3309
3342
|
isDragging: _isDragging
|
|
3310
3343
|
} = interaction;
|
|
3311
3344
|
const { menuPosition, handleCellContextMenu, closeContextMenu } = ctxMenu;
|
|
3312
|
-
const { headerFilterInput, cellDescriptorInput, statusBarConfig, showEmptyInGrid, onCellError
|
|
3345
|
+
const { headerFilterInput, cellDescriptorInput, statusBarConfig, showEmptyInGrid, onCellError } = viewModels;
|
|
3313
3346
|
const items = p.items;
|
|
3314
3347
|
const getRowId = p.getRowId;
|
|
3315
3348
|
const layoutMode = p.layoutMode ?? "fill";
|
|
@@ -3321,7 +3354,6 @@ function createDataGridTable(ui) {
|
|
|
3321
3354
|
const ariaLabel = p["aria-label"];
|
|
3322
3355
|
const ariaLabelledBy = p["aria-labelledby"];
|
|
3323
3356
|
const fitToContent = layoutMode === "content";
|
|
3324
|
-
const allowOverflowX = !suppressHorizontalScroll && containerWidth > 0 && (minTableWidth > containerWidth || desiredTableWidth > containerWidth);
|
|
3325
3357
|
const headerRows = headerRowsComputed.value;
|
|
3326
3358
|
const editCallbacks = { commitCellEdit, setEditingCell, setPendingEditorValue, cancelPopoverEdit };
|
|
3327
3359
|
const interactionHandlers = { handleCellMouseDown, setActiveCell, setEditingCell, handleCellContextMenu };
|
|
@@ -3333,6 +3365,16 @@ function createDataGridTable(ui) {
|
|
|
3333
3365
|
rowSel.updateSelection(selectedRowIds.has(rowId) ? /* @__PURE__ */ new Set() : /* @__PURE__ */ new Set([rowId]));
|
|
3334
3366
|
};
|
|
3335
3367
|
const renderCellContent = (item, col, rowIndex, colIdx) => {
|
|
3368
|
+
try {
|
|
3369
|
+
return renderCellContentInner(item, col, rowIndex, colIdx);
|
|
3370
|
+
} catch (err) {
|
|
3371
|
+
if (onCellError) {
|
|
3372
|
+
onCellError(err instanceof Error ? err : new Error(String(err)), void 0);
|
|
3373
|
+
}
|
|
3374
|
+
return "";
|
|
3375
|
+
}
|
|
3376
|
+
};
|
|
3377
|
+
const renderCellContentInner = (item, col, rowIndex, colIdx) => {
|
|
3336
3378
|
const descriptor = getCellRenderDescriptor(item, col, rowIndex, colIdx, cellDescriptorInput);
|
|
3337
3379
|
if (descriptor.mode === "editing-inline") {
|
|
3338
3380
|
const editorProps = buildInlineEditorProps(item, col, descriptor, editCallbacks);
|
|
@@ -3408,7 +3450,7 @@ function createDataGridTable(ui) {
|
|
|
3408
3450
|
minHeight: isLoading && items.length === 0 ? "200px" : "0",
|
|
3409
3451
|
width: fitToContent ? "fit-content" : "100%",
|
|
3410
3452
|
maxWidth: "100%",
|
|
3411
|
-
overflowX: suppressHorizontalScroll ? "hidden" :
|
|
3453
|
+
overflowX: suppressHorizontalScroll ? "hidden" : "auto",
|
|
3412
3454
|
overflowY: "auto",
|
|
3413
3455
|
backgroundColor: "#fff",
|
|
3414
3456
|
willChange: "scroll-position"
|
|
@@ -3430,11 +3472,11 @@ function createDataGridTable(ui) {
|
|
|
3430
3472
|
onMousedown: onWrapperMousedown,
|
|
3431
3473
|
onKeydown: handleGridKeyDown,
|
|
3432
3474
|
onContextmenu,
|
|
3433
|
-
"data-
|
|
3475
|
+
"data-suppress-scroll": suppressHorizontalScroll ? "true" : void 0,
|
|
3434
3476
|
style: wrapperStyle
|
|
3435
3477
|
}, [
|
|
3436
3478
|
h("div", { class: "ogrid-scroll-wrapper" }, [
|
|
3437
|
-
h("div", { style: {
|
|
3479
|
+
h("div", { style: { width: "max-content", minWidth: "100%", overflow: "clip" } }, [
|
|
3438
3480
|
h("div", {
|
|
3439
3481
|
ref: (el) => {
|
|
3440
3482
|
tableContainerRef.value = el;
|
|
@@ -3454,7 +3496,8 @@ function createDataGridTable(ui) {
|
|
|
3454
3496
|
tableRef.value = el;
|
|
3455
3497
|
},
|
|
3456
3498
|
class: "ogrid-table",
|
|
3457
|
-
|
|
3499
|
+
role: "grid",
|
|
3500
|
+
style: { width: "100%", minWidth: "max-content" }
|
|
3458
3501
|
}, [
|
|
3459
3502
|
// Header
|
|
3460
3503
|
h(
|
|
@@ -3531,6 +3574,8 @@ function createDataGridTable(ui) {
|
|
|
3531
3574
|
if (!cell.columnDef) return null;
|
|
3532
3575
|
const col = cell.columnDef;
|
|
3533
3576
|
const { classes: headerClasses, style: headerStyle } = getHeaderClassAndStyle(col);
|
|
3577
|
+
const isSorted = p.sortBy === col.columnId;
|
|
3578
|
+
const ariaSort = isSorted ? p.sortDirection === "asc" ? "ascending" : "descending" : void 0;
|
|
3534
3579
|
return h("th", {
|
|
3535
3580
|
key: col.columnId,
|
|
3536
3581
|
scope: "col",
|
|
@@ -3538,6 +3583,7 @@ function createDataGridTable(ui) {
|
|
|
3538
3583
|
rowSpan: headerRows.length > 1 ? headerRows.length - rowIdx : void 0,
|
|
3539
3584
|
class: headerClasses,
|
|
3540
3585
|
style: headerStyle,
|
|
3586
|
+
"aria-sort": ariaSort,
|
|
3541
3587
|
onMousedown: (e) => handleReorderMouseDown(col.columnId, e)
|
|
3542
3588
|
}, [
|
|
3543
3589
|
h("div", { class: "ogrid-header-content" }, [
|
|
@@ -3586,6 +3632,7 @@ function createDataGridTable(ui) {
|
|
|
3586
3632
|
rows.push(h("tr", {
|
|
3587
3633
|
key: rowIdStr,
|
|
3588
3634
|
"data-row-id": rowIdStr,
|
|
3635
|
+
"aria-selected": isSelected || void 0,
|
|
3589
3636
|
onClick: handleSingleRowClick,
|
|
3590
3637
|
style: { cursor: rowSelection === "single" ? "pointer" : void 0 }
|
|
3591
3638
|
}, [
|
|
@@ -1,29 +1,33 @@
|
|
|
1
1
|
/* OGrid Shared Layout Styles — consumed by vue-vuetify and vue-primevue */
|
|
2
2
|
|
|
3
|
-
/* Remove focus outline from scrollable wrapper (keyboard nav is handled via cell outlines)
|
|
3
|
+
/* Remove focus outline from scrollable wrapper (keyboard nav is handled via cell outlines).
|
|
4
|
+
[role="region"][tabindex] has attribute-selector specificity (0,2,0) which beats any
|
|
5
|
+
framework's single-class or element rule — no !important needed. */
|
|
4
6
|
[role="region"][tabindex="0"] {
|
|
5
|
-
outline: none
|
|
7
|
+
outline: none;
|
|
6
8
|
}
|
|
7
9
|
|
|
8
|
-
/* Cell selection highlighting
|
|
9
|
-
.ogrid-
|
|
10
|
-
|
|
10
|
+
/* Cell selection highlighting.
|
|
11
|
+
Qualify with .ogrid-outer-container (specificity 0,2,0) to beat row-level hover backgrounds. */
|
|
12
|
+
.ogrid-outer-container .ogrid-cell-in-range {
|
|
13
|
+
background: var(--ogrid-bg-range, rgba(33, 115, 70, 0.12));
|
|
11
14
|
}
|
|
12
15
|
|
|
13
16
|
/* Cut range highlighting */
|
|
14
|
-
.ogrid-cell-cut {
|
|
15
|
-
background: var(--ogrid-hover-bg)
|
|
17
|
+
.ogrid-outer-container .ogrid-cell-cut {
|
|
18
|
+
background: var(--ogrid-hover-bg);
|
|
16
19
|
opacity: 0.7;
|
|
17
20
|
}
|
|
18
21
|
|
|
19
|
-
/* Drag-range highlight applied via DOM attributes during drag (bypasses Vue for performance)
|
|
20
|
-
|
|
21
|
-
|
|
22
|
+
/* Drag-range highlight applied via DOM attributes during drag (bypasses Vue for performance).
|
|
23
|
+
Qualifier .ogrid-outer-container raises specificity to 0,2,0, enough to beat row-hover rules. */
|
|
24
|
+
.ogrid-outer-container [data-drag-range] {
|
|
25
|
+
background: var(--ogrid-range-bg, rgba(33, 115, 70, 0.12));
|
|
22
26
|
}
|
|
23
27
|
|
|
24
28
|
/* Anchor cell during drag: white/transparent background (like Excel) */
|
|
25
|
-
[data-drag-anchor] {
|
|
26
|
-
background: var(--ogrid-bg)
|
|
29
|
+
.ogrid-outer-container [data-drag-anchor] {
|
|
30
|
+
background: var(--ogrid-bg);
|
|
27
31
|
}
|
|
28
32
|
|
|
29
33
|
/* === Layout === */
|
|
@@ -67,7 +71,7 @@
|
|
|
67
71
|
/* === Header === */
|
|
68
72
|
|
|
69
73
|
.ogrid-thead {
|
|
70
|
-
z-index: 8;
|
|
74
|
+
z-index: var(--ogrid-z-thead, 8);
|
|
71
75
|
background-color: var(--ogrid-header-bg);
|
|
72
76
|
}
|
|
73
77
|
|
|
@@ -78,7 +82,7 @@
|
|
|
78
82
|
.ogrid-header-cell {
|
|
79
83
|
font-weight: 600;
|
|
80
84
|
background-color: var(--ogrid-header-bg);
|
|
81
|
-
z-index: 8;
|
|
85
|
+
z-index: var(--ogrid-z-thead, 8);
|
|
82
86
|
}
|
|
83
87
|
|
|
84
88
|
.ogrid-sticky-header .ogrid-header-cell {
|
|
@@ -87,14 +91,14 @@
|
|
|
87
91
|
}
|
|
88
92
|
|
|
89
93
|
.ogrid-header-cell--pinned-left {
|
|
90
|
-
z-index: 10;
|
|
94
|
+
z-index: var(--ogrid-z-pinned-header, 10);
|
|
91
95
|
will-change: transform;
|
|
92
96
|
border-right: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
|
|
93
97
|
box-shadow: 2px 0 4px -1px rgba(0, 0, 0, 0.1);
|
|
94
98
|
}
|
|
95
99
|
|
|
96
100
|
.ogrid-header-cell--pinned-right {
|
|
97
|
-
z-index: 10;
|
|
101
|
+
z-index: var(--ogrid-z-pinned-header, 10);
|
|
98
102
|
will-change: transform;
|
|
99
103
|
border-left: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
|
|
100
104
|
box-shadow: -2px 0 4px -1px rgba(0, 0, 0, 0.1);
|
|
@@ -189,7 +193,7 @@
|
|
|
189
193
|
|
|
190
194
|
.ogrid-data-cell--pinned-left {
|
|
191
195
|
position: sticky;
|
|
192
|
-
z-index: 6;
|
|
196
|
+
z-index: var(--ogrid-z-pinned, 6);
|
|
193
197
|
background-color: var(--ogrid-bg);
|
|
194
198
|
will-change: transform;
|
|
195
199
|
border-right: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
|
|
@@ -198,7 +202,7 @@
|
|
|
198
202
|
|
|
199
203
|
.ogrid-data-cell--pinned-right {
|
|
200
204
|
position: sticky;
|
|
201
|
-
z-index: 6;
|
|
205
|
+
z-index: var(--ogrid-z-pinned, 6);
|
|
202
206
|
background-color: var(--ogrid-bg);
|
|
203
207
|
will-change: transform;
|
|
204
208
|
border-left: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
|
|
@@ -211,7 +215,7 @@
|
|
|
211
215
|
display: flex;
|
|
212
216
|
align-items: center;
|
|
213
217
|
min-width: 0;
|
|
214
|
-
padding: 6px 10px;
|
|
218
|
+
padding: var(--ogrid-cell-padding, 6px 10px);
|
|
215
219
|
box-sizing: border-box;
|
|
216
220
|
overflow: hidden;
|
|
217
221
|
text-overflow: ellipsis;
|
|
@@ -237,7 +241,7 @@
|
|
|
237
241
|
.ogrid-cell-content--active {
|
|
238
242
|
outline: 2px solid var(--ogrid-selection, #217346);
|
|
239
243
|
outline-offset: -1px;
|
|
240
|
-
z-index: 2;
|
|
244
|
+
z-index: var(--ogrid-z-active-cell, 2);
|
|
241
245
|
position: relative;
|
|
242
246
|
overflow: visible;
|
|
243
247
|
}
|
|
@@ -252,7 +256,7 @@
|
|
|
252
256
|
box-sizing: border-box;
|
|
253
257
|
outline: 2px solid var(--ogrid-selection-color, #217346);
|
|
254
258
|
outline-offset: -1px;
|
|
255
|
-
z-index: 2;
|
|
259
|
+
z-index: var(--ogrid-z-active-cell, 2);
|
|
256
260
|
position: relative;
|
|
257
261
|
background: var(--ogrid-bg, #fff);
|
|
258
262
|
overflow: visible;
|
|
@@ -272,7 +276,7 @@
|
|
|
272
276
|
border-radius: 1px;
|
|
273
277
|
cursor: crosshair;
|
|
274
278
|
pointer-events: auto;
|
|
275
|
-
z-index: 3;
|
|
279
|
+
z-index: var(--ogrid-z-fill-handle, 3);
|
|
276
280
|
}
|
|
277
281
|
|
|
278
282
|
/* === Resize handle === */
|
|
@@ -296,7 +300,7 @@
|
|
|
296
300
|
width: 3px;
|
|
297
301
|
background: var(--ogrid-primary, #217346);
|
|
298
302
|
pointer-events: none;
|
|
299
|
-
z-index: 100;
|
|
303
|
+
z-index: var(--ogrid-z-drop-indicator, 100);
|
|
300
304
|
}
|
|
301
305
|
|
|
302
306
|
/* === Empty state === */
|
|
@@ -324,7 +328,7 @@
|
|
|
324
328
|
.ogrid-loading-overlay {
|
|
325
329
|
position: absolute;
|
|
326
330
|
inset: 0;
|
|
327
|
-
z-index: 2;
|
|
331
|
+
z-index: var(--ogrid-z-loading, 2);
|
|
328
332
|
display: flex;
|
|
329
333
|
align-items: center;
|
|
330
334
|
justify-content: center;
|
|
@@ -6,6 +6,13 @@
|
|
|
6
6
|
|
|
7
7
|
/* ─── Light Theme (default) ─── */
|
|
8
8
|
:where(:root) {
|
|
9
|
+
/* Cell padding — override for row density:
|
|
10
|
+
--ogrid-cell-padding : shorthand (default 6px 10px)
|
|
11
|
+
--ogrid-cell-padding-vertical : vertical only (default 6px)
|
|
12
|
+
--ogrid-cell-padding-horizontal: horizontal only (default 10px) */
|
|
13
|
+
--ogrid-cell-padding: 6px 10px;
|
|
14
|
+
--ogrid-cell-padding-vertical: 6px;
|
|
15
|
+
--ogrid-cell-padding-horizontal: 10px;
|
|
9
16
|
--ogrid-bg: #ffffff;
|
|
10
17
|
--ogrid-fg: rgba(0, 0, 0, 0.87);
|
|
11
18
|
--ogrid-fg-secondary: rgba(0, 0, 0, 0.6);
|
|
@@ -25,6 +25,8 @@ export interface UseFillHandleResult {
|
|
|
25
25
|
startCol: number;
|
|
26
26
|
} | null) => void;
|
|
27
27
|
handleFillHandleMouseDown: (e: MouseEvent) => void;
|
|
28
|
+
/** Fill the current selection down from the top row (Ctrl+D). No-op if no selection or editable=false. */
|
|
29
|
+
fillDown: () => void;
|
|
28
30
|
}
|
|
29
31
|
/**
|
|
30
32
|
* Manages Excel-style fill handle drag-to-fill for cell ranges.
|
|
@@ -37,6 +37,8 @@ export interface UseKeyboardNavigationParams<T> {
|
|
|
37
37
|
rowSelection: Ref<RowSelectionMode>;
|
|
38
38
|
wrapperRef: MaybeShallowRef<HTMLElement | null>;
|
|
39
39
|
scrollToRow?: (index: number, align?: 'start' | 'center' | 'end') => void;
|
|
40
|
+
fillDown?: () => void;
|
|
41
|
+
onKeyDown?: Ref<((event: KeyboardEvent) => void) | undefined>;
|
|
40
42
|
};
|
|
41
43
|
}
|
|
42
44
|
export interface UseKeyboardNavigationResult {
|
|
@@ -5,6 +5,11 @@ export interface UseVirtualScrollParams {
|
|
|
5
5
|
rowHeight: number;
|
|
6
6
|
enabled: Ref<boolean>;
|
|
7
7
|
overscan?: number;
|
|
8
|
+
/**
|
|
9
|
+
* Minimum row count before virtual scrolling activates. Default: 100.
|
|
10
|
+
* When totalRows < threshold, all rows render without virtualization.
|
|
11
|
+
*/
|
|
12
|
+
threshold?: number;
|
|
8
13
|
}
|
|
9
14
|
export interface UseVirtualScrollResult {
|
|
10
15
|
containerRef: Ref<HTMLElement | null>;
|
|
@@ -171,4 +171,6 @@ export interface IOGridDataGridProps<T> {
|
|
|
171
171
|
density?: 'compact' | 'normal' | 'comfortable';
|
|
172
172
|
'aria-label'?: string;
|
|
173
173
|
'aria-labelledby'?: string;
|
|
174
|
+
/** Custom keydown handler. Called before grid's built-in handling. Call event.preventDefault() to suppress grid default. */
|
|
175
|
+
onKeyDown?: (event: KeyboardEvent) => void;
|
|
174
176
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alaarab/ogrid-vue",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.11",
|
|
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.1.
|
|
39
|
+
"@alaarab/ogrid-core": "2.1.11"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
42
|
"vue": "^3.3.0"
|