UNPKG

@mskcc/carbon-react

Version:

Carbon react components for the MSKCC DSM

181 lines (173 loc) 6.45 kB
/** * MSKCC 2021, 2024 */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _rollupPluginBabelHelpers = require('../../_virtual/_rollupPluginBabelHelpers.js'); var cx = require('classnames'); var PropTypes = require('prop-types'); var React = require('react'); var index = require('../Popover/index.js'); var useDelayedState = require('../../internal/useDelayedState.js'); var useId = require('../../internal/useId.js'); var useNoInteractiveChildren = require('../../internal/useNoInteractiveChildren.js'); var usePrefix = require('../../internal/usePrefix.js'); var match = require('../../internal/keyboard/match.js'); var keys = require('../../internal/keyboard/keys.js'); function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } var cx__default = /*#__PURE__*/_interopDefaultLegacy(cx); var PropTypes__default = /*#__PURE__*/_interopDefaultLegacy(PropTypes); var React__default = /*#__PURE__*/_interopDefaultLegacy(React); function Tooltip(_ref) { let { align = 'top', className: customClassName, children, label, description, enterDelayMs = 100, leaveDelayMs = 300, defaultOpen = false, closeOnActivation = false, disabled = false, ...rest } = _ref; const containerRef = React.useRef(null); const tooltipRef = React.useRef(null); const [open, setOpen] = useDelayedState.useDelayedState(defaultOpen); const id = useId.useId('tooltip'); const prefix = usePrefix.usePrefix(); const child = React__default["default"].Children.only(children); const triggerProps = disabled ? {} : { onFocus: () => setOpen(true), onBlur: () => setOpen(false), onClick: () => closeOnActivation && setOpen(false), onMouseEnter: onMouseEnter }; function getChildEventHandlers(childProps) { if (disabled) { return {}; } const eventHandlerFunctions = ['onFocus', 'onBlur', 'onClick', 'onMouseEnter']; const eventHandlers = {}; eventHandlerFunctions.forEach(functionName => { eventHandlers[functionName] = evt => { triggerProps[functionName](); if (childProps?.[functionName]) { childProps?.[functionName](evt); } }; }); return eventHandlers; } if (label) { triggerProps['aria-labelledby'] = id; } else { triggerProps['aria-describedby'] = id; } function onKeyDown(event) { if (disabled) { return; } if (open && match.match(event, keys.Escape)) { event.stopPropagation(); setOpen(false); } if (open && closeOnActivation && (match.match(event, keys.Enter) || match.match(event, keys.Space))) { setOpen(false); } } function onMouseEnter() { if (!disabled) { setOpen(true, enterDelayMs); } } function onMouseLeave() { if (!disabled) { setOpen(false, leaveDelayMs); } } useNoInteractiveChildren.useNoInteractiveChildren(tooltipRef, 'The Tooltip component must have no interactive content rendered by the' + '`label` or `description` prop'); React.useEffect(() => { if (containerRef !== null && containerRef.current) { const interactiveContent = useNoInteractiveChildren.getInteractiveContent(containerRef.current); if (!interactiveContent) { setOpen(false); } } }); return /*#__PURE__*/React__default["default"].createElement(index.Popover, _rollupPluginBabelHelpers["extends"]({}, rest, { align: align, className: cx__default["default"](`${prefix}--tooltip`, customClassName), dropShadow: false, highContrast: true, onKeyDown: disabled ? undefined : onKeyDown, onMouseLeave: disabled ? undefined : onMouseLeave, open: disabled ? false : open, ref: containerRef }), /*#__PURE__*/React__default["default"].createElement("div", { className: `${prefix}--tooltip-trigger__wrapper` }, child !== undefined ? /*#__PURE__*/React__default["default"].cloneElement(child, { ...triggerProps, ...getChildEventHandlers(child.props) }) : null), /*#__PURE__*/React__default["default"].createElement(index.PopoverContent, { "aria-hidden": "true", className: `${prefix}--tooltip-content`, id: id, ref: tooltipRef, role: "tooltip" }, label || description)); } Tooltip.propTypes = { /** * Specify how the trigger should align with the tooltip */ align: PropTypes__default["default"].oneOf(['top', 'top-left', 'top-right', 'bottom', 'bottom-left', 'bottom-right', 'left', 'left-bottom', 'left-top', 'right', 'right-bottom', 'right-top']), /** * Pass in the child to which the tooltip will be applied */ children: PropTypes__default["default"].node, /** * Specify an optional className to be applied to the container node */ className: PropTypes__default["default"].string, /** * Determines wether the tooltip should close when inner content is activated (click, Enter or Space) */ closeOnActivation: PropTypes__default["default"].bool, /** * Specify whether the tooltip should be open when it first renders */ defaultOpen: PropTypes__default["default"].bool, /** * Provide the description to be rendered inside of the Tooltip. The * description will use `aria-describedby` and will describe the child node * in addition to the text rendered inside of the child. This means that if you * have text in the child node, that it will be announced alongside the * description to the screen reader. * * Note: if label and description are both provided, label will be used and * description will not be used */ description: PropTypes__default["default"].node, disabled: PropTypes__default["default"].bool, /** * Specify the duration in milliseconds to delay before displaying the tooltip */ enterDelayMs: PropTypes__default["default"].number, /** * Provide the label to be rendered inside of the Tooltip. The label will use * `aria-labelledby` and will fully describe the child node that is provided. * This means that if you have text in the child node, that it will not be * announced to the screen reader. * * Note: if label and description are both provided, description will not be * used */ label: PropTypes__default["default"].node, /** * Specify the duration in milliseconds to delay before hiding the tooltip */ leaveDelayMs: PropTypes__default["default"].number }; exports.Tooltip = Tooltip;