@helpscout/hsds-react
Version:
React component library for Help Scout's Design System
316 lines (254 loc) • 11.5 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
exports.__esModule = true;
exports.default = exports.TooltipContext = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _objectWithoutPropertiesLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutPropertiesLoose"));
var _react = _interopRequireWildcard(require("react"));
var _propTypes = _interopRequireDefault(require("prop-types"));
var _headless = _interopRequireDefault(require("@tippyjs/react/headless"));
var _lodash = _interopRequireDefault(require("lodash.isfunction"));
var _getValidProps = _interopRequireDefault(require("@helpscout/react-utils/dist/getValidProps"));
var _classnames = _interopRequireDefault(require("classnames"));
var _Tooltip = require("./Tooltip.css");
var _KeyboardBadge = _interopRequireDefault(require("../KeyboardBadge"));
var _jsxRuntime = require("react/jsx-runtime");
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
var TooltipContext = /*#__PURE__*/(0, _react.createContext)({});
exports.TooltipContext = TooltipContext;
var getClassName = function getClassName(className) {
return (0, _classnames.default)('c-Tooltip', className);
};
var hideOnEsc = {
name: 'hideOnEsc',
defaultValue: true,
fn: function fn(_ref) {
var hide = _ref.hide;
function onKeyDown(event) {
if (event.keyCode === 27) {
hide();
}
}
return {
onShow: function onShow() {
document.addEventListener('keydown', onKeyDown);
},
onHide: function onHide() {
document.removeEventListener('keydown', onKeyDown);
}
};
}
};
var Tooltip = function Tooltip(_ref2) {
var animationDelay = _ref2.animationDelay,
animationDuration = _ref2.animationDuration,
arrowSize = _ref2.arrowSize,
badge = _ref2.badge,
children = _ref2.children,
className = _ref2.className,
closeOnContentClick = _ref2.closeOnContentClick,
closeOnEscPress = _ref2.closeOnEscPress,
display = _ref2.display,
dataCy = _ref2['data-cy'],
_ref2$getTippyInstanc = _ref2.getTippyInstance,
getTippyInstance = _ref2$getTippyInstanc === void 0 ? function () {} : _ref2$getTippyInstanc,
innerRef = _ref2.innerRef,
isOpen = _ref2.isOpen,
minWidth = _ref2.minWidth,
maxWidth = _ref2.maxWidth,
placement = _ref2.placement,
renderProp = _ref2.render,
renderContent = _ref2.renderContent,
title = _ref2.title,
triggerOn = _ref2.triggerOn,
withTriggerWrapper = _ref2.withTriggerWrapper,
_ref2$withArrow = _ref2.withArrow,
withArrow = _ref2$withArrow === void 0 ? true : _ref2$withArrow,
zIndexProp = _ref2.zIndex,
rest = (0, _objectWithoutPropertiesLoose2.default)(_ref2, ["animationDelay", "animationDuration", "arrowSize", "badge", "children", "className", "closeOnContentClick", "closeOnEscPress", "display", "data-cy", "getTippyInstance", "innerRef", "isOpen", "minWidth", "maxWidth", "placement", "render", "renderContent", "title", "triggerOn", "withTriggerWrapper", "withArrow", "zIndex"]);
var _ref3 = (0, _react.useContext)(TooltipContext) || {},
_ref3$zIndex = _ref3.zIndex,
zIndex = _ref3$zIndex === void 0 ? zIndexProp : _ref3$zIndex,
animationDurationContext = _ref3.animationDuration;
var _useState = (0, _react.useState)(animationDuration === 0),
isEntered = _useState[0],
setEntered = _useState[1];
var isMounted = (0, _react.useRef)(true);
(0, _react.useEffect)(function () {
return function () {
isMounted.current = false;
};
}, []);
var hasRenderContent = renderContent && (0, _lodash.default)(renderContent);
var hasRender = renderProp && (0, _lodash.default)(renderProp);
var shouldRenderTooltip = title || hasRenderContent || hasRender;
var hasKeyboardBadge = badge && !hasRender;
var duration = animationDurationContext ? animationDurationContext : animationDuration;
var tooltipProps = {
className: getClassName(className),
arrowSize: arrowSize,
animationDuration: duration,
'data-entered': isEntered,
maxWidth: maxWidth,
minWidth: minWidth,
ref: innerRef,
tabIndex: '-1'
};
var renderTooltip = function renderTooltip(_ref4) {
var className = _ref4.className,
props = (0, _objectWithoutPropertiesLoose2.default)(_ref4, ["className"]);
var titleContent = null;
if (typeof title === 'string') {
titleContent = /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
className: "c-Tooltip__title",
dangerouslySetInnerHTML: {
__html: title
}
});
} else {
titleContent = title;
}
var tooltipClassnames = (0, _classnames.default)(className, hasKeyboardBadge && 'with-badge', typeof title === 'string' && 'with-plain-title');
var toolTipComponent = /*#__PURE__*/(0, _jsxRuntime.jsx)(_Tooltip.TooltipAnimationUI, {
children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_Tooltip.TooltipUI, (0, _extends2.default)({
className: tooltipClassnames
}, props, {
children: [renderContent ? renderContent() : titleContent, hasKeyboardBadge ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_KeyboardBadge.default, {
value: badge
}) : null, withArrow && /*#__PURE__*/(0, _jsxRuntime.jsx)(_Tooltip.ArrowUI, {
className: "c-Tooltip_ArrowUI",
arrowSize: arrowSize,
"data-popper-arrow": true
})]
}))
});
return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
className: "hsds-react hsds-beacon",
children: toolTipComponent
});
};
var render = function render(attrs) {
var props = (0, _extends2.default)({}, tooltipProps, attrs);
if (renderProp) return renderProp(props);
return renderTooltip(props);
};
var onShow = function onShow() {
setTimeout(function () {
if (isMounted.current) {
setEntered(true);
}
}, animationDelay);
};
var onCreate = function onCreate(instance) {
getTippyInstance && getTippyInstance(instance);
};
var onHide = function onHide() {
setEntered(false);
};
var extraProps = {};
if (zIndex) {
extraProps.zIndex = zIndex;
}
if (!closeOnContentClick) {
extraProps.interactive = true;
extraProps.interactiveBorder = 20;
}
var plugins = [];
if (closeOnEscPress) {
plugins.push(hideOnEsc);
}
var defaultTippyProps = {
onCreate: onCreate,
onHide: onHide,
onShow: onShow,
placement: placement,
plugins: plugins,
render: render,
maxWidth: maxWidth
}; // only set those props if the component is not in a controlled way
if (!rest.hasOwnProperty('visible')) {
defaultTippyProps.showOnCreate = isOpen;
defaultTippyProps.trigger = triggerOn === 'hover' ? 'mouseenter' : triggerOn;
}
var tippyProps = (0, _extends2.default)({}, defaultTippyProps, rest, extraProps);
if (!shouldRenderTooltip) {
return children ? /*#__PURE__*/(0, _jsxRuntime.jsx)("span", (0, _extends2.default)({}, (0, _getValidProps.default)(rest), {
className: getClassName(className),
children: children
})) : null;
}
var triggerComponent;
if (!withTriggerWrapper && /*#__PURE__*/_react.default.isValidElement(children) && _react.default.Children.count(children) === 1) {
var component = _react.default.Children.only(children);
var triggerProps = {
className: (0, _classnames.default)('TooltipTrigger', component.props.className),
'data-cy': component.props['data-cy'] || dataCy,
tabIndex: component.props['tabIndex'] || 0,
'aria-expanded': null // let tippy handle that prop
};
triggerComponent = /*#__PURE__*/_react.default.cloneElement(component, triggerProps);
} else {
triggerComponent = /*#__PURE__*/(0, _jsxRuntime.jsx)(_Tooltip.TooltipTriggerUI, {
tabIndex: "0",
display: display,
"data-cy": dataCy,
className: "TooltipTrigger",
children: children
});
}
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_headless.default, (0, _extends2.default)({}, tippyProps, {
children: triggerComponent
}));
};
Tooltip.defaultProps = {
animationDelay: 0,
animationDuration: 200,
arrowSize: 12,
closeOnEscPress: true,
'data-cy': 'Tooltip',
display: null,
isOpen: false,
placement: 'top',
triggerOn: 'mouseenter focus',
withTriggerWrapper: true
};
Tooltip.propTypes = {
animationDelay: _propTypes.default.number,
animationDuration: _propTypes.default.number,
/** Size of the Arrow in pixels */
arrowSize: _propTypes.default.oneOfType([_propTypes.default.number, _propTypes.default.string]),
/** Render the value within a KeyboardBadge component after the title. Will be render only when using the title prop */
badge: _propTypes.default.string,
/** Custom class names to be added to the component. */
className: _propTypes.default.string,
/** Whether to allow closing the tooltip on pressing ESC */
closeOnEscPress: _propTypes.default.bool,
/** Data attr for Cypress tests. */
'data-cy': _propTypes.default.string,
/** Apply custom css rule `display` */
display: _propTypes.default.string,
getTippyInstance: _propTypes.default.any,
/** Determine if the tooltip is open via a prop */
isOpen: _propTypes.default.bool,
/** Max width for the component. */
maxWidth: _propTypes.default.oneOfType([_propTypes.default.number, _propTypes.default.string]),
/** Min width for the component. */
minWidth: _propTypes.default.oneOfType([_propTypes.default.number, _propTypes.default.string]),
/** Renders a component within the Tooltip. Is prioritized over `title` */
renderContent: _propTypes.default.func,
/** Where to place the Tooltip. */
placement: _propTypes.default.string,
/** Text to display within the Tooltip. */
title: _propTypes.default.oneOfType([_propTypes.default.object, _propTypes.default.string]),
/** Determines how to engage the component. */
triggerOn: _propTypes.default.string,
/** Set the tooltip to be controlled externally */
visible: _propTypes.default.bool,
/** Wrap the trigger with a span */
withTriggerWrapper: _propTypes.default.bool,
/** Whether to render the arrow */
withArrow: _propTypes.default.bool
};
var _default = Tooltip;
exports.default = _default;