@alaarab/ogrid-react 2.1.13 → 2.1.14

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
@@ -971,23 +971,94 @@ var ROW_NUMBER_COLUMN_WIDTH = 50;
971
971
  var DEFAULT_MIN_COLUMN_WIDTH = 80;
972
972
  var CELL_PADDING = 16;
973
973
  var GRID_BORDER_RADIUS = 6;
974
- var AUTOSIZE_EXTRA_PX = 28;
974
+ var AUTOSIZE_EXTRA_PX = 16;
975
975
  var AUTOSIZE_MAX_PX = 520;
976
+ function measureHeaderWidth(th) {
977
+ const cs = getComputedStyle(th);
978
+ const thPadding = (parseFloat(cs.paddingLeft) || 0) + (parseFloat(cs.paddingRight) || 0);
979
+ let resizeHandleWidth = 0;
980
+ for (let i = 0; i < th.children.length; i++) {
981
+ const child = th.children[i];
982
+ const cls = child.className || "";
983
+ if (cls.includes("resizeHandle") || cls.includes("resize-handle") || cls.includes("ogrid-resize-handle")) {
984
+ resizeHandleWidth = child.offsetWidth;
985
+ break;
986
+ }
987
+ }
988
+ const contentContainer = th.firstElementChild;
989
+ if (!contentContainer) return th.offsetWidth;
990
+ const modified = [];
991
+ const expandDescendants = (parent) => {
992
+ for (let i = 0; i < parent.children.length; i++) {
993
+ const child = parent.children[i];
994
+ const style = getComputedStyle(child);
995
+ if (style.overflow === "hidden" || style.flexShrink !== "0") {
996
+ modified.push({
997
+ el: child,
998
+ overflow: child.style.overflow,
999
+ flexShrink: child.style.flexShrink,
1000
+ width: child.style.width,
1001
+ minWidth: child.style.minWidth
1002
+ });
1003
+ child.style.overflow = "visible";
1004
+ child.style.flexShrink = "0";
1005
+ child.style.width = "max-content";
1006
+ child.style.minWidth = "max-content";
1007
+ }
1008
+ expandDescendants(child);
1009
+ }
1010
+ };
1011
+ const origPos = contentContainer.style.position;
1012
+ const origWidth = contentContainer.style.width;
1013
+ contentContainer.style.position = "absolute";
1014
+ contentContainer.style.width = "max-content";
1015
+ expandDescendants(contentContainer);
1016
+ const expandedWidth = contentContainer.offsetWidth;
1017
+ contentContainer.style.position = origPos;
1018
+ contentContainer.style.width = origWidth;
1019
+ for (const m of modified) {
1020
+ m.el.style.overflow = m.overflow;
1021
+ m.el.style.flexShrink = m.flexShrink;
1022
+ m.el.style.width = m.width;
1023
+ m.el.style.minWidth = m.minWidth;
1024
+ }
1025
+ return expandedWidth + resizeHandleWidth + thPadding;
1026
+ }
976
1027
  function measureColumnContentWidth(columnId, minWidth, container) {
977
1028
  const minW = minWidth ?? DEFAULT_MIN_COLUMN_WIDTH;
978
- const root = document;
1029
+ const root = container ?? document;
979
1030
  const cells = root.querySelectorAll(`[data-column-id="${columnId}"]`);
980
1031
  if (cells.length === 0) return minW;
981
1032
  let maxWidth = minW;
1033
+ const contentEls = [];
1034
+ const origPositions = [];
1035
+ const origWidths = [];
982
1036
  cells.forEach((cell) => {
983
1037
  const el = cell;
984
- const label = el.querySelector?.("[data-header-label]");
985
- if (label) {
986
- maxWidth = Math.max(maxWidth, label.scrollWidth + AUTOSIZE_EXTRA_PX);
1038
+ const isHeader = !!el.querySelector?.("[data-header-label]");
1039
+ if (isHeader) {
1040
+ maxWidth = Math.max(maxWidth, measureHeaderWidth(el));
987
1041
  } else {
988
- maxWidth = Math.max(maxWidth, el.scrollWidth);
1042
+ const content = el.firstElementChild ?? el;
1043
+ contentEls.push(content);
989
1044
  }
990
1045
  });
1046
+ if (contentEls.length > 0) {
1047
+ for (let i = 0; i < contentEls.length; i++) {
1048
+ const el = contentEls[i];
1049
+ origPositions.push(el.style.position);
1050
+ origWidths.push(el.style.width);
1051
+ el.style.position = "absolute";
1052
+ el.style.width = "max-content";
1053
+ }
1054
+ for (let i = 0; i < contentEls.length; i++) {
1055
+ maxWidth = Math.max(maxWidth, contentEls[i].offsetWidth + AUTOSIZE_EXTRA_PX);
1056
+ }
1057
+ for (let i = 0; i < contentEls.length; i++) {
1058
+ contentEls[i].style.position = origPositions[i];
1059
+ contentEls[i].style.width = origWidths[i];
1060
+ }
1061
+ }
991
1062
  return Math.min(AUTOSIZE_MAX_PX, Math.max(minW, Math.ceil(maxWidth)));
992
1063
  }
993
1064
  function findCtrlArrowTarget(pos, edge, step, isEmpty) {
@@ -3318,7 +3389,8 @@ function useTableLayout(params) {
3318
3389
  const rect = el.getBoundingClientRect();
3319
3390
  const cs = window.getComputedStyle(el);
3320
3391
  const borderX = (parseFloat(cs.borderLeftWidth || "0") || 0) + (parseFloat(cs.borderRightWidth || "0") || 0);
3321
- setContainerWidth(Math.max(0, rect.width - borderX));
3392
+ const next = Math.round(Math.max(0, rect.width - borderX));
3393
+ setContainerWidth((prev) => prev === next ? prev : next);
3322
3394
  };
3323
3395
  const ro = new ResizeObserver(measure);
3324
3396
  ro.observe(el);
@@ -3623,6 +3695,11 @@ function useDataGridLayout(params) {
3623
3695
  pinnedColumns,
3624
3696
  onColumnPinned
3625
3697
  });
3698
+ const overridesKey = useMemo(() => {
3699
+ const entries = Object.entries(columnSizingOverrides);
3700
+ if (entries.length === 0) return "";
3701
+ return entries.map(([id, v]) => `${id}:${Math.round(v.widthPx)}`).join(",");
3702
+ }, [columnSizingOverrides]);
3626
3703
  const [measuredColumnWidths, setMeasuredColumnWidths] = useState({});
3627
3704
  useLayoutEffect(() => {
3628
3705
  const wrapper = wrapperRef.current;
@@ -3641,7 +3718,7 @@ function useDataGridLayout(params) {
3641
3718
  if (Object.keys(prev).length !== Object.keys(measured).length) return measured;
3642
3719
  return prev;
3643
3720
  });
3644
- }, [visibleCols, columnSizingOverrides, wrapperRef]);
3721
+ }, [visibleCols, overridesKey, wrapperRef]);
3645
3722
  const columnWidthMap = useMemo(() => {
3646
3723
  const map = {};
3647
3724
  for (const col of visibleCols) {
@@ -4736,10 +4813,25 @@ function useColumnResize({
4736
4813
  document.addEventListener("mouseup", onUp);
4737
4814
  cleanupRef.current = cleanup;
4738
4815
  }, [defaultWidth, minWidth, setColumnSizingOverrides, columnSizingOverridesRef]);
4816
+ const handleResizeDoubleClick = useCallback((e, col) => {
4817
+ e.preventDefault();
4818
+ e.stopPropagation();
4819
+ const columnId = col.columnId;
4820
+ const thEl = e.currentTarget.closest("th");
4821
+ const container = thEl?.closest("table")?.parentElement ?? void 0;
4822
+ const idealWidth = measureColumnContentWidth(columnId, minWidth, container);
4823
+ setColumnSizingOverrides((prev) => ({
4824
+ ...prev,
4825
+ [columnId]: { widthPx: idealWidth }
4826
+ }));
4827
+ if (onColumnResizedRef.current) {
4828
+ onColumnResizedRef.current(columnId, idealWidth);
4829
+ }
4830
+ }, [minWidth, setColumnSizingOverrides]);
4739
4831
  const getColumnWidth = useCallback((col) => {
4740
4832
  return columnSizingOverrides[col.columnId]?.widthPx ?? col.idealWidth ?? col.defaultWidth ?? defaultWidth;
4741
4833
  }, [columnSizingOverrides, defaultWidth]);
4742
- return { handleResizeStart, getColumnWidth };
4834
+ return { handleResizeStart, handleResizeDoubleClick, getColumnWidth };
4743
4835
  }
4744
4836
  function getSelectDisplayText(value, formatValue) {
4745
4837
  if (formatValue) return formatValue(value);
@@ -6071,7 +6163,7 @@ function useDataGridTableOrchestration(params) {
6071
6163
  const headerRows = useMemo(() => buildHeaderRows(columns, visibleColumns), [columns, visibleColumns]);
6072
6164
  const allowOverflowX = !suppressHorizontalScroll && containerWidth > 0 && (minTableWidth > containerWidth || desiredTableWidth > containerWidth);
6073
6165
  const fitToContent = layoutMode === "content";
6074
- const { handleResizeStart, getColumnWidth } = useColumnResize({
6166
+ const { handleResizeStart, handleResizeDoubleClick, getColumnWidth } = useColumnResize({
6075
6167
  columnSizingOverrides,
6076
6168
  setColumnSizingOverrides
6077
6169
  });
@@ -6135,6 +6227,7 @@ function useDataGridTableOrchestration(params) {
6135
6227
  pinning,
6136
6228
  // Column resize
6137
6229
  handleResizeStart,
6230
+ handleResizeDoubleClick,
6138
6231
  getColumnWidth,
6139
6232
  // Column reorder
6140
6233
  isReorderDragging,
@@ -13,6 +13,7 @@ export interface UseColumnResizeParams {
13
13
  }
14
14
  export interface UseColumnResizeResult<T> {
15
15
  handleResizeStart: (e: React.MouseEvent, col: IColumnDef<T>) => void;
16
+ handleResizeDoubleClick: (e: React.MouseEvent, col: IColumnDef<T>) => void;
16
17
  getColumnWidth: (col: IColumnDef<T>) => number;
17
18
  }
18
19
  /**
@@ -24,6 +24,7 @@ export interface UseDataGridTableOrchestrationResult<T> {
24
24
  viewModels: DataGridViewModelState<T>;
25
25
  pinning: DataGridPinningState;
26
26
  handleResizeStart: UseColumnResizeResult<T>['handleResizeStart'];
27
+ handleResizeDoubleClick: UseColumnResizeResult<T>['handleResizeDoubleClick'];
27
28
  getColumnWidth: UseColumnResizeResult<T>['getColumnWidth'];
28
29
  isReorderDragging: UseColumnReorderResult['isDragging'];
29
30
  dropIndicatorX: UseColumnReorderResult['dropIndicatorX'];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alaarab/ogrid-react",
3
- "version": "2.1.13",
3
+ "version": "2.1.14",
4
4
  "description": "OGrid React – React hooks, headless components, and utilities for OGrid data grids.",
5
5
  "main": "dist/esm/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -39,7 +39,7 @@
39
39
  "node": ">=18"
40
40
  },
41
41
  "dependencies": {
42
- "@alaarab/ogrid-core": "2.1.13",
42
+ "@alaarab/ogrid-core": "2.1.14",
43
43
  "@tanstack/react-virtual": "^3.0.0"
44
44
  },
45
45
  "peerDependencies": {