From 823f45800b3eebaa4214c5502b7100aabd7d0827 Mon Sep 17 00:00:00 2001 From: Nataly Merezhuk Date: Mon, 3 Feb 2025 12:01:47 -0500 Subject: [PATCH 01/18] Adds isOnlyRow prop and xpands cell to auto height if isOnlyRow. --- src/components/Grid/Cell.tsx | 3 +- src/components/Grid/Grid.tsx | 95 +++++++++++++++++++----------- src/components/Grid/StyledCell.tsx | 8 ++- 3 files changed, 68 insertions(+), 38 deletions(-) diff --git a/src/components/Grid/Cell.tsx b/src/components/Grid/Cell.tsx index a107e287..9fb96d12 100644 --- a/src/components/Grid/Cell.tsx +++ b/src/components/Grid/Cell.tsx @@ -59,7 +59,7 @@ export const Cell = memo( const selectionBorderLeft = rightOfSelectionBorder || rightOfFocus || isFocused; const selectionBorderTop = belowSelectionBorder || belowFocus || isFocused; - + console.log("Only row? ",rowCount === 1 ) return (
diff --git a/src/components/Grid/Grid.tsx b/src/components/Grid/Grid.tsx index e1fe99b6..eb8fce2d 100644 --- a/src/components/Grid/Grid.tsx +++ b/src/components/Grid/Grid.tsx @@ -777,14 +777,36 @@ export const Grid = forwardRef( }, [rowStart, onItemsRendered]); const CellWithWidth = (args: GridChildComponentProps): JSX.Element => { - const width = columnWidth(args.columnIndex); - return ( - - ); - }; + const width = columnWidth(args.columnIndex); + return ( + + ); +}; + + useEffect(() => { + if (gridRef.current) { + gridRef.current.resetAfterRowIndex(0); + } + }, [rowCount]); + + const getRowHeight = useCallback( + (index: number, parentHeight: number): number => { + const headerHeight = 33; + + // For single data row case + if (rowCount === 1 && index === 0) { + console.log("Returning parentheight - headerheight", parentHeight, parentHeight - headerHeight) + return parentHeight - headerHeight*2; + } + + console.log("Returning rowheight ", rowHeight) + return rowHeight; // Default row height for multiple rows + }, + [rowCount, rowHeight] + ); return ( ( $showBorder={showBorder} > - {({ height, width }) => ( - rowHeight} - useIsScrolling={useIsScrolling} - innerElementType={InnerElementType} - itemData={data} - initialScrollTop={ - focus.row < rowStart - ? focus.row * rowHeight - : (focus.row - rowStart) * rowHeight - } - initialScrollLeft={getColumnHorizontalPosition(focus.column)} - columnWidth={columnWidth} - rowCount={rowCount} - onScroll={onScroll} - outerRef={outerRef} - outerElementType={OuterElementType} - onItemsRendered={onItemsRendered} - {...props} - > - {CellWithWidth} - - )} + {({ height, width }) => { + console.log('Parent container height:', height); + return ( + getRowHeight(index, height)} + useIsScrolling={useIsScrolling} + innerElementType={InnerElementType} + itemData={data} + initialScrollTop={ + focus.row < rowStart + ? focus.row * rowHeight + : (focus.row - rowStart) * rowHeight + } + initialScrollLeft={getColumnHorizontalPosition(focus.column)} + columnWidth={columnWidth} + rowCount={rowCount} + onScroll={onScroll} + outerRef={outerRef} + outerElementType={OuterElementType} + onItemsRendered={onItemsRendered} + {...props} + > + {CellWithWidth} + + ) + }} diff --git a/src/components/Grid/StyledCell.tsx b/src/components/Grid/StyledCell.tsx index 1b6bb906..c2d4e50a 100644 --- a/src/components/Grid/StyledCell.tsx +++ b/src/components/Grid/StyledCell.tsx @@ -13,6 +13,7 @@ export const StyledCell = styled.div<{ $height: number; $type?: "body" | "header"; $showBorder: boolean; + $isOnlyRow?: boolean; }>` display: block; text-align: left; @@ -34,8 +35,9 @@ export const StyledCell = styled.div<{ $height, $type = "body", $showBorder, + $isOnlyRow }) => ` - height: ${$height}px; + height: ${$isOnlyRow ? "100%" : `${$height}px`}; background: ${theme.click.grid[$type].cell.color.background[$selectionType]}; color: ${ $type === "header" @@ -95,10 +97,12 @@ export const StyledCell = styled.div<{ $type = "body", $isSelectedTop, $isSelectedLeft, + $isOnlyRow }) => $isSelectedTop || $isSelectedLeft || - ($selectionType === "selectDirect" && ($isLastRow || $isLastColumn)) + ($selectionType === "selectDirect" && ($isLastRow || $isLastColumn)) || + $isOnlyRow ? ` &::before { content: ""; From a85986019e3b973c173c496159900fbcaae4a8f0 Mon Sep 17 00:00:00 2001 From: Nataly Merezhuk Date: Mon, 3 Feb 2025 17:23:00 -0500 Subject: [PATCH 02/18] Adds styling for isOnlyRow prop. --- src/components/Grid/Grid.tsx | 65 +++++++++++++----------------- src/components/Grid/StyledCell.tsx | 13 +++++- 2 files changed, 40 insertions(+), 38 deletions(-) diff --git a/src/components/Grid/Grid.tsx b/src/components/Grid/Grid.tsx index eb8fce2d..3026f643 100644 --- a/src/components/Grid/Grid.tsx +++ b/src/components/Grid/Grid.tsx @@ -794,16 +794,12 @@ export const Grid = forwardRef( const getRowHeight = useCallback( (index: number, parentHeight: number): number => { - const headerHeight = 33; - // For single data row case if (rowCount === 1 && index === 0) { - console.log("Returning parentheight - headerheight", parentHeight, parentHeight - headerHeight) - return parentHeight - headerHeight*2; + return parentHeight - rowHeight*2; } - console.log("Returning rowheight ", rowHeight) - return rowHeight; // Default row height for multiple rows + return rowHeight; }, [rowCount, rowHeight] ); @@ -836,36 +832,33 @@ export const Grid = forwardRef( $showBorder={showBorder} > - {({ height, width }) => { - console.log('Parent container height:', height); - return ( - getRowHeight(index, height)} - useIsScrolling={useIsScrolling} - innerElementType={InnerElementType} - itemData={data} - initialScrollTop={ - focus.row < rowStart - ? focus.row * rowHeight - : (focus.row - rowStart) * rowHeight - } - initialScrollLeft={getColumnHorizontalPosition(focus.column)} - columnWidth={columnWidth} - rowCount={rowCount} - onScroll={onScroll} - outerRef={outerRef} - outerElementType={OuterElementType} - onItemsRendered={onItemsRendered} - {...props} - > - {CellWithWidth} - - ) - }} + {({ height, width }) => ( + getRowHeight(index, height)} + useIsScrolling={useIsScrolling} + innerElementType={InnerElementType} + itemData={data} + initialScrollTop={ + focus.row < rowStart + ? focus.row * rowHeight + : (focus.row - rowStart) * rowHeight + } + initialScrollLeft={getColumnHorizontalPosition(focus.column)} + columnWidth={columnWidth} + rowCount={rowCount} + onScroll={onScroll} + outerRef={outerRef} + outerElementType={OuterElementType} + onItemsRendered={onItemsRendered} + {...props} + > + {CellWithWidth} + + )} diff --git a/src/components/Grid/StyledCell.tsx b/src/components/Grid/StyledCell.tsx index c2d4e50a..f6d3976f 100644 --- a/src/components/Grid/StyledCell.tsx +++ b/src/components/Grid/StyledCell.tsx @@ -35,9 +35,10 @@ export const StyledCell = styled.div<{ $height, $type = "body", $showBorder, - $isOnlyRow + $isOnlyRow, }) => ` - height: ${$isOnlyRow ? "100%" : `${$height}px`}; + height: ${$isOnlyRow ? "auto" : `${$height}px`}; + overflow-y: ${$isOnlyRow ? "auto" : "hidden"}; background: ${theme.click.grid[$type].cell.color.background[$selectionType]}; color: ${ $type === "header" @@ -88,6 +89,10 @@ export const StyledCell = styled.div<{ ` : "border-right: none;" } + ${ + $isOnlyRow + && "border: none;" + } `} ${({ theme, @@ -131,6 +136,10 @@ export const StyledCell = styled.div<{ ? `border-right: 1px solid ${theme.click.grid[$type].cell.color.stroke.selectDirect};` : "" } + ${ + $isOnlyRow + && "border: none;" + } } ` : ""}; From 5db69add8941a4ea0fb10e7993a7f5e65e607aad Mon Sep 17 00:00:00 2001 From: Nataly Merezhuk Date: Mon, 3 Feb 2025 17:31:40 -0500 Subject: [PATCH 03/18] Adds prettier and comment. --- src/components/Grid/Cell.tsx | 12 +++--------- src/components/Grid/Grid.tsx | 25 +++++++++++++------------ src/components/Grid/StyledCell.tsx | 12 +++--------- 3 files changed, 19 insertions(+), 30 deletions(-) diff --git a/src/components/Grid/Cell.tsx b/src/components/Grid/Cell.tsx index 9fb96d12..66ae281c 100644 --- a/src/components/Grid/Cell.tsx +++ b/src/components/Grid/Cell.tsx @@ -5,16 +5,10 @@ import { StyledCell } from "./StyledCell"; type CellProps = GridChildComponentProps & { width: number; -} +}; export const Cell = memo( - ({ - data, - rowIndex, - columnIndex, - style, - ...props - }: CellProps) => { + ({ data, rowIndex, columnIndex, style, ...props }: CellProps) => { const { cell: CellData, getSelectionType, @@ -59,7 +53,7 @@ export const Cell = memo( const selectionBorderLeft = rightOfSelectionBorder || rightOfFocus || isFocused; const selectionBorderTop = belowSelectionBorder || belowFocus || isFocused; - console.log("Only row? ",rowCount === 1 ) + console.log("Only row? ", rowCount === 1); return (
( }, [rowStart, onItemsRendered]); const CellWithWidth = (args: GridChildComponentProps): JSX.Element => { - const width = columnWidth(args.columnIndex); - return ( - - ); -}; + const width = columnWidth(args.columnIndex); + return ( + + ); + }; + // Handles the case when rowCount changes, expanding the cell height + // to fit content if there is only one row. useEffect(() => { if (gridRef.current) { gridRef.current.resetAfterRowIndex(0); @@ -794,11 +796,10 @@ export const Grid = forwardRef( const getRowHeight = useCallback( (index: number, parentHeight: number): number => { - if (rowCount === 1 && index === 0) { - return parentHeight - rowHeight*2; + return parentHeight - rowHeight * 2; } - + return rowHeight; }, [rowCount, rowHeight] @@ -858,7 +859,7 @@ export const Grid = forwardRef( > {CellWithWidth} - )} + )} diff --git a/src/components/Grid/StyledCell.tsx b/src/components/Grid/StyledCell.tsx index f6d3976f..529f3a7c 100644 --- a/src/components/Grid/StyledCell.tsx +++ b/src/components/Grid/StyledCell.tsx @@ -89,10 +89,7 @@ export const StyledCell = styled.div<{ ` : "border-right: none;" } - ${ - $isOnlyRow - && "border: none;" - } + ${$isOnlyRow && "border: none;"} `} ${({ theme, @@ -102,7 +99,7 @@ export const StyledCell = styled.div<{ $type = "body", $isSelectedTop, $isSelectedLeft, - $isOnlyRow + $isOnlyRow, }) => $isSelectedTop || $isSelectedLeft || @@ -136,10 +133,7 @@ export const StyledCell = styled.div<{ ? `border-right: 1px solid ${theme.click.grid[$type].cell.color.stroke.selectDirect};` : "" } - ${ - $isOnlyRow - && "border: none;" - } + ${$isOnlyRow && "border: none;"} } ` : ""}; From 5cda6dcb3948e128efcf2b8ef012ea7e390031a3 Mon Sep 17 00:00:00 2001 From: Nataly Merezhuk Date: Tue, 4 Feb 2025 08:49:49 -0500 Subject: [PATCH 04/18] Removes console.log --- src/components/Grid/Cell.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/Grid/Cell.tsx b/src/components/Grid/Cell.tsx index 66ae281c..4f036cc1 100644 --- a/src/components/Grid/Cell.tsx +++ b/src/components/Grid/Cell.tsx @@ -53,7 +53,6 @@ export const Cell = memo( const selectionBorderLeft = rightOfSelectionBorder || rightOfFocus || isFocused; const selectionBorderTop = belowSelectionBorder || belowFocus || isFocused; - console.log("Only row? ", rowCount === 1); return (
Date: Tue, 4 Feb 2025 12:31:56 -0500 Subject: [PATCH 05/18] Adds story to test autoheight. --- src/components/Grid/Grid.stories.tsx | 108 +++++++++++++++++++++++++++ src/components/Grid/Grid.tsx | 2 + src/components/Grid/types.ts | 1 + 3 files changed, 111 insertions(+) diff --git a/src/components/Grid/Grid.stories.tsx b/src/components/Grid/Grid.stories.tsx index 9cbd5767..e5b90a51 100644 --- a/src/components/Grid/Grid.stories.tsx +++ b/src/components/Grid/Grid.stories.tsx @@ -20,6 +20,7 @@ interface Props { row: number; column: number; }; + autoheight?: boolean; } const Grid = ({ columnCount, rowCount, focus: focusProp, ...props }: Props) => { const [focus, setFocus] = useState(focusProp); @@ -71,6 +72,7 @@ const Grid = ({ columnCount, rowCount, focus: focusProp, ...props }: Props) => { }); }} getMenuOptions={getMenuOptions} + autoheight={props.autoheight} {...props} />
@@ -121,3 +123,109 @@ export const Playground = { }, }, }; + +export const AutoHeightWithVariableData = { + args: { + rowCount: 10, + columnCount: 5, + autoheight: true, + rowStart: 0, + }, + parameters: { + docs: { + source: { + transform: (_: string, story: { args: Props; [x: string]: unknown }) => { + const { rowCount, columnCount, autoheight, ...props } = story.args; + return ` +const VariableCell: CellProps = ({ type, rowIndex, columnIndex, isScrolling, width, ...props }) => { + let content = \`Row \${rowIndex}, Col \${columnIndex}\${rowIndex % 2 === 0 ? '\\nExtra line' : ''}\`; + + if (rowIndex === 0 && columnIndex === 0) { + content = \`CREATE TABLE random_user_events ( + user_id UInt32, + event_time DateTime, + event_type Enum8('click' = 1, 'view' = 2, 'purchase' = 3), + item_id String, + price Decimal(10,2), + quantity UInt16 +) ENGINE = MergeTree() +ORDER BY (user_id, event_time) +PARTITION BY toYYYYMM(event_time) +SETTINGS index_granularity = 8192;\`; + } + + return ( +
+ {content} +
+ ); +}; + + 300} + autoheight={${autoheight}} +${Object.entries(props) + .flatMap(([key, value]) => + typeof value === "boolean" + ? value + ? ` ${key}` + : [] + : ` ${key}=${typeof value == "string" ? `"${value}"` : `{${value}}`}` + ) + .join("\n")} +/> +`; + }, + }, + }, + }, + render: (args) => { + const VariableCell: CellProps = ({ type, rowIndex, columnIndex, isScrolling, width, ...props }) => { + let content = `Row ${rowIndex}, Col ${columnIndex}${rowIndex % 2 === 0 ? '\nExtra line' : ''}`; + + if (rowIndex === 0 && columnIndex === 0) { + content = `CREATE TABLE random_user_events ( + user_id UInt32, + event_time DateTime, + event_type Enum8('click' = 1, 'view' = 2, 'purchase' = 3), + item_id String, + price Decimal(10,2), + quantity UInt16 +) ENGINE = MergeTree() +ORDER BY (user_id, event_time) +PARTITION BY toYYYYMM(event_time) +SETTINGS index_granularity = 8192;`; + } + + return ( +
+ {content} +
+ ); + }; + + return 300} />; + }, +}; diff --git a/src/components/Grid/Grid.tsx b/src/components/Grid/Grid.tsx index 182ded49..8b64de76 100644 --- a/src/components/Grid/Grid.tsx +++ b/src/components/Grid/Grid.tsx @@ -149,6 +149,7 @@ export const Grid = forwardRef( onContextMenu: onContextMenuProp, forwardedGridRef, onItemsRendered: onItemsRenderedProp, + rowAutoHeight, ...props }, forwardedRef @@ -777,6 +778,7 @@ export const Grid = forwardRef( }, [rowStart, onItemsRendered]); const CellWithWidth = (args: GridChildComponentProps): JSX.Element => { + console.log("Cell with width ", rowAutoHeight) const width = columnWidth(args.columnIndex); return ( void; onContextMenu?: MouseEventHandler; forwardedGridRef?: MutableRefObject; + rowAutoHeight?: boolean; } export type ResizerPosition = { From acc1208761324376ee6d8512b2341f658ac4ef2d Mon Sep 17 00:00:00 2001 From: Nataly Merezhuk Date: Tue, 4 Feb 2025 18:17:16 -0500 Subject: [PATCH 06/18] Adds rowAutoHeight prop and removes isOnlyRow prop. --- src/components/Grid/Cell.tsx | 3 +- src/components/Grid/Grid.stories.tsx | 117 ++---------------------- src/components/Grid/Grid.tsx | 16 +--- src/components/Grid/RowNumberColumn.tsx | 6 ++ src/components/Grid/StyledCell.tsx | 16 ++-- src/components/Grid/types.ts | 1 + 6 files changed, 28 insertions(+), 131 deletions(-) diff --git a/src/components/Grid/Cell.tsx b/src/components/Grid/Cell.tsx index 4f036cc1..8a4e4f28 100644 --- a/src/components/Grid/Cell.tsx +++ b/src/components/Grid/Cell.tsx @@ -19,6 +19,7 @@ export const Cell = memo( showHeader, rowHeight, rowStart, + rowAutoHeight, } = data; const currentRowIndex = rowIndex + rowStart; @@ -78,7 +79,7 @@ export const Cell = memo( data-grid-row={currentRowIndex} data-grid-column={columnIndex} $showBorder - $isOnlyRow={rowCount === 1} + $rowAutoHeight={rowAutoHeight} {...props} />
diff --git a/src/components/Grid/Grid.stories.tsx b/src/components/Grid/Grid.stories.tsx index e5b90a51..d4552e95 100644 --- a/src/components/Grid/Grid.stories.tsx +++ b/src/components/Grid/Grid.stories.tsx @@ -2,7 +2,14 @@ import { useCallback, useEffect, useState } from "react"; import { CellProps, GridContextMenuItemProps, SelectedRegion, SelectionFocus } from ".."; import { Grid as CUIGrid } from "./Grid"; -const Cell: CellProps = ({ type, rowIndex, columnIndex, isScrolling, width, ...props }) => { +const Cell: CellProps = ({ + type, + rowIndex, + columnIndex, + isScrolling, + width, + ...props +}) => { return (
{ const [focus, setFocus] = useState(focusProp); @@ -72,7 +78,6 @@ const Grid = ({ columnCount, rowCount, focus: focusProp, ...props }: Props) => { }); }} getMenuOptions={getMenuOptions} - autoheight={props.autoheight} {...props} />
@@ -123,109 +128,3 @@ export const Playground = { }, }, }; - -export const AutoHeightWithVariableData = { - args: { - rowCount: 10, - columnCount: 5, - autoheight: true, - rowStart: 0, - }, - parameters: { - docs: { - source: { - transform: (_: string, story: { args: Props; [x: string]: unknown }) => { - const { rowCount, columnCount, autoheight, ...props } = story.args; - return ` -const VariableCell: CellProps = ({ type, rowIndex, columnIndex, isScrolling, width, ...props }) => { - let content = \`Row \${rowIndex}, Col \${columnIndex}\${rowIndex % 2 === 0 ? '\\nExtra line' : ''}\`; - - if (rowIndex === 0 && columnIndex === 0) { - content = \`CREATE TABLE random_user_events ( - user_id UInt32, - event_time DateTime, - event_type Enum8('click' = 1, 'view' = 2, 'purchase' = 3), - item_id String, - price Decimal(10,2), - quantity UInt16 -) ENGINE = MergeTree() -ORDER BY (user_id, event_time) -PARTITION BY toYYYYMM(event_time) -SETTINGS index_granularity = 8192;\`; - } - - return ( -
- {content} -
- ); -}; - - 300} - autoheight={${autoheight}} -${Object.entries(props) - .flatMap(([key, value]) => - typeof value === "boolean" - ? value - ? ` ${key}` - : [] - : ` ${key}=${typeof value == "string" ? `"${value}"` : `{${value}}`}` - ) - .join("\n")} -/> -`; - }, - }, - }, - }, - render: (args) => { - const VariableCell: CellProps = ({ type, rowIndex, columnIndex, isScrolling, width, ...props }) => { - let content = `Row ${rowIndex}, Col ${columnIndex}${rowIndex % 2 === 0 ? '\nExtra line' : ''}`; - - if (rowIndex === 0 && columnIndex === 0) { - content = `CREATE TABLE random_user_events ( - user_id UInt32, - event_time DateTime, - event_type Enum8('click' = 1, 'view' = 2, 'purchase' = 3), - item_id String, - price Decimal(10,2), - quantity UInt16 -) ENGINE = MergeTree() -ORDER BY (user_id, event_time) -PARTITION BY toYYYYMM(event_time) -SETTINGS index_granularity = 8192;`; - } - - return ( -
- {content} -
- ); - }; - - return 300} />; - }, -}; diff --git a/src/components/Grid/Grid.tsx b/src/components/Grid/Grid.tsx index 8b64de76..82787355 100644 --- a/src/components/Grid/Grid.tsx +++ b/src/components/Grid/Grid.tsx @@ -406,6 +406,7 @@ export const Grid = forwardRef( headerHeight, rowNumberWidth, rowStart, + rowAutoHeight, }; const InnerElementType = forwardRef( @@ -436,6 +437,7 @@ export const Grid = forwardRef( showHeader={showHeader} rowStart={rowStart} showBorder={showBorder} + rowAutoHeight={rowAutoHeight} /> )} @@ -778,7 +780,6 @@ export const Grid = forwardRef( }, [rowStart, onItemsRendered]); const CellWithWidth = (args: GridChildComponentProps): JSX.Element => { - console.log("Cell with width ", rowAutoHeight) const width = columnWidth(args.columnIndex); return ( ( } }, [rowCount]); - const getRowHeight = useCallback( - (index: number, parentHeight: number): number => { - if (rowCount === 1 && index === 0) { - return parentHeight - rowHeight * 2; - } - - return rowHeight; - }, - [rowCount, rowHeight] - ); - return ( ( height={height} width={width} columnCount={columnCount} - rowHeight={index => getRowHeight(index, height)} + rowHeight={() => rowHeight} useIsScrolling={useIsScrolling} innerElementType={InnerElementType} itemData={data} diff --git a/src/components/Grid/RowNumberColumn.tsx b/src/components/Grid/RowNumberColumn.tsx index feed1bc9..e42375a6 100644 --- a/src/components/Grid/RowNumberColumn.tsx +++ b/src/components/Grid/RowNumberColumn.tsx @@ -47,6 +47,7 @@ interface RowNumberColumnProps { scrolledHorizontal: boolean; rowStart: number; showBorder: boolean; + rowAutoHeight?: boolean; } interface RowNumberProps extends Pick< @@ -56,6 +57,7 @@ interface RowNumberProps rowIndex: number; isLastRow: boolean; isFirstRow: boolean; + rowAutoHeight?: boolean; } const RowNumber = ({ rowIndex, @@ -65,6 +67,7 @@ const RowNumber = ({ isFirstRow, showBorder, rowStart, + rowAutoHeight }: RowNumberProps) => { const currentRowIndex = rowIndex + rowStart; const selectionType = getSelectionType({ @@ -96,6 +99,7 @@ const RowNumber = ({ $isLastRow={isLastRow} $isSelectedLeft={isSelected} $isSelectedTop={isSelectedTop} + $rowAutoHeight={rowAutoHeight} data-selected={isSelected} data-grid-row={currentRowIndex} data-grid-column={-1} @@ -121,6 +125,7 @@ const RowNumberColumn = ({ scrolledHorizontal, rowStart = 0, showBorder, + rowAutoHeight }: RowNumberColumnProps) => { return ( ) )} diff --git a/src/components/Grid/StyledCell.tsx b/src/components/Grid/StyledCell.tsx index 529f3a7c..3c9cd166 100644 --- a/src/components/Grid/StyledCell.tsx +++ b/src/components/Grid/StyledCell.tsx @@ -13,7 +13,7 @@ export const StyledCell = styled.div<{ $height: number; $type?: "body" | "header"; $showBorder: boolean; - $isOnlyRow?: boolean; + $rowAutoHeight?: boolean; }>` display: block; text-align: left; @@ -35,10 +35,10 @@ export const StyledCell = styled.div<{ $height, $type = "body", $showBorder, - $isOnlyRow, + $rowAutoHeight, }) => ` - height: ${$isOnlyRow ? "auto" : `${$height}px`}; - overflow-y: ${$isOnlyRow ? "auto" : "hidden"}; + height: ${$rowAutoHeight ? "auto" : `${$height}px`}; + overflow-y: ${$rowAutoHeight ? "auto" : "hidden"}; background: ${theme.click.grid[$type].cell.color.background[$selectionType]}; color: ${ $type === "header" @@ -89,7 +89,7 @@ export const StyledCell = styled.div<{ ` : "border-right: none;" } - ${$isOnlyRow && "border: none;"} + ${$rowAutoHeight && "border: none;"} `} ${({ theme, @@ -99,12 +99,12 @@ export const StyledCell = styled.div<{ $type = "body", $isSelectedTop, $isSelectedLeft, - $isOnlyRow, + $rowAutoHeight, }) => $isSelectedTop || $isSelectedLeft || ($selectionType === "selectDirect" && ($isLastRow || $isLastColumn)) || - $isOnlyRow + $rowAutoHeight ? ` &::before { content: ""; @@ -133,7 +133,7 @@ export const StyledCell = styled.div<{ ? `border-right: 1px solid ${theme.click.grid[$type].cell.color.stroke.selectDirect};` : "" } - ${$isOnlyRow && "border: none;"} + ${$rowAutoHeight && "border: none;"} } ` : ""}; diff --git a/src/components/Grid/types.ts b/src/components/Grid/types.ts index e972ae26..f0c63de4 100644 --- a/src/components/Grid/types.ts +++ b/src/components/Grid/types.ts @@ -157,6 +157,7 @@ export interface ItemDataType { headerHeight: number; rowNumberWidth: number; rowStart: number; + rowAutoHeight?: boolean; } export interface GridContextMenuItemProps extends Omit { From c8b1668cd8e5c99b4ef688979cdc602e8847d598 Mon Sep 17 00:00:00 2001 From: Nataly Merezhuk Date: Thu, 6 Feb 2025 10:50:30 -0500 Subject: [PATCH 07/18] Adds rowHeight story. --- src/components/Grid/Grid.stories.tsx | 117 +++++++++++++++++++++++++-- 1 file changed, 109 insertions(+), 8 deletions(-) diff --git a/src/components/Grid/Grid.stories.tsx b/src/components/Grid/Grid.stories.tsx index d4552e95..e5b90a51 100644 --- a/src/components/Grid/Grid.stories.tsx +++ b/src/components/Grid/Grid.stories.tsx @@ -2,14 +2,7 @@ import { useCallback, useEffect, useState } from "react"; import { CellProps, GridContextMenuItemProps, SelectedRegion, SelectionFocus } from ".."; import { Grid as CUIGrid } from "./Grid"; -const Cell: CellProps = ({ - type, - rowIndex, - columnIndex, - isScrolling, - width, - ...props -}) => { +const Cell: CellProps = ({ type, rowIndex, columnIndex, isScrolling, width, ...props }) => { return (
{ const [focus, setFocus] = useState(focusProp); @@ -78,6 +72,7 @@ const Grid = ({ columnCount, rowCount, focus: focusProp, ...props }: Props) => { }); }} getMenuOptions={getMenuOptions} + autoheight={props.autoheight} {...props} />
@@ -128,3 +123,109 @@ export const Playground = { }, }, }; + +export const AutoHeightWithVariableData = { + args: { + rowCount: 10, + columnCount: 5, + autoheight: true, + rowStart: 0, + }, + parameters: { + docs: { + source: { + transform: (_: string, story: { args: Props; [x: string]: unknown }) => { + const { rowCount, columnCount, autoheight, ...props } = story.args; + return ` +const VariableCell: CellProps = ({ type, rowIndex, columnIndex, isScrolling, width, ...props }) => { + let content = \`Row \${rowIndex}, Col \${columnIndex}\${rowIndex % 2 === 0 ? '\\nExtra line' : ''}\`; + + if (rowIndex === 0 && columnIndex === 0) { + content = \`CREATE TABLE random_user_events ( + user_id UInt32, + event_time DateTime, + event_type Enum8('click' = 1, 'view' = 2, 'purchase' = 3), + item_id String, + price Decimal(10,2), + quantity UInt16 +) ENGINE = MergeTree() +ORDER BY (user_id, event_time) +PARTITION BY toYYYYMM(event_time) +SETTINGS index_granularity = 8192;\`; + } + + return ( +
+ {content} +
+ ); +}; + + 300} + autoheight={${autoheight}} +${Object.entries(props) + .flatMap(([key, value]) => + typeof value === "boolean" + ? value + ? ` ${key}` + : [] + : ` ${key}=${typeof value == "string" ? `"${value}"` : `{${value}}`}` + ) + .join("\n")} +/> +`; + }, + }, + }, + }, + render: (args) => { + const VariableCell: CellProps = ({ type, rowIndex, columnIndex, isScrolling, width, ...props }) => { + let content = `Row ${rowIndex}, Col ${columnIndex}${rowIndex % 2 === 0 ? '\nExtra line' : ''}`; + + if (rowIndex === 0 && columnIndex === 0) { + content = `CREATE TABLE random_user_events ( + user_id UInt32, + event_time DateTime, + event_type Enum8('click' = 1, 'view' = 2, 'purchase' = 3), + item_id String, + price Decimal(10,2), + quantity UInt16 +) ENGINE = MergeTree() +ORDER BY (user_id, event_time) +PARTITION BY toYYYYMM(event_time) +SETTINGS index_granularity = 8192;`; + } + + return ( +
+ {content} +
+ ); + }; + + return 300} />; + }, +}; From 4553538a55abc264bda2f462d8949a0c7ce97c47 Mon Sep 17 00:00:00 2001 From: Nataly Merezhuk Date: Thu, 6 Feb 2025 11:01:26 -0500 Subject: [PATCH 08/18] Corrects the story --- src/components/Grid/Grid.stories.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/Grid/Grid.stories.tsx b/src/components/Grid/Grid.stories.tsx index e5b90a51..d5bcd6f6 100644 --- a/src/components/Grid/Grid.stories.tsx +++ b/src/components/Grid/Grid.stories.tsx @@ -20,7 +20,7 @@ interface Props { row: number; column: number; }; - autoheight?: boolean; + rowAutoHeight?: boolean; } const Grid = ({ columnCount, rowCount, focus: focusProp, ...props }: Props) => { const [focus, setFocus] = useState(focusProp); @@ -72,7 +72,7 @@ const Grid = ({ columnCount, rowCount, focus: focusProp, ...props }: Props) => { }); }} getMenuOptions={getMenuOptions} - autoheight={props.autoheight} + rowAutoHeight={props.rowAutoHeight} {...props} /> @@ -128,14 +128,14 @@ export const AutoHeightWithVariableData = { args: { rowCount: 10, columnCount: 5, - autoheight: true, + rowAutoHeight: true, rowStart: 0, }, parameters: { docs: { source: { transform: (_: string, story: { args: Props; [x: string]: unknown }) => { - const { rowCount, columnCount, autoheight, ...props } = story.args; + const { rowCount, columnCount, rowAutoHeight, ...props } = story.args; return ` const VariableCell: CellProps = ({ type, rowIndex, columnIndex, isScrolling, width, ...props }) => { let content = \`Row \${rowIndex}, Col \${columnIndex}\${rowIndex % 2 === 0 ? '\\nExtra line' : ''}\`; @@ -175,7 +175,7 @@ SETTINGS index_granularity = 8192;\`; cell={VariableCell} focus={{ row: 0, column: 0 }} columnWidth={() => 300} - autoheight={${autoheight}} + rowAutoHeight={${rowAutoHeight}} ${Object.entries(props) .flatMap(([key, value]) => typeof value === "boolean" From 64af679d3559acac01e675a45cbd1f782a3cb3d8 Mon Sep 17 00:00:00 2001 From: Nataly Merezhuk Date: Fri, 7 Feb 2025 00:34:57 -0500 Subject: [PATCH 09/18] Getting cell height in grid. --- src/components/Grid/Cell.tsx | 23 +++++++++++++++++++-- src/components/Grid/Grid.tsx | 39 ++++++++++++++++++++++++++++++++++-- src/components/Grid/types.ts | 1 + 3 files changed, 59 insertions(+), 4 deletions(-) diff --git a/src/components/Grid/Cell.tsx b/src/components/Grid/Cell.tsx index 8a4e4f28..2b16b905 100644 --- a/src/components/Grid/Cell.tsx +++ b/src/components/Grid/Cell.tsx @@ -1,4 +1,4 @@ -import { memo } from "react"; +import { memo, useEffect, useRef } from "react"; import { GridChildComponentProps, areEqual } from "react-window"; import { ItemDataType } from "./types"; import { StyledCell } from "./StyledCell"; @@ -54,11 +54,30 @@ export const Cell = memo( const selectionBorderLeft = rightOfSelectionBorder || rightOfFocus || isFocused; const selectionBorderTop = belowSelectionBorder || belowFocus || isFocused; + + const cellRef = useRef(null); + + // useEffect(() => { + // console.log("Current ref form cell: ", cellRef.current?.getBoundingClientRect().height) + // }) + + useEffect(() => { + console.log("Current ref form cell: ", cellRef.current?.getBoundingClientRect().height) + if (cellRef.current && data.updateRowHeight) { + const height = cellRef.current.getBoundingClientRect().height; + data.updateRowHeight(rowIndex, height); + } + }, [cellRef, data.updateRowHeight, rowIndex]); + return (
( onCopyCallback, ]); + const rowHeightsRef = useRef(new Map()); + + + const updateRowHeight = useCallback((rowIndex: number, height: number) => { + console.log("Updating row height!"); + const prevHeight = rowHeightsRef.current.get(rowIndex) || 0; + if (height > prevHeight) { + rowHeightsRef.current.set(rowIndex, height); + gridRef.current?.resetAfterRowIndex(rowIndex); + } + }, []); + + const customOnCopy: () => Promise = useMemo(() => { const result = async () => { if (onCopyProp) { @@ -407,6 +420,7 @@ export const Grid = forwardRef( rowNumberWidth, rowStart, rowAutoHeight, + updateRowHeight }; const InnerElementType = forwardRef( @@ -758,7 +772,6 @@ export const Grid = forwardRef( const onItemsRendered = useCallback( (props: GridOnItemsRenderedProps) => { lastItemsRenderedProps.current = props; - return onItemsRenderedProp?.({ ...props, visibleRowStartIndex: props.visibleRowStartIndex + rowStart, @@ -794,9 +807,30 @@ export const Grid = forwardRef( useEffect(() => { if (gridRef.current) { gridRef.current.resetAfterRowIndex(0); + console.log("Inner: ", innerCellRef.current?.scrollHeight) + console.log("Bounding: ", innerCellRef.current?.scrollHeight) } }, [rowCount]); + + const innerCellRef = useRef(null); + + useEffect(() => { + console.log("Inner: ", innerCellRef.current?.getBoundingClientRect().height) + if (innerCellRef.current) { + // gridRef.current.resetAfterRowIndex(0); + console.log("Is current") + } + }, [onItemsRendered]); + + const getRowHeight = useCallback((index: number) => { + console.log(`GetRowHeight: from ref: ${rowHeightsRef.current.get(index)}`) + return rowHeightsRef.current.get(index) || rowHeight; + }, [rowHeight]); + + + // console.log("Inner ref? ", innerCellRef.current?.scrollHeight) + // console.log("Bounding client height? ", innerCellRef.current?.getBoundingClientRect().height) return ( ( height={height} width={width} columnCount={columnCount} - rowHeight={() => rowHeight} + rowHeight={getRowHeight} useIsScrolling={useIsScrolling} innerElementType={InnerElementType} itemData={data} @@ -847,6 +881,7 @@ export const Grid = forwardRef( outerRef={outerRef} outerElementType={OuterElementType} onItemsRendered={onItemsRendered} + innerRef={innerCellRef} {...props} > {CellWithWidth} diff --git a/src/components/Grid/types.ts b/src/components/Grid/types.ts index f0c63de4..22625209 100644 --- a/src/components/Grid/types.ts +++ b/src/components/Grid/types.ts @@ -158,6 +158,7 @@ export interface ItemDataType { rowNumberWidth: number; rowStart: number; rowAutoHeight?: boolean; + updateRowHeight: (rowIndex: number, height: number) => void; } export interface GridContextMenuItemProps extends Omit { From 3df9be8dc6e8e8f83c8b2e1e51da62819ef2af8f Mon Sep 17 00:00:00 2001 From: Nataly Merezhuk Date: Fri, 7 Feb 2025 02:33:31 -0500 Subject: [PATCH 10/18] Index column height works. --- src/components/Grid/Cell.tsx | 9 +++--- src/components/Grid/Grid.tsx | 37 +++++++++++++++++-------- src/components/Grid/RowNumberColumn.tsx | 6 ++-- src/components/Grid/StyledCell.tsx | 3 +- src/components/Grid/types.ts | 1 + 5 files changed, 37 insertions(+), 19 deletions(-) diff --git a/src/components/Grid/Cell.tsx b/src/components/Grid/Cell.tsx index 2b16b905..593b5191 100644 --- a/src/components/Grid/Cell.tsx +++ b/src/components/Grid/Cell.tsx @@ -20,6 +20,7 @@ export const Cell = memo( rowHeight, rowStart, rowAutoHeight, + getRowHeight } = data; const currentRowIndex = rowIndex + rowStart; @@ -57,9 +58,8 @@ export const Cell = memo( const cellRef = useRef(null); - // useEffect(() => { - // console.log("Current ref form cell: ", cellRef.current?.getBoundingClientRect().height) - // }) + const currentHeight = getRowHeight(rowIndex); + console.log(`Which is bigger, rowHeight ${rowHeight} or current height? ${currentHeight}`) useEffect(() => { console.log("Current ref form cell: ", cellRef.current?.getBoundingClientRect().height) @@ -69,11 +69,12 @@ export const Cell = memo( } }, [cellRef, data.updateRowHeight, rowIndex]); + console.log("Row height is: ", rowHeight) return (
( onCopyCallback, ]); + const rowHeightsRef = useRef(new Map()); - + + const getRowHeight = useCallback((index: number) => { + // console.log(`GetRowHeight: from ref: ${rowHeightsRef.current.get(index)}`) + if (rowHeightsRef.current.get(index)) { + // console.log(`Returning ref: ${rowHeightsRef.current.get(index)}`) + return rowHeightsRef.current.get(index) + 33; + } + // console.log("Returning rowHeight") + return rowHeight; + }, [rowHeight]); const updateRowHeight = useCallback((rowIndex: number, height: number) => { console.log("Updating row height!"); const prevHeight = rowHeightsRef.current.get(rowIndex) || 0; + console.log("Previous row height", prevHeight); if (height > prevHeight) { rowHeightsRef.current.set(rowIndex, height); - gridRef.current?.resetAfterRowIndex(rowIndex); + console.log("Current height > prevheight", rowHeightsRef); + if (gridRef.current) { + gridRef.current.resetAfterRowIndex(rowIndex); + console.log("Reset the grid"); + } } }, []); @@ -420,7 +435,8 @@ export const Grid = forwardRef( rowNumberWidth, rowStart, rowAutoHeight, - updateRowHeight + updateRowHeight, + getRowHeight }; const InnerElementType = forwardRef( @@ -806,9 +822,9 @@ export const Grid = forwardRef( // to fit content if there is only one row. useEffect(() => { if (gridRef.current) { - gridRef.current.resetAfterRowIndex(0); - console.log("Inner: ", innerCellRef.current?.scrollHeight) - console.log("Bounding: ", innerCellRef.current?.scrollHeight) + gridRef.current.resetAfterRowIndex(1); + // console.log("Inner: ", innerCellRef.current?.scrollHeight) + // console.log("Bounding: ", innerCellRef.current?.scrollHeight) } }, [rowCount]); @@ -816,17 +832,14 @@ export const Grid = forwardRef( const innerCellRef = useRef(null); useEffect(() => { - console.log("Inner: ", innerCellRef.current?.getBoundingClientRect().height) + // console.log("Inner: ", innerCellRef.current?.getBoundingClientRect().height) if (innerCellRef.current) { // gridRef.current.resetAfterRowIndex(0); - console.log("Is current") + // console.log("Is current") } }, [onItemsRendered]); - const getRowHeight = useCallback((index: number) => { - console.log(`GetRowHeight: from ref: ${rowHeightsRef.current.get(index)}`) - return rowHeightsRef.current.get(index) || rowHeight; - }, [rowHeight]); + // console.log("Inner ref? ", innerCellRef.current?.scrollHeight) diff --git a/src/components/Grid/RowNumberColumn.tsx b/src/components/Grid/RowNumberColumn.tsx index e42375a6..fc069e98 100644 --- a/src/components/Grid/RowNumberColumn.tsx +++ b/src/components/Grid/RowNumberColumn.tsx @@ -23,6 +23,7 @@ const RowNumberColumnContainer = styled.div<{ const RowNumberCell = styled.div<{ $height: number; $rowNumber: number; + $rowAutoHeight?: boolean; }>` position: absolute; left: 0; @@ -30,9 +31,9 @@ const RowNumberCell = styled.div<{ text-overflow: ellipsis; white-space: nowrap; width: 100%; - ${({ $height, $rowNumber }) => ` + ${({ $height, $rowNumber, $rowAutoHeight }) => ` top: ${$height * $rowNumber}px; - height: ${$height}px; + height: ${$rowAutoHeight ? "100%" : `${$height}px`}; `} `; interface RowNumberColumnProps { @@ -87,6 +88,7 @@ const RowNumber = ({ ` - height: ${$rowAutoHeight ? "auto" : `${$height}px`}; + height: ${$rowAutoHeight ? "100%" : `${$height}px`}; + min-height: ${$rowAutoHeight ? "auto" : ""}; overflow-y: ${$rowAutoHeight ? "auto" : "hidden"}; background: ${theme.click.grid[$type].cell.color.background[$selectionType]}; color: ${ diff --git a/src/components/Grid/types.ts b/src/components/Grid/types.ts index 22625209..35d6b228 100644 --- a/src/components/Grid/types.ts +++ b/src/components/Grid/types.ts @@ -159,6 +159,7 @@ export interface ItemDataType { rowStart: number; rowAutoHeight?: boolean; updateRowHeight: (rowIndex: number, height: number) => void; + getRowHeight: (index: number) => number; } export interface GridContextMenuItemProps extends Omit { From ee47873e93d21fbe48ef266ac24cd234e1c9b65a Mon Sep 17 00:00:00 2001 From: Nataly Merezhuk Date: Fri, 7 Feb 2025 08:33:31 -0500 Subject: [PATCH 11/18] Corrects overflow, runs prettier. --- src/components/Grid/Cell.tsx | 11 +-- src/components/Grid/Grid.stories.tsx | 115 ++---------------------- src/components/Grid/Grid.tsx | 54 +++-------- src/components/Grid/Header.tsx | 6 +- src/components/Grid/RowNumberColumn.tsx | 9 +- src/components/Grid/StyledCell.tsx | 4 +- 6 files changed, 38 insertions(+), 161 deletions(-) diff --git a/src/components/Grid/Cell.tsx b/src/components/Grid/Cell.tsx index 593b5191..90fdeca9 100644 --- a/src/components/Grid/Cell.tsx +++ b/src/components/Grid/Cell.tsx @@ -20,7 +20,6 @@ export const Cell = memo( rowHeight, rowStart, rowAutoHeight, - getRowHeight } = data; const currentRowIndex = rowIndex + rowStart; @@ -58,23 +57,19 @@ export const Cell = memo( const cellRef = useRef(null); - const currentHeight = getRowHeight(rowIndex); - console.log(`Which is bigger, rowHeight ${rowHeight} or current height? ${currentHeight}`) - useEffect(() => { - console.log("Current ref form cell: ", cellRef.current?.getBoundingClientRect().height) if (cellRef.current && data.updateRowHeight) { const height = cellRef.current.getBoundingClientRect().height; data.updateRowHeight(rowIndex, height); } - }, [cellRef, data.updateRowHeight, rowIndex]); + }); - console.log("Row height is: ", rowHeight) + console.log("Row height is: ", rowHeight); return (
{ +const Cell: CellProps = ({ + type, + rowIndex, + columnIndex, + isScrolling, + width, + ...props +}) => { return (
{ - const { rowCount, columnCount, rowAutoHeight, ...props } = story.args; - return ` -const VariableCell: CellProps = ({ type, rowIndex, columnIndex, isScrolling, width, ...props }) => { - let content = \`Row \${rowIndex}, Col \${columnIndex}\${rowIndex % 2 === 0 ? '\\nExtra line' : ''}\`; - - if (rowIndex === 0 && columnIndex === 0) { - content = \`CREATE TABLE random_user_events ( - user_id UInt32, - event_time DateTime, - event_type Enum8('click' = 1, 'view' = 2, 'purchase' = 3), - item_id String, - price Decimal(10,2), - quantity UInt16 -) ENGINE = MergeTree() -ORDER BY (user_id, event_time) -PARTITION BY toYYYYMM(event_time) -SETTINGS index_granularity = 8192;\`; - } - - return ( -
- {content} -
- ); -}; - - 300} - rowAutoHeight={${rowAutoHeight}} -${Object.entries(props) - .flatMap(([key, value]) => - typeof value === "boolean" - ? value - ? ` ${key}` - : [] - : ` ${key}=${typeof value == "string" ? `"${value}"` : `{${value}}`}` - ) - .join("\n")} -/> -`; - }, - }, - }, - }, - render: (args) => { - const VariableCell: CellProps = ({ type, rowIndex, columnIndex, isScrolling, width, ...props }) => { - let content = `Row ${rowIndex}, Col ${columnIndex}${rowIndex % 2 === 0 ? '\nExtra line' : ''}`; - - if (rowIndex === 0 && columnIndex === 0) { - content = `CREATE TABLE random_user_events ( - user_id UInt32, - event_time DateTime, - event_type Enum8('click' = 1, 'view' = 2, 'purchase' = 3), - item_id String, - price Decimal(10,2), - quantity UInt16 -) ENGINE = MergeTree() -ORDER BY (user_id, event_time) -PARTITION BY toYYYYMM(event_time) -SETTINGS index_granularity = 8192;`; - } - - return ( -
- {content} -
- ); - }; - - return 300} />; - }, -}; diff --git a/src/components/Grid/Grid.tsx b/src/components/Grid/Grid.tsx index adf9db09..284aecb5 100644 --- a/src/components/Grid/Grid.tsx +++ b/src/components/Grid/Grid.tsx @@ -213,33 +213,27 @@ export const Grid = forwardRef( onCopyCallback, ]); - const rowHeightsRef = useRef(new Map()); - - const getRowHeight = useCallback((index: number) => { - // console.log(`GetRowHeight: from ref: ${rowHeightsRef.current.get(index)}`) - if (rowHeightsRef.current.get(index)) { - // console.log(`Returning ref: ${rowHeightsRef.current.get(index)}`) - return rowHeightsRef.current.get(index) + 33; - } - // console.log("Returning rowHeight") - return rowHeight; - }, [rowHeight]); + + const getRowHeight = useCallback( + (index: number) => { + if (rowAutoHeight && rowHeightsRef.current.get(index)) { + return rowHeightsRef.current.get(index) + 33; + } + return rowHeight; + }, + [rowHeight, rowAutoHeight] + ); const updateRowHeight = useCallback((rowIndex: number, height: number) => { - console.log("Updating row height!"); const prevHeight = rowHeightsRef.current.get(rowIndex) || 0; - console.log("Previous row height", prevHeight); if (height > prevHeight) { rowHeightsRef.current.set(rowIndex, height); - console.log("Current height > prevheight", rowHeightsRef); if (gridRef.current) { gridRef.current.resetAfterRowIndex(rowIndex); - console.log("Reset the grid"); } } }, []); - const customOnCopy: () => Promise = useMemo(() => { const result = async () => { @@ -436,7 +430,7 @@ export const Grid = forwardRef( rowStart, rowAutoHeight, updateRowHeight, - getRowHeight + getRowHeight, }; const InnerElementType = forwardRef( @@ -818,32 +812,13 @@ export const Grid = forwardRef( ); }; - // Handles the case when rowCount changes, expanding the cell height - // to fit content if there is only one row. + // Handles the case when rowCount/columnCount changes, rerenders styles useEffect(() => { if (gridRef.current) { - gridRef.current.resetAfterRowIndex(1); - // console.log("Inner: ", innerCellRef.current?.scrollHeight) - // console.log("Bounding: ", innerCellRef.current?.scrollHeight) - } - }, [rowCount]); - - - const innerCellRef = useRef(null); - - useEffect(() => { - // console.log("Inner: ", innerCellRef.current?.getBoundingClientRect().height) - if (innerCellRef.current) { - // gridRef.current.resetAfterRowIndex(0); - // console.log("Is current") + gridRef.current.resetAfterRowIndex(0); } - }, [onItemsRendered]); + }, [rowCount, columnCount]); - - - - // console.log("Inner ref? ", innerCellRef.current?.scrollHeight) - // console.log("Bounding client height? ", innerCellRef.current?.getBoundingClientRect().height) return ( ( outerRef={outerRef} outerElementType={OuterElementType} onItemsRendered={onItemsRendered} - innerRef={innerCellRef} {...props} > {CellWithWidth} diff --git a/src/components/Grid/Header.tsx b/src/components/Grid/Header.tsx index b5d1265c..4725e972 100644 --- a/src/components/Grid/Header.tsx +++ b/src/components/Grid/Header.tsx @@ -99,6 +99,7 @@ const RowColumnContainer = styled(HeaderCellContainer)<{ const RowColumn = styled(StyledCell)` width: 100%; text-align: right; + overflow: hidden; `; const Column = ({ @@ -130,7 +131,7 @@ const Column = ({ (leftSelectionType === "selectDirect" || isSelected) && leftSelectionType !== selectionType; - const columnWidth = getColumnWidth(columnIndex) + const columnWidth = getColumnWidth(columnIndex); return ( { const selectedAllType = getSelectionType({ type: "all", diff --git a/src/components/Grid/RowNumberColumn.tsx b/src/components/Grid/RowNumberColumn.tsx index fc069e98..12c00d0e 100644 --- a/src/components/Grid/RowNumberColumn.tsx +++ b/src/components/Grid/RowNumberColumn.tsx @@ -5,13 +5,14 @@ const RowNumberColumnContainer = styled.div<{ $height: number; $width: number; $scrolledHorizontal: boolean; + $rowAutoHeight?: boolean; }>` position: sticky; left: 0; ${({ $height, $width }) => ` top: ${$height}px; width: ${$width}px; - height: 100%; + height: 100% `} ${({ $scrolledHorizontal, theme }) => @@ -68,7 +69,7 @@ const RowNumber = ({ isFirstRow, showBorder, rowStart, - rowAutoHeight + rowAutoHeight, }: RowNumberProps) => { const currentRowIndex = rowIndex + rowStart; const selectionType = getSelectionType({ @@ -102,6 +103,7 @@ const RowNumber = ({ $isSelectedLeft={isSelected} $isSelectedTop={isSelectedTop} $rowAutoHeight={rowAutoHeight} + $overflow="hidden" data-selected={isSelected} data-grid-row={currentRowIndex} data-grid-column={-1} @@ -127,13 +129,14 @@ const RowNumberColumn = ({ scrolledHorizontal, rowStart = 0, showBorder, - rowAutoHeight + rowAutoHeight, }: RowNumberColumnProps) => { return ( {Array.from({ length: maxRow - minRow + 1 }, (_, index) => minRow + index).map( rowIndex => ( diff --git a/src/components/Grid/StyledCell.tsx b/src/components/Grid/StyledCell.tsx index ef0914a3..b3c2a5fb 100644 --- a/src/components/Grid/StyledCell.tsx +++ b/src/components/Grid/StyledCell.tsx @@ -14,6 +14,7 @@ export const StyledCell = styled.div<{ $type?: "body" | "header"; $showBorder: boolean; $rowAutoHeight?: boolean; + $overflow?: string; }>` display: block; text-align: left; @@ -36,10 +37,11 @@ export const StyledCell = styled.div<{ $type = "body", $showBorder, $rowAutoHeight, + $overflow, }) => ` height: ${$rowAutoHeight ? "100%" : `${$height}px`}; min-height: ${$rowAutoHeight ? "auto" : ""}; - overflow-y: ${$rowAutoHeight ? "auto" : "hidden"}; + overflow-y: ${$overflow ? $overflow : "auto"}; background: ${theme.click.grid[$type].cell.color.background[$selectionType]}; color: ${ $type === "header" From 7b43a98fe5f9d4ca4a92ed5a119d295624d93d4e Mon Sep 17 00:00:00 2001 From: Nataly Merezhuk Date: Fri, 7 Feb 2025 12:30:18 -0500 Subject: [PATCH 12/18] Cleanup + requested changes. --- src/components/Grid/Cell.tsx | 11 ++++++----- src/components/Grid/Grid.tsx | 4 ++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/components/Grid/Cell.tsx b/src/components/Grid/Cell.tsx index 90fdeca9..8104b29b 100644 --- a/src/components/Grid/Cell.tsx +++ b/src/components/Grid/Cell.tsx @@ -64,13 +64,14 @@ export const Cell = memo( } }); - console.log("Row height is: ", rowHeight); + const styleWithHeight = { + ...style, + height: "auto" + } + return (
( const getRowHeight = useCallback( (index: number) => { if (rowAutoHeight && rowHeightsRef.current.get(index)) { - return rowHeightsRef.current.get(index) + 33; + return rowHeightsRef.current.get(index) + rowHeight; } return rowHeight; }, @@ -226,7 +226,7 @@ export const Grid = forwardRef( ); const updateRowHeight = useCallback((rowIndex: number, height: number) => { - const prevHeight = rowHeightsRef.current.get(rowIndex) || 0; + const prevHeight = rowHeightsRef.current.get(rowIndex) ?? 0; if (height > prevHeight) { rowHeightsRef.current.set(rowIndex, height); if (gridRef.current) { From 905a2efe9b642f16b30e942758553e0a0370d2d3 Mon Sep 17 00:00:00 2001 From: Nataly Merezhuk Date: Mon, 10 Feb 2025 08:09:57 -0500 Subject: [PATCH 13/18] Adds tests to calculate rowheight. --- src/components/Grid/Grid.test.tsx | 75 +++++++++++++++++++++++++++---- 1 file changed, 66 insertions(+), 9 deletions(-) diff --git a/src/components/Grid/Grid.test.tsx b/src/components/Grid/Grid.test.tsx index d5e34f4c..89a9ac6e 100644 --- a/src/components/Grid/Grid.test.tsx +++ b/src/components/Grid/Grid.test.tsx @@ -1,16 +1,33 @@ -import {CellProps, Grid, GridProps} from "@/components"; -import {renderCUI} from "@/utils/test-utils"; -import {SelectionFocus} from "./types"; -import {ReactNode} from "react"; +import { CellProps, Grid, GridProps } from "@/components"; +import { renderCUI } from "@/utils/test-utils"; +import { SelectionFocus } from "./types"; +import { ReactNode } from "react"; +import { act } from "react-dom/test-utils"; const Cell: CellProps = ({ type, rowIndex, columnIndex, isScrolling, ...props }) => { + let content = `${rowIndex} ${columnIndex} - ${type}`; + + if (rowIndex === 0 && columnIndex === 0) { + content = `CREATE TABLE random_user_events ( + user_id UInt32, + event_time DateTime, + event_type Enum8('click' = 1, 'view' = 2, 'purchase' = 3), + item_id String, + price Decimal(10,2), + quantity UInt16 + ) ENGINE = MergeTree() + ORDER BY (user_id, event_time) + PARTITION BY toYYYYMM(event_time) + SETTINGS index_granularity = 8192;`; + } + return (
- {rowIndex} {columnIndex} - {type} + {content}
); }; @@ -31,6 +48,7 @@ interface Props focus?: SelectionFocus; onFocusChange?: (rowIndex: number, columnIndex: number) => void; onColumnResize?: () => void; + rowAutoHeight?: boolean; } type AutoSizerModule = typeof import("react-virtualized-auto-sizer"); @@ -54,24 +72,26 @@ describe("Grid", () => { }; const renderGrid = ({ - rowCount = 20, - columnCount = 20, + rowCount, + columnCount, columnWidth, onColumnResize, focus, onFocusChange, + rowAutoHeight, ...props }: Props) => renderCUI( ); @@ -99,4 +119,41 @@ describe("Grid", () => { cell && expect(cell.dataset.selected).toEqual("true"); cell && expect(cell.dataset.focused).toEqual("true"); }); + + it.only("should set row height to default (33px) when rowAutoHeight is false", async () => { + const { queryByTestId } = renderGrid({ + rowCount: 10, + columnCount: 10, + rowAutoHeight: false, + }); + + const cell = queryByTestId("row-cell-0-0"); + expect(cell).toBeDefined(); + + if (!cell) { + throw new Error("Cell with data-testid 'row-cell-0-0' not found"); + } + + const computedHeight = window.getComputedStyle(cell).height; + const heightValue = parseFloat(computedHeight); + expect(heightValue).toBe(33); + }); + + it("should expand row height to 100% when rowAutoHeight is true", async () => { + const { queryByTestId } = renderGrid({ + rowCount: 1, + columnCount: 1, + rowAutoHeight: true, + }); + + const cell = queryByTestId("row-cell-0-0"); + expect(cell).toBeDefined(); + + if (!cell) { + throw new Error("Cell with data-testid 'row-cell-0-0' not found"); + } + + const computedHeight = window.getComputedStyle(cell).height; + expect(computedHeight).toBe("100%"); + }); }); From 8ffc18dd96a4b1c37d40919a9870a99ea8eb5284 Mon Sep 17 00:00:00 2001 From: Nataly Merezhuk Date: Mon, 10 Feb 2025 08:54:03 -0500 Subject: [PATCH 14/18] Fixes rerender. --- src/components/Grid/Cell.tsx | 12 +++++++----- src/components/Grid/Grid.tsx | 21 +++++++++++++-------- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/components/Grid/Cell.tsx b/src/components/Grid/Cell.tsx index 8104b29b..41ff093a 100644 --- a/src/components/Grid/Cell.tsx +++ b/src/components/Grid/Cell.tsx @@ -20,6 +20,7 @@ export const Cell = memo( rowHeight, rowStart, rowAutoHeight, + updateRowHeight, } = data; const currentRowIndex = rowIndex + rowStart; @@ -58,16 +59,17 @@ export const Cell = memo( const cellRef = useRef(null); useEffect(() => { - if (cellRef.current && data.updateRowHeight) { + if (rowCount !== 1) return; + else if (cellRef.current) { const height = cellRef.current.getBoundingClientRect().height; - data.updateRowHeight(rowIndex, height); + updateRowHeight(rowIndex, height); } - }); + }, [rowCount, updateRowHeight, rowIndex]); const styleWithHeight = { ...style, - height: "auto" - } + height: "auto", + }; return (
( [rowHeight, rowAutoHeight] ); - const updateRowHeight = useCallback((rowIndex: number, height: number) => { - const prevHeight = rowHeightsRef.current.get(rowIndex) ?? 0; - if (height > prevHeight) { - rowHeightsRef.current.set(rowIndex, height); - if (gridRef.current) { - gridRef.current.resetAfterRowIndex(rowIndex); + const updateRowHeight = useCallback( + (rowIndex: number, height: number) => { + if (rowCount !== 1) return; + + const prevHeight = rowHeightsRef.current.get(rowIndex) ?? 0; + if (height > prevHeight) { + rowHeightsRef.current.set(rowIndex, height); + if (gridRef.current) { + gridRef.current.resetAfterRowIndex(rowIndex); + } } - } - }, []); + }, + [rowCount] + ); const customOnCopy: () => Promise = useMemo(() => { const result = async () => { From 973277c99dfd6ed6e16c4644669fd6df9fa03917 Mon Sep 17 00:00:00 2001 From: Nataly Merezhuk Date: Mon, 10 Feb 2025 11:29:33 -0500 Subject: [PATCH 15/18] Fixes imports, rerenders, and overflow. --- src/components/Grid/Cell.tsx | 4 ++-- src/components/Grid/Grid.test.tsx | 1 - src/components/Grid/Grid.tsx | 5 ++--- src/components/Grid/Header.tsx | 1 - src/components/Grid/RowNumberColumn.tsx | 1 - src/components/Grid/StyledCell.tsx | 4 +--- 6 files changed, 5 insertions(+), 11 deletions(-) diff --git a/src/components/Grid/Cell.tsx b/src/components/Grid/Cell.tsx index 41ff093a..c8d0b12d 100644 --- a/src/components/Grid/Cell.tsx +++ b/src/components/Grid/Cell.tsx @@ -59,12 +59,12 @@ export const Cell = memo( const cellRef = useRef(null); useEffect(() => { - if (rowCount !== 1) return; + if (!rowAutoHeight) return; else if (cellRef.current) { const height = cellRef.current.getBoundingClientRect().height; updateRowHeight(rowIndex, height); } - }, [rowCount, updateRowHeight, rowIndex]); + }, [updateRowHeight, rowIndex, rowAutoHeight]); const styleWithHeight = { ...style, diff --git a/src/components/Grid/Grid.test.tsx b/src/components/Grid/Grid.test.tsx index 89a9ac6e..4ddcc0d9 100644 --- a/src/components/Grid/Grid.test.tsx +++ b/src/components/Grid/Grid.test.tsx @@ -2,7 +2,6 @@ import { CellProps, Grid, GridProps } from "@/components"; import { renderCUI } from "@/utils/test-utils"; import { SelectionFocus } from "./types"; import { ReactNode } from "react"; -import { act } from "react-dom/test-utils"; const Cell: CellProps = ({ type, rowIndex, columnIndex, isScrolling, ...props }) => { let content = `${rowIndex} ${columnIndex} - ${type}`; diff --git a/src/components/Grid/Grid.tsx b/src/components/Grid/Grid.tsx index 017e7eab..8fa695d2 100644 --- a/src/components/Grid/Grid.tsx +++ b/src/components/Grid/Grid.tsx @@ -227,8 +227,7 @@ export const Grid = forwardRef( const updateRowHeight = useCallback( (rowIndex: number, height: number) => { - if (rowCount !== 1) return; - + if (!rowAutoHeight) return; const prevHeight = rowHeightsRef.current.get(rowIndex) ?? 0; if (height > prevHeight) { rowHeightsRef.current.set(rowIndex, height); @@ -237,7 +236,7 @@ export const Grid = forwardRef( } } }, - [rowCount] + [rowAutoHeight] ); const customOnCopy: () => Promise = useMemo(() => { diff --git a/src/components/Grid/Header.tsx b/src/components/Grid/Header.tsx index 4725e972..32b5a9de 100644 --- a/src/components/Grid/Header.tsx +++ b/src/components/Grid/Header.tsx @@ -153,7 +153,6 @@ const Column = ({ $isLastRow={false} $isFirstRow $height={height} - $overflow="hidden" data-grid-row={-1} data-grid-column={columnIndex} data-selected={isSelected} diff --git a/src/components/Grid/RowNumberColumn.tsx b/src/components/Grid/RowNumberColumn.tsx index 12c00d0e..8c39cc4c 100644 --- a/src/components/Grid/RowNumberColumn.tsx +++ b/src/components/Grid/RowNumberColumn.tsx @@ -103,7 +103,6 @@ const RowNumber = ({ $isSelectedLeft={isSelected} $isSelectedTop={isSelectedTop} $rowAutoHeight={rowAutoHeight} - $overflow="hidden" data-selected={isSelected} data-grid-row={currentRowIndex} data-grid-column={-1} diff --git a/src/components/Grid/StyledCell.tsx b/src/components/Grid/StyledCell.tsx index b3c2a5fb..975cfdee 100644 --- a/src/components/Grid/StyledCell.tsx +++ b/src/components/Grid/StyledCell.tsx @@ -14,7 +14,6 @@ export const StyledCell = styled.div<{ $type?: "body" | "header"; $showBorder: boolean; $rowAutoHeight?: boolean; - $overflow?: string; }>` display: block; text-align: left; @@ -37,11 +36,10 @@ export const StyledCell = styled.div<{ $type = "body", $showBorder, $rowAutoHeight, - $overflow, }) => ` height: ${$rowAutoHeight ? "100%" : `${$height}px`}; min-height: ${$rowAutoHeight ? "auto" : ""}; - overflow-y: ${$overflow ? $overflow : "auto"}; + overflow-y: ${$rowAutoHeight ? "auto" : ""}; background: ${theme.click.grid[$type].cell.color.background[$selectionType]}; color: ${ $type === "header" From 6a77f935954c26eaeb2ed722541b1d8002d0e2ae Mon Sep 17 00:00:00 2001 From: Nataly Merezhuk Date: Mon, 10 Feb 2025 11:46:11 -0500 Subject: [PATCH 16/18] Removes only modifier from test. --- src/components/Grid/Grid.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Grid/Grid.test.tsx b/src/components/Grid/Grid.test.tsx index 4ddcc0d9..fd2af738 100644 --- a/src/components/Grid/Grid.test.tsx +++ b/src/components/Grid/Grid.test.tsx @@ -119,7 +119,7 @@ describe("Grid", () => { cell && expect(cell.dataset.focused).toEqual("true"); }); - it.only("should set row height to default (33px) when rowAutoHeight is false", async () => { + it("should set row height to default (33px) when rowAutoHeight is false", async () => { const { queryByTestId } = renderGrid({ rowCount: 10, columnCount: 10, From 6378cf8c7a1b2a49b46aaa85e631b1e222f63c38 Mon Sep 17 00:00:00 2001 From: Nataly Merezhuk Date: Mon, 10 Feb 2025 17:04:43 -0500 Subject: [PATCH 17/18] Adds requested changes. --- src/components/Grid/Cell.tsx | 4 ++-- src/components/Grid/Grid.test.tsx | 20 ++++++-------------- src/components/Grid/Grid.tsx | 2 +- 3 files changed, 9 insertions(+), 17 deletions(-) diff --git a/src/components/Grid/Cell.tsx b/src/components/Grid/Cell.tsx index c8d0b12d..24935122 100644 --- a/src/components/Grid/Cell.tsx +++ b/src/components/Grid/Cell.tsx @@ -59,8 +59,8 @@ export const Cell = memo( const cellRef = useRef(null); useEffect(() => { - if (!rowAutoHeight) return; - else if (cellRef.current) { + if (!rowAutoHeight) {return;} + if (cellRef.current) { const height = cellRef.current.getBoundingClientRect().height; updateRowHeight(rowIndex, height); } diff --git a/src/components/Grid/Grid.test.tsx b/src/components/Grid/Grid.test.tsx index fd2af738..5c8846e5 100644 --- a/src/components/Grid/Grid.test.tsx +++ b/src/components/Grid/Grid.test.tsx @@ -71,8 +71,8 @@ describe("Grid", () => { }; const renderGrid = ({ - rowCount, - columnCount, + rowCount = 20, + columnCount = 20, columnWidth, onColumnResize, focus, @@ -82,8 +82,8 @@ describe("Grid", () => { }: Props) => renderCUI( { const cell = queryByTestId("row-cell-0-0"); expect(cell).toBeDefined(); - if (!cell) { - throw new Error("Cell with data-testid 'row-cell-0-0' not found"); - } - - const computedHeight = window.getComputedStyle(cell).height; + const computedHeight = window.getComputedStyle(cell!).height; const heightValue = parseFloat(computedHeight); expect(heightValue).toBe(33); }); @@ -148,11 +144,7 @@ describe("Grid", () => { const cell = queryByTestId("row-cell-0-0"); expect(cell).toBeDefined(); - if (!cell) { - throw new Error("Cell with data-testid 'row-cell-0-0' not found"); - } - - const computedHeight = window.getComputedStyle(cell).height; + const computedHeight = window.getComputedStyle(cell!).height; expect(computedHeight).toBe("100%"); }); }); diff --git a/src/components/Grid/Grid.tsx b/src/components/Grid/Grid.tsx index 8fa695d2..c7d321b9 100644 --- a/src/components/Grid/Grid.tsx +++ b/src/components/Grid/Grid.tsx @@ -227,7 +227,7 @@ export const Grid = forwardRef( const updateRowHeight = useCallback( (rowIndex: number, height: number) => { - if (!rowAutoHeight) return; + if (!rowAutoHeight) {return;} const prevHeight = rowHeightsRef.current.get(rowIndex) ?? 0; if (height > prevHeight) { rowHeightsRef.current.set(rowIndex, height); From e68c8c601cc65af34518445789492daa87a04a86 Mon Sep 17 00:00:00 2001 From: Nataly Merezhuk Date: Mon, 10 Feb 2025 17:36:45 -0500 Subject: [PATCH 18/18] Corrects tests; runs prettier. --- src/components/Grid/Cell.tsx | 4 +++- src/components/Grid/Grid.test.tsx | 14 ++++++-------- src/components/Grid/Grid.tsx | 4 +++- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/components/Grid/Cell.tsx b/src/components/Grid/Cell.tsx index 24935122..bcf09236 100644 --- a/src/components/Grid/Cell.tsx +++ b/src/components/Grid/Cell.tsx @@ -59,7 +59,9 @@ export const Cell = memo( const cellRef = useRef(null); useEffect(() => { - if (!rowAutoHeight) {return;} + if (!rowAutoHeight) { + return; + } if (cellRef.current) { const height = cellRef.current.getBoundingClientRect().height; updateRowHeight(rowIndex, height); diff --git a/src/components/Grid/Grid.test.tsx b/src/components/Grid/Grid.test.tsx index 5c8846e5..6df8ab49 100644 --- a/src/components/Grid/Grid.test.tsx +++ b/src/components/Grid/Grid.test.tsx @@ -120,31 +120,29 @@ describe("Grid", () => { }); it("should set row height to default (33px) when rowAutoHeight is false", async () => { - const { queryByTestId } = renderGrid({ + const { getByTestId } = renderGrid({ rowCount: 10, columnCount: 10, rowAutoHeight: false, }); - const cell = queryByTestId("row-cell-0-0"); - expect(cell).toBeDefined(); + const cell = getByTestId("row-cell-0-0"); - const computedHeight = window.getComputedStyle(cell!).height; + const computedHeight = window.getComputedStyle(cell).height; const heightValue = parseFloat(computedHeight); expect(heightValue).toBe(33); }); it("should expand row height to 100% when rowAutoHeight is true", async () => { - const { queryByTestId } = renderGrid({ + const { getByTestId } = renderGrid({ rowCount: 1, columnCount: 1, rowAutoHeight: true, }); - const cell = queryByTestId("row-cell-0-0"); - expect(cell).toBeDefined(); + const cell = getByTestId("row-cell-0-0"); - const computedHeight = window.getComputedStyle(cell!).height; + const computedHeight = window.getComputedStyle(cell).height; expect(computedHeight).toBe("100%"); }); }); diff --git a/src/components/Grid/Grid.tsx b/src/components/Grid/Grid.tsx index c7d321b9..2191b6e7 100644 --- a/src/components/Grid/Grid.tsx +++ b/src/components/Grid/Grid.tsx @@ -227,7 +227,9 @@ export const Grid = forwardRef( const updateRowHeight = useCallback( (rowIndex: number, height: number) => { - if (!rowAutoHeight) {return;} + if (!rowAutoHeight) { + return; + } const prevHeight = rowHeightsRef.current.get(rowIndex) ?? 0; if (height > prevHeight) { rowHeightsRef.current.set(rowIndex, height);