{"version":3,"file":"Overlay.mjs","sources":["../../../../src/components/Overlay/Overlay.tsx"],"sourcesContent":["'use client'\n\nimport {\n  forwardRef,\n  useCallback,\n  useEffect,\n  useReducer,\n  useRef,\n  useState,\n} from 'react'\nimport ReactDOM from 'react-dom'\n\nimport classNames from 'classnames'\n\nimport useEventHandler from '~/src/hooks/useEventHandler'\nimport { useIsomorphicLayoutEffect } from '~/src/hooks/useIsomorphicLayoutEffect'\nimport useMergeRefs from '~/src/hooks/useMergeRefs'\nimport { getZIndexClassName } from '~/src/types/props-helpers'\n\nimport { useModalContainerContext } from '~/src/components/Modal'\nimport { ThemeProvider, useThemeName } from '~/src/components/ThemeProvider'\nimport { useWindow } from '~/src/components/WindowProvider'\n\nimport type {\n  ContainerRectAttr,\n  OverlayProps,\n  TargetRectAttr,\n} from './Overlay.types'\nimport { getOverlayStyle } from './utils'\n\nimport styles from './Overlay.module.scss'\n\nexport const CONTAINER_TEST_ID = 'bezier-container'\nexport const OVERLAY_TEST_ID = 'bezier-overlay'\nexport const ESCAPE_KEY = 'Escape'\n\nexport const Overlay = forwardRef<HTMLDivElement, OverlayProps>(\n  function Overlay(\n    {\n      children,\n      style,\n      className,\n      show = false,\n      container: givenContainer,\n      target,\n      position = 'left-center',\n      marginX = 0,\n      marginY = 0,\n      keepInContainer = false,\n      withTransition = false,\n      enableClickOutside = false,\n      containerStyle,\n      containerClassName,\n      onHide,\n      onTransitionEnd,\n      zIndex = 'overlay',\n      ...rest\n    },\n    forwardedRef\n  ) {\n    const { window, document, rootElement } = useWindow()\n\n    const [shouldRender, setShouldRender] = useState(false)\n    const [shouldShow, setShouldShow] = useState(false)\n\n    const containerRect = useRef<ContainerRectAttr | null>(null)\n    const targetRect = useRef<TargetRectAttr | null>(null)\n\n    const [, forceUpdate] = useReducer((x) => !x, true)\n\n    const containerRef = useRef<HTMLDivElement>(null)\n    const overlayRef = useRef<HTMLDivElement>(null)\n    const mergedRef = useMergeRefs<HTMLDivElement>(overlayRef, forwardedRef)\n\n    const modalContainer = useModalContainerContext()\n    const hasContainer = Boolean(givenContainer || modalContainer)\n    const container = givenContainer ?? modalContainer ?? rootElement\n\n    const handleOverlayForceUpdate = useCallback(() => {\n      forceUpdate()\n    }, [])\n\n    const handleContainerRect = useCallback(() => {\n      const {\n        width: containerWidth,\n        height: containerHeight,\n        top: containerTop,\n        left: containerLeft,\n      } = container.getBoundingClientRect()\n\n      containerRect.current = {\n        containerWidth,\n        containerHeight,\n        containerTop,\n        containerLeft,\n        scrollTop: hasContainer ? container.scrollTop : 0,\n        scrollLeft: hasContainer ? container.scrollLeft : 0,\n      }\n    }, [container, hasContainer])\n\n    useIsomorphicLayoutEffect(\n      function initContainerRect() {\n        if (show) {\n          handleContainerRect()\n        }\n      },\n      [show, handleContainerRect]\n    )\n\n    const handleTargetRect = useCallback(() => {\n      if (!target) {\n        return\n      }\n      const {\n        width: targetWidth,\n        height: targetHeight,\n        top: targetTop,\n        left: targetLeft,\n      } = target.getBoundingClientRect()\n      const { clientTop, clientLeft } = target\n\n      targetRect.current = {\n        targetWidth,\n        targetHeight,\n        targetTop,\n        targetLeft,\n        clientTop,\n        clientLeft,\n      }\n    }, [target])\n\n    useIsomorphicLayoutEffect(\n      function initTargetRect() {\n        if (show) {\n          handleTargetRect()\n        }\n      },\n      [show, handleTargetRect]\n    )\n\n    const handleTransitionEnd = useCallback<\n      React.TransitionEventHandler<HTMLDivElement>\n    >(\n      (event) => {\n        onTransitionEnd?.(event)\n        if (!show) {\n          setShouldRender(false)\n        }\n      },\n      [show, onTransitionEnd]\n    )\n\n    const handleBlockMouseWheel = useCallback(\n      (event: HTMLElementEventMap['wheel']) => {\n        event.stopPropagation()\n      },\n      []\n    )\n\n    const handleHideOverlay = useCallback(\n      (event: MouseEvent) => {\n        /**\n         * NOTE: Type checking with instanceof makes it difficult to handle cases where the window object is different.\n         */\n        if (\n          !event.target ||\n          !(event.target as HTMLElement).closest(`.${styles.Overlay}`)\n        ) {\n          onHide?.()\n\n          if (!enableClickOutside) {\n            event.stopPropagation()\n          }\n        }\n      },\n      [enableClickOutside, onHide]\n    )\n\n    const handleKeydown = useCallback(\n      (event: HTMLElementEventMap['keyup']) => {\n        if (event.key === ESCAPE_KEY) {\n          onHide?.()\n        }\n      },\n      [onHide]\n    )\n\n    useEventHandler(document, 'click', handleHideOverlay, show, true)\n    useEventHandler(document, 'keydown', handleKeydown, show)\n    useEventHandler(containerRef.current, 'wheel', handleBlockMouseWheel, show)\n\n    useEffect(() => {\n      handleOverlayForceUpdate()\n    }, [children, handleOverlayForceUpdate])\n\n    /**\n     * Case 1: show === true\n     * show -> shouldRender -> shouldShow\n     * shouldRender 를 true 로 설정하고, 직후에 shouldShow 를 true 로 설정하여 transition 유발\n     *\n     * Case 2: show === false\n     * show -> shouldShow -> (...) -> shouldRender\n     * shouldShow 를 false 로 설정하고, shouldRender 는 transition 필요 여부에 따라 다르게 결정함\n     *    Case 2-1: withTransition === true\n     *    shouldShow -> onTransitionEnd -> shouldRender\n     *    onTransitionEnd handler 를 이용해 transition 이 끝난 다음 shouldRender 를 false 로 설정\n     *    Case 2-2: withTransition === false\n     *    shouldShow && shouldRender\n     *    transition 을 기다릴 필요가 없으므로 바로 shouldRender 를 false 로 설정\n     */\n    useEffect(() => {\n      if (show) {\n        if (shouldRender) {\n          window.requestAnimationFrame(() => setShouldShow(true))\n        } else {\n          window.requestAnimationFrame(() => setShouldRender(true))\n        }\n      }\n\n      if (!show) {\n        window.requestAnimationFrame(() => setShouldShow(false))\n\n        if (!withTransition) {\n          window.requestAnimationFrame(() => setShouldRender(false))\n        }\n      }\n    }, [show, withTransition, shouldRender, shouldShow, window])\n\n    const themeName = useThemeName()\n\n    if (!shouldRender) {\n      return null\n    }\n\n    const Content = (\n      <ThemeProvider themeName={themeName}>\n        <div\n          className={classNames(\n            styles.Overlay,\n            getZIndexClassName(zIndex),\n            !shouldShow && styles.hidden,\n            withTransition && styles.transition,\n            className\n          )}\n          style={{\n            ...style,\n            ...getOverlayStyle({\n              containerRect: containerRect.current,\n              targetRect: targetRect.current,\n              overlay: overlayRef.current,\n              position,\n              marginX,\n              marginY,\n              keepInContainer,\n              show: shouldShow,\n            }),\n          }}\n          ref={mergedRef}\n          data-testid={OVERLAY_TEST_ID}\n          onTransitionEnd={handleTransitionEnd}\n          {...rest}\n        >\n          {children}\n        </div>\n      </ThemeProvider>\n    )\n\n    return ReactDOM.createPortal(\n      hasContainer ? (\n        Content\n      ) : (\n        <div\n          style={containerStyle}\n          className={classNames(\n            styles.OverlayContainer,\n            !show && styles.hidden,\n            containerClassName\n          )}\n          ref={containerRef}\n          data-testid={CONTAINER_TEST_ID}\n        >\n          <div className={styles.OverlayWrapper}>{Content}</div>\n        </div>\n      ),\n      container\n    )\n  }\n)\n"],"names":["CONTAINER_TEST_ID","OVERLAY_TEST_ID","ESCAPE_KEY","Overlay","forwardRef","children","style","className","show","container","givenContainer","target","position","marginX","marginY","keepInContainer","withTransition","enableClickOutside","containerStyle","containerClassName","onHide","onTransitionEnd","zIndex","rest","forwardedRef","_ref","window","document","rootElement","useWindow","shouldRender","setShouldRender","useState","shouldShow","setShouldShow","containerRect","useRef","targetRect","forceUpdate","useReducer","x","containerRef","overlayRef","mergedRef","useMergeRefs","modalContainer","useModalContainerContext","hasContainer","Boolean","handleOverlayForceUpdate","useCallback","handleContainerRect","width","containerWidth","height","containerHeight","top","containerTop","left","containerLeft","getBoundingClientRect","current","scrollTop","scrollLeft","useIsomorphicLayoutEffect","initContainerRect","handleTargetRect","targetWidth","targetHeight","targetTop","targetLeft","clientTop","clientLeft","initTargetRect","handleTransitionEnd","event","handleBlockMouseWheel","stopPropagation","handleHideOverlay","closest","styles","handleKeydown","key","useEventHandler","useEffect","requestAnimationFrame","themeName","useThemeName","Content","_jsx","ThemeProvider","classNames","getZIndexClassName","hidden","transition","getOverlayStyle","overlay","ref","ReactDOM","createPortal","OverlayContainer","OverlayWrapper"],"mappings":"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"}