@optilogic/core 1.3.0 → 1.3.1
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/index.cjs +80 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -2
- package/dist/index.d.ts +15 -2
- package/dist/index.js +80 -25
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/data-grid/DataGrid.tsx +66 -24
- package/src/components/data-grid/components/HeaderCell.tsx +5 -1
- package/src/components/data-grid/hooks/useColumnResize.ts +30 -1
- package/src/components/data-grid/types.ts +5 -0
package/dist/index.cjs
CHANGED
|
@@ -3471,6 +3471,7 @@ function HeaderCell({
|
|
|
3471
3471
|
sorting,
|
|
3472
3472
|
filter,
|
|
3473
3473
|
isResizable,
|
|
3474
|
+
fillWidth,
|
|
3474
3475
|
onSort,
|
|
3475
3476
|
onFilterChange,
|
|
3476
3477
|
onResizeMouseDown,
|
|
@@ -3514,7 +3515,8 @@ function HeaderCell({
|
|
|
3514
3515
|
"div",
|
|
3515
3516
|
{
|
|
3516
3517
|
className: cn(
|
|
3517
|
-
"relative
|
|
3518
|
+
"relative border-r border-border last:border-r-0",
|
|
3519
|
+
!fillWidth && "flex-shrink-0",
|
|
3518
3520
|
"bg-muted select-none",
|
|
3519
3521
|
isResizing && "bg-accent/20"
|
|
3520
3522
|
),
|
|
@@ -4454,11 +4456,15 @@ function useColumnResizeManager(options) {
|
|
|
4454
4456
|
resizableColumns,
|
|
4455
4457
|
onColumnResize,
|
|
4456
4458
|
onColumnResizeStart,
|
|
4457
|
-
onColumnResizeEnd
|
|
4459
|
+
onColumnResizeEnd,
|
|
4460
|
+
fillWidth,
|
|
4461
|
+
containerWidth,
|
|
4462
|
+
effectiveColumnWidths
|
|
4458
4463
|
} = options;
|
|
4459
4464
|
const [resizingColumn, setResizingColumn] = React20.useState(null);
|
|
4460
4465
|
const startXRef = React20.useRef(0);
|
|
4461
4466
|
const startWidthRef = React20.useRef(0);
|
|
4467
|
+
const startEffectiveWidthsRef = React20.useRef({});
|
|
4462
4468
|
const getColumn = React20.useCallback(
|
|
4463
4469
|
(columnKey) => {
|
|
4464
4470
|
return columns.find((c) => c.key === columnKey);
|
|
@@ -4482,9 +4488,20 @@ function useColumnResizeManager(options) {
|
|
|
4482
4488
|
resizingColumn,
|
|
4483
4489
|
startWidthRef.current + deltaX
|
|
4484
4490
|
);
|
|
4491
|
+
if (fillWidth && containerWidth) {
|
|
4492
|
+
const otherCols = columns.filter((c) => c.key !== resizingColumn);
|
|
4493
|
+
const startEffective = startEffectiveWidthsRef.current;
|
|
4494
|
+
const otherTotal = otherCols.reduce((s, c) => s + (startEffective[c.key] || 0), 0);
|
|
4495
|
+
const remaining = containerWidth - newWidth;
|
|
4496
|
+
for (const col of otherCols) {
|
|
4497
|
+
const proportion = (startEffective[col.key] || 0) / otherTotal;
|
|
4498
|
+
const adjusted = clampWidth(col.key, Math.floor(remaining * proportion));
|
|
4499
|
+
onColumnResize(col.key, adjusted);
|
|
4500
|
+
}
|
|
4501
|
+
}
|
|
4485
4502
|
onColumnResize(resizingColumn, newWidth);
|
|
4486
4503
|
},
|
|
4487
|
-
[resizingColumn, clampWidth, onColumnResize]
|
|
4504
|
+
[resizingColumn, clampWidth, onColumnResize, fillWidth, containerWidth, columns]
|
|
4488
4505
|
);
|
|
4489
4506
|
const handleMouseUp = React20.useCallback(() => {
|
|
4490
4507
|
if (!resizingColumn) return;
|
|
@@ -4518,6 +4535,9 @@ function useColumnResizeManager(options) {
|
|
|
4518
4535
|
document.body.style.userSelect = "none";
|
|
4519
4536
|
document.body.style.cursor = "col-resize";
|
|
4520
4537
|
onColumnResizeStart?.(columnKey);
|
|
4538
|
+
if (fillWidth && effectiveColumnWidths) {
|
|
4539
|
+
startEffectiveWidthsRef.current = { ...effectiveColumnWidths };
|
|
4540
|
+
}
|
|
4521
4541
|
};
|
|
4522
4542
|
const handleDoubleClick = (event) => {
|
|
4523
4543
|
if (!isResizable) return;
|
|
@@ -4543,7 +4563,9 @@ function useColumnResizeManager(options) {
|
|
|
4543
4563
|
resizingColumn,
|
|
4544
4564
|
onColumnResize,
|
|
4545
4565
|
onColumnResizeStart,
|
|
4546
|
-
onColumnResizeEnd
|
|
4566
|
+
onColumnResizeEnd,
|
|
4567
|
+
fillWidth,
|
|
4568
|
+
effectiveColumnWidths
|
|
4547
4569
|
]
|
|
4548
4570
|
);
|
|
4549
4571
|
return {
|
|
@@ -4768,6 +4790,7 @@ function DataGrid({
|
|
|
4768
4790
|
tooltipMinLength = 30,
|
|
4769
4791
|
enableKeyboardNavigation = true,
|
|
4770
4792
|
showColumnBorders = true,
|
|
4793
|
+
fillWidth,
|
|
4771
4794
|
enableInternalSorting = true,
|
|
4772
4795
|
enableInternalFiltering = true,
|
|
4773
4796
|
// Controlled sorting
|
|
@@ -4822,6 +4845,16 @@ function DataGrid({
|
|
|
4822
4845
|
const headerRef = React20__namespace.useRef(null);
|
|
4823
4846
|
const [headerHeight, setHeaderHeight] = React20__namespace.useState(40);
|
|
4824
4847
|
const [hoveredCell, setHoveredCell] = React20__namespace.useState(null);
|
|
4848
|
+
const [containerWidth, setContainerWidth] = React20__namespace.useState(0);
|
|
4849
|
+
React20__namespace.useLayoutEffect(() => {
|
|
4850
|
+
if (!fillWidth || !parentRef.current) return;
|
|
4851
|
+
const observer = new ResizeObserver((entries) => {
|
|
4852
|
+
const w = entries[0]?.contentRect.width;
|
|
4853
|
+
if (w && w > 0) setContainerWidth(w);
|
|
4854
|
+
});
|
|
4855
|
+
observer.observe(parentRef.current);
|
|
4856
|
+
return () => observer.disconnect();
|
|
4857
|
+
}, [fillWidth]);
|
|
4825
4858
|
const visibleColumns = React20__namespace.useMemo(
|
|
4826
4859
|
() => columns.filter((col) => !col.hidden),
|
|
4827
4860
|
[columns]
|
|
@@ -4875,14 +4908,6 @@ function DataGrid({
|
|
|
4875
4908
|
visibleColumns
|
|
4876
4909
|
]);
|
|
4877
4910
|
processedDataRef.current = processedData;
|
|
4878
|
-
const { resizingColumn, getResizeProps } = useColumnResizeManager({
|
|
4879
|
-
columns: visibleColumns,
|
|
4880
|
-
columnWidths: state.columnWidths,
|
|
4881
|
-
resizableColumns,
|
|
4882
|
-
onColumnResize: actions.setColumnWidth,
|
|
4883
|
-
onColumnResizeStart,
|
|
4884
|
-
onColumnResizeEnd
|
|
4885
|
-
});
|
|
4886
4911
|
const shouldVirtualize = virtualized ?? processedData.length > 100;
|
|
4887
4912
|
React20__namespace.useLayoutEffect(() => {
|
|
4888
4913
|
if (headerRef.current && shouldVirtualize) {
|
|
@@ -4896,12 +4921,38 @@ function DataGrid({
|
|
|
4896
4921
|
overscan: DEFAULT_OVERSCAN,
|
|
4897
4922
|
enabled: shouldVirtualize
|
|
4898
4923
|
});
|
|
4899
|
-
const tableWidth = React20__namespace.useMemo(() => {
|
|
4900
|
-
|
|
4901
|
-
|
|
4902
|
-
|
|
4903
|
-
|
|
4904
|
-
|
|
4924
|
+
const { tableWidth, effectiveColumnWidths } = React20__namespace.useMemo(() => {
|
|
4925
|
+
const rawWidths = {};
|
|
4926
|
+
let rawTotal = 0;
|
|
4927
|
+
for (const col of visibleColumns) {
|
|
4928
|
+
const w = state.columnWidths[col.key] || col.width || estimateColumnWidth(col);
|
|
4929
|
+
rawWidths[col.key] = w;
|
|
4930
|
+
rawTotal += w;
|
|
4931
|
+
}
|
|
4932
|
+
if (!fillWidth || !containerWidth || rawTotal >= containerWidth) {
|
|
4933
|
+
return { tableWidth: rawTotal, effectiveColumnWidths: rawWidths };
|
|
4934
|
+
}
|
|
4935
|
+
const scale = containerWidth / rawTotal;
|
|
4936
|
+
const scaled = {};
|
|
4937
|
+
for (const col of visibleColumns) {
|
|
4938
|
+
let w = Math.floor(rawWidths[col.key] * scale);
|
|
4939
|
+
if (col.minWidth) w = Math.max(w, col.minWidth);
|
|
4940
|
+
if (col.maxWidth) w = Math.min(w, col.maxWidth);
|
|
4941
|
+
scaled[col.key] = w;
|
|
4942
|
+
}
|
|
4943
|
+
return { tableWidth: containerWidth, effectiveColumnWidths: scaled };
|
|
4944
|
+
}, [visibleColumns, state.columnWidths, fillWidth, containerWidth]);
|
|
4945
|
+
const { resizingColumn, getResizeProps } = useColumnResizeManager({
|
|
4946
|
+
columns: visibleColumns,
|
|
4947
|
+
columnWidths: state.columnWidths,
|
|
4948
|
+
resizableColumns,
|
|
4949
|
+
onColumnResize: actions.setColumnWidth,
|
|
4950
|
+
onColumnResizeStart,
|
|
4951
|
+
onColumnResizeEnd,
|
|
4952
|
+
fillWidth,
|
|
4953
|
+
containerWidth,
|
|
4954
|
+
effectiveColumnWidths
|
|
4955
|
+
});
|
|
4905
4956
|
const visibleRowCount = React20__namespace.useMemo(() => {
|
|
4906
4957
|
if (!parentRef.current) return 10;
|
|
4907
4958
|
return Math.floor(parentRef.current.clientHeight / DEFAULT_ROW_HEIGHT);
|
|
@@ -5133,7 +5184,7 @@ function DataGrid({
|
|
|
5133
5184
|
},
|
|
5134
5185
|
role: "row",
|
|
5135
5186
|
children: visibleColumns.map((column, colIndex) => {
|
|
5136
|
-
const width =
|
|
5187
|
+
const width = effectiveColumnWidths[column.key];
|
|
5137
5188
|
const resizeProps = getResizeProps(column.key);
|
|
5138
5189
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
5139
5190
|
HeaderCell,
|
|
@@ -5144,6 +5195,7 @@ function DataGrid({
|
|
|
5144
5195
|
sorting: getColumnSort(column.key),
|
|
5145
5196
|
filter: getColumnFilter(column.key),
|
|
5146
5197
|
isResizable: resizableColumns && column.resizable !== false,
|
|
5198
|
+
fillWidth,
|
|
5147
5199
|
onSort: () => handleSort(column.key),
|
|
5148
5200
|
onFilterChange: (filter) => handleFilterChange(column.key, filter),
|
|
5149
5201
|
onResizeMouseDown: resizeProps.handleMouseDown,
|
|
@@ -5192,7 +5244,7 @@ function DataGrid({
|
|
|
5192
5244
|
"aria-rowindex": virtualRow.index + 1,
|
|
5193
5245
|
"aria-selected": isSelected,
|
|
5194
5246
|
children: visibleColumns.map((column, colIndex) => {
|
|
5195
|
-
const width =
|
|
5247
|
+
const width = effectiveColumnWidths[column.key];
|
|
5196
5248
|
const isEditingThisCell = state.editingCell?.rowIndex === virtualRow.index && state.editingCell?.columnKey === column.key;
|
|
5197
5249
|
const isFocused = state.focusedCell?.rowIndex === virtualRow.index && state.focusedCell?.columnKey === column.key;
|
|
5198
5250
|
const cellContent = renderCell(
|
|
@@ -5207,7 +5259,8 @@ function DataGrid({
|
|
|
5207
5259
|
"div",
|
|
5208
5260
|
{
|
|
5209
5261
|
className: cn(
|
|
5210
|
-
"
|
|
5262
|
+
"px-3 py-2 text-sm overflow-hidden",
|
|
5263
|
+
!fillWidth && "flex-shrink-0",
|
|
5211
5264
|
showColumnBorders && "border-r border-border last:border-r-0",
|
|
5212
5265
|
isFocused && !isEditingThisCell && "ring-2 ring-inset ring-primary",
|
|
5213
5266
|
isEditingThisCell && "ring-2 ring-inset ring-primary bg-background",
|
|
@@ -5319,7 +5372,7 @@ function DataGrid({
|
|
|
5319
5372
|
}
|
|
5320
5373
|
)
|
|
5321
5374
|
] }) }),
|
|
5322
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 overflow-auto min-h-0", children: [
|
|
5375
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { ref: parentRef, className: "flex-1 overflow-auto min-h-0", children: [
|
|
5323
5376
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5324
5377
|
"div",
|
|
5325
5378
|
{
|
|
@@ -5330,7 +5383,7 @@ function DataGrid({
|
|
|
5330
5383
|
style: { width: tableWidth ? `${tableWidth}px` : "100%" },
|
|
5331
5384
|
role: "row",
|
|
5332
5385
|
children: visibleColumns.map((column, colIndex) => {
|
|
5333
|
-
const width =
|
|
5386
|
+
const width = effectiveColumnWidths[column.key];
|
|
5334
5387
|
const resizeProps = getResizeProps(column.key);
|
|
5335
5388
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
5336
5389
|
HeaderCell,
|
|
@@ -5341,6 +5394,7 @@ function DataGrid({
|
|
|
5341
5394
|
sorting: getColumnSort(column.key),
|
|
5342
5395
|
filter: getColumnFilter(column.key),
|
|
5343
5396
|
isResizable: resizableColumns && column.resizable !== false,
|
|
5397
|
+
fillWidth,
|
|
5344
5398
|
onSort: () => handleSort(column.key),
|
|
5345
5399
|
onFilterChange: (filter) => handleFilterChange(column.key, filter),
|
|
5346
5400
|
onResizeMouseDown: resizeProps.handleMouseDown,
|
|
@@ -5370,14 +5424,15 @@ function DataGrid({
|
|
|
5370
5424
|
onDoubleClick: () => onRowDoubleClick?.(row, rowIndex),
|
|
5371
5425
|
role: "row",
|
|
5372
5426
|
children: visibleColumns.map((column) => {
|
|
5373
|
-
const width =
|
|
5427
|
+
const width = effectiveColumnWidths[column.key];
|
|
5374
5428
|
const isEditingThisCell = state.editingCell?.rowIndex === rowIndex && state.editingCell?.columnKey === column.key;
|
|
5375
5429
|
const isFocused = state.focusedCell?.rowIndex === rowIndex && state.focusedCell?.columnKey === column.key;
|
|
5376
5430
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
5377
5431
|
"div",
|
|
5378
5432
|
{
|
|
5379
5433
|
className: cn(
|
|
5380
|
-
"
|
|
5434
|
+
"px-3 py-2 text-sm overflow-hidden",
|
|
5435
|
+
!fillWidth && "flex-shrink-0",
|
|
5381
5436
|
showColumnBorders && "border-r border-border last:border-r-0",
|
|
5382
5437
|
isFocused && !isEditingThisCell && "ring-2 ring-inset ring-primary",
|
|
5383
5438
|
isEditingThisCell && "ring-2 ring-inset ring-primary bg-background",
|