react-use#useThrottle TypeScript Examples
The following examples show how to use
react-use#useThrottle.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: PanelCanvas.tsx From ace with GNU Affero General Public License v3.0 | 4 votes |
PanelCanvasElement = <T extends PossibleCanvasElements>({ element, title, initialWidth, initialHeight, canvasZoom, resizingEnabled, onResizeCompleted, topBarContent, id, children, }: PropsWithChildren<PanelCanvasElementProps<T>>) => { const projectDispatch = useProjectDispatch(); const xResizeOriginalPos = useRef(0); const yResizeOriginalPos = useRef(0); const resizeMode = useRef<'x' | 'y' | 'xy' | null>(null); const [width, setWidth] = useState(initialWidth); const [height, setHeight] = useState(initialHeight); const [offsetX, setOffsetX] = useState(() => element.position.x); const [offsetY, setOffsetY] = useState(() => element.position.y); const throttledOffsetX = useThrottle(offsetX, 750); const throttledOffsetY = useThrottle(offsetY, 750); const TITLE_FONTSIZE = 18; const roundToGrid = (input: number): number => { const PROJECTED_GRID_CELL_SIZE = (PANEL_CANVAS_SIZE / GRID_SVG_SIZE) * GRID_LINE_SIZE; return Math.round(input / PROJECTED_GRID_CELL_SIZE) * PROJECTED_GRID_CELL_SIZE; }; // Handle updating the saved element when the throttled position is updated useEffect(() => { projectDispatch(updateCanvasElement({ ...element, position: { x: throttledOffsetX, y: throttledOffsetY } })); // eslint-disable-next-line react-hooks/exhaustive-deps }, [element.__kind, projectDispatch, throttledOffsetX, throttledOffsetY]); const [editPositionX, setEditPositionX] = useState(() => element.position.x); const [editPositionY, setEditPositionY] = useState(() => element.position.y); // Handle setting element position as edit movement changes useEffect(() => { setOffsetX(roundToGrid(editPositionX)); setOffsetY(roundToGrid(editPositionY)); }, [editPositionX, editPositionY]); const inEditMode = useProjectSelector((state) => state.interactionToolbar.panel === WorkspacePanelSelection.Edit); const canvasElementRef = useRef<HTMLDivElement>(null); const handlePanStart = (event: MouseEvent) => { document.body.addEventListener('mouseup', handlePanStop); document.body.addEventListener('mousemove', handlePanMouseMove); event.stopPropagation(); }; const handlePanStop = (event: globalThis.MouseEvent) => { document.body.removeEventListener('mouseup', handlePanStop); document.body.removeEventListener('mousemove', handlePanMouseMove); event.stopPropagation(); }; const handlePanMouseMove = (event: globalThis.MouseEvent) => { if (!canvasElementRef.current) { return; } setEditPositionX((old) => old + event.movementX / canvasZoom); setEditPositionY((old) => old + event.movementY / canvasZoom); event.stopPropagation(); }; const handleMouseDown = (e: React.MouseEvent) => { (e as any).canvasTarget = element; }; const handleResizeMouseMove = useCallback((e: globalThis.PointerEvent) => { if (resizeMode.current.includes('x')) { const delta = (e.clientX / canvasZoom) - xResizeOriginalPos.current; setWidth(initialWidth + delta); } if (resizeMode.current.includes('y')) { const delta = (e.clientY / canvasZoom) - yResizeOriginalPos.current; setHeight(initialHeight + delta); } }, [canvasZoom, initialWidth, initialHeight]); const handleResizeStop = useCallback((event: globalThis.MouseEvent) => { document.body.removeEventListener('mouseup', handleResizeStop); document.body.removeEventListener('pointermove', handleResizeMouseMove); event.stopPropagation(); // For some reason, width and height do not update fast enough onResizeCompleted(canvasElementRef.current.clientWidth, canvasElementRef.current.clientHeight); }, [handleResizeMouseMove, onResizeCompleted]); const handleResizeStart = useCallback((event: React.MouseEvent, newResizeMode: 'x' | 'y' | 'xy') => { document.body.addEventListener('mouseup', handleResizeStop); document.body.addEventListener('pointermove', handleResizeMouseMove); event.stopPropagation(); if (newResizeMode.includes('x')) { xResizeOriginalPos.current = event.clientX / canvasZoom; } if (newResizeMode.includes('y')) { yResizeOriginalPos.current = event.clientY / canvasZoom; } resizeMode.current = newResizeMode; }, [canvasZoom, handleResizeMouseMove, handleResizeStop]); return ( <span id={id} className="absolute" onMouseDown={handleMouseDown}> <span ref={canvasElementRef} className="shadow-md" style={{ width: `${width}px`, height: `${height}px`, position: 'absolute', // transitionDuration: '0.1s', transform: `translate(${(PANEL_CANVAS_SIZE / 2) + offsetX}px, ${(PANEL_CANVAS_SIZE / 2) + offsetY}px)`, }} > <span className="w-full absolute flex flex-row px-3 bg-gray-800 border-2 border-gray-700 rounded-t-md bg-opacity-80 h-10 -top-10 justify-between items-center"> <h1 style={{ fontSize: `${TITLE_FONTSIZE}px` }}>{title}</h1> <div className="flex flex-row flex-grow ml-2"> <div className="w-full flex items-center gap-x-2 ml-2.5"> {topBarContent} </div> {inEditMode && ( <div className="flex flex-row ml-2"> <IconArrowsMaximize size={22} className="hover:text-purple-500 hover:cursor-pointer" onMouseDown={handlePanStart} /> </div> )} </div> </span> <span className="block border border-[#00c2cc] hover:border-green-500 overflow-hidden" style={{ width: `${width}px`, height: `${height}px`, }} > {children} </span> {resizingEnabled && ( <> <span className="absolute top-0 right-[-4px] flex flex-col justify-center" style={{ height: 'calc(100% + 4px)' }}> <span className="absolute w-[4px] h-[40px] bg-green-500" style={{ cursor: 'ew-resize' }} onMouseDown={(e) => handleResizeStart(e, 'x')} /> <span className="mt-auto w-[4px] h-[40px] bg-green-500" style={{ cursor: 'nwse-resize' }} onMouseDown={(e) => handleResizeStart(e, 'xy')} /> </span> <span className="absolute flex justify-center" style={{ width: 'calc(100% + 4px)' }}> <span className="absolute w-[40px] h-[4px] bg-green-500" style={{ cursor: 'ns-resize' }} onMouseDown={(e) => handleResizeStart(e, 'y')} /> <span className="ml-auto w-[40px] h-[4px] bg-green-500" style={{ cursor: 'nwse-resize' }} onMouseDown={(e) => handleResizeStart(e, 'xy')} /> </span> </> )} </span> </span> ); }