npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

react-amnesia

v0.3.0

Published

AI-friendly application undo/redo (CTRL+Z) for React

Readme

react-amnesia

AI-friendly application undo/redo (Ctrl+Z) for React.

npm version CI docs license

react-amnesia logo

react-amnesia is a small, in-memory command-history store for React applications. It manages an undo / redo stack and ships a useState-shaped hook so any piece of state in your UI can become reversible. Like its sister project react-mnemonic, it is designed to be AI-first: visible structure, unambiguous specifications, and small, composable primitives that an agent can reason about without guessing.

react-amnesia works well alongside react-mnemonic (so undoable state can also survive page reloads) but does not require it.

Installation

npm install react-amnesia

React 18 or 19 is required (^18.0.0 || ^19.0.0). The library is tested against both versions under <StrictMode>.

Quick start

Wrap the part of your tree that should share an undo stack in AmnesiaProvider, drop an AmnesiaShortcuts somewhere inside it for keyboard bindings, then use useUndoableState for any value the user can edit.

import { AmnesiaProvider, AmnesiaShortcuts, useUndoableState } from "react-amnesia";

function TitleEditor() {
    const [title, setTitle] = useUndoableState("Untitled", {
        label: "Edit title",
        coalesceKey: "edit:title",
    });

    return <input value={title} onChange={(event) => setTitle(event.target.value)} />;
}

export default function App() {
    return (
        <AmnesiaProvider capacity={200}>
            <AmnesiaShortcuts />
            <TitleEditor />
        </AmnesiaProvider>
    );
}

Ctrl+Z / Cmd+Z undoes the last edit; Ctrl+Shift+Z / Cmd+Shift+Z / Ctrl+Y redoes. Rapid keystrokes that share a coalesceKey collapse into a single history entry, so a single undo reverts the entire burst.

Why use it

  • useState-shaped hook (useUndoableState) for reversible UI state
  • Imperative push({ redo, undo, label }) for arbitrary actions
  • useAmnesiaLabels(scopeId?) selector for stable Undo/Redo menu labels
  • Coalescing for keystroke / drag bursts
  • Capacity-bounded stack so history can't grow without limit
  • Standard keyboard bindings via a single <AmnesiaShortcuts /> element
  • Optional react-mnemonic integration for persistence-aware undoables
  • Zero runtime dependencies; published TypeScript types

Pick the right entrypoint

| Entrypoint | Use when | | ------------------------ | -------------------------------------------------------------------------------------- | | react-amnesia/core | Pure undo/redo runtime. No react-mnemonic dependency. | | react-amnesia/mnemonic | You want usePersistedUndoableState to combine undo with react-mnemonic storage. | | react-amnesia/native | You need native editable detection / document.execCommand("undo" \| "redo") helpers. | | react-amnesia | Top-level entrypoint that re-exports core. Drop-in default for most apps. |

Imperative commands

For actions that don't fit a single value (e.g. inserting / deleting list items, mutating a graph, applying a transform), push commands directly.

import { useAmnesia } from "react-amnesia";

function AddItemButton({ list }: { list: List }) {
    const { push } = useAmnesia();
    return (
        <button
            onClick={() => {
                const item = list.createItem();
                push({
                    label: "Add item",
                    redo: () => list.add(item),
                    undo: () => list.remove(item.id),
                });
            }}
        >
            Add
        </button>
    );
}

push calls redo() once on insertion. If your call site has already mutated the application state, pass { applied: true } to skip that initial run.

Optional persistence

When paired with react-mnemonic, usePersistedUndoableState reads and writes the value through useMnemonicKey while still recording each user edit on the local Amnesia stack:

import { MnemonicProvider } from "react-mnemonic";
import { AmnesiaProvider, AmnesiaShortcuts } from "react-amnesia";
import { usePersistedUndoableState } from "react-amnesia/mnemonic";

function ThemePicker() {
    const { value, set } = usePersistedUndoableState<"light" | "dark">("theme", {
        defaultValue: "light",
        label: "Change theme",
    });
    return (
        <select value={value} onChange={(e) => set(e.target.value as "light" | "dark")}>
            <option value="light">Light</option>
            <option value="dark">Dark</option>
        </select>
    );
}

export default function App() {
    return (
        <MnemonicProvider namespace="my-app">
            <AmnesiaProvider>
                <AmnesiaShortcuts />
                <ThemePicker />
            </AmnesiaProvider>
        </MnemonicProvider>
    );
}

The undo stack itself is intentionally not persisted. Closures aren't serializable, and replaying old commands against new state is usually the wrong default. Reloads keep the latest value, but the history starts fresh on each session.

AI resources

| Resource | Purpose | | ------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------- | | AI Docs | Canonical invariants, decision matrix, recipes, anti-patterns, and setup guidance | | llms.txt | Compact retrieval index for tight context windows | | llms-full.txt | Long-form export for indexing and larger prompt contexts | | ai-contract.json | Machine-readable runtime contract for tooling and agent integrations | | DeepWiki priorities | Steering file that points DeepWiki toward the highest-signal sources | | AI Assistant Setup | Generated instruction packs plus the documented MCP-friendly retrieval path |

Learn more

License

MIT