Repository: QCHackers/tqec
Pull request #133 (2024-02-09 20:38:32)

Add redux; update package.json and eslintrc
Address https://github.com/QCHackers/tqec/issues/132. No functional changes.
* Provide sample reducer for the app
* Create redux store using the reducer
* Surround `App` with store provider
* Update `package.json` and `package-lock.json` to accommodate redux installation
* Update `axios` version
* Remove dangling comma from `eslintrc`


Patch:
diff --git a/frontend/.eslintrc.json b/frontend/.eslintrc.json
index be442c4b..ca36cf8d 100644
--- a/frontend/.eslintrc.json
+++ b/frontend/.eslintrc.json
@@ -23,6 +23,6 @@
 		"react/jsx-indent": "off",
 		"react/jsx-indent-props": "off",
 		"react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }],
-		"comma-dangle": ["error", "only-multiline"],
+		"comma-dangle": ["error", "only-multiline"]
 	}
 }
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index 62f42d0e..f8d58ee0 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -11,11 +11,12 @@
 				"@pixi/filter-drop-shadow": "^5.2.0",
 				"@pixi/react": "^7.1.1",
 				"@pixi/ui": "^0.10.1",
+				"@reduxjs/toolkit": "^2.1.0",
 				"@testing-library/jest-dom": "^5.17.0",
 				"@testing-library/react": "^13.4.0",
 				"@testing-library/user-event": "^13.5.0",
 				"assert": "^2.1.0",
-				"axios": "^0.24.0",
+				"axios": "^1.6.7",
 				"install": "^0.13.0",
 				"npm": "^10.2.5",
 				"pixi-filters": "^5.2.1",
@@ -23,7 +24,9 @@
 				"react": "^18.2.0",
 				"react-dom": "^18.2.0",
 				"react-pixi-fiber": "^1.0.6",
+				"react-redux": "^9.1.0",
 				"react-scripts": "5.0.1",
