Merge pull request 'Move to Typescript.' (#4) from feature/typescript into main
Reviewed-on: #4
This commit is contained in:
commit
2c72e5e0c8
16 changed files with 482 additions and 119 deletions
344
package-lock.json
generated
344
package-lock.json
generated
|
@ -8,8 +8,13 @@
|
|||
"name": "a-maze-r",
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"@types/jest": "^29.5.0",
|
||||
"@types/node": "^18.15.11",
|
||||
"@types/react": "^18.0.35",
|
||||
"@types/react-dom": "^18.0.11",
|
||||
"react": "^18.0.0",
|
||||
"react-dom": "^18.0.0"
|
||||
"react-dom": "^18.0.0",
|
||||
"typescript": "^5.0.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"react-scripts": "^5.0.1"
|
||||
|
@ -32,7 +37,6 @@
|
|||
"version": "7.21.4",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz",
|
||||
"integrity": "sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/highlight": "^7.18.6"
|
||||
},
|
||||
|
@ -414,7 +418,6 @@
|
|||
"version": "7.19.1",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz",
|
||||
"integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
|
@ -461,7 +464,6 @@
|
|||
"version": "7.18.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz",
|
||||
"integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/helper-validator-identifier": "^7.18.6",
|
||||
"chalk": "^2.0.0",
|
||||
|
@ -2642,6 +2644,25 @@
|
|||
"node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@jest/expect-utils": {
|
||||
"version": "29.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.5.0.tgz",
|
||||
"integrity": "sha512-fmKzsidoXQT2KwnrwE0SQq3uj8Z763vzR8LnLBwC2qYWEFpjX8daRsk6rHUM1QvNlEW/UJXNXm59ztmJJWs2Mg==",
|
||||
"dependencies": {
|
||||
"jest-get-type": "^29.4.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@jest/expect-utils/node_modules/jest-get-type": {
|
||||
"version": "29.4.3",
|
||||
"resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz",
|
||||
"integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==",
|
||||
"engines": {
|
||||
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@jest/fake-timers": {
|
||||
"version": "27.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz",
|
||||
|
@ -3753,14 +3774,12 @@
|
|||
"node_modules/@types/istanbul-lib-coverage": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz",
|
||||
"integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==",
|
||||
"dev": true
|
||||
"integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g=="
|
||||
},
|
||||
"node_modules/@types/istanbul-lib-report": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz",
|
||||
"integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/istanbul-lib-coverage": "*"
|
||||
}
|
||||
|
@ -3769,11 +3788,246 @@
|
|||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz",
|
||||
"integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/istanbul-lib-report": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/jest": {
|
||||
"version": "29.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.0.tgz",
|
||||
"integrity": "sha512-3Emr5VOl/aoBwnWcH/EFQvlSAmjV+XtV9GGu5mwdYew5vhQh0IUZx/60x0TzHDu09Bi7HMx10t/namdJw5QIcg==",
|
||||
"dependencies": {
|
||||
"expect": "^29.0.0",
|
||||
"pretty-format": "^29.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/jest/node_modules/@jest/schemas": {
|
||||
"version": "29.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.3.tgz",
|
||||
"integrity": "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==",
|
||||
"dependencies": {
|
||||
"@sinclair/typebox": "^0.25.16"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/jest/node_modules/@jest/types": {
|
||||
"version": "29.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@jest/types/-/types-29.5.0.tgz",
|
||||
"integrity": "sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog==",
|
||||
"dependencies": {
|
||||
"@jest/schemas": "^29.4.3",
|
||||
"@types/istanbul-lib-coverage": "^2.0.0",
|
||||
"@types/istanbul-reports": "^3.0.0",
|
||||
"@types/node": "*",
|
||||
"@types/yargs": "^17.0.8",
|
||||
"chalk": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/jest/node_modules/@sinclair/typebox": {
|
||||
"version": "0.25.24",
|
||||
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.24.tgz",
|
||||
"integrity": "sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ=="
|
||||
},
|
||||
"node_modules/@types/jest/node_modules/@types/yargs": {
|
||||
"version": "17.0.24",
|
||||
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz",
|
||||
"integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==",
|
||||
"dependencies": {
|
||||
"@types/yargs-parser": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/jest/node_modules/ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"dependencies": {
|
||||
"color-convert": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/jest/node_modules/chalk": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
||||
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
|
||||
"dependencies": {
|
||||
"ansi-styles": "^4.1.0",
|
||||
"supports-color": "^7.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/chalk?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/jest/node_modules/color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"dependencies": {
|
||||
"color-name": "~1.1.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/jest/node_modules/color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
|
||||
},
|
||||
"node_modules/@types/jest/node_modules/diff-sequences": {
|
||||
"version": "29.4.3",
|
||||
"resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz",
|
||||
"integrity": "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==",
|
||||
"engines": {
|
||||
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/jest/node_modules/expect": {
|
||||
"version": "29.5.0",
|
||||
"resolved": "https://registry.npmjs.org/expect/-/expect-29.5.0.tgz",
|
||||
"integrity": "sha512-yM7xqUrCO2JdpFo4XpM82t+PJBFybdqoQuJLDGeDX2ij8NZzqRHyu3Hp188/JX7SWqud+7t4MUdvcgGBICMHZg==",
|
||||
"dependencies": {
|
||||
"@jest/expect-utils": "^29.5.0",
|
||||
"jest-get-type": "^29.4.3",
|
||||
"jest-matcher-utils": "^29.5.0",
|
||||
"jest-message-util": "^29.5.0",
|
||||
"jest-util": "^29.5.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/jest/node_modules/has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/jest/node_modules/jest-diff": {
|
||||
"version": "29.5.0",
|
||||
"resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.5.0.tgz",
|
||||
"integrity": "sha512-LtxijLLZBduXnHSniy0WMdaHjmQnt3g5sa16W4p0HqukYTTsyTW3GD1q41TyGl5YFXj/5B2U6dlh5FM1LIMgxw==",
|
||||
"dependencies": {
|
||||
"chalk": "^4.0.0",
|
||||
"diff-sequences": "^29.4.3",
|
||||
"jest-get-type": "^29.4.3",
|
||||
"pretty-format": "^29.5.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/jest/node_modules/jest-get-type": {
|
||||
"version": "29.4.3",
|
||||
"resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz",
|
||||
"integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==",
|
||||
"engines": {
|
||||
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/jest/node_modules/jest-matcher-utils": {
|
||||
"version": "29.5.0",
|
||||
"resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.5.0.tgz",
|
||||
"integrity": "sha512-lecRtgm/rjIK0CQ7LPQwzCs2VwW6WAahA55YBuI+xqmhm7LAaxokSB8C97yJeYyT+HvQkH741StzpU41wohhWw==",
|
||||
"dependencies": {
|
||||
"chalk": "^4.0.0",
|
||||
"jest-diff": "^29.5.0",
|
||||
"jest-get-type": "^29.4.3",
|
||||
"pretty-format": "^29.5.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/jest/node_modules/jest-message-util": {
|
||||
"version": "29.5.0",
|
||||
"resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.5.0.tgz",
|
||||
"integrity": "sha512-Kijeg9Dag6CKtIDA7O21zNTACqD5MD/8HfIV8pdD94vFyFuer52SigdC3IQMhab3vACxXMiFk+yMHNdbqtyTGA==",
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.12.13",
|
||||
"@jest/types": "^29.5.0",
|
||||
"@types/stack-utils": "^2.0.0",
|
||||
"chalk": "^4.0.0",
|
||||
"graceful-fs": "^4.2.9",
|
||||
"micromatch": "^4.0.4",
|
||||
"pretty-format": "^29.5.0",
|
||||
"slash": "^3.0.0",
|
||||
"stack-utils": "^2.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/jest/node_modules/jest-util": {
|
||||
"version": "29.5.0",
|
||||
"resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.5.0.tgz",
|
||||
"integrity": "sha512-RYMgG/MTadOr5t8KdhejfvUU82MxsCu5MF6KuDUHl+NuwzUt+Sm6jJWxTJVrDR1j5M/gJVCPKQEpWXY+yIQ6lQ==",
|
||||
"dependencies": {
|
||||
"@jest/types": "^29.5.0",
|
||||
"@types/node": "*",
|
||||
"chalk": "^4.0.0",
|
||||
"ci-info": "^3.2.0",
|
||||
"graceful-fs": "^4.2.9",
|
||||
"picomatch": "^2.2.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/jest/node_modules/pretty-format": {
|
||||
"version": "29.5.0",
|
||||
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz",
|
||||
"integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==",
|
||||
"dependencies": {
|
||||
"@jest/schemas": "^29.4.3",
|
||||
"ansi-styles": "^5.0.0",
|
||||
"react-is": "^18.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/jest/node_modules/pretty-format/node_modules/ansi-styles": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
|
||||
"integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/jest/node_modules/react-is": {
|
||||
"version": "18.2.0",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
|
||||
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
|
||||
},
|
||||
"node_modules/@types/jest/node_modules/supports-color": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||
"dependencies": {
|
||||
"has-flag": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/json-schema": {
|
||||
"version": "7.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
|
||||
|
@ -3795,8 +4049,7 @@
|
|||
"node_modules/@types/node": {
|
||||
"version": "18.15.11",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.11.tgz",
|
||||
"integrity": "sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==",
|
||||
"dev": true
|
||||
"integrity": "sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q=="
|
||||
},
|
||||
"node_modules/@types/parse-json": {
|
||||
"version": "4.0.0",
|
||||
|
@ -3810,6 +4063,11 @@
|
|||
"integrity": "sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/prop-types": {
|
||||
"version": "15.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
|
||||
"integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w=="
|
||||
},
|
||||
"node_modules/@types/q": {
|
||||
"version": "1.5.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.5.tgz",
|
||||
|
@ -3828,6 +4086,24 @@
|
|||
"integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/react": {
|
||||
"version": "18.0.35",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.35.tgz",
|
||||
"integrity": "sha512-6Laome31HpetaIUGFWl1VQ3mdSImwxtFZ39rh059a1MNnKGqBpC88J6NJ8n/Is3Qx7CefDGLgf/KhN/sYCf7ag==",
|
||||
"dependencies": {
|
||||
"@types/prop-types": "*",
|
||||
"@types/scheduler": "*",
|
||||
"csstype": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/react-dom": {
|
||||
"version": "18.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.11.tgz",
|
||||
"integrity": "sha512-O38bPbI2CWtgw/OoQoY+BRelw7uysmXbWvw3nLWO21H1HSh+GOlqPuXshJfjmpNlKiiSDG9cc1JZAaMmVdcTlw==",
|
||||
"dependencies": {
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/resolve": {
|
||||
"version": "1.17.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz",
|
||||
|
@ -3843,6 +4119,11 @@
|
|||
"integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/scheduler": {
|
||||
"version": "0.16.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz",
|
||||
"integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ=="
|
||||
},
|
||||
"node_modules/@types/semver": {
|
||||
"version": "7.3.13",
|
||||
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz",
|
||||
|
@ -3880,8 +4161,7 @@
|
|||
"node_modules/@types/stack-utils": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz",
|
||||
"integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw=="
|
||||
},
|
||||
"node_modules/@types/trusted-types": {
|
||||
"version": "2.0.3",
|
||||
|
@ -3910,8 +4190,7 @@
|
|||
"node_modules/@types/yargs-parser": {
|
||||
"version": "21.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz",
|
||||
"integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==",
|
||||
"dev": true
|
||||
"integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA=="
|
||||
},
|
||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||
"version": "5.58.0",
|
||||
|
@ -4617,7 +4896,6 @@
|
|||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"color-convert": "^1.9.0"
|
||||
},
|
||||
|
@ -5314,7 +5592,6 @@
|
|||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"fill-range": "^7.0.1"
|
||||
},
|
||||
|
@ -5490,7 +5767,6 @@
|
|||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ansi-styles": "^3.2.1",
|
||||
"escape-string-regexp": "^1.0.5",
|
||||
|
@ -5567,7 +5843,6 @@
|
|||
"version": "3.8.0",
|
||||
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz",
|
||||
"integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
|
@ -5650,7 +5925,6 @@
|
|||
"version": "1.9.3",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"color-name": "1.1.3"
|
||||
}
|
||||
|
@ -5658,8 +5932,7 @@
|
|||
"node_modules/color-name": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
|
||||
},
|
||||
"node_modules/colord": {
|
||||
"version": "2.9.3",
|
||||
|
@ -6349,6 +6622,11 @@
|
|||
"integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/csstype": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz",
|
||||
"integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ=="
|
||||
},
|
||||
"node_modules/damerau-levenshtein": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
|
||||
|
@ -6974,7 +7252,6 @@
|
|||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
"integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
}
|
||||
|
@ -8034,7 +8311,6 @@
|
|||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
},
|
||||
|
@ -8684,8 +8960,7 @@
|
|||
"node_modules/graceful-fs": {
|
||||
"version": "4.2.11",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
|
||||
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="
|
||||
},
|
||||
"node_modules/grapheme-splitter": {
|
||||
"version": "1.0.4",
|
||||
|
@ -8745,7 +9020,6 @@
|
|||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||
"integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
|
@ -9415,7 +9689,6 @@
|
|||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.12.0"
|
||||
}
|
||||
|
@ -12345,7 +12618,6 @@
|
|||
"version": "4.0.5",
|
||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
|
||||
"integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"braces": "^3.0.2",
|
||||
"picomatch": "^2.3.1"
|
||||
|
@ -13088,7 +13360,6 @@
|
|||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
||||
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8.6"
|
||||
},
|
||||
|
@ -15879,7 +16150,6 @@
|
|||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
|
||||
"integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
|
@ -16013,7 +16283,6 @@
|
|||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz",
|
||||
"integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"escape-string-regexp": "^2.0.0"
|
||||
},
|
||||
|
@ -16025,7 +16294,6 @@
|
|||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
|
||||
"integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
|
@ -16321,7 +16589,6 @@
|
|||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"has-flag": "^3.0.0"
|
||||
},
|
||||
|
@ -16716,7 +16983,6 @@
|
|||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"is-number": "^7.0.0"
|
||||
},
|
||||
|
@ -16911,17 +17177,15 @@
|
|||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "4.9.5",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
|
||||
"integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"version": "5.0.4",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz",
|
||||
"integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==",
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4.2.0"
|
||||
"node": ">=12.20"
|
||||
}
|
||||
},
|
||||
"node_modules/unbox-primitive": {
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
{
|
||||
"dependencies": {
|
||||
"@types/jest": "^29.5.0",
|
||||
"@types/node": "^18.15.11",
|
||||
"@types/react": "^18.0.35",
|
||||
"@types/react-dom": "^18.0.11",
|
||||
"react": "^18.0.0",
|
||||
"react-dom": "^18.0.0"
|
||||
"react-dom": "^18.0.0",
|
||||
"typescript": "^5.0.4"
|
||||
},
|
||||
"main": "/index.js",
|
||||
"homepage": ".",
|
||||
|
|
|
@ -1,18 +1,13 @@
|
|||
import React, {useReducer} from 'react';
|
||||
import Maze from "./Maze";
|
||||
import InputForm from "./InputForm";
|
||||
import reduce from "./reducer";
|
||||
import MessageBanner from "./MessageBanner";
|
||||
import {useReducer} from 'react';
|
||||
import Maze from "./Maze.tsx";
|
||||
import InputForm from "./InputForm.tsx";
|
||||
import reduce from "./state/reducer.ts";
|
||||
import MessageBanner from "./MessageBanner.tsx";
|
||||
import {INITIAL_STATE} from "./state/state.ts";
|
||||
import {actionToggledShowSolution} from "./state/action.ts";
|
||||
|
||||
export default function App() {
|
||||
const [state, dispatch] = useReducer(reduce, {
|
||||
maze: null,
|
||||
loading: false,
|
||||
errorMessage: null,
|
||||
showSolution: false,
|
||||
userPath: []
|
||||
},
|
||||
undefined);
|
||||
const [state, dispatch] = useReducer(reduce, INITIAL_STATE);
|
||||
const hasValidMaze = !!state.maze;
|
||||
return (
|
||||
<>
|
||||
|
@ -25,10 +20,7 @@ export default function App() {
|
|||
<h1>The Maze ({state.maze.width}x{state.maze.height}, ID: {state.maze.id})</h1>
|
||||
<input type={"checkbox"}
|
||||
onChange={(e) => {
|
||||
dispatch({
|
||||
type: 'toggled_show_solution',
|
||||
value: e.target.checked
|
||||
});
|
||||
dispatch(actionToggledShowSolution(e.target.checked));
|
||||
}}
|
||||
id={"showSolution"}/><label htmlFor="showSolution">Show Solution</label>
|
||||
<Maze state={state}
|
|
@ -1,11 +1,13 @@
|
|||
import React from 'react';
|
||||
import {MazeCell} from "./model/Maze";
|
||||
import Coordinates from "./model/Coordinates";
|
||||
import {actionClickedCell} from "./state/action.ts";
|
||||
|
||||
function isMarked(x, y, marked) {
|
||||
function isMarked(x: number, y: number, marked: Coordinates[]): boolean {
|
||||
return !!marked.find(e => e.x === x && e.y === y);
|
||||
}
|
||||
|
||||
export default function Cell({x, y, state, dispatch}) {
|
||||
const cell = state.maze.grid[y][x];
|
||||
const cell: MazeCell = state.maze.grid[y][x];
|
||||
let classes = "cell r" + y + " c" + x;
|
||||
if (cell.top) classes += " top";
|
||||
if (cell.right) classes += " right";
|
||||
|
@ -19,19 +21,11 @@ export default function Cell({x, y, state, dispatch}) {
|
|||
onMouseEnter={(e) => {
|
||||
const leftPressed = e.buttons & 0x1;
|
||||
if (leftPressed) {
|
||||
dispatch({
|
||||
type: 'clicked_cell',
|
||||
x,
|
||||
y
|
||||
});
|
||||
dispatch(actionClickedCell(x, y));
|
||||
}
|
||||
}}
|
||||
onClick={(e) => {
|
||||
dispatch({
|
||||
type: 'clicked_cell',
|
||||
x,
|
||||
y
|
||||
});
|
||||
dispatch(actionClickedCell(x, y));
|
||||
}}>
|
||||
</div>
|
||||
);
|
|
@ -1,32 +1,25 @@
|
|||
import React, {useState} from 'react';
|
||||
import ValidatingInputNumberField from "./ValidatingInputNumberField";
|
||||
import {useState} from 'react';
|
||||
import ValidatingInputNumberField from "./ValidatingInputNumberField.tsx";
|
||||
import {actionLoadedMaze, actionLoadingFailed, actionStartedLoading} from "./state/action.ts";
|
||||
|
||||
export default function InputForm({state, dispatch}) {
|
||||
const [width, setWidth] = useState(10);
|
||||
const [height, setHeight] = useState(10);
|
||||
const [id, setId] = useState(null);
|
||||
const [id, setId] = useState(null as number);
|
||||
|
||||
const handleSubmit = (e) => {
|
||||
e.preventDefault();
|
||||
dispatch({
|
||||
type: 'started_loading'
|
||||
});
|
||||
dispatch(actionStartedLoading());
|
||||
const url = `https://manuel.friedli.info/labyrinth/create/json?w=${width}&h=${height}&id=${id || ''}`;
|
||||
fetch(url)
|
||||
.then(response => response.json())
|
||||
// .then(result => new Promise(resolve => setTimeout(resolve, 600, result)))
|
||||
.then(result => {
|
||||
dispatch({
|
||||
type: 'loaded_maze',
|
||||
maze: result
|
||||
});
|
||||
dispatch(actionLoadedMaze(result));
|
||||
})
|
||||
.catch(reason => {
|
||||
console.error("Failed to fetch maze data.", reason);
|
||||
dispatch({
|
||||
type: 'loading_failed',
|
||||
reason
|
||||
});
|
||||
dispatch(actionLoadingFailed(reason));
|
||||
});
|
||||
};
|
||||
const validateWidthHeightInput = value => {
|
|
@ -1,5 +1,4 @@
|
|||
import React from 'react';
|
||||
import Cell from "./Cell";
|
||||
import Cell from "./Cell.tsx";
|
||||
|
||||
|
||||
export default function Maze({state, dispatch}) {
|
||||
|
@ -7,9 +6,9 @@ export default function Maze({state, dispatch}) {
|
|||
return <div>No valid maze.</div>
|
||||
}
|
||||
|
||||
let maze = [];
|
||||
let maze: JSX.Element[] = [];
|
||||
for (let y = 0; y < state.maze.height; y++) {
|
||||
let row = [];
|
||||
let row: JSX.Element[] = [];
|
||||
for (let x = 0; x < state.maze.width; x++) {
|
||||
row.push(<Cell key={`${x}x${y}`} x={x} y={y} state={state} dispatch={dispatch}/>)
|
||||
}
|
|
@ -1,10 +1,8 @@
|
|||
import React from "react";
|
||||
import {actionClosedMessageBanner} from "./state/action.ts";
|
||||
|
||||
export default function MessageBanner({state, dispatch}) {
|
||||
function handleClose() {
|
||||
dispatch({
|
||||
type: 'closed_message_banner'
|
||||
})
|
||||
dispatch(actionClosedMessageBanner());
|
||||
}
|
||||
|
||||
if (!!state.errorMessage) {
|
12
src/index.js
12
src/index.js
|
@ -1,12 +0,0 @@
|
|||
import React, { StrictMode } from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import "./styles.css";
|
||||
|
||||
import App from "./App";
|
||||
|
||||
const root = createRoot(document.getElementById("root"));
|
||||
root.render(
|
||||
<StrictMode>
|
||||
<App />
|
||||
</StrictMode>
|
||||
);
|
12
src/index.tsx
Normal file
12
src/index.tsx
Normal file
|
@ -0,0 +1,12 @@
|
|||
import {StrictMode} from "react";
|
||||
import {createRoot, Root} from "react-dom/client";
|
||||
import "./styles.css";
|
||||
import App from "./App.tsx";
|
||||
|
||||
|
||||
const root: Root = createRoot(document.getElementById("root"));
|
||||
root.render(
|
||||
<StrictMode>
|
||||
<App/>
|
||||
</StrictMode>
|
||||
);
|
4
src/model/Coordinates.ts
Normal file
4
src/model/Coordinates.ts
Normal file
|
@ -0,0 +1,4 @@
|
|||
export default interface Coordinates {
|
||||
x: number,
|
||||
y: number
|
||||
}
|
18
src/model/Maze.ts
Normal file
18
src/model/Maze.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
import Coordinates from "./Coordinates";
|
||||
|
||||
export default interface Maze {
|
||||
id: string,
|
||||
width: number,
|
||||
height: number,
|
||||
start: Coordinates,
|
||||
end: Coordinates,
|
||||
grid: MazeCell[][]
|
||||
}
|
||||
|
||||
export interface MazeCell {
|
||||
top: boolean,
|
||||
right: boolean,
|
||||
bottom: boolean,
|
||||
left: boolean,
|
||||
solution: boolean
|
||||
}
|
60
src/state/action.ts
Normal file
60
src/state/action.ts
Normal file
|
@ -0,0 +1,60 @@
|
|||
import Maze from "../model/Maze";
|
||||
|
||||
export interface Action {
|
||||
type: string,
|
||||
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
export const ID_ACTION_STARTED_LOADING = 'started_loading';
|
||||
|
||||
export function actionStartedLoading(): Action {
|
||||
return {
|
||||
type: ID_ACTION_STARTED_LOADING
|
||||
}
|
||||
}
|
||||
|
||||
export const ID_ACTION_LOADED_MAZE = 'loaded_maze';
|
||||
|
||||
export function actionLoadedMaze(maze: Maze): Action {
|
||||
return {
|
||||
type: ID_ACTION_LOADED_MAZE,
|
||||
maze
|
||||
}
|
||||
}
|
||||
|
||||
export const ID_ACTION_LOADING_FAILED = 'loading_failed';
|
||||
|
||||
export function actionLoadingFailed(reason: string): Action {
|
||||
return {
|
||||
type: ID_ACTION_LOADING_FAILED,
|
||||
reason
|
||||
};
|
||||
}
|
||||
|
||||
export const ID_ACTION_TOGGLED_SHOW_SOLUTION = 'toggled_show_solution';
|
||||
|
||||
export function actionToggledShowSolution(value: boolean): Action {
|
||||
return {
|
||||
type: ID_ACTION_TOGGLED_SHOW_SOLUTION,
|
||||
value
|
||||
}
|
||||
}
|
||||
|
||||
export const ID_ACTION_CLOSED_MESSAGE_BANNER = 'closed_message_banner';
|
||||
|
||||
export function actionClosedMessageBanner(): Action {
|
||||
return {
|
||||
type: ID_ACTION_CLOSED_MESSAGE_BANNER
|
||||
}
|
||||
}
|
||||
|
||||
export const ID_ACTION_CLICKED_CELL = 'clicked_cell';
|
||||
|
||||
export function actionClickedCell(x: number, y: number): Action {
|
||||
return {
|
||||
type: ID_ACTION_CLICKED_CELL,
|
||||
x,
|
||||
y
|
||||
}
|
||||
}
|
|
@ -1,8 +1,18 @@
|
|||
import handleUserClicked from "./userpathhandler";
|
||||
import handleUserClicked from "./userpathhandler.ts";
|
||||
import {State} from "./state";
|
||||
import {
|
||||
Action,
|
||||
ID_ACTION_CLICKED_CELL,
|
||||
ID_ACTION_CLOSED_MESSAGE_BANNER,
|
||||
ID_ACTION_LOADED_MAZE,
|
||||
ID_ACTION_LOADING_FAILED,
|
||||
ID_ACTION_STARTED_LOADING,
|
||||
ID_ACTION_TOGGLED_SHOW_SOLUTION
|
||||
} from "./action.ts";
|
||||
|
||||
export default function reduce(state, action) {
|
||||
export default function reduce(state: State, action: Action) {
|
||||
switch (action.type) {
|
||||
case 'started_loading': {
|
||||
case ID_ACTION_STARTED_LOADING: {
|
||||
return {
|
||||
...state,
|
||||
maze: null,
|
||||
|
@ -10,7 +20,7 @@ export default function reduce(state, action) {
|
|||
errorMessage: null
|
||||
}
|
||||
}
|
||||
case 'loaded_maze': {
|
||||
case ID_ACTION_LOADED_MAZE: {
|
||||
return {
|
||||
...state,
|
||||
loading: false,
|
||||
|
@ -18,26 +28,26 @@ export default function reduce(state, action) {
|
|||
userPath: []
|
||||
}
|
||||
}
|
||||
case 'loading_failed': {
|
||||
case ID_ACTION_LOADING_FAILED: {
|
||||
return {
|
||||
...state,
|
||||
loading: false,
|
||||
errorMessage: `Failed to load maze. Reason: ${action.reason}`
|
||||
}
|
||||
}
|
||||
case 'toggled_show_solution': {
|
||||
case ID_ACTION_TOGGLED_SHOW_SOLUTION: {
|
||||
return {
|
||||
...state,
|
||||
showSolution: action.value
|
||||
}
|
||||
}
|
||||
case 'closed_message_banner': {
|
||||
case ID_ACTION_CLOSED_MESSAGE_BANNER: {
|
||||
return {
|
||||
...state,
|
||||
errorMessage: null
|
||||
}
|
||||
}
|
||||
case 'clicked_cell': {
|
||||
case ID_ACTION_CLICKED_CELL: {
|
||||
// There's so much logic involved, externalize that into its own file.
|
||||
return handleUserClicked(state, action.x, action.y);
|
||||
}
|
18
src/state/state.ts
Normal file
18
src/state/state.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
import Coordinates from "../model/Coordinates";
|
||||
import Maze from "../model/Maze";
|
||||
|
||||
export interface State {
|
||||
errorMessage: string | null,
|
||||
loading: boolean,
|
||||
maze: Maze | null,
|
||||
showSolution: boolean,
|
||||
userPath: Coordinates[]
|
||||
}
|
||||
|
||||
export const INITIAL_STATE: State = {
|
||||
errorMessage: null,
|
||||
loading: false,
|
||||
maze: null,
|
||||
showSolution: false,
|
||||
userPath: []
|
||||
};
|
|
@ -1,12 +1,19 @@
|
|||
export default function handleUserClicked(state, x, y) {
|
||||
import {State} from "./state";
|
||||
import Coordinates from "../model/Coordinates";
|
||||
import {MazeCell} from "../model/Maze";
|
||||
|
||||
export default function handleUserClicked(state: State, x: number, y: number): State {
|
||||
if (isClickAllowed(x, y, state)) {
|
||||
// Okay, we clicked a cell that's adjacent to the end of the userpath (or which IS the end of the userpath)
|
||||
// and that's not blocked by a wall. Now let's see.
|
||||
if (-1 === state.userPath.findIndex(step => step.x === x && step.y === y)) {
|
||||
// The clicked cell is not yet part of the userpath --> add it.
|
||||
// If it's the end tile, also show a congratulation message
|
||||
const showMessage = x === state.maze.end.x && y === state.maze.end.y;
|
||||
return {
|
||||
...state,
|
||||
userPath: [...state.userPath, {x: x, y: y}]
|
||||
userPath: [...state.userPath, {x, y}],
|
||||
errorMessage: showMessage ? "Congratulations! You won!" : state.errorMessage
|
||||
};
|
||||
} else {
|
||||
// The clicked cell IS part of the userpath. Is it the last cell of it?
|
||||
|
@ -15,7 +22,8 @@ export default function handleUserClicked(state, x, y) {
|
|||
// Yes, it's the last cell of the userpath --> remove it.
|
||||
return {
|
||||
...state,
|
||||
userPath: state.userPath.filter(step => step.x !== x || step.y !== y)
|
||||
userPath: state.userPath.filter(step => step.x !== x || step.y !== y),
|
||||
errorMessage: null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +32,7 @@ export default function handleUserClicked(state, x, y) {
|
|||
return state;
|
||||
}
|
||||
|
||||
function isClickAllowed(x, y, state) {
|
||||
function isClickAllowed(x: number, y: number, state: State): boolean {
|
||||
const lastCoordsFromUserPath = getLastCoordsFromUserPath(state);
|
||||
if (!lastCoordsFromUserPath) {
|
||||
// when nothing has been marked yet, we can only toggle the starting position
|
||||
|
@ -61,11 +69,11 @@ function isClickAllowed(x, y, state) {
|
|||
return false;
|
||||
}
|
||||
|
||||
function getCellAt(coords, state) {
|
||||
function getCellAt(coords: Coordinates, state: State): MazeCell {
|
||||
return state.maze.grid[coords.y][coords.x];
|
||||
}
|
||||
|
||||
function getLastCoordsFromUserPath(state) {
|
||||
function getLastCoordsFromUserPath(state: State): Coordinates | null {
|
||||
if (state.userPath.length > 0) {
|
||||
return state.userPath[state.userPath.length - 1];
|
||||
}
|
Loading…
Reference in a new issue