import { DataNode, PushNode } from './buildPushTree' import { RunnerPartialObject } from './types' export interface ListItem { id: number uuid: string created_at: Date updated_at: Date } export const getHeightPlusY = (pushNode: PushNode): number => { if (pushNode.dataNode) { return pushNode.dataNode.height + pushNode.originalY + pushNode.yOffset } else { console.error({ pushNode }) throw new Error('getHeightPlusY -> pushNode without dataNode') } } export const getHeight = (pushNode: PushNode): number => { if (pushNode.dataNode) { return pushNode.dataNode.height } else { console.error({ pushNode }) throw new Error('getHeight -> pushNode without dataNode') } } // get sum per column, export const getMasonryHeightForList = (parent: PushNode): number => { const { columnCount, rowMargin } = parent if (!parent.dataNode?.listItems.length) { return 0 } if (columnCount === undefined || rowMargin === undefined) { throw new Error(`List parent ${parent.objectId}`) } const columnHeights = new Array(columnCount).fill(0) // for each, sum to its column parent.children.forEach((child, index) => { columnHeights[index % columnCount] += getHeight(child) }) const spaceBetweenRows = (rowMargin * (parent.dataNode.listItems.length - 1)) / columnCount // return the max const masonryListHeight = Math.max(...columnHeights) + spaceBetweenRows return masonryListHeight } // get sum of max per row export const getNonMasonryHeightForList = (parent: PushNode): number => { const { columnCount, rowMargin } = parent const rows = parent.dataNode?.listItems.length || 0 if (rows === 0) { return 0 } if (columnCount === undefined || rowMargin === undefined) { throw new Error(`List parent ${parent.objectId}`) } let total = 0 for (let i = 0; i < rows; i += 1) { const start = columnCount * i const end = columnCount * (i + 1) // for each set on its row const rowListItemHeights = parent.children .slice(start, end) .map(node => node.dataNode?.height || 0) // get the max of each row, with 0 as minimum const maxRowListItemHeight = Math.max(...rowListItemHeights, 0) total += maxRowListItemHeight } const spaceBetweenRows = (rowMargin * (rows - 1)) / columnCount // return the sum const totalListHeight = total + spaceBetweenRows return totalListHeight } export const getRowHeight = ( list: DataNode, object: RunnerPartialObject, item: ListItem ): number | undefined => { const { listItems, pushNode } = list const { id: itemId } = item const { attributes } = object const { columnCount = 1 } = attributes if (!pushNode) { return } const index = listItems?.findIndex(id => id === itemId) const row = Math.floor(index / columnCount) const rowItems = pushNode.children.slice( columnCount * row, columnCount * (1 + row) ) const getMaxHeight = (current: number, listItem: PushNode) => { const { dataNode } = listItem const { height } = dataNode || {} if (height) { return Math.max(current, height) } return current } return rowItems.reduce(getMaxHeight, 0) } export const getSingleColumnHeightForList = (parent: PushNode): number => { const { columnCount, rowMargin } = parent const rows = parent.dataNode?.listItems.length || 0 if (rows === 0) { return 0 } if (columnCount === undefined || rowMargin === undefined) { throw new Error(`List parent ${parent.objectId}`) } const spaceBetweenRows = rowMargin * (rows - 1) return ( parent.children.reduce( (total: number, child: PushNode) => getHeightPlusY(child) + total, 0 ) + spaceBetweenRows ) } export const getChildrenHeightsForList = (parent: PushNode): number => { if (parent.columnCount === 1) { return getSingleColumnHeightForList(parent) } else if (parent.masonry) { return getMasonryHeightForList(parent) } else { return getNonMasonryHeightForList(parent) } } export const getChildrenHeightsForSection = (parent: PushNode): number => { if (!parent.children?.length) { return getHeight(parent) } else { return getChildrenHeights(parent) + (parent?.paddingBottom || 0) } } export const getChildrenHeights = (parent: PushNode): number => { return parent.children.reduce((previousMax, node) => { const heightPlusY = getHeightPlusY(node) return Math.max(heightPlusY, previousMax) }, 0) }