{"version":3,"file":"index-D2_CDSQy.js","sources":["../../../app/javascript/src/explore/hooks/useNonInitialEffect/index.tsx","../../../app/javascript/src/explore/elements/Expand/index.tsx"],"sourcesContent":["/* eslint-disable consistent-return */\nimport {\n useEffect, EffectCallback, DependencyList, useRef, useLayoutEffect,\n} from 'react';\n\n/**\n * These hook gets called only when the dependencies change but not during initial render.\n * https://medium.com/swlh/prevent-useeffects-callback-firing-during-initial-render-the-armchair-critic-f71bc0e03536\n *\n * @param {EffectCallback} effect The `useEffect` callback function.\n * @param {DependencyList} deps An array of dependencies.\n *\n */\n\n// eslint-disable-next-line max-len\nfunction createReactEffect( initialRender: React.MutableRefObject<boolean>, effect: EffectCallback ) {\n return () => {\n if ( initialRender.current ) {\n initialRender.current = false;\n return;\n }\n return effect();\n };\n}\nexport const useNonInitialEffect = ( effect: EffectCallback, deps: DependencyList ) => {\n const initialRender = useRef( true );\n\n useEffect( createReactEffect( initialRender, effect ), deps );\n};\n\nexport const useNonInitialLayoutEffect = ( effect: EffectCallback, deps: DependencyList ) => {\n const initialRender = useRef( true );\n\n useLayoutEffect( createReactEffect( initialRender, effect ), deps );\n};\n","/* eslint-disable max-len */\n/* eslint-disable no-use-before-define */\nimport * as React from 'react';\nimport cls from 'classnames';\n\nimport animateHeight from 'src/animations/animateHeight';\nimport { useNonInitialLayoutEffect } from 'src/explore/hooks/useNonInitialEffect';\nimport BreakpointsService from 'src/explore/services/breakpoints';\n\nexport type IHeightByBreakpoint = {\n xs?: number | null;\n sm?: number | null;\n md?: number | null;\n lg?: number | null;\n};\n\nexport interface ExpandProps {\n className?: string;\n initialHeight?: number | IHeightByBreakpoint;\n isOpen: boolean;\n children:\n | React.ReactNode\n | (( props: {\n collapsedHeight?: number | null;\n isOpen?: boolean;\n overflow?: boolean;\n }) => React.ReactNode );\n}\n\nexport const Expand = ({ children, className, isOpen, initialHeight }: ExpandProps ) => {\n const [ overflow, setOverflow ] = React.useState( false );\n\n // initial height for every breakpoint\n const initialHeightByBreakpoint = useInitialHeightByBreakpoint( initialHeight );\n\n // compute collpased height for this breakpoint\n const collapsedHeight = useCollapsedHeight( initialHeightByBreakpoint );\n\n // set refs\n const containerRef = React.useRef<HTMLDivElement>( null );\n const [ contentRef, setContentRef, height ] = useRefCallback();\n\n // expansion logic\n useAnimateHeight( containerRef.current, contentRef, !isOpen, collapsedHeight );\n\n // compute overflow\n React.useEffect(() => {\n const determineOverflow = () => {\n if ( contentRef ) {\n setOverflow(\n typeof collapsedHeight === 'number' && collapsedHeight < calculateHeight( contentRef )\n );\n }\n };\n\n determineOverflow();\n window.addEventListener( 'resize', determineOverflow );\n return () => {\n window.removeEventListener( 'resize', determineOverflow );\n };\n }, [ collapsedHeight, contentRef, height ]);\n\n return (\n <div\n className={cls( 'overflow-hidden', className )}\n ref={containerRef}\n style={overflow && !isOpen ? { height: collapsedHeight } : null}\n >\n <div className=\"overflow-hidden\" ref={setContentRef}>\n {typeof children === 'function'\n ? children({ collapsedHeight, isOpen, overflow })\n : children}\n </div>\n </div>\n );\n};\n\nconst calculateHeight = ( elem: HTMLDivElement ) => {\n const style = getComputedStyle( elem );\n return elem.offsetHeight + parseInt( style.marginTop, 10 ) + parseInt( style.marginBottom, 10 );\n};\n\n/**\n * HOOKS\n */\n\n// hook to animate height bsased on open state\nfunction useAnimateHeight(\n container: HTMLDivElement,\n content: HTMLDivElement,\n open: boolean,\n minHeight: number\n) {\n // animation function\n const setHeight = React.useCallback(\n () =>\n animateHeight({\n container,\n content,\n duration: 200,\n }),\n [ container, content ]\n );\n\n // run animation anytime open state changes\n useNonInitialLayoutEffect(() => {\n setHeight()({\n open,\n minHeight,\n });\n }, [ open ]);\n}\n\n// compute collapsed height for current breakpoint\nfunction useCollapsedHeight( initialHeights: IHeightByBreakpoint ) {\n const [ collapsedHeight, setCollapsedHeight ] = React.useState<number>( null );\n\n React.useEffect(() => {\n const collapse = () => {\n // initial height for current breakpoint\n const newHeight =\n initialHeights[BreakpointsService.getBreakpointSize() as keyof IHeightByBreakpoint];\n setCollapsedHeight( newHeight );\n };\n collapse();\n\n window.addEventListener( 'resize', collapse );\n return () => {\n window.removeEventListener( 'resize', collapse );\n };\n }, [ initialHeights ]);\n\n return collapsedHeight;\n}\n\n// initial height for every breakpoint\nexport function useInitialHeightByBreakpoint( initialHeight: ExpandProps['initialHeight']) {\n return React.useMemo<IHeightByBreakpoint>(() => {\n if ( typeof initialHeight !== 'object' ) {\n return {\n xs: initialHeight,\n sm: initialHeight,\n md: initialHeight,\n lg: initialHeight,\n };\n }\n\n let cascadingHeight: number = initialHeight.xs || null;\n const heights: IHeightByBreakpoint = {};\n\n const sizes: Array<keyof IHeightByBreakpoint> = [ 'xs', 'sm', 'md', 'lg' ];\n sizes.forEach(( size: keyof IHeightByBreakpoint ) => {\n if ( initialHeight[size] || initialHeight[size] === null ) {\n cascadingHeight = initialHeight[size];\n }\n heights[size] = cascadingHeight;\n });\n\n return heights;\n }, [ initialHeight ]);\n}\n\n// ref function with callback to determine height\n// any time the elem changes make sure to compute the height\nfunction useRefCallback(): [HTMLDivElement | null, ( elem: HTMLDivElement ) => void, number | null] {\n const [ ref, setRef ] = React.useState<HTMLDivElement>( null );\n const [ height, setHeight ] = React.useState<number>( null );\n\n const refCallback = ( elem: HTMLDivElement ) => {\n if ( elem ) {\n setRef( elem );\n setHeight( calculateHeight( elem ));\n }\n };\n\n return [ ref, refCallback, height ];\n}\n"],"names":["createReactEffect","initialRender","effect","useNonInitialLayoutEffect","deps","useRef","useLayoutEffect","Expand","children","className","isOpen","initialHeight","overflow","setOverflow","React.useState","initialHeightByBreakpoint","useInitialHeightByBreakpoint","collapsedHeight","useCollapsedHeight","containerRef","React.useRef","contentRef","setContentRef","height","useRefCallback","useAnimateHeight","React.useEffect","determineOverflow","calculateHeight","React.createElement","cls","elem","style","container","content","open","minHeight","setHeight","React.useCallback","animateHeight","initialHeights","setCollapsedHeight","collapse","newHeight","BreakpointsService","React.useMemo","cascadingHeight","heights","size","ref","setRef"],"mappings":"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"}