UNPKG

@shopify/shop-minis-react

Version:

React component library for Shopify Shop Minis with Tailwind CSS v4 support (source-only, requires TypeScript)

150 lines (149 loc) 4.05 kB
import { useState as M, useRef as P, useCallback as o, useEffect as O } from "react"; const _ = 200, H = 400; function U({ onRefresh: g, threshold: R = _, indicatorThreshold: p = 0, enabled: E = !1 }) { const [Y, u] = M({ isPulling: !1, pullDistance: 0, canRefresh: !1 }), i = P(0), F = P(0), f = P(null), e = P(null), a = P(!1), A = o( (n) => { !E || !f.current || a.current || (e.current && (cancelAnimationFrame(e.current), e.current = null), u((t) => { const r = f.current; if (!r) return t; if (r.scrollTop <= 0) { const h = n.touches[0]; i.current = h.clientY; } else return i.current = 0, { ...t, isPulling: !1, pullDistance: 0, canRefresh: !1 }; return t; })); }, [E] ), S = o( (n, t) => { !E || !f.current || i.current === 0 || u((r) => { if (a.current) return r; const c = f.current; if (!c) return r; const h = c.scrollTop <= 0; F.current = n; const s = F.current - i.current; if (h && s > 0) { const l = s, m = l >= p; if (m && t && t(), m || r.isPulling) { const D = l > R ? R + (l - R) * 0.5 : l; return { ...r, isPulling: m, pullDistance: D, canRefresh: l >= R }; } return r; } else if (r.isPulling) return { ...r, isPulling: !1, pullDistance: 0, canRefresh: !1 }; return r; }); }, [R, p, E] ), L = o( (n) => { if (a.current) return; const t = n.touches[0]; t && i.current !== 0 && S(t.clientY, () => n.preventDefault()); }, [S] ), v = o(() => { a.current = !1; }, []), w = o((n) => { e.current && (cancelAnimationFrame(e.current), e.current = null); let t = n; if (t === void 0 && u((s) => (t = s.pullDistance, s)), !t || t <= 0) { u((s) => ({ ...s, pullDistance: 0, canRefresh: !1, isPulling: !1 })); return; } const r = H, c = Date.now(), h = () => { const s = Date.now() - c, T = Math.min(s / r, 1), l = 1 - (1 - T) ** 3, m = t * (1 - l); u((D) => ({ ...D, pullDistance: m, canRefresh: T < 1 ? D.canRefresh : !1 })), T < 1 ? e.current = requestAnimationFrame(h) : (e.current = null, u((D) => ({ ...D, pullDistance: 0, canRefresh: !1, isPulling: !1 }))); }; e.current = requestAnimationFrame(h); }, []), d = o(async () => { if (a.current) { i.current = 0; return; } i.current = 0, e.current && (cancelAnimationFrame(e.current), e.current = null); let n = !1, t = 0; const r = a.current; if (u((c) => (n = c.canRefresh && !r, t = c.pullDistance, { ...c, isPulling: !1 })), t <= 0) { u((c) => ({ ...c, pullDistance: 0, canRefresh: !1 })); return; } if (n && g) { a.current = !0; try { await g(); } catch (c) { console.error("Pull to refresh failed:", c); } v(); } w(t); }, [g, w, v]), I = o( (n) => { if (n) return f.current = n, n.addEventListener("touchstart", A, { passive: !1 }), n.addEventListener("touchmove", L, { passive: !1 }), n.addEventListener("touchend", d), n.addEventListener("touchcancel", d), () => { n.removeEventListener("touchstart", A), n.removeEventListener("touchmove", L), n.removeEventListener("touchend", d), n.removeEventListener("touchcancel", d); }; }, [A, L, d] ); return O(() => () => { e.current && (cancelAnimationFrame(e.current), e.current = null); }, []), { state: Y, bindToElement: I, containerRef: f }; } export { U as usePullToRefresh }; //# sourceMappingURL=usePullToRefresh.js.map