@cainiaofe/cn-ui-m
Version:
121 lines (120 loc) • 6.52 kB
JavaScript
import { __awaiter, __generator } from "tslib";
import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState, } from 'react';
import classNames from 'classnames';
import { Arrow } from './arrow';
import { arrow, autoUpdate, computePosition, platform, flip, hide, limitShift, offset, shift, } from '@floating-ui/dom';
import { useLockScroll } from "../../utils/use-lock-scroll";
import { Portal } from '../cn-modal/portal';
import { withNativeProps } from '@cainiaofe/cn-ui-common';
import { useClickAway } from 'ahooks';
import { isRTL } from '@cainiaofe/cn-i18n';
var rtl = isRTL();
var classNamePrefix = 'cn-ui-m-popover';
export var CnPopoverModal = forwardRef(function (props, ref) {
var _a = props.visible, visibleProps = _a === void 0 ? false : _a, container = props.container, placement = props.placement, _b = props.floatingMode, floatingMode = _b === void 0 ? 'light' : _b, _c = props.floatingContent, floatingContent = _c === void 0 ? '' : _c, className = props.className, clickAwayCallback = props.clickAwayCallback;
var _d = useState(props.visible), visible = _d[0], setVisible = _d[1];
useEffect(function () {
if (visible && !visibleProps) {
var t1_1 = setTimeout(function () { return setVisible(false); }, 300);
return function () { return clearTimeout(t1_1); };
}
setVisible(visibleProps);
return function () { };
}, [visible, visibleProps]);
var containerRef = useRef(null);
useLockScroll(containerRef, !!visible);
var floatingRef = useRef(null);
var arrowRef = useRef(null);
var floatingElement = withNativeProps(props, React.createElement("div", { className: classNames(CN_UI_HASH_CLASS_NAME, classNamePrefix, "".concat(classNamePrefix, "-").concat(floatingMode), !visibleProps && "".concat(classNamePrefix, "-hidden"), className), ref: floatingRef, dir: rtl ? 'rtl' : undefined, "data-testid": "cn-popover-modal" },
React.createElement("div", { className: "".concat(classNamePrefix, "-arrow"), ref: arrowRef },
React.createElement(Arrow, { className: "".concat(classNamePrefix, "-arrow-icon") })),
React.createElement("div", { className: "".concat(classNamePrefix, "-inner") },
React.createElement("div", { className: "".concat(classNamePrefix, "-inner-content") }, floatingContent))));
var _e = useState(null), targetElement = _e[0], setTargetElement = _e[1];
var floatingUpdate = useCallback(function (targetRef) { return __awaiter(void 0, void 0, void 0, function () {
var target, floating, arrowElement, _a, x, y, realPlacement, middlewareData, side, arrowSide, _b, arrowX, arrowY, arrowRotate;
var _c;
var _d, _e, _f;
return __generator(this, function (_g) {
switch (_g.label) {
case 0:
target = targetRef
? ((_e = (_d = targetRef.current) === null || _d === void 0 ? void 0 : _d.element) !== null && _e !== void 0 ? _e : null)
: targetElement;
floating = floatingRef.current;
arrowElement = arrowRef.current;
setTargetElement(target);
if (!target || !floating || !arrowElement)
return [2 /*return*/];
return [4 /*yield*/, computePosition(target, floating, {
placement: placement,
platform: platform,
middleware: [
offset(12),
shift({
padding: 4,
crossAxis: false,
limiter: limitShift(),
}),
flip(),
hide(),
arrow({
element: arrowElement,
padding: 12,
}),
],
})];
case 1:
_a = _g.sent(), x = _a.x, y = _a.y, realPlacement = _a.placement, middlewareData = _a.middlewareData;
Object.assign(floating.style, {
left: "".concat(x, "px"),
top: "".concat(y, "px"),
});
side = realPlacement.split('-')[0];
arrowSide = {
top: 'bottom',
right: 'left',
bottom: 'top',
left: 'right',
}[side];
_b = (_f = middlewareData.arrow) !== null && _f !== void 0 ? _f : {}, arrowX = _b.x, arrowY = _b.y;
Object.assign(arrowElement.style, (_c = {
left: arrowX != null ? "".concat(arrowX, "px") : '',
top: arrowY != null ? "".concat(arrowY, "px") : '',
right: '',
bottom: ''
},
_c[arrowSide] = '-8px',
_c));
arrowRotate = {
top: '0deg',
bottom: '180deg',
left: '270deg',
right: '90deg',
}[side];
arrowElement.style.setProperty('--arrow-icon-rotate', arrowRotate);
return [2 /*return*/];
}
});
}); }, [placement, targetElement]);
useEffect(function () {
var floatingEle = floatingRef.current;
if (!targetElement || !floatingEle)
return;
return autoUpdate(targetElement, floatingEle, function () {
setTargetElement(targetElement);
floatingUpdate();
}, {
elementResize: typeof ResizeObserver !== 'undefined',
});
}, [floatingUpdate, targetElement]);
useImperativeHandle(ref, function () {
var retRef = {
floatingUpdate: floatingUpdate,
floatingRef: floatingRef,
};
return retRef;
}, [floatingUpdate]);
useClickAway(clickAwayCallback, [function () { return targetElement; }, floatingRef], ['click', 'touchmove']);
return React.createElement(Portal, { container: container }, floatingElement);
});