UNPKG

tossable

Version:

Generated by ambients-cli

116 lines (98 loc) 3.02 kB
import { inertia, pointer, value, calc, ColdSubscription } from "popmotion"; import { Cancellable } from "@lincode/promiselikes"; import "../assets/style.css"; import TouchLib from "touchlib"; import { extendFunction } from "@lincode/utils"; export class TossableHandle extends Cancellable { public constructor( cb: () => void, public set: (val: number) => void, public enable: () => void, public disable: () => void ) { super(cb); } } type Options = { min?: number, max?: number, start?: number, tug?: number, power?: number, bounceStiffness?: number, bounceDamping?: number, speed?: number, touchTarget: HTMLElement, current?: () => number, step: (val: number) => void, onComplete?: () => void, axis?: "x" | "y" } export default ({ min = 0, max = 500, start = min, tug = 0.2, power = 0.6, bounceStiffness = 400, bounceDamping = 20, speed = 1, touchTarget, current, step, onComplete, axis = "x" }: Options) => { const reaction = value(start, step); onComplete && (reaction.complete = extendFunction(reaction.complete, onComplete)); let trackerStart: ColdSubscription | undefined; let trackerStop: ColdSubscription | undefined; const touch = new TouchLib(touchTarget); touchTarget.classList.add("tossable-" + axis); const handle0 = touch.on("panstart", e => { trackerStart?.stop(); trackerStop?.stop(); const isVertical = Math.abs(e.deltaX) < Math.abs(e.deltaY) / 2; if ((axis === "x" && isVertical) || (axis === "y" && !isVertical)) return; const reactionStart = current?.() ?? reaction.get() as number; const applyOverdrag = (v: number) => { if (v < min) return calc.getValueFromProgress(min, v, tug); if (v > max) return calc.getValueFromProgress(max, v, tug); return v; } trackerStop = undefined; trackerStart = pointer({ preventDefault: false }) .pipe((v: { x: number, y: number }) => reactionStart + (v[axis] - e[axis]) * speed, applyOverdrag) .start(reaction); }); const handle1 = touch.on("panend", () => { trackerStart?.stop(); trackerStop?.stop(); trackerStart = undefined; //@ts-ignore trackerStop = inertia({ min, max, from: reaction.get(), velocity: reaction.getVelocity(), power, bounceStiffness, bounceDamping }).start(reaction); }); return new TossableHandle( () => { handle0.cancel(); handle1.cancel(); }, val => { trackerStart?.stop(); trackerStop?.stop(); trackerStart = undefined; trackerStop = undefined; reaction.update(val); }, () => touch.enable(), () => touch.disable() ); }