@itwin/itwinui-react
Version:
A react component library for iTwinUI
244 lines (243 loc) • 6.66 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', {
value: true,
});
function _export(target, all) {
for (var name in all)
Object.defineProperty(target, name, {
enumerable: true,
get: all[name],
});
}
_export(exports, {
Tooltip: function () {
return Tooltip;
},
defaultTooltipDelay: function () {
return defaultTooltipDelay;
},
});
const _interop_require_default = require('@swc/helpers/_/_interop_require_default');
const _interop_require_wildcard = require('@swc/helpers/_/_interop_require_wildcard');
const _react = /*#__PURE__*/ _interop_require_wildcard._(require('react'));
const _classnames = /*#__PURE__*/ _interop_require_default._(
require('classnames'),
);
const _react1 = require('@floating-ui/react');
const _index = require('../../utils/index.js');
const defaultTooltipDelay = {
open: 200,
close: 200,
};
const useTooltip = (options = {}) => {
let uniqueId = (0, _index.useId)();
let {
placement = 'top',
visible,
onVisibleChange,
middleware = {
flip: true,
shift: true,
},
autoUpdateOptions = {},
reference,
ariaStrategy = 'description',
id = uniqueId,
...props
} = options;
let [open, onOpenChange] = (0, _index.useControlledState)(
false,
visible,
onVisibleChange,
);
let syncWithControlledState = _react.useCallback(
(element) => {
queueMicrotask(() => {
try {
element?.togglePopover?.(open);
} catch {}
});
},
[open],
);
let floating = (0, _react1.useFloating)({
placement,
open,
onOpenChange,
strategy: 'fixed',
whileElementsMounted: _react.useMemo(
() =>
open
? (...args) => (0, _react1.autoUpdate)(...args, autoUpdateOptions)
: void 0,
[autoUpdateOptions, open],
),
middleware: _react.useMemo(
() =>
[
void 0 !== middleware.offset
? (0, _react1.offset)(middleware.offset)
: (0, _react1.offset)(4),
middleware.flip &&
(0, _react1.flip)({
padding: 4,
}),
middleware.shift &&
(0, _react1.shift)({
padding: 4,
}),
middleware.size &&
(0, _react1.size)({
padding: 4,
}),
middleware.autoPlacement &&
(0, _react1.autoPlacement)({
padding: 4,
}),
middleware.inline && (0, _react1.inline)(),
middleware.hide &&
(0, _react1.hide)({
padding: 4,
}),
].filter(Boolean),
[middleware],
),
...(reference && {
elements: {
reference,
},
}),
});
let ariaProps = _react.useMemo(
() =>
'description' === ariaStrategy
? {
'aria-describedby': id,
}
: 'label' === ariaStrategy
? {
'aria-labelledby': id,
}
: {},
[ariaStrategy, id],
);
let { delay } = (0, _react1.useDelayGroup)(floating.context, {
id: (0, _index.useId)(),
});
let interactions = (0, _react1.useInteractions)([
(0, _react1.useHover)(floating.context, {
delay: 0 !== delay ? delay : defaultTooltipDelay,
handleClose: (0, _react1.safePolygon)({
buffer: -1 / 0,
}),
move: false,
}),
(0, _react1.useFocus)(floating.context),
(0, _react1.useDismiss)(floating.context, {
referencePress: true,
referencePressEvent: 'click',
}),
]);
_react.useEffect(() => {
if (!reference) return;
let domEventName = (e) => e.toLowerCase().substring(2);
let cleanupValues = {};
Object.entries({
...ariaProps,
...interactions.getReferenceProps(),
}).forEach(([key, value]) => {
if ('function' == typeof value) {
let patchedHandler = (event) => {
value({
...event,
nativeEvent: event,
});
};
reference.addEventListener(domEventName(key), patchedHandler);
cleanupValues[key] = patchedHandler;
} else if (value) {
cleanupValues[key] = reference.getAttribute(key);
reference.setAttribute(key, value);
}
});
return () => {
Object.entries(cleanupValues).forEach(([key, value]) => {
if ('function' == typeof value)
reference.removeEventListener(domEventName(key), value);
else if (value) reference.setAttribute(key, value);
else reference.removeAttribute(key);
});
};
}, [ariaProps, reference, interactions]);
let getReferenceProps = _react.useCallback(
(userProps) =>
interactions.getReferenceProps({
...userProps,
...ariaProps,
}),
[interactions, ariaProps],
);
let floatingProps = _react.useMemo(
() => ({
...interactions.getFloatingProps({
hidden: !open,
'aria-hidden': 'true',
...props,
id,
}),
popover: 'manual',
}),
[interactions, props, id, open],
);
return _react.useMemo(
() => ({
getReferenceProps,
floatingProps,
...floating,
refs: {
...floating.refs,
setFloating: (element) => {
floating.refs.setFloating(element);
syncWithControlledState(element);
},
},
floatingStyles: floating.context.open ? floating.floatingStyles : {},
}),
[getReferenceProps, floatingProps, floating, syncWithControlledState],
);
};
const Tooltip = _react.forwardRef((props, forwardedRef) => {
let { content, children, portal = true, className, style, ...rest } = props;
let tooltip = useTooltip(rest);
let refs = (0, _index.useMergedRefs)(tooltip.refs.setFloating, forwardedRef);
return _react.createElement(
_react.Fragment,
null,
(0, _index.cloneElementWithRef)(children, (children) => ({
...tooltip.getReferenceProps(children.props),
ref: tooltip.refs.setReference,
})),
'none' !== props.ariaStrategy || tooltip.context.open
? _react.createElement(
_index.Portal,
{
portal: portal,
},
_react.createElement(
_index.Box,
{
className: (0, _classnames.default)('iui-tooltip', className),
ref: refs,
style: {
...tooltip.floatingStyles,
...style,
},
...tooltip.floatingProps,
},
content,
),
)
: null,
);
});
if ('development' === process.env.NODE_ENV) Tooltip.displayName = 'Tooltip';