From 9fc6bd721061123a6851f0591cf79f6c84a615e8 Mon Sep 17 00:00:00 2001 From: Charles Kornoelje <33156025+charkour@users.noreply.github.com> Date: Thu, 1 Apr 2021 20:25:46 -0400 Subject: [PATCH] add useUndo and undo middleware --- package.json | 5 +++- src/index.js | 34 ++++++++++++++++++++++++ src/index.tsx | 15 ----------- stories/Thing.stories.tsx | 55 +++++++++++++++++++++++++++++++++++---- yarn.lock | 5 ++++ 5 files changed, 93 insertions(+), 21 deletions(-) create mode 100644 src/index.js delete mode 100644 src/index.tsx diff --git a/package.json b/package.json index 307c77c..bc1a63a 100644 --- a/package.json +++ b/package.json @@ -67,5 +67,8 @@ "path": "dist/zundo.esm.js", "limit": "10 KB" } - ] + ], + "dependencies": { + "zustand": "^3.3.3" + } } diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..a38681e --- /dev/null +++ b/src/index.js @@ -0,0 +1,34 @@ + +import createVanilla from "zustand/vanilla"; +import create from "zustand"; + +// original implementation +// https://stackblitz.com/edit/react-bcql2z + +// use immer patches? https://immerjs.github.io/immer/patches/ + +// Stores previous actions +const undoStore = createVanilla((set, get) => ({ + prevActions: [], + undo: () => { + get().handle(get().prevActions.pop()); + }, + handle: undefined +})); +const { getState, setState, subscribe, destroy } = undoStore; +export const useUndo = create(undoStore); + +// custom middleware to get previous state +export const undo = config => (set, get, api) => + config( + args => { + setState({ + prevActions: [...getState().prevActions, { ...get() }], + handle: set + }); + set(args); + console.log(" new state", get()); + }, + get, + api + ); \ No newline at end of file diff --git a/src/index.tsx b/src/index.tsx deleted file mode 100644 index 4487cc0..0000000 --- a/src/index.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import React, { FC, HTMLAttributes, ReactChild } from 'react'; - -export interface Props extends HTMLAttributes { - /** custom content, defaults to 'the snozzberries taste like snozzberries' */ - children?: ReactChild; -} - -// Please do not use types off of a default export module or else Storybook Docs will suffer. -// see: https://github.com/storybookjs/storybook/issues/9556 -/** - * A custom Thing component. Neat! - */ -export const Thing: FC = ({ children }) => { - return
{children || `the snozzberries taste like snozzberries`}
; -}; diff --git a/stories/Thing.stories.tsx b/stories/Thing.stories.tsx index 3e9f7e6..4bbb5c0 100644 --- a/stories/Thing.stories.tsx +++ b/stories/Thing.stories.tsx @@ -1,10 +1,10 @@ -import React from 'react'; +import React, { useState } from 'react'; import { Meta, Story } from '@storybook/react'; -import { Thing, Props } from '../src'; +import { undo, useUndo } from '../src'; +import create from 'zustand'; const meta: Meta = { - title: 'Welcome', - component: Thing, + title: 'Demo', argTypes: { children: { control: { @@ -19,7 +19,52 @@ const meta: Meta = { export default meta; -const Template: Story = args => ; +// create a store with undo middleware +const useStoreWithUndo = create( + undo(set => ({ + bees: 0, + text: "", + incrementBees: () => set(state => (state.bees += 1)), + decrementBees: () => set(state => (state.bees -= 1)), + submitText: text => set({ text }) + })) +); + +const App = () => { + const { prevActions, undo } = useUndo(); + const { + bees, + incrementBees, + decrementBees, + submitText, + text + } = useStoreWithUndo(); + const [inputText, setInputText] = useState(""); + + return ( +
+

🐻 ♻️ Zustand undo!

+ actions stack: {JSON.stringify(prevActions)} +
+
+ bees: {bees} +
+ + +
+
+ setInputText(e.target.value)} /> +
+ +
+ text: {text} +
+ +
+ ); +} + +const Template: Story<{}> = args => ; // By passing using the Args format for exported stories, you can control the props for a component for reuse in a test // https://storybook.js.org/docs/react/workflows/unit-testing diff --git a/yarn.lock b/yarn.lock index af2d96a..8d61307 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13414,6 +13414,11 @@ yocto-queue@^0.1.0: resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== +zustand@^3.3.3: + version "3.3.3" + resolved "https://registry.yarnpkg.com/zustand/-/zustand-3.3.3.tgz#88b930a873d0f13e406f96958c1409645ea8b370" + integrity sha512-KTN/O76rVc9muDoprsCDe/LQjbuq+GHYt5JdYahuXaGZ+8Gyk44SepzTFeQTF5J+b8+/Q+o90BaSEQ3WImKPog== + zwitch@^1.0.0: version "1.0.5" resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-1.0.5.tgz#d11d7381ffed16b742f6af7b3f223d5cd9fe9920"