+				"redux": "^5.0.1",
 				"web-vitals": "^2.1.4"
 			},
 			"devDependencies": {
@@ -190,9 +193,9 @@
 			}
 		},
 		"node_modules/@babel/eslint-parser": {
-			"version": "7.23.9",
-			"resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.23.9.tgz",
-			"integrity": "sha512-xPndlO7qxiJbn0ATvfXQBjCS7qApc9xmKHArgI/FTEFxXas5dnjC/VqM37lfZun9dclRYcn+YQAr6uDFy0bB2g==",
+			"version": "7.23.10",
+			"resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.23.10.tgz",
+			"integrity": "sha512-3wSYDPZVnhseRnxRJH6ZVTNknBz76AEnyC+AYYhasjP3Yy23qz0ERR7Fcd2SHmYuSFJ2kY9gaaDd3vyqU09eSw==",
 			"dependencies": {
 				"@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1",
 				"eslint-visitor-keys": "^2.1.0",
@@ -266,9 +269,9 @@
 			}
 		},
 		"node_modules/@babel/helper-create-class-features-plugin": {
-			"version": "7.23.9",
-			"resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.23.9.tgz",
-			"integrity": "sha512-B2L9neXTIyPQoXDm+NtovPvG6VOLWnaXu3BIeVDWwdKFgG30oNa6CqVGiJPDWQwIAK49t9gnQI9c6K6RzabiKw==",
+			"version": "7.23.10",
+			"resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.23.10.tgz",
+			"integrity": "sha512-2XpP2XhkXzgxecPNEEK8Vz8Asj9aRxt08oKOqtiZoqV2UGZ5T+EkyP9sXQ9nwMxBIG34a7jmasVqoMop7VdPUw==",
 			"dependencies": {
 				"@babel/helper-annotate-as-pure": "^7.22.5",
 				"@babel/helper-environment-visitor": "^7.22.20",
@@ -3464,39 +3467,39 @@
 			}
 		},
 		"node_modules/@pixi/accessibility": {
-			"version": "7.3.3",
-			"resolved": "https://registry.npmjs.org/@pixi/accessibility/-/accessibility-7.3.3.tgz",
-			"integrity": "sha512-cHiIEP54RNqvPKmi45HvvnTbiWU+/lzdTY0zK7OXx3TmcEQRn2A7GZ1I+uxx476NeXGJtGSvv3copyxFjPB6Ew==",
+			"version": "7.4.0",
+			"resolved": "https://registry.npmjs.org/@pixi/accessibility/-/accessibility-7.4.0.tgz",
+			"integrity": "sha512-muosfpn333YNz2s7mtoVlKvcXswFOJ4r+5rePn3r/95KQIpuB+xX6pETuzGq0p8uOpKxtkNokGj5s2dyM0blHA==",
 			"peerDependencies": {
-				"@pixi/core": "7.3.3",
-				"@pixi/display": "7.3.3",
-				"@pixi/events": "7.3.3"
+				"@pixi/core": "7.4.0",
+				"@pixi/display": "7.4.0",
+				"@pixi/events": "7.4.0"
 			}
 		},
 		"node_modules/@pixi/app": {
-			"version": "7.3.3",
-			"resolved": "https://registry.npmjs.org/@pixi/app/-/app-7.3.3.tgz",
-			"integrity": "sha512-MS5r/yU0CrWMPXXrgKAzgC2KC35Och8fT9z6J1XUCs7yHhdO8768rnSePJuzhj9Yaclv7PUpNQzh8rG9o/MzkQ==",
+			"version": "7.4.0",
+			"resolved": "https://registry.npmjs.org/@pixi/app/-/app-7.4.0.tgz",
+			"integrity": "sha512-9pDB974rfuObG5YHvR7kdWhDiIV26b0GeC4vHRQB3bkmltguMi8SCQ9WQKH3WwRLaflzf9EMZpgX10cU1gLgKg==",
 			"peerDependencies": {
-				"@pixi/core": "7.3.3",
-				"@pixi/display": "7.3.3"
+				"@pixi/core": "7.4.0",
+				"@pixi/display": "7.4.0"
 			}
 		},
 		"node_modules/@pixi/assets": {
-			"version": "7.3.3",
-			"resolved": "https://registry.npmjs.org/@pixi/assets/-/assets-7.3.3.tgz",
-			"integrity": "sha512-KcLXVehdJ2kc2bSnTfatLPLL6sLD7dwU+EZ5bWQ/PZDSsfML3kLFvq84VXd4k8LKNX4RCvfy4yeeIUW1o5tnMg==",
+			"version": "7.4.0",
+			"resolved": "https://registry.npmjs.org/@pixi/assets/-/assets-7.4.0.tgz",
+			"integrity": "sha512-Z7J2ZYSZ41Pr3CK0IXgtVV1HiLm1sG0AOZHAPMwB82wNdIDvmWowo/LkXvQmSHFLxFlEz1hWOdOFs1daWAeIfg==",
 			"dependencies": {
 				"@types/css-font-loading-module": "^0.0.12"
 			},
 			"peerDependencies": {
-				"@pixi/core": "7.3.3"
+				"@pixi/core": "7.4.0"
 			}
 		},
 		"node_modules/@pixi/color": {
-			"version": "7.3.3",
-			"resolved": "https://registry.npmjs.org/@pixi/color/-/color-7.3.3.tgz",
-			"integrity": "sha512-IiiFhNIqXt7yULe0Wkq5Hn38ymDoEen/6EvV2y2AQIOu6TyuET5PGswAdMfG7ZjfwBaCudK6yQEUjWaXbgRUmw==",
+			"version": "7.4.0",
+			"resolved": "https://registry.npmjs.org/@pixi/color/-/color-7.4.0.tgz",
+			"integrity": "sha512-Qgn3OSW9SFCQ8wrm524anENwIAeRTORC014LkTqaBQrpuOUHrx11SCy4kNFaQyZWO1DCTe4m8g/foCK7zJM7cg==",
 			"dependencies": {
 				"@pixi/colord": "^2.9.6"
 			}
@@ -3507,33 +3510,32 @@
 			"integrity": "sha512-nezytU2pw587fQstUu1AsJZDVEynjskwOL+kibwcdxsMBFqPsFFNA7xl0ii/gXuDi6M0xj3mfRJj8pBSc2jCfA=="
 		},
 		"node_modules/@pixi/compressed-textures": {
-			"version": "7.3.3",
-			"resolved": "https://registry.npmjs.org/@pixi/compressed-textures/-/compressed-textures-7.3.3.tgz",
-			"integrity": "sha512-4h1NKePF5blN7qux29yEnKiGdk4vZif59XtLviW7Y3r9MKgKSoizDl0RqU4SKo4eC1P0jpt1qOjiG4TE+AjXGQ==",
+			"version": "7.4.0",
+			"resolved": "https://registry.npmjs.org/@pixi/compressed-textures/-/compressed-textures-7.4.0.tgz",
+			"integrity": "sha512-M9bpOFeUPuss57mbRtJOD8cGh+X8xsfx8YMBqWzQTAfbA8hsTQ+O4arbMTyIxqZnaTvpmhlhTKwaVaI2V15NAg==",
 			"peerDependencies": {
-				"@pixi/assets": "7.3.3",
-				"@pixi/core": "7.3.3"
+				"@pixi/assets": "7.4.0",
+				"@pixi/core": "7.4.0"
 			}
 		},
 		"node_modules/@pixi/constants": {
-			"version": "7.3.3",
-			"resolved": "https://registry.npmjs.org/@pixi/constants/-/constants-7.3.3.tgz",
-			"integrity": "sha512-ww1JdekmKBUqHyPq8A5L+86FkzpS4KidlBm9wkX1fcd+6QQzq/vbx1JOz6m3CmH5LnlmDZ+zysLezvpZlBcwwA=="
+			"version": "7.4.0",
+			"resolved": "https://registry.npmjs.org/@pixi/constants/-/constants-7.4.0.tgz",
+			"integrity": "sha512-jQMPMRqkOTjI4D0cHWqvu+pofw6bIa8861x2vp2kNsmM2zcBO/b01AlmILi5pEDk0nTumgzgmVHZ7dtT9KxfQw=="
 		},
 		"node_modules/@pixi/core": {
-			"version": "7.3.3",
-			"resolved": "https://registry.npmjs.org/@pixi/core/-/core-7.3.3.tgz",
-			"integrity": "sha512-064tuK6NoGIl/2Wf4EUlaLLlnRMZuDdLqnISsj2/A70towg2QUWgHhwZsCB4NvAssidWu/sIT+vk5IKDmh1LKA==",
+			"version": "7.4.0",
+			"resolved": "https://registry.npmjs.org/@pixi/core/-/core-7.4.0.tgz",
+			"integrity": "sha512-X6UiDzmdd2oRK3zQggDrWNIlw5rjZakByRIwI6MRgj17FGkpNkCY78dO1snZ6qnpUoo5M03aSUCFCfq6LKA5Bg==",
 			"dependencies": {
-				"@pixi/color": "7.3.3",
-				"@pixi/constants": "7.3.3",
-				"@pixi/extensions": "7.3.3",
-				"@pixi/math": "7.3.3",
-				"@pixi/runner": "7.3.3",
-				"@pixi/settings": "7.3.3",
-				"@pixi/ticker": "7.3.3",
-				"@pixi/utils": "7.3.3",
-				"@types/offscreencanvas": "^2019.6.4"
+				"@pixi/color": "7.4.0",
+				"@pixi/constants": "7.4.0",
+				"@pixi/extensions": "7.4.0",
+				"@pixi/math": "7.4.0",
+				"@pixi/runner": "7.4.0",
+				"@pixi/settings": "7.4.0",
+				"@pixi/ticker": "7.4.0",
+				"@pixi/utils": "7.4.0"
 			},
 			"funding": {
 				"type": "opencollective",
@@ -3541,33 +3543,33 @@
 			}
 		},
 		"node_modules/@pixi/display": {
-			"version": "7.3.3",
-			"resolved": "https://registry.npmjs.org/@pixi/display/-/display-7.3.3.tgz",
-			"integrity": "sha512-iULZ2E6Z4vhI0FypXpUbtA+CODnj/CuTt2pi9gsw00ILI12eEx76cAiazvhxnCNqcfmj1RRK2P6s9Vzr5WmEIg==",
+			"version": "7.4.0",
+			"resolved": "https://registry.npmjs.org/@pixi/display/-/display-7.4.0.tgz",
+			"integrity": "sha512-l+K6H9CqB2tQltpaxal3dIPPAOWhBWszrJm5EbK5sVVQFcaWXgeS/Hmniz0DhT7OpPmstcx4nii9hZgRkmMmEg==",
 			"peerDependencies": {
-				"@pixi/core": "7.3.3"
+				"@pixi/core": "7.4.0"
 			}
 		},
 		"node_modules/@pixi/events": {
-			"version": "7.3.3",
-			"resolved": "https://registry.npmjs.org/@pixi/events/-/events-7.3.3.tgz",
-			"integrity": "sha512-1oDfdFtKsy0Z9ew09MrSYGIIeGnBXr/c7866A32Od3KXql0dhd7UpFFpaFKLCXydDHRgFkjOP7t0/Pp1luTvfg==",
+			"version": "7.4.0",
+			"resolved": "https://registry.npmjs.org/@pixi/events/-/events-7.4.0.tgz",
+			"integrity": "sha512-9hshDahiFDbl3ZJt9cqutST+2aIZ8/bT29VVFuN2f0ZHatbEHVl46jqu0IL8d+TAlNUr+SI/JEaPA6/MR9sH6w==",
 			"peerDependencies": {
-				"@pixi/core": "7.3.3",
-				"@pixi/display": "7.3.3"
+				"@pixi/core": "7.4.0",
+				"@pixi/display": "7.4.0"
 			}
 		},
 		"node_modules/@pixi/extensions": {
-			"version": "7.3.3",
-			"resolved": "https://registry.npmjs.org/@pixi/extensions/-/extensions-7.3.3.tgz",
-			"integrity": "sha512-Of44Wde0ZHYCuMoDLFl/8SOSPV2NiDBUB6QKBvYvNdhVslbO3pxrn9oQH9Fmsd8iGcGJ/YtyI5H2T/ky4Bo6AQ=="
+			"version": "7.4.0",
+			"resolved": "https://registry.npmjs.org/@pixi/extensions/-/extensions-7.4.0.tgz",
+			"integrity": "sha512-bX0aw6z2D9bJ5NOsrbuWXnBR7sy2z+dyq2EQ2/t0dF6Si764r8FiA0QUGFn9NJO1FTnB9LLjz7q4c0XaWF3mcg=="
 		},
 		"node_modules/@pixi/extract": {
-			"version": "7.3.3",
-			"resolved": "https://registry.npmjs.org/@pixi/extract/-/extract-7.3.3.tgz",
-			"integrity": "sha512-quD61mNtgq3w2USIPUBOuxD9kVWIPoh8offqJugT4ZZS2XlSnh2FvLjCEC66jVmMM0tmk6HGAfc5xRFNlyw8PQ==",
+			"version": "7.4.0",
+			"resolved": "https://registry.npmjs.org/@pixi/extract/-/extract-7.4.0.tgz",
+			"integrity": "sha512-PLOdi8LxnRBRTKLx5plA9hWsIObiQ44tKMcyaLIESXNoUGE3135Aih10Hg1whrQcG4n9EqRjNak7LtwKRylRbg==",
 			"peerDependencies": {
-				"@pixi/core": "7.3.3"
+				"@pixi/core": "7.4.0"
 			}
 		},
 		"node_modules/@pixi/filter-adjustment": {
@@ -3590,11 +3592,11 @@
 			}
 		},
 		"node_modules/@pixi/filter-alpha": {
-			"version": "7.3.3",
-			"resolved": "https://registry.npmjs.org/@pixi/filter-alpha/-/filter-alpha-7.3.3.tgz",
-			"integrity": "sha512-StLLxEkCyghK3dhzLZD9jMu4lZ/ir4Bah2XXXWGhwE+XCO+//rnXreZ8v74R52WbaLUNDHzwlbq7/+BABwMu5w==",
+			"version": "7.4.0",
+			"resolved": "https://registry.npmjs.org/@pixi/filter-alpha/-/filter-alpha-7.4.0.tgz",
+			"integrity": "sha512-1KjdTcU4drduzF1HDu1clxZgM7b6lfE1CKESlY5CizJSMMGcycOUQRq/TWK54xrsJTyPWwNu5ojma6dcIqLOrw==",
 			"peerDependencies": {
-				"@pixi/core": "7.3.3"
+				"@pixi/core": "7.4.0"
 			}
 		},
 		"node_modules/@pixi/filter-ascii": {
@@ -3624,11 +3626,11 @@
 			}
 		},
 		"node_modules/@pixi/filter-blur": {
-			"version": "7.3.3",
-			"resolved": "https://registry.npmjs.org/@pixi/filter-blur/-/filter-blur-7.3.3.tgz",
-			"integrity": "sha512-AZzMbcFoL+uHxiVM2nQrQM0MQdLdd5mw7Fd4F60ROB96tmMK/M5W/FTqgdqXUQYld6wCFZKtJMulonVaPKLXDA==",
+			"version": "7.4.0",
+			"resolved": "https://registry.npmjs.org/@pixi/filter-blur/-/filter-blur-7.4.0.tgz",
+			"integrity": "sha512-XUrhswyuc4+flpDL0fQcRuei8ctgYCdTxCuetSqpS+qdf4gOJyq5UyCwDycJiudZD6+R23svUX5OQOPwkWTsNA==",
 			"peerDependencies": {
-				"@pixi/core": "7.3.3"
+				"@pixi/core": "7.4.0"
 			}
 		},
 		"node_modules/@pixi/filter-bulge-pinch": {
@@ -3656,11 +3658,11 @@
 			}
 		},
 		"node_modules/@pixi/filter-color-matrix": {
-			"version": "7.3.3",
-			"resolved": "https://registry.npmjs.org/@pixi/filter-color-matrix/-/filter-color-matrix-7.3.3.tgz",
-			"integrity": "sha512-Ot9lQ24lff4DPok0qy+c3IekfEuGf0Y1mx/dB3iLceys2hJHF5wK8rrhKrA1vc5IgrirbZpmjK8it9cVFzEW2g==",
+			"version": "7.4.0",
+			"resolved": "https://registry.npmjs.org/@pixi/filter-color-matrix/-/filter-color-matrix-7.4.0.tgz",
+			"integrity": "sha512-Ap5Fh6iJo5Mk6xMTia5KAWj9G0b4F3LiqrrWkM0y9gGzD5ei85Hd+XHHJtzWi+d4P/EWv7KlND6SnVcTZFgV4A==",
 			"peerDependencies": {
-				"@pixi/core": "7.3.3"
+				"@pixi/core": "7.4.0"
 			}
 		},
 		"node_modules/@pixi/filter-color-overlay": {
@@ -3704,11 +3706,11 @@
 			}
 		},
 		"node_modules/@pixi/filter-displacement": {
-			"version": "7.3.3",
-			"resolved": "https://registry.npmjs.org/@pixi/filter-displacement/-/filter-displacement-7.3.3.tgz",
-			"integrity": "sha512-fBnZTUmt6wwazdk/ZDW3HJEkf9s5b8uDuOwHvUAPWTJ6oYqwAjFXnrTlhEwB/Fp+0v6hUVVlHWEYk07HVgjEIg==",
+			"version": "7.4.0",
+			"resolved": "https://registry.npmjs.org/@pixi/filter-displacement/-/filter-displacement-7.4.0.tgz",
+			"integrity": "sha512-fcFLxFge2V6o7LqIsz/goDTMbwLdHjGggbu9/t4+byNP5f+S2TTR3oT4nulTYhNQph5vyllhSPJgHoqXXRhTwg==",
 			"peerDependencies": {
-				"@pixi/core": "7.3.3"
+				"@pixi/core": "7.4.0"
 			}
 		},
 		"node_modules/@pixi/filter-dot": {
@@ -3739,11 +3741,11 @@
 			}
 		},
 		"node_modules/@pixi/filter-fxaa": {
-			"version": "7.3.3",
-			"resolved": "https://registry.npmjs.org/@pixi/filter-fxaa/-/filter-fxaa-7.3.3.tgz",
-			"integrity": "sha512-xq5xcpu68axMrGsVOcpxqebLAa+B4yBSLQlI2rsn7s8YtWY+pC20lsaNnKDlrv9hwJ1Ah7BtBZy0EVVaeFNYqA==",
+			"version": "7.4.0",
+			"resolved": "https://registry.npmjs.org/@pixi/filter-fxaa/-/filter-fxaa-7.4.0.tgz",
+			"integrity": "sha512-W4l01ca9hJpjAfswRkw6UaCNh76E9ymigSVIBzhUUFwjfvVvIh7+O9SnEzkTVHsY15ANsznD0XZjgt3pW/wFbg==",
 			"peerDependencies": {
-				"@pixi/core": "7.3.3"
+				"@pixi/core": "7.4.0"
 			}
 		},
 		"node_modules/@pixi/filter-glitch": {
@@ -3811,11 +3813,11 @@
 			}
 		},
 		"node_modules/@pixi/filter-noise": {
-			"version": "7.3.3",
-			"resolved": "https://registry.npmjs.org/@pixi/filter-noise/-/filter-noise-7.3.3.tgz",
-			"integrity": "sha512-Hwwk1xLvA+0wTqJtKTnIGzyZmLubm5ylgqsMRHQqujDtVSIqE2SY1iVUcGA5vv31C7rFFkxGT4yhtfnYBNCvKQ==",
+			"version": "7.4.0",
+			"resolved": "https://registry.npmjs.org/@pixi/filter-noise/-/filter-noise-7.4.0.tgz",
+			"integrity": "sha512-q2+CWODAJO79j0StJ+xakX4D8r8w/RLURRiyG+focTIj1ws/7sdDmDsV+jmeKm6pEktwgA3JYWIKZUnezlGf8g==",
 			"peerDependencies": {
-				"@pixi/core": "7.3.3"
+				"@pixi/core": "7.4.0"
 			}
 		},
 		"node_modules/@pixi/filter-old-film": {
@@ -3907,84 +3909,84 @@
 			}
 		},
 		"node_modules/@pixi/graphics": {
-			"version": "7.3.3",
-			"resolved": "https://registry.npmjs.org/@pixi/graphics/-/graphics-7.3.3.tgz",
-			"integrity": "sha512-czX/SEQTSCI3kkH5DFAcchPaPYOAF7cz1P5K2hVvClE/bbbIWN0H2sBIF6pIY1ENkZ0aguQs36yDeXUDWXyoiQ==",
+			"version": "7.4.0",
+			"resolved": "https://registry.npmjs.org/@pixi/graphics/-/graphics-7.4.0.tgz",
+			"integrity": "sha512-9GcXbP/iTFEA5xwXx6sSwGyIYPd6XVhFJR7ALqqnlYC+FvvvHPoh7cN3HPa1Aw9dWpNRKUKuNcoOYPmd0O0aJA==",
 			"peerDependencies": {
-				"@pixi/core": "7.3.3",
-				"@pixi/display": "7.3.3",
-				"@pixi/sprite": "7.3.3"
+				"@pixi/core": "7.4.0",
+				"@pixi/display": "7.4.0",
+				"@pixi/sprite": "7.4.0"
 			}
 		},
 		"node_modules/@pixi/math": {
-			"version": "7.3.3",
-			"resolved": "https://registry.npmjs.org/@pixi/math/-/math-7.3.3.tgz",
-			"integrity": "sha512-kaHN6iusINPS0wIbrhP82za+B2qNDWHPHip/QtmpQTp81ibOIfHlDMOlsnE6rSdelTFNhrNWoTWU8IvXUbvy8g=="
+			"version": "7.4.0",
+			"resolved": "https://registry.npmjs.org/@pixi/math/-/math-7.4.0.tgz",
+			"integrity": "sha512-9WCWKX5z/VOYGpsnXXQ73vg/IT+bUXCLO6miXuS5YPXNfw9RpvdV4ZgFmuQwPNM7wfFk5T7Uvfr8ZJRBCfKhZw=="
 		},
 		"node_modules/@pixi/mesh": {
-			"version": "7.3.3",
-			"resolved": "https://registry.npmjs.org/@pixi/mesh/-/mesh-7.3.3.tgz",
-			"integrity": "sha512-8G3FO44wLDimNlCqXBKF+zQ3nBqJ4kMBbIjGxRaRkJmahcMYkY2zJpYsYh1YqKQztL9UmcP5V170VEIcPsmaJw==",
+			"version": "7.4.0",
+			"resolved": "https://registry.npmjs.org/@pixi/mesh/-/mesh-7.4.0.tgz",
+			"integrity": "sha512-Ql5B3q8UD898LTKTPAkveOU72tN9xD8CsLPuvmPSrjpE5FlyRhrS90JzD26/sz6H3B7Kfu2gRjilmujCzNvuWA==",
 			"peerDependencies": {
-				"@pixi/core": "7.3.3",
-				"@pixi/display": "7.3.3"
+				"@pixi/core": "7.4.0",
+				"@pixi/display": "7.4.0"
 			}
 		},
 		"node_modules/@pixi/mesh-extras": {
-			"version": "7.3.3",
-			"resolved": "https://registry.npmjs.org/@pixi/mesh-extras/-/mesh-extras-7.3.3.tgz",
-			"integrity": "sha512-2TW1n97PpSZIZomfoEcKezGeGLPyd82ng2u8SXQoy9keCmB2yK361/RO88jvWbY4qpnJn/89LiLyYEBiJtSmWg==",
+			"version": "7.4.0",
+			"resolved": "https://registry.npmjs.org/@pixi/mesh-extras/-/mesh-extras-7.4.0.tgz",
+			"integrity": "sha512-YMI72eDruRd3iUIxfFNW+siuwvvrBv4/A9GDeBySKdfqbMOnzi0GLjxvF88bcP7eujdJQDwzTnAV4hW0UNIkjw==",
 			"peerDependencies": {
-				"@pixi/core": "7.3.3",
-				"@pixi/mesh": "7.3.3"
+				"@pixi/core": "7.4.0",
+				"@pixi/mesh": "7.4.0"
 			}
 		},
 		"node_modules/@pixi/mixin-cache-as-bitmap": {
-			"version": "7.3.3",
-			"resolved": "https://registry.npmjs.org/@pixi/mixin-cache-as-bitmap/-/mixin-cache-as-bitmap-7.3.3.tgz",
-			"integrity": "sha512-Vv/H24CADY5w2DZaTYhXsfr8wAyKsg6gYn0DLgWDnAI3PWkRcB0fVDfowlHAEzltfxyH4tp9LVc2jtbEIKfSlQ==",
+			"version": "7.4.0",
+			"resolved": "https://registry.npmjs.org/@pixi/mixin-cache-as-bitmap/-/mixin-cache-as-bitmap-7.4.0.tgz",
+			"integrity": "sha512-wFkwU19dCyY5m0JxiKf6UJwvR8XaGDWA/0VXZelBF+WwIj54uKjN4lNSnSApHHByFfq9BRka7B5C1fU9eZNOzg==",
 			"peerDependencies": {
-				"@pixi/core": "7.3.3",
-				"@pixi/display": "7.3.3",
-				"@pixi/sprite": "7.3.3"
+				"@pixi/core": "7.4.0",
+				"@pixi/display": "7.4.0",
+				"@pixi/sprite": "7.4.0"
 			}
 		},
 		"node_modules/@pixi/mixin-get-child-by-name": {
-			"version": "7.3.3",
-			"resolved": "https://registry.npmjs.org/@pixi/mixin-get-child-by-name/-/mixin-get-child-by-name-7.3.3.tgz",
-			"integrity": "sha512-75vlViVaynPyIYQIaoU08k1iP+8s9ct2YEnW91vyiHGxxE7BBimiYomWkAUYXtSnaSFoDkNPOh7iI91Icmkf+w==",
+			"version": "7.4.0",
+			"resolved": "https://registry.npmjs.org/@pixi/mixin-get-child-by-name/-/mixin-get-child-by-name-7.4.0.tgz",
+			"integrity": "sha512-GAWXSNnYtZyppxGVpt0lN2Iq6Z1MYuGeE/X5rYd5yO+Ra9VbUaslTRxf2y8H1TTWOPCIs8mcSTNdJTgElSfqbQ==",
 			"peerDependencies": {
-				"@pixi/display": "7.3.3"
+				"@pixi/display": "7.4.0"
 			}
 		},
 		"node_modules/@pixi/mixin-get-global-position": {
-			"version": "7.3.3",
-			"resolved": "https://registry.npmjs.org/@pixi/mixin-get-global-position/-/mixin-get-global-position-7.3.3.tgz",
-			"integrity": "sha512-ZEScRlx/KSr0z40+xqF9jl9N8j0aFZCNwSluoMLuFecvn4kpaCQx8i4F8j+GkkdrnCfanSYE9ySADlUCsKmzHA==",
+			"version": "7.4.0",
+			"resolved": "https://registry.npmjs.org/@pixi/mixin-get-global-position/-/mixin-get-global-position-7.4.0.tgz",
+			"integrity": "sha512-u2EKXi7sv1zG2exk/bpjozBTOElBAsHnA0sHe0kz6sELpNBjv4g2n0Hwfl+qd69S+60zfN44ER+ihbFUWgD5VA==",
 			"peerDependencies": {
-				"@pixi/core": "7.3.3",
-				"@pixi/display": "7.3.3"
+				"@pixi/core": "7.4.0",
+				"@pixi/display": "7.4.0"
 			}
 		},
 		"node_modules/@pixi/particle-container": {
-			"version": "7.3.3",
-			"resolved": "https://registry.npmjs.org/@pixi/particle-container/-/particle-container-7.3.3.tgz",
-			"integrity": "sha512-OxigacwSbPjVogahmBYUiYMIH+NhNa+jvGAk5OYEF431gcVmjtravPbk7mmFdGKmOMICztSyVX8kOyhXxCv63A==",
+			"version": "7.4.0",
+			"resolved": "https://registry.npmjs.org/@pixi/particle-container/-/particle-container-7.4.0.tgz",
+			"integrity": "sha512-y3cB2EvgzfOm/pw4qBFsKOVoRzhzLy/FFj92DbD3bL5a6Z+YtKblkeWw3P5exzZJBTRn9sEk1vhzBb1HM/WEJw==",
 			"peerDependencies": {
-				"@pixi/core": "7.3.3",
-				"@pixi/display": "7.3.3",
-				"@pixi/sprite": "7.3.3"
+				"@pixi/core": "7.4.0",
+				"@pixi/display": "7.4.0",
+				"@pixi/sprite": "7.4.0"
 			}
 		},
 		"node_modules/@pixi/prepare": {
-			"version": "7.3.3",
-			"resolved": "https://registry.npmjs.org/@pixi/prepare/-/prepare-7.3.3.tgz",
-			"integrity": "sha512-2SdTyHJSDZeaEMuxXqOX01FUDhIjfWUmVCufLXxzjd8gZ52RWBpohl2gDRszPJMyPox142xzUiCnb4RuNXGHDw==",
+			"version": "7.4.0",
+			"resolved": "https://registry.npmjs.org/@pixi/prepare/-/prepare-7.4.0.tgz",
+			"integrity": "sha512-qMRf0SPVYW6k0ZG19SdddwH/FErywEzkJtS7pCVrFy31RP4dF+ZunEffKNPm3Kf5b94JXd6+lIAxDy4tDVqXNQ==",
 			"peerDependencies": {
-				"@pixi/core": "7.3.3",
-				"@pixi/display": "7.3.3",
-				"@pixi/graphics": "7.3.3",
-				"@pixi/text": "7.3.3"
+				"@pixi/core": "7.4.0",
+				"@pixi/display": "7.4.0",
+				"@pixi/graphics": "7.4.0",
+				"@pixi/text": "7.4.0"
 			}
 		},
 		"node_modules/@pixi/react": {
@@ -4021,103 +4023,103 @@
 			}
 		},
 		"node_modules/@pixi/runner": {
-			"version": "7.3.3",
-			"resolved": "https://registry.npmjs.org/@pixi/runner/-/runner-7.3.3.tgz",
-			"integrity": "sha512-LUObHyxM3tK504ChbioYySZhFhyNs779uA71fuWSFV04Ry0WNlbqVvwTbKGkyR6er6blfxdqk7d51WmuQtfLCg=="
+			"version": "7.4.0",
+			"resolved": "https://registry.npmjs.org/@pixi/runner/-/runner-7.4.0.tgz",
+			"integrity": "sha512-TIfocv2TD4xHOiGSpeu2y3GMN09cKEpxiS/rswdCU/aacfgSyvjEmskL/dbq/PSA4FCmjVHLyjgNPvd79WPZhQ=="
 		},
 		"node_modules/@pixi/settings": {
-			"version": "7.3.3",
-			"resolved": "https://registry.npmjs.org/@pixi/settings/-/settings-7.3.3.tgz",
-			"integrity": "sha512-a1OePduDPOfnrCm1U1RL7JhuEAncA5/jNwF51urclXU6HNTHiJT41/S6KELPoV8NbLyJCKtnKwzbbPkzKwc0Yg==",
+			"version": "7.4.0",
+			"resolved": "https://registry.npmjs.org/@pixi/settings/-/settings-7.4.0.tgz",
+			"integrity": "sha512-ODWmSVfLnn384xFsXp+NNV6mQ+AwoeI4FtN+tMcJ+w/qQTi+eq6VLIpgqNx2Z/TJESI4HY4jxL6qz4SJEs7SMA==",
 			"dependencies": {
-				"@pixi/constants": "7.3.3",
+				"@pixi/constants": "7.4.0",
 				"@types/css-font-loading-module": "^0.0.12",
 				"ismobilejs": "^1.1.0"
 			}
 		},
 		"node_modules/@pixi/sprite": {
-			"version": "7.3.3",
-			"resolved": "https://registry.npmjs.org/@pixi/sprite/-/sprite-7.3.3.tgz",
-			"integrity": "sha512-P/RxnvNV0PiuyaT9HA8F1aX9krp1BgjllBQcn6KHVxyAP8tJE0TD9pfHOU1+xRuoX37swXRQiDFTF6YvWzozUQ==",
+			"version": "7.4.0",
+			"resolved": "https://registry.npmjs.org/@pixi/sprite/-/sprite-7.4.0.tgz",
+			"integrity": "sha512-+yQdq3aKS59s9uxiW066geWLCKYTRjtbdgE2qtyUP4pK/bYanWVWash7K8P3qVX8NQsQKjGvNPoa2fkP6MBE1Q==",
 			"peerDependencies": {
-				"@pixi/core": "7.3.3",
-				"@pixi/display": "7.3.3"
+				"@pixi/core": "7.4.0",
+				"@pixi/display": "7.4.0"
 			}
 		},
 		"node_modules/@pixi/sprite-animated": {
-			"version": "7.3.3",
-			"resolved": "https://registry.npmjs.org/@pixi/sprite-animated/-/sprite-animated-7.3.3.tgz",
-			"integrity": "sha512-BYvehHk3PlNln9tRfZ/zGp2MzVwRjggFe+s4NCQd1EU/NPQewqJGCAiQFB4Gc3hFK2Y8wkW7SpGAzuk/E2WTxg==",
+			"version": "7.4.0",
+			"resolved": "https://registry.npmjs.org/@pixi/sprite-animated/-/sprite-animated-7.4.0.tgz",
+			"integrity": "sha512-SVIO78hHqVvBg5kh13TES0oqmjBhjeQmCgXVzT1nC62Vxh/6AAd9JOKid706lXoqRgw7H7OhdunEWL6J2zN4KA==",
 			"peerDependencies": {
-				"@pixi/core": "7.3.3",
-				"@pixi/sprite": "7.3.3"
+				"@pixi/core": "7.4.0",
+				"@pixi/sprite": "7.4.0"
 			}
 		},
 		"node_modules/@pixi/sprite-tiling": {
-			"version": "7.3.3",
-			"resolved": "https://registry.npmjs.org/@pixi/sprite-tiling/-/sprite-tiling-7.3.3.tgz",
-			"integrity": "sha512-T4ms0TcfKq7JNRaUBaQyZsaxWziPh2EY10vFQEG17J3uyCrjQmN4dDS9AMoaltL1K3vh+CTSUnWO8S8mE1dn4Q==",
+			"version": "7.4.0",
+			"resolved": "https://registry.npmjs.org/@pixi/sprite-tiling/-/sprite-tiling-7.4.0.tgz",
+			"integrity": "sha512-q0wjrdhvqnfSRNYIJ0KHUIT0nARvlmBoKBtjEZLAnk1jQCFzrJIg4qfmsBNDSOzMVaAxAot0EbOLjld6EZmf8w==",
 			"peerDependencies": {
-				"@pixi/core": "7.3.3",
-				"@pixi/display": "7.3.3",
-				"@pixi/sprite": "7.3.3"
+				"@pixi/core": "7.4.0",
+				"@pixi/display": "7.4.0",
+				"@pixi/sprite": "7.4.0"
 			}
 		},
 		"node_modules/@pixi/spritesheet": {
-			"version": "7.3.3",
-			"resolved": "https://registry.npmjs.org/@pixi/spritesheet/-/spritesheet-7.3.3.tgz",
-			"integrity": "sha512-aAebizGNiKijWmJ39bnAb8FbuXbxRINuWZ2xt7ANzJQxhbo7dX+qlF4pz91yj3gHQaulzJM2oKz4a5q6cHa7dw==",
+			"version": "7.4.0",
+			"resolved": "https://registry.npmjs.org/@pixi/spritesheet/-/spritesheet-7.4.0.tgz",
+			"integrity": "sha512-wztt4ne71AWDY4WMyuoMUrZlYVeKkubRTqT9HcPYxDEClxZAz1ggsr03PB4RGHbNQkVC1ImrAi9fa0D0PkyPYg==",
 			"peerDependencies": {
-				"@pixi/assets": "7.3.3",
-				"@pixi/core": "7.3.3"
+				"@pixi/assets": "7.4.0",
+				"@pixi/core": "7.4.0"
 			}
 		},
 		"node_modules/@pixi/text": {
-			"version": "7.3.3",
-			"resolved": "https://registry.npmjs.org/@pixi/text/-/text-7.3.3.tgz",
-			"integrity": "sha512-s9BLmiURYeJppPYB040jrGbtbsWM9PcXSRtr40xrbR0a+HPlxDEWCaHka9DiUFr/lIuOpA0y/YjmZskq5o5R7g==",
+			"version": "7.4.0",
+			"resolved": "https://registry.npmjs.org/@pixi/text/-/text-7.4.0.tgz",
+			"integrity": "sha512-yVVeWYH6N+E38R+D7tvOVwDhbFxrInZ7fkOllfePu3KaKsUXbjklgtKUyPREs1LGJC8ffrpCPo1k9BVmwFA4Eg==",
 			"peerDependencies": {
-				"@pixi/core": "7.3.3",
-				"@pixi/sprite": "7.3.3"
+				"@pixi/core": "7.4.0",
+				"@pixi/sprite": "7.4.0"
 			}
 		},
 		"node_modules/@pixi/text-bitmap": {
-			"version": "7.3.3",
-			"resolved": "https://registry.npmjs.org/@pixi/text-bitmap/-/text-bitmap-7.3.3.tgz",
-			"integrity": "sha512-2IOBoSHtb2e1aoxB/pfJPFW34XeY8HpDtGJKn3F9IUYpBo6nnnZ6DuJNZyFG2r/hiytjVvulqI66CzOH/eJJ4A==",
+			"version": "7.4.0",
+			"resolved": "https://registry.npmjs.org/@pixi/text-bitmap/-/text-bitmap-7.4.0.tgz",
+			"integrity": "sha512-OkYixlqMW9b1EHtEbSP9mgZEqI0WLN1KP4h2EyJk0LC9lH2Ybp3v7ZGHKAetGkSCt8PXY5AfXbcWtm+TgTWbJw==",
 			"peerDependencies": {
-				"@pixi/assets": "7.3.3",
-				"@pixi/core": "7.3.3",
-				"@pixi/display": "7.3.3",
-				"@pixi/mesh": "7.3.3",
-				"@pixi/text": "7.3.3"
+				"@pixi/assets": "7.4.0",
+				"@pixi/core": "7.4.0",
+				"@pixi/display": "7.4.0",
+				"@pixi/mesh": "7.4.0",
+				"@pixi/text": "7.4.0"
 			}
 		},
 		"node_modules/@pixi/text-html": {
-			"version": "7.3.3",
-			"resolved": "https://registry.npmjs.org/@pixi/text-html/-/text-html-7.3.3.tgz",
-			"integrity": "sha512-z8vsgsqVJuFEVX07wh0IYAwQ5DBiel8Lhxo2Ly8594O0mIdQ1IPvtAPv+WRyG35WT0i26J7GL2BZxURouDP2WA==",
+			"version": "7.4.0",
+			"resolved": "https://registry.npmjs.org/@pixi/text-html/-/text-html-7.4.0.tgz",
+			"integrity": "sha512-HOSKLynkL4cXQdv7zMst7+vISKp4ueCdJpV2zwQJnwVa/dHKlMULQ4+F5yxbtgAF8fYcH3iNfFLaraFlx1hL5A==",
 			"peerDependencies": {
-				"@pixi/core": "7.3.3",
-				"@pixi/display": "7.3.3",
-				"@pixi/sprite": "7.3.3",
-				"@pixi/text": "7.3.3"
+				"@pixi/core": "7.4.0",
+				"@pixi/display": "7.4.0",
+				"@pixi/sprite": "7.4.0",
+				"@pixi/text": "7.4.0"
 			}
 		},
 		"node_modules/@pixi/ticker": {
-			"version": "7.3.3",
-			"resolved": "https://registry.npmjs.org/@pixi/ticker/-/ticker-7.3.3.tgz",
-			"integrity": "sha512-AxeMKP9vTcla+yYXCABc0uKUODjIsJRXk3DCHVpoPeeqRYPaKH291RtDw92QFw7FFgGBbRgsptBjF9Q+uO5hDA==",
+			"version": "7.4.0",
+			"resolved": "https://registry.npmjs.org/@pixi/ticker/-/ticker-7.4.0.tgz",
+			"integrity": "sha512-GaDmk27tEpPfUVgVTNQWGuOYGu6ehqmVSGxecCv4No5KHP52+LihTC4YHO06zRxfyrIOgafooDL/vQiEMqas8g==",
 			"dependencies": {
-				"@pixi/extensions": "7.3.3",
-				"@pixi/settings": "7.3.3",
-				"@pixi/utils": "7.3.3"
+				"@pixi/extensions": "7.4.0",
+				"@pixi/settings": "7.4.0",
+				"@pixi/utils": "7.4.0"
 			}
 		},
 		"node_modules/@pixi/ui": {
-			"version": "0.10.3",
-			"resolved": "https://registry.npmjs.org/@pixi/ui/-/ui-0.10.3.tgz",
-			"integrity": "sha512-0oalBQ3bvVJQtQ1zDoWYaL8gQRpJebcjVonXJKCFQwwGKd4uNfQwxx+qRLdFcuYlPnrZiNPelaE6UgchF8qRtw==",
+			"version": "0.10.5",
+			"resolved": "https://registry.npmjs.org/@pixi/ui/-/ui-0.10.5.tgz",
+			"integrity": "sha512-jI+X+gaK9MuNTg/XJAAptwAZrC4wLwAD0QDgb1zoe1pln5yqZIg0JvS3NW5kNSLkJ6kpx9TjquuV0+SlEBDRIw==",
 			"dependencies": {
 				"tweedle.js": "^2.1.0",
 				"typed-signals": "^2.5.0"
@@ -4134,13 +4136,13 @@
 			}
 		},
 		"node_modules/@pixi/utils": {
-			"version": "7.3.3",
-			"resolved": "https://registry.npmjs.org/@pixi/utils/-/utils-7.3.3.tgz",
-			"integrity": "sha512-rgWD0YV6oDKOVuQJ9ra6g3VdoN8usC6Kj/t3Ba1t9P+k9qUKIM0gCr9/bxFf7CJ/EUS8A2WTVfEmJVN2TwZfxg==",
+			"version": "7.4.0",
+			"resolved": "https://registry.npmjs.org/@pixi/utils/-/utils-7.4.0.tgz",
+			"integrity": "sha512-VBnxNGGg/uj7k1wmvyNZei2qpbFNN/kdQ2/mwNXJtFcFymVfijNZWRUNobpSRE/yHx40WGYzSm3ZJZrF4WxFzA==",
 			"dependencies": {
-				"@pixi/color": "7.3.3",
-				"@pixi/constants": "7.3.3",
-				"@pixi/settings": "7.3.3",
+				"@pixi/color": "7.4.0",
+				"@pixi/constants": "7.4.0",
+				"@pixi/settings": "7.4.0",
 				"@types/earcut": "^2.1.0",
 				"earcut": "^2.2.4",
 				"eventemitter3": "^4.0.0",
@@ -4205,6 +4207,29 @@
 				}
 			}
 		},
