function numberBox() {
const wrapper = html`<div>`;
const input = html`<input type="number">`;
const undoButton = html`<button>Undo</button>`;
const redoButton = html`<button>Redo</button>`;
const state = {
history: [],
value: 0,
undo: undoButton,
redo: redoButton
};
let curIndex = -1;
const addToHistory = debounce(e => {
if (curIndex !== state.history.length - 1) {
state.history = state.history.slice(0, curIndex);
}
state.history.push(e.target.valueAsNumber);
curIndex++;
state.value = e.target.valueAsNumber;
wrapper.value = state;
wrapper.dispatchEvent(new CustomEvent("input"));
}, 250);
input.addEventListener('input', addToHistory);
undoButton.addEventListener('click', undo);
redoButton.addEventListener('click', redo);
function undo() {
if (curIndex) curIndex--;
state.value = state.history[curIndex];
input.value = state.value;
wrapper.value = state;
wrapper.dispatchEvent(new CustomEvent("input"));
}
function redo() {
if (curIndex < state.history.length - 1) curIndex++;
state.value = state.history[curIndex];
input.value = state.value;
wrapper.value = state;
wrapper.dispatchEvent(new CustomEvent("input"));
}
function debounce(func, wait, immediate) {
var timeout;
return function() {
var context = this,
args = arguments;
var later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
}
wrapper.appendChild(input);
wrapper.appendChild(undoButton);
wrapper.appendChild(redoButton);
wrapper.value = state;
return wrapper;
}