node package manager

boxes

Mutable state containers with time travelling

Boxes

Mutable state containers with time travelling for JavaScript apps

Boxes is written in vanilla ES6, so maybe you want to transpile it before using it.

Live demo (for modern browsers)

Project in active development, API may change

Create and return a new box from a given object (state).

Every box has its independent history.

let state = {a:1, o: {x: true}}
let box = boxes(state)

Returns the state of the box

box.get() //=> {a:1, o: {x: true}} 

Save scope changes in history. scope is state by default. save method returns the box, so you can chain multiple calls

// save state scope 
box.save()
// save picked scope 
box.save(scope.o)

Subscribe action method to changes in scope. That action will be launched on scope saving. scope is state by default.

on returns unsubscribe method.

let unsubscribe = box.subscribe(console.log)
scope.= 99
box.save()
// console will print: {a: 99, o: {x: true}} 
 
unsubscribe()
scope.= 3
box.save()
// console will print nothing 
 
box.on(scope.o, console.log)
scope.o.x = false
box.save(scope.o)
// console will print: {x: false} 

Remove listener action from scope bindings

const state = {a: 1}
const box = boxes(state)
let control = 0
const fn = () => control++
box.on(fn)
box.emit()
control === 1 // true 
 
box.off(state, fn)
box.emit()
control === 1 // true 

emit subscriptions without saving scope. scope is state by default. emit method returns the box, so you can chain multiple calls

// subscribe to a scope 
box.on(scope.o, myAction)
// will call `myAction` 
box.emit(scope.o)

Undo and redo changes in state. steps is a number greater than 0, by default 1. Both methods returns the actual position in history

let state = {a: 1}
let box = boxes(state)
 
delete state.a
state.= 99
box.save()
 
state.= 'boxes!'
box.save()
 
box.undo()
state.=== undefined // true 
state.=== 99 // true 
 
box.undo()
state.=== 1 // true 
state.=== undefined // true 
 
box.redo(2)
state.=== undefined // true 
state.=== 'boxes!' // true 

Boxes saves every change with a log. You can examine this array in box.records.

Change the log info of last commit. info can be any type. The log info of every change is Date.now() by default, but you can change it with box.log(info)

let state = {a: 1}
let box = boxes(state)
 
box.log('this is the initial state')
state.= 99
box.save() // will log `Date.now()` 
 
box.records // ['this is the initial state', 1460337512847] 

Travel in history to story in position, then return the actual position in the history as a number

let state = {a: 1}
let box = boxes(state)
 
box.now() === 0 // true 
 
state.= 9
box.save().now() === 1 // true 
 
box.undo()
box.now() === 0 // true 
 
box.now(1)
box.now() === 1 // true 

npm test

Open test/test.html

  • Build UMD file: npm run build-umd
  • Build browser tests: npm run build-tests
  • Run both builds: npm run build




© 2016 Jacobo Tabernero - Released under MIT License