# @zakkster/lite-ease
> 30 Penner easing functions as pure (t)=>t. Zero dependencies. Tree-shakeable. Composable.

## Install
npm i @zakkster/lite-ease

## Import
import { easeOutBounce, easeInOutElastic, clamp01, reverse, mirror, chain, blend, scale } from '@zakkster/lite-ease';

## Key Facts
- 31 easings: 10 families × 3 variants (In/Out/InOut) + linear
- Every easing: (t: number) => number, t ∈ [0, 1]
- Composable: lerp(a, b, easeOutBounce(t))
- clamp01(t) clamps overshoot from Back/Elastic
- reverse(ease) creates the inverse curve
- easings map for string-based lookup
- Zero dependencies, pure math, no allocation in hot path

## Composition Helpers (v1.1)
Factory functions — build the closure ONCE at init scope, reuse the returned function in the hot path. Zero allocation per call.
- mirror(ease, clamp?) — ping-pong (0 → 1 → 0)
- chain(easeA, easeB, clamp?) — sequential: easeA on [0, 0.5], easeB on [0.5, 1]
- blend(easeA, easeB, weight) — linear crossfade, weight clamped to [0, 1] at init
- scale(ease, fromT, toT, clamp?) — remap to sub-segment; throws if toT <= fromT

## Families
Sine, Quad, Cubic, Quart, Quint, Expo, Circ, Back, Elastic, Bounce

## Overshoot Warning
easeOutBack and easeOutElastic return values > 1.0 at certain t values.
Use clamp01() wrapper if you need strict [0,1] output.

## Hot-Path Warning
Do NOT call mirror/chain/blend/scale per-frame. The factories allocate one
closure each call — building them inside an rAF loop produces a new closure
every frame and defeats the zero-GC design. Build once outside the loop.
