UNPKG

@itwin/itwinui-react

Version:

A react component library for iTwinUI

244 lines (243 loc) 6.66 kB
'use strict'; 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';