diff --git a/web/app/components/workflow/panel/index.tsx b/web/app/components/workflow/panel/index.tsx index 775191ece..5ecf0d2af 100644 --- a/web/app/components/workflow/panel/index.tsx +++ b/web/app/components/workflow/panel/index.tsx @@ -1,5 +1,5 @@ import type { FC } from 'react' -import { memo, useEffect, useRef } from 'react' +import { memo, useCallback, useEffect, useRef } from 'react' import { useNodes } from 'reactflow' import type { CommonNodeType } from '../types' import { Panel as NodePanel } from '../nodes' @@ -13,6 +13,51 @@ export type PanelProps = { right?: React.ReactNode } } + +/** + * Reference MDN standard implementation:https://developer.mozilla.org/zh-CN/docs/Web/API/ResizeObserverEntry/borderBoxSize + */ +const getEntryWidth = (entry: ResizeObserverEntry, element: HTMLElement): number => { + if (entry.borderBoxSize?.length > 0) + return entry.borderBoxSize[0].inlineSize + + if (entry.contentRect.width > 0) + return entry.contentRect.width + + return element.getBoundingClientRect().width +} + +const useResizeObserver = ( + callback: (width: number) => void, + dependencies: React.DependencyList = [], +) => { + const elementRef = useRef(null) + + const stableCallback = useCallback(callback, [callback]) + + useEffect(() => { + const element = elementRef.current + if (!element) return + + const resizeObserver = new ResizeObserver((entries) => { + for (const entry of entries) { + const width = getEntryWidth(entry, element) + stableCallback(width) + } + }) + + resizeObserver.observe(element) + + const initialWidth = element.getBoundingClientRect().width + stableCallback(initialWidth) + + return () => { + resizeObserver.disconnect() + } + }, [stableCallback, ...dependencies]) + return elementRef +} + const Panel: FC = ({ components, }) => { @@ -20,44 +65,21 @@ const Panel: FC = ({ const selectedNode = nodes.find(node => node.data.selected) const showEnvPanel = useStore(s => s.showEnvPanel) const isRestoring = useStore(s => s.isRestoring) + const showWorkflowVersionHistoryPanel = useStore(s => s.showWorkflowVersionHistoryPanel) - const rightPanelRef = useRef(null) const setRightPanelWidth = useStore(s => s.setRightPanelWidth) - - // get right panel width - useEffect(() => { - if (rightPanelRef.current) { - const resizeRightPanelObserver = new ResizeObserver((entries) => { - for (const entry of entries) { - const { inlineSize } = entry.borderBoxSize[0] - setRightPanelWidth(inlineSize) - } - }) - resizeRightPanelObserver.observe(rightPanelRef.current) - return () => { - resizeRightPanelObserver.disconnect() - } - } - }, [setRightPanelWidth]) - - const otherPanelRef = useRef(null) const setOtherPanelWidth = useStore(s => s.setOtherPanelWidth) - // get other panel width - useEffect(() => { - if (otherPanelRef.current) { - const resizeOtherPanelObserver = new ResizeObserver((entries) => { - for (const entry of entries) { - const { inlineSize } = entry.borderBoxSize[0] - setOtherPanelWidth(inlineSize) - } - }) - resizeOtherPanelObserver.observe(otherPanelRef.current) - return () => { - resizeOtherPanelObserver.disconnect() - } - } - }, [setOtherPanelWidth]) + const rightPanelRef = useResizeObserver( + setRightPanelWidth, + [setRightPanelWidth, selectedNode, showEnvPanel, showWorkflowVersionHistoryPanel], + ) + + const otherPanelRef = useResizeObserver( + setOtherPanelWidth, + [setOtherPanelWidth, showEnvPanel, showWorkflowVersionHistoryPanel], + ) + return (
= ({ className={cn('absolute bottom-1 right-0 top-14 z-10 flex outline-none')} key={`${isRestoring}`} > - { - components?.left - } - { - !!selectedNode && ( - - ) - } + {components?.left} + {!!selectedNode && }
- { - components?.right - } - { - showEnvPanel && ( - - ) - } + {components?.right} + {showEnvPanel && }
)