diff --git a/src/RootDropTargets.tsx b/src/RootDropTargets.tsx index 28bbaa1..a01c8d3 100644 --- a/src/RootDropTargets.tsx +++ b/src/RootDropTargets.tsx @@ -11,20 +11,50 @@ export interface RootDropTargetsProps { isDragging: boolean; } -class RootDropTargetsClass extends React.PureComponent { - render() { - return ( -
- {values(MosaicDropTargetPosition).map((position) => ( - - ))} -
- ); - } +const RootDropTargetsComponent = React.memo((props: RootDropTargetsProps) => { + const delayedIsDragging = useDelayedTrue(props.isDragging, 0); + return ( +
+ {values(MosaicDropTargetPosition).map((position) => ( + + ))} +
+ ); +}); +RootDropTargetsComponent.displayName = 'RootDropTargetsComponent'; + +function useDelayedTrue(currentValue: boolean, delay: number): boolean { + const delayedRef = React.useRef(currentValue); + + const [, setCounter] = React.useState(0); + const setAndRender = (newValue: boolean) => { + delayedRef.current = newValue; + setCounter((count) => count + 1); + }; + + React.useEffect(() => { + if (delayedRef.current === currentValue) { + return; + } + + let timer: number | undefined; + if (currentValue) { + timer = window.setTimeout(() => setAndRender(true), delay); + } else { + setAndRender(false); + } + return () => { + if (timer) { + window.clearTimeout(timer); + } + }; + }, [currentValue]); + + return delayedRef.current; } const dropTarget = {}; @@ -34,4 +64,4 @@ export const RootDropTargets = DropTarget( (_connect, monitor): RootDropTargetsProps => ({ isDragging: monitor.getItem() !== null && monitor.getItemType() === MosaicDragType.WINDOW, }), -)(RootDropTargetsClass as any) as React.ComponentType<{}>; +)(RootDropTargetsComponent as any) as React.ComponentType; diff --git a/styles/mosaic-window.less b/styles/mosaic-window.less index 93281fd..76779e0 100644 --- a/styles/mosaic-window.less +++ b/styles/mosaic-window.less @@ -25,6 +25,9 @@ } .mosaic-window-title { + display: flex; + align-items: center; + height: 100%; padding-left: 15px; flex: 1; text-overflow: ellipsis;