@letar/forms

Undo / Redo

Ctrl+Z/Ctrl+Y history for forms with useFormHistory

Overview

No form library offers built-in undo/redo. useFormHistory() fills that gap with debounced snapshots, keyboard shortcuts, and an optional visual controls component.

import { HistoryControls, useFormHistory } from '@letar/forms'

function ProductEditor() {
  const form = useDeclarativeForm()
  const history = useFormHistory(form)

  return (
    <Form schema={ProductSchema} onSubmit={save}>
      <HistoryControls history={history} />
      <Form.Field.String name="title" />
      <Form.Field.RichText name="description" />
      <Form.Field.Currency name="price" />
      <Form.Button.Submit>Save</Form.Button.Submit>
    </Form>
  )
}

How It Works

  1. Subscribes to form.store (TanStack Form reactive store)
  2. On change → debounce 500ms → structuredClone snapshot
  3. Undo/Redo applies snapshot via form.setFieldValue per field
  4. Undo/redo changes are not recorded in history (prevents recursion)
  5. Branching (undo → edit) trims future entries

API: useFormHistory(form, config?)

const history = useFormHistory(form, {
  maxHistory: 50,        // Max snapshots (default: 50)
  debounceMs: 500,       // Delay before recording (default: 500ms)
  keyboard: true,        // Ctrl+Z/Y shortcuts (default: true)
  persist: false,        // sessionStorage (default: false)
  persistKey: 'form-history',
})

Returns:

FieldTypeDescription
undo() => voidUndo last change
redo() => voidRedo undone change
canUndobooleanHas undo history
canRedobooleanHas redo history
currentIndexnumberPosition in stack
historyLengthnumberTotal snapshots
clear() => voidReset history

Keyboard Shortcuts

KeysAction
Ctrl+Z / Cmd+ZUndo
Ctrl+Shift+Z / Ctrl+YRedo

Disable: keyboard: false.

HistoryControls

<HistoryControls
  history={historyApi}
  showCounter    // Show "3/7" counter
  size="sm"      // xs | sm | md
/>

When to Use

  • CMS / content editors (many fields, frequent edits)
  • Product configurators
  • Forms with RichText (users expect Ctrl+Z)
  • Long forms (10+ fields) where mistakes are costly

On this page