@atlaskit/popup
Version:
A popup displays brief content in an overlay.
205 lines (202 loc) • 8.88 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _typeof = require("@babel/runtime/helpers/typeof");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.PopupTrigger = exports.PopupContent = exports.Popup = void 0;
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
var _react = _interopRequireWildcard(require("react"));
var _tinyInvariant = _interopRequireDefault(require("tiny-invariant"));
var _noop = _interopRequireDefault(require("@atlaskit/ds-lib/noop"));
var _useId = require("@atlaskit/ds-lib/use-id");
var _layering = require("@atlaskit/layering");
var _openLayerObserver = require("@atlaskit/layering/experimental/open-layer-observer");
var _popper = require("@atlaskit/popper");
var _portal = _interopRequireDefault(require("@atlaskit/portal"));
var _popperWrapper = _interopRequireDefault(require("../popper-wrapper"));
var _useAppearance = require("../use-appearance");
var _useGetMemoizedMergedTriggerRef = require("../use-get-memoized-merged-trigger-ref");
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
var IsOpenContext = /*#__PURE__*/(0, _react.createContext)(false);
var IdContext = /*#__PURE__*/(0, _react.createContext)(undefined);
var TriggerRefContext = /*#__PURE__*/(0, _react.createContext)(null);
var SetTriggerRefContext = /*#__PURE__*/(0, _react.createContext)(_noop.default);
var EnsureIsInsidePopupContext = /*#__PURE__*/(0, _react.createContext)(false);
// Used to ensure popup sub-components are used within a Popup
// and provide a useful error message if not.
var useEnsureIsInsidePopup = function useEnsureIsInsidePopup() {
var context = (0, _react.useContext)(EnsureIsInsidePopupContext);
(0, _tinyInvariant.default)(context, 'PopupTrigger and PopupContent components must be used within a Popup');
};
/**
* __Popup__
*
* Popup is a composable component that provides the context for the trigger and content components.
*
* Usage example:
* ```jsx
* <Popup>
* <PopupTrigger>
* {(props) => (
* <button type="button" {...props}>Click me</button>
* )}
* </PopupTrigger>
* <PopupContent>
* {(props) => <div>Hello world</div>}
* </PopupContent>
* </Popup>
* ```
*/
var Popup = exports.Popup = function Popup(_ref) {
var children = _ref.children,
providedId = _ref.id,
_ref$isOpen = _ref.isOpen,
isOpen = _ref$isOpen === void 0 ? false : _ref$isOpen;
var _useState = (0, _react.useState)(null),
_useState2 = (0, _slicedToArray2.default)(_useState, 2),
triggerRef = _useState2[0],
setTriggerRef = _useState2[1];
var generatedId = (0, _useId.useId)();
var id = providedId || generatedId;
return /*#__PURE__*/_react.default.createElement(EnsureIsInsidePopupContext.Provider, {
value: true
}, /*#__PURE__*/_react.default.createElement(IdContext.Provider, {
value: id
}, /*#__PURE__*/_react.default.createElement(TriggerRefContext.Provider, {
value: triggerRef
}, /*#__PURE__*/_react.default.createElement(SetTriggerRefContext.Provider, {
value: setTriggerRef
}, /*#__PURE__*/_react.default.createElement(IsOpenContext.Provider, {
value: isOpen
}, /*#__PURE__*/_react.default.createElement(_popper.Manager, null, children))))));
};
/**
* __Popup trigger__
*
* Popup trigger is the component that renders the trigger for the popup.
*
* It must be a child of the Popup component.
*/
var PopupTrigger = exports.PopupTrigger = function PopupTrigger(_ref2) {
var children = _ref2.children;
useEnsureIsInsidePopup();
var isOpen = (0, _react.useContext)(IsOpenContext);
var id = (0, _react.useContext)(IdContext);
var setTriggerRef = (0, _react.useContext)(SetTriggerRefContext);
var getMergedTriggerRef = (0, _useGetMemoizedMergedTriggerRef.useGetMemoizedMergedTriggerRef)();
return /*#__PURE__*/_react.default.createElement(_popper.Reference, null, function (_ref3) {
var ref = _ref3.ref;
return children({
ref: getMergedTriggerRef(ref, setTriggerRef, isOpen),
'aria-controls': id,
'aria-expanded': isOpen,
'aria-haspopup': true
});
});
};
var defaultLayer = 400;
/**
* Disables popper.js GPU acceleration for this popup.
* This means only positioning will be used, without any transforms.
*
* Performance will be degraded if the popup is expected to move.
*/
var shouldDisableGpuAccelerationModifiers = [{
name: 'computeStyles',
options: {
gpuAcceleration: false
}
}];
/**
* __Popup content__
*
* Popup content is the component that renders the content of the popup.
*
* It must be a child of the Popup component.
*/
var PopupContent = exports.PopupContent = function PopupContent(_ref4) {
var xcss = _ref4.xcss,
_ref4$appearance = _ref4.appearance,
inAppearance = _ref4$appearance === void 0 ? 'default' : _ref4$appearance,
children = _ref4.children,
boundary = _ref4.boundary,
offset = _ref4.offset,
strategy = _ref4.strategy,
onClose = _ref4.onClose,
testId = _ref4.testId,
_ref4$rootBoundary = _ref4.rootBoundary,
rootBoundary = _ref4$rootBoundary === void 0 ? 'viewport' : _ref4$rootBoundary,
_ref4$shouldFlip = _ref4.shouldFlip,
shouldFlip = _ref4$shouldFlip === void 0 ? true : _ref4$shouldFlip,
_ref4$placement = _ref4.placement,
placement = _ref4$placement === void 0 ? 'auto' : _ref4$placement,
fallbackPlacements = _ref4.fallbackPlacements,
popupComponent = _ref4.popupComponent,
_ref4$autoFocus = _ref4.autoFocus,
autoFocus = _ref4$autoFocus === void 0 ? true : _ref4$autoFocus,
_ref4$zIndex = _ref4.zIndex,
zIndex = _ref4$zIndex === void 0 ? defaultLayer : _ref4$zIndex,
_ref4$shouldUseCaptur = _ref4.shouldUseCaptureOnOutsideClick,
shouldUseCaptureOnOutsideClick = _ref4$shouldUseCaptur === void 0 ? false : _ref4$shouldUseCaptur,
inShouldRenderToParent = _ref4.shouldRenderToParent,
_ref4$shouldDisableFo = _ref4.shouldDisableFocusLock,
shouldDisableFocusLock = _ref4$shouldDisableFo === void 0 ? false : _ref4$shouldDisableFo,
shouldFitContainer = _ref4.shouldFitContainer,
shouldFitViewport = _ref4.shouldFitViewport,
_ref4$shouldDisableGp = _ref4.shouldDisableGpuAcceleration,
shouldDisableGpuAcceleration = _ref4$shouldDisableGp === void 0 ? false : _ref4$shouldDisableGp;
useEnsureIsInsidePopup();
var isOpen = (0, _react.useContext)(IsOpenContext);
var id = (0, _react.useContext)(IdContext);
var triggerRef = (0, _react.useContext)(TriggerRefContext);
var _usePopupAppearance = (0, _useAppearance.usePopupAppearance)({
appearance: inAppearance,
shouldRenderToParent: inShouldRenderToParent
}),
appearance = _usePopupAppearance.appearance,
shouldRenderToParent = _usePopupAppearance.shouldRenderToParent;
var handleOpenLayerObserverCloseSignal = (0, _react.useCallback)(function () {
onClose === null || onClose === void 0 || onClose(null);
}, [onClose]);
(0, _openLayerObserver.useNotifyOpenLayerObserver)({
isOpen: isOpen,
onClose: handleOpenLayerObserverCloseSignal
});
if (!isOpen) {
return null;
}
var popperWrapper = /*#__PURE__*/_react.default.createElement(_layering.Layering, {
isDisabled: false
}, /*#__PURE__*/_react.default.createElement(_popperWrapper.default, {
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,
shouldRenderToParent: shouldRenderToParent,
shouldDisableFocusLock: shouldDisableFocusLock,
triggerRef: triggerRef,
strategy: strategy,
shouldFitViewport: shouldFitViewport,
modifiers: shouldDisableGpuAcceleration ? shouldDisableGpuAccelerationModifiers : undefined
}));
if (shouldRenderToParent) {
return popperWrapper;
}
return /*#__PURE__*/_react.default.createElement(_portal.default, {
zIndex: zIndex
}, popperWrapper);
};