wix-style-react
Version:
wix-style-react
136 lines • 5.64 kB
JavaScript
import React, { useState, useImperativeHandle, forwardRef, useMemo, useCallback, } from 'react';
import PropTypes from 'prop-types';
import Popover from '../Popover';
import RawText from '../Text/RawText';
import { dataHooks, TIMEOUT } from './constants';
import { st, classes } from './Tooltip.st.css';
const Tooltip = forwardRef(({ onShow = () => ({}), onHide = () => ({}), size = 'medium', className, placement = 'top', exitDelay = 0, enterDelay = 0, moveArrowTo, appendTo = 'window', flip = true, fixed = false, maxWidth = 204, fluid, moveBy, disabled, children, zIndex = 6000, textAlign = 'start', content = '', inline, 'aria-describedby': ariaDescribedBy, 'aria-labelledby': ariaLabelledBy, ...rest }, ref) => {
const [shown, setShown] = useState(false);
useImperativeHandle(ref, () => ({ open, close }));
const open = useCallback(() => {
setShown(true);
onShow?.();
}, [onShow]);
const close = useCallback(() => {
setShown(false);
onHide?.();
}, [onHide]);
const isDisabled = useMemo(() => disabled === undefined
? // @ts-expect-error
children?.props && children?.props?.disabled
: disabled, [children, disabled]);
const onFocus = useCallback((event, handlers) => {
const focusableHOC = handlers && handlers.focus;
const target = event.target;
try {
if (process.env.NODE_ENV !== 'test' &&
target instanceof Element &&
!target.matches(':focus-visible')) {
handlers?.blur();
return;
}
}
catch (e) {
// browser does not support `matches(':focus-visible')` fallback to original focus behavior
}
open();
return focusableHOC ? handlers.focus() : null;
}, [open]);
const onBlur = useCallback((_event, handlers) => {
const focusableHOC = handlers && handlers.blur;
close();
return focusableHOC ? handlers.blur() : null;
}, [close]);
const triggerElement = useMemo(() => {
if (typeof children === 'string' || !children) {
return children;
}
if (React.isValidElement(children)) {
return React.cloneElement(children, {
onFocus: isDisabled ? undefined : onFocus,
onBlur: isDisabled ? undefined : onBlur,
...(ariaLabelledBy
? { 'aria-labelledby': ariaLabelledBy }
: { 'aria-describedby': ariaDescribedBy }),
});
}
if (typeof children === 'function') {
return children({
onFocus,
onBlur,
});
}
return;
}, [
children,
isDisabled,
onFocus,
onBlur,
ariaDescribedBy,
ariaLabelledBy,
]);
const contentElement = useMemo(() => {
const textSize = size === 'small' ? 'tiny' : 'small';
const textWeight = size === 'small' ? 'normal' : 'thin';
return (React.createElement("div", { style: { textAlign } }, typeof content === 'string' ? (
// @ts-ignore
React.createElement(RawText, { dataHook: dataHooks.tooltipText, size: textSize, weight: textWeight, light: true, className: classes.text }, content)) : (content)));
}, [content, textAlign, size]);
return (React.createElement(Popover, { role: "tooltip", showArrow: size !== 'small', className: st(classes.root, { size, inline }, className), placement: placement, shown: isDisabled ? false : shown, onMouseEnter: isDisabled ? undefined : open, onMouseLeave: close, onClickOutside: close, "data-size": size, hideDelay: exitDelay, showDelay: enterDelay, moveBy: moveBy, moveArrowTo: moveArrowTo, appendTo: appendTo, id: ariaLabelledBy || ariaDescribedBy, flip: flip, fixed: fixed, maxWidth: maxWidth, fluid: fluid, disableClickOutsideWhenClosed: true, zIndex: zIndex, ...rest, theme: "dark", timeout: TIMEOUT },
React.createElement(Popover.Element, null, triggerElement),
React.createElement(Popover.Content, null, contentElement)));
});
Tooltip.displayName = 'Tooltip';
Tooltip.propTypes = {
dataHook: PropTypes.string,
className: PropTypes.string,
// @ts-ignore
children: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),
// @ts-ignore
content: PropTypes.node,
textAlign: PropTypes.oneOf(['start', 'center']),
enterDelay: PropTypes.number,
exitDelay: PropTypes.number,
// @ts-expect-error
moveBy: PropTypes.shape({
x: PropTypes.number,
y: PropTypes.number,
}),
moveArrowTo: PropTypes.number,
// @ts-expect-error
appendTo: PropTypes.oneOfType([
PropTypes.oneOf(['window', 'scrollParent', 'viewport', 'parent']),
PropTypes.element,
PropTypes.func,
]),
flip: PropTypes.bool,
fixed: PropTypes.bool,
maxWidth: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
onShow: PropTypes.func,
onHide: PropTypes.func,
placement: PropTypes.oneOf([
'auto-start',
'auto',
'auto-end',
'top-start',
'top',
'top-end',
'right-start',
'right',
'right-end',
'bottom-end',
'bottom',
'bottom-start',
'left-end',
'left',
'left-start',
]),
disabled: PropTypes.bool,
size: PropTypes.oneOf(['small', 'medium']),
'aria-describedby': PropTypes.string,
'aria-labelledby': PropTypes.string,
zIndex: PropTypes.number,
fluid: PropTypes.bool,
};
export default Tooltip;
//# sourceMappingURL=Tooltip.js.map