npm package: @penner/easing
Description: Modern TypeScript implementations of the classic Penner easing functions with physics-based parameters
Author: Robert Penner
Latest version: 0.1.0

# @penner/easing

Modern TypeScript implementations of the classic Penner easing functions with physics-based parameters and tree-shakeable exports.

## Features

- **Tree-shakeable**: Import only the easing functions you need
- **Physics-based**: Configure easings with intuitive physical parameters
- **TypeScript**: Full type safety with comprehensive interfaces
- **Modern API**: Clean factory functions with sensible defaults
- **High performance**: Optimized implementations with numerical stability

## Installation

```bash
npm install @penner/easing
```

## Quick Start

```ts
import { back, bounce, spring } from '@penner/easing';

// Configure with physics parameters
const bounceOut = bounce.out({ bounces: 4, decay: 0.95 });
const backOut = back.out(0.15);
const springOut = spring.out({ bounces: 4, decay: 0.9 });

// Use in animations
const progress = bounceOut(0.5); // Returns the eased value at t=0.5
```

## Easing Families

### Back

Creates overshoot effects where the animation goes beyond its target before settling.

```ts
import { back } from '@penner/easing';

// Default overshoot (10%)
const easeOut = back.out();

// Custom overshoot (20%)
const easeOutBig = back.out(0.2);

// All variants
const easeIn = back.in(0.15);
const easeInOut = back.inOut(0.1);
const easeOutIn = back.outIn(0.1);
```

### Bounce

Physics-based bouncing with configurable energy loss and number of bounces.

```ts
import { bounce } from '@penner/easing';

// Default bounce (4 bounces, 95% decay)
const easeOut = bounce.out();

// Custom bounce
const easeOutBouncy = bounce.out({
  bounces: 6,
  decay: 0.8,
});

// All variants
const easeIn = bounce.in({ bounces: 3, decay: 0.9 });
const easeInOut = bounce.inOut();
const easeOutIn = bounce.outIn();
```

### Spring

Damped oscillations with configurable bounces and decay.

```ts
import { spring } from '@penner/easing';

// Default spring (4 bounces, 95% decay)
const easeOut = spring.out();

// Custom oscillations
const easeOutCustom = spring.out({
  bounces: 6,
  decay: 0.9,
});

// Critically damped (no oscillation)
const easeOutSmooth = spring.out({ bounces: 0 });

// All variants
const easeIn = spring.in();
const easeInOut = spring.inOut();
const easeOutIn = spring.outIn();
```

### Overdamped

Overdamped spring easing for smooth, non-oscillating motion.

```ts
import { overdamped } from '@penner/easing';
```

### Power

Custom polynomial easings with any exponent, including fractional powers.

```ts
import { power } from '@penner/easing';

// Create custom power functions
const sqrtOut = power.out(0.5); // Square root easing
const customIn = power.in(2.5); // t^2.5 easing

// All variants
const easeIn = power.in(1.7);
const easeOut = power.out(1.7);
const easeInOut = power.inOut(1.7);
const easeOutIn = power.outIn(1.7);
```

### Standard Easings

Classic polynomial and trigonometric easing functions. Each is a `StandardEasingFamily` with `.in`, `.out`, `.inOut`, and `.outIn` properties.

```ts
import { quad, cubic, quart, quint, sine, circular, expo } from '@penner/easing';

// Access variants as properties (not function calls)
const quadOut = quad.out;
const cubicIn = cubic.in;
const quartInOut = quart.inOut;
const sineOutIn = sine.outIn;
```

### Linear, Smoothstep, Smootherstep

Simple easing functions exported as single `EasingFn` values (not families).

```ts
import { linear, smoothstep, smootherstep } from '@penner/easing';

const value = smoothstep(0.5); // Hermite interpolation
```

### Exponential

Configurable exponential easing with utility functions.

```ts
import { expo, makeExpoEaseOut } from '@penner/easing';

// Standard expo family
const easeOut = expo.out;
const easeIn = expo.in;

// Custom exponential ease-out
const customExpo = makeExpoEaseOut(10);
```

## Tree-Shaking

Import only what you need to keep bundle sizes small:

```ts
// Import specific families
import { bounce, spring } from '@penner/easing';

// Import standard easings alongside physics-based ones
import { quad, cubic, back } from '@penner/easing';
```

## Configuration Interfaces

### BounceConfig

```ts
interface BounceConfig {
  bounces?: number; // Number of bounces (default: 4)
  decay?: number;   // Total height decay as fraction 0-1 (default: 0.95)
}
```

### SpringConfig

```ts
interface SpringConfig {
  bounces?: number; // Visible oscillation half-cycles (default: 4)
  decay?: number;   // Total amplitude decay as fraction 0-1 (default: 0.95)
}
```

## Utility Functions

```ts
import {
  reverseEasingFn,
  mirrorEasingFnToRight,
  mirrorEasingFnToLeft,
  clamp01,
  easingFnToCssLinear,
  createVelocityFn,
} from '@penner/easing';

// Reverse an easing function (swap start and end)
const myEaseIn = reverseEasingFn(quad.out);

// Mirror an easing to the right (ease-in becomes ease-in-out)
const myEaseInOut = mirrorEasingFnToRight(quad.in);

// Clamp values to 0-1 range
const safe = clamp01(someValue);

// Convert an easing function to a CSS linear() approximation
const css = easingFnToCssLinear(bounce.out());
```

## Migration from Legacy Penner Functions

If you're migrating from classic Penner easing functions:

```ts
// Old: easeOutBack(t, b, c, d, s)
// New:
const backOut = back.out(s * 0.1); // Convert strength to overshoot fraction
const result = b + c * backOut(t / d);

// Old: easeOutBounce(t, b, c, d)
// New:
const bounceOut = bounce.out(); // Uses sensible defaults
const result = b + c * bounceOut(t / d);
```

## License

MIT - see LICENSE file for details.