@fluentui/react-northstar
Version:
A themable React component library.
256 lines (254 loc) • 10.4 kB
JavaScript
import _invoke from "lodash/invoke";
import { tooltipAsLabelBehavior } from '@fluentui/accessibility';
import { useAccessibility, useAutoControlled, useTelemetry, useFluentContext, useTriggerElement, useUnhandledProps, useOnIFrameFocus } from '@fluentui/react-bindings';
import { Ref } from '@fluentui/react-component-ref';
import * as customPropTypes from '@fluentui/react-proptypes';
import * as PropTypes from 'prop-types';
import * as React from 'react';
import { commonPropTypes, isFromKeyboard, setWhatInputSource, getOrGenerateIdFromShorthand, createShorthandFactory } from '../../utils';
import { ALIGNMENTS, POSITIONS, Popper, AUTOSIZES } from '../../utils/positioner';
import { PortalInner } from '../Portal/PortalInner';
import { TooltipContent } from './TooltipContent';
export var tooltipClassName = 'ui-tooltip';
/**
* A Tooltip displays additional non-modal information on top of its target element.
* Tooltip doesn't receive focus and cannot contain focusable elements.
*
* @accessibility
* Implements [ARIA Tooltip](https://www.w3.org/TR/wai-aria-practices-1.1/#tooltip) design pattern.
*/
export var Tooltip = /*#__PURE__*/function () {
var Tooltip = function Tooltip(props) {
var context = useFluentContext();
var _useTelemetry = useTelemetry(Tooltip.displayName, context.telemetry),
setStart = _useTelemetry.setStart,
setEnd = _useTelemetry.setEnd;
setStart();
var accessibility = props.accessibility,
align = props.align,
content = props.content,
flipBoundary = props.flipBoundary,
mountNode = props.mountNode,
mouseLeaveDelay = props.mouseLeaveDelay,
offset = props.offset,
overflowBoundary = props.overflowBoundary,
pointing = props.pointing,
popperRef = props.popperRef,
position = props.position,
positionFixed = props.positionFixed,
target = props.target,
trigger = props.trigger,
unstable_disableTether = props.unstable_disableTether,
unstable_pinned = props.unstable_pinned,
autoSize = props.autoSize,
subtle = props.subtle,
dismissOnContentMouseEnter = props.dismissOnContentMouseEnter,
mouseEnterDelay = props.mouseEnterDelay;
var _useAutoControlled = useAutoControlled({
defaultValue: props.defaultOpen,
value: props.open,
initialValue: false
}),
open = _useAutoControlled[0],
setOpen = _useAutoControlled[1];
var triggerElement = useTriggerElement(props);
var unhandledProps = useUnhandledProps(Tooltip.handledProps, props);
useOnIFrameFocus(open, context.target, function (e) {
setOpen(function (__) {
_invoke(props, 'onOpenChange', e, Object.assign({}, props, {
open: false
}));
return false;
});
});
var contentRef = React.useRef();
var pointerTargetRef = React.useRef();
var triggerRef = React.useRef();
var closeTimeoutId = React.useRef();
var openTimeoutId = React.useRef();
// TODO: Consider `getOrGenerateIdFromShorthand()` as hook and make it SSR safe
var contentId = React.useRef();
contentId.current = getOrGenerateIdFromShorthand('tooltip-content-', content, contentId.current);
var getA11Props = useAccessibility(accessibility, {
actionHandlers: {
close: function close(e) {
setTooltipOpen(false, e);
e.stopPropagation();
e.preventDefault();
}
},
mapPropsToBehavior: function mapPropsToBehavior() {
return {
'aria-describedby': props['aria-describedby'],
'aria-label': props['aria-label'],
'aria-labelledby': props['aria-labelledby'],
contentId: contentId.current,
triggerAriaLabel: trigger && trigger.props['aria-label'],
open: open
};
}
});
var getContentOverrideProps = function getContentOverrideProps(predefinedProps) {
return {
onMouseEnter: function onMouseEnter(e) {
if (!dismissOnContentMouseEnter) {
setTooltipOpen(true, e);
}
_invoke(predefinedProps, 'onMouseEnter', e);
},
onMouseLeave: function onMouseLeave(e) {
setTooltipOpen(false, e);
_invoke(predefinedProps, 'onMouseLeave', e);
}
};
};
var renderPopperChildren = function renderPopperChildren(popperProps) {
var tooltipContent = TooltipContent.create(content, {
defaultProps: function defaultProps() {
return getA11Props('tooltip', {
open: open,
placement: popperProps.placement,
pointing: pointing,
pointerRef: pointerTargetRef,
subtle: subtle
});
},
generateKey: false,
overrideProps: getContentOverrideProps
});
return tooltipContent ? /*#__PURE__*/React.createElement(Ref, {
innerRef: contentRef
}, tooltipContent) : null;
};
var shouldStayOpen = function shouldStayOpen(e) {
return _invoke(e, 'currentTarget.contains', e.relatedTarget) || _invoke(contentRef.current, 'contains', e.relatedTarget);
};
var trySetOpen = function trySetOpen(newValue, e) {
setOpen(newValue);
_invoke(props, 'onOpenChange', e, Object.assign({}, props, {
open: newValue
}));
};
var setTooltipOpen = function setTooltipOpen(newOpen, e) {
context.target.defaultView.clearTimeout(closeTimeoutId.current);
context.target.defaultView.clearTimeout(openTimeoutId.current);
if (newOpen) {
if (mouseEnterDelay !== 0) {
openTimeoutId.current = context.target.defaultView.setTimeout(function () {
trySetOpen(true, e);
}, mouseEnterDelay);
} else {
trySetOpen(true, e);
}
} else {
closeTimeoutId.current = context.target.defaultView.setTimeout(function () {
trySetOpen(false, e);
}, mouseLeaveDelay);
}
};
var triggerProps = {
onFocus: function onFocus(e) {
if (isFromKeyboard()) {
trySetOpen(true, e);
}
for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
args[_key - 1] = arguments[_key];
}
_invoke.apply(void 0, [triggerElement, 'props.onFocus', e].concat(args));
},
onBlur: function onBlur(e) {
if (!shouldStayOpen(e)) {
trySetOpen(false, e);
}
for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
args[_key2 - 1] = arguments[_key2];
}
_invoke.apply(void 0, [triggerElement, 'props.onBlur', e].concat(args));
},
onMouseEnter: function onMouseEnter(e) {
setTooltipOpen(true, e);
setWhatInputSource(context.target, 'mouse');
for (var _len3 = arguments.length, args = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
args[_key3 - 1] = arguments[_key3];
}
_invoke.apply(void 0, [triggerElement, 'props.onMouseEnter', e].concat(args));
},
onMouseLeave: function onMouseLeave(e) {
setTooltipOpen(false, e);
for (var _len4 = arguments.length, args = new Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) {
args[_key4 - 1] = arguments[_key4];
}
_invoke.apply(void 0, [triggerElement, 'props.onMouseLeave', e].concat(args));
}
};
var element = /*#__PURE__*/React.createElement(React.Fragment, null, triggerElement && /*#__PURE__*/React.createElement(Ref, {
innerRef: triggerRef
}, /*#__PURE__*/React.cloneElement(triggerElement, getA11Props('trigger', Object.assign({}, unhandledProps, triggerElement.props, triggerProps)))), /*#__PURE__*/React.createElement(PortalInner, {
mountNode: mountNode
}, /*#__PURE__*/React.createElement(Popper, {
align: align,
flipBoundary: flipBoundary,
offset: offset,
overflowBoundary: overflowBoundary,
pointerTargetRef: pointerTargetRef,
popperRef: popperRef,
position: position,
positionFixed: positionFixed,
enabled: open,
rtl: context.rtl,
targetRef: target || triggerRef,
children: renderPopperChildren,
unstable_disableTether: unstable_disableTether,
autoSize: autoSize,
unstable_pinned: unstable_pinned
})));
setEnd();
return element;
};
Tooltip.displayName = 'Tooltip';
Tooltip.defaultProps = {
align: 'center',
position: 'above',
mouseLeaveDelay: 10,
mouseEnterDelay: 0,
subtle: true,
accessibility: tooltipAsLabelBehavior,
offset: [4, 4]
};
Tooltip.propTypes = Object.assign({}, commonPropTypes.createCommon({
as: false,
content: false
}), {
dismissOnContentMouseEnter: PropTypes.bool,
mouseEnterDelay: PropTypes.number,
align: PropTypes.oneOf(ALIGNMENTS),
subtle: PropTypes.bool,
children: PropTypes.element,
defaultOpen: PropTypes.bool,
mountNode: customPropTypes.domNode,
mouseLeaveDelay: PropTypes.number,
offset: PropTypes.oneOfType([PropTypes.func, PropTypes.arrayOf(PropTypes.number)]),
open: PropTypes.bool,
onOpenChange: PropTypes.func,
pointing: PropTypes.bool,
position: PropTypes.oneOf(POSITIONS),
positionFixed: PropTypes.bool,
target: customPropTypes.domNode,
trigger: customPropTypes.every([customPropTypes.disallow(['children']), PropTypes.element]),
content: customPropTypes.shorthandAllowingChildren,
unstable_disableTether: PropTypes.oneOf([true, false, 'all']),
unstable_pinned: PropTypes.bool,
autoSize: PropTypes.oneOf(AUTOSIZES),
popperRef: customPropTypes.ref,
flipBoundary: PropTypes.oneOfType([PropTypes.object, PropTypes.arrayOf(PropTypes.object), PropTypes.oneOf(['clippingParents', 'window', 'scrollParent'])]),
overflowBoundary: PropTypes.oneOfType([PropTypes.object, PropTypes.arrayOf(PropTypes.object), PropTypes.oneOf(['clippingParents', 'window', 'scrollParent'])])
});
Tooltip.handledProps = Object.keys(Tooltip.propTypes);
Tooltip.Content = TooltipContent;
Tooltip.create = createShorthandFactory({
Component: Tooltip,
mappedProp: 'content'
});
return Tooltip;
}();
//# sourceMappingURL=Tooltip.js.map