@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
JavaScript
"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;