/* ============================================================ mobile-swipeable.jsx SwipeableRow — ligne qui révèle des actions au swipe. ============================================================ */ const { useState: uSw, useRef: rSw, useEffect: eSw } = React; /* ============================================================ SwipeableRow Nom système : SwipeableRow Cas d'usage : ligne d'une liste avec actions cachées (archive, suppression, marquer comme lu…). Style iOS Mail / Things / Apple Reminders. Gestes : SwipeLeft (révèle leftActions à droite), SwipeRight (révèle rightActions à gauche), Tap sur la ligne (action principale), Tap sur une action (déclenche l'action puis ferme). ============================================================ */ function SwipeableRow({ children, leftActions = [], rightActions = [], onTap }) { // leftActions s'affichent quand on swipe vers la GAUCHE // (la ligne se décale à gauche, dévoilant les actions à DROITE) const [tx, setTx] = uSw(0); const [dragging, setDragging] = uSw(false); const startX = rSw(0); const initialTx = rSw(0); const leftW = leftActions.length * 76; // actions à droite (révélées par swipe gauche) const rightW = rightActions.length * 76; // actions à gauche (révélées par swipe droit) const snap = (x) => { if (x < -leftW * 0.5) setTx(-leftW); else if (x > rightW * 0.5) setTx(rightW); else setTx(0); }; const onStart = (e) => { setDragging(true); startX.current = (e.touches ? e.touches[0].clientX : e.clientX); initialTx.current = tx; }; const onMove = (e) => { if (!dragging) return; const x = (e.touches ? e.touches[0].clientX : e.clientX); let d = initialTx.current + (x - startX.current); // limite + élasticité hors zone if (d > rightW) d = rightW + (d - rightW) * 0.3; if (d < -leftW) d = -leftW + (d + leftW) * 0.3; setTx(d); }; const onEnd = () => { setDragging(false); snap(tx); }; const fire = (action) => { setTx(0); setTimeout(() => action.onClick && action.onClick(), 200); }; const handleTap = (e) => { if (tx !== 0) { setTx(0); return; } if (Math.abs(tx) < 4 && onTap) onTap(e); }; return (