# react-utils/history

Undo/redo history management via React context.

```typescript
import {
    HistoryContextProvider,
    useWriteHistory,
    useUndoHistory,
    useRedoHistory,
    useResetHistory,
} from '@yaoc1996/js-tools/react-utils'
```

---

## Provider

---

### `HistoryContextProvider`

Provides history context to its descendants. All history hooks must be called inside this provider.

#### Parameters

| Name | Type | Description |
|------|------|-------------|
| `maxAge` | `number` | Maximum number of undo steps to retain. Oldest entries are dropped when the limit is reached. |
| `children` | `ReactNode` | Child elements. |

#### Example

```typescript
<HistoryContextProvider maxAge={50}>
    <MyEditor />
</HistoryContextProvider>
```

---

## Hooks

---

### `useWriteHistory()`

Returns a `write` function that executes a `ForwardAction` immediately and records the resulting reverse action in history. Calling `write` clears the redo stack.

#### Returns

`(forwardAction: ForwardAction) => void`

#### Example

```typescript
const write = useWriteHistory()

function handleChange(newValue: string) {
    const prev = value
    write(() => {
        setValue(newValue)
        return () => setValue(prev)
    })
}
```

#### Notes

- History is capped at `maxAge` entries; the oldest entry is dropped when the cap is reached.
- Every call to `write` clears the redo stack.

---

### `useUndoHistory()`

Returns `[canUndo, undo]`. `canUndo` is `true` when there is at least one entry in history.

#### Returns

`readonly [boolean, () => void]`

#### Example

```typescript
const [canUndo, undo] = useUndoHistory()

<button onClick={undo} disabled={!canUndo}>Undo</button>
```

#### Notes

- Calling `undo` when `canUndo` is `false` is a no-op.
- The undone entry is pushed onto the redo stack.

---

### `useRedoHistory()`

Returns `[canRedo, redo]`. `canRedo` is `true` when there are entries in the redo stack.

#### Returns

`readonly [boolean, () => void]`

#### Example

```typescript
const [canRedo, redo] = useRedoHistory()

<button onClick={redo} disabled={!canRedo}>Redo</button>
```

#### Notes

- Calling `redo` when `canRedo` is `false` is a no-op.
- The redone entry is pushed back onto the history stack.
- The redo stack is cleared whenever `useWriteHistory` is called.

---

### `useResetHistory()`

Returns a `reset` function that clears both the undo history and the redo stack.

#### Returns

`() => void`

#### Example

```typescript
const reset = useResetHistory()

<button onClick={reset}>Reset history</button>
```

---

## Types

```typescript
type ReverseAction = () => void
type ForwardAction = () => ReverseAction
```
