{"_id":"@dgkit/signal-history","_rev":"4-0e464c9a82fe5dd8615978f596794a8a","name":"@dgkit/signal-history","dist-tags":{"latest":"0.2.2"},"versions":{"0.1.0":{"name":"@dgkit/signal-history","version":"0.1.0","keywords":["angular","standalone","ssr","signal-history","dgkit"],"author":{"name":"Danylo Grynyk","email":"danielgrynyk@gmail.com"},"license":"MIT","_id":"@dgkit/signal-history@0.1.0","maintainers":[{"name":"grynyk","email":"danielgrynyk@gmail.com"}],"homepage":"https://github.com/grynyk/dgkit/tree/main/packages/signal-history#readme","bugs":{"url":"https://github.com/grynyk/dgkit/issues"},"dist":{"shasum":"e5f4b678242147a31db489c3000d652c315ebcdb","tarball":"https://registry.npmjs.org/@dgkit/signal-history/-/signal-history-0.1.0.tgz","fileCount":8,"integrity":"sha512-1nAdoNW9KAOQMAueX6l73V7wVvsI/nv043i+0sqp8sXyeFQxoiSFgqHlgjQ6hppI45pIqIbahhdt0j4Ugca47A==","signatures":[{"sig":"MEUCIQCFsbfHpy+7vyLGWxX+Vhxth6oM0WT4t+OBMfbP23NRwAIgbZ55CC+Cdw2KiVzCRaUSh01lzIvGb0UqU3oUGyJCNMI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@dgkit%2fsignal-history@0.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":26123},"type":"module","_from":"file:dgkit-signal-history-0.1.0.tgz","module":"fesm2022/dgkit-signal-history.mjs","exports":{".":{"types":"./types/dgkit-signal-history.d.ts","default":"./fesm2022/dgkit-signal-history.mjs"},"./package.json":{"default":"./package.json"}},"typings":"types/dgkit-signal-history.d.ts","_npmUser":{"name":"grynyk","email":"danielgrynyk@gmail.com"},"_resolved":"/tmp/e28181e8b98fb81a80e9e883cbbe8159/dgkit-signal-history-0.1.0.tgz","_integrity":"sha512-1nAdoNW9KAOQMAueX6l73V7wVvsI/nv043i+0sqp8sXyeFQxoiSFgqHlgjQ6hppI45pIqIbahhdt0j4Ugca47A==","repository":{"url":"git+https://github.com/grynyk/dgkit.git","type":"git","directory":"packages/signal-history"},"_npmVersion":"11.6.2","description":"Undo/redo history for Angular signals, with grouped transactions.","directories":{},"sideEffects":false,"_nodeVersion":"24.13.0","dependencies":{"tslib":"^2.3.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"peerDependencies":{"rxjs":"^6.5.3 || ^7.4.0","@angular/core":">=18.0.0 <22.0.0","@angular/common":">=18.0.0 <22.0.0"},"_npmOperationalInternal":{"tmp":"tmp/signal-history_0.1.0_1784881359499_0.5583509473420605","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@dgkit/signal-history","version":"0.2.0","keywords":["angular","standalone","ssr","signal-history","dgkit"],"author":{"name":"Danylo Grynyk","email":"danielgrynyk@gmail.com"},"license":"MIT","_id":"@dgkit/signal-history@0.2.0","maintainers":[{"name":"grynyk","email":"danielgrynyk@gmail.com"}],"homepage":"https://github.com/grynyk/dgkit/tree/main/packages/signal-history#readme","bugs":{"url":"https://github.com/grynyk/dgkit/issues"},"dist":{"shasum":"f0aa1f709ecb8b9f5ff07ea2bc22cf678f54d806","tarball":"https://registry.npmjs.org/@dgkit/signal-history/-/signal-history-0.2.0.tgz","fileCount":7,"integrity":"sha512-HcuYpSo4brOsh2jRw53Hg8DSQtF6w30KtTAGxCCnCkJl36INZCgYB3LnTYOLs06jKDD6wURh04VlD1i3AwQdog==","signatures":[{"sig":"MEUCIQDBsx/fzCoaDlHP+Nm3Rq8nZ/XIFD64uPZBbRuP+M30XAIgVu6Ry4IJ9SchDXkQbRByx3h5F/UBmxKkBdMNDso7CtI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@dgkit%2fsignal-history@0.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":29762},"type":"module","module":"fesm2022/dgkit-signal-history.mjs","exports":{".":{"types":"./types/dgkit-signal-history.d.ts","default":"./fesm2022/dgkit-signal-history.mjs"},"./package.json":{"default":"./package.json"}},"gitHead":"0f9145a8d1efefa43821e22bd561cfb1dd567202","typings":"types/dgkit-signal-history.d.ts","_npmUser":{"name":"grynyk","email":"danielgrynyk@gmail.com"},"repository":{"url":"git+https://github.com/grynyk/dgkit.git","type":"git","directory":"packages/signal-history"},"_npmVersion":"11.6.2","description":"Undo/redo history for Angular signals, with grouped transactions.","directories":{},"sideEffects":false,"_nodeVersion":"24.13.0","dependencies":{"tslib":"^2.3.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"peerDependencies":{"rxjs":"^6.5.3 || ^7.4.0","@angular/core":">=18.0.0 <22.0.0","@angular/common":">=18.0.0 <22.0.0"},"_npmOperationalInternal":{"tmp":"tmp/signal-history_0.2.0_1784886035638_0.2339453436084522","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"@dgkit/signal-history","version":"0.2.1","keywords":["angular","standalone","ssr","signal-history","dgkit"],"author":{"name":"Danylo Grynyk","email":"danielgrynyk@gmail.com"},"license":"MIT","_id":"@dgkit/signal-history@0.2.1","maintainers":[{"name":"grynyk","email":"danielgrynyk@gmail.com"}],"homepage":"https://github.com/grynyk/dgkit/tree/main/packages/signal-history#readme","bugs":{"url":"https://github.com/grynyk/dgkit/issues"},"dist":{"shasum":"45ca4a77ed969c993a0486b9b59cac6e33866bba","tarball":"https://registry.npmjs.org/@dgkit/signal-history/-/signal-history-0.2.1.tgz","fileCount":7,"integrity":"sha512-RqUDEzyBvtHM3mM9+JT1xVrl8wWhqyJitZtqR/VYoBbU3jIboyWoOh3jXopjHFK+Lj8V9MaTdUFHBw6W0vV6/w==","signatures":[{"sig":"MEUCIF0jgsG7Vew3VjKyOga1XXs34T5zWVAjZzuEW2U/ThEdAiEAhgX+a3PgGZxgnFzqQ6YzswXlhmtc/83IYH/42wD2vZ8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@dgkit%2fsignal-history@0.2.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":30179},"type":"module","module":"fesm2022/dgkit-signal-history.mjs","exports":{".":{"types":"./types/dgkit-signal-history.d.ts","default":"./fesm2022/dgkit-signal-history.mjs"},"./package.json":{"default":"./package.json"}},"gitHead":"b57e4b0193dc465e58452ab76addebb226ac6ffc","typings":"types/dgkit-signal-history.d.ts","_npmUser":{"name":"grynyk","email":"danielgrynyk@gmail.com"},"repository":{"url":"git+https://github.com/grynyk/dgkit.git","type":"git","directory":"packages/signal-history"},"_npmVersion":"11.6.2","description":"Undo/redo history for Angular signals, with grouped transactions.","directories":{},"sideEffects":false,"_nodeVersion":"24.13.0","dependencies":{"tslib":"^2.3.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"peerDependencies":{"rxjs":"^6.5.3 || ^7.4.0","@angular/core":">=18.0.0 <22.0.0","@angular/common":">=18.0.0 <22.0.0"},"_npmOperationalInternal":{"tmp":"tmp/signal-history_0.2.1_1785930820614_0.6395727342600115","host":"s3://npm-registry-packages-npm-production"}},"0.2.2":{"name":"@dgkit/signal-history","version":"0.2.2","description":"Undo/redo history for Angular signals, with grouped transactions.","author":{"name":"Danylo Grynyk","email":"danielgrynyk@gmail.com"},"license":"MIT","homepage":"https://github.com/grynyk/dgkit/tree/main/packages/signal-history#readme","bugs":{"url":"https://github.com/grynyk/dgkit/issues"},"repository":{"type":"git","url":"git+https://github.com/grynyk/dgkit.git","directory":"packages/signal-history"},"keywords":["angular","standalone","ssr","signal-history","dgkit"],"sideEffects":false,"publishConfig":{"access":"public"},"peerDependencies":{"@angular/common":">=18.0.0 <22.0.0","@angular/core":">=18.0.0 <22.0.0","rxjs":"^6.5.3 || ^7.4.0"},"dependencies":{"tslib":"^2.3.0"},"module":"fesm2022/dgkit-signal-history.mjs","typings":"types/dgkit-signal-history.d.ts","exports":{"./package.json":{"default":"./package.json"},".":{"types":"./types/dgkit-signal-history.d.ts","default":"./fesm2022/dgkit-signal-history.mjs"}},"type":"module","gitHead":"9feef546280123103cdbf57fc425b6fff6a0dc4e","_id":"@dgkit/signal-history@0.2.2","_nodeVersion":"24.13.0","_npmVersion":"11.6.2","dist":{"integrity":"sha512-vi30P1DBZ3HaHGVNc/3johl5UnoVPEejf9e30qFye1O2UbwoadDb/L6PVdUzdInNUgbPDRgxzJedHlVCwlJz6Q==","shasum":"7c42b02d4cf228770abcb43a37d1ce6fb291444f","tarball":"https://registry.npmjs.org/@dgkit/signal-history/-/signal-history-0.2.2.tgz","fileCount":7,"unpackedSize":30272,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@dgkit%2fsignal-history@0.2.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQD+zuWlcUssKu2nRK2GarybLKBrAtIHfWC6Xaa6Q0eNUAIhAKDUMSi9lhihtZUfzsJppytzz48hP4Js81XiYAPIXzuo"}]},"_npmUser":{"name":"grynyk","email":"danielgrynyk@gmail.com"},"directories":{},"maintainers":[{"name":"grynyk","email":"danielgrynyk@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/signal-history_0.2.2_1786579329913_0.6199294262185655"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-24T08:22:39.299Z","modified":"2026-08-13T00:02:10.434Z","0.1.0":"2026-07-24T08:22:39.646Z","0.2.0":"2026-07-24T09:40:35.792Z","0.2.1":"2026-08-05T11:53:40.767Z","0.2.2":"2026-08-13T00:02:10.067Z"},"bugs":{"url":"https://github.com/grynyk/dgkit/issues"},"author":{"name":"Danylo Grynyk","email":"danielgrynyk@gmail.com"},"license":"MIT","homepage":"https://github.com/grynyk/dgkit/tree/main/packages/signal-history#readme","keywords":["angular","standalone","ssr","signal-history","dgkit"],"repository":{"type":"git","url":"git+https://github.com/grynyk/dgkit.git","directory":"packages/signal-history"},"description":"Undo/redo history for Angular signals, with grouped transactions.","maintainers":[{"name":"grynyk","email":"danielgrynyk@gmail.com"}],"readme":"# @dgkit/signal-history\n\n[![npm](https://img.shields.io/npm/v/@dgkit/signal-history)](https://www.npmjs.com/package/@dgkit/signal-history) [![Playground](https://img.shields.io/badge/playground-live-blueviolet)](https://grynyk.github.io/dgkit/#/)\n\n**Undo/redo for Angular signals.** Attach history to any `WritableSignal` and\nget `undo()`, `redo()`, `canUndo()`, `canRedo()` — all signals, so they drop\nstraight into templates and `computed()`s.\n\nUseful for editors, dashboards, configuration screens, drag-and-drop builders,\nfilters and complex forms.\n\n- ✅ Works with any existing `WritableSignal` — no wrapper type to adopt\n- ✅ Grouped **transactions** — many writes, one undo step\n- ✅ **Debounce** mode — coalesce keystrokes into one entry\n- ✅ Bounded memory via `limit`\n- ✅ Custom equality — ignore structurally identical values\n- ✅ Automatic teardown with the injection context\n\n## Installation\n\n```bash\nyarn add @dgkit/signal-history\n```\n\n## Compatibility\n\nWorks with **Angular 18, 19, 20 and 21**.\n\n| Peer dependency   | Supported range      |\n| ----------------- | -------------------- |\n| `@angular/core`   | `>=18.0.0 <22.0.0`   |\n| `@angular/common` | `>=18.0.0 <22.0.0`   |\n| `rxjs`            | `^6.5.3` or `^7.4.0` |\n\nAngular and RxJS are **peer dependencies** — never bundled into the package.\n\n## Quick start\n\n```ts\nimport { signal } from '@angular/core';\nimport { signalHistory } from '@dgkit/signal-history';\n\nconst document = signal(initialDocument);\n\nconst history = signalHistory(document, {\n  limit: 50,\n  debounce: 300,\n});\n\nhistory.undo();\nhistory.redo();\nhistory.canUndo(); // Signal<boolean>\nhistory.canRedo(); // Signal<boolean>\nhistory.reset();\n```\n\nIn a component:\n\n```ts\n@Component({\n  standalone: true,\n  template: `\n    <button (click)=\"history.undo()\" [disabled]=\"!history.canUndo()\">\n      Undo\n    </button>\n    <button (click)=\"history.redo()\" [disabled]=\"!history.canRedo()\">\n      Redo\n    </button>\n  `,\n})\nexport class Editor {\n  protected readonly doc = signal({ title: '', description: '' });\n  protected readonly history = signalHistory(this.doc, { debounce: 300 });\n}\n```\n\n## Transactions\n\nGroup several writes into a single undoable step:\n\n```ts\nhistory.transaction(() => {\n  document.update(updateTitle);\n  document.update(updateDescription);\n});\n\nhistory.undo(); // reverts both at once\n```\n\nTransactions nest — only the outermost one commits an entry — and the depth is\nrestored even if the callback throws.\n\n## API\n\n```ts\nconst history = signalHistory(source, options?);\n\nhistory.undo();\nhistory.redo();\nhistory.canUndo();   // Signal<boolean>\nhistory.canRedo();   // Signal<boolean>\nhistory.reset();     // clear history, keep the current value\nhistory.reset(value) // clear history and set a new baseline value\nhistory.transaction(fn);\nhistory.past();      // Signal<readonly T[]>  oldest first\nhistory.future();    // Signal<readonly T[]>  next-to-redo first\nhistory.destroy();   // stop tracking early (also automatic on destroy)\n```\n\n### Options\n\n| Option     | Type                      | Default     | Description                                                       |\n| ---------- | ------------------------- | ----------- | ----------------------------------------------------------------- |\n| `limit`    | `number`                  | `100`       | Max past entries; oldest dropped. `0`/non-finite means unlimited. |\n| `debounce` | `number`                  | `0`         | Coalesce changes arriving within this window into one entry.      |\n| `equal`    | `(a: T, b: T) => boolean` | `Object.is` | Decides whether a change is worth recording.                      |\n\n## Behavior details\n\n### How changes are observed\n\nHistory watches the source with an `effect`. A burst of **synchronous** writes\ntherefore collapses into a single entry naturally — the watcher sees the final\nvalue once per flush. Use `transaction()` when you need that grouping guaranteed\nregardless of flush timing.\n\nUndo/redo/reset update the internal \"current\" marker _before_ writing to the\nsource, so history never re-records its own writes — this is timing-independent\nand doesn't rely on effect scheduling order.\n\n### Redo invalidation\n\nAny new change clears the redo stack, matching standard editor semantics.\n\n### Memory\n\n`limit` bounds the past stack. Values are stored by reference — if you mutate\nobjects in place rather than replacing them, history will hold the same mutated\nreference. Prefer immutable updates (`update(x => ({...x, …}))`).\n\n## License\n\n[MIT](../../LICENSE)\n","readmeFilename":"README.md"}