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

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

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

Loading…
Cancel
Save