import { gloss } from 'gloss' import React, { useRef } from 'react' import { composeRefs } from '../helpers/composeRefs' import { PaddedView } from './PaddedView' import { ScrollableIntersection, ScrollableParentContext } from './ScrollableParentStore' import { ScrollableViewProps } from './types' import { View } from './View' import { wrappingSpaceTheme } from './wrappingSpaceTheme' // dont allow flexDirection so we force props down through flexDirection export function ScrollableView(props: ScrollableViewProps) { const ref = useRef(null) const scrollableParent = ScrollableParentContext.useCreateStore({ ref }) const { children, scrollable, parentSpacing, hideScrollbars, minHeight, ...rest } = props // ignore minHeight, use in paddedview minHeight // add padding inside scrollable so we get proper padding after end elements const content = wrapWithPaddedView(children, props) const hasPadding = isPadded(props) return ( {scrollable && scrollableParent.shouldScrollIntersect && ( )} {content} ) } export const ScrollableChrome = gloss(View, { boxSizing: 'content-box', flexDirection: 'inherit', flexWrap: 'inherit', }).theme(props => ({ ...(props.scrollable === 'x' && { overflowX: 'auto', overflowY: 'hidden' }), ...(props.scrollable === 'y' && { overflowY: 'auto', overflowX: 'hidden' }), ...(props.scrollable === true && { overflow: 'auto' }), ...(!props.scrollable && wrappingSpaceTheme(props)), })) export const isPadded = (props: ScrollableViewProps) => Array.isArray(props.padding) ? props.padding.some(x => !!x) : !!props.padding export function wrapWithPaddedView( element: React.ReactNode, props: ScrollableViewProps, ): JSX.Element { // wrap inner with padding view only if necessary (this is a low level view) // this is necessary so CSS scrollable has proper "end margin" if (isPadded(props)) { const isWrapped = props.flexWrap === 'wrap' element = ( {element} ) } return element as JSX.Element }