+		"node_modules/@reduxjs/toolkit": {
+			"version": "2.1.0",
+			"resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.1.0.tgz",
+			"integrity": "sha512-nfJ/b4ZhzUevQ1ZPKjlDL6CMYxO4o7ZL7OSsvSOxzT/EN11LsBDgTqP7aedHtBrFSVoK7oTP1SbMWUwGb30NLg==",
+			"dependencies": {
+				"immer": "^10.0.3",
+				"redux": "^5.0.1",
+				"redux-thunk": "^3.1.0",
+				"reselect": "^5.0.1"
+			},
+			"peerDependencies": {
+				"react": "^16.9.0 || ^17.0.0 || ^18",
+				"react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0"
+			},
+			"peerDependenciesMeta": {
+				"react": {
+					"optional": true
+				},
+				"react-redux": {
+					"optional": true
+				}
+			}
+		},
 		"node_modules/@rollup/plugin-babel": {
 			"version": "5.3.1",
 			"resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz",
@@ -4306,9 +4331,9 @@
 			}
 		},
 		"node_modules/@stylistic/eslint-plugin-js": {
-			"version": "1.5.4",
-			"resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-1.5.4.tgz",
-			"integrity": "sha512-3ctWb3NvJNV1MsrZN91cYp2EGInLPSoZKphXIbIRx/zjZxKwLDr9z4LMOWtqjq14li/OgqUUcMq5pj8fgbLoTw==",
+			"version": "1.6.1",
+			"resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-1.6.1.tgz",
+			"integrity": "sha512-gHRxkbA5p8S1fnChE7Yf5NFltRZCzbCuQOcoTe93PSKBC4GqVjZmlWUSLz9pJKHvDAUTjWkfttWHIOaFYPEhRQ==",
 			"dev": true,
 			"dependencies": {
 				"acorn": "^8.11.3",
@@ -4780,9 +4805,9 @@
 			}
 		},
 		"node_modules/@types/express-serve-static-core": {
-			"version": "4.17.42",
-			"resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.42.tgz",
-			"integrity": "sha512-ckM3jm2bf/MfB3+spLPWYPUH573plBFwpOhqQ2WottxYV85j1HQFlxmnTq57X1yHY9awZPig06hL/cLMgNWHIQ==",
+			"version": "4.17.43",
+			"resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.43.tgz",
+			"integrity": "sha512-oaYtiBirUOPQGSWNGPWnzyAFJ0BP3cwvN4oWZQY+zUBwpVIGsKUkpBpSztp74drYcjavs7SKFZ4DX1V2QeN8rg==",
 			"dependencies": {
 				"@types/node": "*",
 				"@types/qs": "*",
@@ -4838,9 +4863,9 @@
 			}
 		},
 		"node_modules/@types/jest": {
-			"version": "29.5.11",
-			"resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.11.tgz",
-			"integrity": "sha512-S2mHmYIVe13vrm6q4kN6fLYYAka15ALQki/vgDC3mIukEOx8WJlv0kQPM+d4w8Gp6u0uSdKND04IlTXBv0rwnQ==",
+			"version": "29.5.12",
+			"resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.12.tgz",
+			"integrity": "sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==",
 			"dependencies": {
 				"expect": "^29.0.0",
 				"pretty-format": "^29.0.0"
@@ -4891,9 +4916,9 @@
 			"integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w=="
 		},
 		"node_modules/@types/node": {
-			"version": "20.11.7",
-			"resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.7.tgz",
-			"integrity": "sha512-GPmeN1C3XAyV5uybAf4cMLWT9fDWcmQhZVtMFu7OR32WjrqGG+Wnk2V1d0bmtUyE/Zy1QJ9BxyiTih9z8Oks8A==",
+			"version": "20.11.17",
+			"resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.17.tgz",
+			"integrity": "sha512-QmgQZGWu1Yw9TDyAP9ZzpFJKynYNeOvwMJmaxABfieQoVoiVOS6MN1WSpqpRcbeA5+RW82kraAVxCCJg+780Qw==",
 			"dependencies": {
 				"undici-types": "~5.26.4"
 			}
@@ -4906,11 +4931,6 @@
 				"@types/node": "*"
 			}
 		},
