From 7a87d013888044c946c2b49eb83b9f27a3d60c73 Mon Sep 17 00:00:00 2001 From: GoldBro233 Date: Wed, 17 Sep 2025 20:56:17 +0800 Subject: [PATCH] Init: Finish basic game function. --- .gitignore | 16 ++++++ README.md | 36 ++++++++++++++ biome.json | 34 +++++++++++++ bun.lock | 123 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 25 ++++++++++ rsbuild.config.ts | 6 +++ src/App.css | 90 +++++++++++++++++++++++++++++++++ src/App.tsx | 79 +++++++++++++++++++++++++++++ src/env.d.ts | 11 +++++ src/index.tsx | 12 +++++ tsconfig.json | 25 ++++++++++ 11 files changed, 457 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 biome.json create mode 100644 bun.lock create mode 100644 package.json create mode 100644 rsbuild.config.ts create mode 100644 src/App.css create mode 100644 src/App.tsx create mode 100644 src/env.d.ts create mode 100644 src/index.tsx create mode 100644 tsconfig.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6f3092c --- /dev/null +++ b/.gitignore @@ -0,0 +1,16 @@ +# Local +.DS_Store +*.local +*.log* + +# Dist +node_modules +dist/ + +# Profile +.rspack-profile-*/ + +# IDE +.vscode/* +!.vscode/extensions.json +.idea diff --git a/README.md b/README.md new file mode 100644 index 0000000..a80dc73 --- /dev/null +++ b/README.md @@ -0,0 +1,36 @@ +# Rsbuild project + +## Setup + +Install the dependencies: + +```bash +pnpm install +``` + +## Get started + +Start the dev server, and the app will be available at [http://localhost:3000](http://localhost:3000). + +```bash +pnpm dev +``` + +Build the app for production: + +```bash +pnpm build +``` + +Preview the production build locally: + +```bash +pnpm preview +``` + +## Learn more + +To learn more about Rsbuild, check out the following resources: + +- [Rsbuild documentation](https://rsbuild.rs) - explore Rsbuild features and APIs. +- [Rsbuild GitHub repository](https://github.com/web-infra-dev/rsbuild) - your feedback and contributions are welcome! diff --git a/biome.json b/biome.json new file mode 100644 index 0000000..53f38c7 --- /dev/null +++ b/biome.json @@ -0,0 +1,34 @@ +{ + "$schema": "./node_modules/@biomejs/biome/configuration_schema.json", + "assist": { + "actions": { + "source": { + "organizeImports": "on" + } + } + }, + "vcs": { + "enabled": true, + "clientKind": "git", + "useIgnoreFile": true + }, + "formatter": { + "indentStyle": "space" + }, + "javascript": { + "formatter": { + "quoteStyle": "single" + } + }, + "css": { + "parser": { + "cssModules": true + } + }, + "linter": { + "enabled": true, + "rules": { + "recommended": true + } + } +} diff --git a/bun.lock b/bun.lock new file mode 100644 index 0000000..aba983a --- /dev/null +++ b/bun.lock @@ -0,0 +1,123 @@ +{ + "lockfileVersion": 1, + "workspaces": { + "": { + "name": "rsbuild-react-ts", + "dependencies": { + "react": "^19.1.1", + "react-dom": "^19.1.1", + }, + "devDependencies": { + "@biomejs/biome": "2.2.3", + "@rsbuild/core": "^1.5.4", + "@rsbuild/plugin-react": "^1.4.0", + "@types/react": "^19.1.12", + "@types/react-dom": "^19.1.9", + "typescript": "^5.9.2", + }, + }, + }, + "packages": { + "@biomejs/biome": ["@biomejs/biome@2.2.3", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.2.3", "@biomejs/cli-darwin-x64": "2.2.3", "@biomejs/cli-linux-arm64": "2.2.3", "@biomejs/cli-linux-arm64-musl": "2.2.3", "@biomejs/cli-linux-x64": "2.2.3", "@biomejs/cli-linux-x64-musl": "2.2.3", "@biomejs/cli-win32-arm64": "2.2.3", "@biomejs/cli-win32-x64": "2.2.3" }, "bin": { "biome": "bin/biome" } }, "sha512-9w0uMTvPrIdvUrxazZ42Ib7t8Y2yoGLKLdNne93RLICmaHw7mcLv4PPb5LvZLJF3141gQHiCColOh/v6VWlWmg=="], + + "@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.2.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-OrqQVBpadB5eqzinXN4+Q6honBz+tTlKVCsbEuEpljK8ASSItzIRZUA02mTikl3H/1nO2BMPFiJ0nkEZNy3B1w=="], + + "@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.2.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-OCdBpb1TmyfsTgBAM1kPMXyYKTohQ48WpiN9tkt9xvU6gKVKHY4oVwteBebiOqyfyzCNaSiuKIPjmHjUZ2ZNMg=="], + + "@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.2.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-g/Uta2DqYpECxG+vUmTAmUKlVhnGEcY7DXWgKP8ruLRa8Si1QHsWknPY3B/wCo0KgYiFIOAZ9hjsHfNb9L85+g=="], + + "@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.2.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-q3w9jJ6JFPZPeqyvwwPeaiS/6NEszZ+pXKF+IczNo8Xj6fsii45a4gEEicKyKIytalV+s829ACZujQlXAiVLBQ=="], + + "@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.2.3", "", { "os": "linux", "cpu": "x64" }, "sha512-LEtyYL1fJsvw35CxrbQ0gZoxOG3oZsAjzfRdvRBRHxOpQ91Q5doRVjvWW/wepgSdgk5hlaNzfeqpyGmfSD0Eyw=="], + + "@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.2.3", "", { "os": "linux", "cpu": "x64" }, "sha512-y76Dn4vkP1sMRGPFlNc+OTETBhGPJ90jY3il6jAfur8XWrYBQV3swZ1Jo0R2g+JpOeeoA0cOwM7mJG6svDz79w=="], + + "@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.2.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-Ms9zFYzjcJK7LV+AOMYnjN3pV3xL8Prxf9aWdDVL74onLn5kcvZ1ZMQswE5XHtnd/r/0bnUd928Rpbs14BzVmA=="], + + "@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.2.3", "", { "os": "win32", "cpu": "x64" }, "sha512-gvCpewE7mBwBIpqk1YrUqNR4mCiyJm6UI3YWQQXkedSSEwzRdodRpaKhbdbHw1/hmTWOVXQ+Eih5Qctf4TCVOQ=="], + + "@emnapi/core": ["@emnapi/core@1.5.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" } }, "sha512-sbP8GzB1WDzacS8fgNPpHlp6C9VZe+SJP3F90W9rLemaQj2PzIuTEl1qDOYQf58YIpyjViI24y9aPWCjEzY2cg=="], + + "@emnapi/runtime": ["@emnapi/runtime@1.5.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ=="], + + "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="], + + "@module-federation/error-codes": ["@module-federation/error-codes@0.18.0", "", {}, "sha512-Woonm8ehyVIUPXChmbu80Zj6uJkC0dD9SJUZ/wOPtO8iiz/m+dkrOugAuKgoiR6qH4F+yorWila954tBz4uKsQ=="], + + "@module-federation/runtime": ["@module-federation/runtime@0.18.0", "", { "dependencies": { "@module-federation/error-codes": "0.18.0", "@module-federation/runtime-core": "0.18.0", "@module-federation/sdk": "0.18.0" } }, "sha512-+C4YtoSztM7nHwNyZl6dQKGUVJdsPrUdaf3HIKReg/GQbrt9uvOlUWo2NXMZ8vDAnf/QRrpSYAwXHmWDn9Obaw=="], + + "@module-federation/runtime-core": ["@module-federation/runtime-core@0.18.0", "", { "dependencies": { "@module-federation/error-codes": "0.18.0", "@module-federation/sdk": "0.18.0" } }, "sha512-ZyYhrDyVAhUzriOsVfgL6vwd+5ebYm595Y13KeMf6TKDRoUHBMTLGQ8WM4TDj8JNsy7LigncK8C03fn97of0QQ=="], + + "@module-federation/runtime-tools": ["@module-federation/runtime-tools@0.18.0", "", { "dependencies": { "@module-federation/runtime": "0.18.0", "@module-federation/webpack-bundler-runtime": "0.18.0" } }, "sha512-fSga9o4t1UfXNV/Kh6qFvRyZpPp3EHSPRISNeyT8ZoTpzDNiYzhtw0BPUSSD8m6C6XQh2s/11rI4g80UY+d+hA=="], + + "@module-federation/sdk": ["@module-federation/sdk@0.18.0", "", {}, "sha512-Lo/Feq73tO2unjmpRfyyoUkTVoejhItXOk/h5C+4cistnHbTV8XHrW/13fD5e1Iu60heVdAhhelJd6F898Ve9A=="], + + "@module-federation/webpack-bundler-runtime": ["@module-federation/webpack-bundler-runtime@0.18.0", "", { "dependencies": { "@module-federation/runtime": "0.18.0", "@module-federation/sdk": "0.18.0" } }, "sha512-TEvErbF+YQ+6IFimhUYKK3a5wapD90d90sLsNpcu2kB3QGT7t4nIluE25duXuZDVUKLz86tEPrza/oaaCWTpvQ=="], + + "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.0.5", "", { "dependencies": { "@emnapi/core": "^1.5.0", "@emnapi/runtime": "^1.5.0", "@tybys/wasm-util": "^0.10.1" } }, "sha512-TBr9Cf9onSAS2LQ2+QHx6XcC6h9+RIzJgbqG3++9TUZSH204AwEy5jg3BTQ0VATsyoGj4ee49tN/y6rvaOOtcg=="], + + "@rsbuild/core": ["@rsbuild/core@1.5.6", "", { "dependencies": { "@rspack/core": "1.5.3", "@rspack/lite-tapable": "~1.0.1", "@swc/helpers": "^0.5.17", "core-js": "~3.45.1", "jiti": "^2.5.1" }, "bin": { "rsbuild": "bin/rsbuild.js" } }, "sha512-EbJ9HlkI2Y2C59pAv877rHz3qS+5dy9anXxagOOXEHt4u3/uqSj7pcz3cD+UWkFQ4XOGJ3mMwkPfR7EE24t12A=="], + + "@rsbuild/plugin-react": ["@rsbuild/plugin-react@1.4.0", "", { "dependencies": { "@rspack/plugin-react-refresh": "^1.5.0", "react-refresh": "^0.17.0" }, "peerDependencies": { "@rsbuild/core": "1.x" } }, "sha512-YhhOUOonJBjnKpUf7E4iXKidldPWAGmYBRtDjQgcSmW4tbW0DasFpNCqLn5870Q2Ly6oCU06sLv+8G597I36+w=="], + + "@rspack/binding": ["@rspack/binding@1.5.3", "", { "optionalDependencies": { "@rspack/binding-darwin-arm64": "1.5.3", "@rspack/binding-darwin-x64": "1.5.3", "@rspack/binding-linux-arm64-gnu": "1.5.3", "@rspack/binding-linux-arm64-musl": "1.5.3", "@rspack/binding-linux-x64-gnu": "1.5.3", "@rspack/binding-linux-x64-musl": "1.5.3", "@rspack/binding-wasm32-wasi": "1.5.3", "@rspack/binding-win32-arm64-msvc": "1.5.3", "@rspack/binding-win32-ia32-msvc": "1.5.3", "@rspack/binding-win32-x64-msvc": "1.5.3" } }, "sha512-bWAKligHxelx3XxOgFmK6k1vR+ANxjBXLXTmgOiZxsJNScHJap3HYViXWJHKj5jvdXEvg9sC8TE7WNctCfa8iQ=="], + + "@rspack/binding-darwin-arm64": ["@rspack/binding-darwin-arm64@1.5.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-8R1uqr5E2CzRZjsA1QLXkD4xwcsiHmLJTIzCNj9QJ4+lCw6XgtPqpHZuk3zNROLayijEKwotGXJFHJIbgv1clA=="], + + "@rspack/binding-darwin-x64": ["@rspack/binding-darwin-x64@1.5.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-R4sb+scZbaBasyS+TQ6dRvv+f/2ZaZ0nXgY7t/ehcuGRvUz3S7FTJF/Mr/Ocxj5oVfb06thDAm+zaAVg+hsM9A=="], + + "@rspack/binding-linux-arm64-gnu": ["@rspack/binding-linux-arm64-gnu@1.5.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-NeDJJRNTLx8wOQT+si90th7cdt04I2F697Mp5w0a3Jf3XHAmsraBMn0phdLGWJoUWrrfVGthjgZDl5lcc1UHEA=="], + + "@rspack/binding-linux-arm64-musl": ["@rspack/binding-linux-arm64-musl@1.5.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-M9utPq9s7zJkKapUlyfwwYT/rjZ+XM56NHQMUH9MVYgMJIl+66QURgWUXCAbuogxf1XWayUGQaZsgypoOrTG9A=="], + + "@rspack/binding-linux-x64-gnu": ["@rspack/binding-linux-x64-gnu@1.5.3", "", { "os": "linux", "cpu": "x64" }, "sha512-AsKqU4pIg0yYg1VvSEU0NspIwCexqXD2AYE0wujAAwBo0hOfbt5dl1JCK7idiZdIQvoFg86HbfGwdHIVcFLI0w=="], + + "@rspack/binding-linux-x64-musl": ["@rspack/binding-linux-x64-musl@1.5.3", "", { "os": "linux", "cpu": "x64" }, "sha512-0aHuvDef92pFZaHhk8Mp8RP9TfTzhQ+Pjqrc2ixRS/FeJA+jVB2CSaYlAPP4QrgXdmW7tewSxEw8hYhF9CNv/A=="], + + "@rspack/binding-wasm32-wasi": ["@rspack/binding-wasm32-wasi@1.5.3", "", { "dependencies": { "@napi-rs/wasm-runtime": "^1.0.1" }, "cpu": "none" }, "sha512-Y7KN/ZRuWcFdjCzuZE0JsPwTqJAz1aipJsEOI3whBUj9Va2RwbR9r3vbW6OscS0Wm3rTJAfqH0xwx9x3GksnAw=="], + + "@rspack/binding-win32-arm64-msvc": ["@rspack/binding-win32-arm64-msvc@1.5.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-I9SqobDwFwcIUNzr+VwvR2lUGqfarOpFDp7mZmA6+qO/V0yJxS0aqBIwNoZB/UFPbUh71OdmFavBzcTYE9vPSg=="], + + "@rspack/binding-win32-ia32-msvc": ["@rspack/binding-win32-ia32-msvc@1.5.3", "", { "os": "win32", "cpu": "ia32" }, "sha512-pPSzSycfK03lLNxzwEkrRUfqETB7y0KEEbO0HcGX63EC9Ne4SILJfkkH55G0PO4aT/dfAosAlkf6V64ATgrHGA=="], + + "@rspack/binding-win32-x64-msvc": ["@rspack/binding-win32-x64-msvc@1.5.3", "", { "os": "win32", "cpu": "x64" }, "sha512-He/GrFVrCZ4gBrHSxGd7mnwk9A9BDkAeZZEBnfK4n/HfXxU32WX5jiAGacFoJQYFLDOWTAcmxFad37TSs61zXw=="], + + "@rspack/core": ["@rspack/core@1.5.3", "", { "dependencies": { "@module-federation/runtime-tools": "0.18.0", "@rspack/binding": "1.5.3", "@rspack/lite-tapable": "1.0.1" }, "peerDependencies": { "@swc/helpers": ">=0.5.1" }, "optionalPeers": ["@swc/helpers"] }, "sha512-EMNXysJyqsfd2aVys5C7GDZKaLEcoN5qgs7ZFhWOWJGKgBqjdKTljyRTd4RRZV4fV6iAko/WrxnAxmzZNk8mjA=="], + + "@rspack/lite-tapable": ["@rspack/lite-tapable@1.0.1", "", {}, "sha512-VynGOEsVw2s8TAlLf/uESfrgfrq2+rcXB1muPJYBWbsm1Oa6r5qVQhjA5ggM6z/coYPrsVMgovl3Ff7Q7OCp1w=="], + + "@rspack/plugin-react-refresh": ["@rspack/plugin-react-refresh@1.5.1", "", { "dependencies": { "error-stack-parser": "^2.1.4", "html-entities": "^2.6.0" }, "peerDependencies": { "react-refresh": ">=0.10.0 <1.0.0", "webpack-hot-middleware": "2.x" }, "optionalPeers": ["webpack-hot-middleware"] }, "sha512-GT3KV1GSmIXO8dQg6taNf9AuZ8XHEs8cZqRn5mC2GT6DPCvUA/ZKezIGsHTyH+HMEbJnJ/T8yYeJnvnzuUcqAQ=="], + + "@swc/helpers": ["@swc/helpers@0.5.17", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A=="], + + "@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="], + + "@types/react": ["@types/react@19.1.13", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-hHkbU/eoO3EG5/MZkuFSKmYqPbSVk5byPFa3e7y/8TybHiLMACgI8seVYlicwk7H5K/rI2px9xrQp/C+AUDTiQ=="], + + "@types/react-dom": ["@types/react-dom@19.1.9", "", { "peerDependencies": { "@types/react": "^19.0.0" } }, "sha512-qXRuZaOsAdXKFyOhRBg6Lqqc0yay13vN7KrIg4L7N4aaHN68ma9OK3NE1BoDFgFOTfM7zg+3/8+2n8rLUH3OKQ=="], + + "core-js": ["core-js@3.45.1", "", {}, "sha512-L4NPsJlCfZsPeXukyzHFlg/i7IIVwHSItR0wg0FLNqYClJ4MQYTYLbC7EkjKYRLZF2iof2MUgN0EGy7MdQFChg=="], + + "csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="], + + "error-stack-parser": ["error-stack-parser@2.1.4", "", { "dependencies": { "stackframe": "^1.3.4" } }, "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ=="], + + "html-entities": ["html-entities@2.6.0", "", {}, "sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ=="], + + "jiti": ["jiti@2.5.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w=="], + + "react": ["react@19.1.1", "", {}, "sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ=="], + + "react-dom": ["react-dom@19.1.1", "", { "dependencies": { "scheduler": "^0.26.0" }, "peerDependencies": { "react": "^19.1.1" } }, "sha512-Dlq/5LAZgF0Gaz6yiqZCf6VCcZs1ghAJyrsu84Q/GT0gV+mCxbfmKNoGRKBYMJ8IEdGPqu49YWXD02GCknEDkw=="], + + "react-refresh": ["react-refresh@0.17.0", "", {}, "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ=="], + + "scheduler": ["scheduler@0.26.0", "", {}, "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA=="], + + "stackframe": ["stackframe@1.3.4", "", {}, "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw=="], + + "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + + "typescript": ["typescript@5.9.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A=="], + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..e76e8ef --- /dev/null +++ b/package.json @@ -0,0 +1,25 @@ +{ + "name": "rsbuild-react-ts", + "version": "1.0.0", + "private": true, + "type": "module", + "scripts": { + "build": "rsbuild build", + "check": "biome check --write", + "dev": "rsbuild dev --open", + "format": "biome format --write", + "preview": "rsbuild preview" + }, + "dependencies": { + "react": "^19.1.1", + "react-dom": "^19.1.1" + }, + "devDependencies": { + "@biomejs/biome": "2.2.3", + "@rsbuild/core": "^1.5.4", + "@rsbuild/plugin-react": "^1.4.0", + "@types/react": "^19.1.12", + "@types/react-dom": "^19.1.9", + "typescript": "^5.9.2" + } +} diff --git a/rsbuild.config.ts b/rsbuild.config.ts new file mode 100644 index 0000000..c9962d3 --- /dev/null +++ b/rsbuild.config.ts @@ -0,0 +1,6 @@ +import { defineConfig } from '@rsbuild/core'; +import { pluginReact } from '@rsbuild/plugin-react'; + +export default defineConfig({ + plugins: [pluginReact()], +}); diff --git a/src/App.css b/src/App.css new file mode 100644 index 0000000..6326128 --- /dev/null +++ b/src/App.css @@ -0,0 +1,90 @@ +* { + box-sizing: border-box; +} + +body { + font-family: sans-serif; + margin: 20px; + padding: 0; +} + +h1 { + margin-top: 0; + font-size: 22px; +} + +h2 { + margin-top: 0; + font-size: 20px; +} + +h3 { + margin-top: 0; + font-size: 18px; +} + +h4 { + margin-top: 0; + font-size: 16px; +} + +h5 { + margin-top: 0; + font-size: 14px; +} + +h6 { + margin-top: 0; + font-size: 12px; +} + +code { + font-size: 1.2em; +} + +ul { + padding-inline-start: 20px; +} + +* { + box-sizing: border-box; +} + +body { + font-family: sans-serif; + margin: 20px; + padding: 0; +} + +.square { + background: #fff; + border: 1px solid #999; + float: left; + font-size: 24px; + font-weight: bold; + line-height: 34px; + height: 34px; + margin-right: -1px; + margin-top: -1px; + padding: 0; + text-align: center; + width: 34px; +} + +.board-row:after { + clear: both; + content: ''; + display: table; +} + +.status { + margin-bottom: 10px; +} +.game { + display: flex; + flex-direction: row; +} + +.game-info { + margin-left: 20px; +} \ No newline at end of file diff --git a/src/App.tsx b/src/App.tsx new file mode 100644 index 0000000..2edc6de --- /dev/null +++ b/src/App.tsx @@ -0,0 +1,79 @@ +import { useState } from "react" + +interface SquareProps { + value: 'X' | 'O' | null; + onSquareClick: () => void; +} + +function Square({ + value, onSquareClick}: SquareProps) { + return +} + +export default function Board() { + const [XIsNext, setXIsNext] = useState(true); + const [squares, setSquares] = useState(Array(9).fill(null)); + + const winner = calculateWinner(squares); + let status; + if (winner) { + status = "Winner: " + winner; + } else { + status = "Next player: " + (XIsNext ? "X" : "O"); + } + + function handleClick (i: number) { + if (squares[i] || calculateWinner(squares)) { + return; + } + const nextSquares = squares.slice(); + if (XIsNext) { + nextSquares[i] = "X"; + } else { + nextSquares[i] = "O"; + } + setSquares(nextSquares); + setXIsNext(!XIsNext); + } + + return( + <> +
{status}
+
+ handleClick(0)}/> + handleClick(1)}/> + handleClick(2)}/> +
+
+ handleClick(3)}/> + handleClick(4)}/> + handleClick(5)}/> +
+
+ handleClick(6)}/> + handleClick(7)}/> + handleClick(8)}/> +
+ + ) +} + +function calculateWinner(squares: Array) { + const lines = [ + [0, 1, 2], + [3, 4, 5], + [6, 7, 8], + [0, 3, 6], + [1, 4, 7], + [2, 5, 8], + [0, 4, 8], + [2, 4, 6] + ]; + for (let i = 0; i < lines.length; i++) { + const [a, b, c] = lines[i]; + if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) { + return squares[a]; + } + } + return null; +} \ No newline at end of file diff --git a/src/env.d.ts b/src/env.d.ts new file mode 100644 index 0000000..698ba8b --- /dev/null +++ b/src/env.d.ts @@ -0,0 +1,11 @@ +/// + +/** + * Imports the SVG file as a React component. + * @requires [@rsbuild/plugin-svgr](https://npmjs.com/package/@rsbuild/plugin-svgr) + */ +declare module '*.svg?react' { + import type React from 'react'; + const ReactComponent: React.FunctionComponent>; + export default ReactComponent; +} diff --git a/src/index.tsx b/src/index.tsx new file mode 100644 index 0000000..10d1541 --- /dev/null +++ b/src/index.tsx @@ -0,0 +1,12 @@ +import {StrictMode} from 'react'; +import {createRoot,} from 'react-dom/client'; +import App from './App'; +import './App.css' + +const root = createRoot(document.getElementById("root")) + +root.render( + + + +) \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..23ff22a --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "lib": ["DOM", "ES2020"], + "jsx": "react-jsx", + "target": "ES2020", + "noEmit": true, + "skipLibCheck": true, + "useDefineForClassFields": true, + + /* modules */ + "module": "ESNext", + "moduleDetection": "force", + "moduleResolution": "bundler", + "verbatimModuleSyntax": true, + "resolveJsonModule": true, + "allowImportingTsExtensions": true, + "noUncheckedSideEffectImports": true, + + /* type checking */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true + }, + "include": ["src"] +}