@wix/design-system
Version:
@wix/design-system
99 lines • 4.73 kB
JavaScript
import React, { useState, useImperativeHandle, forwardRef, useMemo, useEffect, useRef, } from 'react';
import Popover from '../Popover';
import RawText from '../Text/RawText';
import { dataHooks, TIMEOUT } from './constants';
import { ZIndex } from '../common/ZIndex';
import { st, classes } from './Tooltip.st.css.js';
import { useEventCallback } from '../common/useEventCallback/useEventCallback';
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 = ZIndex.tooltip, textAlign = 'start', content = '', inline, 'aria-describedby': ariaDescribedBy, 'aria-labelledby': ariaLabelledBy, interactive = true, ...rest }, ref) => {
const [shown, setShown] = useState(false);
const contentRef = useRef(null);
const open = useEventCallback(() => {
setShown(true);
onShow?.();
});
const close = useEventCallback(() => {
setShown(false);
onHide?.();
});
useImperativeHandle(ref, () => ({
open,
close,
getContentElement: () => contentRef.current,
}));
const isDisabled = disabled ?? false;
const onFocus = useEventCallback((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;
});
const onBlur = useEventCallback((_event, handlers) => {
const focusableHOC = handlers && handlers.blur;
close();
return focusableHOC ? handlers.blur() : null;
});
const handleKeyDown = useEventCallback((event) => {
if (event.key === 'Escape' && shown) {
close();
}
});
useEffect(() => {
document.addEventListener('keydown', handleKeyDown);
return () => {
document.removeEventListener('keydown', handleKeyDown);
};
}, [handleKeyDown]);
const triggerElement = useMemo(() => {
if (typeof children === 'string' || !children) {
return children;
}
if (React.isValidElement(children)) {
const ariaProps = ariaLabelledBy
? { 'aria-labelledby': ariaLabelledBy }
: { 'aria-describedby': ariaDescribedBy };
return React.cloneElement(children, {
...(isDisabled ? {} : { onFocus, onBlur }),
...ariaProps,
});
}
if (typeof children === 'function') {
return children({
onFocus,
onBlur,
});
}
return;
}, [
children,
isDisabled,
onFocus,
onBlur,
ariaDescribedBy,
ariaLabelledBy,
]);
const contentElement = useMemo(() => {
const textSize = size === 'small' ? 'tiny' : 'small';
return (React.createElement("div", { style: { textAlign } }, typeof content === 'string' ? (
// @ts-ignore
React.createElement(RawText, { dataHook: dataHooks.tooltipText, size: textSize, light: true, className: classes.text, renderChildren: ({ text }) => text, renderElement: ({ element }) => element }, 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, onEscPress: 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, interactive: interactive, ...rest, theme: "dark", timeout: TIMEOUT },
React.createElement(Popover.Element, null, triggerElement),
React.createElement(Popover.Content, null,
React.createElement("div", { ref: contentRef, style: { maxWidth } }, contentElement))));
});
Tooltip.displayName = 'Tooltip';
export default Tooltip;
//# sourceMappingURL=Tooltip.js.map