// ===== Draggable stickers + Ctrl+Z easter egg ===== const { useEffect, useRef, useState } = React; function Sticker({ id, initial, children, rotate = 0, onMove }) { const [pos, setPos] = useState(initial); const [drag, setDrag] = useState(false); const ref = useRef(null); const drift = useRef({ vx: 0, vy: 0, lastX: 0, lastY: 0, lastT: 0 }); useEffect(() => { onMove && onMove(id, pos); }, [pos]); const onDown = (e) => { const pt = 'touches' in e ? e.touches[0] : e; const rect = ref.current.getBoundingClientRect(); const offX = pt.clientX - rect.left; const offY = pt.clientY - rect.top; setDrag(true); drift.current.lastX = pt.clientX; drift.current.lastY = pt.clientY; drift.current.lastT = performance.now(); const move = (ev) => { const p = 'touches' in ev ? ev.touches[0] : ev; const now = performance.now(); const dt = Math.max(16, now - drift.current.lastT); drift.current.vx = (p.clientX - drift.current.lastX) / dt * 16; drift.current.vy = (p.clientY - drift.current.lastY) / dt * 16; drift.current.lastX = p.clientX; drift.current.lastY = p.clientY; drift.current.lastT = now; // absolute container coords const container = ref.current.offsetParent || document.body; const cRect = container.getBoundingClientRect(); setPos({ x: p.clientX - cRect.left - offX, y: p.clientY - cRect.top - offY }); ev.preventDefault(); }; const up = () => { setDrag(false); // throw with inertia let { vx, vy } = drift.current; const animate = () => { vx *= 0.92; vy *= 0.92; if (Math.abs(vx) < 0.3 && Math.abs(vy) < 0.3) return; setPos(p => ({ x: p.x + vx, y: p.y + vy })); requestAnimationFrame(animate); }; animate(); window.removeEventListener('mousemove', move); window.removeEventListener('mouseup', up); window.removeEventListener('touchmove', move); window.removeEventListener('touchend', up); }; window.addEventListener('mousemove', move); window.addEventListener('mouseup', up); window.addEventListener('touchmove', move, { passive: false }); window.addEventListener('touchend', up); }; return (
{children}
); } // preset sticker SVGs const STICKER_SVGS = { star: ( NEW! ), arrow: ( ), cloud: ( nice. ), squiggle: ( ), dot: ( CTRL ), z: ( Z ), }; window.Sticker = Sticker; window.STICKER_SVGS = STICKER_SVGS;