UNPKG

svelte-ux

Version:

- Increment version in `package.json` and commit as `Version bump to x.y.z` - `npm run publish`

78 lines (77 loc) 3.32 kB
import { writable, get } from 'svelte/store'; import { applyPatches, createDraft, finishDraft, enablePatches, setAutoFreeze, current, } from 'immer'; import { set } from 'lodash-es'; // Needed for finishDraft() patches/inverseChanges - https://immerjs.github.io/immer/patches enablePatches(); // Disable autofreezing for now (needed for Period layer after saving new hierarchy) - https://immerjs.github.io/immer/freezing/ setAutoFreeze(false); export default function formStore(initialState, options) { const stateStore = writable(initialState); const draftStore = writable(createDraft(initialState)); const errorsStore = writable({}); // TODO: Improve type (`{ [key in keyof T]: string }`?) const undoList = []; const storeApi = { subscribe: stateStore.subscribe }; let currentDraftValue = writable(current(get(draftStore))); const draftApi = { ...draftStore, set(newState) { draftStore.set(createDraft(newState)); }, /** Apply draft to state after verifying with schema (if available). Append change to undo stack */ commit() { const draft = get(draftStore); if (options === null || options === void 0 ? void 0 : options.schema) { const result = options.schema.safeParse(draft); if (result.success === true) { // Clear errors errorsStore.set({}); // TODO: Consider using `result.data` in case there are defaults, etc? } else { const errors = {}; for (const issue of result.error.issues) { set(errors, issue.path, issue.message); } errorsStore.set(errors); return false; } } const newState = finishDraft(draft, (patches, inverseChanges) => { undoList.push(inverseChanges); }); stateStore.set(newState); draftStore.set(createDraft(newState)); return true; }, /** Revert draft to last committed state */ revert() { const currentState = get(stateStore); draftStore.set(createDraft(currentState)); currentDraftValue.set(currentState); }, /** Revert draft and state to initial state */ revertAll() { stateStore.set(initialState); draftStore.set(createDraft(initialState)); currentDraftValue.set(initialState); }, /** Undo last committed change */ undo() { if (undoList.length) { const undo = undoList.pop(); const currentState = get(stateStore); const newState = applyPatches(currentState, undo); stateStore.set(newState); draftStore.set(createDraft(newState)); currentDraftValue.set(newState); } }, /** Refresh `current` draft value (un-proxied) */ refresh() { currentDraftValue.set(current(get(draftStore))); }, current: currentDraftValue, }; const errorsApi = { subscribe: errorsStore.subscribe }; return [storeApi, draftApi, errorsApi]; }