UNPKG

jjb-lc-designable

Version:

基于alibaba-designable源码二次封装的表单设计器。

74 lines 2.8 kB
import React, { useRef, useState, useLayoutEffect } from 'react'; import { reaction } from 'jjb-lc-formily/reactive'; import { usePrefix, useViewport } from '../../hooks'; import { Selector } from './Selector'; import { Copy } from './Copy'; import { Delete } from './Delete'; import { DragHandler } from './DragHandler'; import cls from 'classnames'; const HELPER_DEBOUNCE_TIMEOUT = 100; export const Helpers = ({ node, nodeRect }) => { const prefix = usePrefix('aux-helpers'); const viewport = useViewport(); const unmountRef = useRef(false); const ref = useRef(); const [position, setPosition] = useState('top-right'); useLayoutEffect(() => { let request = null; const getYInViewport = (nodeRect, helpersRect) => { if (nodeRect.top - viewport.scrollY > helpersRect.height) { return 'top'; } else if (viewport.isScrollTop && nodeRect.height + helpersRect.height > viewport.height) { return 'inner-top'; } else if (nodeRect.bottom >= viewport.scrollY + viewport.height && nodeRect.height + helpersRect.height > viewport.height) { return 'inner-bottom'; } return 'bottom'; }; const getXInViewport = (nodeRect, helpersRect) => { const widthDelta = helpersRect.width - nodeRect.width; if (widthDelta >= 0) { if (nodeRect.x < widthDelta) { return 'left'; } else if (nodeRect.right + widthDelta > viewport.width) { return 'right'; } else { return 'center'; } } return 'right'; }; const update = () => { const helpersRect = ref.current?.getBoundingClientRect(); if (!helpersRect || !nodeRect) return; if (unmountRef.current) return; setPosition(getYInViewport(nodeRect, helpersRect) + '-' + getXInViewport(nodeRect, helpersRect)); }; update(); return reaction(() => [viewport.width, viewport.height, viewport.scrollX, viewport.scrollY, viewport.isScrollBottom, viewport.isScrollTop], () => { clearTimeout(request); request = setTimeout(update, HELPER_DEBOUNCE_TIMEOUT); }); }, [viewport, nodeRect]); if (!nodeRect || !node) return null; return /*#__PURE__*/React.createElement("div", { className: cls(prefix, { [position]: true }), ref: ref }, /*#__PURE__*/React.createElement("div", { className: cls(prefix + '-content') }, /*#__PURE__*/React.createElement(Selector, { node: node }), node?.allowClone() === false ? null : /*#__PURE__*/React.createElement(Copy, { node: node }), node?.allowDrag() === false ? null : /*#__PURE__*/React.createElement(DragHandler, { node: node }), node?.allowDelete() === false ? null : /*#__PURE__*/React.createElement(Delete, { node: node }))); }; Helpers.displayName = 'Helpers';