app/Frontpage/SearchResultsPane.tsx (65 lines of code) (raw):

import React, { CSSProperties, useEffect, useState } from "react"; import { VidispineItem } from "../vidispine/item/VidispineItem"; import ItemTile from "./ItemTile"; import { FixedSizeGrid, GridChildComponentProps } from "react-window"; interface SearchResultsPaneProps { results: VidispineItem[]; parentRef: React.RefObject<HTMLDivElement>; onItemClicked: (itemId: string) => void; } const SearchResultsPane: React.FC<SearchResultsPaneProps> = (props) => { const [dimensions, setDimensions] = useState({ height: window.innerHeight, width: window.innerWidth, }); //tile sizes, in pixels const tileWidth = 240; const tileHeight = 240; const tileMargin = 20; //react-window uses absolute positioning so we need to do a bit of maths... const totalResults = props.results.length; const columnCount = Math.floor(dimensions.width / (tileWidth + tileMargin)); const rowCount = Math.ceil(totalResults / columnCount); useEffect(() => { if (props.parentRef.current) { const parentDiv = props.parentRef.current as HTMLDivElement; const newval = { height: parentDiv.clientHeight, width: parentDiv.clientWidth, }; setDimensions(newval); console.log("debug: set search results pane to ", newval); } }, [props.parentRef]); const itemTileContainer = (childProps: GridChildComponentProps) => { const { columnIndex, rowIndex, style } = childProps; const itemIndex = rowIndex * columnCount + columnIndex; const outerDivStyle = Object.assign({} as CSSProperties, style, { marginLeft: tileMargin / 2, marginRight: tileMargin / 2, }); return itemIndex < totalResults ? ( <div style={outerDivStyle}> <ItemTile item={props.results[itemIndex]} imageMaxWidth={240} imageMaxHeight={135} onClick={props.onItemClicked} /> </div> ) : ( <></> ); }; return ( <FixedSizeGrid columnCount={columnCount} columnWidth={tileWidth + tileMargin} height={dimensions.height} rowCount={rowCount} rowHeight={tileHeight + tileMargin} width={dimensions.width} > {itemTileContainer} </FixedSizeGrid> ); }; export default SearchResultsPane;