mirror of
https://github.com/aculix/negotium.git
synced 2026-09-11 07:28:17 +00:00
6b01e4c246
Removes docs/superpowers, which held a design note and an implementation plan. Those were working notes rather than anything the project needs, and they don't belong in the repo. Everything else here is wording: em dashes swapped for ordinary punctuation across the README and the code comments, and a few sentences straightened out.
52 lines
1.4 KiB
JavaScript
52 lines
1.4 KiB
JavaScript
/** Bounded stack of reversible operations. Kept separate from tasks.js so that
|
|
* module stays purely functional while this one holds the state. */
|
|
export function createUndoStack(limit = 10) {
|
|
const entries = []
|
|
|
|
return {
|
|
push(entry) {
|
|
entries.push(entry)
|
|
if (entries.length > limit) entries.shift()
|
|
},
|
|
pop() {
|
|
return entries.length > 0 ? entries.pop() : null
|
|
},
|
|
get size() {
|
|
return entries.length
|
|
},
|
|
clear() {
|
|
entries.length = 0
|
|
},
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Reverses one entry against the current task list.
|
|
*
|
|
* Indices are clamped because the list may have changed since the entry was
|
|
* recorded. A task deleted from position 5 can be restored into a list that
|
|
* has since shrunk to two items, and landing at the end beats throwing.
|
|
*
|
|
* `clearCompleted` entries must record `removed` in ascending index order, so
|
|
* re-inserting front to back puts each task back where it was.
|
|
*/
|
|
export function applyUndo(tasks, entry) {
|
|
if (!entry) return tasks
|
|
|
|
if (entry.type === 'delete') {
|
|
const next = [...tasks]
|
|
next.splice(Math.min(entry.index, next.length), 0, entry.task)
|
|
return next
|
|
}
|
|
|
|
if (entry.type === 'clearCompleted') {
|
|
const next = [...tasks]
|
|
for (const { task, index } of entry.removed) {
|
|
next.splice(Math.min(index, next.length), 0, task)
|
|
}
|
|
return next
|
|
}
|
|
|
|
return tasks
|
|
}
|