UNPKG

zent

Version:

一套前端设计语言和基于React的实现

107 lines (106 loc) 4.51 kB
import { __assign } from "tslib"; import { jsx as _jsx } from "react/jsx-runtime"; import cx from 'classnames'; import { Subject } from 'rxjs'; import { usePopoverContext } from './Context'; import Portal from '../portal'; import { useWindowEventHandler } from '../utils/component/WindowEventHandler'; import findPositionedParent from '../utils/dom/findPositionedParent'; import { INVISIBLE_POSITION } from './placement'; import { useLazy } from '../utils/hooks/useLazy'; import { useAnimationFramed } from '../utils/hooks/useAnimationFramed'; import { createContext, useContext, useEffect, useImperativeHandle, useMemo, useRef, useState, } from 'react'; import { useMounted } from '../utils/hooks/useMounted'; var ContentContext = createContext({ positionChanged$: new Subject(), }); ContentContext.displayName = 'PopoverContentContext'; function translateToContainerCoordinates(containerRect, bb) { var left = containerRect.left, top = containerRect.top; return { width: bb.width, height: bb.height, top: bb.top - top, left: bb.left - left, bottom: bb.bottom - top, right: bb.right - left, }; } function getPosition(_a, getContainer, getPositionedParent, portalRef) { var _b; var visible = _a.visible, placement = _a.placement, popover = _a.popover, cushion = _a.cushion; if (!visible) { return INVISIBLE_POSITION; } var container = getContainer(); var parent = getPositionedParent(); var portal = portalRef.current; var anchor = (_b = popover.getAnchor) === null || _b === void 0 ? void 0 : _b.call(popover); if (!container || !parent || !portal || !anchor || !(anchor instanceof HTMLElement)) { return INVISIBLE_POSITION; } var parentRect = parent.getBoundingClientRect(); var content = portal.container; var contentRect = content.getBoundingClientRect(); var anchorRect = anchor.getBoundingClientRect(); var relativeRect = translateToContainerCoordinates(parentRect, anchorRect); var position = placement({ relativeRect: relativeRect, anchor: anchor, anchorRect: anchorRect, content: content, contentRect: contentRect, containerRect: parentRect, container: parent, cushion: cushion, }); return position; } function PopoverContent(_a) { var children = _a.children; var ctx = usePopoverContext(); var parentPositionChanged$ = useContext(ContentContext).positionChanged$; var contentCtx = useMemo(function () { return ({ positionChanged$: new Subject(), }); }, []); var _b = useState(INVISIBLE_POSITION), position = _b[0], setPosition = _b[1]; var contextRef = useRef(ctx); contextRef.current = ctx; var containerSelector = ctx.containerSelector, portalRef = ctx.portalRef; var getContainer = useLazy(function () { return document.querySelector(containerSelector); }, [containerSelector]); var getPositionedParent = useLazy(function () { var container = getContainer(); return container && findPositionedParent(container); }, [getContainer]); var mounted = useMounted(); var adjustPosition = useAnimationFramed(function () { if (!mounted.current) { return; } var position = getPosition(contextRef.current, getContainer, getPositionedParent, portalRef); setPosition(position); }); useImperativeHandle(ctx.contentRef, function () { return ({ adjustPosition: adjustPosition, }); }, [adjustPosition]); useWindowEventHandler('resize', adjustPosition); useWindowEventHandler('scroll', adjustPosition, { capture: true, }); useEffect(function () { ctx.popover.positionUpdated(); contentCtx.positionChanged$.next(); }, [ctx.popover, position, contentCtx]); useEffect(function () { var $ = parentPositionChanged$.subscribe(function () { adjustPosition(); }); return function () { return $.unsubscribe(); }; }, [parentPositionChanged$, adjustPosition]); return (_jsx(Portal, __assign({ ref: portalRef, visible: ctx.visible, selector: containerSelector, className: cx('zent-popover-v2', position.className, ctx.className), style: __assign(__assign({}, position.style), ctx.style) }, { children: _jsx(ContentContext.Provider, __assign({ value: contentCtx }, { children: children }), void 0) }), void 0)); } export default PopoverContent;