UNPKG

@atlaskit/popup

Version:

A popup displays brief content in an overlay.

154 lines (151 loc) • 6.21 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'; var defaultLayer = 400; var 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(_ref) { var xcss = _ref.xcss, _ref$appearance = _ref.appearance, inAppearance = _ref$appearance === void 0 ? 'default' : _ref$appearance, children = _ref.children, boundary = _ref.boundary, offset = _ref.offset, strategy = _ref.strategy, onClose = _ref.onClose, testId = _ref.testId, _ref$rootBoundary = _ref.rootBoundary, rootBoundary = _ref$rootBoundary === void 0 ? 'viewport' : _ref$rootBoundary, _ref$shouldFlip = _ref.shouldFlip, shouldFlip = _ref$shouldFlip === void 0 ? true : _ref$shouldFlip, _ref$placement = _ref.placement, placement = _ref$placement === void 0 ? 'auto' : _ref$placement, fallbackPlacements = _ref.fallbackPlacements, popupComponent = _ref.popupComponent, _ref$autoFocus = _ref.autoFocus, autoFocus = _ref$autoFocus === void 0 ? true : _ref$autoFocus, _ref$zIndex = _ref.zIndex, zIndex = _ref$zIndex === void 0 ? defaultLayer : _ref$zIndex, _ref$shouldUseCapture = _ref.shouldUseCaptureOnOutsideClick, shouldUseCaptureOnOutsideClick = _ref$shouldUseCapture === void 0 ? false : _ref$shouldUseCapture, shouldIgnoreCloseEvent = _ref.shouldIgnoreCloseEvent, inShouldRenderToParent = _ref.shouldRenderToParent, _ref$shouldDisableFoc = _ref.shouldDisableFocusLock, shouldDisableFocusLock = _ref$shouldDisableFoc === void 0 ? false : _ref$shouldDisableFoc, shouldFitContainer = _ref.shouldFitContainer, shouldFitViewport = _ref.shouldFitViewport, _ref$shouldDisableGpu = _ref.shouldDisableGpuAcceleration, shouldDisableGpuAcceleration = _ref$shouldDisableGpu === void 0 ? false : _ref$shouldDisableGpu, role = _ref.role, titleId = _ref.titleId, isOpen = _ref.isOpen, id = _ref.id; var triggerRef = useContext(TriggerRefContext); var _usePopupAppearance = usePopupAppearance({ appearance: inAppearance, shouldRenderToParent: inShouldRenderToParent }), appearance = _usePopupAppearance.appearance, shouldRenderToParent = _usePopupAppearance.shouldRenderToParent; var handleOpenLayerObserverCloseSignal = useCallback(function () { onClose === null || onClose === void 0 || onClose(null); }, [onClose]); useNotifyOpenLayerObserver({ isOpen: isOpen, onClose: handleOpenLayerObserverCloseSignal, type: 'popup' }); if (!isOpen) { return null; } var 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(); var isOpen = useContext(IsOpenContext); var 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 })); }