@domx/dataelement
Version:
A DataElement base class for handling data state changes
81 lines • 2.71 kB
JavaScript
export { RootState };
const stateProp = Symbol();
/**
* Used to keep track of a global state tree
* for data elements.
*/
class RootState {
/** Initializes/resets the root state */
static init(state) {
RootState.current = state;
}
/** Returns the state at the given state path */
static get(path) {
const value = path.split(".").reduce((state, prop) => state !== undefined ? state[prop] : undefined, RootState.current);
return value === undefined ? null : value;
}
/** Sets the state at the given state path */
static set(path, value) {
setState(RootState.current, path, value);
}
/** Removes the state at the given state path */
static delete(path) {
setState(RootState.current, path, undefined);
}
/**
* Creates a copy of the root state and sets the value at the state path.
* Used for intermediate changes before committing.
*/
static draft(path, value) {
const copy = JSON.parse(JSON.stringify(RootState.current));
const state = setState(copy, path, value);
return state;
}
/** The current root state */
static get current() {
if (!window[stateProp]) {
window[stateProp] = {};
}
return window[stateProp];
}
static set current(state) {
window[stateProp] = state;
}
static snapshot(name) {
window.dispatchEvent(new CustomEvent("rootstate-snapshot", {
detail: {
name,
state: RootState.current
}
}));
}
}
/** Used for setting, deleting, and drafting state */
const setState = (state, path, value) => {
let currentState = state;
const pathParts = path.split(".");
let deleteElStatePath = null;
pathParts.forEach((prop, index) => {
if (index === pathParts.length - 1) {
if (value === undefined) {
delete currentState[prop];
// if empty, then delete that part as well
if (Object.keys(currentState).length === 0) {
deleteElStatePath = [...pathParts].splice(0, pathParts.length - 1).join(".");
}
}
else {
currentState[prop] = Object.assign({}, value);
}
}
else if (currentState[prop] === undefined) {
currentState[prop] = {};
}
currentState = currentState[prop];
});
if (deleteElStatePath) {
return setState(RootState.current, deleteElStatePath, undefined);
}
return state;
};
//# sourceMappingURL=RootState.js.map