save work for after react 19 migration

This commit is contained in:
Evan Simkowitz 2024-12-29 13:58:09 -05:00
parent cb2cd72cd4
commit 9eaec86697
No known key found for this signature in database
2 changed files with 42 additions and 36 deletions

View File

@ -10,7 +10,7 @@ import "./iconbutton.scss";
type IconButtonProps = { decl: IconButtonDecl; className?: string }; type IconButtonProps = { decl: IconButtonDecl; className?: string };
export const IconButton = memo( export const IconButton = memo(
forwardRef<HTMLButtonElement, IconButtonProps>(({ decl, className }, ref) => { forwardRef<HTMLButtonElement, IconButtonProps>(({ decl, className }, ref) => {
ref = ref ?? useRef<HTMLButtonElement>(null); const localRef = ref ?? useRef<HTMLButtonElement>(null);
const spin = decl.iconSpin ?? false; const spin = decl.iconSpin ?? false;
useLongClick(ref, decl.click, decl.longClick, decl.disabled); useLongClick(ref, decl.click, decl.longClick, decl.disabled);
return ( return (

View File

@ -1,40 +1,45 @@
// Copyright 2024, Command Line Inc. // Copyright 2024, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
import { useCallback, useEffect, useRef, useState } from "react"; import { useCallback, useEffect, useRef } from "react";
export const useLongClick = (ref, onClick, onLongClick, disabled = false, ms = 300) => { export function useLongClick<T extends HTMLElement>(
const timerRef = useRef(null); ref: React.MutableRefObject<T>,
const [longClickTriggered, setLongClickTriggered] = useState(false); onClick?: React.PointerEventHandler<T>,
onLongClick?: React.PointerEventHandler<T>,
disabled = false,
ms = 300
) {
const clickStartRef = useRef<number>(0);
const startPress = useCallback( const startPress = useCallback(
(e: React.MouseEvent<any>) => { (e: React.PointerEvent<T>) => {
if (onLongClick == null) { if (!onLongClick) {
return; onClick?.(e);
} else {
clickStartRef.current = Date.now();
} }
setLongClickTriggered(false);
timerRef.current = setTimeout(() => {
setLongClickTriggered(true);
onLongClick?.(e);
}, ms);
}, },
[onLongClick, ms] [onLongClick, onClick]
); );
const stopPress = useCallback(() => { const stopPress = useCallback(
clearTimeout(timerRef.current); (e: React.PointerEvent<T>) => {
}, []); const clickStart = clickStartRef.current;
clickStartRef.current = 0;
const handleClick = useCallback( if (clickStart !== 0) {
(e: React.MouseEvent<any>) => { const now = Date.now();
if (longClickTriggered) { const longClickTriggered = now - clickStart > ms;
e.preventDefault(); if (longClickTriggered && onLongClick) {
e.stopPropagation(); onLongClick?.(e);
return; } else {
onClick?.(e);
}
} else {
onClick?.(e);
} }
onClick?.(e);
}, },
[longClickTriggered, onClick] [ms, onClick, onLongClick]
); );
useEffect(() => { useEffect(() => {
@ -42,18 +47,19 @@ export const useLongClick = (ref, onClick, onLongClick, disabled = false, ms = 3
if (!element || disabled) return; if (!element || disabled) return;
element.addEventListener("mousedown", startPress); const startPressBound = startPress.bind(element);
element.addEventListener("mouseup", stopPress); const stopPressBound = stopPress.bind(element);
element.addEventListener("mouseleave", stopPress);
element.addEventListener("click", handleClick); element.addEventListener("pointerdown", startPressBound);
element.addEventListener("pointerup", stopPressBound);
element.addEventListener("pointerleave", stopPressBound);
return () => { return () => {
element.removeEventListener("mousedown", startPress); element.removeEventListener("pointerdown", startPressBound);
element.removeEventListener("mouseup", stopPress); element.removeEventListener("pointerup", stopPressBound);
element.removeEventListener("mouseleave", stopPress); element.removeEventListener("pointerleave", stopPressBound);
element.removeEventListener("click", handleClick);
}; };
}, [ref.current, startPress, stopPress, handleClick]); }, [ref.current, startPress, stopPress]);
return ref; return ref;
}; }