-		"node_modules/@types/offscreencanvas": {
-			"version": "2019.7.3",
-			"resolved": "https://registry.npmjs.org/@types/offscreencanvas/-/offscreencanvas-2019.7.3.tgz",
-			"integrity": "sha512-ieXiYmgSRXUDeOntE1InxjWyvEelZGP63M+cGuquuRLuIKKT1osnkXjxev9B7d1nXSug5vpunx+gNlbVxMlC9A=="
-		},
 		"node_modules/@types/parse-json": {
 			"version": "4.0.2",
 			"resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz",
@@ -4942,9 +4962,9 @@
 			"integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ=="
 		},
 		"node_modules/@types/react": {
-			"version": "18.2.48",
-			"resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.48.tgz",
-			"integrity": "sha512-qboRCl6Ie70DQQG9hhNREz81jqC1cs9EVNcjQ1AU+jH6NFfSAhVVbrrY/+nSF+Bsk4AOwm9Qa61InvMCyV+H3w==",
+			"version": "18.2.55",
+			"resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.55.tgz",
+			"integrity": "sha512-Y2Tz5P4yz23brwm2d7jNon39qoAtMMmalOQv6+fEFt1mT+FcM3D841wDpoUvFXhaYenuROCy3FZYqdTjM7qVyA==",
 			"dependencies": {
 				"@types/prop-types": "*",
 				"@types/scheduler": "*",
@@ -4952,9 +4972,9 @@
 			}
 		},
 		"node_modules/@types/react-dom": {
-			"version": "18.2.18",
-			"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.18.tgz",
-			"integrity": "sha512-TJxDm6OfAX2KJWJdMEVTwWke5Sc/E/RlnPGvGfS0W7+6ocy2xhDVQVh/KvC2Uf7kACs+gDytdusDSdWfWkaNzw==",
+			"version": "18.2.19",
+			"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.19.tgz",
+			"integrity": "sha512-aZvQL6uUbIJpjZk4U8JZGbau9KDeAwMfmhyWorxgBkqDIEf6ROjRozcmPIicqsUwPUjbkDfHKgGee1Lq65APcA==",
 			"dependencies": {
 				"@types/react": "*"
 			}
@@ -5035,6 +5055,11 @@
 			"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
 			"integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="
 		},
+		"node_modules/@types/use-sync-external-store": {
+			"version": "0.0.3",
+			"resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz",
+			"integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA=="
+		},
 		"node_modules/@types/ws": {
 			"version": "8.5.10",
 			"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz",
@@ -5101,9 +5126,9 @@
 			}
 		},
 		"node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": {
-			"version": "7.5.4",
-			"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
-			"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
+			"version": "7.6.0",
+			"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz",
+			"integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==",
 			"dependencies": {
 				"lru-cache": "^6.0.0"
 			},
@@ -5255,9 +5280,9 @@
 			}
 		},
 		"node_modules/@typescript-eslint/typescript-estree/node_modules/semver": {
-			"version": "7.5.4",
-			"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
-			"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
+			"version": "7.6.0",
+			"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz",
+			"integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==",
 			"dependencies": {
 				"lru-cache": "^6.0.0"
 			},
@@ -5330,9 +5355,9 @@
 			}
 		},
 		"node_modules/@typescript-eslint/utils/node_modules/semver": {
-			"version": "7.5.4",
-			"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
-			"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
+			"version": "7.6.0",
+			"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz",
+			"integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==",
 			"dependencies": {
 				"lru-cache": "^6.0.0"
 			},
@@ -5767,12 +5792,15 @@
 			}
 		},
 		"node_modules/array-buffer-byte-length": {
-			"version": "1.0.0",
-			"resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz",
-			"integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==",
+			"version": "1.0.1",
+			"resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz",
+			"integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==",
 			"dependencies": {
-				"call-bind": "^1.0.2",
-				"is-array-buffer": "^3.0.1"
+				"call-bind": "^1.0.5",
+				"is-array-buffer": "^3.0.4"
+			},
+			"engines": {
+				"node": ">= 0.4"
 			},
 			"funding": {
 				"url": "https://github.com/sponsors/ljharb"
@@ -5809,16 +5837,34 @@
 				"node": ">=8"
 			}
 		},
-		"node_modules/array.prototype.findlastindex": {
-			"version": "1.2.3",
-			"resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz",
-			"integrity": "sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==",
+		"node_modules/array.prototype.filter": {
+			"version": "1.0.3",
+			"resolved": "https://registry.npmjs.org/array.prototype.filter/-/array.prototype.filter-1.0.3.tgz",
+			"integrity": "sha512-VizNcj/RGJiUyQBgzwxzE5oHdeuXY5hSbbmKMlphj1cy1Vl7Pn2asCGbSrru6hSQjmCzqTBPVWAF/whmEOVHbw==",
 			"dependencies": {
 				"call-bind": "^1.0.2",
 				"define-properties": "^1.2.0",
 				"es-abstract": "^1.22.1",
-				"es-shim-unscopables": "^1.0.0",
-				"get-intrinsic": "^1.2.1"
+				"es-array-method-boxes-properly": "^1.0.0",
+				"is-string": "^1.0.7"
+			},
+			"engines": {
+				"node": ">= 0.4"
+			},
+			"funding": {
+				"url": "https://github.com/sponsors/ljharb"
+			}
+		},
+		"node_modules/array.prototype.findlastindex": {
+			"version": "1.2.4",
+			"resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.4.tgz",
+			"integrity": "sha512-hzvSHUshSpCflDR1QMUBLHGHP1VIEBegT4pix9H/Z92Xw3ySoy6c2qh7lJWTJnRJ8JCZ9bJNCgTyYaJGcJu6xQ==",
+			"dependencies": {
+				"call-bind": "^1.0.5",
+				"define-properties": "^1.2.1",
+				"es-abstract": "^1.22.3",
+				"es-errors": "^1.3.0",
+				"es-shim-unscopables": "^1.0.2"
 			},
 			"engines": {
 				"node": ">= 0.4"
@@ -5880,28 +5926,29 @@
 			}
 		},
 		"node_modules/array.prototype.tosorted": {
-			"version": "1.1.2",
-			"resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.2.tgz",
-			"integrity": "sha512-HuQCHOlk1Weat5jzStICBCd83NxiIMwqDg/dHEsoefabn/hJRj5pVdWcPUSpRrwhwxZOsQassMpgN/xRYFBMIg==",
+			"version": "1.1.3",
+			"resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.3.tgz",
+			"integrity": "sha512-/DdH4TiTmOKzyQbp/eadcCVexiCb36xJg7HshYOYJnNZFDj33GEv0P7GxsynpShhq4OLYJzbGcBDkLsDt7MnNg==",
 			"dependencies": {
-				"call-bind": "^1.0.2",
-				"define-properties": "^1.2.0",
-				"es-abstract": "^1.22.1",
-				"es-shim-unscopables": "^1.0.0",
-				"get-intrinsic": "^1.2.1"
+				"call-bind": "^1.0.5",
+				"define-properties": "^1.2.1",
+				"es-abstract": "^1.22.3",
+				"es-errors": "^1.1.0",
+				"es-shim-unscopables": "^1.0.2"
 			}
 		},
 		"node_modules/arraybuffer.prototype.slice": {
-			"version": "1.0.2",
-			"resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz",
-			"integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==",
+			"version": "1.0.3",
+			"resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz",
+			"integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==",
 			"dependencies": {
-				"array-buffer-byte-length": "^1.0.0",
-				"call-bind": "^1.0.2",
-				"define-properties": "^1.2.0",
-				"es-abstract": "^1.22.1",
-				"get-intrinsic": "^1.2.1",
-				"is-array-buffer": "^3.0.2",
+				"array-buffer-byte-length": "^1.0.1",
+				"call-bind": "^1.0.5",
+				"define-properties": "^1.2.1",
+				"es-abstract": "^1.22.3",
+				"es-errors": "^1.2.1",
+				"get-intrinsic": "^1.2.3",
+				"is-array-buffer": "^3.0.4",
 				"is-shared-array-buffer": "^1.0.2"
 			},
 			"engines": {
@@ -5996,9 +6043,9 @@
 			}
 		},
 		"node_modules/available-typed-arrays": {
-			"version": "1.0.5",
-			"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
-			"integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==",
+			"version": "1.0.6",
+			"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.6.tgz",
+			"integrity": "sha512-j1QzY8iPNPG4o4xmO3ptzpRxTciqD3MgEHtifP/YnJpIo58Xu+ne4BejlbkuaLfXn/nz6HFiw29bLpj2PNMdGg==",
 			"engines": {
 				"node": ">= 0.4"
 			},
@@ -6015,11 +6062,13 @@
 			}
 		},
 		"node_modules/axios": {
-			"version": "0.24.0",
-			"resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz",
-			"integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==",
+			"version": "1.6.7",
+			"resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz",
+			"integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==",
 			"dependencies": {
-				"follow-redirects": "^1.14.4"
+				"follow-redirects": "^1.15.4",
+				"form-data": "^4.0.0",
+				"proxy-from-env": "^1.1.0"
 			}
 		},
 		"node_modules/axobject-query": {
@@ -6492,9 +6541,9 @@
 			}
 		},
 		"node_modules/builtins/node_modules/semver": {
-			"version": "7.5.4",
-			"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
-			"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
+			"version": "7.6.0",
+			"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz",
+			"integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==",
 			"dev": true,
 			"dependencies": {
 				"lru-cache": "^6.0.0"
@@ -6521,13 +6570,17 @@
 			}
 		},
 		"node_modules/call-bind": {
-			"version": "1.0.5",
-			"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz",
-			"integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==",
+			"version": "1.0.6",
+			"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.6.tgz",
+			"integrity": "sha512-Mj50FLHtlsoVfRfnHaZvyrooHcrlceNZdL/QBvJJVd9Ta55qCQK0gs4ss2oZDeV9zFCs6ewzYgVE5yfVmfFpVg==",
 			"dependencies": {
+				"es-errors": "^1.3.0",
 				"function-bind": "^1.1.2",
-				"get-intrinsic": "^1.2.1",
-				"set-function-length": "^1.1.1"
+				"get-intrinsic": "^1.2.3",
+				"set-function-length": "^1.2.0"
+			},
+			"engines": {
+				"node": ">= 0.4"
 			},
 			"funding": {
 				"url": "https://github.com/sponsors/ljharb"
@@ -6581,9 +6634,9 @@
 			}
 		},
 		"node_modules/caniuse-lite": {
-			"version": "1.0.30001580",
-			"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001580.tgz",
-			"integrity": "sha512-mtj5ur2FFPZcCEpXFy8ADXbDACuNFXg6mxVDqp7tqooX6l3zwm+d8EPoeOSIFRDvHs8qu7/SLFOGniULkcH2iA==",
+			"version": "1.0.30001585",
+			"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001585.tgz",
+			"integrity": "sha512-yr2BWR1yLXQ8fMpdS/4ZZXpseBgE7o4g41x3a6AJOqZuOi+iE/WdJYAuZ6Y95i4Ohd2Y+9MzIWRR+uGABH4s3Q==",
 			"funding": [
 				{
 					"type": "opencollective",
@@ -6636,15 +6689,9 @@
 			"integrity": "sha512-+67P1GkJRaxQD6PKK0Et9DhwQB+vGg3PM5+aavopCpZT1lj9jeqfvpgTLAWErNj8qApkkmXlu/Ug74kmhagkXg=="
 		},
 		"node_modules/chokidar": {
-			"version": "3.5.3",
-			"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
-			"integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
-			"funding": [
-				{
-					"type": "individual",
-					"url": "https://paulmillr.com/funding/"
-				}
-			],
+			"version": "3.6.0",
+			"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
+			"integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
 			"dependencies": {
 				"anymatch": "~3.1.2",
 				"braces": "~3.0.2",
@@ -6657,6 +6704,9 @@
 			"engines": {
 				"node": ">= 8.10.0"
 			},
+			"funding": {
+				"url": "https://paulmillr.com/funding/"
+			},
 			"optionalDependencies": {
 				"fsevents": "~2.3.2"
 			}
@@ -7110,9 +7160,9 @@
 			}
 		},
 		"node_modules/css-loader": {
-			"version": "6.9.1",
-			"resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.9.1.tgz",
-			"integrity": "sha512-OzABOh0+26JKFdMzlK6PY1u5Zx8+Ck7CVRlcGNZoY9qwJjdfu2VWFuprTIpPW+Av5TZTVViYWcFQaEEQURLknQ==",
+			"version": "6.10.0",
+			"resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.10.0.tgz",
+			"integrity": "sha512-LTSA/jWbwdMlk+rhmElbDR2vbtQoTBPr7fkJE+mxrHj+7ru0hUmHafDRzWIjIHTwpitWVaqY2/UWGRca3yUgRw==",
 			"dependencies": {
 				"icss-utils": "^5.1.0",
 				"postcss": "^8.4.33",
@@ -7131,7 +7181,16 @@
 				"url": "https://opencollective.com/webpack"
 			},
 			"peerDependencies": {
+				"@rspack/core": "0.x || 1.x",
 				"webpack": "^5.0.0"
+			},
+			"peerDependenciesMeta": {
+				"@rspack/core": {
+					"optional": true
+				},
+				"webpack": {
+					"optional": true
+				}
 			}
 		},
 		"node_modules/css-loader/node_modules/lru-cache": {
@@ -7146,9 +7205,9 @@
 			}
 		},
 		"node_modules/css-loader/node_modules/semver": {
-			"version": "7.5.4",
-			"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
-			"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
+			"version": "7.6.0",
+			"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz",
+			"integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==",
 			"dependencies": {
 				"lru-cache": "^6.0.0"
 			},
@@ -7613,13 +7672,14 @@
 			}
 		},
 		"node_modules/define-data-property": {
-			"version": "1.1.1",
-			"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz",
-			"integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==",
+			"version": "1.1.2",
+			"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.2.tgz",
+			"integrity": "sha512-SRtsSqsDbgpJBbW3pABMCOt6rQyeM8s8RiyeSN8jYG8sYmt/kGJejbydttUsnDs1tadr19tvhT4ShwMyoqAm4g==",
 			"dependencies": {
-				"get-intrinsic": "^1.2.1",
+				"es-errors": "^1.3.0",
+				"get-intrinsic": "^1.2.2",
 				"gopd": "^1.0.1",
-				"has-property-descriptors": "^1.0.0"
+				"has-property-descriptors": "^1.0.1"
 			},
 			"engines": {
 				"node": ">= 0.4"
@@ -7916,9 +7976,9 @@
 			}
 		},
 		"node_modules/electron-to-chromium": {
-			"version": "1.4.648",
-			"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.648.tgz",
-			"integrity": "sha512-EmFMarXeqJp9cUKu/QEciEApn0S/xRcpZWuAm32U7NgoZCimjsilKXHRO9saeEW55eHZagIDg6XTUOv32w9pjg=="
+			"version": "1.4.665",
+			"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.665.tgz",
+			"integrity": "sha512-UpyCWObBoD+nSZgOC2ToaIdZB0r9GhqT2WahPKiSki6ckkSuKhQNso8V2PrFcHBMleI/eqbKgVQgVC4Wni4ilw=="
 		},
 		"node_modules/emittery": {
 			"version": "0.8.1",
@@ -8045,6 +8105,14 @@
 			"resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz",
 			"integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA=="
 		},
