@ornery/ui-grid-react 0.1.9 → 0.1.10
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/demo/main.tsx +4 -2
- package/dist/UiGrid.d.ts.map +1 -1
- package/dist/index.js +149 -27
- package/dist/index.mjs +150 -27
- package/dist/ui-grid.css +46 -0
- package/dist/useGridState.d.ts +5 -0
- package/dist/useGridState.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/UiGrid.tsx +22 -6
- package/src/ui-grid.css +46 -0
- package/src/useGridState.ts +168 -20
package/dist/index.mjs
CHANGED
|
@@ -61,6 +61,7 @@ import {
|
|
|
61
61
|
buildGridFocusCellResult,
|
|
62
62
|
findNextGridCell,
|
|
63
63
|
isPrintableGridKey,
|
|
64
|
+
isGridNavigationKey,
|
|
64
65
|
isGridCellPosition,
|
|
65
66
|
exportCsvRows,
|
|
66
67
|
buildGridRows,
|
|
@@ -186,6 +187,7 @@ function useGridState(options, onRegisterApi) {
|
|
|
186
187
|
});
|
|
187
188
|
const [autoViewportHeight, setAutoViewportHeight] = useState(null);
|
|
188
189
|
const [pinnedColumns, setPinnedColumns] = useState({});
|
|
190
|
+
const [columnWidthOverrides, setColumnWidthOverrides] = useState({});
|
|
189
191
|
const gridContainerRef = useRef(null);
|
|
190
192
|
const initializedGridIdRef = useRef(null);
|
|
191
193
|
const lastCanvasHeightRef = useRef(0);
|
|
@@ -223,6 +225,14 @@ function useGridState(options, onRegisterApi) {
|
|
|
223
225
|
currentPageRef.current = currentPage;
|
|
224
226
|
const pageSizeRef = useRef(pageSize);
|
|
225
227
|
pageSizeRef.current = pageSize;
|
|
228
|
+
const setEditingCellState = useCallback((nextEditingCell) => {
|
|
229
|
+
editingCellRef.current = nextEditingCell;
|
|
230
|
+
setEditingCell(nextEditingCell);
|
|
231
|
+
}, []);
|
|
232
|
+
const setEditingValueState = useCallback((nextEditingValue) => {
|
|
233
|
+
editingValueRef.current = nextEditingValue;
|
|
234
|
+
setEditingValue(nextEditingValue);
|
|
235
|
+
}, []);
|
|
226
236
|
const infiniteScrollStateRef = useRef(infiniteScrollState);
|
|
227
237
|
infiniteScrollStateRef.current = infiniteScrollState;
|
|
228
238
|
const optionsRef = useRef(options);
|
|
@@ -230,9 +240,13 @@ function useGridState(options, onRegisterApi) {
|
|
|
230
240
|
const rowSize = options.rowHeight ?? 44;
|
|
231
241
|
const visibleColumns = useMemo(() => {
|
|
232
242
|
const orderedColumns = orderVisibleColumns(options.columnDefs, columnOrder);
|
|
243
|
+
const applyWidthOverrides = (columns) => columns.map((col) => {
|
|
244
|
+
const override = columnWidthOverrides[col.name];
|
|
245
|
+
return override == null ? col : { ...col, width: override };
|
|
246
|
+
});
|
|
233
247
|
const pinnedEntries = Object.entries(pinnedColumns);
|
|
234
248
|
if (pinnedEntries.length === 0) {
|
|
235
|
-
return orderedColumns;
|
|
249
|
+
return applyWidthOverrides(orderedColumns);
|
|
236
250
|
}
|
|
237
251
|
const columnByName = new Map(orderedColumns.map((column) => [column.name, column]));
|
|
238
252
|
const pinnedLeft = pinnedEntries.filter(([, direction]) => direction === "left").map(([columnName]) => columnByName.get(columnName)).filter((column) => column !== void 0);
|
|
@@ -240,8 +254,8 @@ function useGridState(options, onRegisterApi) {
|
|
|
240
254
|
const centerColumns = orderedColumns.filter(
|
|
241
255
|
(column) => pinnedColumns[column.name] === void 0
|
|
242
256
|
);
|
|
243
|
-
return [...pinnedLeft, ...centerColumns, ...pinnedRight];
|
|
244
|
-
}, [options.columnDefs, columnOrder, pinnedColumns]);
|
|
257
|
+
return applyWidthOverrides([...pinnedLeft, ...centerColumns, ...pinnedRight]);
|
|
258
|
+
}, [options.columnDefs, columnOrder, pinnedColumns, columnWidthOverrides]);
|
|
245
259
|
const visibleColumnsRef = useRef(visibleColumns);
|
|
246
260
|
visibleColumnsRef.current = visibleColumns;
|
|
247
261
|
const pipeline = useMemo(() => {
|
|
@@ -378,11 +392,12 @@ function useGridState(options, onRegisterApi) {
|
|
|
378
392
|
if (retry) requestAnimationFrame(() => doFocus(false));
|
|
379
393
|
return;
|
|
380
394
|
}
|
|
381
|
-
target.focus();
|
|
395
|
+
target.focus({ preventScroll: true });
|
|
382
396
|
if (retry && container.ownerDocument.activeElement !== target) {
|
|
383
397
|
requestAnimationFrame(() => doFocus(false));
|
|
384
398
|
}
|
|
385
399
|
};
|
|
400
|
+
doFocus(true);
|
|
386
401
|
queueMicrotask(() => doFocus(true));
|
|
387
402
|
}, []);
|
|
388
403
|
const focusEditorInput = useCallback((focusToken) => {
|
|
@@ -710,8 +725,8 @@ function useGridState(options, onRegisterApi) {
|
|
|
710
725
|
gridApiRef.current,
|
|
711
726
|
{
|
|
712
727
|
setFocusedCell: (fc) => setFocusedCell(fc),
|
|
713
|
-
setEditingCell:
|
|
714
|
-
setEditingValue:
|
|
728
|
+
setEditingCell: setEditingCellState,
|
|
729
|
+
setEditingValue: setEditingValueState
|
|
715
730
|
},
|
|
716
731
|
row,
|
|
717
732
|
column,
|
|
@@ -723,15 +738,15 @@ function useGridState(options, onRegisterApi) {
|
|
|
723
738
|
queueMicrotask(() => focusEditorInput(focusToken));
|
|
724
739
|
}
|
|
725
740
|
},
|
|
726
|
-
[focusEditorInput]
|
|
741
|
+
[focusEditorInput, setEditingCellState, setEditingValueState]
|
|
727
742
|
);
|
|
728
743
|
const commitCellEditFn = useCallback(
|
|
729
744
|
(direction, restoreFocus = true) => {
|
|
730
745
|
const result = commitGridCellEditCommand(gridApiRef.current, {
|
|
731
746
|
getEditingCell: () => editingCellRef.current,
|
|
732
747
|
getEditingValue: () => editingValueRef.current,
|
|
733
|
-
setEditingCell:
|
|
734
|
-
setEditingValue:
|
|
748
|
+
setEditingCell: setEditingCellState,
|
|
749
|
+
setEditingValue: setEditingValueState,
|
|
735
750
|
findRowById: (rowId) => coreFindGridRowById(buildRowsFromData(optionsRef.current.data), rowId),
|
|
736
751
|
findColumnByName: (columnName) => visibleColumnsRef.current.find((c) => c.name === columnName),
|
|
737
752
|
parseEditedValue: (column, value, oldValue) => parseGridEditedValue(column, value, oldValue),
|
|
@@ -749,25 +764,25 @@ function useGridState(options, onRegisterApi) {
|
|
|
749
764
|
focusRenderedCell(result.focusTarget);
|
|
750
765
|
}
|
|
751
766
|
},
|
|
752
|
-
[buildRowsFromData, focusRenderedCell]
|
|
767
|
+
[buildRowsFromData, focusRenderedCell, setEditingCellState, setEditingValueState]
|
|
753
768
|
);
|
|
754
769
|
const cancelCellEditFn = useCallback(() => {
|
|
755
770
|
const hadEditingCell = editingCellRef.current !== null;
|
|
756
771
|
const result = cancelGridCellEditCommand(gridApiRef.current, {
|
|
757
772
|
getEditingCell: () => editingCellRef.current,
|
|
758
|
-
setEditingCell:
|
|
759
|
-
setEditingValue:
|
|
773
|
+
setEditingCell: setEditingCellState,
|
|
774
|
+
setEditingValue: setEditingValueState,
|
|
760
775
|
findRowById: (rowId) => coreFindGridRowById(buildRowsFromData(optionsRef.current.data), rowId),
|
|
761
776
|
findColumnByName: (columnName) => visibleColumnsRef.current.find((c) => c.name === columnName)
|
|
762
777
|
});
|
|
763
778
|
if (!hadEditingCell) return;
|
|
764
779
|
editorFocusTokenRef.current += 1;
|
|
765
780
|
if (result.focusTarget) focusRenderedCell(result.focusTarget);
|
|
766
|
-
}, [buildRowsFromData, focusRenderedCell]);
|
|
781
|
+
}, [buildRowsFromData, focusRenderedCell, setEditingCellState, setEditingValueState]);
|
|
767
782
|
const moveFocusFn = useCallback(
|
|
768
783
|
(row, column, direction, triggerEvent) => {
|
|
769
784
|
const nextCell = findNextGridCell({
|
|
770
|
-
rows: pipelineRef.current.
|
|
785
|
+
rows: pipelineRef.current.displayItems.filter((item) => item.kind === "row").map((item) => item.row),
|
|
771
786
|
columns: visibleColumnsRef.current,
|
|
772
787
|
rowId: row.id,
|
|
773
788
|
columnName: column.name,
|
|
@@ -844,8 +859,8 @@ function useGridState(options, onRegisterApi) {
|
|
|
844
859
|
setHiddenRowReasons({});
|
|
845
860
|
setCollapsedGroups({});
|
|
846
861
|
setFocusedCell(null);
|
|
847
|
-
|
|
848
|
-
|
|
862
|
+
setEditingCellState(null);
|
|
863
|
+
setEditingValueState("");
|
|
849
864
|
setExpandedRows({});
|
|
850
865
|
setExpandedTreeRows({});
|
|
851
866
|
setColumnOrder(options.columnDefs.map((column) => column.name));
|
|
@@ -879,7 +894,7 @@ function useGridState(options, onRegisterApi) {
|
|
|
879
894
|
}
|
|
880
895
|
}, [pipeline, gridApi, rowSize]);
|
|
881
896
|
useEffect(() => {
|
|
882
|
-
if (!FEATURE_AUTO_RESIZE
|
|
897
|
+
if (!FEATURE_AUTO_RESIZE) return;
|
|
883
898
|
const container = gridContainerRef.current;
|
|
884
899
|
if (!container) return;
|
|
885
900
|
const observer = observeGridHostSize(container, ({ height: nextHeight, width: nextWidth }) => {
|
|
@@ -981,6 +996,9 @@ function useGridState(options, onRegisterApi) {
|
|
|
981
996
|
const isFocusedCellFn = useCallback((row, column) => {
|
|
982
997
|
return isGridCellPosition(focusedCellRef.current, row.id, column.name);
|
|
983
998
|
}, []);
|
|
999
|
+
const isFocusedRowFn = useCallback((row) => {
|
|
1000
|
+
return focusedCellRef.current?.rowId === row.id || editingCellRef.current?.rowId === row.id;
|
|
1001
|
+
}, []);
|
|
984
1002
|
const isEditingCellFn = useCallback((row, column) => {
|
|
985
1003
|
return isGridCellPosition(editingCellRef.current, row.id, column.name);
|
|
986
1004
|
}, []);
|
|
@@ -1104,34 +1122,45 @@ function useGridState(options, onRegisterApi) {
|
|
|
1104
1122
|
);
|
|
1105
1123
|
const handleCellKeyDownFn = useCallback(
|
|
1106
1124
|
(row, column, event) => {
|
|
1107
|
-
|
|
1125
|
+
if (isGridNavigationKey(event.key)) {
|
|
1126
|
+
setFocusedCell({ rowId: row.id, columnName: column.name });
|
|
1127
|
+
} else {
|
|
1128
|
+
focusCellFn(row, column, event.nativeEvent);
|
|
1129
|
+
}
|
|
1108
1130
|
switch (event.key) {
|
|
1109
1131
|
case "ArrowLeft":
|
|
1110
1132
|
event.preventDefault();
|
|
1133
|
+
event.stopPropagation();
|
|
1111
1134
|
moveFocusFn(row, column, "left", event.nativeEvent);
|
|
1112
1135
|
return;
|
|
1113
1136
|
case "ArrowRight":
|
|
1114
1137
|
event.preventDefault();
|
|
1138
|
+
event.stopPropagation();
|
|
1115
1139
|
moveFocusFn(row, column, "right", event.nativeEvent);
|
|
1116
1140
|
return;
|
|
1117
1141
|
case "ArrowUp":
|
|
1118
1142
|
event.preventDefault();
|
|
1143
|
+
event.stopPropagation();
|
|
1119
1144
|
moveFocusFn(row, column, "up", event.nativeEvent);
|
|
1120
1145
|
return;
|
|
1121
1146
|
case "ArrowDown":
|
|
1122
1147
|
event.preventDefault();
|
|
1148
|
+
event.stopPropagation();
|
|
1123
1149
|
moveFocusFn(row, column, "down", event.nativeEvent);
|
|
1124
1150
|
return;
|
|
1125
1151
|
case "Tab":
|
|
1126
1152
|
event.preventDefault();
|
|
1153
|
+
event.stopPropagation();
|
|
1127
1154
|
moveFocusFn(row, column, event.shiftKey ? "left" : "right", event.nativeEvent);
|
|
1128
1155
|
return;
|
|
1129
1156
|
case "Enter":
|
|
1130
1157
|
event.preventDefault();
|
|
1158
|
+
event.stopPropagation();
|
|
1131
1159
|
moveFocusFn(row, column, event.shiftKey ? "up" : "down", event.nativeEvent);
|
|
1132
1160
|
return;
|
|
1133
1161
|
case "F2":
|
|
1134
1162
|
event.preventDefault();
|
|
1163
|
+
event.stopPropagation();
|
|
1135
1164
|
if (isCellEditable(row, column, event.nativeEvent)) {
|
|
1136
1165
|
startCellEditFn(row, column, event.nativeEvent);
|
|
1137
1166
|
}
|
|
@@ -1140,6 +1169,7 @@ function useGridState(options, onRegisterApi) {
|
|
|
1140
1169
|
case "Delete":
|
|
1141
1170
|
if (isCellEditable(row, column, event.nativeEvent)) {
|
|
1142
1171
|
event.preventDefault();
|
|
1172
|
+
event.stopPropagation();
|
|
1143
1173
|
startCellEditFn(row, column, event.nativeEvent, "");
|
|
1144
1174
|
}
|
|
1145
1175
|
return;
|
|
@@ -1148,6 +1178,7 @@ function useGridState(options, onRegisterApi) {
|
|
|
1148
1178
|
}
|
|
1149
1179
|
if (isPrintableGridKey(event.key, event.ctrlKey, event.metaKey, event.altKey) && isCellEditable(row, column, event.nativeEvent)) {
|
|
1150
1180
|
event.preventDefault();
|
|
1181
|
+
event.stopPropagation();
|
|
1151
1182
|
startCellEditFn(row, column, event.nativeEvent, event.key);
|
|
1152
1183
|
}
|
|
1153
1184
|
},
|
|
@@ -1163,23 +1194,32 @@ function useGridState(options, onRegisterApi) {
|
|
|
1163
1194
|
[focusCellFn, isCellEditable, startCellEditFn]
|
|
1164
1195
|
);
|
|
1165
1196
|
const updateEditingValueFn = useCallback((value) => {
|
|
1166
|
-
|
|
1167
|
-
}, []);
|
|
1197
|
+
setEditingValueState(value);
|
|
1198
|
+
}, [setEditingValueState]);
|
|
1168
1199
|
const handleEditorKeyDownFn = useCallback(
|
|
1169
1200
|
(event) => {
|
|
1170
1201
|
if (event.key === "Escape") {
|
|
1171
1202
|
event.preventDefault();
|
|
1203
|
+
event.stopPropagation();
|
|
1172
1204
|
cancelCellEditFn();
|
|
1173
1205
|
return;
|
|
1174
1206
|
}
|
|
1175
1207
|
if (event.key === "Enter") {
|
|
1176
1208
|
event.preventDefault();
|
|
1209
|
+
event.stopPropagation();
|
|
1177
1210
|
commitCellEditFn(event.shiftKey ? "up" : "down");
|
|
1178
1211
|
return;
|
|
1179
1212
|
}
|
|
1180
1213
|
if (event.key === "Tab") {
|
|
1181
1214
|
event.preventDefault();
|
|
1215
|
+
event.stopPropagation();
|
|
1182
1216
|
commitCellEditFn(event.shiftKey ? "left" : "right");
|
|
1217
|
+
return;
|
|
1218
|
+
}
|
|
1219
|
+
if (event.key === "ArrowUp" || event.key === "ArrowDown") {
|
|
1220
|
+
event.preventDefault();
|
|
1221
|
+
event.stopPropagation();
|
|
1222
|
+
commitCellEditFn(event.key === "ArrowUp" ? "up" : "down");
|
|
1183
1223
|
}
|
|
1184
1224
|
},
|
|
1185
1225
|
[cancelCellEditFn, commitCellEditFn]
|
|
@@ -1241,6 +1281,72 @@ function useGridState(options, onRegisterApi) {
|
|
|
1241
1281
|
},
|
|
1242
1282
|
[setPaginationPageSizeFn]
|
|
1243
1283
|
);
|
|
1284
|
+
const canResizeColumnsFn = useCallback(() => {
|
|
1285
|
+
return optionsRef.current.enableColumnResizing !== false;
|
|
1286
|
+
}, []);
|
|
1287
|
+
const setColumnWidthOverrideFn = useCallback((columnName, widthPx) => {
|
|
1288
|
+
const nextWidth = `${Math.max(88, Math.round(widthPx))}px`;
|
|
1289
|
+
setColumnWidthOverrides((current) => ({ ...current, [columnName]: nextWidth }));
|
|
1290
|
+
}, []);
|
|
1291
|
+
const measureAutoColumnWidthFn = useCallback((columnName) => {
|
|
1292
|
+
const container = gridContainerRef.current;
|
|
1293
|
+
if (container == null) return 176;
|
|
1294
|
+
const escaped = CSS.escape ? CSS.escape(columnName) : columnName.replace(/([\\".#:[\](){}+~> ])/g, "\\$1");
|
|
1295
|
+
const selectors = [
|
|
1296
|
+
`.header-cell[data-col-name="${escaped}"]`,
|
|
1297
|
+
`.filter-cell[data-col-name="${escaped}"]`,
|
|
1298
|
+
`.body-cell[data-col-name="${escaped}"] .cell-shell`
|
|
1299
|
+
];
|
|
1300
|
+
let maxWidth = 0;
|
|
1301
|
+
for (const selector of selectors) {
|
|
1302
|
+
const elements = container.querySelectorAll(selector);
|
|
1303
|
+
for (const element of elements) {
|
|
1304
|
+
maxWidth = Math.max(maxWidth, element.scrollWidth);
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1307
|
+
return maxWidth + 12;
|
|
1308
|
+
}, []);
|
|
1309
|
+
const handleHeaderResizeMouseDownFn = useCallback(
|
|
1310
|
+
(column, event) => {
|
|
1311
|
+
if (!canResizeColumnsFn()) return;
|
|
1312
|
+
event.preventDefault();
|
|
1313
|
+
event.stopPropagation();
|
|
1314
|
+
const headerCell = event.currentTarget.closest(".header-cell");
|
|
1315
|
+
if (headerCell == null) return;
|
|
1316
|
+
const startX = event.clientX;
|
|
1317
|
+
const startWidth = headerCell.getBoundingClientRect().width;
|
|
1318
|
+
let lastWidth = startWidth;
|
|
1319
|
+
const handleMove = (moveEvent) => {
|
|
1320
|
+
lastWidth = Math.max(88, startWidth + (moveEvent.clientX - startX));
|
|
1321
|
+
const widthStr = `${Math.round(lastWidth)}px`;
|
|
1322
|
+
const newTemplate = buildGridTemplateColumns(
|
|
1323
|
+
visibleColumnsRef.current.map(
|
|
1324
|
+
(c) => c.name === column.name ? { ...c, width: widthStr } : c
|
|
1325
|
+
)
|
|
1326
|
+
);
|
|
1327
|
+
gridContainerRef.current?.querySelectorAll(".header-grid, .filter-grid, .body-grid").forEach((el) => {
|
|
1328
|
+
el.style.gridTemplateColumns = newTemplate;
|
|
1329
|
+
});
|
|
1330
|
+
};
|
|
1331
|
+
const handleUp = () => {
|
|
1332
|
+
window.removeEventListener("mousemove", handleMove);
|
|
1333
|
+
window.removeEventListener("mouseup", handleUp);
|
|
1334
|
+
setColumnWidthOverrideFn(column.name, lastWidth);
|
|
1335
|
+
};
|
|
1336
|
+
window.addEventListener("mousemove", handleMove);
|
|
1337
|
+
window.addEventListener("mouseup", handleUp);
|
|
1338
|
+
},
|
|
1339
|
+
[canResizeColumnsFn, setColumnWidthOverrideFn]
|
|
1340
|
+
);
|
|
1341
|
+
const autoSizeColumnFn = useCallback(
|
|
1342
|
+
(column, event) => {
|
|
1343
|
+
if (!canResizeColumnsFn()) return;
|
|
1344
|
+
event.preventDefault();
|
|
1345
|
+
event.stopPropagation();
|
|
1346
|
+
setColumnWidthOverrideFn(column.name, measureAutoColumnWidthFn(column.name));
|
|
1347
|
+
},
|
|
1348
|
+
[canResizeColumnsFn, setColumnWidthOverrideFn, measureAutoColumnWidthFn]
|
|
1349
|
+
);
|
|
1244
1350
|
const onViewportScrollFn = useCallback((startIndex) => {
|
|
1245
1351
|
if (!scrollingRef.current) {
|
|
1246
1352
|
scrollingRef.current = true;
|
|
@@ -1298,6 +1404,7 @@ function useGridState(options, onRegisterApi) {
|
|
|
1298
1404
|
paginationSelectedPageSize,
|
|
1299
1405
|
rowSize,
|
|
1300
1406
|
viewportHeightPx,
|
|
1407
|
+
autoViewportHeight,
|
|
1301
1408
|
headerLabel: headerLabelFn,
|
|
1302
1409
|
isGroupItem: isGroupItemFn,
|
|
1303
1410
|
isExpandableItem: isExpandableItemFn,
|
|
@@ -1313,6 +1420,7 @@ function useGridState(options, onRegisterApi) {
|
|
|
1313
1420
|
groupDisclosureLabel: groupDisclosureLabelFn,
|
|
1314
1421
|
displayValue: displayValueFn,
|
|
1315
1422
|
isFocusedCell: isFocusedCellFn,
|
|
1423
|
+
isFocusedRow: isFocusedRowFn,
|
|
1316
1424
|
isEditingCell: isEditingCellFn,
|
|
1317
1425
|
editorInputType: editorInputTypeFn,
|
|
1318
1426
|
cellContext: cellContextFn,
|
|
@@ -1359,6 +1467,9 @@ function useGridState(options, onRegisterApi) {
|
|
|
1359
1467
|
toggleTreeRow: toggleTreeRowFn,
|
|
1360
1468
|
moveColumn: moveColumnFn,
|
|
1361
1469
|
moveVisibleColumn: moveVisibleColumnFn,
|
|
1470
|
+
canResizeColumns: canResizeColumnsFn,
|
|
1471
|
+
handleHeaderResizeMouseDown: handleHeaderResizeMouseDownFn,
|
|
1472
|
+
autoSizeColumn: autoSizeColumnFn,
|
|
1362
1473
|
nextPage: nextPageFn,
|
|
1363
1474
|
previousPage: previousPageFn,
|
|
1364
1475
|
onPageSizeChange: onPageSizeChangeFn,
|
|
@@ -1446,6 +1557,7 @@ function UiGrid({
|
|
|
1446
1557
|
virtualizationEnabled,
|
|
1447
1558
|
rowSize,
|
|
1448
1559
|
editingValue,
|
|
1560
|
+
autoViewportHeight,
|
|
1449
1561
|
sortingFeature,
|
|
1450
1562
|
filteringFeature,
|
|
1451
1563
|
groupingFeature,
|
|
@@ -1463,10 +1575,8 @@ function UiGrid({
|
|
|
1463
1575
|
const [headerStickyHeight, setHeaderStickyHeight] = React.useState(0);
|
|
1464
1576
|
const [filterStickyHeight, setFilterStickyHeight] = React.useState(0);
|
|
1465
1577
|
const stickyChromeHeight = headerStickyHeight + filterStickyHeight;
|
|
1466
|
-
const
|
|
1467
|
-
|
|
1468
|
-
(options.viewportHeight ?? 560) - stickyChromeHeight
|
|
1469
|
-
);
|
|
1578
|
+
const resolvedViewportHeight = options.viewportHeight ?? (autoViewportHeight && autoViewportHeight > 0 ? autoViewportHeight : 560);
|
|
1579
|
+
const bodyViewportHeight = Math.max(rowSize, resolvedViewportHeight - stickyChromeHeight);
|
|
1470
1580
|
const virtualScroll = useVirtualScroll({
|
|
1471
1581
|
itemCount: displayItems.length,
|
|
1472
1582
|
itemSize: rowSize,
|
|
@@ -1476,7 +1586,7 @@ function UiGrid({
|
|
|
1476
1586
|
const [openPinMenuColumn, setOpenPinMenuColumn] = React.useState(null);
|
|
1477
1587
|
const [draggedColumnName, setDraggedColumnName] = React.useState(null);
|
|
1478
1588
|
const [dropTargetColumnName, setDropTargetColumnName] = React.useState(null);
|
|
1479
|
-
const scrollContainerHeight = `${
|
|
1589
|
+
const scrollContainerHeight = `${resolvedViewportHeight}px`;
|
|
1480
1590
|
function renderHeaderContent(column) {
|
|
1481
1591
|
const value = state.headerLabel(column);
|
|
1482
1592
|
const context = {
|
|
@@ -1782,6 +1892,7 @@ function UiGrid({
|
|
|
1782
1892
|
if (column.align === "center") classes.push("align-center");
|
|
1783
1893
|
if (column.align === "end") classes.push("align-end");
|
|
1784
1894
|
if (state.isFocusedCell(item.row, column)) classes.push("cell-focused");
|
|
1895
|
+
if (state.isFocusedRow(item.row)) classes.push("row-focused");
|
|
1785
1896
|
if (cellEditFeature && state.isEditingCell(item.row, column)) classes.push("cell-editing");
|
|
1786
1897
|
return classes.join(" ");
|
|
1787
1898
|
}
|
|
@@ -1829,7 +1940,7 @@ function UiGrid({
|
|
|
1829
1940
|
{
|
|
1830
1941
|
className: `header-cell ui-grid-header-cell${sortingFeature && state.sortDirection(column) !== "none" ? " is-active" : ""}${pinned ? " is-pinned" : ""}${pinMenuOpen ? " is-pin-menu-open" : ""}${draggedColumnName === column.name ? " is-dragging" : ""}${dropTargetColumnName === column.name ? " is-drag-target" : ""}`,
|
|
1831
1942
|
"data-part": "header-cell",
|
|
1832
|
-
|
|
1943
|
+
"data-col-name": column.name,
|
|
1833
1944
|
"aria-sort": sortingFeature ? state.sortAriaSort(column) : void 0,
|
|
1834
1945
|
draggable: columnMovingFeature,
|
|
1835
1946
|
onDragStart: (event) => handleHeaderDragStart(column, event),
|
|
@@ -1952,7 +2063,19 @@ function UiGrid({
|
|
|
1952
2063
|
]
|
|
1953
2064
|
}
|
|
1954
2065
|
)
|
|
1955
|
-
] })
|
|
2066
|
+
] }),
|
|
2067
|
+
state.canResizeColumns() && /* @__PURE__ */ jsx(
|
|
2068
|
+
"button",
|
|
2069
|
+
{
|
|
2070
|
+
type: "button",
|
|
2071
|
+
className: "column-resizer",
|
|
2072
|
+
"data-col-name": column.name,
|
|
2073
|
+
"aria-label": `Resize ${state.headerLabel(column)} column`,
|
|
2074
|
+
title: "Drag to resize, double-click to auto fit",
|
|
2075
|
+
onMouseDown: (event) => state.handleHeaderResizeMouseDown(column, event),
|
|
2076
|
+
onDoubleClick: (event) => state.autoSizeColumn(column, event)
|
|
2077
|
+
}
|
|
2078
|
+
)
|
|
1956
2079
|
]
|
|
1957
2080
|
},
|
|
1958
2081
|
column.name
|
package/dist/ui-grid.css
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
.ui-grid-host {
|
|
2
|
+
/* Stretch to fill the parent so the autoresize observer can measure a
|
|
3
|
+
deterministic height. Consumers can override these properties to opt
|
|
4
|
+
back into intrinsic sizing. */
|
|
5
|
+
display: flex;
|
|
6
|
+
flex-direction: column;
|
|
7
|
+
min-height: 0;
|
|
8
|
+
height: 100%;
|
|
2
9
|
--_ui-grid-border-color: var(--ui-grid-border-color, var(--app-ui-grid-border-color, #d4d4d8));
|
|
3
10
|
--_ui-grid-header-background: var(
|
|
4
11
|
--ui-grid-header-background,
|
|
@@ -221,6 +228,12 @@
|
|
|
221
228
|
border: 1px solid var(--ui-grid-border-color);
|
|
222
229
|
box-shadow: var(--ui-grid-shadow);
|
|
223
230
|
overflow: hidden;
|
|
231
|
+
/* Allow the frame to grow inside the flexed host so the body grid can fill
|
|
232
|
+
the available height when no explicit viewportHeight is set. */
|
|
233
|
+
display: flex;
|
|
234
|
+
flex-direction: column;
|
|
235
|
+
flex: 1 1 auto;
|
|
236
|
+
min-height: 0;
|
|
224
237
|
}
|
|
225
238
|
|
|
226
239
|
.metrics-strip {
|
|
@@ -313,6 +326,7 @@
|
|
|
313
326
|
background: var(--ui-grid-header-background);
|
|
314
327
|
font-weight: var(--ui-grid-header-weight);
|
|
315
328
|
align-items: center;
|
|
329
|
+
position: relative;
|
|
316
330
|
}
|
|
317
331
|
|
|
318
332
|
.header-cell[draggable='true'] {
|
|
@@ -337,6 +351,38 @@
|
|
|
337
351
|
z-index: var(--ui-grid-pin-menu-open-z-index);
|
|
338
352
|
}
|
|
339
353
|
|
|
354
|
+
.column-resizer {
|
|
355
|
+
position: absolute;
|
|
356
|
+
top: 0;
|
|
357
|
+
right: -4px;
|
|
358
|
+
width: 8px;
|
|
359
|
+
height: 100%;
|
|
360
|
+
padding: 0;
|
|
361
|
+
border: 0;
|
|
362
|
+
background: transparent;
|
|
363
|
+
cursor: col-resize;
|
|
364
|
+
z-index: 5;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
.column-resizer::after {
|
|
368
|
+
content: '';
|
|
369
|
+
position: absolute;
|
|
370
|
+
top: 20%;
|
|
371
|
+
bottom: 20%;
|
|
372
|
+
left: 50%;
|
|
373
|
+
width: 2px;
|
|
374
|
+
transform: translateX(-50%);
|
|
375
|
+
border-radius: 999px;
|
|
376
|
+
background: color-mix(in srgb, var(--ui-grid-border-color, #888) 80%, transparent);
|
|
377
|
+
opacity: 0;
|
|
378
|
+
transition: opacity 120ms ease;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
.header-cell:hover .column-resizer::after,
|
|
382
|
+
.column-resizer:focus-visible::after {
|
|
383
|
+
opacity: 1;
|
|
384
|
+
}
|
|
385
|
+
|
|
340
386
|
.header-label {
|
|
341
387
|
min-width: 0;
|
|
342
388
|
display: block;
|
package/dist/useGridState.d.ts
CHANGED
|
@@ -30,6 +30,7 @@ export interface UseGridStateResult {
|
|
|
30
30
|
paginationSelectedPageSize: number;
|
|
31
31
|
rowSize: number;
|
|
32
32
|
viewportHeightPx: string;
|
|
33
|
+
autoViewportHeight: number | null;
|
|
33
34
|
headerLabel: (column: GridColumnDef) => string;
|
|
34
35
|
isGroupItem: (item: DisplayItem) => item is GroupItem;
|
|
35
36
|
isExpandableItem: (item: DisplayItem) => item is ExpandableItem;
|
|
@@ -45,6 +46,7 @@ export interface UseGridStateResult {
|
|
|
45
46
|
groupDisclosureLabel: (item: GroupItem) => string;
|
|
46
47
|
displayValue: (row: GridRow, column: GridColumnDef) => string;
|
|
47
48
|
isFocusedCell: (row: GridRow, column: GridColumnDef) => boolean;
|
|
49
|
+
isFocusedRow: (row: GridRow) => boolean;
|
|
48
50
|
isEditingCell: (row: GridRow, column: GridColumnDef) => boolean;
|
|
49
51
|
editorInputType: (column: GridColumnDef) => string;
|
|
50
52
|
cellContext: (row: GridRow, column: GridColumnDef) => GridCellTemplateContext;
|
|
@@ -100,6 +102,9 @@ export interface UseGridStateResult {
|
|
|
100
102
|
toggleTreeRow: (row: GridRow, event?: React.MouseEvent) => void;
|
|
101
103
|
moveColumn: (fromIndex: number, toIndex: number) => void;
|
|
102
104
|
moveVisibleColumn: (columnName: string, targetColumnName: string) => void;
|
|
105
|
+
canResizeColumns: () => boolean;
|
|
106
|
+
handleHeaderResizeMouseDown: (column: GridColumnDef, event: React.MouseEvent) => void;
|
|
107
|
+
autoSizeColumn: (column: GridColumnDef, event: React.MouseEvent) => void;
|
|
103
108
|
nextPage: () => void;
|
|
104
109
|
previousPage: () => void;
|
|
105
110
|
onPageSizeChange: (value: string) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useGridState.d.ts","sourceRoot":"","sources":["../src/useGridState.ts"],"names":[],"mappings":"AASA,OAAO,EAEL,SAAS,EAET,WAAW,EACX,aAAa,EACb,OAAO,EAEP,mBAAmB,EACnB,gBAAgB,EAChB,UAAU,EACV,SAAS,
|
|
1
|
+
{"version":3,"file":"useGridState.d.ts","sourceRoot":"","sources":["../src/useGridState.ts"],"names":[],"mappings":"AASA,OAAO,EAEL,SAAS,EAET,WAAW,EACX,aAAa,EACb,OAAO,EAEP,mBAAmB,EACnB,gBAAgB,EAChB,UAAU,EACV,SAAS,EA+GV,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EACV,WAAW,EACX,SAAS,EACT,cAAc,EACd,OAAO,EACP,cAAc,EACd,uBAAuB,EAEvB,uBAAuB,EACvB,6BAA6B,EAG9B,MAAM,sBAAsB,CAAC;AA+C9B,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,cAAc,CAAC;IACzB,cAAc,EAAE,aAAa,EAAE,CAAC;IAChC,MAAM,EAAE,UAAU,CAAC;IACnB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,OAAO,EAAE,SAAS,CAAC;IACnB,gBAAgB,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAGzD,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACzC,SAAS,EAAE,SAAS,CAAC;IACrB,WAAW,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACrC,WAAW,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACrC,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC1C,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAC5C,mBAAmB,EAAE,uBAAuB,CAAC;IAG7C,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,qBAAqB,EAAE,OAAO,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,0BAA0B,EAAE,MAAM,CAAC;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,MAAM,CAAC;IACzB,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAGlC,WAAW,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,MAAM,CAAC;IAC/C,WAAW,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,IAAI,SAAS,CAAC;IACtD,gBAAgB,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,IAAI,cAAc,CAAC;IAChE,SAAS,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,IAAI,OAAO,CAAC;IAClD,eAAe,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,OAAO,CAAC;IAChD,eAAe,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,MAAM,CAAC;IACnD,YAAY,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,MAAM,CAAC;IAChD,aAAa,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,MAAM,CAAC;IACjD,mBAAmB,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,MAAM,CAAC;IACvD,WAAW,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,MAAM,CAAC;IAC5C,iBAAiB,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,MAAM,CAAC;IACrD,qBAAqB,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,OAAO,CAAC;IAC1D,oBAAoB,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,MAAM,CAAC;IAClD,YAAY,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,KAAK,MAAM,CAAC;IAC9D,aAAa,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,KAAK,OAAO,CAAC;IAChE,YAAY,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC;IACxC,aAAa,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,KAAK,OAAO,CAAC;IAChE,eAAe,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,MAAM,CAAC;IACnD,WAAW,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,KAAK,uBAAuB,CAAC;IAC9E,eAAe,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,6BAA6B,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC3F,WAAW,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,MAAM,CAAC;IAC/C,gBAAgB,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,OAAO,CAAC;IACrD,kBAAkB,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,OAAO,CAAC;IACvD,UAAU,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,KAAK,MAAM,CAAC;IAC5D,eAAe,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,MAAM,CAAC;IAC1C,iBAAiB,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC;IAC7C,iBAAiB,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,MAAM,CAAC;IAC5C,SAAS,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,OAAO,CAAC;IAC9C,cAAc,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,KAAK,OAAO,CAAC;IACjE,gBAAgB,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,KAAK,OAAO,CAAC;IACnE,sBAAsB,EAAE,MAAM,OAAO,CAAC;IACtC,iBAAiB,EAAE,MAAM,MAAM,CAAC;IAChC,eAAe,EAAE,MAAM,MAAM,EAAE,CAAC;IAChC,cAAc,EAAE,CACd,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,aAAa,EACrB,YAAY,CAAC,EAAE,KAAK,GAAG,aAAa,GAAG,IAAI,KACxC,OAAO,CAAC;IACb,iBAAiB,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,OAAO,CAAC;IAGtD,QAAQ,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,OAAO,CAAC;IAC7C,YAAY,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK;QAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC3F,gBAAgB,EAAE,MAAM,OAAO,CAAC;IAChC,gBAAgB,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,OAAO,CAAC;IACrD,SAAS,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,IAAI,CAAC;IAC3C,cAAc,EAAE,OAAO,CAAC;IAGxB,cAAc,EAAE,OAAO,CAAC;IACxB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,eAAe,EAAE,OAAO,CAAC;IACzB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,eAAe,EAAE,OAAO,CAAC;IACzB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,eAAe,EAAE,OAAO,CAAC;IACzB,qBAAqB,EAAE,OAAO,CAAC;IAC/B,mBAAmB,EAAE,OAAO,CAAC;IAC7B,gBAAgB,EAAE,OAAO,CAAC;IAG1B,iBAAiB,EAAE,MAAM,OAAO,CAAC;IACjC,kBAAkB,EAAE,MAAM,OAAO,CAAC;IAGlC,UAAU,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,IAAI,CAAC;IAC5C,YAAY,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1D,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,cAAc,EAAE,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,CAAC,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IAC1E,WAAW,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;IACvC,SAAS,EAAE,CACT,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,aAAa,EACrB,YAAY,CAAC,EAAE,KAAK,GAAG,aAAa,GAAG,IAAI,KACxC,IAAI,CAAC;IACV,iBAAiB,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,KAAK,CAAC,aAAa,KAAK,IAAI,CAAC;IAC7F,qBAAqB,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IAC9F,kBAAkB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,mBAAmB,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,aAAa,KAAK,IAAI,CAAC;IAC1D,gBAAgB,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IACpD,kBAAkB,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IACrE,aAAa,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IAChE,UAAU,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD,iBAAiB,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1E,gBAAgB,EAAE,MAAM,OAAO,CAAC;IAChC,2BAA2B,EAAE,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IACtF,cAAc,EAAE,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IACzE,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,gBAAgB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,YAAY,EAAE,CAAC,UAAU,CAAC,EAAE,MAAM,KAAK,mBAAmB,CAAC;IAC3D,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,gBAAgB,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;CAChD;AAED,wBAAgB,YAAY,CAC1B,OAAO,EAAE,WAAW,EACpB,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,SAAS,KAAK,IAAI,GACvC,kBAAkB,CAkiDpB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ornery/ui-grid-react",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.10",
|
|
4
4
|
"description": "React wrapper for @ornery/ui-grid-core",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"./styles": "./dist/ui-grid.css"
|
|
15
15
|
},
|
|
16
16
|
"peerDependencies": {
|
|
17
|
-
"@ornery/ui-grid-core": "0.1.
|
|
17
|
+
"@ornery/ui-grid-core": "0.1.10",
|
|
18
18
|
"react": "^18.0.0 || ^19.0.0",
|
|
19
19
|
"react-dom": "^18.0.0 || ^19.0.0"
|
|
20
20
|
},
|
package/src/UiGrid.tsx
CHANGED
|
@@ -41,6 +41,7 @@ export function UiGrid({
|
|
|
41
41
|
virtualizationEnabled,
|
|
42
42
|
rowSize,
|
|
43
43
|
editingValue,
|
|
44
|
+
autoViewportHeight,
|
|
44
45
|
sortingFeature,
|
|
45
46
|
filteringFeature,
|
|
46
47
|
groupingFeature,
|
|
@@ -59,10 +60,12 @@ export function UiGrid({
|
|
|
59
60
|
const [headerStickyHeight, setHeaderStickyHeight] = React.useState(0);
|
|
60
61
|
const [filterStickyHeight, setFilterStickyHeight] = React.useState(0);
|
|
61
62
|
const stickyChromeHeight = headerStickyHeight + filterStickyHeight;
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
63
|
+
// Prefer the explicit viewportHeight, otherwise fall back to the container
|
|
64
|
+
// height measured by the autoresize observer so the grid fills its parent
|
|
65
|
+
// by default. The 560 fallback only applies before the first measurement.
|
|
66
|
+
const resolvedViewportHeight =
|
|
67
|
+
options.viewportHeight ?? (autoViewportHeight && autoViewportHeight > 0 ? autoViewportHeight : 560);
|
|
68
|
+
const bodyViewportHeight = Math.max(rowSize, resolvedViewportHeight - stickyChromeHeight);
|
|
66
69
|
|
|
67
70
|
const virtualScroll = useVirtualScroll({
|
|
68
71
|
itemCount: displayItems.length,
|
|
@@ -74,7 +77,7 @@ export function UiGrid({
|
|
|
74
77
|
const [openPinMenuColumn, setOpenPinMenuColumn] = React.useState<string | null>(null);
|
|
75
78
|
const [draggedColumnName, setDraggedColumnName] = React.useState<string | null>(null);
|
|
76
79
|
const [dropTargetColumnName, setDropTargetColumnName] = React.useState<string | null>(null);
|
|
77
|
-
const scrollContainerHeight = `${
|
|
80
|
+
const scrollContainerHeight = `${resolvedViewportHeight}px`;
|
|
78
81
|
|
|
79
82
|
function renderHeaderContent(column: GridColumnDef): React.ReactNode {
|
|
80
83
|
const value = state.headerLabel(column);
|
|
@@ -414,6 +417,7 @@ export function UiGrid({
|
|
|
414
417
|
if (column.align === 'center') classes.push('align-center');
|
|
415
418
|
if (column.align === 'end') classes.push('align-end');
|
|
416
419
|
if (state.isFocusedCell(item.row, column)) classes.push('cell-focused');
|
|
420
|
+
if (state.isFocusedRow(item.row)) classes.push('row-focused');
|
|
417
421
|
if (cellEditFeature && state.isEditingCell(item.row, column)) classes.push('cell-editing');
|
|
418
422
|
return classes.join(' ');
|
|
419
423
|
}
|
|
@@ -474,7 +478,7 @@ export function UiGrid({
|
|
|
474
478
|
key={column.name}
|
|
475
479
|
className={`header-cell ui-grid-header-cell${sortingFeature && state.sortDirection(column) !== 'none' ? ' is-active' : ''}${pinned ? ' is-pinned' : ''}${pinMenuOpen ? ' is-pin-menu-open' : ''}${draggedColumnName === column.name ? ' is-dragging' : ''}${dropTargetColumnName === column.name ? ' is-drag-target' : ''}`}
|
|
476
480
|
data-part="header-cell"
|
|
477
|
-
|
|
481
|
+
data-col-name={column.name}
|
|
478
482
|
aria-sort={sortingFeature ? (state.sortAriaSort(column) as any) : undefined}
|
|
479
483
|
draggable={columnMovingFeature}
|
|
480
484
|
onDragStart={(event) => handleHeaderDragStart(column, event)}
|
|
@@ -596,6 +600,18 @@ export function UiGrid({
|
|
|
596
600
|
</div>
|
|
597
601
|
)}
|
|
598
602
|
</div>
|
|
603
|
+
|
|
604
|
+
{state.canResizeColumns() && (
|
|
605
|
+
<button
|
|
606
|
+
type="button"
|
|
607
|
+
className="column-resizer"
|
|
608
|
+
data-col-name={column.name}
|
|
609
|
+
aria-label={`Resize ${state.headerLabel(column)} column`}
|
|
610
|
+
title="Drag to resize, double-click to auto fit"
|
|
611
|
+
onMouseDown={(event) => state.handleHeaderResizeMouseDown(column, event)}
|
|
612
|
+
onDoubleClick={(event) => state.autoSizeColumn(column, event)}
|
|
613
|
+
/>
|
|
614
|
+
)}
|
|
599
615
|
</div>
|
|
600
616
|
);
|
|
601
617
|
})}
|