From e3ae2a2b217941be82102347894854f41cb9815f Mon Sep 17 00:00:00 2001 From: David Khourshid Date: Fri, 2 Feb 2024 14:22:56 -0500 Subject: [PATCH] Undo redo example --- examples/readme.md | 4 +- examples/undo-redo/.gitignore | 24 ++ examples/undo-redo/index.html | 13 + examples/undo-redo/package.json | 18 + examples/undo-redo/pnpm-lock.yaml | 556 +++++++++++++++++++++++++++ examples/undo-redo/public/vite.svg | 1 + examples/undo-redo/src/machine.ts | 94 +++++ examples/undo-redo/src/main.ts | 14 + examples/undo-redo/src/style.css | 96 +++++ examples/undo-redo/src/vite-env.d.ts | 1 + examples/undo-redo/tsconfig.json | 23 ++ 11 files changed, 843 insertions(+), 1 deletion(-) create mode 100644 examples/undo-redo/.gitignore create mode 100644 examples/undo-redo/index.html create mode 100644 examples/undo-redo/package.json create mode 100644 examples/undo-redo/pnpm-lock.yaml create mode 100644 examples/undo-redo/public/vite.svg create mode 100644 examples/undo-redo/src/machine.ts create mode 100644 examples/undo-redo/src/main.ts create mode 100644 examples/undo-redo/src/style.css create mode 100644 examples/undo-redo/src/vite-env.d.ts create mode 100644 examples/undo-redo/tsconfig.json diff --git a/examples/readme.md b/examples/readme.md index 2846e07dac..fcaf02341e 100644 --- a/examples/readme.md +++ b/examples/readme.md @@ -5,12 +5,14 @@ These steps assume You've forked the repo and created a branch for your PR. For 1. In the CLI, navigate to the `/examples` folder. Start a [new Vite project](https://vitejs.dev/guide/#scaffolding-your-first-vite-project) using the appropiate template (e.g. `react-ts`) and adding the name of the framework at the end of your example's name: ```bash +cd examples pnpm create vite@latest my-example-react --template react-ts ``` -2. Install `xstate` and the library-specific beta (e.g. `@xstate/react`): +2. Navigate to the project you just created and install `xstate` and any related libraries (e.g. `@xstate/react`): ```bash +cd my-example-react pnpm i xstate @xstate/react ``` diff --git a/examples/undo-redo/.gitignore b/examples/undo-redo/.gitignore new file mode 100644 index 0000000000..a547bf36d8 --- /dev/null +++ b/examples/undo-redo/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/examples/undo-redo/index.html b/examples/undo-redo/index.html new file mode 100644 index 0000000000..44a933506f --- /dev/null +++ b/examples/undo-redo/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite + TS + + +
+ + + diff --git a/examples/undo-redo/package.json b/examples/undo-redo/package.json new file mode 100644 index 0000000000..474a862050 --- /dev/null +++ b/examples/undo-redo/package.json @@ -0,0 +1,18 @@ +{ + "name": "undo-redo", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc && vite build", + "preview": "vite preview" + }, + "devDependencies": { + "typescript": "^5.2.2", + "vite": "^5.0.8" + }, + "dependencies": { + "xstate": "^5.6.0" + } +} diff --git a/examples/undo-redo/pnpm-lock.yaml b/examples/undo-redo/pnpm-lock.yaml new file mode 100644 index 0000000000..f9bd3fa265 --- /dev/null +++ b/examples/undo-redo/pnpm-lock.yaml @@ -0,0 +1,556 @@ +lockfileVersion: '6.0' + +dependencies: + xstate: + specifier: ^5.6.0 + version: registry.npmjs.org/xstate@5.6.0 + +devDependencies: + typescript: + specifier: ^5.2.2 + version: registry.npmjs.org/typescript@5.3.3 + vite: + specifier: ^5.0.8 + version: registry.npmjs.org/vite@5.0.12 + +packages: + + registry.npmjs.org/@esbuild/aix-ppc64@0.19.12: + resolution: {integrity: sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz} + name: '@esbuild/aix-ppc64' + version: 0.19.12 + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + requiresBuild: true + dev: true + optional: true + + registry.npmjs.org/@esbuild/android-arm64@0.19.12: + resolution: {integrity: sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz} + name: '@esbuild/android-arm64' + version: 0.19.12 + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + registry.npmjs.org/@esbuild/android-arm@0.19.12: + resolution: {integrity: sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.12.tgz} + name: '@esbuild/android-arm' + version: 0.19.12 + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + + registry.npmjs.org/@esbuild/android-x64@0.19.12: + resolution: {integrity: sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.12.tgz} + name: '@esbuild/android-x64' + version: 0.19.12 + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: true + optional: true + + registry.npmjs.org/@esbuild/darwin-arm64@0.19.12: + resolution: {integrity: sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz} + name: '@esbuild/darwin-arm64' + version: 0.19.12 + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + registry.npmjs.org/@esbuild/darwin-x64@0.19.12: + resolution: {integrity: sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz} + name: '@esbuild/darwin-x64' + version: 0.19.12 + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + registry.npmjs.org/@esbuild/freebsd-arm64@0.19.12: + resolution: {integrity: sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz} + name: '@esbuild/freebsd-arm64' + version: 0.19.12 + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + registry.npmjs.org/@esbuild/freebsd-x64@0.19.12: + resolution: {integrity: sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz} + name: '@esbuild/freebsd-x64' + version: 0.19.12 + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + registry.npmjs.org/@esbuild/linux-arm64@0.19.12: + resolution: {integrity: sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz} + name: '@esbuild/linux-arm64' + version: 0.19.12 + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + registry.npmjs.org/@esbuild/linux-arm@0.19.12: + resolution: {integrity: sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz} + name: '@esbuild/linux-arm' + version: 0.19.12 + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + registry.npmjs.org/@esbuild/linux-ia32@0.19.12: + resolution: {integrity: sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz} + name: '@esbuild/linux-ia32' + version: 0.19.12 + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + + registry.npmjs.org/@esbuild/linux-loong64@0.19.12: + resolution: {integrity: sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz} + name: '@esbuild/linux-loong64' + version: 0.19.12 + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + registry.npmjs.org/@esbuild/linux-mips64el@0.19.12: + resolution: {integrity: sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz} + name: '@esbuild/linux-mips64el' + version: 0.19.12 + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: true + optional: true + + registry.npmjs.org/@esbuild/linux-ppc64@0.19.12: + resolution: {integrity: sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz} + name: '@esbuild/linux-ppc64' + version: 0.19.12 + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + registry.npmjs.org/@esbuild/linux-riscv64@0.19.12: + resolution: {integrity: sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz} + name: '@esbuild/linux-riscv64' + version: 0.19.12 + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + registry.npmjs.org/@esbuild/linux-s390x@0.19.12: + resolution: {integrity: sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz} + name: '@esbuild/linux-s390x' + version: 0.19.12 + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + + registry.npmjs.org/@esbuild/linux-x64@0.19.12: + resolution: {integrity: sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz} + name: '@esbuild/linux-x64' + version: 0.19.12 + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + registry.npmjs.org/@esbuild/netbsd-x64@0.19.12: + resolution: {integrity: sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz} + name: '@esbuild/netbsd-x64' + version: 0.19.12 + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: true + optional: true + + registry.npmjs.org/@esbuild/openbsd-x64@0.19.12: + resolution: {integrity: sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz} + name: '@esbuild/openbsd-x64' + version: 0.19.12 + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + + registry.npmjs.org/@esbuild/sunos-x64@0.19.12: + resolution: {integrity: sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz} + name: '@esbuild/sunos-x64' + version: 0.19.12 + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: true + optional: true + + registry.npmjs.org/@esbuild/win32-arm64@0.19.12: + resolution: {integrity: sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz} + name: '@esbuild/win32-arm64' + version: 0.19.12 + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + registry.npmjs.org/@esbuild/win32-ia32@0.19.12: + resolution: {integrity: sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz} + name: '@esbuild/win32-ia32' + version: 0.19.12 + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + registry.npmjs.org/@esbuild/win32-x64@0.19.12: + resolution: {integrity: sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz} + name: '@esbuild/win32-x64' + version: 0.19.12 + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + registry.npmjs.org/@rollup/rollup-android-arm-eabi@4.9.6: + resolution: {integrity: sha512-MVNXSSYN6QXOulbHpLMKYi60ppyO13W9my1qogeiAqtjb2yR4LSmfU2+POvDkLzhjYLXz9Rf9+9a3zFHW1Lecg==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.9.6.tgz} + name: '@rollup/rollup-android-arm-eabi' + version: 4.9.6 + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + + registry.npmjs.org/@rollup/rollup-android-arm64@4.9.6: + resolution: {integrity: sha512-T14aNLpqJ5wzKNf5jEDpv5zgyIqcpn1MlwCrUXLrwoADr2RkWA0vOWP4XxbO9aiO3dvMCQICZdKeDrFl7UMClw==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.9.6.tgz} + name: '@rollup/rollup-android-arm64' + version: 4.9.6 + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + registry.npmjs.org/@rollup/rollup-darwin-arm64@4.9.6: + resolution: {integrity: sha512-CqNNAyhRkTbo8VVZ5R85X73H3R5NX9ONnKbXuHisGWC0qRbTTxnF1U4V9NafzJbgGM0sHZpdO83pLPzq8uOZFw==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.9.6.tgz} + name: '@rollup/rollup-darwin-arm64' + version: 4.9.6 + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + registry.npmjs.org/@rollup/rollup-darwin-x64@4.9.6: + resolution: {integrity: sha512-zRDtdJuRvA1dc9Mp6BWYqAsU5oeLixdfUvkTHuiYOHwqYuQ4YgSmi6+/lPvSsqc/I0Omw3DdICx4Tfacdzmhog==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.9.6.tgz} + name: '@rollup/rollup-darwin-x64' + version: 4.9.6 + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf@4.9.6: + resolution: {integrity: sha512-oNk8YXDDnNyG4qlNb6is1ojTOGL/tRhbbKeE/YuccItzerEZT68Z9gHrY3ROh7axDc974+zYAPxK5SH0j/G+QQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.9.6.tgz} + name: '@rollup/rollup-linux-arm-gnueabihf' + version: 4.9.6 + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + registry.npmjs.org/@rollup/rollup-linux-arm64-gnu@4.9.6: + resolution: {integrity: sha512-Z3O60yxPtuCYobrtzjo0wlmvDdx2qZfeAWTyfOjEDqd08kthDKexLpV97KfAeUXPosENKd8uyJMRDfFMxcYkDQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.9.6.tgz} + name: '@rollup/rollup-linux-arm64-gnu' + version: 4.9.6 + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + registry.npmjs.org/@rollup/rollup-linux-arm64-musl@4.9.6: + resolution: {integrity: sha512-gpiG0qQJNdYEVad+1iAsGAbgAnZ8j07FapmnIAQgODKcOTjLEWM9sRb+MbQyVsYCnA0Im6M6QIq6ax7liws6eQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.9.6.tgz} + name: '@rollup/rollup-linux-arm64-musl' + version: 4.9.6 + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu@4.9.6: + resolution: {integrity: sha512-+uCOcvVmFUYvVDr27aiyun9WgZk0tXe7ThuzoUTAukZJOwS5MrGbmSlNOhx1j80GdpqbOty05XqSl5w4dQvcOA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.9.6.tgz} + name: '@rollup/rollup-linux-riscv64-gnu' + version: 4.9.6 + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + registry.npmjs.org/@rollup/rollup-linux-x64-gnu@4.9.6: + resolution: {integrity: sha512-HUNqM32dGzfBKuaDUBqFB7tP6VMN74eLZ33Q9Y1TBqRDn+qDonkAUyKWwF9BR9unV7QUzffLnz9GrnKvMqC/fw==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.9.6.tgz} + name: '@rollup/rollup-linux-x64-gnu' + version: 4.9.6 + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + registry.npmjs.org/@rollup/rollup-linux-x64-musl@4.9.6: + resolution: {integrity: sha512-ch7M+9Tr5R4FK40FHQk8VnML0Szi2KRujUgHXd/HjuH9ifH72GUmw6lStZBo3c3GB82vHa0ZoUfjfcM7JiiMrQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.9.6.tgz} + name: '@rollup/rollup-linux-x64-musl' + version: 4.9.6 + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + registry.npmjs.org/@rollup/rollup-win32-arm64-msvc@4.9.6: + resolution: {integrity: sha512-VD6qnR99dhmTQ1mJhIzXsRcTBvTjbfbGGwKAHcu+52cVl15AC/kplkhxzW/uT0Xl62Y/meBKDZvoJSJN+vTeGA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.9.6.tgz} + name: '@rollup/rollup-win32-arm64-msvc' + version: 4.9.6 + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + registry.npmjs.org/@rollup/rollup-win32-ia32-msvc@4.9.6: + resolution: {integrity: sha512-J9AFDq/xiRI58eR2NIDfyVmTYGyIZmRcvcAoJ48oDld/NTR8wyiPUu2X/v1navJ+N/FGg68LEbX3Ejd6l8B7MQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.9.6.tgz} + name: '@rollup/rollup-win32-ia32-msvc' + version: 4.9.6 + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + registry.npmjs.org/@rollup/rollup-win32-x64-msvc@4.9.6: + resolution: {integrity: sha512-jqzNLhNDvIZOrt69Ce4UjGRpXJBzhUBzawMwnaDAwyHriki3XollsewxWzOzz+4yOFDkuJHtTsZFwMxhYJWmLQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.9.6.tgz} + name: '@rollup/rollup-win32-x64-msvc' + version: 4.9.6 + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + registry.npmjs.org/@types/estree@1.0.5: + resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz} + name: '@types/estree' + version: 1.0.5 + dev: true + + registry.npmjs.org/esbuild@0.19.12: + resolution: {integrity: sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz} + name: esbuild + version: 0.19.12 + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/aix-ppc64': registry.npmjs.org/@esbuild/aix-ppc64@0.19.12 + '@esbuild/android-arm': registry.npmjs.org/@esbuild/android-arm@0.19.12 + '@esbuild/android-arm64': registry.npmjs.org/@esbuild/android-arm64@0.19.12 + '@esbuild/android-x64': registry.npmjs.org/@esbuild/android-x64@0.19.12 + '@esbuild/darwin-arm64': registry.npmjs.org/@esbuild/darwin-arm64@0.19.12 + '@esbuild/darwin-x64': registry.npmjs.org/@esbuild/darwin-x64@0.19.12 + '@esbuild/freebsd-arm64': registry.npmjs.org/@esbuild/freebsd-arm64@0.19.12 + '@esbuild/freebsd-x64': registry.npmjs.org/@esbuild/freebsd-x64@0.19.12 + '@esbuild/linux-arm': registry.npmjs.org/@esbuild/linux-arm@0.19.12 + '@esbuild/linux-arm64': registry.npmjs.org/@esbuild/linux-arm64@0.19.12 + '@esbuild/linux-ia32': registry.npmjs.org/@esbuild/linux-ia32@0.19.12 + '@esbuild/linux-loong64': registry.npmjs.org/@esbuild/linux-loong64@0.19.12 + '@esbuild/linux-mips64el': registry.npmjs.org/@esbuild/linux-mips64el@0.19.12 + '@esbuild/linux-ppc64': registry.npmjs.org/@esbuild/linux-ppc64@0.19.12 + '@esbuild/linux-riscv64': registry.npmjs.org/@esbuild/linux-riscv64@0.19.12 + '@esbuild/linux-s390x': registry.npmjs.org/@esbuild/linux-s390x@0.19.12 + '@esbuild/linux-x64': registry.npmjs.org/@esbuild/linux-x64@0.19.12 + '@esbuild/netbsd-x64': registry.npmjs.org/@esbuild/netbsd-x64@0.19.12 + '@esbuild/openbsd-x64': registry.npmjs.org/@esbuild/openbsd-x64@0.19.12 + '@esbuild/sunos-x64': registry.npmjs.org/@esbuild/sunos-x64@0.19.12 + '@esbuild/win32-arm64': registry.npmjs.org/@esbuild/win32-arm64@0.19.12 + '@esbuild/win32-ia32': registry.npmjs.org/@esbuild/win32-ia32@0.19.12 + '@esbuild/win32-x64': registry.npmjs.org/@esbuild/win32-x64@0.19.12 + dev: true + + registry.npmjs.org/fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz} + name: fsevents + version: 2.3.3 + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + requiresBuild: true + dev: true + optional: true + + registry.npmjs.org/nanoid@3.3.7: + resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz} + name: nanoid + version: 3.3.7 + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + dev: true + + registry.npmjs.org/picocolors@1.0.0: + resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz} + name: picocolors + version: 1.0.0 + dev: true + + registry.npmjs.org/postcss@8.4.33: + resolution: {integrity: sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/postcss/-/postcss-8.4.33.tgz} + name: postcss + version: 8.4.33 + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: registry.npmjs.org/nanoid@3.3.7 + picocolors: registry.npmjs.org/picocolors@1.0.0 + source-map-js: registry.npmjs.org/source-map-js@1.0.2 + dev: true + + registry.npmjs.org/rollup@4.9.6: + resolution: {integrity: sha512-05lzkCS2uASX0CiLFybYfVkwNbKZG5NFQ6Go0VWyogFTXXbR039UVsegViTntkk4OglHBdF54ccApXRRuXRbsg==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/rollup/-/rollup-4.9.6.tgz} + name: rollup + version: 4.9.6 + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + dependencies: + '@types/estree': registry.npmjs.org/@types/estree@1.0.5 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': registry.npmjs.org/@rollup/rollup-android-arm-eabi@4.9.6 + '@rollup/rollup-android-arm64': registry.npmjs.org/@rollup/rollup-android-arm64@4.9.6 + '@rollup/rollup-darwin-arm64': registry.npmjs.org/@rollup/rollup-darwin-arm64@4.9.6 + '@rollup/rollup-darwin-x64': registry.npmjs.org/@rollup/rollup-darwin-x64@4.9.6 + '@rollup/rollup-linux-arm-gnueabihf': registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf@4.9.6 + '@rollup/rollup-linux-arm64-gnu': registry.npmjs.org/@rollup/rollup-linux-arm64-gnu@4.9.6 + '@rollup/rollup-linux-arm64-musl': registry.npmjs.org/@rollup/rollup-linux-arm64-musl@4.9.6 + '@rollup/rollup-linux-riscv64-gnu': registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu@4.9.6 + '@rollup/rollup-linux-x64-gnu': registry.npmjs.org/@rollup/rollup-linux-x64-gnu@4.9.6 + '@rollup/rollup-linux-x64-musl': registry.npmjs.org/@rollup/rollup-linux-x64-musl@4.9.6 + '@rollup/rollup-win32-arm64-msvc': registry.npmjs.org/@rollup/rollup-win32-arm64-msvc@4.9.6 + '@rollup/rollup-win32-ia32-msvc': registry.npmjs.org/@rollup/rollup-win32-ia32-msvc@4.9.6 + '@rollup/rollup-win32-x64-msvc': registry.npmjs.org/@rollup/rollup-win32-x64-msvc@4.9.6 + fsevents: registry.npmjs.org/fsevents@2.3.3 + dev: true + + registry.npmjs.org/source-map-js@1.0.2: + resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz} + name: source-map-js + version: 1.0.2 + engines: {node: '>=0.10.0'} + dev: true + + registry.npmjs.org/typescript@5.3.3: + resolution: {integrity: sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz} + name: typescript + version: 5.3.3 + engines: {node: '>=14.17'} + hasBin: true + dev: true + + registry.npmjs.org/vite@5.0.12: + resolution: {integrity: sha512-4hsnEkG3q0N4Tzf1+t6NdN9dg/L3BM+q8SWgbSPnJvrgH2kgdyzfVJwbR1ic69/4uMJJ/3dqDZZE5/WwqW8U1w==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/vite/-/vite-5.0.12.tgz} + name: vite + version: 5.0.12 + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || >=20.0.0 + less: '*' + lightningcss: ^1.21.0 + sass: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + dependencies: + esbuild: registry.npmjs.org/esbuild@0.19.12 + postcss: registry.npmjs.org/postcss@8.4.33 + rollup: registry.npmjs.org/rollup@4.9.6 + optionalDependencies: + fsevents: registry.npmjs.org/fsevents@2.3.3 + dev: true + + registry.npmjs.org/xstate@5.6.0: + resolution: {integrity: sha512-l62p4ZHM/fkGl68574s1dFzFmY8B3BeOff9EqBZbuonTSOXGx1fWTnh4SHSrS8Vhr5wyRT9afqWliMoO6Q+hUQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/xstate/-/xstate-5.6.0.tgz} + name: xstate + version: 5.6.0 + dev: false diff --git a/examples/undo-redo/public/vite.svg b/examples/undo-redo/public/vite.svg new file mode 100644 index 0000000000..e7b8dfb1b2 --- /dev/null +++ b/examples/undo-redo/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/examples/undo-redo/src/machine.ts b/examples/undo-redo/src/machine.ts new file mode 100644 index 0000000000..6bc7d9b475 --- /dev/null +++ b/examples/undo-redo/src/machine.ts @@ -0,0 +1,94 @@ +import { + ActorLogic, + AnyActorLogic, + EventFrom, + InputFrom, + SnapshotFrom, + assign, + setup +} from 'xstate'; + +export const machine = setup({ + types: { + context: {} as { + items: string[]; + }, + events: {} as { + type: 'item.add'; + item: string; + } + } +}).createMachine({ + context: { + items: [] + }, + on: { + 'item.add': { + actions: assign({ + items: ({ context, event }) => { + return [...context.items, event.item]; + } + }) + } + } +}); + +type ActorLogicWithUndoRedo = ActorLogic< + SnapshotFrom & { + undoStack: SnapshotFrom[]; + redoStack: SnapshotFrom[]; + }, + EventFrom | { type: 'undo' } | { type: 'redo' }, + InputFrom, + any +>; + +export function withUndoRedo( + logic: T +): ActorLogicWithUndoRedo { + return { + ...logic, + transition(snapshot, event, actorScope) { + if (event.type === 'undo') { + const previousSnapshot = snapshot.undoStack.pop(); + + if (previousSnapshot) { + return { + ...previousSnapshot, + undoStack: snapshot.undoStack, + redoStack: [snapshot, ...snapshot.redoStack] + }; + } + + return snapshot; + } + if (event.type === 'redo') { + const nextSnapshot = snapshot.redoStack.pop(); + if (nextSnapshot) { + return { + ...nextSnapshot, + undoStack: [...snapshot.undoStack, snapshot], + redoStack: snapshot.redoStack + }; + } + + return snapshot; + } + + const nextSnapshot = logic.transition(snapshot, event, actorScope); + + return { + ...nextSnapshot, + undoStack: [...snapshot.undoStack, snapshot], + redoStack: [] + }; + }, + getInitialSnapshot(...args) { + return { + ...logic.getInitialSnapshot(...args), + undoStack: [], + redoStack: [] + }; + } + } satisfies ActorLogicWithUndoRedo; +} diff --git a/examples/undo-redo/src/main.ts b/examples/undo-redo/src/main.ts new file mode 100644 index 0000000000..55cf987c9e --- /dev/null +++ b/examples/undo-redo/src/main.ts @@ -0,0 +1,14 @@ +import './style.css'; +import { machine, withUndoRedo } from './machine.ts'; +import { createActor } from 'xstate'; + +const logic = withUndoRedo(machine); +const actor = createActor(logic); +actor.subscribe((s) => console.log(s.context.items)); +actor.start(); +actor.send({ type: 'item.add', item: 'first' }); +actor.send({ type: 'item.add', item: 'second' }); +actor.send({ type: 'item.add', item: 'third' }); +actor.send({ type: 'undo' }); +actor.send({ type: 'undo' }); +actor.send({ type: 'redo' }); diff --git a/examples/undo-redo/src/style.css b/examples/undo-redo/src/style.css new file mode 100644 index 0000000000..f9c7350248 --- /dev/null +++ b/examples/undo-redo/src/style.css @@ -0,0 +1,96 @@ +:root { + font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; + line-height: 1.5; + font-weight: 400; + + color-scheme: light dark; + color: rgba(255, 255, 255, 0.87); + background-color: #242424; + + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +a { + font-weight: 500; + color: #646cff; + text-decoration: inherit; +} +a:hover { + color: #535bf2; +} + +body { + margin: 0; + display: flex; + place-items: center; + min-width: 320px; + min-height: 100vh; +} + +h1 { + font-size: 3.2em; + line-height: 1.1; +} + +#app { + max-width: 1280px; + margin: 0 auto; + padding: 2rem; + text-align: center; +} + +.logo { + height: 6em; + padding: 1.5em; + will-change: filter; + transition: filter 300ms; +} +.logo:hover { + filter: drop-shadow(0 0 2em #646cffaa); +} +.logo.vanilla:hover { + filter: drop-shadow(0 0 2em #3178c6aa); +} + +.card { + padding: 2em; +} + +.read-the-docs { + color: #888; +} + +button { + border-radius: 8px; + border: 1px solid transparent; + padding: 0.6em 1.2em; + font-size: 1em; + font-weight: 500; + font-family: inherit; + background-color: #1a1a1a; + cursor: pointer; + transition: border-color 0.25s; +} +button:hover { + border-color: #646cff; +} +button:focus, +button:focus-visible { + outline: 4px auto -webkit-focus-ring-color; +} + +@media (prefers-color-scheme: light) { + :root { + color: #213547; + background-color: #ffffff; + } + a:hover { + color: #747bff; + } + button { + background-color: #f9f9f9; + } +} diff --git a/examples/undo-redo/src/vite-env.d.ts b/examples/undo-redo/src/vite-env.d.ts new file mode 100644 index 0000000000..11f02fe2a0 --- /dev/null +++ b/examples/undo-redo/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/undo-redo/tsconfig.json b/examples/undo-redo/tsconfig.json new file mode 100644 index 0000000000..75abdef265 --- /dev/null +++ b/examples/undo-redo/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "module": "ESNext", + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"] +}