import React, { Children, cloneElement, createContext, isValidElement, memo, ReactElement, useMemo } from 'react'
import { useParentNodeSize } from '../hooks/useParentNodeSize'
import { Stack, StackProps } from '../View/Stack'
import { View } from '../View/View'
import { useVisibility } from '../Visibility'
export type LayoutProps = StackProps & {
type?: 'column' | 'row'
children?: React.ReactNode
}
export const LayoutContext = createContext<{
total: number
flexes: number[]
type: LayoutProps['type']
}>({
total: 0,
flexes: [],
type: 'row',
})
export const acceptsProps = (child, key) =>
!!(child && child.type && child.type.acceptsProps && child.type.acceptsProps[key])
export const Layout = memo((props: LayoutProps) => {
const children: ReactElement[] = Children.map(props.children, child => {
if (!isValidElement(child) || !acceptsProps(child, 'paneProps')) {
console.warn(
`Invalid child: accepts only as children. You can fix this by adding Component.acceptsProps = { paneProps: true } and passing the pane props down to child .`,
child,
props,
)
return null
}
return child
}).filter(Boolean)
const visibility = useVisibility()
const total = children.length
const flexes = children.map(child => child.props.flex || 1)
const memoValue = useMemo(() => ({ type: props.type, total, flexes }), [
props.type,
total,
JSON.stringify(flexes),
])
const { ref, height, width } = useParentNodeSize({
disable: !visibility,
throttle: 200,
})
return (
)
})
const FlexLayout = memo(({ children, type, ...colProps }: LayoutProps) => {
const visibility = useVisibility()
const { ref, ...size } = useParentNodeSize({
disable: !visibility,
throttle: 200,
})
const dimension = type === 'row' ? 'width' : 'height'
const parentSize = size[dimension]
const validChildren = Children.toArray(children).filter(child => !!child)
const total = validChildren.length
const childElements = validChildren.map((child, index) => {
return cloneElement(child as any, {
index,
total,
parentSize,
})
})
// only flex once we measure
// const flex = parentSize ? 1 : 'inherit'
if (type === 'row') {
return (
{childElements}
)
}
return (
{childElements}
)
})