+		"node_modules/es-errors": {
+			"version": "1.3.0",
+			"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+			"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+			"engines": {
+				"node": ">= 0.4"
+			}
+		},
 		"node_modules/es-get-iterator": {
 			"version": "1.1.3",
 			"resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz",
@@ -8128,9 +8196,9 @@
 			}
 		},
 		"node_modules/escalade": {
-			"version": "3.1.1",
-			"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
-			"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
+			"version": "3.1.2",
+			"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz",
+			"integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==",
 			"engines": {
 				"node": ">=6"
 			}
@@ -8592,9 +8660,9 @@
 			}
 		},
 		"node_modules/eslint-plugin-n/node_modules/semver": {
-			"version": "7.5.4",
-			"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
-			"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
+			"version": "7.6.0",
+			"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz",
+			"integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==",
 			"dev": true,
 			"dependencies": {
 				"lru-cache": "^6.0.0"
@@ -9105,9 +9173,9 @@
 			"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="
 		},
 		"node_modules/fastq": {
-			"version": "1.17.0",
-			"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.0.tgz",
-			"integrity": "sha512-zGygtijUMT7jnk3h26kUms3BkSDp4IfIKjmnqI2tvx6nuBfiF1UqOxbnLfzdv+apBy+53oaImsKtMw/xYbW+1w==",
+			"version": "1.17.1",
+			"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
+			"integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==",
 			"dependencies": {
 				"reusify": "^1.0.4"
 			}
@@ -9454,9 +9522,9 @@
 			}
 		},
 		"node_modules/fork-ts-checker-webpack-plugin/node_modules/semver": {
-			"version": "7.5.4",
-			"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
-			"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
+			"version": "7.6.0",
+			"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz",
+			"integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==",
 			"dependencies": {
 				"lru-cache": "^6.0.0"
 			},
@@ -9481,9 +9549,9 @@
 			"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
 		},
 		"node_modules/form-data": {
-			"version": "3.0.1",
-			"resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz",
-			"integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==",
+			"version": "4.0.0",
+			"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
+			"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
 			"dependencies": {
 				"asynckit": "^0.4.0",
 				"combined-stream": "^1.0.8",
@@ -9607,15 +9675,19 @@
 			}
 		},
 		"node_modules/get-intrinsic": {
-			"version": "1.2.2",
-			"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz",
-			"integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==",
+			"version": "1.2.4",
+			"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
+			"integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
 			"dependencies": {
+				"es-errors": "^1.3.0",
 				"function-bind": "^1.1.2",
 				"has-proto": "^1.0.1",
 				"has-symbols": "^1.0.3",
 				"hasown": "^2.0.0"
 			},
+			"engines": {
+				"node": ">= 0.4"
+			},
 			"funding": {
 				"url": "https://github.com/sponsors/ljharb"
 			}
@@ -9645,12 +9717,13 @@
 			}
 		},
 		"node_modules/get-symbol-description": {
-			"version": "1.0.0",
-			"resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz",
-			"integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==",
+			"version": "1.0.2",
+			"resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz",
+			"integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==",
 			"dependencies": {
-				"call-bind": "^1.0.2",
-				"get-intrinsic": "^1.1.1"
+				"call-bind": "^1.0.5",
+				"es-errors": "^1.3.0",
+				"get-intrinsic": "^1.2.4"
 			},
 			"engines": {
 				"node": ">= 0.4"
@@ -9871,11 +9944,11 @@
 			}
 		},
 		"node_modules/has-tostringtag": {
-			"version": "1.0.0",
-			"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
-			"integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
+			"version": "1.0.2",
+			"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+			"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
 			"dependencies": {
-				"has-symbols": "^1.0.2"
+				"has-symbols": "^1.0.3"
 			},
 			"engines": {
 				"node": ">= 0.4"
@@ -10187,17 +10260,17 @@
 			}
 		},
 		"node_modules/ignore": {
-			"version": "5.3.0",
-			"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz",
-			"integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==",
+			"version": "5.3.1",
+			"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz",
+			"integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==",
 			"engines": {
 				"node": ">= 4"
 			}
 		},
 		"node_modules/immer": {
-			"version": "9.0.21",
-			"resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz",
-			"integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==",
+			"version": "10.0.3",
+			"resolved": "https://registry.npmjs.org/immer/-/immer-10.0.3.tgz",
+			"integrity": "sha512-pwupu3eWfouuaowscykeckFmVTpqbzW+rXFCX8rQLkZzM9ftBmU/++Ra+o+L27mz03zJTlyV4UUr+fdKNffo4A==",
 			"funding": {
 				"type": "opencollective",
 				"url": "https://opencollective.com/immer"
@@ -10280,11 +10353,11 @@
 			}
 		},
 		"node_modules/internal-slot": {
-			"version": "1.0.6",
-			"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz",
-			"integrity": "sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==",
+			"version": "1.0.7",
+			"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz",
+			"integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==",
 			"dependencies": {
-				"get-intrinsic": "^1.2.2",
+				"es-errors": "^1.3.0",
 				"hasown": "^2.0.0",
 				"side-channel": "^1.0.4"
 			},
@@ -10316,13 +10389,15 @@
 			}
 		},
 		"node_modules/is-array-buffer": {
-			"version": "3.0.2",
-			"resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz",
-			"integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==",
+			"version": "3.0.4",
+			"resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz",
+			"integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==",
 			"dependencies": {
 				"call-bind": "^1.0.2",
-				"get-intrinsic": "^1.2.0",
-				"is-typed-array": "^1.1.10"
+				"get-intrinsic": "^1.2.1"
+			},
+			"engines": {
+				"node": ">= 0.4"
 			},
 			"funding": {
 				"url": "https://github.com/sponsors/ljharb"
@@ -10677,11 +10752,11 @@
 			}
 		},
 		"node_modules/is-typed-array": {
-			"version": "1.1.12",
-			"resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz",
-			"integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==",
+			"version": "1.1.13",
+			"resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz",
+			"integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==",
 			"dependencies": {
-				"which-typed-array": "^1.1.11"
+				"which-typed-array": "^1.1.14"
 			},
 			"engines": {
 				"node": ">= 0.4"
@@ -10814,9 +10889,9 @@
 			}
 		},
 		"node_modules/istanbul-lib-report/node_modules/semver": {
-			"version": "7.5.4",
-			"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
-			"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
+			"version": "7.6.0",
+			"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz",
+			"integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==",
 			"dependencies": {
 				"lru-cache": "^6.0.0"
 			},
@@ -12335,9 +12410,9 @@
 			}
 		},
 		"node_modules/jest-snapshot/node_modules/semver": {
-			"version": "7.5.4",
-			"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
-			"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
+			"version": "7.6.0",
+			"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz",
+			"integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==",
 			"dependencies": {
 				"lru-cache": "^6.0.0"
 			},
@@ -12850,6 +12925,19 @@
 				}
 			}
 		},
