Move to Typescript. #4
					 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", |       "name": "a-maze-r", | ||||||
|       "version": "0.0.0", |       "version": "0.0.0", | ||||||
|       "dependencies": { |       "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": "^18.0.0", | ||||||
|         "react-dom": "^18.0.0" |         "react-dom": "^18.0.0", | ||||||
|  |         "typescript": "^5.0.4" | ||||||
|       }, |       }, | ||||||
|       "devDependencies": { |       "devDependencies": { | ||||||
|         "react-scripts": "^5.0.1" |         "react-scripts": "^5.0.1" | ||||||
|  | @ -32,7 +37,6 @@ | ||||||
|       "version": "7.21.4", |       "version": "7.21.4", | ||||||
|       "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz", |       "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz", | ||||||
|       "integrity": "sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==", |       "integrity": "sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==", | ||||||
|       "dev": true, |  | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
|         "@babel/highlight": "^7.18.6" |         "@babel/highlight": "^7.18.6" | ||||||
|       }, |       }, | ||||||
|  | @ -414,7 +418,6 @@ | ||||||
|       "version": "7.19.1", |       "version": "7.19.1", | ||||||
|       "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", |       "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", | ||||||
|       "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", |       "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", | ||||||
|       "dev": true, |  | ||||||
|       "engines": { |       "engines": { | ||||||
|         "node": ">=6.9.0" |         "node": ">=6.9.0" | ||||||
|       } |       } | ||||||
|  | @ -461,7 +464,6 @@ | ||||||
|       "version": "7.18.6", |       "version": "7.18.6", | ||||||
|       "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", |       "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", | ||||||
|       "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", |       "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", | ||||||
|       "dev": true, |  | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
|         "@babel/helper-validator-identifier": "^7.18.6", |         "@babel/helper-validator-identifier": "^7.18.6", | ||||||
|         "chalk": "^2.0.0", |         "chalk": "^2.0.0", | ||||||
|  | @ -2642,6 +2644,25 @@ | ||||||
|         "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" |         "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": { |     "node_modules/@jest/fake-timers": { | ||||||
|       "version": "27.5.1", |       "version": "27.5.1", | ||||||
|       "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz", |       "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz", | ||||||
|  | @ -3753,14 +3774,12 @@ | ||||||
|     "node_modules/@types/istanbul-lib-coverage": { |     "node_modules/@types/istanbul-lib-coverage": { | ||||||
|       "version": "2.0.4", |       "version": "2.0.4", | ||||||
|       "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", |       "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", | ||||||
|       "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", |       "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==" | ||||||
|       "dev": true |  | ||||||
|     }, |     }, | ||||||
|     "node_modules/@types/istanbul-lib-report": { |     "node_modules/@types/istanbul-lib-report": { | ||||||
|       "version": "3.0.0", |       "version": "3.0.0", | ||||||
|       "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", |       "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", | ||||||
|       "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", |       "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", | ||||||
|       "dev": true, |  | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
|         "@types/istanbul-lib-coverage": "*" |         "@types/istanbul-lib-coverage": "*" | ||||||
|       } |       } | ||||||
|  | @ -3769,11 +3788,246 @@ | ||||||
|       "version": "3.0.1", |       "version": "3.0.1", | ||||||
|       "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", |       "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", | ||||||
|       "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", |       "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", | ||||||
|       "dev": true, |  | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
|         "@types/istanbul-lib-report": "*" |         "@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": { |     "node_modules/@types/json-schema": { | ||||||
|       "version": "7.0.11", |       "version": "7.0.11", | ||||||
|       "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", |       "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", | ||||||
|  | @ -3795,8 +4049,7 @@ | ||||||
|     "node_modules/@types/node": { |     "node_modules/@types/node": { | ||||||
|       "version": "18.15.11", |       "version": "18.15.11", | ||||||
|       "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.11.tgz", |       "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.11.tgz", | ||||||
|       "integrity": "sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==", |       "integrity": "sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==" | ||||||
|       "dev": true |  | ||||||
|     }, |     }, | ||||||
|     "node_modules/@types/parse-json": { |     "node_modules/@types/parse-json": { | ||||||
|       "version": "4.0.0", |       "version": "4.0.0", | ||||||
|  | @ -3810,6 +4063,11 @@ | ||||||
|       "integrity": "sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==", |       "integrity": "sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==", | ||||||
|       "dev": true |       "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": { |     "node_modules/@types/q": { | ||||||
|       "version": "1.5.5", |       "version": "1.5.5", | ||||||
|       "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.5.tgz", |       "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.5.tgz", | ||||||
|  | @ -3828,6 +4086,24 @@ | ||||||
|       "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", |       "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", | ||||||
|       "dev": true |       "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": { |     "node_modules/@types/resolve": { | ||||||
|       "version": "1.17.1", |       "version": "1.17.1", | ||||||
|       "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", |       "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", | ||||||
|  | @ -3843,6 +4119,11 @@ | ||||||
|       "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", |       "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", | ||||||
|       "dev": true |       "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": { |     "node_modules/@types/semver": { | ||||||
|       "version": "7.3.13", |       "version": "7.3.13", | ||||||
|       "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", |       "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", | ||||||
|  | @ -3880,8 +4161,7 @@ | ||||||
|     "node_modules/@types/stack-utils": { |     "node_modules/@types/stack-utils": { | ||||||
|       "version": "2.0.1", |       "version": "2.0.1", | ||||||
|       "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", |       "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", | ||||||
|       "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", |       "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==" | ||||||
|       "dev": true |  | ||||||
|     }, |     }, | ||||||
|     "node_modules/@types/trusted-types": { |     "node_modules/@types/trusted-types": { | ||||||
|       "version": "2.0.3", |       "version": "2.0.3", | ||||||
|  | @ -3910,8 +4190,7 @@ | ||||||
|     "node_modules/@types/yargs-parser": { |     "node_modules/@types/yargs-parser": { | ||||||
|       "version": "21.0.0", |       "version": "21.0.0", | ||||||
|       "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", |       "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", | ||||||
|       "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", |       "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==" | ||||||
|       "dev": true |  | ||||||
|     }, |     }, | ||||||
|     "node_modules/@typescript-eslint/eslint-plugin": { |     "node_modules/@typescript-eslint/eslint-plugin": { | ||||||
|       "version": "5.58.0", |       "version": "5.58.0", | ||||||
|  | @ -4617,7 +4896,6 @@ | ||||||
|       "version": "3.2.1", |       "version": "3.2.1", | ||||||
|       "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", |       "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", | ||||||
|       "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", |       "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", | ||||||
|       "dev": true, |  | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
|         "color-convert": "^1.9.0" |         "color-convert": "^1.9.0" | ||||||
|       }, |       }, | ||||||
|  | @ -5314,7 +5592,6 @@ | ||||||
|       "version": "3.0.2", |       "version": "3.0.2", | ||||||
|       "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", |       "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", | ||||||
|       "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", |       "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", | ||||||
|       "dev": true, |  | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
|         "fill-range": "^7.0.1" |         "fill-range": "^7.0.1" | ||||||
|       }, |       }, | ||||||
|  | @ -5490,7 +5767,6 @@ | ||||||
|       "version": "2.4.2", |       "version": "2.4.2", | ||||||
|       "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", |       "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", | ||||||
|       "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", |       "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", | ||||||
|       "dev": true, |  | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
|         "ansi-styles": "^3.2.1", |         "ansi-styles": "^3.2.1", | ||||||
|         "escape-string-regexp": "^1.0.5", |         "escape-string-regexp": "^1.0.5", | ||||||
|  | @ -5567,7 +5843,6 @@ | ||||||
|       "version": "3.8.0", |       "version": "3.8.0", | ||||||
|       "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", |       "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", | ||||||
|       "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", |       "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", | ||||||
|       "dev": true, |  | ||||||
|       "funding": [ |       "funding": [ | ||||||
|         { |         { | ||||||
|           "type": "github", |           "type": "github", | ||||||
|  | @ -5650,7 +5925,6 @@ | ||||||
|       "version": "1.9.3", |       "version": "1.9.3", | ||||||
|       "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", |       "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", | ||||||
|       "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", |       "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", | ||||||
|       "dev": true, |  | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
|         "color-name": "1.1.3" |         "color-name": "1.1.3" | ||||||
|       } |       } | ||||||
|  | @ -5658,8 +5932,7 @@ | ||||||
|     "node_modules/color-name": { |     "node_modules/color-name": { | ||||||
|       "version": "1.1.3", |       "version": "1.1.3", | ||||||
|       "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", |       "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", | ||||||
|       "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", |       "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" | ||||||
|       "dev": true |  | ||||||
|     }, |     }, | ||||||
|     "node_modules/colord": { |     "node_modules/colord": { | ||||||
|       "version": "2.9.3", |       "version": "2.9.3", | ||||||
|  | @ -6349,6 +6622,11 @@ | ||||||
|       "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", |       "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", | ||||||
|       "dev": true |       "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": { |     "node_modules/damerau-levenshtein": { | ||||||
|       "version": "1.0.8", |       "version": "1.0.8", | ||||||
|       "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", |       "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", | ||||||
|  | @ -6974,7 +7252,6 @@ | ||||||
|       "version": "1.0.5", |       "version": "1.0.5", | ||||||
|       "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", |       "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", | ||||||
|       "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", |       "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", | ||||||
|       "dev": true, |  | ||||||
|       "engines": { |       "engines": { | ||||||
|         "node": ">=0.8.0" |         "node": ">=0.8.0" | ||||||
|       } |       } | ||||||
|  | @ -8034,7 +8311,6 @@ | ||||||
|       "version": "7.0.1", |       "version": "7.0.1", | ||||||
|       "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", |       "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", | ||||||
|       "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", |       "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", | ||||||
|       "dev": true, |  | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
|         "to-regex-range": "^5.0.1" |         "to-regex-range": "^5.0.1" | ||||||
|       }, |       }, | ||||||
|  | @ -8684,8 +8960,7 @@ | ||||||
|     "node_modules/graceful-fs": { |     "node_modules/graceful-fs": { | ||||||
|       "version": "4.2.11", |       "version": "4.2.11", | ||||||
|       "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", |       "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", | ||||||
|       "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", |       "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" | ||||||
|       "dev": true |  | ||||||
|     }, |     }, | ||||||
|     "node_modules/grapheme-splitter": { |     "node_modules/grapheme-splitter": { | ||||||
|       "version": "1.0.4", |       "version": "1.0.4", | ||||||
|  | @ -8745,7 +9020,6 @@ | ||||||
|       "version": "3.0.0", |       "version": "3.0.0", | ||||||
|       "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", |       "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", | ||||||
|       "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", |       "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", | ||||||
|       "dev": true, |  | ||||||
|       "engines": { |       "engines": { | ||||||
|         "node": ">=4" |         "node": ">=4" | ||||||
|       } |       } | ||||||
|  | @ -9415,7 +9689,6 @@ | ||||||
|       "version": "7.0.0", |       "version": "7.0.0", | ||||||
|       "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", |       "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", | ||||||
|       "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", |       "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", | ||||||
|       "dev": true, |  | ||||||
|       "engines": { |       "engines": { | ||||||
|         "node": ">=0.12.0" |         "node": ">=0.12.0" | ||||||
|       } |       } | ||||||
|  | @ -12345,7 +12618,6 @@ | ||||||
|       "version": "4.0.5", |       "version": "4.0.5", | ||||||
|       "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", |       "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", | ||||||
|       "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", |       "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", | ||||||
|       "dev": true, |  | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
|         "braces": "^3.0.2", |         "braces": "^3.0.2", | ||||||
|         "picomatch": "^2.3.1" |         "picomatch": "^2.3.1" | ||||||
|  | @ -13088,7 +13360,6 @@ | ||||||
|       "version": "2.3.1", |       "version": "2.3.1", | ||||||
|       "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", |       "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", | ||||||
|       "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", |       "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", | ||||||
|       "dev": true, |  | ||||||
|       "engines": { |       "engines": { | ||||||
|         "node": ">=8.6" |         "node": ">=8.6" | ||||||
|       }, |       }, | ||||||
|  | @ -15879,7 +16150,6 @@ | ||||||
|       "version": "3.0.0", |       "version": "3.0.0", | ||||||
|       "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", |       "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", | ||||||
|       "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", |       "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", | ||||||
|       "dev": true, |  | ||||||
|       "engines": { |       "engines": { | ||||||
|         "node": ">=8" |         "node": ">=8" | ||||||
|       } |       } | ||||||
|  | @ -16013,7 +16283,6 @@ | ||||||
|       "version": "2.0.6", |       "version": "2.0.6", | ||||||
|       "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", |       "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", | ||||||
|       "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", |       "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", | ||||||
|       "dev": true, |  | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
|         "escape-string-regexp": "^2.0.0" |         "escape-string-regexp": "^2.0.0" | ||||||
|       }, |       }, | ||||||
|  | @ -16025,7 +16294,6 @@ | ||||||
|       "version": "2.0.0", |       "version": "2.0.0", | ||||||
|       "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", |       "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", | ||||||
|       "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", |       "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", | ||||||
|       "dev": true, |  | ||||||
|       "engines": { |       "engines": { | ||||||
|         "node": ">=8" |         "node": ">=8" | ||||||
|       } |       } | ||||||
|  | @ -16321,7 +16589,6 @@ | ||||||
|       "version": "5.5.0", |       "version": "5.5.0", | ||||||
|       "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", |       "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", | ||||||
|       "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", |       "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", | ||||||
|       "dev": true, |  | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
|         "has-flag": "^3.0.0" |         "has-flag": "^3.0.0" | ||||||
|       }, |       }, | ||||||
|  | @ -16716,7 +16983,6 @@ | ||||||
|       "version": "5.0.1", |       "version": "5.0.1", | ||||||
|       "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", |       "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", | ||||||
|       "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", |       "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", | ||||||
|       "dev": true, |  | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
|         "is-number": "^7.0.0" |         "is-number": "^7.0.0" | ||||||
|       }, |       }, | ||||||
|  | @ -16911,17 +17177,15 @@ | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "node_modules/typescript": { |     "node_modules/typescript": { | ||||||
|       "version": "4.9.5", |       "version": "5.0.4", | ||||||
|       "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", |       "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", | ||||||
|       "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", |       "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", | ||||||
|       "dev": true, |  | ||||||
|       "peer": true, |  | ||||||
|       "bin": { |       "bin": { | ||||||
|         "tsc": "bin/tsc", |         "tsc": "bin/tsc", | ||||||
|         "tsserver": "bin/tsserver" |         "tsserver": "bin/tsserver" | ||||||
|       }, |       }, | ||||||
|       "engines": { |       "engines": { | ||||||
|         "node": ">=4.2.0" |         "node": ">=12.20" | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "node_modules/unbox-primitive": { |     "node_modules/unbox-primitive": { | ||||||
|  |  | ||||||
|  | @ -1,7 +1,12 @@ | ||||||
| { | { | ||||||
|   "dependencies": { |   "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": "^18.0.0", | ||||||
|     "react-dom": "^18.0.0" |     "react-dom": "^18.0.0", | ||||||
|  |     "typescript": "^5.0.4" | ||||||
|   }, |   }, | ||||||
|   "main": "/index.js", |   "main": "/index.js", | ||||||
|   "homepage": ".", |   "homepage": ".", | ||||||
|  |  | ||||||
|  | @ -1,18 +1,13 @@ | ||||||
| import React, {useReducer} from 'react'; | import {useReducer} from 'react'; | ||||||
| import Maze from "./Maze"; | import Maze from "./Maze.tsx"; | ||||||
| import InputForm from "./InputForm"; | import InputForm from "./InputForm.tsx"; | ||||||
| import reduce from "./reducer"; | import reduce from "./state/reducer.ts"; | ||||||
| import MessageBanner from "./MessageBanner"; | import MessageBanner from "./MessageBanner.tsx"; | ||||||
|  | import {INITIAL_STATE} from "./state/state.ts"; | ||||||
|  | import {actionToggledShowSolution} from "./state/action.ts"; | ||||||
| 
 | 
 | ||||||
| export default function App() { | export default function App() { | ||||||
|     const [state, dispatch] = useReducer(reduce, { |     const [state, dispatch] = useReducer(reduce, INITIAL_STATE); | ||||||
|             maze: null, |  | ||||||
|             loading: false, |  | ||||||
|             errorMessage: null, |  | ||||||
|             showSolution: false, |  | ||||||
|             userPath: [] |  | ||||||
|         }, |  | ||||||
|         undefined); |  | ||||||
|     const hasValidMaze = !!state.maze; |     const hasValidMaze = !!state.maze; | ||||||
|     return ( |     return ( | ||||||
|         <> |         <> | ||||||
|  | @ -25,10 +20,7 @@ export default function App() { | ||||||
|                     <h1>The Maze ({state.maze.width}x{state.maze.height}, ID: {state.maze.id})</h1> |                     <h1>The Maze ({state.maze.width}x{state.maze.height}, ID: {state.maze.id})</h1> | ||||||
|                     <input type={"checkbox"} |                     <input type={"checkbox"} | ||||||
|                            onChange={(e) => { |                            onChange={(e) => { | ||||||
|                                dispatch({ |                                dispatch(actionToggledShowSolution(e.target.checked)); | ||||||
|                                    type: 'toggled_show_solution', |  | ||||||
|                                    value: e.target.checked |  | ||||||
|                                }); |  | ||||||
|                            }} |                            }} | ||||||
|                            id={"showSolution"}/><label htmlFor="showSolution">Show Solution</label> |                            id={"showSolution"}/><label htmlFor="showSolution">Show Solution</label> | ||||||
|                     <Maze state={state} |                     <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); |     return !!marked.find(e => e.x === x && e.y === y); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export default function Cell({x, y, state, dispatch}) { | 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; |     let classes = "cell r" + y + " c" + x; | ||||||
|     if (cell.top) classes += " top"; |     if (cell.top) classes += " top"; | ||||||
|     if (cell.right) classes += " right"; |     if (cell.right) classes += " right"; | ||||||
|  | @ -19,19 +21,11 @@ export default function Cell({x, y, state, dispatch}) { | ||||||
|              onMouseEnter={(e) => { |              onMouseEnter={(e) => { | ||||||
|                  const leftPressed = e.buttons & 0x1; |                  const leftPressed = e.buttons & 0x1; | ||||||
|                  if (leftPressed) { |                  if (leftPressed) { | ||||||
|                      dispatch({ |                      dispatch(actionClickedCell(x, y)); | ||||||
|                          type: 'clicked_cell', |  | ||||||
|                          x, |  | ||||||
|                          y |  | ||||||
|                      }); |  | ||||||
|                  } |                  } | ||||||
|              }} |              }} | ||||||
|              onClick={(e) => { |              onClick={(e) => { | ||||||
|                  dispatch({ |                  dispatch(actionClickedCell(x, y)); | ||||||
|                      type: 'clicked_cell', |  | ||||||
|                      x, |  | ||||||
|                      y |  | ||||||
|                  }); |  | ||||||
|              }}> |              }}> | ||||||
|         </div> |         </div> | ||||||
|     ); |     ); | ||||||
|  | @ -1,32 +1,25 @@ | ||||||
| import React, {useState} from 'react'; | import {useState} from 'react'; | ||||||
| import ValidatingInputNumberField from "./ValidatingInputNumberField"; | import ValidatingInputNumberField from "./ValidatingInputNumberField.tsx"; | ||||||
|  | import {actionLoadedMaze, actionLoadingFailed, actionStartedLoading} from "./state/action.ts"; | ||||||
| 
 | 
 | ||||||
| export default function InputForm({state, dispatch}) { | export default function InputForm({state, dispatch}) { | ||||||
|     const [width, setWidth] = useState(10); |     const [width, setWidth] = useState(10); | ||||||
|     const [height, setHeight] = useState(10); |     const [height, setHeight] = useState(10); | ||||||
|     const [id, setId] = useState(null); |     const [id, setId] = useState(null as number); | ||||||
| 
 | 
 | ||||||
|     const handleSubmit = (e) => { |     const handleSubmit = (e) => { | ||||||
|         e.preventDefault(); |         e.preventDefault(); | ||||||
|         dispatch({ |         dispatch(actionStartedLoading()); | ||||||
|             type: 'started_loading' |  | ||||||
|         }); |  | ||||||
|         const url = `https://manuel.friedli.info/labyrinth/create/json?w=${width}&h=${height}&id=${id || ''}`; |         const url = `https://manuel.friedli.info/labyrinth/create/json?w=${width}&h=${height}&id=${id || ''}`; | ||||||
|         fetch(url) |         fetch(url) | ||||||
|             .then(response => response.json()) |             .then(response => response.json()) | ||||||
|             // .then(result => new Promise(resolve => setTimeout(resolve, 600, result)))
 |             // .then(result => new Promise(resolve => setTimeout(resolve, 600, result)))
 | ||||||
|             .then(result => { |             .then(result => { | ||||||
|                 dispatch({ |                 dispatch(actionLoadedMaze(result)); | ||||||
|                     type: 'loaded_maze', |  | ||||||
|                     maze: result |  | ||||||
|                 }); |  | ||||||
|             }) |             }) | ||||||
|             .catch(reason => { |             .catch(reason => { | ||||||
|                 console.error("Failed to fetch maze data.", reason); |                 console.error("Failed to fetch maze data.", reason); | ||||||
|                 dispatch({ |                 dispatch(actionLoadingFailed(reason)); | ||||||
|                     type: 'loading_failed', |  | ||||||
|                     reason |  | ||||||
|                 }); |  | ||||||
|             }); |             }); | ||||||
|     }; |     }; | ||||||
|     const validateWidthHeightInput = value => { |     const validateWidthHeightInput = value => { | ||||||
|  | @ -1,5 +1,4 @@ | ||||||
| import React from 'react'; | import Cell from "./Cell.tsx"; | ||||||
| import Cell from "./Cell"; |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| export default function Maze({state, dispatch}) { | export default function Maze({state, dispatch}) { | ||||||
|  | @ -7,9 +6,9 @@ export default function Maze({state, dispatch}) { | ||||||
|         return <div>No valid maze.</div> |         return <div>No valid maze.</div> | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     let maze = []; |     let maze: JSX.Element[] = []; | ||||||
|     for (let y = 0; y < state.maze.height; y++) { |     for (let y = 0; y < state.maze.height; y++) { | ||||||
|         let row = []; |         let row: JSX.Element[] = []; | ||||||
|         for (let x = 0; x < state.maze.width; x++) { |         for (let x = 0; x < state.maze.width; x++) { | ||||||
|             row.push(<Cell key={`${x}x${y}`} x={x} y={y} state={state} dispatch={dispatch}/>) |             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}) { | export default function MessageBanner({state, dispatch}) { | ||||||
|     function handleClose() { |     function handleClose() { | ||||||
|         dispatch({ |         dispatch(actionClosedMessageBanner()); | ||||||
|             type: 'closed_message_banner' |  | ||||||
|         }) |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (!!state.errorMessage) { |     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) { |     switch (action.type) { | ||||||
|         case 'started_loading': { |         case ID_ACTION_STARTED_LOADING: { | ||||||
|             return { |             return { | ||||||
|                 ...state, |                 ...state, | ||||||
|                 maze: null, |                 maze: null, | ||||||
|  | @ -10,7 +20,7 @@ export default function reduce(state, action) { | ||||||
|                 errorMessage: null |                 errorMessage: null | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         case 'loaded_maze': { |         case ID_ACTION_LOADED_MAZE: { | ||||||
|             return { |             return { | ||||||
|                 ...state, |                 ...state, | ||||||
|                 loading: false, |                 loading: false, | ||||||
|  | @ -18,26 +28,26 @@ export default function reduce(state, action) { | ||||||
|                 userPath: [] |                 userPath: [] | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         case 'loading_failed': { |         case ID_ACTION_LOADING_FAILED: { | ||||||
|             return { |             return { | ||||||
|                 ...state, |                 ...state, | ||||||
|                 loading: false, |                 loading: false, | ||||||
|                 errorMessage: `Failed to load maze. Reason: ${action.reason}` |                 errorMessage: `Failed to load maze. Reason: ${action.reason}` | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         case 'toggled_show_solution': { |         case ID_ACTION_TOGGLED_SHOW_SOLUTION: { | ||||||
|             return { |             return { | ||||||
|                 ...state, |                 ...state, | ||||||
|                 showSolution: action.value |                 showSolution: action.value | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         case 'closed_message_banner': { |         case ID_ACTION_CLOSED_MESSAGE_BANNER: { | ||||||
|             return { |             return { | ||||||
|                 ...state, |                 ...state, | ||||||
|                 errorMessage: null |                 errorMessage: null | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         case 'clicked_cell': { |         case ID_ACTION_CLICKED_CELL: { | ||||||
|             // There's so much logic involved, externalize that into its own file.
 |             // There's so much logic involved, externalize that into its own file.
 | ||||||
|             return handleUserClicked(state, action.x, action.y); |             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)) { |     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)
 |         // 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.
 |         // and that's not blocked by a wall. Now let's see.
 | ||||||
|         if (-1 === state.userPath.findIndex(step => step.x === x && step.y === y)) { |         if (-1 === state.userPath.findIndex(step => step.x === x && step.y === y)) { | ||||||
|             // The clicked cell is not yet part of the userpath --> add it.
 |             // 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 { |             return { | ||||||
|                 ...state, |                 ...state, | ||||||
|                 userPath: [...state.userPath, {x: x, y: y}] |                 userPath: [...state.userPath, {x, y}], | ||||||
|  |                 errorMessage: showMessage ? "Congratulations! You won!" : state.errorMessage | ||||||
|             }; |             }; | ||||||
|         } else { |         } else { | ||||||
|             // The clicked cell IS part of the userpath. Is it the last cell of it?
 |             // 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.
 |                 // Yes, it's the last cell of the userpath --> remove it.
 | ||||||
|                 return { |                 return { | ||||||
|                     ...state, |                     ...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; |     return state; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function isClickAllowed(x, y, state) { | function isClickAllowed(x: number, y: number, state: State): boolean { | ||||||
|     const lastCoordsFromUserPath = getLastCoordsFromUserPath(state); |     const lastCoordsFromUserPath = getLastCoordsFromUserPath(state); | ||||||
|     if (!lastCoordsFromUserPath) { |     if (!lastCoordsFromUserPath) { | ||||||
|         // when nothing has been marked yet, we can only toggle the starting position
 |         // when nothing has been marked yet, we can only toggle the starting position
 | ||||||
|  | @ -61,11 +69,11 @@ function isClickAllowed(x, y, state) { | ||||||
|     return false; |     return false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function getCellAt(coords, state) { | function getCellAt(coords: Coordinates, state: State): MazeCell { | ||||||
|     return state.maze.grid[coords.y][coords.x]; |     return state.maze.grid[coords.y][coords.x]; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function getLastCoordsFromUserPath(state) { | function getLastCoordsFromUserPath(state: State): Coordinates | null { | ||||||
|     if (state.userPath.length > 0) { |     if (state.userPath.length > 0) { | ||||||
|         return state.userPath[state.userPath.length - 1]; |         return state.userPath[state.userPath.length - 1]; | ||||||
|     } |     } | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue