# edge

Respond when a selected piece of state crosses an edge.



<DemoPreview name="edge" />

## Usage [#usage]

```ts
import { edge } from '@joycostudio/xyz'

const sync = edge(
  (state: { phase: string }) => state.phase,
  (next, previous) => console.log(previous, '→', next)
)

sync({ phase: 'loading' }) // undefined → loading
sync({ phase: 'loading' }) // unchanged: no callback
sync({ phase: 'ready' }) // loading → ready
```

## API [#api]

### edge [#edge]

```ts
edge<State, Selected>(
  select: (state: State) => Selected,
  onChange: (next: Selected, previous: Selected | undefined, state: State) => void,
  equals?: (left: Selected, right: Selected) => boolean
): (state: State) => void
```

Returns a state-sync function. It calls `onChange` on the first value and whenever the selected value changes.

| Argument   | Description                                                                                                                        |
| ---------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| `select`   | Reads the value to track from the supplied state. Runs on every sync call.                                                         |
| `onChange` | Receives the next selected value, previous selected value, and current state. The previous value is `undefined` on the first call. |
| `equals?`  | Compares the next selected value with the previous one. Return `true` to skip the callback. Defaults to `Object.is`.               |

The previous value is stored before `onChange` runs, so synchronous re-entry with the same selected value does not trigger another callback.

```ts
const sync = edge(
  (state: { progress: number }) => Math.floor(state.progress * 100),
  (percent, previous) => console.log(previous, '→', percent)
)

sync({ progress: 0.101 }) // undefined → 10
sync({ progress: 0.109 }) // unchanged: no callback
sync({ progress: 0.11 }) // 10 → 11
```

### sync [#sync]

```ts
sync(state: State): void
```

The function returned by `edge`. Call it whenever you want to check the current state for a transition.

| Argument | Description                                                                  |
| -------- | ---------------------------------------------------------------------------- |
| `state`  | Current state passed to `select` and, when the value changes, to `onChange`. |

```ts
// Using the sync function above:
sync({ progress: 0.5 }) // 11 → 50
sync({ progress: 0.5 }) // unchanged: no callback
```