+		"node_modules/jsdom/node_modules/form-data": {
+			"version": "3.0.1",
+			"resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz",
+			"integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==",
+			"dependencies": {
+				"asynckit": "^0.4.0",
+				"combined-stream": "^1.0.8",
+				"mime-types": "^2.1.12"
+			},
+			"engines": {
+				"node": ">= 6"
+			}
+		},
 		"node_modules/jsdom/node_modules/tr46": {
 			"version": "2.1.0",
 			"resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz",
@@ -13315,11 +13403,12 @@
 			}
 		},
 		"node_modules/mini-css-extract-plugin": {
-			"version": "2.7.7",
-			"resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.7.tgz",
-			"integrity": "sha512-+0n11YGyRavUR3IlaOzJ0/4Il1avMvJ1VJfhWfCn24ITQXhRr1gghbhhrda6tgtNcpZaWKdSuwKq20Jb7fnlyw==",
+			"version": "2.8.0",
+			"resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.8.0.tgz",
+			"integrity": "sha512-CxmUYPFcTgET1zImteG/LZOy/4T5rTojesQXkSNBiquhydn78tfbCE9sjIjnJ/UcjNjOC1bphTCCW5rrS7cXAg==",
 			"dependencies": {
-				"schema-utils": "^4.0.0"
+				"schema-utils": "^4.0.0",
+				"tapable": "^2.2.1"
 			},
 			"engines": {
 				"node": ">= 12.13.0"
@@ -16231,14 +16320,15 @@
 			}
 		},
 		"node_modules/object.groupby": {
-			"version": "1.0.1",
-			"resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.1.tgz",
-			"integrity": "sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==",
+			"version": "1.0.2",
+			"resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.2.tgz",
+			"integrity": "sha512-bzBq58S+x+uo0VjurFT0UktpKHOZmv4/xePiOA1nbB9pMqpGK7rUPNgf+1YC+7mE+0HzhTMqNUuCqvKhj6FnBw==",
 			"dependencies": {
-				"call-bind": "^1.0.2",
-				"define-properties": "^1.2.0",
-				"es-abstract": "^1.22.1",
-				"get-intrinsic": "^1.2.1"
+				"array.prototype.filter": "^1.0.3",
+				"call-bind": "^1.0.5",
+				"define-properties": "^1.2.1",
+				"es-abstract": "^1.22.3",
+				"es-errors": "^1.0.0"
 			}
 		},
 		"node_modules/object.hasown": {
@@ -16599,40 +16689,40 @@
 			}
 		},
 		"node_modules/pixi.js": {
-			"version": "7.3.3",
-			"resolved": "https://registry.npmjs.org/pixi.js/-/pixi.js-7.3.3.tgz",
-			"integrity": "sha512-EuAyWZBL5lKViCgYkB6dbwkiI/MNht8O8F8956up9vwGEGf659QRHxfVQoRj8zdNGOBbe51XAxQMfLaW/l0Ekg==",
-			"dependencies": {
-				"@pixi/accessibility": "7.3.3",
-				"@pixi/app": "7.3.3",
-				"@pixi/assets": "7.3.3",
-				"@pixi/compressed-textures": "7.3.3",
-				"@pixi/core": "7.3.3",
-				"@pixi/display": "7.3.3",
-				"@pixi/events": "7.3.3",
-				"@pixi/extensions": "7.3.3",
-				"@pixi/extract": "7.3.3",
-				"@pixi/filter-alpha": "7.3.3",
-				"@pixi/filter-blur": "7.3.3",
-				"@pixi/filter-color-matrix": "7.3.3",
-				"@pixi/filter-displacement": "7.3.3",
-				"@pixi/filter-fxaa": "7.3.3",
-				"@pixi/filter-noise": "7.3.3",
-				"@pixi/graphics": "7.3.3",
-				"@pixi/mesh": "7.3.3",
-				"@pixi/mesh-extras": "7.3.3",
-				"@pixi/mixin-cache-as-bitmap": "7.3.3",
-				"@pixi/mixin-get-child-by-name": "7.3.3",
-				"@pixi/mixin-get-global-position": "7.3.3",
-				"@pixi/particle-container": "7.3.3",
-				"@pixi/prepare": "7.3.3",
-				"@pixi/sprite": "7.3.3",
-				"@pixi/sprite-animated": "7.3.3",
-				"@pixi/sprite-tiling": "7.3.3",
-				"@pixi/spritesheet": "7.3.3",
-				"@pixi/text": "7.3.3",
-				"@pixi/text-bitmap": "7.3.3",
-				"@pixi/text-html": "7.3.3"
+			"version": "7.4.0",
+			"resolved": "https://registry.npmjs.org/pixi.js/-/pixi.js-7.4.0.tgz",
+			"integrity": "sha512-c2q3NG06RcSzgcyNieuC/ogzdaBKRoZvBlAiPdL8ubhJyEVCoSA+zitjsCe/m3t5cVrrjPnwo81ps+fg908hBw==",
+			"dependencies": {
+				"@pixi/accessibility": "7.4.0",
+				"@pixi/app": "7.4.0",
+				"@pixi/assets": "7.4.0",
+				"@pixi/compressed-textures": "7.4.0",
+				"@pixi/core": "7.4.0",
+				"@pixi/display": "7.4.0",
+				"@pixi/events": "7.4.0",
+				"@pixi/extensions": "7.4.0",
+				"@pixi/extract": "7.4.0",
+				"@pixi/filter-alpha": "7.4.0",
+				"@pixi/filter-blur": "7.4.0",
+				"@pixi/filter-color-matrix": "7.4.0",
+				"@pixi/filter-displacement": "7.4.0",
+				"@pixi/filter-fxaa": "7.4.0",
+				"@pixi/filter-noise": "7.4.0",
+				"@pixi/graphics": "7.4.0",
+				"@pixi/mesh": "7.4.0",
+				"@pixi/mesh-extras": "7.4.0",
+				"@pixi/mixin-cache-as-bitmap": "7.4.0",
+				"@pixi/mixin-get-child-by-name": "7.4.0",
+				"@pixi/mixin-get-global-position": "7.4.0",
+				"@pixi/particle-container": "7.4.0",
+				"@pixi/prepare": "7.4.0",
+				"@pixi/sprite": "7.4.0",
+				"@pixi/sprite-animated": "7.4.0",
+				"@pixi/sprite-tiling": "7.4.0",
+				"@pixi/spritesheet": "7.4.0",
+				"@pixi/text": "7.4.0",
+				"@pixi/text-bitmap": "7.4.0",
+				"@pixi/text-html": "7.4.0"
 			},
 			"funding": {
 				"type": "opencollective",
@@ -16766,9 +16856,9 @@
 			}
 		},
 		"node_modules/postcss": {
-			"version": "8.4.33",
-			"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.33.tgz",
-			"integrity": "sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==",
+			"version": "8.4.35",
+			"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz",
+			"integrity": "sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==",
 			"funding": [
 				{
 					"type": "opencollective",
@@ -17304,9 +17394,9 @@
 			}
 		},
 		"node_modules/postcss-loader/node_modules/semver": {
-			"version": "7.5.4",
-			"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
-			"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
+			"version": "7.6.0",
+			"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz",
+			"integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==",
 			"dependencies": {
 				"lru-cache": "^6.0.0"
 			},
@@ -18100,6 +18190,11 @@
 				"node": ">= 0.10"
 			}
 		},
+		"node_modules/proxy-from-env": {
+			"version": "1.1.0",
+			"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+			"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
+		},
 		"node_modules/psl": {
 			"version": "1.9.0",
 			"resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
@@ -18291,6 +18386,15 @@
 				"node": ">=14"
 			}
 		},
+		"node_modules/react-dev-utils/node_modules/immer": {
+			"version": "9.0.21",
+			"resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz",
+			"integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==",
+			"funding": {
+				"type": "opencollective",
+				"url": "https://opencollective.com/immer"
+			}
+		},
 		"node_modules/react-dev-utils/node_modules/loader-utils": {
 			"version": "3.2.1",
 			"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.1.tgz",
@@ -18361,6 +18465,32 @@
 				"object-assign": "^4.1.1"
 			}
 		},
+		"node_modules/react-redux": {
+			"version": "9.1.0",
+			"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.1.0.tgz",
+			"integrity": "sha512-6qoDzIO+gbrza8h3hjMA9aq4nwVFCKFtY2iLxCtVT38Swyy2C/dJCGBXHeHLtx6qlg/8qzc2MrhOeduf5K32wQ==",
+			"dependencies": {
+				"@types/use-sync-external-store": "^0.0.3",
+				"use-sync-external-store": "^1.0.0"
+			},
+			"peerDependencies": {
+				"@types/react": "^18.2.25",
+				"react": "^18.0",
+				"react-native": ">=0.69",
+				"redux": "^5.0.0"
+			},
+			"peerDependenciesMeta": {
+				"@types/react": {
+					"optional": true
+				},
+				"react-native": {
+					"optional": true
+				},
+				"redux": {
+					"optional": true
+				}
+			}
+		},
 		"node_modules/react-refresh": {
 			"version": "0.11.0",
 			"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz",
@@ -18453,9 +18583,9 @@
 			}
 		},
 		"node_modules/react-scripts/node_modules/semver": {
-			"version": "7.5.4",
-			"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
-			"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
+			"version": "7.6.0",
+			"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz",
+			"integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==",
 			"dependencies": {
 				"lru-cache": "^6.0.0"
 			},
@@ -18526,15 +18656,29 @@
 				"node": ">=8"
 			}
 		},
+		"node_modules/redux": {
+			"version": "5.0.1",
+			"resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz",
+			"integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w=="
+		},
+		"node_modules/redux-thunk": {
+			"version": "3.1.0",
+			"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz",
+			"integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==",
+			"peerDependencies": {
+				"redux": "^5.0.0"
+			}
+		},
 		"node_modules/reflect.getprototypeof": {
-			"version": "1.0.4",
-			"resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz",
-			"integrity": "sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw==",
+			"version": "1.0.5",
+			"resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.5.tgz",
+			"integrity": "sha512-62wgfC8dJWrmxv44CA36pLDnP6KKl3Vhxb7PL+8+qrrFMMoJij4vgiMP8zV4O8+CBMXY1mHxI5fITGHXFHVmQQ==",
 			"dependencies": {
-				"call-bind": "^1.0.2",
-				"define-properties": "^1.2.0",
-				"es-abstract": "^1.22.1",
-				"get-intrinsic": "^1.2.1",
+				"call-bind": "^1.0.5",
+				"define-properties": "^1.2.1",
+				"es-abstract": "^1.22.3",
+				"es-errors": "^1.0.0",
+				"get-intrinsic": "^1.2.3",
 				"globalthis": "^1.0.3",
 				"which-builtin-type": "^1.1.3"
 			},
@@ -18683,6 +18827,11 @@
 			"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
 			"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ=="
 		},
