Browse Source

fix: Draggable+Flippable interactions. blur, ESC to stop

master
Muthu Kumar 1 month ago
parent
commit
73d73cb11e
Failed to extract signature
  1. 14
      src/components/Flippable.tsx
  2. 15
      src/draggable.attempts/6/Draggable.ts

14
src/components/Flippable.tsx

@ -19,11 +19,11 @@ export const Flippable: React.FC<FlippableProps> = ({
const mouseDownTime = useRef<number>(0); const mouseDownTime = useRef<number>(0);
const DRAG_THRESHOLD = 250; // milliseconds const DRAG_THRESHOLD = 250; // milliseconds
const handleMouseDown = () => { const down = () => {
mouseDownTime.current = Date.now(); mouseDownTime.current = Date.now();
}; };
const handleClick = () => { const up = () => {
if (Date.now() - mouseDownTime.current < DRAG_THRESHOLD) { if (Date.now() - mouseDownTime.current < DRAG_THRESHOLD) {
setIsFlipped(prev => !prev); setIsFlipped(prev => !prev);
@ -45,9 +45,8 @@ export const Flippable: React.FC<FlippableProps> = ({
return ( return (
<div <div
ref={ref} ref={ref}
onClick={handleClick} onPointerUp={up}
onMouseDown={handleMouseDown} onPointerDown={down}
onTouchStart={handleMouseDown}
className={cx( className={cx(
css` css`
position: relative; position: relative;
@ -66,8 +65,13 @@ export const Flippable: React.FC<FlippableProps> = ({
-webkit-backface-visibility: hidden; /* Safari */ -webkit-backface-visibility: hidden; /* Safari */
} }
.card-front {
pointer-events: ${isFlipped ? "none" : "auto"};
}
.card-back { .card-back {
rotate: y 180deg; rotate: y 180deg;
pointer-events: ${isFlipped ? "auto" : "none"};
} }
`, `,
className, className,

15
src/draggable.attempts/6/Draggable.ts

@ -88,7 +88,6 @@ export function makeDraggable(card: HTMLElement, opts: DraggableOpts = {}) {
state.dragging = true; state.dragging = true;
activePointerId = e.pointerId; activePointerId = e.pointerId;
card.style.cursor = "grabbing"; card.style.cursor = "grabbing";
card.setPointerCapture(e.pointerId);
velocity = { x: 0, y: 0 }; velocity = { x: 0, y: 0 };
const dx = e.pageX - center.x; const dx = e.pageX - center.x;
@ -148,13 +147,17 @@ export function makeDraggable(card: HTMLElement, opts: DraggableOpts = {}) {
}; };
}; };
const up = (e: PointerEvent) => { const cancel = () => {
if (e.pointerId === activePointerId) {
state.dragging = false; state.dragging = false;
activePointerId = null; activePointerId = null;
card.style.cursor = "grab"; card.style.cursor = "grab";
// Momentum is handled in the render loop // Momentum is handled in the render loop
} };
const up = (e: PointerEvent | FocusEvent | KeyboardEvent) => {
if ("pointerId" in e && e.pointerId === activePointerId) return cancel();
else if ("key" in e && e.key === "Escape") return cancel();
else return cancel();
}; };
// Debounced Resize Handler using the Reset-Reflow-Recalculate-Reapply strategy // Debounced Resize Handler using the Reset-Reflow-Recalculate-Reapply strategy
@ -244,6 +247,8 @@ export function makeDraggable(card: HTMLElement, opts: DraggableOpts = {}) {
window.addEventListener("pointermove", move, { passive: true }); window.addEventListener("pointermove", move, { passive: true });
window.addEventListener("pointerup", up, { passive: true }); window.addEventListener("pointerup", up, { passive: true });
window.addEventListener("pointercancel", up, { passive: true }); window.addEventListener("pointercancel", up, { passive: true });
window.addEventListener("blur", up, { passive: true });
window.addEventListener("keydown", up, { passive: true });
window.addEventListener("resize", handleResize); window.addEventListener("resize", handleResize);
render(); render();
@ -254,6 +259,8 @@ export function makeDraggable(card: HTMLElement, opts: DraggableOpts = {}) {
window.removeEventListener("pointermove", move); window.removeEventListener("pointermove", move);
window.removeEventListener("pointerup", up); window.removeEventListener("pointerup", up);
window.removeEventListener("pointercancel", up); window.removeEventListener("pointercancel", up);
window.removeEventListener("blur", up);
window.removeEventListener("keydown", up);
window.removeEventListener("resize", handleResize); window.removeEventListener("resize", handleResize);
card.style.cursor = ""; card.style.cursor = "";
card.style.touchAction = ""; card.style.touchAction = "";

Loading…
Cancel
Save