UNPKG

@atlaskit/popup

Version:

A popup displays brief content in an overlay.

147 lines (144 loc) • 4.93 kB
import _extends from "@babel/runtime/helpers/extends"; import React, { useCallback, useContext } from 'react'; import { Layering } from '@atlaskit/layering/layering'; import { useNotifyOpenLayerObserver } from '@atlaskit/layering/use-notify-open-layer-observer'; import { fg } from '@atlaskit/platform-feature-flags/fg'; import Portal from '@atlaskit/portal/portal'; import PopperWrapper from '../popper-wrapper'; import { usePopupAppearance } from '../use-appearance'; import { IdContext } from './id-context'; import { IsOpenContext } from './is-open-context'; import { PopupContentTopLayer } from './popup-content-top-layer'; import { TriggerRefContext } from './trigger-ref-context'; import { useEnsureIsInsidePopup } from './use-ensure-is-inside-popup'; const defaultLayer = 400; const shouldDisableGpuAccelerationModifiers = [{ name: 'computeStyles', options: { gpuAcceleration: false } }]; /** * Legacy (Popper + Portal) implementation of the compositional PopupContent. * * Renders when the `platform-dst-top-layer` flag is off. This component owns * the open layer observer registration, which on the top-layer path is handled * by the `Popover` primitive inside `PopupContentTopLayer` instead. */ function PopupContentLegacy({ xcss, appearance: inAppearance = 'default', children, boundary, offset, strategy, onClose, testId, rootBoundary = 'viewport', shouldFlip = true, placement = 'auto', fallbackPlacements, popupComponent, autoFocus = true, zIndex = defaultLayer, shouldUseCaptureOnOutsideClick = false, shouldIgnoreCloseEvent, shouldRenderToParent: inShouldRenderToParent, shouldDisableFocusLock = false, shouldFitContainer, shouldFitViewport, shouldDisableGpuAcceleration = false, role, titleId, isOpen, id }) { const triggerRef = useContext(TriggerRefContext); const { appearance, shouldRenderToParent } = usePopupAppearance({ appearance: inAppearance, shouldRenderToParent: inShouldRenderToParent }); const handleOpenLayerObserverCloseSignal = useCallback(() => { onClose === null || onClose === void 0 ? void 0 : onClose(null); }, [onClose]); useNotifyOpenLayerObserver({ isOpen, onClose: handleOpenLayerObserverCloseSignal, type: 'popup' }); if (!isOpen) { return null; } const popperWrapper = /*#__PURE__*/React.createElement(Layering, { isDisabled: false }, /*#__PURE__*/React.createElement(PopperWrapper, { xcss: xcss, appearance: appearance, content: children, isOpen: isOpen, placement: placement, fallbackPlacements: fallbackPlacements, boundary: boundary, rootBoundary: rootBoundary, shouldFlip: shouldFlip, offset: offset, popupComponent: popupComponent, id: id, testId: testId, onClose: onClose, autoFocus: autoFocus, shouldFitContainer: shouldFitContainer, shouldUseCaptureOnOutsideClick: shouldUseCaptureOnOutsideClick, shouldIgnoreCloseEvent: shouldIgnoreCloseEvent, shouldRenderToParent: shouldRenderToParent, shouldDisableFocusLock: shouldDisableFocusLock, triggerRef: triggerRef, strategy: strategy, shouldFitViewport: shouldFitViewport, modifiers: shouldDisableGpuAcceleration ? shouldDisableGpuAccelerationModifiers : undefined, role: role, titleId: titleId })); if (shouldRenderToParent) { return popperWrapper; } return /*#__PURE__*/React.createElement(Portal, { zIndex: zIndex }, popperWrapper); } /** * __Popup content__ * * Popup content is the component that renders the content of the popup. * * It must be a child of the Popup component. */ export function PopupContent(props) { useEnsureIsInsidePopup(); const isOpen = useContext(IsOpenContext); const id = useContext(IdContext); // Select the rendering implementation at the component boundary rather than // gating hooks inside a single component. Each implementation owns its own // hooks, so a runtime feature-flag change swaps component types (a clean // remount) instead of changing the hook order of a mounted component. // // Forwarding the full props onto the chosen implementation is intentional: // both implementations declare explicit prop types, so the forward is type // checked rather than an unbounded API. if (fg('platform-dst-top-layer')) { // The top-layer Popover registers with the open layer observer itself. // eslint-disable-next-line @repo/internal/react/no-unsafe-spread-props -- intentional forward to a typed implementation return /*#__PURE__*/React.createElement(PopupContentTopLayer, _extends({}, props, { isOpen: isOpen, id: id })); } // eslint-disable-next-line @repo/internal/react/no-unsafe-spread-props -- intentional forward to a typed implementation return /*#__PURE__*/React.createElement(PopupContentLegacy, _extends({}, props, { isOpen: isOpen, id: id })); }