@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 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 flex-shrink-0 border-r border-border last:border-r-0",
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
- return visibleColumns.reduce((acc, col) => {
4901
- const width = state.columnWidths[col.key] || col.width || estimateColumnWidth(col);
4902
- return acc + width;
4903
- }, 0);
4904
- }, [visibleColumns, state.columnWidths]);
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 = state.columnWidths[column.key] || column.width || estimateColumnWidth(column);
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 = state.columnWidths[column.key] || column.width || estimateColumnWidth(column);
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
- "flex-shrink-0 px-3 py-2 text-sm overflow-hidden",
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 = state.columnWidths[column.key] || column.width || estimateColumnWidth(column);
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 = state.columnWidths[column.key] || column.width || estimateColumnWidth(column);
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
- "flex-shrink-0 px-3 py-2 text-sm overflow-hidden",
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",