refactor: improvements
This commit is contained in:
46
frontend/src/app/canvas/ViewportDisplayContext.tsx
Normal file
46
frontend/src/app/canvas/ViewportDisplayContext.tsx
Normal file
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Single subscriber for viewport zoom: one component (ViewportDisplayProvider)
|
||||
* subscribes to useViewport() and provides displayMode so contextual nodes
|
||||
* don't each subscribe to viewport and re-render on every pan/zoom.
|
||||
*/
|
||||
|
||||
import React, { useLayoutEffect, useRef, useState } from 'react'
|
||||
import { useViewport } from '@xyflow/react'
|
||||
import { CONTEXTUAL_ZOOM_THRESHOLD } from '@/app/canvas/ContextualZoomNode'
|
||||
|
||||
export type ViewportDisplayMode = 'compact' | 'full'
|
||||
|
||||
const HYSTERESIS = 0.02
|
||||
|
||||
const ViewportDisplayContext = React.createContext<ViewportDisplayMode>('full')
|
||||
export { ViewportDisplayContext }
|
||||
|
||||
/**
|
||||
* Must be rendered inside ReactFlowProvider. Subscribes to viewport once,
|
||||
* maps zoom to displayMode with hysteresis, and provides it to descendants.
|
||||
*/
|
||||
export function ViewportDisplayProvider({ children }: { children: React.ReactNode }) {
|
||||
const { zoom } = useViewport()
|
||||
const [displayMode, setDisplayMode] = useState<ViewportDisplayMode>(() =>
|
||||
zoom <= CONTEXTUAL_ZOOM_THRESHOLD ? 'compact' : 'full'
|
||||
)
|
||||
const lastRef = useRef(displayMode)
|
||||
|
||||
useLayoutEffect(() => {
|
||||
const low = CONTEXTUAL_ZOOM_THRESHOLD - HYSTERESIS
|
||||
const high = CONTEXTUAL_ZOOM_THRESHOLD + HYSTERESIS
|
||||
let next: ViewportDisplayMode = lastRef.current
|
||||
if (zoom <= low) next = 'compact'
|
||||
else if (zoom >= high) next = 'full'
|
||||
if (next !== lastRef.current) {
|
||||
lastRef.current = next
|
||||
setDisplayMode(next)
|
||||
}
|
||||
}, [zoom])
|
||||
|
||||
return (
|
||||
<ViewportDisplayContext.Provider value={displayMode}>
|
||||
{children}
|
||||
</ViewportDisplayContext.Provider>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user