diff --git a/leaky-ships/components/xstate/example.tsx b/leaky-ships/components/xstate/example.tsx
new file mode 100644
index 0000000..706f84e
--- /dev/null
+++ b/leaky-ships/components/xstate/example.tsx
@@ -0,0 +1,27 @@
+import { useMachine } from '@xstate/react';
+import { createMachine } from 'xstate';
+
+const toggleMachine = createMachine({
+ id: 'toggle',
+ initial: 'inactive',
+ states: {
+ inactive: {
+ on: { TOGGLE: 'active' }
+ },
+ active: {
+ on: { TOGGLE: 'inactive' }
+ }
+ }
+});
+
+export const Toggler = () => {
+ const [state, send] = useMachine(toggleMachine);
+
+ return (
+
+ );
+};
diff --git a/leaky-ships/components/xstate/test.tsx b/leaky-ships/components/xstate/test.tsx
new file mode 100644
index 0000000..9965213
--- /dev/null
+++ b/leaky-ships/components/xstate/test.tsx
@@ -0,0 +1,64 @@
+import { useMachine } from '@xstate/react';
+import { createMachine } from 'xstate';
+
+const toggleMachine =
+ /** @xstate-layout N4IgpgJg5mDOIC5QBcD2UoBswDoCSAdgJbIDEAtgJ4AqArgE4EDaADALqKgAOqsJRqApxAAPRAFoALADYcATjkB2SQFYVclSwBMW9SoA0ISolWKcKgMzbpARkUtJADkdbpAXzeG0GbPmJkwAjAqOkZWDiQQHj5kASFIsQRxaRYcVUcLORtM6SdJCxtDYwQLRxt5FS1HB0UbFmlpTMkPL3QsXAB3AEMSADFUelCCUjARMABjWmQwIfDhaP5BYUSbOpwtCwLNepZtFjsixAt1ddctbIUHSpsWkG92nG6+gaGRggg5yIXYpYSTFVktWkujkGRYjkkkkOCFM5isrjsDmcrlu918T2Q-XoAFEglQRmNJtNZux5rxFvFQIldJIcAVMpoZHZ8lpFNDjnJTsDGRZFGpVKi2uiepiBrjgpQ3h9SV9yT9KaJ-oCbNzQVYIVCjEdWWljsi5Ls5JI+SoPJ4QARUBA4MI0WAyTE4ssJBtOY4UsdFDobOpJEpoSrHDhpNs5I1dpIbDoLIKfLhCCQHRTnUkbFkcO6WJ7vb7-VqYTZabU+ZsDSwsopYw8MVihkn5SnA8GVBlpHILDJTCHoX7yiwvdyIRlFLyq8Lnji8cVuHKnX8EDZqmkjQV++q+ZrirpZD79vtXWn1GPcLAABaoDq4iAAZXG9DAgXrc6piDUnOkjkUZUUI4Ucl07JLvYrJhg05zKLoZpuEAA */
+ createMachine({
+ predictableActionArguments: true,
+ id: 'toggle',
+ initial: "Init",
+ context: {
+ player: 1
+ },
+ states: {
+ Init: {
+ on: {
+ myTurn: "waitForTurn",
+ enemyTurn: "waitForEnemy",
+ }
+ },
+ waitForTurn: {
+ entry: ["enableUI"],
+ exit: ["disableUI"],
+ on: {
+ executeTurn: { target: "waitForEnemy", actions: ["switchPlayers"] },
+ end: "showEndScreen"
+ }
+ },
+ waitForEnemy: {
+ on: {
+ executeTurn: { target: "waitForTurn", actions: ["switchPlayers"] },
+ end: "showEndScreen"
+ }
+ },
+ showEndScreen: {
+ type: "final"
+ }
+ }
+ },
+ {
+ actions: {
+ switchPlayers: (context, event) => {
+ return context.player ? 0 : 1
+ },
+ enableUI: (context, event) => { },
+ disableUI: (context, event) => { }
+ }
+ }
+ );
+
+export const XStateTest = () => {
+ const [state, send] = useMachine(toggleMachine);
+
+ return (
+
+ {JSON.stringify({
+ value: state.value,
+ context: state.context
+ }, null, 2)}
+ {state.nextEvents.map((event, i) =>
+
+
)}
+
+ );
+};
\ No newline at end of file
diff --git a/leaky-ships/package-lock.json b/leaky-ships/package-lock.json
index 21e8a9c..6f19b2f 100644
--- a/leaky-ships/package-lock.json
+++ b/leaky-ships/package-lock.json
@@ -20,6 +20,7 @@
"@types/node": "18.11.18",
"@types/react": "18.0.26",
"@types/react-dom": "18.0.10",
+ "@xstate/react": "^3.0.2",
"classnames": "^2.3.2",
"eslint": "8.31.0",
"eslint-config-next": "13.1.1",
@@ -27,7 +28,8 @@
"react": "18.2.0",
"react-dom": "18.2.0",
"socket.io-client": "^4.5.4",
- "typescript": "4.9.4"
+ "typescript": "4.9.4",
+ "xstate": "^4.35.2"
},
"devDependencies": {
"@types/web-bluetooth": "^0.0.16",
@@ -628,6 +630,28 @@
"url": "https://opencollective.com/typescript-eslint"
}
},
+ "node_modules/@xstate/react": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@xstate/react/-/react-3.0.2.tgz",
+ "integrity": "sha512-sFbnMyi+FHF6bXbdvOF6RKVJ9VxrhhUz7KJ/8qKwpqFs0h+EoGOXdfAeuS3aEy29JsFaRclozBxDpsEJd/vlkg==",
+ "dependencies": {
+ "use-isomorphic-layout-effect": "^1.0.0",
+ "use-sync-external-store": "^1.0.0"
+ },
+ "peerDependencies": {
+ "@xstate/fsm": "^2.0.0",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0",
+ "xstate": "^4.35.2"
+ },
+ "peerDependenciesMeta": {
+ "@xstate/fsm": {
+ "optional": true
+ },
+ "xstate": {
+ "optional": true
+ }
+ }
+ },
"node_modules/acorn": {
"version": "8.8.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz",
@@ -3410,6 +3434,27 @@
"punycode": "^2.1.0"
}
},
+ "node_modules/use-isomorphic-layout-effect": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz",
+ "integrity": "sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==",
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/use-sync-external-store": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
+ "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==",
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
@@ -3499,6 +3544,15 @@
"node": ">=0.4.0"
}
},
+ "node_modules/xstate": {
+ "version": "4.35.2",
+ "resolved": "https://registry.npmjs.org/xstate/-/xstate-4.35.2.tgz",
+ "integrity": "sha512-5X7EyJv5OHHtGQwN7DsmCAbSnDs3Mxl1cXQ4PVaLwi+7p/RRapERnd1dFyHjYin+KQoLLfuXpl1dPBThgyIGNg==",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/xstate"
+ }
+ },
"node_modules/yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
@@ -3881,6 +3935,15 @@
"eslint-visitor-keys": "^3.3.0"
}
},
+ "@xstate/react": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@xstate/react/-/react-3.0.2.tgz",
+ "integrity": "sha512-sFbnMyi+FHF6bXbdvOF6RKVJ9VxrhhUz7KJ/8qKwpqFs0h+EoGOXdfAeuS3aEy29JsFaRclozBxDpsEJd/vlkg==",
+ "requires": {
+ "use-isomorphic-layout-effect": "^1.0.0",
+ "use-sync-external-store": "^1.0.0"
+ }
+ },
"acorn": {
"version": "8.8.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz",
@@ -5821,6 +5884,18 @@
"punycode": "^2.1.0"
}
},
+ "use-isomorphic-layout-effect": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz",
+ "integrity": "sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==",
+ "requires": {}
+ },
+ "use-sync-external-store": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
+ "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==",
+ "requires": {}
+ },
"which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
@@ -5875,6 +5950,11 @@
"resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz",
"integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A=="
},
+ "xstate": {
+ "version": "4.35.2",
+ "resolved": "https://registry.npmjs.org/xstate/-/xstate-4.35.2.tgz",
+ "integrity": "sha512-5X7EyJv5OHHtGQwN7DsmCAbSnDs3Mxl1cXQ4PVaLwi+7p/RRapERnd1dFyHjYin+KQoLLfuXpl1dPBThgyIGNg=="
+ },
"yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
diff --git a/leaky-ships/package.json b/leaky-ships/package.json
index 03e4c91..6acef93 100644
--- a/leaky-ships/package.json
+++ b/leaky-ships/package.json
@@ -21,6 +21,7 @@
"@types/node": "18.11.18",
"@types/react": "18.0.26",
"@types/react-dom": "18.0.10",
+ "@xstate/react": "^3.0.2",
"classnames": "^2.3.2",
"eslint": "8.31.0",
"eslint-config-next": "13.1.1",
@@ -28,7 +29,8 @@
"react": "18.2.0",
"react-dom": "18.2.0",
"socket.io-client": "^4.5.4",
- "typescript": "4.9.4"
+ "typescript": "4.9.4",
+ "xstate": "^4.35.2"
},
"devDependencies": {
"@types/web-bluetooth": "^0.0.16",
diff --git a/leaky-ships/pages/index.tsx b/leaky-ships/pages/index.tsx
index 7d57233..2c05552 100644
--- a/leaky-ships/pages/index.tsx
+++ b/leaky-ships/pages/index.tsx
@@ -1,5 +1,6 @@
import Head from 'next/head'
import Link from 'next/link'
+import { XStateTest } from '../components/xstate/test'
export default function Home() {
return (
@@ -16,6 +17,7 @@ export default function Home() {
Grid Effect
Grid Effect with Content
SocketIO
+
>
)