+		"node_modules/reselect": {
+			"version": "5.1.0",
+			"resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.0.tgz",
+			"integrity": "sha512-aw7jcGLDpSgNDyWBQLv2cedml85qd95/iszJjN988zX1t7AVRJi19d9kto5+W7oCfQ94gyo40dVbT6g2k4/kXg=="
+		},
 		"node_modules/resolve": {
 			"version": "1.22.8",
 			"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
@@ -18935,12 +19084,12 @@
 			]
 		},
 		"node_modules/safe-regex-test": {
-			"version": "1.0.2",
-			"resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.2.tgz",
-			"integrity": "sha512-83S9w6eFq12BBIJYvjMux6/dkirb8+4zJRA9cxNBVb7Wq5fJBW+Xze48WqR8pxua7bDuAaaAxtVVd4Idjp1dBQ==",
+			"version": "1.0.3",
+			"resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz",
+			"integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==",
 			"dependencies": {
-				"call-bind": "^1.0.5",
-				"get-intrinsic": "^1.2.2",
+				"call-bind": "^1.0.6",
+				"es-errors": "^1.3.0",
 				"is-regex": "^1.1.4"
 			},
 			"engines": {
@@ -19197,13 +19346,14 @@
 			}
 		},
 		"node_modules/set-function-length": {
-			"version": "1.2.0",
-			"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.0.tgz",
-			"integrity": "sha512-4DBHDoyHlM1IRPGYcoxexgh67y4ueR53FKV1yyxwFMY7aCqcN/38M1+SwZ/qJQ8iLv7+ck385ot4CcisOAPT9w==",
+			"version": "1.2.1",
+			"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz",
+			"integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==",
 			"dependencies": {
-				"define-data-property": "^1.1.1",
+				"define-data-property": "^1.1.2",
+				"es-errors": "^1.3.0",
 				"function-bind": "^1.1.2",
-				"get-intrinsic": "^1.2.2",
+				"get-intrinsic": "^1.2.3",
 				"gopd": "^1.0.1",
 				"has-property-descriptors": "^1.0.1"
 			},
@@ -19262,13 +19412,17 @@
 			}
 		},
 		"node_modules/side-channel": {
-			"version": "1.0.4",
-			"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
-			"integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
+			"version": "1.0.5",
+			"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.5.tgz",
+			"integrity": "sha512-QcgiIWV4WV7qWExbN5llt6frQB/lBven9pqliLXfGPB+K9ZYXxDozp0wLkHS24kWCm+6YXH/f0HhnObZnZOBnQ==",
 			"dependencies": {
-				"call-bind": "^1.0.0",
-				"get-intrinsic": "^1.0.2",
-				"object-inspect": "^1.9.0"
+				"call-bind": "^1.0.6",
+				"es-errors": "^1.3.0",
+				"get-intrinsic": "^1.2.4",
+				"object-inspect": "^1.13.1"
+			},
+			"engines": {
+				"node": ">= 0.4"
 			},
 			"funding": {
 				"url": "https://github.com/sponsors/ljharb"
@@ -20424,13 +20578,13 @@
 			}
 		},
 		"node_modules/typed-array-buffer": {
-			"version": "1.0.0",
-			"resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz",
-			"integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==",
+			"version": "1.0.1",
+			"resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.1.tgz",
+			"integrity": "sha512-RSqu1UEuSlrBhHTWC8O9FnPjOduNs4M7rJ4pRKoEjtx1zUNOPN2sSXHLDX+Y2WPbHIxbvg4JFo2DNAEfPIKWoQ==",
 			"dependencies": {
-				"call-bind": "^1.0.2",
-				"get-intrinsic": "^1.2.1",
-				"is-typed-array": "^1.1.10"
+				"call-bind": "^1.0.6",
+				"es-errors": "^1.3.0",
+				"is-typed-array": "^1.1.13"
 			},
 			"engines": {
 				"node": ">= 0.4"
@@ -20693,6 +20847,14 @@
 			"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
 			"integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ=="
 		},
+		"node_modules/use-sync-external-store": {
+			"version": "1.2.0",
+			"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
+			"integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==",
+			"peerDependencies": {
+				"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+			}
+		},
 		"node_modules/util": {
 			"version": "0.12.5",
 			"resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz",
@@ -20833,9 +20995,9 @@
 			}
 		},
 		"node_modules/webpack": {
-			"version": "5.90.0",
-			"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.90.0.tgz",
-			"integrity": "sha512-bdmyXRCXeeNIePv6R6tGPyy20aUobw4Zy8r0LUS2EWO+U+Ke/gYDgsCh7bl5rB6jPpr4r0SZa6dPxBxLooDT3w==",
+			"version": "5.90.1",
+			"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.90.1.tgz",
+			"integrity": "sha512-SstPdlAC5IvgFnhiRok8hqJo/+ArAbNv7rhU4fnWGHNVfN59HSQFaxZDSAL3IFG2YmqxuRs+IU33milSxbPlog==",
 			"dependencies": {
 				"@types/eslint-scope": "^3.7.3",
 				"@types/estree": "^1.0.5",
@@ -21272,15 +21434,15 @@
 			}
 		},
 		"node_modules/which-typed-array": {
-			"version": "1.1.13",
-			"resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz",
-			"integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==",
+			"version": "1.1.14",
+			"resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.14.tgz",
+			"integrity": "sha512-VnXFiIW8yNn9kIHN88xvZ4yOWchftKDsRJ8fEPacX/wl1lOvBrhsJ/OeJCXq7B0AaijRuqgzSKalJoPk+D8MPg==",
 			"dependencies": {
-				"available-typed-arrays": "^1.0.5",
-				"call-bind": "^1.0.4",
+				"available-typed-arrays": "^1.0.6",
+				"call-bind": "^1.0.5",
 				"for-each": "^0.3.3",
 				"gopd": "^1.0.1",
-				"has-tostringtag": "^1.0.0"
+				"has-tostringtag": "^1.0.1"
 			},
 			"engines": {
 				"node": ">= 0.4"
diff --git a/frontend/package.json b/frontend/package.json
index 24ed7678..d73ad4f7 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -6,11 +6,12 @@
 		"@pixi/filter-drop-shadow": "^5.2.0",
 		"@pixi/react": "^7.1.1",
 		"@pixi/ui": "^0.10.1",
+		"@reduxjs/toolkit": "^2.1.0",
 		"@testing-library/jest-dom": "^5.17.0",
 		"@testing-library/react": "^13.4.0",
 		"@testing-library/user-event": "^13.5.0",
 		"assert": "^2.1.0",
-		"axios": "^0.24.0",
+		"axios": "^1.6.7",
 		"install": "^0.13.0",
 		"npm": "^10.2.5",
 		"pixi-filters": "^5.2.1",
@@ -18,7 +19,9 @@
 		"react": "^18.2.0",
 		"react-dom": "^18.2.0",
 		"react-pixi-fiber": "^1.0.6",
+		"react-redux": "^9.1.0",
 		"react-scripts": "5.0.1",
+		"redux": "^5.0.1",
 		"web-vitals": "^2.1.4"
 	},
 	"scripts": {
diff --git a/frontend/src/index.js b/frontend/src/index.js
index 2cb1087e..de1b9c87 100644
--- a/frontend/src/index.js
+++ b/frontend/src/index.js
@@ -1,11 +1,41 @@
 import React from 'react';
 import ReactDOM from 'react-dom/client';
 import './index.css';
+import { Provider } from 'react-redux';
+import { configureStore } from '@reduxjs/toolkit';
 import App from './App';
 
+const initialState = {
+  todos: [],
+};
+
+// eslint-disable-next-line default-param-last
+const reducer = (state = initialState, action) => {
+  switch (action.type) {
+  case 'ADD_TODO':
+    return {
+      ...state,
+      todos: [...state.todos, action.payload],
+    };
+  case 'REMOVE_TODO':
+    return {
+      ...state,
+      todos: state.todos.filter((todo) => todo.id !== action.payload),
+    };
+  default:
+    return state;
+  }
+};
+
+const store = configureStore({ reducer });
+
 const root = ReactDOM.createRoot(document.getElementById('root'));
 root.render(
   <React.StrictMode>
-    <App />
+    <Provider store={store}>
+      <App />
+    </Provider>
   </React.StrictMode>
 );
+
+export default store;
diff --git a/notebooks/corner.ipynb b/notebooks/corner.ipynb
index 246c6504..7a19276c 100644
--- a/notebooks/corner.ipynb
+++ b/notebooks/corner.ipynb
@@ -97,7 +97,7 @@
             "# The library can go quite high:\n",
             "corner.scale_to(2500)\n",
             "plaquette_indices = list(range(1, corner.expected_plaquettes_number + 1))\n",
-            "array = corner.instantiate(*plaquette_indices)\n",
+            "array = corner.instantiate(plaquette_indices)\n",
             "print(array.shape)\n",
             "print(corner.shape)"
          ]
diff --git a/notebooks/doubling_distance.ipynb b/notebooks/doubling_distance.ipynb
index 3d52d671..84625db1 100644
--- a/notebooks/doubling_distance.ipynb
+++ b/notebooks/doubling_distance.ipynb
@@ -36,6 +36,7 @@
             },
             "outputs": [],
             "source": [
+                "import typing as ty\n",
                 "import numpy\n",
                 "from tqec.templates.atomic.rectangle import (\n",
                 "    AlternatingRectangleTemplate,\n",
@@ -104,12 +105,19 @@
                 "# - the square numbered 12 that has a specific top-right plaquette\n",
                 "class SpecificAlternatingSquareTemplate(AlternatingSquareTemplate):\n",
                 "    def instantiate(\n",
-                "        self, x_plaquette: int, z_plaquette: int, special_plaquette: int, *_: int\n",
+                "        self,\n",
+                "        plaquette_indices: ty.Sequence[int],\n",
                 "    ) -> numpy.ndarray:\n",
-                "        arr = super().instantiate(x_plaquette, z_plaquette, *_)\n",
+                "        self._check_plaquette_number(plaquette_indices)\n",
+                "        x_plaquette, z_plaquette, special_plaquette = plaquette_indices[:3]\n",
+                "        arr = super().instantiate([x_plaquette, z_plaquette])\n",
                 "        arr[0, -1] = special_plaquette\n",
                 "        return arr\n",
                 "\n",
+                "    @property\n",
+                "    def expected_plaquettes_number(self) -> int:\n",
+                "        return 3\n",
+                "\n",
                 "\n",
                 "top_right_specific_square = TemplateWithIndices(\n",
                 "    SpecificAlternatingSquareTemplate(dim), [1, 1, 1]\n",
@@ -352,7 +360,7 @@
             "outputs": [],
             "source": [
                 "plaquette_indices = list(range(1, doubling_template.expected_plaquettes_number + 1))\n",
-                "arr = doubling_template.scale_to(500).instantiate(*plaquette_indices)\n",
+                "arr = doubling_template.scale_to(500).instantiate(plaquette_indices)\n",
                 "print(\"Array shape:\", arr.shape)"
             ]
         }
diff --git a/notebooks/move_qubit_along_a_line.ipynb b/notebooks/move_qubit_along_a_line.ipynb
index 3c8d55da..82b7d6d7 100644
--- a/notebooks/move_qubit_along_a_line.ipynb
+++ b/notebooks/move_qubit_along_a_line.ipynb
@@ -45,6 +45,7 @@
             "outputs": [],
             "source": [
                 "import functools\n",
+                "import typing as ty\n",
                 "\n",
                 "import cirq\n",
                 "import matplotlib.pyplot as plt\n",
@@ -153,17 +154,24 @@
                 "\n",
                 "    def instantiate(\n",
                 "        self,\n",
-                "        x_plaquette: int,\n",
-                "        z_plaquette: int,\n",
-                "        overlap_plaquette1: int,\n",
-                "        overlap_plaquette2: int,\n",
-                "        *_: int,\n",
+                "        plaquette_indices: ty.Sequence[int],\n",
                 "    ) -> np.ndarray:\n",
-                "        arr = super().instantiate(x_plaquette, z_plaquette, *_)\n",
+                "        self._check_plaquette_number(plaquette_indices)\n",
+                "        (\n",
+                "            x_plaquette,\n",
+                "            z_plaquette,\n",
+                "            overlap_plaquette1,\n",
+                "            overlap_plaquette2,\n",
+                "        ) = plaquette_indices[:4]\n",
+                "        arr = super().instantiate([x_plaquette, z_plaquette])\n",
                 "        col_idx = -1 if self._overlap_at_tail else 0\n",
                 "        arr[::2, col_idx] = overlap_plaquette1\n",
                 "        arr[1::2, col_idx] = overlap_plaquette2\n",
-                "        return arr"
+                "        return arr\n",
+                "\n",
+                "    @property\n",
+                "    def expected_plaquettes_number(self) -> int:\n",
+                "        return 4"
             ]
         },
         {
diff --git a/setup.cfg b/setup.cfg
index 317e44ac..1fe8aae9 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -36,6 +36,7 @@ classifiers =
 packages = find_namespace:
 package_dir=
     = src
+include_package_data = True
 install_requires = 
     # See https://github.com/pypa/setuptools/issues/1951 for explanation
     # about why we prefer duplicating the list here.
@@ -48,6 +49,9 @@ install_requires =
     Flask==3.0.0
     flask_cors==3.0.10
 
+[options.package_data]
+tqec = py.typed
+
 [options.packages.find]
 where = src
 exclude = tests*
@@ -55,6 +59,7 @@ exclude = tests*
 [options.extras_require]
 testing = 
     pytest
+    mypy
 dev = 
     sinter
     pymatching
diff --git a/src/tqec/detectors/operation.py b/src/tqec/detectors/operation.py
index 9a24c797..90ed3dea 100644
--- a/src/tqec/detectors/operation.py
+++ b/src/tqec/detectors/operation.py
@@ -1,7 +1,7 @@
 from __future__ import annotations
 
 from dataclasses import dataclass
-from typing import Any
+from typing import Any, Sequence
 
 import cirq
 from tqec.exceptions import TQECException
@@ -262,7 +262,9 @@ def make_shift_coords(*shifts: int) -> cirq.Operation:
 
 def make_detector(
     local_coordinate_system_origin: cirq.GridQubit,
-    relative_measurements: list[tuple[cirq.GridQubit, int] | RelativeMeasurementData],
+    relative_measurements: Sequence[
+        tuple[cirq.GridQubit, int] | RelativeMeasurementData
+    ],
     time_coordinate: int = 0,
 ) -> cirq.Operation:
     """This is a helper function to make a :class:`Detector` operation with the
@@ -300,7 +302,9 @@ def make_detector(
 
 def make_observable(
     local_coordinate_system_origin: cirq.GridQubit,
-    relative_measurements: list[tuple[cirq.GridQubit, int] | RelativeMeasurementData],
+    relative_measurements: Sequence[
+        tuple[cirq.GridQubit, int] | RelativeMeasurementData
+    ],
     observable_index: int = 0,
 ) -> cirq.Operation:
     """This is a helper function to make a :class:`Observable` operation with the
diff --git a/src/tqec/display.py b/src/tqec/display.py
index 8a52f9fa..5de16e2e 100644
--- a/src/tqec/display.py
+++ b/src/tqec/display.py
@@ -2,22 +2,26 @@ from __future__ import annotations
 
 import math
 import pathlib
+import typing as ty
 
 from tqec.templates.base import Template
 from tqec.templates.composed import ComposedTemplate
 
 
-def display_template(template: Template, *plaquette_indices: int) -> None:
+def display_template(
+    template: Template, plaquette_indices: ty.Sequence[int] | None = None
+) -> None:
     """Display a template instance with ASCII output.
 
     Args:
         template: the Template instance to display.
-        *plaquette_indices: the plaquette indices that are forwarded to the call
+        plaquette_indices: the plaquette indices that are forwarded to the call
             to `template.instantiate` to get the actual template representation.
+            If None, default to ``range(1, template.expected_plaquettes_number + 1)``.
     """
-    if len(plaquette_indices) == 0:
+    if plaquette_indices is None:
         plaquette_indices = tuple(range(1, template.expected_plaquettes_number + 1))
-    arr = template.instantiate(*plaquette_indices)
+    arr = template.instantiate(plaquette_indices)
     for line in arr:
         for element in line:
             element = str(element) if element != 0 else "."
@@ -39,7 +43,7 @@ def display_templates_svg(
     svg files.
 
     Args:
-        templates: the TemplateOrchestrator instance to display.
+        templates: the ComposedTemplate instance to display.
         write_svg_file: the path to the SVG file to write.
         canvas_height: the height of the canvas in pixels to draw on.
         *plaquette_indices: the plaquette indices that are forwarded to the call
@@ -53,8 +57,8 @@ def display_templates_svg(
     template_list = templates._templates
     ul_positions = templates._compute_ul_absolute_position()
     box = templates._get_bounding_box_from_ul_positions(ul_positions)
-    box_width = box[1].x - box[0].x
-    box_height = box[1].y - box[0].y
+    box_width: float = box[1].x - box[0].x
+    box_height: float = box[1].y - box[0].y
     pad = max(box_width, box_height) * 0.1
     box_width += pad
     box_height += pad
@@ -64,19 +68,19 @@ def display_templates_svg(
     def rect(
         x: int, y: int, width: int, height: int, label: int = 0, outmost: bool = False
     ) -> list[str]:
-        x = (x - box[0].x + pad / 2) * scale_factor
-        y = (y - box[0].y + pad / 2) * scale_factor
-        width = width * scale_factor
-        height = height * scale_factor
+        x_scaled = (x - box[0].x + pad / 2) * scale_factor
+        y_scaled = (y - box[0].y + pad / 2) * scale_factor
+        width_scaled = width * scale_factor
+        height_scaled = height * scale_factor
         lines: list[str] = []
         stroke = "#00FF00" if outmost else "black"
         stroke_width = 3 if outmost else 2
         # Draw the rectangle
         lines.append(
-            f'<rect x="{x}" '
-            f'y="{y}" '
-            f'width="{width}" '
-            f'height="{height}" '
+            f'<rect x="{x_scaled}" '
+            f'y="{y_scaled}" '
+            f'width="{width_scaled}" '
+            f'height="{height_scaled}" '
             f'stroke="{stroke}" '
             f'stroke-width="{stroke_width}" '
             'fill="none" />'
@@ -84,8 +88,8 @@ def display_templates_svg(
         # Draw the plaquette index
         if label:
             lines.append(
-                f'<text x="{x + width / 2}" '
-                f'y="{y + height / 2}" '
+                f'<text x="{x_scaled + width_scaled / 2}" '
+                f'y="{y_scaled + height_scaled / 2}" '
                 'font-size="10" '
                 'text-anchor="middle" '
                 f'dominant-baseline="middle">{label}</text>'
@@ -105,7 +109,7 @@ def display_templates_svg(
             plaquette_indices[k]
             for k in templates._relative_position_graph.nodes[i]["plaquette_indices"]
         ]
-        arr = template.instantiate(*indices)
+        arr = template.instantiate(indices)
         outer_rects.extend(
             rect(ul_position.x, ul_position.y, len(arr[0]), len(arr), outmost=True)
         )
diff --git a/src/tqec/generation/circuit.py b/src/tqec/generation/circuit.py
index d3c58128..4140d8af 100644
--- a/src/tqec/generation/circuit.py
+++ b/src/tqec/generation/circuit.py
@@ -57,7 +57,7 @@ def generate_circuit(
     # instantiate the template with the appropriate plaquette indices.
     # Index 0 is "no plaquette" by convention and should not be included here.
     _indices = list(range(1, len(plaquettes) + 1))
-    template_plaquettes = template.instantiate(*_indices)
+    template_plaquettes = template.instantiate(_indices)
     increments = template.get_increments()
     # Plaquettes indices are starting at 1 in template_plaquettes. To avoid
     # offsets in the following code, we add an empty circuit at position 0.
diff --git a/src/tqec/plaquette/library/xx.py b/src/tqec/plaquette/library/xx.py
index fdf35161..6740f2ce 100644
--- a/src/tqec/plaquette/library/xx.py
+++ b/src/tqec/plaquette/library/xx.py
@@ -1,5 +1,4 @@
 import cirq
-
 from tqec.detectors.operation import make_detector
 from tqec.enums import PlaquetteOrientation
 from tqec.plaquette.plaquette import PlaquetteList, RoundedPlaquette
@@ -33,13 +32,19 @@ class XXInitialisationPlaquette(BaseXXPlaquette):
         data_qubits = [
             q.to_grid_qubit() for q in RoundedPlaquette.get_data_qubits(orientation)
         ]
-        detector = [
-            cirq.Moment(make_detector(
-                syndrome_qubit,
-                [(cirq.GridQubit(0, 0), -1)],
-                time_coordinate=0,
-            )),
-        ] if include_detector else []
+        detector = (
+            [
+                cirq.Moment(
+                    make_detector(
+                        syndrome_qubit,
+                        [(cirq.GridQubit(0, 0), -1)],
+                        time_coordinate=0,
+                    )
+                ),
+            ]
+            if include_detector
+            else []
+        )
         super().__init__(
             circuit=ScheduledCircuit(
                 cirq.Circuit(
@@ -52,8 +57,9 @@ class XXInitialisationPlaquette(BaseXXPlaquette):
                         cirq.Moment(cirq.CX(syndrome_qubit, data_qubits[0])),
                         cirq.Moment(cirq.CX(syndrome_qubit, data_qubits[1])),
                         cirq.Moment(cirq.H(syndrome_qubit)),
-                        cirq.Moment([cirq.M(syndrome_qubit)] + detector),
-                    ] + detector
+                        cirq.Moment([cirq.M(syndrome_qubit)]),
+                    ]
+                    + detector
                 ),
                 schedule,
             ),
@@ -74,16 +80,22 @@ class XXMemoryPlaquette(BaseXXPlaquette):
         data_qubits = [
             q.to_grid_qubit() for q in RoundedPlaquette.get_data_qubits(orientation)
         ]
-        detector = [
-            cirq.Moment(make_detector(
-                syndrome_qubit,
-                [
-                    (cirq.GridQubit(0, 0), -1),
-                    (cirq.GridQubit(0, 0), -2),
-                ],
-                time_coordinate=0,
-            )),
-        ] if include_detector else []
+        detector = (
+            [
+                cirq.Moment(
+                    make_detector(
+                        syndrome_qubit,
+                        [
+                            (cirq.GridQubit(0, 0), -1),
+                            (cirq.GridQubit(0, 0), -2),
+                        ],
+                        time_coordinate=0,
+                    )
+                ),
+            ]
+            if include_detector
+            else []
+        )
         super().__init__(
             circuit=ScheduledCircuit(
                 cirq.Circuit(
@@ -97,7 +109,8 @@ class XXMemoryPlaquette(BaseXXPlaquette):
                         cirq.Moment(cirq.CX(syndrome_qubit, data_qubits[1])),
                         cirq.Moment(cirq.H(syndrome_qubit)),
                         cirq.Moment(cirq.M(syndrome_qubit)),
-                    ] + detector
+                    ]
+                    + detector
                 ),
                 schedule,
             ),
@@ -117,21 +130,22 @@ class XXFinalMeasurementPlaquette(BaseXXPlaquette):
         data_qubits = [
             q.to_grid_qubit() for q in RoundedPlaquette.get_data_qubits(orientation)
         ]
-        detector = [
-            cirq.Moment(
-                make_detector(
-                    syndrome_qubit,
-                    [
-                        (cirq.GridQubit(0, 0), -1),
-                        *[
-                            (dq - syndrome_qubit, -1)
-                            for dq in data_qubits
+        detector = (
+            [
+                cirq.Moment(
+                    make_detector(
+                        syndrome_qubit,
+                        [
+                            (cirq.GridQubit(0, 0), -1),
+                            *[(dq - syndrome_qubit, -1) for dq in data_qubits],
                         ],
-                    ],
-                    time_coordinate=1,
+                        time_coordinate=1,
+                    )
                 )
-            )
-        ] if include_detector else []
+            ]
+            if include_detector
+            else []
+        )
         super().__init__(
             circuit=ScheduledCircuit(
                 cirq.Circuit(
@@ -142,7 +156,8 @@ class XXFinalMeasurementPlaquette(BaseXXPlaquette):
                                 for q in data_qubits
                             ]
                         ),
-                    ] + detector
+                    ]
+                    + detector
                 ),
             ),
             orientation=orientation,
diff --git a/src/tqec/plaquette/schedule.py b/src/tqec/plaquette/schedule.py
index da8b69ee..c8d1ba1b 100644
--- a/src/tqec/plaquette/schedule.py
+++ b/src/tqec/plaquette/schedule.py
@@ -250,7 +250,7 @@ class ScheduledCircuit:
         the union of the qubits of all the operations performed on and the origin of all
         the detectors.
         """
-        operation_qubits = set(self.raw_circuit.all_qubits())
+        operation_qubits = self.qubits
         detector_origins = set(detector.origin for detector in self.detectors)
         return frozenset(operation_qubits.union(detector_origins))
 
@@ -275,7 +275,10 @@ class ScheduledCircuit:
         """
 
         def remap_qubits(op: cirq.Operation) -> cirq.Operation:
-            op = op.transform_qubits(qubit_map)
+            # See https://github.com/QCHackers/tqec/pull/127#issuecomment-1934133595
+            # for an explanation on why this cast has been introduced.
+            cast_qubit_map = typing.cast(dict[cirq.Qid, cirq.Qid], qubit_map)
+            op = op.transform_qubits(cast_qubit_map)
             untagged = op.untagged
             if isinstance(op.gate, cirq.MeasurementGate):
                 return cirq.measure(*op.qubits).with_tags(*op.tags)
diff --git a/src/tqec/py.typed b/src/tqec/py.typed
new file mode 100644
index 00000000..e69de29b
diff --git a/src/tqec/templates/atomic/rectangle.py b/src/tqec/templates/atomic/rectangle.py
index 56e5447b..a78db9bb 100644
--- a/src/tqec/templates/atomic/rectangle.py
+++ b/src/tqec/templates/atomic/rectangle.py
@@ -59,7 +59,9 @@ class AlternatingRectangleTemplate(Template):
         self._width = width
         self._height = height
 
-    def instantiate(self, p1: int, p2: int, *_: int) -> numpy.ndarray:
+    def instantiate(self, plaquette_indices: ty.Sequence[int]) -> numpy.ndarray:
+        self._check_plaquette_number(plaquette_indices)
+        p1, p2 = plaquette_indices[:2]
         ret = numpy.zeros(self.shape.to_numpy_shape(), dtype=int)
         odd = slice(0, None, 2)
         even = slice(1, None, 2)
@@ -141,12 +143,12 @@ class RawRectangleTemplate(Template):
         super().__init__(default_x_increment, default_y_increment)
         if not indices or not indices[0]:
             raise TQECException(
-                f"You should provide at least one index to {__class__.__name__}."
+                f"You should provide at least one index to {self.__class__.__name__}."
             )
         line_lens = set(len(line) for line in indices)
         if len(line_lens) > 1:
             raise TQECException(
-                f"The 2-dimensional array provided to {__class__.__name__} should "
+                f"The 2-dimensional array provided to {self.__class__.__name__} should "
                 "be rectangular. Please provide an array with equally-sized rows."
             )
         all_indices: set[int] = set().union(*[set(line) for line in indices])
@@ -163,7 +165,8 @@ class RawRectangleTemplate(Template):
             )
         self._indices = indices
 
-    def instantiate(self, *plaquette_indices: int) -> numpy.ndarray:
+    def instantiate(self, plaquette_indices: ty.Sequence[int]) -> numpy.ndarray:
+        self._check_plaquette_number(plaquette_indices)
         try:
             # Use numpy indexing to instantiate the raw values.
             plaquette_indices_array = numpy.array(plaquette_indices, dtype=int)
diff --git a/src/tqec/templates/atomic/square.py b/src/tqec/templates/atomic/square.py
index f407c338..6cc7557f 100644
--- a/src/tqec/templates/atomic/square.py
+++ b/src/tqec/templates/atomic/square.py
@@ -100,15 +100,9 @@ class AlternatingCornerSquareTemplate(Template):
         self._corner_position = corner_position
         self._top_plaquettes_on_diagonal = top_plaquettes_on_diagonal
 
-    def instantiate(
-        self,
-        p1: int,
-        p2: int,
-        p1_flipped: int,
-        p2_flipped: int,
-        corner_plaquette: int,
-        *_: int,
-    ) -> numpy.ndarray:
+    def instantiate(self, plaquette_indices: ty.Sequence[int]) -> numpy.ndarray:
+        self._check_plaquette_number(plaquette_indices)
+        p1, p2, p1_flipped, p2_flipped, corner_plaquette = plaquette_indices[:5]
         ret = numpy.zeros(self.shape.to_numpy_shape(), dtype=int)
         # Fill ret as if it was in the upper-left corner and then correct
         ret[0, 0] = corner_plaquette
diff --git a/src/tqec/templates/base.py b/src/tqec/templates/base.py
index 59e4240a..4096a6b6 100644
--- a/src/tqec/templates/base.py
+++ b/src/tqec/templates/base.py
@@ -81,12 +81,32 @@ class Template(JSONEncodable):
             default_x_increment, default_y_increment
         )
 
+    def _check_plaquette_number(self, plaquette_indices: ty.Sequence[int]) -> None:
+        """Checks the number of provided plaquettes.
+
+        This method should be called to check that the number of plaquette indices
+        provided to the ``instantiate`` method is correct.
+
+        Args:
+            plaquette_indices: the indices provided to the ``instantiate`` method.
+
+        Raises:
+            TQECError: when there is not enough plaquette indices to instantiate
+                the ``Template`` instance.
+        """
+        if len(plaquette_indices) < self.expected_plaquettes_number:
+            raise TQECException(
+                f"{self.__class__.__name__}.instanciate needs "
+                f"{self.expected_plaquettes_number} plaquettes, but only "
+                f"{len(plaquette_indices)} were provided."
+            )
+
     @abstractmethod
-    def instantiate(self, *plaquette_indices: int) -> numpy.ndarray:
+    def instantiate(self, plaquette_indices: ty.Sequence[int]) -> numpy.ndarray:
         """Generate the numpy array representing the template.
 
         Args:
-            *plaquette_indices: the plaquette indices that will be forwarded to
+            plaquette_indices: the plaquette indices that will be forwarded to
                 the underlying Shape instance's instantiate method.
 
         Returns:
diff --git a/src/tqec/templates/composed.py b/src/tqec/templates/composed.py
index a8d33038..b581356d 100644
--- a/src/tqec/templates/composed.py
+++ b/src/tqec/templates/composed.py
@@ -110,7 +110,7 @@ class ComposedTemplate(Template):
             raise TQECException(
                 f"Asking for element identified by {template_id} when only "
                 f"{len(self._templates)} templates have been added to "
-                f"the {__class__.__name__} instance."
+                f"the {self.__class__.__name__} instance."
             )
 
     def add_template(
@@ -379,16 +379,16 @@ class ComposedTemplate(Template):
             y = tul.y - bbul.y
             # Numpy indexing is (y, x) in our coordinate system convention.
             ret[y : y + tshapey, x : x + tshapex] = template.instantiate(
-                *plaquette_indices
+                plaquette_indices
             )
 
         return ret
 
-    def instantiate(self, *plaquette_indices: int) -> numpy.ndarray:
+    def instantiate(self, plaquette_indices: ty.Sequence[int]) -> numpy.ndarray:
         """Generate the numpy array representing the template.
 
         Args:
-            *plaquette_indices: the plaquette indices that will be used to
+            plaquette_indices: the plaquette indices that will be used to
                 instantiate the different orchestrated templates.
 
         Returns:
@@ -411,7 +411,7 @@ class ComposedTemplate(Template):
         """
         if 0 in plaquette_indices:
             raise TQECException(
-                f"{__class__.__name__} does not expect a plaquette 0 anymore."
+                f"{self.__class__.__name__} does not expect a plaquette 0 anymore."
             )
         if len(plaquette_indices) != self.expected_plaquettes_number:
             raise TQECException(
@@ -453,10 +453,10 @@ class ComposedTemplate(Template):
 
     def to_dict(self) -> dict[str, ty.Any]:
         return {
-            # __class__ is "TemplateOrchestrator" here, whatever the type of self is. This is different
+            # self.__class__ is "ComposedTemplate" here, whatever the type of self is. This is different
             # from what is done in the Template base class. This is done to avoid users subclassing this
             # class and having a subclass name we do not control in the "type" entry.
-            "type": __class__.__name__,
+            "type": self.__class__.__name__,
             "kwargs": {
                 "templates": [t.to_dict() for t in self._templates],
             },


Test patch:
diff --git a/src/tqec/templates/atomic/rectangle_test.py b/src/tqec/templates/atomic/rectangle_test.py
index 85df9429..f4c1acfc 100644
--- a/src/tqec/templates/atomic/rectangle_test.py
+++ b/src/tqec/templates/atomic/rectangle_test.py
@@ -65,7 +65,7 @@ def test_rectangle_template_one_fixed_scaling_instantiate_default_plaquettes(
     dim2x2, dim2
 ):
     template = AlternatingRectangleTemplate(dim2x2, dim2)
-    arr = template.instantiate(1, 2)
+    arr = template.instantiate([1, 2])
     numpy.testing.assert_equal(arr, [[1, 2, 1, 2], [2, 1, 2, 1]])
 
 
@@ -73,7 +73,7 @@ def test_rectangle_template_one_fixed_scaling_instantiate_random_plaquettes(
     dim2x2, dim2
 ):
     template = AlternatingRectangleTemplate(dim2x2, dim2)
-    arr = template.instantiate(78, 195)
+    arr = template.instantiate([78, 195])
     numpy.testing.assert_equal(arr, [[78, 195, 78, 195], [195, 78, 195, 78]])
 
 
@@ -140,25 +140,25 @@ def test_raw_rectangle_larger_expected_plaquettes_number():
 
 def test_raw_rectangle_simple_instantiate():
     template = RawRectangleTemplate([[0]])
-    arr = template.instantiate(1)
+    arr = template.instantiate([1])
     numpy.testing.assert_equal(arr, [[1]])
 
 
 def test_raw_rectangle_simple_instantiate_random_plaquette_index():
     template = RawRectangleTemplate([[0]])
-    arr = template.instantiate(345897)
+    arr = template.instantiate([345897])
     numpy.testing.assert_equal(arr, [[345897]])
 
 
 def test_raw_rectangle_larger_instantiate():
     template = RawRectangleTemplate([[0], [1], [2]])
-    arr = template.instantiate(3, 2, 1)
+    arr = template.instantiate([3, 2, 1])
     numpy.testing.assert_equal(arr, [[3], [2], [1]])
 
 
 def test_raw_rectangle_larger_instantiate_different_order():
     template = RawRectangleTemplate([[0], [2], [1]])
-    arr = template.instantiate(3, 2, 1)
+    arr = template.instantiate([3, 2, 1])
     numpy.testing.assert_equal(arr, [[3], [1], [2]])
 
 
diff --git a/src/tqec/templates/atomic/square_test.py b/src/tqec/templates/atomic/square_test.py
index cc4ea9de..dc316587 100644
--- a/src/tqec/templates/atomic/square_test.py
+++ b/src/tqec/templates/atomic/square_test.py
@@ -55,7 +55,7 @@ def test_square_template_one_fixed_scaling(dim2):
 
 def test_square_template_instantiate_default_plaquettes(dim2x2):
     template = AlternatingSquareTemplate(dim2x2)
-    arr = template.instantiate(1, 2)
+    arr = template.instantiate([1, 2])
     numpy.testing.assert_equal(
         arr, [[1, 2, 1, 2], [2, 1, 2, 1], [1, 2, 1, 2], [2, 1, 2, 1]]
     )
@@ -63,7 +63,7 @@ def test_square_template_instantiate_default_plaquettes(dim2x2):
 
 def test_square_template_one_fixed_scaling_instantiate_random_plaquettes(dim2x2, dim2):
     template = AlternatingSquareTemplate(dim2x2, dim2)
-    arr = template.instantiate(78, 195)
+    arr = template.instantiate([78, 195])
     numpy.testing.assert_equal(
         arr,
         [