UNPKG

@atlaskit/inline-dialog

Version:

An inline dialog is a pop-up container for small amounts of information. It can also contain controls.

199 lines (190 loc) 8.24 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _typeof = require("@babel/runtime/helpers/typeof"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _react = _interopRequireWildcard(require("react")); var _bindEventListener = require("bind-event-listener"); var _analyticsNext = require("@atlaskit/analytics-next"); var _noop = _interopRequireDefault(require("@atlaskit/ds-lib/noop")); var _layering = require("@atlaskit/layering"); var _popper = require("@atlaskit/popper"); var _container = require("./styled/container"); 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 _checkIsChildOfPortal = function checkIsChildOfPortal(node) { if (!node) { return false; } return node.classList && node.classList.contains('atlaskit-portal-container') || _checkIsChildOfPortal(node.parentElement); }; // Close manager for layering var CloseManager = function CloseManager(_ref) { var handleEscapeClose = _ref.handleEscapeClose, handleClick = _ref.handleClick; (0, _layering.useCloseOnEscapePress)({ onClose: handleEscapeClose }); var _useLayering = (0, _layering.useLayering)(), isLayerDisabled = _useLayering.isLayerDisabled; (0, _react.useEffect)(function () { return (0, _bindEventListener.bind)(window, { type: 'click', listener: function listener(e) { if (isLayerDisabled()) { return; } handleClick(e); }, options: { capture: true } }); }, [handleClick, isLayerDisabled]); // only create a dummy component for using ths hook in class component return /*#__PURE__*/_react.default.createElement("span", null); }; var InlineDialog = /*#__PURE__*/(0, _react.memo)(function InlineDialog(_ref2) { var _ref2$isOpen = _ref2.isOpen, isOpen = _ref2$isOpen === void 0 ? false : _ref2$isOpen, _ref2$onContentBlur = _ref2.onContentBlur, onContentBlur = _ref2$onContentBlur === void 0 ? _noop.default : _ref2$onContentBlur, _ref2$onContentClick = _ref2.onContentClick, onContentClick = _ref2$onContentClick === void 0 ? _noop.default : _ref2$onContentClick, _ref2$onContentFocus = _ref2.onContentFocus, onContentFocus = _ref2$onContentFocus === void 0 ? _noop.default : _ref2$onContentFocus, _ref2$onClose = _ref2.onClose, providedOnClose = _ref2$onClose === void 0 ? _noop.default : _ref2$onClose, _ref2$placement = _ref2.placement, placement = _ref2$placement === void 0 ? 'bottom-start' : _ref2$placement, _ref2$strategy = _ref2.strategy, strategy = _ref2$strategy === void 0 ? 'fixed' : _ref2$strategy, testId = _ref2.testId, content = _ref2.content, children = _ref2.children, fallbackPlacements = _ref2.fallbackPlacements; var containerRef = (0, _react.useRef)(null); var triggerRef = (0, _react.useRef)(null); var onClose = (0, _analyticsNext.usePlatformLeafEventHandler)({ fn: function fn(event) { return providedOnClose(event); }, action: 'closed', componentName: 'inlineDialog', packageName: "@atlaskit/inline-dialog", packageVersion: "0.0.0-development" }); // we put this into a ref to avoid handleCloseRequest having this as a dependency var onCloseRef = (0, _react.useRef)(onClose); (0, _react.useEffect)(function () { onCloseRef.current = onClose; }); var handleCloseRequest = (0, _react.useCallback)(function (event) { var target = event.target; // checks for when target is not HTMLElement if (!(target instanceof HTMLElement)) { return; } // TODO: This is to handle the case where the target is no longer in the DOM. // This happens with react-select in datetime picker. There might be other // edge cases for this. if (!document.body.contains(target)) { return; } if (isOpen) { var _onCloseRef$current; (_onCloseRef$current = onCloseRef.current) === null || _onCloseRef$current === void 0 || _onCloseRef$current.call(onCloseRef, { isOpen: false, event: event }); return; } // handles the case where inline dialog opens portalled elements such as modal if (_checkIsChildOfPortal(target)) { return; } // call onClose if the click originated from outside the dialog if (containerRef.current && !containerRef.current.contains(target)) { var _onCloseRef$current2; (_onCloseRef$current2 = onCloseRef.current) === null || _onCloseRef$current2 === void 0 || _onCloseRef$current2.call(onCloseRef, { isOpen: false, event: event }); } }, [isOpen]); var handleClick = (0, _react.useCallback)(function (event) { var _containerRef$current; // exit if we click outside but on the trigger — it can handle the clicks itself if (triggerRef.current && triggerRef.current.contains(event.target)) { return; } if ((_containerRef$current = containerRef.current) !== null && _containerRef$current !== void 0 && _containerRef$current.contains(event.target)) { return; } handleCloseRequest(event); }, [handleCloseRequest, containerRef, triggerRef]); /** * Auto-flip is enabled by default in `@atlaskit/popper` and * the `InlineDialog` API does not allow disabling it. * * We only need to override it if there are `fallbackPlacements` specified. */ var modifiers = (0, _react.useMemo)(function () { return fallbackPlacements ? [{ name: 'flip', options: { fallbackPlacements: fallbackPlacements } }] : []; }, [fallbackPlacements]); var popper = isOpen ? /*#__PURE__*/_react.default.createElement(_popper.Popper, { placement: placement, strategy: strategy, modifiers: modifiers }, function (_ref3) { var _ref4 = _ref3.ref, style = _ref3.style; return /*#__PURE__*/_react.default.createElement(_container.Container, { onBlur: onContentBlur, onFocus: onContentFocus, onClick: onContentClick, ref: function ref(node) { if (node) { containerRef.current = node; if (typeof _ref4 === 'function') { _ref4(node); } else { _ref4.current = node; } } } // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766 , style: style, testId: testId }, typeof content === 'function' ? content() : content); }) : null; return /*#__PURE__*/_react.default.createElement(_popper.Manager, null, /*#__PURE__*/_react.default.createElement(_popper.Reference, null, function (_ref5) { var _ref6 = _ref5.ref; return /*#__PURE__*/_react.default.createElement("div", { ref: function ref(node) { // Resolve to the first element child of the div in `children` var firstElementChild = (node === null || node === void 0 ? void 0 : node.firstElementChild) || null; triggerRef.current = firstElementChild; if (typeof _ref6 === 'function') { _ref6(firstElementChild); } else { _ref6.current = firstElementChild; } } }, /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, children)); }), isOpen ? /*#__PURE__*/_react.default.createElement(_layering.Layering, { isDisabled: false }, popper, /*#__PURE__*/_react.default.createElement(CloseManager, { handleEscapeClose: handleCloseRequest, handleClick: handleClick })) : popper); }); // eslint-disable-next-line @repo/internal/react/require-jsdoc var _default = exports.default = InlineDialog;