feat: Refactor panel component, add adaptive width observer to optimize panel width management (#21576)

pull/21673/head
GuanMu 11 months ago committed by GitHub
parent 81fc49d78c
commit 787ad5ab38
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -1,5 +1,5 @@
import type { FC } from 'react' import type { FC } from 'react'
import { memo, useEffect, useRef } from 'react' import { memo, useCallback, useEffect, useRef } from 'react'
import { useNodes } from 'reactflow' import { useNodes } from 'reactflow'
import type { CommonNodeType } from '../types' import type { CommonNodeType } from '../types'
import { Panel as NodePanel } from '../nodes' import { Panel as NodePanel } from '../nodes'
@ -13,51 +13,73 @@ export type PanelProps = {
right?: React.ReactNode right?: React.ReactNode
} }
} }
const Panel: FC<PanelProps> = ({
components,
}) => {
const nodes = useNodes<CommonNodeType>()
const selectedNode = nodes.find(node => node.data.selected)
const showEnvPanel = useStore(s => s.showEnvPanel)
const isRestoring = useStore(s => s.isRestoring)
const rightPanelRef = useRef<HTMLDivElement>(null) /**
const setRightPanelWidth = useStore(s => s.setRightPanelWidth) * Reference MDN standard implementationhttps://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
// get right panel width if (entry.contentRect.width > 0)
useEffect(() => { return entry.contentRect.width
if (rightPanelRef.current) {
const resizeRightPanelObserver = new ResizeObserver((entries) => { return element.getBoundingClientRect().width
for (const entry of entries) {
const { inlineSize } = entry.borderBoxSize[0]
setRightPanelWidth(inlineSize)
}
})
resizeRightPanelObserver.observe(rightPanelRef.current)
return () => {
resizeRightPanelObserver.disconnect()
}
} }
}, [setRightPanelWidth])
const otherPanelRef = useRef<HTMLDivElement>(null) const useResizeObserver = (
const setOtherPanelWidth = useStore(s => s.setOtherPanelWidth) callback: (width: number) => void,
dependencies: React.DependencyList = [],
) => {
const elementRef = useRef<HTMLDivElement>(null)
const stableCallback = useCallback(callback, [callback])
// get other panel width
useEffect(() => { useEffect(() => {
if (otherPanelRef.current) { const element = elementRef.current
const resizeOtherPanelObserver = new ResizeObserver((entries) => { if (!element) return
const resizeObserver = new ResizeObserver((entries) => {
for (const entry of entries) { for (const entry of entries) {
const { inlineSize } = entry.borderBoxSize[0] const width = getEntryWidth(entry, element)
setOtherPanelWidth(inlineSize) stableCallback(width)
} }
}) })
resizeOtherPanelObserver.observe(otherPanelRef.current)
resizeObserver.observe(element)
const initialWidth = element.getBoundingClientRect().width
stableCallback(initialWidth)
return () => { return () => {
resizeOtherPanelObserver.disconnect() resizeObserver.disconnect()
} }
}, [stableCallback, ...dependencies])
return elementRef
} }
}, [setOtherPanelWidth])
const Panel: FC<PanelProps> = ({
components,
}) => {
const nodes = useNodes<CommonNodeType>()
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 setRightPanelWidth = useStore(s => s.setRightPanelWidth)
const setOtherPanelWidth = useStore(s => s.setOtherPanelWidth)
const rightPanelRef = useResizeObserver(
setRightPanelWidth,
[setRightPanelWidth, selectedNode, showEnvPanel, showWorkflowVersionHistoryPanel],
)
const otherPanelRef = useResizeObserver(
setOtherPanelWidth,
[setOtherPanelWidth, showEnvPanel, showWorkflowVersionHistoryPanel],
)
return ( return (
<div <div
ref={rightPanelRef} ref={rightPanelRef}
@ -65,26 +87,14 @@ const Panel: FC<PanelProps> = ({
className={cn('absolute bottom-1 right-0 top-14 z-10 flex outline-none')} className={cn('absolute bottom-1 right-0 top-14 z-10 flex outline-none')}
key={`${isRestoring}`} key={`${isRestoring}`}
> >
{ {components?.left}
components?.left {!!selectedNode && <NodePanel {...selectedNode} />}
}
{
!!selectedNode && (
<NodePanel {...selectedNode!} />
)
}
<div <div
className='relative' className="relative"
ref={otherPanelRef} ref={otherPanelRef}
> >
{ {components?.right}
components?.right {showEnvPanel && <EnvPanel />}
}
{
showEnvPanel && (
<EnvPanel />
)
}
</div> </div>
</div> </div>
) )

Loading…
Cancel
Save