├── .gitignore ├── LICENSE ├── index.html ├── package-lock.json ├── package.json ├── src ├── App.jsx ├── NewTodoForm.jsx ├── TodoItem.jsx ├── TodoList.jsx ├── main.jsx └── styles.css └── vite.config.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 WebDevSimplified 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite + React 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-todo-list", 3 | "version": "0.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "react-todo-list", 9 | "version": "0.0.0", 10 | "dependencies": { 11 | "react": "^18.2.0", 12 | "react-dom": "^18.2.0" 13 | }, 14 | "devDependencies": { 15 | "@types/react": "^18.0.28", 16 | "@types/react-dom": "^18.0.11", 17 | "@vitejs/plugin-react-swc": "^3.0.0", 18 | "vite": "^4.2.0" 19 | } 20 | }, 21 | "node_modules/@esbuild/android-arm": { 22 | "version": "0.17.15", 23 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.15.tgz", 24 | "integrity": "sha512-sRSOVlLawAktpMvDyJIkdLI/c/kdRTOqo8t6ImVxg8yT7LQDUYV5Rp2FKeEosLr6ZCja9UjYAzyRSxGteSJPYg==", 25 | "cpu": [ 26 | "arm" 27 | ], 28 | "dev": true, 29 | "optional": true, 30 | "os": [ 31 | "android" 32 | ], 33 | "engines": { 34 | "node": ">=12" 35 | } 36 | }, 37 | "node_modules/@esbuild/android-arm64": { 38 | "version": "0.17.15", 39 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.15.tgz", 40 | "integrity": "sha512-0kOB6Y7Br3KDVgHeg8PRcvfLkq+AccreK///B4Z6fNZGr/tNHX0z2VywCc7PTeWp+bPvjA5WMvNXltHw5QjAIA==", 41 | "cpu": [ 42 | "arm64" 43 | ], 44 | "dev": true, 45 | "optional": true, 46 | "os": [ 47 | "android" 48 | ], 49 | "engines": { 50 | "node": ">=12" 51 | } 52 | }, 53 | "node_modules/@esbuild/android-x64": { 54 | "version": "0.17.15", 55 | "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.15.tgz", 56 | "integrity": "sha512-MzDqnNajQZ63YkaUWVl9uuhcWyEyh69HGpMIrf+acR4otMkfLJ4sUCxqwbCyPGicE9dVlrysI3lMcDBjGiBBcQ==", 57 | "cpu": [ 58 | "x64" 59 | ], 60 | "dev": true, 61 | "optional": true, 62 | "os": [ 63 | "android" 64 | ], 65 | "engines": { 66 | "node": ">=12" 67 | } 68 | }, 69 | "node_modules/@esbuild/darwin-arm64": { 70 | "version": "0.17.15", 71 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.15.tgz", 72 | "integrity": "sha512-7siLjBc88Z4+6qkMDxPT2juf2e8SJxmsbNVKFY2ifWCDT72v5YJz9arlvBw5oB4W/e61H1+HDB/jnu8nNg0rLA==", 73 | "cpu": [ 74 | "arm64" 75 | ], 76 | "dev": true, 77 | "optional": true, 78 | "os": [ 79 | "darwin" 80 | ], 81 | "engines": { 82 | "node": ">=12" 83 | } 84 | }, 85 | "node_modules/@esbuild/darwin-x64": { 86 | "version": "0.17.15", 87 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.15.tgz", 88 | "integrity": "sha512-NbImBas2rXwYI52BOKTW342Tm3LTeVlaOQ4QPZ7XuWNKiO226DisFk/RyPk3T0CKZkKMuU69yOvlapJEmax7cg==", 89 | "cpu": [ 90 | "x64" 91 | ], 92 | "dev": true, 93 | "optional": true, 94 | "os": [ 95 | "darwin" 96 | ], 97 | "engines": { 98 | "node": ">=12" 99 | } 100 | }, 101 | "node_modules/@esbuild/freebsd-arm64": { 102 | "version": "0.17.15", 103 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.15.tgz", 104 | "integrity": "sha512-Xk9xMDjBVG6CfgoqlVczHAdJnCs0/oeFOspFap5NkYAmRCT2qTn1vJWA2f419iMtsHSLm+O8B6SLV/HlY5cYKg==", 105 | "cpu": [ 106 | "arm64" 107 | ], 108 | "dev": true, 109 | "optional": true, 110 | "os": [ 111 | "freebsd" 112 | ], 113 | "engines": { 114 | "node": ">=12" 115 | } 116 | }, 117 | "node_modules/@esbuild/freebsd-x64": { 118 | "version": "0.17.15", 119 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.15.tgz", 120 | "integrity": "sha512-3TWAnnEOdclvb2pnfsTWtdwthPfOz7qAfcwDLcfZyGJwm1SRZIMOeB5FODVhnM93mFSPsHB9b/PmxNNbSnd0RQ==", 121 | "cpu": [ 122 | "x64" 123 | ], 124 | "dev": true, 125 | "optional": true, 126 | "os": [ 127 | "freebsd" 128 | ], 129 | "engines": { 130 | "node": ">=12" 131 | } 132 | }, 133 | "node_modules/@esbuild/linux-arm": { 134 | "version": "0.17.15", 135 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.15.tgz", 136 | "integrity": "sha512-MLTgiXWEMAMr8nmS9Gigx43zPRmEfeBfGCwxFQEMgJ5MC53QKajaclW6XDPjwJvhbebv+RzK05TQjvH3/aM4Xw==", 137 | "cpu": [ 138 | "arm" 139 | ], 140 | "dev": true, 141 | "optional": true, 142 | "os": [ 143 | "linux" 144 | ], 145 | "engines": { 146 | "node": ">=12" 147 | } 148 | }, 149 | "node_modules/@esbuild/linux-arm64": { 150 | "version": "0.17.15", 151 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.15.tgz", 152 | "integrity": "sha512-T0MVnYw9KT6b83/SqyznTs/3Jg2ODWrZfNccg11XjDehIved2oQfrX/wVuev9N936BpMRaTR9I1J0tdGgUgpJA==", 153 | "cpu": [ 154 | "arm64" 155 | ], 156 | "dev": true, 157 | "optional": true, 158 | "os": [ 159 | "linux" 160 | ], 161 | "engines": { 162 | "node": ">=12" 163 | } 164 | }, 165 | "node_modules/@esbuild/linux-ia32": { 166 | "version": "0.17.15", 167 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.15.tgz", 168 | "integrity": "sha512-wp02sHs015T23zsQtU4Cj57WiteiuASHlD7rXjKUyAGYzlOKDAjqK6bk5dMi2QEl/KVOcsjwL36kD+WW7vJt8Q==", 169 | "cpu": [ 170 | "ia32" 171 | ], 172 | "dev": true, 173 | "optional": true, 174 | "os": [ 175 | "linux" 176 | ], 177 | "engines": { 178 | "node": ">=12" 179 | } 180 | }, 181 | "node_modules/@esbuild/linux-loong64": { 182 | "version": "0.17.15", 183 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.15.tgz", 184 | "integrity": "sha512-k7FsUJjGGSxwnBmMh8d7IbObWu+sF/qbwc+xKZkBe/lTAF16RqxRCnNHA7QTd3oS2AfGBAnHlXL67shV5bBThQ==", 185 | "cpu": [ 186 | "loong64" 187 | ], 188 | "dev": true, 189 | "optional": true, 190 | "os": [ 191 | "linux" 192 | ], 193 | "engines": { 194 | "node": ">=12" 195 | } 196 | }, 197 | "node_modules/@esbuild/linux-mips64el": { 198 | "version": "0.17.15", 199 | "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.15.tgz", 200 | "integrity": "sha512-ZLWk6czDdog+Q9kE/Jfbilu24vEe/iW/Sj2d8EVsmiixQ1rM2RKH2n36qfxK4e8tVcaXkvuV3mU5zTZviE+NVQ==", 201 | "cpu": [ 202 | "mips64el" 203 | ], 204 | "dev": true, 205 | "optional": true, 206 | "os": [ 207 | "linux" 208 | ], 209 | "engines": { 210 | "node": ">=12" 211 | } 212 | }, 213 | "node_modules/@esbuild/linux-ppc64": { 214 | "version": "0.17.15", 215 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.15.tgz", 216 | "integrity": "sha512-mY6dPkIRAiFHRsGfOYZC8Q9rmr8vOBZBme0/j15zFUKM99d4ILY4WpOC7i/LqoY+RE7KaMaSfvY8CqjJtuO4xg==", 217 | "cpu": [ 218 | "ppc64" 219 | ], 220 | "dev": true, 221 | "optional": true, 222 | "os": [ 223 | "linux" 224 | ], 225 | "engines": { 226 | "node": ">=12" 227 | } 228 | }, 229 | "node_modules/@esbuild/linux-riscv64": { 230 | "version": "0.17.15", 231 | "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.15.tgz", 232 | "integrity": "sha512-EcyUtxffdDtWjjwIH8sKzpDRLcVtqANooMNASO59y+xmqqRYBBM7xVLQhqF7nksIbm2yHABptoioS9RAbVMWVA==", 233 | "cpu": [ 234 | "riscv64" 235 | ], 236 | "dev": true, 237 | "optional": true, 238 | "os": [ 239 | "linux" 240 | ], 241 | "engines": { 242 | "node": ">=12" 243 | } 244 | }, 245 | "node_modules/@esbuild/linux-s390x": { 246 | "version": "0.17.15", 247 | "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.15.tgz", 248 | "integrity": "sha512-BuS6Jx/ezxFuHxgsfvz7T4g4YlVrmCmg7UAwboeyNNg0OzNzKsIZXpr3Sb/ZREDXWgt48RO4UQRDBxJN3B9Rbg==", 249 | "cpu": [ 250 | "s390x" 251 | ], 252 | "dev": true, 253 | "optional": true, 254 | "os": [ 255 | "linux" 256 | ], 257 | "engines": { 258 | "node": ">=12" 259 | } 260 | }, 261 | "node_modules/@esbuild/linux-x64": { 262 | "version": "0.17.15", 263 | "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.15.tgz", 264 | "integrity": "sha512-JsdS0EgEViwuKsw5tiJQo9UdQdUJYuB+Mf6HxtJSPN35vez1hlrNb1KajvKWF5Sa35j17+rW1ECEO9iNrIXbNg==", 265 | "cpu": [ 266 | "x64" 267 | ], 268 | "dev": true, 269 | "optional": true, 270 | "os": [ 271 | "linux" 272 | ], 273 | "engines": { 274 | "node": ">=12" 275 | } 276 | }, 277 | "node_modules/@esbuild/netbsd-x64": { 278 | "version": "0.17.15", 279 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.15.tgz", 280 | "integrity": "sha512-R6fKjtUysYGym6uXf6qyNephVUQAGtf3n2RCsOST/neIwPqRWcnc3ogcielOd6pT+J0RDR1RGcy0ZY7d3uHVLA==", 281 | "cpu": [ 282 | "x64" 283 | ], 284 | "dev": true, 285 | "optional": true, 286 | "os": [ 287 | "netbsd" 288 | ], 289 | "engines": { 290 | "node": ">=12" 291 | } 292 | }, 293 | "node_modules/@esbuild/openbsd-x64": { 294 | "version": "0.17.15", 295 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.15.tgz", 296 | "integrity": "sha512-mVD4PGc26b8PI60QaPUltYKeSX0wxuy0AltC+WCTFwvKCq2+OgLP4+fFd+hZXzO2xW1HPKcytZBdjqL6FQFa7w==", 297 | "cpu": [ 298 | "x64" 299 | ], 300 | "dev": true, 301 | "optional": true, 302 | "os": [ 303 | "openbsd" 304 | ], 305 | "engines": { 306 | "node": ">=12" 307 | } 308 | }, 309 | "node_modules/@esbuild/sunos-x64": { 310 | "version": "0.17.15", 311 | "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.15.tgz", 312 | "integrity": "sha512-U6tYPovOkw3459t2CBwGcFYfFRjivcJJc1WC8Q3funIwX8x4fP+R6xL/QuTPNGOblbq/EUDxj9GU+dWKX0oWlQ==", 313 | "cpu": [ 314 | "x64" 315 | ], 316 | "dev": true, 317 | "optional": true, 318 | "os": [ 319 | "sunos" 320 | ], 321 | "engines": { 322 | "node": ">=12" 323 | } 324 | }, 325 | "node_modules/@esbuild/win32-arm64": { 326 | "version": "0.17.15", 327 | "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.15.tgz", 328 | "integrity": "sha512-W+Z5F++wgKAleDABemiyXVnzXgvRFs+GVKThSI+mGgleLWluv0D7Diz4oQpgdpNzh4i2nNDzQtWbjJiqutRp6Q==", 329 | "cpu": [ 330 | "arm64" 331 | ], 332 | "dev": true, 333 | "optional": true, 334 | "os": [ 335 | "win32" 336 | ], 337 | "engines": { 338 | "node": ">=12" 339 | } 340 | }, 341 | "node_modules/@esbuild/win32-ia32": { 342 | "version": "0.17.15", 343 | "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.15.tgz", 344 | "integrity": "sha512-Muz/+uGgheShKGqSVS1KsHtCyEzcdOn/W/Xbh6H91Etm+wiIfwZaBn1W58MeGtfI8WA961YMHFYTthBdQs4t+w==", 345 | "cpu": [ 346 | "ia32" 347 | ], 348 | "dev": true, 349 | "optional": true, 350 | "os": [ 351 | "win32" 352 | ], 353 | "engines": { 354 | "node": ">=12" 355 | } 356 | }, 357 | "node_modules/@esbuild/win32-x64": { 358 | "version": "0.17.15", 359 | "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.15.tgz", 360 | "integrity": "sha512-DjDa9ywLUUmjhV2Y9wUTIF+1XsmuFGvZoCmOWkli1XcNAh5t25cc7fgsCx4Zi/Uurep3TTLyDiKATgGEg61pkA==", 361 | "cpu": [ 362 | "x64" 363 | ], 364 | "dev": true, 365 | "optional": true, 366 | "os": [ 367 | "win32" 368 | ], 369 | "engines": { 370 | "node": ">=12" 371 | } 372 | }, 373 | "node_modules/@swc/core": { 374 | "version": "1.3.46", 375 | "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.3.46.tgz", 376 | "integrity": "sha512-WxzgJMWUBVJ95HsvEqlWzM3Qxp2FQrPa4QdAkQQuuvCMnfdctGUbhX/c3LiSRlWrl2LIkYAi4bLansTOol4QcQ==", 377 | "dev": true, 378 | "hasInstallScript": true, 379 | "engines": { 380 | "node": ">=10" 381 | }, 382 | "funding": { 383 | "type": "opencollective", 384 | "url": "https://opencollective.com/swc" 385 | }, 386 | "optionalDependencies": { 387 | "@swc/core-darwin-arm64": "1.3.46", 388 | "@swc/core-darwin-x64": "1.3.46", 389 | "@swc/core-linux-arm-gnueabihf": "1.3.46", 390 | "@swc/core-linux-arm64-gnu": "1.3.46", 391 | "@swc/core-linux-arm64-musl": "1.3.46", 392 | "@swc/core-linux-x64-gnu": "1.3.46", 393 | "@swc/core-linux-x64-musl": "1.3.46", 394 | "@swc/core-win32-arm64-msvc": "1.3.46", 395 | "@swc/core-win32-ia32-msvc": "1.3.46", 396 | "@swc/core-win32-x64-msvc": "1.3.46" 397 | }, 398 | "peerDependencies": { 399 | "@swc/helpers": "^0.5.0" 400 | } 401 | }, 402 | "node_modules/@swc/core-darwin-arm64": { 403 | "version": "1.3.46", 404 | "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.46.tgz", 405 | "integrity": "sha512-kY4ASe7SsntDw2B1T70H9K1CFmK8POi+LyIpeCyC96EB9wbH2Sax+ploBB/wZALbYzr/dMJzOCU8QXzdmVS4Rg==", 406 | "cpu": [ 407 | "arm64" 408 | ], 409 | "dev": true, 410 | "optional": true, 411 | "os": [ 412 | "darwin" 413 | ], 414 | "engines": { 415 | "node": ">=10" 416 | } 417 | }, 418 | "node_modules/@swc/core-darwin-x64": { 419 | "version": "1.3.46", 420 | "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.3.46.tgz", 421 | "integrity": "sha512-kE3PMk8xW+2BZ3oZiTxxsUU/GzrGwM+qS4frOBz9TYHZe+W1dTtj4F9vBit4PFJ+tv4O6DPt9neGobzdq0UmRw==", 422 | "cpu": [ 423 | "x64" 424 | ], 425 | "dev": true, 426 | "optional": true, 427 | "os": [ 428 | "darwin" 429 | ], 430 | "engines": { 431 | "node": ">=10" 432 | } 433 | }, 434 | "node_modules/@swc/core-linux-arm-gnueabihf": { 435 | "version": "1.3.46", 436 | "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.3.46.tgz", 437 | "integrity": "sha512-7TbiUr9MYxT+mC7sVrayag/isFoaZUG/ogkEK8B/ouA1pnIYqWh3N5ifqCzfcSRiOURt+vVqPyoO1puSiNzVuQ==", 438 | "cpu": [ 439 | "arm" 440 | ], 441 | "dev": true, 442 | "optional": true, 443 | "os": [ 444 | "linux" 445 | ], 446 | "engines": { 447 | "node": ">=10" 448 | } 449 | }, 450 | "node_modules/@swc/core-linux-arm64-gnu": { 451 | "version": "1.3.46", 452 | "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.46.tgz", 453 | "integrity": "sha512-Ycw4LU/wsUK9R+Y/2qFOPQseZDfM5D5gbWGrrYj5RoTm57FbnUsSsO26QeZxUNvams1oAQDkZDuerCc9qBRzIQ==", 454 | "cpu": [ 455 | "arm64" 456 | ], 457 | "dev": true, 458 | "optional": true, 459 | "os": [ 460 | "linux" 461 | ], 462 | "engines": { 463 | "node": ">=10" 464 | } 465 | }, 466 | "node_modules/@swc/core-linux-arm64-musl": { 467 | "version": "1.3.46", 468 | "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.46.tgz", 469 | "integrity": "sha512-cBclyr6IW1PBr8l9D4FkebgbqlkiIYnSJCbY84J/6PfTzQlD6w9a1TAoYxdGZpJ7SGHdmB0oDiZS1rhxCSCV/Q==", 470 | "cpu": [ 471 | "arm64" 472 | ], 473 | "dev": true, 474 | "optional": true, 475 | "os": [ 476 | "linux" 477 | ], 478 | "engines": { 479 | "node": ">=10" 480 | } 481 | }, 482 | "node_modules/@swc/core-linux-x64-gnu": { 483 | "version": "1.3.46", 484 | "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.46.tgz", 485 | "integrity": "sha512-amqMhTA2CXB6t11hVAZSSPKq4DZ9/sWbW3wYYQHxzqrMJML0726OJs4pt0XnlU7FzdP/9M9j2B/gWCRaCMxXVA==", 486 | "cpu": [ 487 | "x64" 488 | ], 489 | "dev": true, 490 | "optional": true, 491 | "os": [ 492 | "linux" 493 | ], 494 | "engines": { 495 | "node": ">=10" 496 | } 497 | }, 498 | "node_modules/@swc/core-linux-x64-musl": { 499 | "version": "1.3.46", 500 | "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.46.tgz", 501 | "integrity": "sha512-WOQZTIkJ9khIj5Z2unf6OTrWV9k8br+HZ93RvnamEmJBlLPUuT9IjB+agNhjaDgOpz9/ZldSGqV7vzl5FGQl1Q==", 502 | "cpu": [ 503 | "x64" 504 | ], 505 | "dev": true, 506 | "optional": true, 507 | "os": [ 508 | "linux" 509 | ], 510 | "engines": { 511 | "node": ">=10" 512 | } 513 | }, 514 | "node_modules/@swc/core-win32-arm64-msvc": { 515 | "version": "1.3.46", 516 | "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.46.tgz", 517 | "integrity": "sha512-4JSREbqaTRQ6QO0EeoiB6G5vuFT8zI8aTOLu5At7Cvlw+X7bOGNO+wJ3Tqw7O+68OL+0bPHzHGTXKL9kUccY1A==", 518 | "cpu": [ 519 | "arm64" 520 | ], 521 | "dev": true, 522 | "optional": true, 523 | "os": [ 524 | "win32" 525 | ], 526 | "engines": { 527 | "node": ">=10" 528 | } 529 | }, 530 | "node_modules/@swc/core-win32-ia32-msvc": { 531 | "version": "1.3.46", 532 | "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.46.tgz", 533 | "integrity": "sha512-kC8dIDzcArm1e85yHJsEZFxcNq5NztLkrqkP1nVOQ+9QXD9DKhjbZtWy2gnpclinii6KEGng8SieWiJiOA0CBQ==", 534 | "cpu": [ 535 | "ia32" 536 | ], 537 | "dev": true, 538 | "optional": true, 539 | "os": [ 540 | "win32" 541 | ], 542 | "engines": { 543 | "node": ">=10" 544 | } 545 | }, 546 | "node_modules/@swc/core-win32-x64-msvc": { 547 | "version": "1.3.46", 548 | "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.46.tgz", 549 | "integrity": "sha512-rrSAfq+DvpJioBxUsnuH+sKl0eXid1DwkwNzkVGHEreN9GoP7GospWtFq7VDcO6DrS/s3HtR4/TzoIYFEBCRIg==", 550 | "cpu": [ 551 | "x64" 552 | ], 553 | "dev": true, 554 | "optional": true, 555 | "os": [ 556 | "win32" 557 | ], 558 | "engines": { 559 | "node": ">=10" 560 | } 561 | }, 562 | "node_modules/@swc/helpers": { 563 | "version": "0.5.0", 564 | "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.0.tgz", 565 | "integrity": "sha512-SjY/p4MmECVVEWspzSRpQEM3sjR17sP8PbGxELWrT+YZMBfiUyt1MRUNjMV23zohwlG2HYtCQOsCwsTHguXkyg==", 566 | "dev": true, 567 | "peer": true, 568 | "dependencies": { 569 | "tslib": "^2.4.0" 570 | } 571 | }, 572 | "node_modules/@types/prop-types": { 573 | "version": "15.7.5", 574 | "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", 575 | "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==", 576 | "dev": true 577 | }, 578 | "node_modules/@types/react": { 579 | "version": "18.0.33", 580 | "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.33.tgz", 581 | "integrity": "sha512-sHxzVxeanvQyQ1lr8NSHaj0kDzcNiGpILEVt69g9S31/7PfMvNCKLKcsHw4lYKjs3cGNJjXSP4mYzX43QlnjNA==", 582 | "dev": true, 583 | "dependencies": { 584 | "@types/prop-types": "*", 585 | "@types/scheduler": "*", 586 | "csstype": "^3.0.2" 587 | } 588 | }, 589 | "node_modules/@types/react-dom": { 590 | "version": "18.0.11", 591 | "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.11.tgz", 592 | "integrity": "sha512-O38bPbI2CWtgw/OoQoY+BRelw7uysmXbWvw3nLWO21H1HSh+GOlqPuXshJfjmpNlKiiSDG9cc1JZAaMmVdcTlw==", 593 | "dev": true, 594 | "dependencies": { 595 | "@types/react": "*" 596 | } 597 | }, 598 | "node_modules/@types/scheduler": { 599 | "version": "0.16.3", 600 | "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz", 601 | "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==", 602 | "dev": true 603 | }, 604 | "node_modules/@vitejs/plugin-react-swc": { 605 | "version": "3.2.0", 606 | "resolved": "https://registry.npmjs.org/@vitejs/plugin-react-swc/-/plugin-react-swc-3.2.0.tgz", 607 | "integrity": "sha512-IcBoXL/mcH7JdQr/nfDlDwTdIaH8Rg7LpfQDF4nAht+juHWIuv6WhpKPCSfY4+zztAaB07qdBoFz1XCZsgo3pQ==", 608 | "dev": true, 609 | "dependencies": { 610 | "@swc/core": "^1.3.35" 611 | }, 612 | "peerDependencies": { 613 | "vite": "^4" 614 | } 615 | }, 616 | "node_modules/csstype": { 617 | "version": "3.1.2", 618 | "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", 619 | "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==", 620 | "dev": true 621 | }, 622 | "node_modules/esbuild": { 623 | "version": "0.17.15", 624 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.15.tgz", 625 | "integrity": "sha512-LBUV2VsUIc/iD9ME75qhT4aJj0r75abCVS0jakhFzOtR7TQsqQA5w0tZ+KTKnwl3kXE0MhskNdHDh/I5aCR1Zw==", 626 | "dev": true, 627 | "hasInstallScript": true, 628 | "bin": { 629 | "esbuild": "bin/esbuild" 630 | }, 631 | "engines": { 632 | "node": ">=12" 633 | }, 634 | "optionalDependencies": { 635 | "@esbuild/android-arm": "0.17.15", 636 | "@esbuild/android-arm64": "0.17.15", 637 | "@esbuild/android-x64": "0.17.15", 638 | "@esbuild/darwin-arm64": "0.17.15", 639 | "@esbuild/darwin-x64": "0.17.15", 640 | "@esbuild/freebsd-arm64": "0.17.15", 641 | "@esbuild/freebsd-x64": "0.17.15", 642 | "@esbuild/linux-arm": "0.17.15", 643 | "@esbuild/linux-arm64": "0.17.15", 644 | "@esbuild/linux-ia32": "0.17.15", 645 | "@esbuild/linux-loong64": "0.17.15", 646 | "@esbuild/linux-mips64el": "0.17.15", 647 | "@esbuild/linux-ppc64": "0.17.15", 648 | "@esbuild/linux-riscv64": "0.17.15", 649 | "@esbuild/linux-s390x": "0.17.15", 650 | "@esbuild/linux-x64": "0.17.15", 651 | "@esbuild/netbsd-x64": "0.17.15", 652 | "@esbuild/openbsd-x64": "0.17.15", 653 | "@esbuild/sunos-x64": "0.17.15", 654 | "@esbuild/win32-arm64": "0.17.15", 655 | "@esbuild/win32-ia32": "0.17.15", 656 | "@esbuild/win32-x64": "0.17.15" 657 | } 658 | }, 659 | "node_modules/fsevents": { 660 | "version": "2.3.2", 661 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", 662 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", 663 | "dev": true, 664 | "hasInstallScript": true, 665 | "optional": true, 666 | "os": [ 667 | "darwin" 668 | ], 669 | "engines": { 670 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 671 | } 672 | }, 673 | "node_modules/function-bind": { 674 | "version": "1.1.1", 675 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 676 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", 677 | "dev": true 678 | }, 679 | "node_modules/has": { 680 | "version": "1.0.3", 681 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 682 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 683 | "dev": true, 684 | "dependencies": { 685 | "function-bind": "^1.1.1" 686 | }, 687 | "engines": { 688 | "node": ">= 0.4.0" 689 | } 690 | }, 691 | "node_modules/is-core-module": { 692 | "version": "2.11.0", 693 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", 694 | "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", 695 | "dev": true, 696 | "dependencies": { 697 | "has": "^1.0.3" 698 | }, 699 | "funding": { 700 | "url": "https://github.com/sponsors/ljharb" 701 | } 702 | }, 703 | "node_modules/js-tokens": { 704 | "version": "4.0.0", 705 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", 706 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" 707 | }, 708 | "node_modules/loose-envify": { 709 | "version": "1.4.0", 710 | "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", 711 | "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", 712 | "dependencies": { 713 | "js-tokens": "^3.0.0 || ^4.0.0" 714 | }, 715 | "bin": { 716 | "loose-envify": "cli.js" 717 | } 718 | }, 719 | "node_modules/nanoid": { 720 | "version": "3.3.6", 721 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", 722 | "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", 723 | "dev": true, 724 | "funding": [ 725 | { 726 | "type": "github", 727 | "url": "https://github.com/sponsors/ai" 728 | } 729 | ], 730 | "bin": { 731 | "nanoid": "bin/nanoid.cjs" 732 | }, 733 | "engines": { 734 | "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" 735 | } 736 | }, 737 | "node_modules/path-parse": { 738 | "version": "1.0.7", 739 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", 740 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", 741 | "dev": true 742 | }, 743 | "node_modules/picocolors": { 744 | "version": "1.0.0", 745 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", 746 | "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", 747 | "dev": true 748 | }, 749 | "node_modules/postcss": { 750 | "version": "8.4.21", 751 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", 752 | "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", 753 | "dev": true, 754 | "funding": [ 755 | { 756 | "type": "opencollective", 757 | "url": "https://opencollective.com/postcss/" 758 | }, 759 | { 760 | "type": "tidelift", 761 | "url": "https://tidelift.com/funding/github/npm/postcss" 762 | } 763 | ], 764 | "dependencies": { 765 | "nanoid": "^3.3.4", 766 | "picocolors": "^1.0.0", 767 | "source-map-js": "^1.0.2" 768 | }, 769 | "engines": { 770 | "node": "^10 || ^12 || >=14" 771 | } 772 | }, 773 | "node_modules/react": { 774 | "version": "18.2.0", 775 | "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", 776 | "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", 777 | "dependencies": { 778 | "loose-envify": "^1.1.0" 779 | }, 780 | "engines": { 781 | "node": ">=0.10.0" 782 | } 783 | }, 784 | "node_modules/react-dom": { 785 | "version": "18.2.0", 786 | "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", 787 | "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", 788 | "dependencies": { 789 | "loose-envify": "^1.1.0", 790 | "scheduler": "^0.23.0" 791 | }, 792 | "peerDependencies": { 793 | "react": "^18.2.0" 794 | } 795 | }, 796 | "node_modules/resolve": { 797 | "version": "1.22.1", 798 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", 799 | "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", 800 | "dev": true, 801 | "dependencies": { 802 | "is-core-module": "^2.9.0", 803 | "path-parse": "^1.0.7", 804 | "supports-preserve-symlinks-flag": "^1.0.0" 805 | }, 806 | "bin": { 807 | "resolve": "bin/resolve" 808 | }, 809 | "funding": { 810 | "url": "https://github.com/sponsors/ljharb" 811 | } 812 | }, 813 | "node_modules/rollup": { 814 | "version": "3.20.2", 815 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.20.2.tgz", 816 | "integrity": "sha512-3zwkBQl7Ai7MFYQE0y1MeQ15+9jsi7XxfrqwTb/9EK8D9C9+//EBR4M+CuA1KODRaNbFez/lWxA5vhEGZp4MUg==", 817 | "dev": true, 818 | "bin": { 819 | "rollup": "dist/bin/rollup" 820 | }, 821 | "engines": { 822 | "node": ">=14.18.0", 823 | "npm": ">=8.0.0" 824 | }, 825 | "optionalDependencies": { 826 | "fsevents": "~2.3.2" 827 | } 828 | }, 829 | "node_modules/scheduler": { 830 | "version": "0.23.0", 831 | "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", 832 | "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", 833 | "dependencies": { 834 | "loose-envify": "^1.1.0" 835 | } 836 | }, 837 | "node_modules/source-map-js": { 838 | "version": "1.0.2", 839 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", 840 | "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", 841 | "dev": true, 842 | "engines": { 843 | "node": ">=0.10.0" 844 | } 845 | }, 846 | "node_modules/supports-preserve-symlinks-flag": { 847 | "version": "1.0.0", 848 | "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", 849 | "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", 850 | "dev": true, 851 | "engines": { 852 | "node": ">= 0.4" 853 | }, 854 | "funding": { 855 | "url": "https://github.com/sponsors/ljharb" 856 | } 857 | }, 858 | "node_modules/tslib": { 859 | "version": "2.5.0", 860 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", 861 | "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", 862 | "dev": true, 863 | "peer": true 864 | }, 865 | "node_modules/vite": { 866 | "version": "4.2.1", 867 | "resolved": "https://registry.npmjs.org/vite/-/vite-4.2.1.tgz", 868 | "integrity": "sha512-7MKhqdy0ISo4wnvwtqZkjke6XN4taqQ2TBaTccLIpOKv7Vp2h4Y+NpmWCnGDeSvvn45KxvWgGyb0MkHvY1vgbg==", 869 | "dev": true, 870 | "dependencies": { 871 | "esbuild": "^0.17.5", 872 | "postcss": "^8.4.21", 873 | "resolve": "^1.22.1", 874 | "rollup": "^3.18.0" 875 | }, 876 | "bin": { 877 | "vite": "bin/vite.js" 878 | }, 879 | "engines": { 880 | "node": "^14.18.0 || >=16.0.0" 881 | }, 882 | "optionalDependencies": { 883 | "fsevents": "~2.3.2" 884 | }, 885 | "peerDependencies": { 886 | "@types/node": ">= 14", 887 | "less": "*", 888 | "sass": "*", 889 | "stylus": "*", 890 | "sugarss": "*", 891 | "terser": "^5.4.0" 892 | }, 893 | "peerDependenciesMeta": { 894 | "@types/node": { 895 | "optional": true 896 | }, 897 | "less": { 898 | "optional": true 899 | }, 900 | "sass": { 901 | "optional": true 902 | }, 903 | "stylus": { 904 | "optional": true 905 | }, 906 | "sugarss": { 907 | "optional": true 908 | }, 909 | "terser": { 910 | "optional": true 911 | } 912 | } 913 | } 914 | } 915 | } 916 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-todo-list", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "preview": "vite preview" 10 | }, 11 | "dependencies": { 12 | "react": "^18.2.0", 13 | "react-dom": "^18.2.0" 14 | }, 15 | "devDependencies": { 16 | "@types/react": "^18.0.28", 17 | "@types/react-dom": "^18.0.11", 18 | "@vitejs/plugin-react-swc": "^3.0.0", 19 | "vite": "^4.2.0" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/App.jsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react" 2 | import { NewTodoForm } from "./NewTodoForm" 3 | import "./styles.css" 4 | import { TodoList } from "./TodoList" 5 | 6 | export default function App() { 7 | const [todos, setTodos] = useState(() => { 8 | const localValue = localStorage.getItem("ITEMS") 9 | if (localValue == null) return [] 10 | 11 | return JSON.parse(localValue) 12 | }) 13 | 14 | useEffect(() => { 15 | localStorage.setItem("ITEMS", JSON.stringify(todos)) 16 | }, [todos]) 17 | 18 | function addTodo(title) { 19 | setTodos(currentTodos => { 20 | return [ 21 | ...currentTodos, 22 | { id: crypto.randomUUID(), title, completed: false }, 23 | ] 24 | }) 25 | } 26 | 27 | function toggleTodo(id, completed) { 28 | setTodos(currentTodos => { 29 | return currentTodos.map(todo => { 30 | if (todo.id === id) { 31 | return { ...todo, completed } 32 | } 33 | 34 | return todo 35 | }) 36 | }) 37 | } 38 | 39 | function deleteTodo(id) { 40 | setTodos(currentTodos => { 41 | return currentTodos.filter(todo => todo.id !== id) 42 | }) 43 | } 44 | 45 | return ( 46 | <> 47 | 48 |

Todo List

49 | 50 | 51 | ) 52 | } 53 | -------------------------------------------------------------------------------- /src/NewTodoForm.jsx: -------------------------------------------------------------------------------- 1 | import { useState } from "react" 2 | 3 | export function NewTodoForm({ onSubmit }) { 4 | const [newItem, setNewItem] = useState("") 5 | 6 | function handleSubmit(e) { 7 | e.preventDefault() 8 | if (newItem === "") return 9 | 10 | onSubmit(newItem) 11 | 12 | setNewItem("") 13 | } 14 | 15 | return ( 16 |
17 |
18 | 19 | setNewItem(e.target.value)} 22 | type="text" 23 | id="item" 24 | /> 25 |
26 | 27 |
28 | ) 29 | } 30 | -------------------------------------------------------------------------------- /src/TodoItem.jsx: -------------------------------------------------------------------------------- 1 | export function TodoItem({ completed, id, title, toggleTodo, deleteTodo }) { 2 | return ( 3 |
  • 4 | 12 | 15 |
  • 16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /src/TodoList.jsx: -------------------------------------------------------------------------------- 1 | import { TodoItem } from "./TodoItem" 2 | 3 | export function TodoList({ todos, toggleTodo, deleteTodo }) { 4 | return ( 5 | 18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /src/main.jsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import ReactDOM from "react-dom/client" 3 | import App from "./App" 4 | 5 | ReactDOM.createRoot(document.getElementById("root")).render( 6 | 7 | 8 | 9 | ) 10 | -------------------------------------------------------------------------------- /src/styles.css: -------------------------------------------------------------------------------- 1 | * { 2 | font-family: Arial, Helvetica, sans-serif; 3 | box-sizing: border-box; 4 | } 5 | 6 | body { 7 | background: #333; 8 | color: hsl(200, 100%, 90%); 9 | max-width: 400px; 10 | padding: 1rem; 11 | margin: 0 auto; 12 | } 13 | 14 | .new-item-form { 15 | display: flex; 16 | flex-direction: column; 17 | gap: 0.5rem; 18 | } 19 | 20 | .form-row { 21 | display: flex; 22 | flex-direction: column; 23 | gap: 0.1rem; 24 | } 25 | 26 | .btn { 27 | background: hsl(200, 100%, 50%, 0.1); 28 | border: 1px solid hsl(200, 100%, 50%); 29 | color: hsl(200, 100%, 50%); 30 | padding: 0.25em 0.5em; 31 | border-radius: 0.25em; 32 | cursor: pointer; 33 | outline: none; 34 | } 35 | 36 | .btn:hover, 37 | .btn:focus-visible { 38 | background: hsl(200, 100%, 50%, 0.2); 39 | } 40 | 41 | .btn.btn-danger { 42 | background: hsl(0, 100%, 40%, 0.1); 43 | border: 1px solid hsl(0, 100%, 40%); 44 | color: hsl(0, 100%, 40%); 45 | } 46 | 47 | .btn.btn-danger:hover, 48 | .btn.btn-danger:focus-visible { 49 | background: hsl(0, 100%, 40%, 0.2); 50 | } 51 | 52 | .new-item-form input { 53 | outline: none; 54 | border: 1px solid hsl(200, 100%, 40%); 55 | background: hsl(200, 100%, 30%); 56 | border-radius: 0.25em; 57 | padding: 0.25em 0.5em; 58 | color: hsl(200, 100%, 90%); 59 | } 60 | 61 | .new-item-form input:focus { 62 | border: 1px solid hsl(200, 100%, 70%); 63 | } 64 | 65 | .header { 66 | font-size: 1.5rem; 67 | margin-top: 1.5rem; 68 | margin-bottom: 0.5rem; 69 | } 70 | 71 | .list { 72 | margin: 0; 73 | padding: 0; 74 | margin-left: 1rem; 75 | list-style: none; 76 | } 77 | 78 | .list li:has(input:checked) label { 79 | color: hsl(200, 20%, 40%); 80 | } 81 | 82 | .list { 83 | display: flex; 84 | flex-direction: column; 85 | gap: 0.3rem; 86 | } 87 | 88 | .list li { 89 | display: flex; 90 | gap: 0.5rem; 91 | align-items: center; 92 | } 93 | 94 | .list li label { 95 | display: flex; 96 | gap: 0.25rem; 97 | cursor: pointer; 98 | align-items: center; 99 | } 100 | 101 | .list li:has(input:focus-visible) label { 102 | outline: 1px solid hsl(200, 100%, 50%); 103 | } 104 | 105 | .list li input { 106 | outline: none; 107 | width: 0; 108 | height: 0; 109 | appearance: none; 110 | pointer-events: none; 111 | position: absolute; 112 | } 113 | 114 | .list li label::before { 115 | content: ""; 116 | display: block; 117 | width: 0.9rem; 118 | height: 0.9rem; 119 | background: hsl(200, 100%, 90%); 120 | border-radius: 0.25em; 121 | display: flex; 122 | justify-content: center; 123 | align-items: center; 124 | } 125 | 126 | .list li label:hover::before { 127 | background: hsl(200, 100%, 80%); 128 | } 129 | 130 | .list li:has(input:checked) label::before { 131 | content: "✔"; 132 | background: hsl(200, 100%, 40%); 133 | color: hsl(200, 100%, 90%); 134 | font-size: 0.75rem; 135 | font-weight: bold; 136 | } 137 | 138 | .list li:has(input:checked) label:hover::before { 139 | background: hsl(200, 100%, 30%); 140 | } 141 | -------------------------------------------------------------------------------- /vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import react from '@vitejs/plugin-react-swc' 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [react()], 7 | }) 8 | --------------------------------------------------------------------------------