import { useRef, useEffect, useMemo, useCallback } from 'react' import PropTypes from 'prop-types' import { ChildrenFnProps, ItemProps } from './types' import { useApiContext } from './hooks' import { NoRefError } from './no-ref-error' /** * Gallery item * * Should be a children of Gallery component */ export const Item = ({ children, ...restProps }: ItemProps): JSX.Element => { const ref = useRef(null) const { remove, set, handleClick, close, isRefRegistered } = useApiContext() const refCallback = useCallback['ref']>( (node) => { ref.current = node set(ref, restProps) }, [set, ...Object.values(restProps)], ) const open = useCallback['open']>( (event) => { if (!isRefRegistered(ref)) { throw new NoRefError() } handleClick(ref, null, null, event) }, [handleClick, isRefRegistered], ) const childrenFnProps: ChildrenFnProps = useMemo( () => ({ ref: refCallback, open, close, }), [refCallback, open, close], ) useEffect(() => { return () => { if (ref.current === null) { remove(ref) } } }, [remove]) return children(childrenFnProps) } Item.propTypes = { children: PropTypes.func.isRequired, original: PropTypes.string, originalSrcset: PropTypes.string, thumbnail: PropTypes.string, width: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), height: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), alt: PropTypes.string, caption: PropTypes.string, content: PropTypes.element, html: PropTypes.string, id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), cropped: PropTypes.bool, sourceId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), }