From 8fce1949859ea5b19a9f3febf95d5cfd7cbd4f9f Mon Sep 17 00:00:00 2001 From: Rodrigo Date: Mon, 5 Oct 2020 07:28:20 +0100 Subject: [PATCH] Updated some props and descriptions --- src/columnGrid/ColumnGrid.tsx | 71 ++-- src/core/GridWrapper.tsx | 302 ++++++-------- ...andler.tsx => HorizontalScrollHandler.tsx} | 67 ++- src/core/gridWrapperProps.ts | 60 +++ src/core/horizontalScrollHandlerProps.ts | 34 ++ .../interfaces/cellMeasureRendererProps.ts | 0 src/core/interfaces/getColumnWidthFn.ts | 3 + src/core/interfaces/registerChildFn.ts | 3 + src/index.tsx | 382 +++++++++--------- 9 files changed, 470 insertions(+), 452 deletions(-) rename src/core/{ScrollHandler.tsx => HorizontalScrollHandler.tsx} (80%) create mode 100644 src/core/gridWrapperProps.ts create mode 100644 src/core/horizontalScrollHandlerProps.ts delete mode 100644 src/core/interfaces/cellMeasureRendererProps.ts diff --git a/src/columnGrid/ColumnGrid.tsx b/src/columnGrid/ColumnGrid.tsx index ce8b7e5..7aa4dee 100644 --- a/src/columnGrid/ColumnGrid.tsx +++ b/src/columnGrid/ColumnGrid.tsx @@ -50,47 +50,40 @@ export const ColumnGrid = React.memo( const headerRendererWrapper = useCallback( ({ style, cell, ref, columnIndex, rowIndex }) => { - const { title, renderer } = cell as Column - /** @todo Cache cell renderer result because if may have not changed so no need to invoke again **/ - const children = renderer - ? (renderer(cell) as any) - : title + const { title, renderer } = cell as Column + /** @todo Cache cell renderer result because if may have not changed so no need to invoke again **/ + const children = renderer ? (renderer(cell) as any) : title - //Ensure dummy cells doesn't have any styling - const headerClassName = - !cell.dummy && - props.coords.colIndex === columnIndex && - rowIndex === 0 - ? clsx( - props.theme?.headerClass, - props.theme?.currentColumnClass, - ) - : !cell.dummy - ? props.theme?.headerClass - : undefined + //Ensure dummy cells doesn't have any styling + const headerClassName = + !cell.dummy && props.coords.colIndex === columnIndex && rowIndex === 0 + ? clsx(props.theme?.headerClass, props.theme?.currentColumnClass) + : !cell.dummy + ? props.theme?.headerClass + : undefined - /** - * @todo If it is a nested header we need to load the styling from the theme property and combine using clsx - */ - return ( -
- {children} -
- ) - }, + /** + * @todo If it is a nested header we need to load the styling from the theme property and combine using clsx + */ + return ( +
+ {children} +
+ ) + }, [props.coords, props.theme, props.width], ) diff --git a/src/core/GridWrapper.tsx b/src/core/GridWrapper.tsx index e7e6a68..7e522cf 100644 --- a/src/core/GridWrapper.tsx +++ b/src/core/GridWrapper.tsx @@ -1,82 +1,26 @@ import React, { useRef, useEffect, - useMemo, useCallback, useImperativeHandle, forwardRef, useState, } from 'react' -import { Grid, CellMeasurerCache, ScrollParams } from 'react-virtualized' +import { Grid, CellMeasurerCache } from 'react-virtualized' import CellMeasurer from '../cellMeasurer/CellMeasureWrapper' -import { HeadersData } from '../columnGrid/types/header.type' import { GridCell, GridData, GridRow } from '../types/row.interface' import { GridApi } from '../types/grid-api.type' import { NavigationCoords } from '../navigation/types/navigation-coords.type' -import { SelectCellFn } from '../navigation/useNavigation' import TextEditor from '../editors/TextEditor' import { createPortal } from 'react-dom' import { ClickAwayListener } from '@material-ui/core' -import { GridTheme } from '../types/grid-theme' import clsx from 'clsx' import { GridCellProps } from 'react-virtualized/dist/es/Grid' import { useEditorManager } from '../editors/useEditorManager' import { MeasurerRendererProps } from '../cellMeasurer/cellMeasureWrapperProps' -import { RegisterChildFn } from './interfaces/registerChildFn' +import { GridWrapperProps } from './gridWrapperProps' -export interface ICellMountedRegisterData { - colIndex: number - rowIndex: number - elementNodeRef: Element -} - -export interface ICellNodeInfo { - rowIndex: number - colIndex: number - elementNodeRef: Element -} - -export interface CellChangeParams { - rowIndex: number - columnIndex: number - previousValue: ValueType - value: ValueType -} - -export interface GridWrapperCommonProps { - headers: HeadersData - // data: GridData; - /** @default { rowIndex: 0, colIndex: 0} **/ - defaultCoords?: NavigationCoords - /** @default false **/ - suppressNavigation?: boolean - /** @default false **/ - outsideClickDeselects?: boolean - onGridReady?: (gridRef: GridApi) => void - theme?: GridTheme - onCellChange: (params: CellChangeParams) => void -} - -interface Props extends GridWrapperCommonProps { - className: string - minRowHeight: number - defaultColumnWidth: number - width: number - scrollLeft: number - scrollTop: number - isScrolling: boolean - height: number - registerChild: RegisterChildFn - gridContainerRef: HTMLDivElement | null - coords: NavigationCoords - rows: Array - columnCount: number - selectCell: SelectCellFn - onCellClick: (params: NavigationCoords & { event: React.MouseEvent }) => void - getColumnWidth: ({ index }: { index: number }) => number -} - -const GridWrapper = forwardRef((props: Props, componentRef: React.Ref) => { +const GridWrapper = forwardRef((props: GridWrapperProps, componentRef: React.Ref) => { const cache = useRef( new CellMeasurerCache({ defaultWidth: props.defaultColumnWidth, @@ -281,129 +225,139 @@ const GridWrapper = forwardRef((props: Props, componentRef: React.Ref) const renderCell = useCallback( ({ style, cell, ref, rowIndex, columnIndex }) => { - const { children } = cell - const isSelected = rowIndex === props.coords.rowIndex && columnIndex === props.coords.colIndex - /** - * @todo Not considering well merged cells, i need to look up by merged too - */ - const isRowSelected = rowIndex === props.coords.rowIndex - if (isSelected) { - style.border = '1px solid blue' - } else { - //Bind default border - if (!props.theme || (!props.theme.cellClass && !cell.dummy)) { - style.border = '1px solid rgb(204, 204, 204)' - } - } - - //Non navigable columns get now a custom disable style - if (props.headers[0][columnIndex]?.disableNavigation && !cell.dummy) { - /** @todo We can apply the custom class if theme has it by using a class builder such as clsx **/ - style.opacity = 0.6 - } - - /** - * @todo We need to check if the row is a dummy but its parent dummy is not anymore visible - * e.:g - * dummy 1 has a rowspawn of total 3 but none of its parent are visible, so dummy 3 assume the children value and highlight - * of the parent because there is none visible - * @todo Check if creating a lifecycle cell mount/unmount helps - * @todo The children renderer has to be controlled via the custom column configuration - * */ + const { children } = cell + const isSelected = + rowIndex === props.coords.rowIndex && + columnIndex === props.coords.colIndex + /** + * @todo Not considering well merged cells, i need to look up by merged too + */ + const isRowSelected = + rowIndex === props.coords.rowIndex + if (isSelected) { + style.border = '1px solid blue' + } else { + //Bind default border + if ( + !props.theme || + (!props.theme.cellClass && !cell.dummy) + ) { + style.border = + '1px solid rgb(204, 204, 204)' + } + } + + //Non navigable columns get now a custom disable style + if ( + props.headers[0][columnIndex] + ?.disableNavigation && + !cell.dummy + ) { + /** @todo We can apply the custom class if theme has it by using a class builder such as clsx **/ + style.opacity = 0.6 + } + + /** + * @todo We need to check if the row is a dummy but its parent dummy is not anymore visible + * e.:g + * dummy 1 has a rowspawn of total 3 but none of its parent are visible, so dummy 3 assume the children value and highlight + * of the parent because there is none visible + * @todo Check if creating a lifecycle cell mount/unmount helps + * @todo The children renderer has to be controlled via header accessor and cell renderer if its present + * */ + + const cellClassName = + !cell.dummy && + isRowSelected && + props.theme?.currentRowClass + ? clsx( + props.theme?.cellClass, + props.theme?.currentRowClass, + ) + : !cell.dummy + ? props.theme?.cellClass + : undefined + + //Ensure dummies does not have border + if (cell.dummy) { + style.border = '0px' + } + + return ( +
+ onCellClick( + event, + cell, + rowIndex, + columnIndex, + ) + } + onDoubleClick={e => + onCellDoubleClick( + e, + cell, + rowIndex, + columnIndex, + children, + ) + } + ref={ref} + > + {typeof children === 'function' + ? children() + : children} +
+ ) + }, + [props.coords, props.theme, props.onCellClick, props.headers, props.width], + ) - const cellClassName = - !cell.dummy && isRowSelected && props.theme?.currentRowClass - ? clsx(props.theme?.cellClass, props.theme?.currentRowClass) - : !cell.dummy - ? props.theme?.cellClass - : undefined + const cellRenderer = useCallback( + ({ rowIndex, columnIndex, key, parent, style, ...otherArgs }: GridCellProps) => { + const cell = props.rows[rowIndex]?.[columnIndex] - //Ensure dummies does not have border - if (cell.dummy) { - style.border = '0px' + const rendererProps: MeasurerRendererProps = { + ...otherArgs, + style, + rowIndex, + columnIndex, + cell, + getColumnWidth: props.getColumnWidth, } - return ( -
onCellClick(event, cell, rowIndex, columnIndex)} - onDoubleClick={e => onCellDoubleClick(e, cell, rowIndex, columnIndex, children)} - ref={ref} - > - {typeof children === 'function' ? children() : children} -
- ) + rendererProps={rendererProps} + /> + ) : null }, - [props.coords, props.theme, props.onCellClick, props.headers, props.width], - ) - - const cellRenderer = useCallback( - ({ rowIndex, columnIndex, key, parent, style, ...otherArgs }: GridCellProps) => { - const cell = - props.rows[ - rowIndex - ]?.[ - columnIndex - ] - - const rendererProps: MeasurerRendererProps = { - ...otherArgs, - style, - rowIndex, - columnIndex, - cell, - getColumnWidth: - props.getColumnWidth, - } - - return cell ? ( - - ) : null - }, [props.rows, props.coords, props.theme, props.width], ) diff --git a/src/core/ScrollHandler.tsx b/src/core/HorizontalScrollHandler.tsx similarity index 80% rename from src/core/ScrollHandler.tsx rename to src/core/HorizontalScrollHandler.tsx index c656c69..7eb4bfd 100644 --- a/src/core/ScrollHandler.tsx +++ b/src/core/HorizontalScrollHandler.tsx @@ -13,8 +13,16 @@ import { debounce } from 'lodash' import { makeStyles } from '@material-ui/core/styles' import { StretchMode } from '../types/stretch-mode.enum' import { GridApi } from '../types/grid-api.type' +import { + HorizontalScrollHandlerProps, + ScrollHandlerRef, + HeaderGridRef, +} from './horizontalScrollHandlerProps' -const recomputeDebounceTimeout = 1000 +//Time to wait before set non scrolling state +const RESET_SCROLLING_STATE_DEBOUNCE_TIME = 100 +//Time to wait before recompute the grid +const RECOMPUTE_DEBOUNCE_TIME = 1000 const useStyles = makeStyles(() => ({ scrollContent: { @@ -44,41 +52,24 @@ const useStyles = makeStyles(() => ({ }, })) -interface VirtualizedGridRef { - forceUpdate: () => void - recomputeGridSize: () => void -} - -interface ScrollHandlerChildrenProps { - height: number - isScrolling: boolean - scrollTop: number - scrollLeft: number - headerRef: React.MutableRefObject - gridRef: React.MutableRefObject -} - -export interface ScrollHandlerRef { - recompute: () => void - forceUpdate: () => void -} - -export type ScrollHandlerChildrenFn = (props: ScrollHandlerChildrenProps) => void - -interface Props { - stretchMode: StretchMode - totalColumnWidth: number - width: number - scrollContainer: Element | null - children: ScrollHandlerChildrenFn -} -const ScrollHandler = forwardRef( +/** + * Component responsible for handling the horizontal scroll using a fake scroll technique + * and sticking on the bottom if necessary + * Only handles the scrollLeft because react-virtualized handles scrollTop for us + */ +const HorizontalScrollHandler = forwardRef( ( - { children, scrollContainer, width, totalColumnWidth, stretchMode }: Props, + { + children, + scrollContainer, + width, + totalColumnWidth, + stretchMode, + }: HorizontalScrollHandlerProps, componentRef: React.Ref, ) => { const scrollChildRef = useRef(null) - const headerRef = useRef(null) + const headerRef = useRef(null) const gridRef = useRef(null) const fakeScrollerRef = useRef(null) const [stickyScroller, setStickyScroller] = useState(true) @@ -125,11 +116,11 @@ const ScrollHandler = forwardRef( const setNotScrolling = useCallback( debounce(() => { setScrolling(false) - }, 100), + }, RESET_SCROLLING_STATE_DEBOUNCE_TIME), [], ) - const handleHorizontalScroll = useCallback( + const handleScroll = useCallback( ({ scrollLeft: paramScrollLeft }) => { //Prevent a re-render when the target scroll left hasn't change if (scrollLeft === paramScrollLeft) { @@ -147,9 +138,11 @@ const ScrollHandler = forwardRef( debounce(() => { headerRef.current?.recomputeGridSize() gridRef.current?.recomputeGridSize() - }, recomputeDebounceTimeout), + }, RECOMPUTE_DEBOUNCE_TIME), [], ) + + // Checks the stretch mode and also the total column width vs actual container width const displayHorizontalScroll = useMemo(() => { return stretchMode === StretchMode.None && totalColumnWidth > width }, [width, totalColumnWidth, stretchMode]) @@ -182,7 +175,7 @@ const ScrollHandler = forwardRef( bottom: stickyScroller ? '0px' : 'unset', }} onScroll={e => { - handleHorizontalScroll({ scrollLeft: e.target['scrollLeft'] }) + handleScroll({ scrollLeft: e.target['scrollLeft'] }) }} ref={fakeScrollerRef} > @@ -214,4 +207,4 @@ const ScrollHandler = forwardRef( }, ) -export default ScrollHandler +export default HorizontalScrollHandler diff --git a/src/core/gridWrapperProps.ts b/src/core/gridWrapperProps.ts new file mode 100644 index 0000000..3705261 --- /dev/null +++ b/src/core/gridWrapperProps.ts @@ -0,0 +1,60 @@ +import { HeadersData } from '../columnGrid/types/header.type' +import { NavigationCoords } from '../navigation/types/navigation-coords.type' +import { GridApi } from '../types/grid-api.type' +import { GridTheme } from '../types/grid-theme' +import { RegisterChildFn } from './interfaces/registerChildFn' +import { GridRow } from '../types/row.interface' +import { SelectCellFn } from '../navigation/useNavigation' +import React from 'react' + +export interface ICellMountedRegisterData { + colIndex: number + rowIndex: number + elementNodeRef: Element +} + +export interface ICellNodeInfo { + rowIndex: number + colIndex: number + elementNodeRef: Element +} + +export interface CellChangeParams { + rowIndex: number + columnIndex: number + previousValue: ValueType + value: ValueType +} + +export interface GridWrapperCommonProps { + headers: HeadersData + // data: GridData; + /** @default { rowIndex: 0, colIndex: 0} **/ + defaultCoords?: NavigationCoords + /** @default false **/ + suppressNavigation?: boolean + /** @default false **/ + outsideClickDeselects?: boolean + onGridReady?: (gridRef: GridApi) => void + theme?: GridTheme + onCellChange: (params: CellChangeParams) => void +} + +export interface GridWrapperProps extends GridWrapperCommonProps { + className: string + minRowHeight: number + defaultColumnWidth: number + width: number + scrollLeft: number + scrollTop: number + isScrolling: boolean + height: number + registerChild: RegisterChildFn + gridContainerRef: HTMLDivElement | null + coords: NavigationCoords + rows: Array + columnCount: number + selectCell: SelectCellFn + onCellClick: (params: NavigationCoords & { event: React.MouseEvent }) => void + getColumnWidth: ({ index }: { index: number }) => number +} diff --git a/src/core/horizontalScrollHandlerProps.ts b/src/core/horizontalScrollHandlerProps.ts new file mode 100644 index 0000000..d0f0424 --- /dev/null +++ b/src/core/horizontalScrollHandlerProps.ts @@ -0,0 +1,34 @@ +import React from 'react' +import { GridApi } from '../types/grid-api.type' +import { StretchMode } from '../types/stretch-mode.enum' + +export interface HeaderGridRef { + forceUpdate: () => void + recomputeGridSize: () => void +} + +interface ScrollHandlerChildrenProps { + height: number + isScrolling: boolean + scrollTop: number + scrollLeft: number + headerRef: React.MutableRefObject + gridRef: React.MutableRefObject +} + +export interface ScrollHandlerRef { + recompute: () => void + forceUpdate: () => void +} + +export type ScrollHandlerChildrenFn = (props: ScrollHandlerChildrenProps) => void + +export interface HorizontalScrollHandlerProps { + stretchMode: StretchMode + //The total of columns width sum considering fixed widths already + totalColumnWidth: number + //Container width (actual size) + width: number + scrollContainer: Element | null + children: ScrollHandlerChildrenFn +} diff --git a/src/core/interfaces/cellMeasureRendererProps.ts b/src/core/interfaces/cellMeasureRendererProps.ts deleted file mode 100644 index e69de29..0000000 diff --git a/src/core/interfaces/getColumnWidthFn.ts b/src/core/interfaces/getColumnWidthFn.ts index 0c9eb76..6120cbe 100644 --- a/src/core/interfaces/getColumnWidthFn.ts +++ b/src/core/interfaces/getColumnWidthFn.ts @@ -2,6 +2,9 @@ export interface GetColumnWidthArgs { index: number } +/** + * Returns the fixed/dynamic width of the given column index + */ export interface GetColumnWidthFn { (args: GetColumnWidthArgs): number } diff --git a/src/core/interfaces/registerChildFn.ts b/src/core/interfaces/registerChildFn.ts index 1e495fc..6901845 100644 --- a/src/core/interfaces/registerChildFn.ts +++ b/src/core/interfaces/registerChildFn.ts @@ -1,3 +1,6 @@ +/** + * React-virtualized requires this function in order to track the HTML element by registering it + */ export interface RegisterChildFn { (element: Element): void } diff --git a/src/index.tsx b/src/index.tsx index 0c1c19f..1513f9e 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,7 +1,7 @@ import React, { forwardRef, useCallback, useMemo, useRef } from 'react' import { AutoSizer, ColumnSizer } from 'react-virtualized' -import ScrollHandler, { ScrollHandlerRef } from './core/ScrollHandler' +import HorizontalScrollHandler, { ScrollHandlerRef } from './core/HorizontalScrollHandler' import GridWrapper, { GridWrapperCommonProps } from './core/GridWrapper' import { makeStyles } from '@material-ui/core/styles' import ColumnGrid from './columnGrid/ColumnGrid' @@ -80,222 +80,200 @@ interface ApolloSpreadSheetRef { forceUpdate: () => void } -export const ApolloSpreadSheet = forwardRef((props: Props, componentRef: React.Ref) => { - const classes = useStyles() - const columnCount = useMemo(() => { - return props.data.length ? props.data[0].length : 0 - }, [props.data]) +export const ApolloSpreadSheet = forwardRef( + (props: Props, componentRef: React.Ref) => { + const classes = useStyles() + const columnCount = useMemo(() => { + return props.data.length ? props.data[0].length : 0 + }, [props.data]) - const gridContainerRef = useRef(null) - const minColumnWidth = props.minColumnWidth ?? 60 - const rows: Array = useMemo(() => { - return insertDummyCells(props.data) - }, [props.data]) - const scrollHandlerRef = useRef(null) + const gridContainerRef = useRef(null) + const minColumnWidth = props.minColumnWidth ?? 60 + const rows: Array = useMemo(() => { + return insertDummyCells(props.data) + }, [props.data]) + const scrollHandlerRef = useRef(null) - /** - * Stores the main headers only, nested headers are not required in here - * because this is used as an utility - * @todo Improve support for nested headers receiving in a new prop like mergedData - */ - const mainHeaders: Column[] = useMemo(() => { - if (Array.isArray(props.headers[0])) { - return props.headers[0] as Column[] - } - return props.headers as Column[] - }, [props.headers]) + /** + * Stores the main headers only, nested headers are not required in here + * because this is used as an utility + * @todo Improve support for nested headers receiving in a new prop like mergedData + */ + const mainHeaders: Column[] = useMemo(() => { + if (Array.isArray(props.headers[0])) { + return props.headers[0] as Column[] + } + return props.headers as Column[] + }, [props.headers]) - /** - * Returns a given column at the provided index if exists - * @param index - * @param line This represents the row but by default we fetch only from the first, this is in order to support nested headers - */ - const getColumnAt = useCallback( - (index: number, line = 0) => { - return props.headers[line]?.[index] - }, - [props.headers], - ) + /** + * Returns a given column at the provided index if exists + * @param index + * @param line This represents the row but by default we fetch only from the first, this is in order to support nested headers + */ + const getColumnAt = useCallback( + (index: number, line = 0) => { + return props.headers[line]?.[index] + }, + [props.headers], + ) - const [coords, selectCell, onCellClick] = useNavigation({ - defaultCoords: props.defaultCoords ?? { rowIndex: 0, colIndex: 0 }, - /** @todo Dont pass the data but a callback so it can read the row/cell from */ - data: rows, - gridRootRef: gridContainerRef.current, - columnsCount: columnCount, - rowsCount: rows.length, - suppressNavigation: props.suppressNavigation ?? false, - getColumnAt, - }) + const [coords, selectCell, onCellClick] = useNavigation({ + defaultCoords: props.defaultCoords ?? { rowIndex: 0, colIndex: 0 }, + /** @todo Dont pass the data but a callback so it can read the row/cell from */ + data: rows, + gridRootRef: gridContainerRef.current, + columnsCount: columnCount, + rowsCount: rows.length, + suppressNavigation: props.suppressNavigation ?? false, + getColumnAt, + }) - const fixedColumnWidths = useRef<{ totalSize: number; mapping: FixedColumnWidthRecord }>({ - totalSize: 0, - mapping: {}, - }) - const latestContainerWidth = useRef(0) - const latestColumns = useRef([]) + const fixedColumnWidths = useRef<{ totalSize: number; mapping: FixedColumnWidthRecord }>({ + totalSize: 0, + mapping: {}, + }) + const latestContainerWidth = useRef(0) + const latestColumns = useRef([]) - const buildColumnTotalWidth = (containerWidth: number) => { - //Cached value - if ( - !shallowDiffers( - mainHeaders, - latestColumns.current, - ) && - latestContainerWidth.current === - containerWidth - ) { - return ( - containerWidth - - fixedColumnWidths.current - .totalSize - - CONTAINER_SCROLL_WIDTH - ) - } + const buildColumnTotalWidth = (containerWidth: number) => { + //Cached value + if ( + !shallowDiffers(mainHeaders, latestColumns.current) && + latestContainerWidth.current === containerWidth + ) { + return containerWidth - fixedColumnWidths.current.totalSize - CONTAINER_SCROLL_WIDTH + } - const { - mapping, - totalSize, - } = createFixedWidthMapping( - mainHeaders, - containerWidth, - minColumnWidth, - props.stretchMode ?? - StretchMode.None, - CONTAINER_SCROLL_WIDTH, - ) + const { mapping, totalSize } = createFixedWidthMapping( + mainHeaders, + containerWidth, + minColumnWidth, + props.stretchMode ?? StretchMode.None, + CONTAINER_SCROLL_WIDTH, + ) - //Just update with the new calculated (if it was otherwise it might have been a cached result) - fixedColumnWidths.current = { - totalSize, - mapping, - } + //Just update with the new calculated (if it was otherwise it might have been a cached result) + fixedColumnWidths.current = { + totalSize, + mapping, + } - //Store if it has changed - if ( - shallowDiffers( - mainHeaders, - latestColumns.current, - ) - ) { - latestColumns.current = mainHeaders as Column[] - } - if ( - latestContainerWidth.current !== - containerWidth - ) { - latestContainerWidth.current = containerWidth - } + //Store if it has changed + if (shallowDiffers(mainHeaders, latestColumns.current)) { + latestColumns.current = mainHeaders as Column[] + } + if (latestContainerWidth.current !== containerWidth) { + latestContainerWidth.current = containerWidth + } - //The available width that the grid will use - return Math.max( - 0, - containerWidth - - fixedColumnWidths.current - .totalSize - - CONTAINER_SCROLL_WIDTH, - ) - } + //The available width that the grid will use + return Math.max( + 0, + containerWidth - fixedColumnWidths.current.totalSize - CONTAINER_SCROLL_WIDTH, + ) + } - /** - * @todo Also we need to support nested headers which means which i'm not sure its okay - * @param getColumnWidth - */ - //https://github.com/bvaughn/react-virtualized/issues/698 - const getColumnWidthHelper = getColumnWidth => ({ index }: { index: number }) => { - return fixedColumnWidths.current.mapping[index] ?? getColumnWidth({ index }) - } + /** + * @todo Also we need to support nested headers which means which i'm not sure its okay + * @param getColumnWidth + */ + //https://github.com/bvaughn/react-virtualized/issues/698 + const getColumnWidthHelper = getColumnWidth => ({ index }: { index: number }) => { + return fixedColumnWidths.current.mapping[index] ?? getColumnWidth({ index }) + } - //Stores the amount of columns that we want to calculate using the remaining width of the grid - const calculatingColumnCount = useMemo(() => { - return columnCount - mainHeaders.filter(e => e.width).length - }, [columnCount, mainHeaders]) + //Stores the amount of columns that we want to calculate using the remaining width of the grid + const calculatingColumnCount = useMemo(() => { + return columnCount - mainHeaders.filter(e => e.width).length + }, [columnCount, mainHeaders]) - const getTotalColumnWidth = useCallback( - getColumnWidth => { - let value = 0 - for (let i = 0; i < columnCount; i++) { - value += getColumnWidthHelper(getColumnWidth)({ index: i }) - } - return value - CONTAINER_SCROLL_WIDTH - }, - [mainHeaders], - ) + const getTotalColumnWidth = useCallback( + getColumnWidth => { + let value = 0 + for (let i = 0; i < columnCount; i++) { + value += getColumnWidthHelper(getColumnWidth)({ index: i }) + } + return value - CONTAINER_SCROLL_WIDTH + }, + [mainHeaders], + ) + + const renderGridsWrapper = (width: number) => { + return ( + <> + + {({ registerChild, getColumnWidth }) => ( + + {({ scrollTop, scrollLeft, isScrolling, gridRef, headerRef, height }) => ( + <> + + + + )} + + )} + + + ) + } - const renderGridsWrapper = (width: number) => { return ( - <> - - {({ registerChild, getColumnWidth }) => ( - - {({ scrollTop, scrollLeft, isScrolling, gridRef, headerRef, height }) => ( - <> - - - - )} - - )} - - +
+ {({ width }) => renderGridsWrapper(width)} +
) - } - - return ( -
- {({ width }) => renderGridsWrapper(width)} -
- ) -}) + }, +) export default ApolloSpreadSheet