UNPKG

ultra-design

Version:
227 lines (207 loc) 8.36 kB
import _defineProperty from '@babel/runtime/helpers/defineProperty'; import _slicedToArray from '@babel/runtime/helpers/slicedToArray'; import React, { forwardRef, useState, useRef, useEffect, useImperativeHandle, cloneElement } from 'react'; import { usePrevious, useClickOutSide } from 'winhooks'; import { getPosition } from './placement.js'; import Layer from './layer.js'; import { useMergeProps } from '../utils/mergeProps.js'; import withStyle from '../utils/withStyle.js'; import { jsxs, Fragment, jsx } from '@emotion/react/jsx-runtime'; function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } var defaultPositionRect = { top: -1000, left: -1000, bottom: -1000, right: -1000, width: 0, height: 0, x: -1000, y: -1000 }; var defaultProps = { trigger: 'hover', defaultVisible: false, placement: 'bottom', showDelay: 50, hideDelay: 50, offset: 12, showArrow: true, transitionClassName: 'ultra-trigger-layer-fade', transitionTimeout: 300, name: 'ultra-trigger' }; var TriggerComponent = /*#__PURE__*/forwardRef(function (p, r) { var props = useMergeProps(defaultProps, p); var children = props.children, trigger = props.trigger, placement = props.placement, defaultVisible = props.defaultVisible, customVisible = props.visible, onVisibleChange = props.onVisibleChange, showDelay = props.showDelay, hideDelay = props.hideDelay, showArrow = props.showArrow, offset = props.offset, getLayerContainer = props.getLayerContainer, triggerRef = props.triggerRef, customLayerStyle = props.layerStyle; var _useState = useState(defaultVisible), _useState2 = _slicedToArray(_useState, 2), visible = _useState2[0], setVisible = _useState2[1]; var _useState3 = useState(defaultPositionRect), _useState4 = _slicedToArray(_useState3, 2), rect = _useState4[0], setRect = _useState4[1]; var timer = useRef(); var layerOffset = showArrow ? offset : offset - 6; var childRef = useRef(null); var layerRef = useRef(null); var updateRect = function updateRect() { var trigger = triggerRef || childRef; if (!trigger.current) return; if (customLayerStyle) return; var triggerRect = trigger.current.getBoundingClientRect(); if (!getLayerContainer) { var _document$documentEle = document.documentElement, scrollTop = _document$documentEle.scrollTop, scrollLeft = _document$documentEle.scrollLeft; setRect(_objectSpread(_objectSpread({}, triggerRect), {}, { width: triggerRect.width || rect.right - rect.left, height: triggerRect.height || rect.bottom - rect.top, top: triggerRect.top + scrollTop, bottom: triggerRect.bottom + scrollTop, left: triggerRect.left + scrollLeft, right: triggerRect.right + scrollLeft })); } else { var _trigger$current = trigger.current, offsetHeight = _trigger$current.offsetHeight, offsetLeft = _trigger$current.offsetLeft, offsetTop = _trigger$current.offsetTop, offsetWidth = _trigger$current.offsetWidth; setRect(_objectSpread(_objectSpread({}, triggerRect), {}, { width: offsetWidth, height: offsetHeight, top: offsetTop, bottom: offsetTop + offsetHeight, left: offsetLeft, right: offsetLeft + offsetWidth })); } }; useEffect(function () { updateRect(); }, [childRef.current ? childRef : triggerRef, visible]); useEffect(function () { window.addEventListener('resize', updateRect); return function () { window.removeEventListener('resize', updateRect); }; }, []); var changeVisible = function changeVisible(next) { var clear = function clear() { clearTimeout(timer.current); timer.current = undefined; }; var handler = function handler(next) { setVisible(next); onVisibleChange === null || onVisibleChange === void 0 ? void 0 : onVisibleChange(next); clear(); }; clear(); if (next) { timer.current = window.setTimeout(function () { return handler(true); }, showDelay); return; } var hideDelayWithoutClick = trigger === 'click' ? 0 : hideDelay; timer.current = window.setTimeout(function () { handler(false); }, hideDelayWithoutClick); }; var prevCustomVisbile = usePrevious(customVisible); useEffect(function () { if (customVisible === undefined) return; if (prevCustomVisbile === undefined && prevCustomVisbile === customVisible) return; changeVisible(customVisible); }, [customVisible]); var mouseEventHandler = function mouseEventHandler(next) { return trigger === 'hover' && changeVisible(next); }; var clickEventHandler = function clickEventHandler() { trigger === 'click' && changeVisible(!visible); }; useClickOutSide(childRef.current ? childRef : triggerRef, function () { trigger === 'click' && changeVisible(false); }, [layerRef]); useImperativeHandle(r, function () { return { layerElement: layerRef.current, update: updateRect, visible: visible, changeVisible: changeVisible }; }, [layerRef.current, visible]); var isElement = /*#__PURE__*/React.isValidElement(children); var layerStyle = getPosition(placement, rect, layerOffset); var child = isElement && /*#__PURE__*/cloneElement(children, { ref: childRef, onMouseEnter: function onMouseEnter() { return mouseEventHandler(true); }, onMouseLeave: function onMouseLeave() { return mouseEventHandler(false); }, onClick: function onClick(e) { var _children$props$onCli, _children$props; clickEventHandler(); isElement && ((_children$props$onCli = (_children$props = children.props).onClick) === null || _children$props$onCli === void 0 ? void 0 : _children$props$onCli.call(_children$props, e)); } }); useEffect(function () { if (!(triggerRef !== null && triggerRef !== void 0 && triggerRef.current)) return; triggerRef.current.addEventListener('mouseenter', function () { return mouseEventHandler(true); }); triggerRef.current.addEventListener('mouseleave', function () { return mouseEventHandler(false); }); triggerRef.current.addEventListener('click', function () { return changeVisible(!visible); }); return function () { if (!(triggerRef !== null && triggerRef !== void 0 && triggerRef.current)) return; triggerRef.current.removeEventListener('mouseenter', function () { return mouseEventHandler(true); }); triggerRef.current.removeEventListener('mouseleave', function () { return mouseEventHandler(false); }); triggerRef.current.removeEventListener('click', function () { return changeVisible(!visible); }); }; }, [triggerRef, visible]); return jsxs(Fragment, { children: [child, jsx(Layer, _objectSpread(_objectSpread({ ref: layerRef }, props), {}, { visible: visible, childRef: childRef.current ? childRef : triggerRef, style: customLayerStyle || layerStyle, onMouseEnter: function onMouseEnter() { return mouseEventHandler(true); }, onMouseLeave: function onMouseLeave() { return mouseEventHandler(false); } }))] }); }); TriggerComponent.displayName = 'UltraTrigger'; var Trigger = withStyle(TriggerComponent); var Trigger$1 = Trigger; export { Trigger$1 as default };