From 16d7387de801d8cb1285cdac2016223ff535ac51 Mon Sep 17 00:00:00 2001 From: Jennifer Obinwanne Date: Wed, 11 Jun 2025 10:24:29 -0700 Subject: [PATCH 01/12] My First Commit --- .gitignore | 1 + package-lock.json | 1149 ++++++++++++++++++--------------- package.json | 3 +- src/App.css | 209 +++++- src/App.jsx | 22 +- src/components/MovieCard.jsx | 36 ++ src/components/MovieList.jsx | 175 +++++ src/components/MovieModal.css | 40 ++ src/components/MovieModal.jsx | 43 ++ src/index.css | 1 + 10 files changed, 1149 insertions(+), 530 deletions(-) create mode 100644 src/components/MovieCard.jsx create mode 100644 src/components/MovieList.jsx create mode 100644 src/components/MovieModal.css create mode 100644 src/components/MovieModal.jsx diff --git a/.gitignore b/.gitignore index a547bf36..7ceb59f8 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,4 @@ dist-ssr *.njsproj *.sln *.sw? +.env diff --git a/package-lock.json b/package-lock.json index 92a683d2..f91866fd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "name": "flixster", "version": "0.0.0", "dependencies": { + "prop-types": "^15.8.1", "react": "^18.2.0", "react-dom": "^18.2.0" }, @@ -19,7 +20,7 @@ "eslint-plugin-react": "^7.34.1", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.4.6", - "vite": "^5.2.0" + "vite": "^6.3.5" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -36,6 +37,7 @@ "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" @@ -45,43 +47,47 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.24.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", - "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/highlight": "^7.24.2", - "picocolors": "^1.0.0" + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.1.tgz", - "integrity": "sha512-Pc65opHDliVpRHuKfzI+gSA4zcgr65O4cl64fFJIWEEh8JoHIHh0Oez1Eo8Arz8zq/JhgKodQaxEwUPRtZylVA==", + "version": "7.27.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.27.5.tgz", + "integrity": "sha512-KiRAp/VoJaWkkte84TvUd9qjdbZAdiqyvMxrGl1N6vzFogKmaLgoM3L1kgtLicp2HP5fBJS8JrZKLVIZGVJAVg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.24.3", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.3.tgz", - "integrity": "sha512-5FcvN1JHw2sHJChotgx8Ek0lyuh4kCKelgMTTqhYJJtloNvUfpAFMeNQUtdlIaktwrSV9LtCdqwk48wL2wBacQ==", + "version": "7.27.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.27.4.tgz", + "integrity": "sha512-bXYxrXFubeYdvB0NhD/NBB3Qi6aZeV20GOWVI47t2dkecCEoneR4NPVcb7abpXDEvejgrUfFtG6vG/zxAKmg+g==", "dev": true, + "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.24.2", - "@babel/generator": "^7.24.1", - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.24.1", - "@babel/parser": "^7.24.1", - "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.1", - "@babel/types": "^7.24.0", + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.27.3", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.27.3", + "@babel/helpers": "^7.27.4", + "@babel/parser": "^7.27.4", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.27.4", + "@babel/types": "^7.27.3", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -97,29 +103,32 @@ } }, "node_modules/@babel/generator": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.1.tgz", - "integrity": "sha512-DfCRfZsBcrPEHUfuBMgbJ1Ut01Y/itOs+hY2nFLgqsqXd52/iSiVq5TITtUasIUgm+IIKdY2/1I7auiQOEeC9A==", + "version": "7.27.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.5.tgz", + "integrity": "sha512-ZGhA37l0e/g2s1Cnzdix0O3aLYm66eF8aufiVteOgnwxgnRP8GoyMj7VWsgWnQbVKXyge7hqrFh2K2TQM6t1Hw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.24.0", + "@babel/parser": "^7.27.5", + "@babel/types": "^7.27.3", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^2.5.1" + "jsesc": "^3.0.2" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", - "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.23.5", - "@babel/helper-validator-option": "^7.23.5", - "browserslist": "^4.22.2", + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" }, @@ -127,63 +136,30 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", - "dev": true, - "dependencies": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-module-imports": { - "version": "7.24.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz", - "integrity": "sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.24.0" + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", - "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.3.tgz", + "integrity": "sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-simple-access": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.20" + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.27.3" }, "engines": { "node": ">=6.9.0" @@ -193,99 +169,68 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz", - "integrity": "sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-simple-access": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", - "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", + "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz", - "integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", - "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.1.tgz", - "integrity": "sha512-BpU09QqEe6ZCHuIHFphEFgvNSrubve1FtyMton26ekZ85gRGi6LrTF7zArARp2YvyFxloeiRmtSCq5sjh1WqIg==", + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.6.tgz", + "integrity": "sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.1", - "@babel/types": "^7.24.0" + "@babel/template": "^7.27.2", + "@babel/types": "^7.27.6" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/highlight": { - "version": "7.24.2", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.2.tgz", - "integrity": "sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==", + "node_modules/@babel/parser": { + "version": "7.27.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.5.tgz", + "integrity": "sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" + "@babel/types": "^7.27.3" }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.1.tgz", - "integrity": "sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg==", - "dev": true, "bin": { "parser": "bin/babel-parser.js" }, @@ -294,12 +239,13 @@ } }, "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.24.1.tgz", - "integrity": "sha512-kDJgnPujTmAZ/9q2CN4m2/lRsUUPDvsG3+tSHWUJIzMGTt5U/b/fwWd3RO3n+5mjLrsBrVa5eKFRVSQbi3dF1w==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", + "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -309,12 +255,13 @@ } }, "node_modules/@babel/plugin-transform-react-jsx-source": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.24.1.tgz", - "integrity": "sha512-1v202n7aUq4uXAieRTKcwPzNyphlCuqHHDcdSNc+vdhoTEZcFMh+L5yZuCmGaIO7bs1nJUNfHB89TZyoL48xNA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", + "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -324,33 +271,32 @@ } }, "node_modules/@babel/template": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", - "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.23.5", - "@babel/parser": "^7.24.0", - "@babel/types": "^7.24.0" + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.1.tgz", - "integrity": "sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.24.1", - "@babel/generator": "^7.24.1", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.24.1", - "@babel/types": "^7.24.0", + "version": "7.27.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.4.tgz", + "integrity": "sha512-oNcu2QbHqts9BtOWJosOVJapWjBDSxGCpFvikNR5TGDYDQf3JwpIoMzIKrvfoti93cLfPJEG4tH9SPVeyCGgdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.27.3", + "@babel/parser": "^7.27.4", + "@babel/template": "^7.27.2", + "@babel/types": "^7.27.3", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -359,385 +305,442 @@ } }, "node_modules/@babel/types": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", - "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.6.tgz", + "integrity": "sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.23.4", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", - "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz", + "integrity": "sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==", "cpu": [ "ppc64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "aix" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-arm": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz", - "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.5.tgz", + "integrity": "sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==", "cpu": [ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", - "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.5.tgz", + "integrity": "sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", - "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.5.tgz", + "integrity": "sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", - "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.5.tgz", + "integrity": "sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", - "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.5.tgz", + "integrity": "sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", - "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.5.tgz", + "integrity": "sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "freebsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", - "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.5.tgz", + "integrity": "sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "freebsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-arm": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", - "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.5.tgz", + "integrity": "sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==", "cpu": [ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", - "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.5.tgz", + "integrity": "sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", - "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.5.tgz", + "integrity": "sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==", "cpu": [ "ia32" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", - "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.5.tgz", + "integrity": "sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==", "cpu": [ "loong64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", - "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.5.tgz", + "integrity": "sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==", "cpu": [ "mips64el" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", - "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.5.tgz", + "integrity": "sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==", "cpu": [ "ppc64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", - "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.5.tgz", + "integrity": "sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==", "cpu": [ "riscv64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", - "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.5.tgz", + "integrity": "sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==", "cpu": [ "s390x" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", - "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.5.tgz", + "integrity": "sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.5.tgz", + "integrity": "sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", - "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.5.tgz", + "integrity": "sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "netbsd" ], "engines": { - "node": ">=12" + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.5.tgz", + "integrity": "sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", - "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.5.tgz", + "integrity": "sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "openbsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", - "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.5.tgz", + "integrity": "sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "sunos" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", - "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.5.tgz", + "integrity": "sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", - "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.5.tgz", + "integrity": "sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==", "cpu": [ "ia32" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", - "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz", + "integrity": "sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@eslint-community/eslint-utils": { @@ -845,10 +848,11 @@ "dev": true }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -863,6 +867,7 @@ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0.0" } @@ -872,21 +877,24 @@ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true, + "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.25", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" @@ -927,196 +935,288 @@ "node": ">= 8" } }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.9", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.9.tgz", + "integrity": "sha512-e9MeMtVWo186sgvFFJOPGy7/d2j2mZhLJIdVW0C/xDluuOvymEATqz6zKsP0ZmXGzQtqlyjz5sC1sYQUoJG98w==", + "dev": true, + "license": "MIT" + }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.13.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.13.2.tgz", - "integrity": "sha512-3XFIDKWMFZrMnao1mJhnOT1h2g0169Os848NhhmGweEcfJ4rCi+3yMCOLG4zA61rbJdkcrM/DjVZm9Hg5p5w7g==", + "version": "4.42.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.42.0.tgz", + "integrity": "sha512-gldmAyS9hpj+H6LpRNlcjQWbuKUtb94lodB9uCz71Jm+7BxK1VIOo7y62tZZwxhA7j1ylv/yQz080L5WkS+LoQ==", "cpu": [ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.13.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.13.2.tgz", - "integrity": "sha512-GdxxXbAuM7Y/YQM9/TwwP+L0omeE/lJAR1J+olu36c3LqqZEBdsIWeQ91KBe6nxwOnb06Xh7JS2U5ooWU5/LgQ==", + "version": "4.42.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.42.0.tgz", + "integrity": "sha512-bpRipfTgmGFdCZDFLRvIkSNO1/3RGS74aWkJJTFJBH7h3MRV4UijkaEUeOMbi9wxtxYmtAbVcnMtHTPBhLEkaw==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.13.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.13.2.tgz", - "integrity": "sha512-mCMlpzlBgOTdaFs83I4XRr8wNPveJiJX1RLfv4hggyIVhfB5mJfN4P8Z6yKh+oE4Luz+qq1P3kVdWrCKcMYrrA==", + "version": "4.42.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.42.0.tgz", + "integrity": "sha512-JxHtA081izPBVCHLKnl6GEA0w3920mlJPLh89NojpU2GsBSB6ypu4erFg/Wx1qbpUbepn0jY4dVWMGZM8gplgA==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.13.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.13.2.tgz", - "integrity": "sha512-yUoEvnH0FBef/NbB1u6d3HNGyruAKnN74LrPAfDQL3O32e3k3OSfLrPgSJmgb3PJrBZWfPyt6m4ZhAFa2nZp2A==", + "version": "4.42.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.42.0.tgz", + "integrity": "sha512-rv5UZaWVIJTDMyQ3dCEK+m0SAn6G7H3PRc2AZmExvbDvtaDc+qXkei0knQWcI3+c9tEs7iL/4I4pTQoPbNL2SA==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" ] }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.42.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.42.0.tgz", + "integrity": "sha512-fJcN4uSGPWdpVmvLuMtALUFwCHgb2XiQjuECkHT3lWLZhSQ3MBQ9pq+WoWeJq2PrNxr9rPM1Qx+IjyGj8/c6zQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.42.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.42.0.tgz", + "integrity": "sha512-CziHfyzpp8hJpCVE/ZdTizw58gr+m7Y2Xq5VOuCSrZR++th2xWAz4Nqk52MoIIrV3JHtVBhbBsJcAxs6NammOQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.13.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.13.2.tgz", - "integrity": "sha512-GYbLs5ErswU/Xs7aGXqzc3RrdEjKdmoCrgzhJWyFL0r5fL3qd1NPcDKDowDnmcoSiGJeU68/Vy+OMUluRxPiLQ==", + "version": "4.42.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.42.0.tgz", + "integrity": "sha512-UsQD5fyLWm2Fe5CDM7VPYAo+UC7+2Px4Y+N3AcPh/LdZu23YcuGPegQly++XEVaC8XUTFVPscl5y5Cl1twEI4A==", "cpu": [ "arm" ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.42.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.42.0.tgz", + "integrity": "sha512-/i8NIrlgc/+4n1lnoWl1zgH7Uo0XK5xK3EDqVTf38KvyYgCU/Rm04+o1VvvzJZnVS5/cWSd07owkzcVasgfIkQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.13.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.13.2.tgz", - "integrity": "sha512-L1+D8/wqGnKQIlh4Zre9i4R4b4noxzH5DDciyahX4oOz62CphY7WDWqJoQ66zNR4oScLNOqQJfNSIAe/6TPUmQ==", + "version": "4.42.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.42.0.tgz", + "integrity": "sha512-eoujJFOvoIBjZEi9hJnXAbWg+Vo1Ov8n/0IKZZcPZ7JhBzxh2A+2NFyeMZIRkY9iwBvSjloKgcvnjTbGKHE44Q==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.13.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.13.2.tgz", - "integrity": "sha512-tK5eoKFkXdz6vjfkSTCupUzCo40xueTOiOO6PeEIadlNBkadH1wNOH8ILCPIl8by/Gmb5AGAeQOFeLev7iZDOA==", + "version": "4.42.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.42.0.tgz", + "integrity": "sha512-/3NrcOWFSR7RQUQIuZQChLND36aTU9IYE4j+TB40VU78S+RA0IiqHR30oSh6P1S9f9/wVOenHQnacs/Byb824g==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.42.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.42.0.tgz", + "integrity": "sha512-O8AplvIeavK5ABmZlKBq9/STdZlnQo7Sle0LLhVA7QT+CiGpNVe197/t8Aph9bhJqbDVGCHpY2i7QyfEDDStDg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.13.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.13.2.tgz", - "integrity": "sha512-zvXvAUGGEYi6tYhcDmb9wlOckVbuD+7z3mzInCSTACJ4DQrdSLPNUeDIcAQW39M3q6PDquqLWu7pnO39uSMRzQ==", + "version": "4.42.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.42.0.tgz", + "integrity": "sha512-6Qb66tbKVN7VyQrekhEzbHRxXXFFD8QKiFAwX5v9Xt6FiJ3BnCVBuyBxa2fkFGqxOCSGGYNejxd8ht+q5SnmtA==", "cpu": [ - "ppc64le" + "ppc64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.13.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.13.2.tgz", - "integrity": "sha512-C3GSKvMtdudHCN5HdmAMSRYR2kkhgdOfye4w0xzyii7lebVr4riCgmM6lRiSCnJn2w1Xz7ZZzHKuLrjx5620kw==", + "version": "4.42.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.42.0.tgz", + "integrity": "sha512-KQETDSEBamQFvg/d8jajtRwLNBlGc3aKpaGiP/LvEbnmVUKlFta1vqJqTrvPtsYsfbE/DLg5CC9zyXRX3fnBiA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.42.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.42.0.tgz", + "integrity": "sha512-qMvnyjcU37sCo/tuC+JqeDKSuukGAd+pVlRl/oyDbkvPJ3awk6G6ua7tyum02O3lI+fio+eM5wsVd66X0jQtxw==", "cpu": [ "riscv64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.13.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.13.2.tgz", - "integrity": "sha512-l4U0KDFwzD36j7HdfJ5/TveEQ1fUTjFFQP5qIt9gBqBgu1G8/kCaq5Ok05kd5TG9F8Lltf3MoYsUMw3rNlJ0Yg==", + "version": "4.42.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.42.0.tgz", + "integrity": "sha512-I2Y1ZUgTgU2RLddUHXTIgyrdOwljjkmcZ/VilvaEumtS3Fkuhbw4p4hgHc39Ypwvo2o7sBFNl2MquNvGCa55Iw==", "cpu": [ "s390x" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.13.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.13.2.tgz", - "integrity": "sha512-xXMLUAMzrtsvh3cZ448vbXqlUa7ZL8z0MwHp63K2IIID2+DeP5iWIT6g1SN7hg1VxPzqx0xZdiDM9l4n9LRU1A==", + "version": "4.42.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.42.0.tgz", + "integrity": "sha512-Gfm6cV6mj3hCUY8TqWa63DB8Mx3NADoFwiJrMpoZ1uESbK8FQV3LXkhfry+8bOniq9pqY1OdsjFWNsSbfjPugw==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.13.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.13.2.tgz", - "integrity": "sha512-M/JYAWickafUijWPai4ehrjzVPKRCyDb1SLuO+ZyPfoXgeCEAlgPkNXewFZx0zcnoIe3ay4UjXIMdXQXOZXWqA==", + "version": "4.42.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.42.0.tgz", + "integrity": "sha512-g86PF8YZ9GRqkdi0VoGlcDUb4rYtQKyTD1IVtxxN4Hpe7YqLBShA7oHMKU6oKTCi3uxwW4VkIGnOaH/El8de3w==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.13.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.13.2.tgz", - "integrity": "sha512-2YWwoVg9KRkIKaXSh0mz3NmfurpmYoBBTAXA9qt7VXk0Xy12PoOP40EFuau+ajgALbbhi4uTj3tSG3tVseCjuA==", + "version": "4.42.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.42.0.tgz", + "integrity": "sha512-+axkdyDGSp6hjyzQ5m1pgcvQScfHnMCcsXkx8pTgy/6qBmWVhtRVlgxjWwDp67wEXXUr0x+vD6tp5W4x6V7u1A==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.13.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.13.2.tgz", - "integrity": "sha512-2FSsE9aQ6OWD20E498NYKEQLneShWes0NGMPQwxWOdws35qQXH+FplabOSP5zEe1pVjurSDOGEVCE2agFwSEsw==", + "version": "4.42.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.42.0.tgz", + "integrity": "sha512-F+5J9pelstXKwRSDq92J0TEBXn2nfUrQGg+HK1+Tk7VOL09e0gBqUHugZv7SW4MGrYj41oNCUe3IKCDGVlis2g==", "cpu": [ "ia32" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.13.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.13.2.tgz", - "integrity": "sha512-7h7J2nokcdPePdKykd8wtc8QqqkqxIrUz7MHj6aNr8waBRU//NLDVnNjQnqQO6fqtjrtCdftpbTuOKAyrAQETQ==", + "version": "4.42.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.42.0.tgz", + "integrity": "sha512-LpHiJRwkaVz/LqjHjK8LCi8osq7elmpwujwbXKNW88bM8eeGxavJIKKjkjpMHAh/2xfnrt1ZSnhTv41WYUHYmA==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -1164,10 +1264,11 @@ } }, "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", + "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==", + "dev": true, + "license": "MIT" }, "node_modules/@types/prop-types": { "version": "15.7.12", @@ -1201,22 +1302,24 @@ "dev": true }, "node_modules/@vitejs/plugin-react": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.2.1.tgz", - "integrity": "sha512-oojO9IDc4nCUUi8qIR11KoQm0XFFLIwsRBwHRR4d/88IWghn1y6ckz/bJ8GHDCsYEJee8mDzqtJxh15/cisJNQ==", + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.5.1.tgz", + "integrity": "sha512-uPZBqSI0YD4lpkIru6M35sIfylLGTyhGHvDZbNLuMA73lMlwJKz5xweH7FajfcCAc2HnINciejA9qTz0dr0M7A==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/core": "^7.23.5", - "@babel/plugin-transform-react-jsx-self": "^7.23.3", - "@babel/plugin-transform-react-jsx-source": "^7.23.3", + "@babel/core": "^7.26.10", + "@babel/plugin-transform-react-jsx-self": "^7.25.9", + "@babel/plugin-transform-react-jsx-source": "^7.25.9", + "@rolldown/pluginutils": "1.0.0-beta.9", "@types/babel__core": "^7.20.5", - "react-refresh": "^0.14.0" + "react-refresh": "^0.17.0" }, "engines": { "node": "^14.18.0 || >=16.0.0" }, "peerDependencies": { - "vite": "^4.2.0 || ^5.0.0" + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0" } }, "node_modules/acorn": { @@ -1265,18 +1368,6 @@ "node": ">=8" } }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -1454,9 +1545,9 @@ } }, "node_modules/browserslist": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", - "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", + "version": "4.25.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.0.tgz", + "integrity": "sha512-PJ8gYKeS5e/whHBh8xrwYK+dAvEj7JXtz6uTucnMRB8OiGTsKccFekoRrjajPBHV8oOY+2tI4uxeceSimKwMFA==", "dev": true, "funding": [ { @@ -1472,11 +1563,12 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001587", - "electron-to-chromium": "^1.4.668", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" + "caniuse-lite": "^1.0.30001718", + "electron-to-chromium": "^1.5.160", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.3" }, "bin": { "browserslist": "cli.js" @@ -1514,9 +1606,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001605", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001605.tgz", - "integrity": "sha512-nXwGlFWo34uliI9z3n6Qc0wZaf7zaZWA1CPZ169La5mV3I/gem7bst0vr5XQH5TJXZIMfDeZyOrZnSlVzKxxHQ==", + "version": "1.0.30001721", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001721.tgz", + "integrity": "sha512-cOuvmUVtKrtEaoKiO0rSc29jcjwMwX5tOHDy4MgVFEWiUXj4uBMJkwI8MDySkgXidpMiHUcviogAvFi4pA2hDQ==", "dev": true, "funding": [ { @@ -1531,36 +1623,8 @@ "type": "github", "url": "https://github.com/sponsors/ai" } - ] - }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true + ], + "license": "CC-BY-4.0" }, "node_modules/concat-map": { "version": "0.0.1", @@ -1572,13 +1636,15 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -1715,10 +1781,11 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.724", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.724.tgz", - "integrity": "sha512-RTRvkmRkGhNBPPpdrgtDKvmOEYTrPlXDfc0J/Nfq5s29tEahAwhiX4mmhNzj6febWMleulxVYPh7QwCSL/EldA==", - "dev": true + "version": "1.5.165", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.165.tgz", + "integrity": "sha512-naiMx1Z6Nb2TxPU6fiFrUrDTjyPMLdTtaOd2oLmG8zVSg2hCWGkhPyxwk+qRmZ1ytwVqUv0u7ZcDA5+ALhaUtw==", + "dev": true, + "license": "ISC" }, "node_modules/es-abstract": { "version": "1.23.3", @@ -1879,61 +1946,56 @@ } }, "node_modules/esbuild": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", - "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.5.tgz", + "integrity": "sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==", "dev": true, "hasInstallScript": true, + "license": "MIT", "bin": { "esbuild": "bin/esbuild" }, "engines": { - "node": ">=12" + "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.20.2", - "@esbuild/android-arm": "0.20.2", - "@esbuild/android-arm64": "0.20.2", - "@esbuild/android-x64": "0.20.2", - "@esbuild/darwin-arm64": "0.20.2", - "@esbuild/darwin-x64": "0.20.2", - "@esbuild/freebsd-arm64": "0.20.2", - "@esbuild/freebsd-x64": "0.20.2", - "@esbuild/linux-arm": "0.20.2", - "@esbuild/linux-arm64": "0.20.2", - "@esbuild/linux-ia32": "0.20.2", - "@esbuild/linux-loong64": "0.20.2", - "@esbuild/linux-mips64el": "0.20.2", - "@esbuild/linux-ppc64": "0.20.2", - "@esbuild/linux-riscv64": "0.20.2", - "@esbuild/linux-s390x": "0.20.2", - "@esbuild/linux-x64": "0.20.2", - "@esbuild/netbsd-x64": "0.20.2", - "@esbuild/openbsd-x64": "0.20.2", - "@esbuild/sunos-x64": "0.20.2", - "@esbuild/win32-arm64": "0.20.2", - "@esbuild/win32-ia32": "0.20.2", - "@esbuild/win32-x64": "0.20.2" + "@esbuild/aix-ppc64": "0.25.5", + "@esbuild/android-arm": "0.25.5", + "@esbuild/android-arm64": "0.25.5", + "@esbuild/android-x64": "0.25.5", + "@esbuild/darwin-arm64": "0.25.5", + "@esbuild/darwin-x64": "0.25.5", + "@esbuild/freebsd-arm64": "0.25.5", + "@esbuild/freebsd-x64": "0.25.5", + "@esbuild/linux-arm": "0.25.5", + "@esbuild/linux-arm64": "0.25.5", + "@esbuild/linux-ia32": "0.25.5", + "@esbuild/linux-loong64": "0.25.5", + "@esbuild/linux-mips64el": "0.25.5", + "@esbuild/linux-ppc64": "0.25.5", + "@esbuild/linux-riscv64": "0.25.5", + "@esbuild/linux-s390x": "0.25.5", + "@esbuild/linux-x64": "0.25.5", + "@esbuild/netbsd-arm64": "0.25.5", + "@esbuild/netbsd-x64": "0.25.5", + "@esbuild/openbsd-arm64": "0.25.5", + "@esbuild/openbsd-x64": "0.25.5", + "@esbuild/sunos-x64": "0.25.5", + "@esbuild/win32-arm64": "0.25.5", + "@esbuild/win32-ia32": "0.25.5", + "@esbuild/win32-x64": "0.25.5" } }, "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/eslint": { "version": "8.57.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", @@ -2265,6 +2327,21 @@ "reusify": "^1.0.4" } }, + "node_modules/fdir": { + "version": "6.4.5", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.5.tgz", + "integrity": "sha512-4BG7puHpVsIYxZUbiUE3RqGloLaSSwzYie5jvasC4LWuBWzZawynvYouhjbQKw2JuIGYdm0DzIxl8iVidKlUEw==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -2334,6 +2411,7 @@ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, "hasInstallScript": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -2383,6 +2461,7 @@ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -2460,6 +2539,7 @@ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -2506,15 +2586,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/has-property-descriptors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", @@ -3022,15 +3093,16 @@ } }, "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", "dev": true, + "license": "MIT", "bin": { "jsesc": "bin/jsesc" }, "engines": { - "node": ">=4" + "node": ">=6" } }, "node_modules/json-buffer": { @@ -3056,6 +3128,7 @@ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, + "license": "MIT", "bin": { "json5": "lib/cli.js" }, @@ -3137,6 +3210,7 @@ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^3.0.2" } @@ -3160,9 +3234,9 @@ "dev": true }, "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", "dev": true, "funding": [ { @@ -3170,6 +3244,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -3184,16 +3259,16 @@ "dev": true }, "node_modules/node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", - "dev": true + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "dev": true, + "license": "MIT" }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -3402,10 +3477,24 @@ "dev": true }, "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } }, "node_modules/possible-typed-array-names": { "version": "1.0.0", @@ -3417,9 +3506,9 @@ } }, "node_modules/postcss": { - "version": "8.4.38", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", - "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", + "version": "8.5.4", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.4.tgz", + "integrity": "sha512-QSa9EBe+uwlGTFmHsPKokv3B/oEMQZxfqW0QqNCyhpa6mB1afzulwn8hihglqAb2pOw+BJgNlmXQ8la2VeHB7w==", "dev": true, "funding": [ { @@ -3435,10 +3524,11 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "nanoid": "^3.3.7", - "picocolors": "^1.0.0", - "source-map-js": "^1.2.0" + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" }, "engines": { "node": "^10 || ^12 || >=14" @@ -3457,7 +3547,7 @@ "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dev": true, + "license": "MIT", "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", @@ -3519,14 +3609,14 @@ "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, "node_modules/react-refresh": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz", - "integrity": "sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==", + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", + "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -3622,12 +3712,13 @@ } }, "node_modules/rollup": { - "version": "4.13.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.13.2.tgz", - "integrity": "sha512-MIlLgsdMprDBXC+4hsPgzWUasLO9CE4zOkj/u6j+Z6j5A4zRY+CtiXAdJyPtgCsc42g658Aeh1DlrdVEJhsL2g==", + "version": "4.42.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.42.0.tgz", + "integrity": "sha512-LW+Vse3BJPyGJGAJt1j8pWDKPd73QM8cRXYK1IxOBgL2AGLu7Xd2YOW0M2sLUBCkF5MshXXtMApyEAEzMVMsnw==", "dev": true, + "license": "MIT", "dependencies": { - "@types/estree": "1.0.5" + "@types/estree": "1.0.7" }, "bin": { "rollup": "dist/bin/rollup" @@ -3637,21 +3728,26 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.13.2", - "@rollup/rollup-android-arm64": "4.13.2", - "@rollup/rollup-darwin-arm64": "4.13.2", - "@rollup/rollup-darwin-x64": "4.13.2", - "@rollup/rollup-linux-arm-gnueabihf": "4.13.2", - "@rollup/rollup-linux-arm64-gnu": "4.13.2", - "@rollup/rollup-linux-arm64-musl": "4.13.2", - "@rollup/rollup-linux-powerpc64le-gnu": "4.13.2", - "@rollup/rollup-linux-riscv64-gnu": "4.13.2", - "@rollup/rollup-linux-s390x-gnu": "4.13.2", - "@rollup/rollup-linux-x64-gnu": "4.13.2", - "@rollup/rollup-linux-x64-musl": "4.13.2", - "@rollup/rollup-win32-arm64-msvc": "4.13.2", - "@rollup/rollup-win32-ia32-msvc": "4.13.2", - "@rollup/rollup-win32-x64-msvc": "4.13.2", + "@rollup/rollup-android-arm-eabi": "4.42.0", + "@rollup/rollup-android-arm64": "4.42.0", + "@rollup/rollup-darwin-arm64": "4.42.0", + "@rollup/rollup-darwin-x64": "4.42.0", + "@rollup/rollup-freebsd-arm64": "4.42.0", + "@rollup/rollup-freebsd-x64": "4.42.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.42.0", + "@rollup/rollup-linux-arm-musleabihf": "4.42.0", + "@rollup/rollup-linux-arm64-gnu": "4.42.0", + "@rollup/rollup-linux-arm64-musl": "4.42.0", + "@rollup/rollup-linux-loongarch64-gnu": "4.42.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.42.0", + "@rollup/rollup-linux-riscv64-gnu": "4.42.0", + "@rollup/rollup-linux-riscv64-musl": "4.42.0", + "@rollup/rollup-linux-s390x-gnu": "4.42.0", + "@rollup/rollup-linux-x64-gnu": "4.42.0", + "@rollup/rollup-linux-x64-musl": "4.42.0", + "@rollup/rollup-win32-arm64-msvc": "4.42.0", + "@rollup/rollup-win32-ia32-msvc": "4.42.0", + "@rollup/rollup-win32-x64-msvc": "4.42.0", "fsevents": "~2.3.2" } }, @@ -3802,10 +3898,11 @@ } }, "node_modules/source-map-js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", - "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } @@ -3909,18 +4006,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", @@ -3939,13 +4024,21 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "node_modules/tinyglobby": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", + "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.4.4", + "picomatch": "^4.0.2" + }, "engines": { - "node": ">=4" + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" } }, "node_modules/type-check": { @@ -4061,9 +4154,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", "dev": true, "funding": [ { @@ -4079,9 +4172,10 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "escalade": "^3.2.0", + "picocolors": "^1.1.1" }, "bin": { "update-browserslist-db": "cli.js" @@ -4100,20 +4194,24 @@ } }, "node_modules/vite": { - "version": "5.2.7", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.7.tgz", - "integrity": "sha512-k14PWOKLI6pMaSzAuGtT+Cf0YmIx12z9YGon39onaJNy8DLBfBJrzg9FQEmkAM5lpHBZs9wksWAsyF/HkpEwJA==", + "version": "6.3.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz", + "integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==", "dev": true, + "license": "MIT", "dependencies": { - "esbuild": "^0.20.1", - "postcss": "^8.4.38", - "rollup": "^4.13.0" + "esbuild": "^0.25.0", + "fdir": "^6.4.4", + "picomatch": "^4.0.2", + "postcss": "^8.5.3", + "rollup": "^4.34.9", + "tinyglobby": "^0.2.13" }, "bin": { "vite": "bin/vite.js" }, "engines": { - "node": "^18.0.0 || >=20.0.0" + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" }, "funding": { "url": "https://github.com/vitejs/vite?sponsor=1" @@ -4122,18 +4220,25 @@ "fsevents": "~2.3.3" }, "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", + "sass-embedded": "*", "stylus": "*", "sugarss": "*", - "terser": "^5.4.0" + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" }, "peerDependenciesMeta": { "@types/node": { "optional": true }, + "jiti": { + "optional": true + }, "less": { "optional": true }, @@ -4143,6 +4248,9 @@ "sass": { "optional": true }, + "sass-embedded": { + "optional": true + }, "stylus": { "optional": true }, @@ -4151,6 +4259,12 @@ }, "terser": { "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true } } }, @@ -4258,7 +4372,8 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/yocto-queue": { "version": "0.1.0", diff --git a/package.json b/package.json index eded5715..78486322 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "preview": "vite preview" }, "dependencies": { + "prop-types": "^15.8.1", "react": "^18.2.0", "react-dom": "^18.2.0" }, @@ -21,6 +22,6 @@ "eslint-plugin-react": "^7.34.1", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.4.6", - "vite": "^5.2.0" + "vite": "^6.3.5" } } diff --git a/src/App.css b/src/App.css index 0bf65669..21606fc3 100644 --- a/src/App.css +++ b/src/App.css @@ -1,3 +1,10 @@ +html, body { + height: 100%; + margin: 0; + padding: 0; + background-color: #f9d0de; /* Soft pink body */ +} + .App { text-align: center; } @@ -12,17 +19,207 @@ padding: 20px; } + +/*for mobile responsiveness*/ @media (max-width: 600px) { - .movie-card { + .controls { + flex-direction: column; + gap: 10px; + align-items: center; + } + + .controls input, + .controls button { width: 100%; + max-width: 100%; } - .search-bar { - flex-direction: column; - gap: 10px; + .movie-list { + grid-template-columns: 1fr; + gap: 15px; } - .search-bar form { - flex-direction: column; + .movie-card { + max-width: 100%; + height: auto; + } + + .movie-card img { + height: auto; + object-fit: contain; + } +} + +@media (max-width: 900px) and (min-width: 601px) { + .movie-list { + grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); } + + .controls { + flex-direction: row; + flex-wrap: wrap; + justify-content: center; + gap: 12px; + } +} + + + + + + + +/* Layout basics */ +main { + padding: 2rem; + font-family: 'Arial', sans-serif; + max-width: 1200px; + margin: auto; + background-color: pink; + min-width: 100vh; + margin-top: 10px; + border-radius: 10px; +} + +h2 { + text-align: center; + margin-bottom: 2rem; +} + +/* Controls: search bar + buttons */ +.controls { + display: flex; + flex-wrap: wrap; + gap: 10px; + justify-content: center; + margin-bottom: 1.5rem; +} + +.controls input { + padding: 8px 12px; + border-radius: 5px; + border: 1px solid #ccc; + flex: 1 1 200px; + max-width: 300px; +} + +.controls button { + padding: 8px 16px; + border: none; + background-color: #007bff; + color: white; + font-weight: bold; + border-radius: 5px; + cursor: pointer; + transition: background-color 0.2s ease; +} + +.controls button:disabled { + background-color: #ccc; + cursor: not-allowed; +} + +.controls button:not(:disabled):hover { + background-color: #0056b3; +} + +/* Movie list layout */ +.movie-list { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); + gap: 20px; + margin-bottom: 2rem; +} + +/* Individual movie card */ +.movie-card { + background-color: palevioletred; + border-radius: 10px; + overflow: hidden; + text-align: center; + padding: 10px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); + transition: transform 0.2s ease; +} + +.movie-card:hover { + transform: scale(1.03); +} + +.movie-card img { + width: 100%; + border-radius: 10px; + height: 270px; + object-fit: cover; +} + +.movie-card h3 { + font-size: 1rem; + margin: 10px 0 5px; +} + +.movie-card p { + font-size: 0.9rem; + color: #333; +} + +/* Load More button */ +.load-more { + display: block; + margin: 0 auto; + padding: 10px 25px; + background-color: hotpink; + color: white; + font-weight: bold; + border: none; + border-radius: 6px; + cursor: pointer; + transition: background-color 0.2s ease; +} + +.load-more:hover { + background-color: #1e7e34; +} + +#Otter{ + font-size: 50px; +} + + + + + +/* Header styles */ +header { + background-color: hotpink; /* hot pink */ + color: white; + color: #333; + padding: 1rem; + text-align: center; + font-size: 1.8rem; + font-weight: bold; + box-shadow: 0 2px 4px rgba(0,0,0,0.05); + font-family:'Lucida Sans', 'Lucida Sans Regular', 'Lucida Grande', 'Lucida Sans Unicode', Geneva, Verdana, sans-serif +} + +/* Footer styles */ +footer { + + color: #999; + text-align: center; + font-size: 0.9rem; + padding: 1rem; + margin-top: 2rem; + border-top: 1px solid #eee; + background-color: hotpink; /* Deep pink */ + color: white; +} + + +.favorite-button { + background: transparent; + border: none; + font-size: 1.5rem; + cursor: pointer; + margin-top: 5px; } diff --git a/src/App.jsx b/src/App.jsx index dfa91584..817462ea 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,12 +1,22 @@ -import { useState } from 'react' -import './App.css' +import './App.css'; +import MovieList from './components/MovieList'; const App = () => { return (
- +
+

🎬 Flixster

+
+ +
+ +
+ +
+ © {new Date().getFullYear()} Flixster by Jennifer 💖 +
- ) -} + ); +}; -export default App +export default App; diff --git a/src/components/MovieCard.jsx b/src/components/MovieCard.jsx new file mode 100644 index 00000000..7c96b868 --- /dev/null +++ b/src/components/MovieCard.jsx @@ -0,0 +1,36 @@ + +import PropTypes from 'prop-types'; + + +const MovieCard = ({ title, posterPath, voteAverage, isFavorite, onToggleFavorite }) => { + const imageUrl = `https://image.tmdb.org/t/p/w500${posterPath}`; + + return ( +
+ +

{title}

+

Rating: {voteAverage}

+ +
+ ); +}; +MovieCard.propTypes = { + title: PropTypes.string.isRequired, + posterPath: PropTypes.string.isRequired, + voteAverage: PropTypes.number.isRequired, + isFavorite: PropTypes.bool.isRequired, + onToggleFavorite: PropTypes.func.isRequired, + + +}; + + +export default MovieCard; diff --git a/src/components/MovieList.jsx b/src/components/MovieList.jsx new file mode 100644 index 00000000..5c621726 --- /dev/null +++ b/src/components/MovieList.jsx @@ -0,0 +1,175 @@ +import { useEffect, useState } from 'react'; +import MovieCard from './MovieCard'; +import MovieModal from './MovieModal'; + + +const MovieList = () => { + const [movies, setMovies] = useState([]); + const [page, setPage] = useState(1); + const [hasMore, setHasMore] = useState(true); + const [searchQuery, setSearchQuery] = useState(''); + const [mode, setMode] = useState('nowPlaying'); + const [selectedMovie, setSelectedMovie] = useState(null); + const [sortOption, setSortOption] = useState(''); + const [favorites, setFavorites] = useState([]); + + + + + const apiKey = import.meta.env.VITE_API_KEY; + + + useEffect(() => { + if (apiKey) { + fetchMovies(1, mode); + } else { + console.error("API key is missing or invalid"); + } +}, [mode]); + + const fetchMovies = async (pageNum = 1, currentMode = 'nowPlaying') => { + try { + const baseUrl = currentMode === 'search' + ? `https://api.themoviedb.org/3/search/movie` + : `https://api.themoviedb.org/3/movie/now_playing`; + + const queryParams = currentMode === 'search' + ? `?query=${searchQuery}&page=${pageNum}&api_key=${apiKey}` + : `?page=${pageNum}&api_key=${apiKey}`; + + const fullUrl = `${baseUrl}${queryParams}`; + const res = await fetch(fullUrl); + const data = await res.json(); + + if (!data.results || data.results.length === 0 || pageNum >= data.total_pages) { + setHasMore(false); + } + + if (pageNum === 1) { + setMovies(data.results); + } else { + setMovies((prev) => [...prev, ...data.results]); + } + } catch (err) { + console.error("Failed to fetch movies:", err); + } + }; + + const handleLoadMore = () => { + const nextPage = page + 1; + setPage(nextPage); + fetchMovies(nextPage, mode); + }; + + const handleSearchChange = (event) => { + setSearchQuery(event.target.value); + }; + + const handleSearch = () => { + setPage(1); + setHasMore(true); + setMode('search'); + fetchMovies(1, 'search'); + }; + + const handleNowPlaying = () => { + setSearchQuery(''); + setPage(1); + setHasMore(true); + setMode('nowPlaying'); + fetchMovies(1, 'nowPlaying'); + }; + const fetchMovieDetails = async (movieId) => { + const res = await fetch( + `https://api.themoviedb.org/3/movie/${movieId}?api_key=${apiKey}` + ); + const data = await res.json(); + setSelectedMovie(data); +}; + +const toggleFavorite = (movieId) => { + setFavorites((prevFavorites) => + prevFavorites.includes(movieId) + ? prevFavorites.filter((id) => id !== movieId) + : [...prevFavorites, movieId] + ); +}; + + +const getSortedMovies = () => { + let sorted = [...movies]; + + if (sortOption === 'title') { + sorted.sort((a, b) => a.title.localeCompare(b.title)); + } else if (sortOption === 'release') { + sorted.sort((a, b) => new Date(b.release_date) - new Date(a.release_date)); + } else if (sortOption === 'rating') { + sorted.sort((a, b) => b.vote_average - a.vote_average); + } + + return sorted; +}; + + + + return ( + <> + {selectedMovie && ( + setSelectedMovie(null)} + /> + )} + +
+

🦦🍿

+ +
+ + + + + +
+ +
+ {getSortedMovies() + .filter((movie) => movie.poster_path) + .map((movie) => ( +
fetchMovieDetails(movie.id)}> + toggleFavorite(movie.id)} + /> +
+ ))} +
+ + {hasMore && ( + + )} + + {!hasMore &&

No more movies to show.

} +
+ +); + +}; + +export default MovieList; diff --git a/src/components/MovieModal.css b/src/components/MovieModal.css new file mode 100644 index 00000000..1a8ebea2 --- /dev/null +++ b/src/components/MovieModal.css @@ -0,0 +1,40 @@ +.modal-overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.7); + display: flex; + align-items: center; + justify-content: center; + z-index: 999; +} + +.modal-content { + background: white; + padding: 1.5rem; + border-radius: 20px; + max-width: 600px; + width: 90%; + text-align: center; + position: relative; + overflow-y: auto; + max-height: 90vh; +} + +.modal-backdrop { + width: 100%; + border-radius: 10px; + margin-bottom: 1rem; +} + +.modal-close { + background: black; + color: white; + border: none; + padding: 10px 25px; + border-radius: 6px; + margin-top: 1rem; + cursor: pointer; +} diff --git a/src/components/MovieModal.jsx b/src/components/MovieModal.jsx new file mode 100644 index 00000000..10d032c0 --- /dev/null +++ b/src/components/MovieModal.jsx @@ -0,0 +1,43 @@ +import './MovieModal.css'; +import PropTypes from 'prop-types'; + + +const MovieModal = ({ movie, onClose }) => { + if (!movie) return null; + + const backdropUrl = `https://image.tmdb.org/t/p/w780${movie.backdrop_path}`; + + return ( +
+
+ {movie.title} +

{movie.title}

+

Release Date: {movie.release_date}

+

Runtime: {movie.runtime} min

+

Overview: {movie.overview}

+

Genres: {movie.genres?.map(g => g.name).join(', ')}

+ +
+
+ ); +}; + +MovieModal.propTypes = { + movie: PropTypes.shape({ + title: PropTypes.string, + overview: PropTypes.string, + runtime: PropTypes.number, + release_date: PropTypes.string, + backdrop_path: PropTypes.string, + genres: PropTypes.arrayOf( + PropTypes.shape({ + id: PropTypes.number, + name: PropTypes.string + }) + ) + }), + onClose: PropTypes.func.isRequired +}; + + +export default MovieModal; diff --git a/src/index.css b/src/index.css index e1faed1a..26f15495 100644 --- a/src/index.css +++ b/src/index.css @@ -17,3 +17,4 @@ button:hover { background-color: #777; color: white; } + From c25beb48eef36805f39670e5a5087be4a81fc6e9 Mon Sep 17 00:00:00 2001 From: Jennifer Obinwanne Date: Wed, 11 Jun 2025 17:19:56 -0700 Subject: [PATCH 02/12] Added the watch feature --- src/App.css | 21 +++++++++ src/assets/close-eye-icon.jpg | Bin 0 -> 17265 bytes src/assets/eye-icon.jpg | Bin 0 -> 41340 bytes src/components/MovieCard.jsx | 39 ++++++++++------ src/components/MovieList.jsx | 83 +++++++++++++++++++++------------- 5 files changed, 98 insertions(+), 45 deletions(-) create mode 100644 src/assets/close-eye-icon.jpg create mode 100644 src/assets/eye-icon.jpg diff --git a/src/App.css b/src/App.css index 21606fc3..31d9ea3f 100644 --- a/src/App.css +++ b/src/App.css @@ -223,3 +223,24 @@ footer { cursor: pointer; margin-top: 5px; } + +.card-icons{ + display: flex; + align-items: flex-end; + justify-content: center; + gap:70px; + background-color: transparent; + border: none; +} +.eye-icon img{ + border: none; + height: 25px; + width: 25px; + background-color: transparent; + +} +button.eye-icon{ + border: none; + background-color: transparent; + +} \ No newline at end of file diff --git a/src/assets/close-eye-icon.jpg b/src/assets/close-eye-icon.jpg new file mode 100644 index 0000000000000000000000000000000000000000..23177a9964b7a6e3712db9c001381a540cb9cba8 GIT binary patch literal 17265 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 NH=+OUe{DJ&`(MWNS^@w7 literal 0 HcmV?d00001 diff --git a/src/assets/eye-icon.jpg b/src/assets/eye-icon.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2f4ca847685178643deefc57479c66e466bc15ac GIT binary patch literal 41340 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 literal 0 HcmV?d00001 diff --git a/src/components/MovieCard.jsx b/src/components/MovieCard.jsx index 7c96b868..c115585d 100644 --- a/src/components/MovieCard.jsx +++ b/src/components/MovieCard.jsx @@ -2,23 +2,34 @@ import PropTypes from 'prop-types'; -const MovieCard = ({ title, posterPath, voteAverage, isFavorite, onToggleFavorite }) => { +const MovieCard = ({ title, posterPath, voteAverage, isFavorite, onToggleFavorite,hasWatched,onToggleWatched }) => { const imageUrl = `https://image.tmdb.org/t/p/w500${posterPath}`; return (
- -

{title}

-

Rating: {voteAverage}

- + Movie Image +

{title}

+

Rating: {voteAverage}

+
+ + +
); }; @@ -28,6 +39,8 @@ MovieCard.propTypes = { voteAverage: PropTypes.number.isRequired, isFavorite: PropTypes.bool.isRequired, onToggleFavorite: PropTypes.func.isRequired, + hasWatched: PropTypes.bool.isRequired, + onToggleWatched: PropTypes.func.isRequired, }; diff --git a/src/components/MovieList.jsx b/src/components/MovieList.jsx index 5c621726..91e500fa 100644 --- a/src/components/MovieList.jsx +++ b/src/components/MovieList.jsx @@ -12,7 +12,7 @@ const MovieList = () => { const [selectedMovie, setSelectedMovie] = useState(null); const [sortOption, setSortOption] = useState(''); const [favorites, setFavorites] = useState([]); - + const [watched, setWatched] = useState([]); @@ -80,11 +80,11 @@ const MovieList = () => { fetchMovies(1, 'nowPlaying'); }; const fetchMovieDetails = async (movieId) => { - const res = await fetch( - `https://api.themoviedb.org/3/movie/${movieId}?api_key=${apiKey}` - ); - const data = await res.json(); - setSelectedMovie(data); + const res = await fetch( + `https://api.themoviedb.org/3/movie/${movieId}?api_key=${apiKey}` + ); + const data = await res.json(); + setSelectedMovie(data); }; const toggleFavorite = (movieId) => { @@ -95,6 +95,15 @@ const toggleFavorite = (movieId) => { ); }; +const toggleWatched = (movieId) => { + setWatched((prev) => + prev.includes(movieId) + ? prev.filter((id) => id !== movieId) + : [...prev, movieId] + + ); +}; + const getSortedMovies = () => { let sorted = [...movies]; @@ -109,6 +118,11 @@ const getSortedMovies = () => { return sorted; }; +const clearSearchBtn = () => { + setSearchQuery(''); + setMode('nowPlaying'); + return null; +} @@ -122,26 +136,28 @@ const getSortedMovies = () => { )}
-

🦦🍿

- -
- - - - - + + + +
@@ -151,12 +167,15 @@ const getSortedMovies = () => { .map((movie) => (
fetchMovieDetails(movie.id)}> toggleFavorite(movie.id)} - /> + title={movie.title} + posterPath={movie.poster_path} + voteAverage={movie.vote_average} + isFavorite={favorites.includes(movie.id)} + onToggleFavorite={() => toggleFavorite(movie.id)} + hasWatched={watched.includes(movie.id)} + onToggleWatched={() => toggleWatched(movie.id)} + + />
))} From 7ebd4b280fe10cf058ceadc7b00a58f86efa3920 Mon Sep 17 00:00:00 2001 From: Jennifer Obinwanne Date: Thu, 12 Jun 2025 09:49:17 -0700 Subject: [PATCH 03/12] Added the Side bar for watched and likes --- src/App.css | 107 ++++++++++++++--- src/components/MovieCard.jsx | 2 + src/components/MovieList.jsx | 215 +++++++++++++++++----------------- src/components/MovieModal.jsx | 59 +++++++++- src/components/Sidebar.css | 30 +++++ src/components/Sidebar.jsx | 42 +++++++ 6 files changed, 333 insertions(+), 122 deletions(-) create mode 100644 src/components/Sidebar.css create mode 100644 src/components/Sidebar.jsx diff --git a/src/App.css b/src/App.css index 31d9ea3f..0a57a6bf 100644 --- a/src/App.css +++ b/src/App.css @@ -9,7 +9,7 @@ html, body { text-align: center; } -.App-header { +/* .App-header { background-color: #282c34; display: flex; flex-direction: row; @@ -17,6 +17,10 @@ html, body { justify-content: space-evenly; color: white; padding: 20px; +} */ +header{ + width: 100%; + } @@ -28,6 +32,18 @@ html, body { align-items: center; } +@media (max-width: 1200px) { + .movie-list { + grid-template-columns: repeat(3, 1fr); /* for tablets */ + } +} + +@media (max-width: 768px) { + .movie-list { + grid-template-columns: repeat(2, 1fr); /* for phones */ + } +} + .controls input, .controls button { width: 100%; @@ -35,13 +51,17 @@ html, body { } .movie-list { - grid-template-columns: 1fr; - gap: 15px; + /* grid-template-columns: 1fr; + gap: 15px; */ + display: grid; + grid-template-columns: repeat(6, 1fr); gap: 16px; + margin-top: 20px; + } .movie-card { max-width: 100%; - height: auto; + height: 360px; } .movie-card img { @@ -71,14 +91,14 @@ html, body { /* Layout basics */ main { - padding: 2rem; - font-family: 'Arial', sans-serif; - max-width: 1200px; - margin: auto; + padding: 1rem 2rem; + flex: 1; + overflow: auto; + position: relative; background-color: pink; - min-width: 100vh; - margin-top: 10px; - border-radius: 10px; + font-family: 'Arial', sans-serif; + width: 100% + } h2 { @@ -93,6 +113,7 @@ h2 { gap: 10px; justify-content: center; margin-bottom: 1.5rem; + margin-top: 0.5rem; } .controls input { @@ -126,9 +147,12 @@ h2 { /* Movie list layout */ .movie-list { display: grid; - grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); + grid-template-columns: repeat(6, 1fr); /* Lock to 6 cards per row */ gap: 20px; - margin-bottom: 2rem; + margin-top: 20px; + padding: 0 20px; + flex-grow: 1; + transition: all 0.3s ease; } /* Individual movie card */ @@ -165,7 +189,7 @@ h2 { /* Load More button */ .load-more { - display: block; + /* display: block; margin: 0 auto; padding: 10px 25px; background-color: hotpink; @@ -174,7 +198,15 @@ h2 { border: none; border-radius: 6px; cursor: pointer; - transition: background-color 0.2s ease; + transition: background-color 0.2s ease; */ + margin-top: 20px; + padding: 10px 16px; + font-size: 16px; + background-color: #ff66b2; + color: white; + border: none; + border-radius: 5px; + cursor: pointer; } .load-more:hover { @@ -183,6 +215,9 @@ h2 { #Otter{ font-size: 50px; + margin-top: 0; /* Remove top space */ + margin-bottom: 0.5rem; /* Just a tiny gap below */ + text-align: center; } @@ -243,4 +278,46 @@ button.eye-icon{ border: none; background-color: transparent; +} + +.layout-container { + /* display: flex; + */ + /* soft pink for body */ + width: 100%; + margin: 0 auto; + padding: 0; + display: flex; + align-items: flex-start; + gap: 0; + background-color: #ffe6f0; + min-height: 100vh; + flex-direction: row; +} + +.sidebar { + width: 250px; + background-color: #ff66b2; /* deep/dark pink */ + color: black; + padding: 20px; + box-shadow: -2px 0 5px rgba(0, 0, 0, 0.1); + position: relative; +} + +.sidebar.closed { + display: none; +} + +.sidebar-toggle { + position: fixed; + top: 20px; + right: 20px; + z-index: 999; + font-size: 24px; + background: #ff66b2; + color: white; + border: none; + border-radius: 5px; + padding: 10px 14px; + cursor: pointer; } \ No newline at end of file diff --git a/src/components/MovieCard.jsx b/src/components/MovieCard.jsx index c115585d..49381b1f 100644 --- a/src/components/MovieCard.jsx +++ b/src/components/MovieCard.jsx @@ -1,5 +1,7 @@ import PropTypes from 'prop-types'; +import '../App.css'; + const MovieCard = ({ title, posterPath, voteAverage, isFavorite, onToggleFavorite,hasWatched,onToggleWatched }) => { diff --git a/src/components/MovieList.jsx b/src/components/MovieList.jsx index 91e500fa..34c56b2c 100644 --- a/src/components/MovieList.jsx +++ b/src/components/MovieList.jsx @@ -1,7 +1,8 @@ import { useEffect, useState } from 'react'; import MovieCard from './MovieCard'; import MovieModal from './MovieModal'; - +import Sidebar from './Sidebar'; +import '../App.css'; const MovieList = () => { const [movies, setMovies] = useState([]); @@ -13,19 +14,17 @@ const MovieList = () => { const [sortOption, setSortOption] = useState(''); const [favorites, setFavorites] = useState([]); const [watched, setWatched] = useState([]); - - + const [sidebarOpen, setSidebarOpen] = useState(true); const apiKey = import.meta.env.VITE_API_KEY; - useEffect(() => { - if (apiKey) { - fetchMovies(1, mode); - } else { - console.error("API key is missing or invalid"); - } -}, [mode]); + if (apiKey) { + fetchMovies(1, mode); + } else { + console.error("API key is missing or invalid"); + } + }, [mode]); const fetchMovies = async (pageNum = 1, currentMode = 'nowPlaying') => { try { @@ -33,26 +32,26 @@ const MovieList = () => { ? `https://api.themoviedb.org/3/search/movie` : `https://api.themoviedb.org/3/movie/now_playing`; - const queryParams = currentMode === 'search' + const queryParams = currentMode === 'search' ? `?query=${searchQuery}&page=${pageNum}&api_key=${apiKey}` : `?page=${pageNum}&api_key=${apiKey}`; - const fullUrl = `${baseUrl}${queryParams}`; - const res = await fetch(fullUrl); - const data = await res.json(); - - if (!data.results || data.results.length === 0 || pageNum >= data.total_pages) { - setHasMore(false); - } - - if (pageNum === 1) { - setMovies(data.results); - } else { - setMovies((prev) => [...prev, ...data.results]); - } - } catch (err) { - console.error("Failed to fetch movies:", err); - } + const fullUrl = `${baseUrl}${queryParams}`; + const res = await fetch(fullUrl); + const data = await res.json(); + + if (!data.results || data.results.length === 0 || pageNum >= data.total_pages) { + setHasMore(false); + } + + if (pageNum === 1) { + setMovies(data.results); + } else { + setMovies((prev) => [...prev, ...data.results]); + } + } catch (err) { + console.error("Failed to fetch movies:", err); + } }; const handleLoadMore = () => { @@ -79,78 +78,86 @@ const MovieList = () => { setMode('nowPlaying'); fetchMovies(1, 'nowPlaying'); }; + const fetchMovieDetails = async (movieId) => { const res = await fetch( - `https://api.themoviedb.org/3/movie/${movieId}?api_key=${apiKey}` + `https://api.themoviedb.org/3/movie/${movieId}?api_key=${apiKey}` ); const data = await res.json(); setSelectedMovie(data); -}; + }; -const toggleFavorite = (movieId) => { - setFavorites((prevFavorites) => - prevFavorites.includes(movieId) - ? prevFavorites.filter((id) => id !== movieId) - : [...prevFavorites, movieId] - ); -}; + const toggleFavorite = (movieId) => { + setFavorites((prevFavorites) => + prevFavorites.includes(movieId) + ? prevFavorites.filter((id) => id !== movieId) + : [...prevFavorites, movieId] + ); + }; -const toggleWatched = (movieId) => { + const toggleWatched = (movieId) => { setWatched((prev) => - prev.includes(movieId) + prev.includes(movieId) ? prev.filter((id) => id !== movieId) : [...prev, movieId] - ); -}; + }; + const getSortedMovies = () => { + let sorted = [...movies]; -const getSortedMovies = () => { - let sorted = [...movies]; + if (sortOption === 'title') { + sorted.sort((a, b) => a.title.localeCompare(b.title)); + } else if (sortOption === 'release') { + sorted.sort((a, b) => new Date(b.release_date) - new Date(a.release_date)); + } else if (sortOption === 'rating') { + sorted.sort((a, b) => b.vote_average - a.vote_average); + } - if (sortOption === 'title') { - sorted.sort((a, b) => a.title.localeCompare(b.title)); - } else if (sortOption === 'release') { - sorted.sort((a, b) => new Date(b.release_date) - new Date(a.release_date)); - } else if (sortOption === 'rating') { - sorted.sort((a, b) => b.vote_average - a.vote_average); - } + return sorted; + }; - return sorted; -}; -const clearSearchBtn = () => { + const clearSearchBtn = () => { setSearchQuery(''); setMode('nowPlaying'); return null; -} - - - - return ( - <> - {selectedMovie && ( - setSelectedMovie(null)} - /> - )} - -
- -

🦦🍿

+ }; -
- - + + {sidebarOpen && ( + favorites.includes(m.id))} + watched={movies.filter((m) => watched.includes(m.id))} + onClose={() => setSidebarOpen(false)} /> - - + )} - + + + + -
- -
- {getSortedMovies() - .filter((movie) => movie.poster_path) - .map((movie) => ( -
fetchMovieDetails(movie.id)}> - toggleFavorite(movie.id)} - hasWatched={watched.includes(movie.id)} - onToggleWatched={() => toggleWatched(movie.id)} - - /> +
- ))} -
- {hasMore && ( - - )} +
+ {getSortedMovies() + .filter((movie) => movie.poster_path) + .map((movie) => ( +
fetchMovieDetails(movie.id)}> + toggleFavorite(movie.id)} + hasWatched={watched.includes(movie.id)} + onToggleWatched={() => toggleWatched(movie.id)} + /> +
+ ))} +
- {!hasMore &&

No more movies to show.

} -
- -); + {hasMore && ()} + {!hasMore &&

No more movies to show.

} +
+ + + + ); }; export default MovieList; diff --git a/src/components/MovieModal.jsx b/src/components/MovieModal.jsx index 10d032c0..156394ee 100644 --- a/src/components/MovieModal.jsx +++ b/src/components/MovieModal.jsx @@ -1,21 +1,75 @@ import './MovieModal.css'; import PropTypes from 'prop-types'; +import { useEffect, useState } from 'react'; + + const MovieModal = ({ movie, onClose }) => { + const [trailerKey, setTrailerKey] = useState(null); + const [noTrailer, setNoTrailer] = useState(false); + + const apiKey = import.meta.env.VITE_API_KEY; + + useEffect(() => { + const fetchTrailer = async () => { + try { + const res = await fetch( + `https://api.themoviedb.org/3/movie/${movie.id}/videos?api_key=${apiKey}` + ); + const data = await res.json(); + + const trailer = data.results.find( + (vid) => vid.type === 'Trailer' && vid.site === 'YouTube' + ); + + if (trailer) { + setTrailerKey(trailer.key); + } else { + setNoTrailer(true); + } + } catch (error) { + console.error('Failed to fetch trailer:', error); + setNoTrailer(true); + } + }; + + fetchTrailer(); + }, [movie.id, apiKey]); + + + if (!movie) return null; const backdropUrl = `https://image.tmdb.org/t/p/w780${movie.backdrop_path}`; return ( -
-
+
+
e.stopPropagation()}> {movie.title}

{movie.title}

Release Date: {movie.release_date}

Runtime: {movie.runtime} min

Overview: {movie.overview}

Genres: {movie.genres?.map(g => g.name).join(', ')}

+ {trailerKey ? ( +
+

🎬 Watch Trailer

+ +
+ ) : noTrailer ? ( +

🚫 No trailer available for this movie.

+ ) : ( +

Loading trailer...

+ )}
@@ -24,6 +78,7 @@ const MovieModal = ({ movie, onClose }) => { MovieModal.propTypes = { movie: PropTypes.shape({ + id: PropTypes.number.isRequired, title: PropTypes.string, overview: PropTypes.string, runtime: PropTypes.number, diff --git a/src/components/Sidebar.css b/src/components/Sidebar.css new file mode 100644 index 00000000..f1491f83 --- /dev/null +++ b/src/components/Sidebar.css @@ -0,0 +1,30 @@ + +.sidebar { + width: 250px; + background-color: #fff0f5; + padding: 1rem; + border-left: 2px solid #ff69b4; + height: 100vh; + overflow-y: auto; + position: sticky; + top: 0; +} + +.sidebar-section { + margin-bottom: 2rem; +} + +.sidebar h3 { + margin-bottom: 0.5rem; + color: #cc3366; +} + +.sidebar ul { + list-style: none; + padding-left: 0; +} + +.sidebar li { + margin-bottom: 0.5rem; + font-size: 0.9rem; +} diff --git a/src/components/Sidebar.jsx b/src/components/Sidebar.jsx new file mode 100644 index 00000000..408208fe --- /dev/null +++ b/src/components/Sidebar.jsx @@ -0,0 +1,42 @@ + +import PropTypes from 'prop-types'; +import './Sidebar.css'; + +const Sidebar = ({ favorites, watched }) => { + return ( + + ); +}; + +Sidebar.propTypes = { + favorites: PropTypes.array.isRequired, + watched: PropTypes.array.isRequired, +}; + +export default Sidebar; \ No newline at end of file From c2d0df1560ea5717e02da4a094e368fb6450681c Mon Sep 17 00:00:00 2001 From: Jennifer Obinwanne Date: Thu, 12 Jun 2025 09:53:39 -0700 Subject: [PATCH 04/12] attempt to fix image on render deploy --- src/components/MovieCard.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/MovieCard.jsx b/src/components/MovieCard.jsx index 49381b1f..caf83765 100644 --- a/src/components/MovieCard.jsx +++ b/src/components/MovieCard.jsx @@ -29,7 +29,7 @@ const MovieCard = ({ title, posterPath, voteAverage, isFavorite, onToggleFavorit onToggleWatched(); // handles the watched toggle }} > -  Watch Status +  Watch Status
From c2fd32a5b3c5d7205793976bf52b5258af1ad387 Mon Sep 17 00:00:00 2001 From: Jennifer Obinwanne Date: Thu, 12 Jun 2025 10:22:42 -0700 Subject: [PATCH 05/12] trying to fix watch status on render --- src/components/MovieCard.jsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/components/MovieCard.jsx b/src/components/MovieCard.jsx index caf83765..faa60d0c 100644 --- a/src/components/MovieCard.jsx +++ b/src/components/MovieCard.jsx @@ -1,12 +1,16 @@ import PropTypes from 'prop-types'; import '../App.css'; +import closeEyeIcon from '/src/assets/close-eye-icon.jpg'; +import eyeIcon from '/src/assets/eye-icon.jpg'; const MovieCard = ({ title, posterPath, voteAverage, isFavorite, onToggleFavorite,hasWatched,onToggleWatched }) => { + const imageUrl = `https://image.tmdb.org/t/p/w500${posterPath}`; + return (
Movie Image @@ -29,7 +33,9 @@ const MovieCard = ({ title, posterPath, voteAverage, isFavorite, onToggleFavorit onToggleWatched(); // handles the watched toggle }} > -  Watch Status + {/* */} + {/*  Watch Status */} + {hasWatched ? : }
From 03dcb3f9f4fdefc1ad88ac96b5916f25451ddd43 Mon Sep 17 00:00:00 2001 From: Jennifer Obinwanne Date: Thu, 12 Jun 2025 12:36:00 -0700 Subject: [PATCH 06/12] worked on my home nav bar --- README.md | 2 ++ src/components/MovieCard.jsx | 2 -- src/components/MovieList.jsx | 18 +++++++++++++++++- src/components/Sidebar.jsx | 14 +++++++++++--- 4 files changed, 30 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index f768e33f..22e9653f 100644 --- a/README.md +++ b/README.md @@ -6,3 +6,5 @@ Currently, two official plugins are available: - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh + +deployed Link = [https://flixster-starter-l0cd.onrender.com] diff --git a/src/components/MovieCard.jsx b/src/components/MovieCard.jsx index faa60d0c..62ef138e 100644 --- a/src/components/MovieCard.jsx +++ b/src/components/MovieCard.jsx @@ -33,8 +33,6 @@ const MovieCard = ({ title, posterPath, voteAverage, isFavorite, onToggleFavorit onToggleWatched(); // handles the watched toggle }} > - {/* */} - {/*  Watch Status */} {hasWatched ? : } diff --git a/src/components/MovieList.jsx b/src/components/MovieList.jsx index 34c56b2c..ca643d59 100644 --- a/src/components/MovieList.jsx +++ b/src/components/MovieList.jsx @@ -14,7 +14,9 @@ const MovieList = () => { const [sortOption, setSortOption] = useState(''); const [favorites, setFavorites] = useState([]); const [watched, setWatched] = useState([]); - const [sidebarOpen, setSidebarOpen] = useState(true); + const [sidebarOpen, setSidebarOpen] = useState(false); + + const apiKey = import.meta.env.VITE_API_KEY; @@ -123,6 +125,19 @@ const MovieList = () => { return null; }; + // for sidebar home + const homePage = () => { + setMode('nowPlaying'); + setSidebarOpen(!sidebarOpen) + } + + // Function to pass to the child component for the "Favorites" button click +// const handleShowFavorites = () => { +// alert("Displaying liked movies: " + prevFavorites.map(movieId => movie.title).join(', ')); +// }; + + + return (
{sidebarOpen && ( favorites.includes(m.id))} watched={movies.filter((m) => watched.includes(m.id))} onClose={() => setSidebarOpen(false)} diff --git a/src/components/Sidebar.jsx b/src/components/Sidebar.jsx index 408208fe..dbba7386 100644 --- a/src/components/Sidebar.jsx +++ b/src/components/Sidebar.jsx @@ -2,11 +2,17 @@ import PropTypes from 'prop-types'; import './Sidebar.css'; -const Sidebar = ({ favorites, watched }) => { +const Sidebar = ({mode, favorites, watched }) => { + + return ( ); }; @@ -37,6 +44,7 @@ const Sidebar = ({ favorites, watched }) => { Sidebar.propTypes = { favorites: PropTypes.array.isRequired, watched: PropTypes.array.isRequired, + mode: PropTypes.func.isRequired, }; export default Sidebar; \ No newline at end of file From c808b9c656b11bcb3cdd65684031f227e5705f94 Mon Sep 17 00:00:00 2001 From: Jennifer Obinwanne Date: Fri, 13 Jun 2025 03:47:19 -0700 Subject: [PATCH 07/12] fixed nav bar issue, allow for overlay display and my home page rendering when nav bar is clicked --- src/App.css | 23 +++++---- src/components/MovieList.jsx | 91 ++++++++++++++++++++++-------------- src/components/Sidebar.css | 15 +++++- src/components/Sidebar.jsx | 18 ++++--- 4 files changed, 92 insertions(+), 55 deletions(-) diff --git a/src/App.css b/src/App.css index 0a57a6bf..6ccc0335 100644 --- a/src/App.css +++ b/src/App.css @@ -53,17 +53,12 @@ header{ .movie-list { /* grid-template-columns: 1fr; gap: 15px; */ - display: grid; - grid-template-columns: repeat(6, 1fr); gap: 16px; + display: flex; + grid-template-columns: repeat(5, 1fr); gap: 18px; margin-top: 20px; } - .movie-card { - max-width: 100%; - height: 360px; - } - .movie-card img { height: auto; object-fit: contain; @@ -157,13 +152,18 @@ h2 { /* Individual movie card */ .movie-card { - background-color: palevioletred; + background-color: #f48fb1; border-radius: 10px; overflow: hidden; text-align: center; padding: 10px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); transition: transform 0.2s ease; + width: 200px; /* fixed width */ + height: 400px; /* fixed height to unify layout */ + display: flex; + flex-direction: column; + justify-content: space-between; } .movie-card:hover { @@ -173,13 +173,16 @@ h2 { .movie-card img { width: 100%; border-radius: 10px; - height: 270px; + height: 250px; object-fit: cover; } .movie-card h3 { font-size: 1rem; margin: 10px 0 5px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; } .movie-card p { @@ -287,7 +290,7 @@ button.eye-icon{ width: 100%; margin: 0 auto; padding: 0; - display: flex; + display: grid; align-items: flex-start; gap: 0; background-color: #ffe6f0; diff --git a/src/components/MovieList.jsx b/src/components/MovieList.jsx index ca643d59..5d48a9f8 100644 --- a/src/components/MovieList.jsx +++ b/src/components/MovieList.jsx @@ -15,6 +15,7 @@ const MovieList = () => { const [favorites, setFavorites] = useState([]); const [watched, setWatched] = useState([]); const [sidebarOpen, setSidebarOpen] = useState(false); + const [viewMode, setViewMode] = useState('all'); @@ -89,34 +90,48 @@ const MovieList = () => { setSelectedMovie(data); }; - const toggleFavorite = (movieId) => { - setFavorites((prevFavorites) => - prevFavorites.includes(movieId) - ? prevFavorites.filter((id) => id !== movieId) - : [...prevFavorites, movieId] - ); - }; + const toggleFavorite = (movie) => { + setFavorites((prevFavorites) => { + const isAlreadyFavorited = prevFavorites.some((m) => m.id === movie.id); + return isAlreadyFavorited + ? prevFavorites.filter((m) => m.id !== movie.id) + : [...prevFavorites, movie]; + }); +}; + + + + const toggleWatched = (movie) => { + setWatched((prevWatched) => { + const isAlreadyWatched = prevWatched.some((m) => m.id === movie.id); + return isAlreadyWatched + ? prevWatched.filter((m) => m.id !== movie.id) + : [...prevWatched, movie]; + }); +}; - const toggleWatched = (movieId) => { - setWatched((prev) => - prev.includes(movieId) - ? prev.filter((id) => id !== movieId) - : [...prev, movieId] - ); - }; const getSortedMovies = () => { - let sorted = [...movies]; + + let filteredMovies; + + if (viewMode === 'favorites') { + filteredMovies = [...favorites]; + } else if (viewMode === 'watched') { + filteredMovies = [...watched]; + } else { + filteredMovies = [...movies]; + } if (sortOption === 'title') { - sorted.sort((a, b) => a.title.localeCompare(b.title)); + filteredMovies.sort((a, b) => a.title.localeCompare(b.title)); } else if (sortOption === 'release') { - sorted.sort((a, b) => new Date(b.release_date) - new Date(a.release_date)); + filteredMovies.sort((a, b) => new Date(b.release_date) - new Date(a.release_date)); } else if (sortOption === 'rating') { - sorted.sort((a, b) => b.vote_average - a.vote_average); + filteredMovies.sort((a, b) => b.vote_average - a.vote_average); } - return sorted; + return filteredMovies; }; const clearSearchBtn = () => { @@ -127,31 +142,38 @@ const MovieList = () => { // for sidebar home const homePage = () => { + setSearchQuery(''); + setViewMode('all'); setMode('nowPlaying'); - setSidebarOpen(!sidebarOpen) + setPage(1); + setHasMore(true); + fetchMovies(1, 'nowPlaying'); + setSidebarOpen(false); } - - // Function to pass to the child component for the "Favorites" button click -// const handleShowFavorites = () => { -// alert("Displaying liked movies: " + prevFavorites.map(movieId => movie.title).join(', ')); -// }; - return ( + + return (
{sidebarOpen && ( + favorites.includes(m.id))} - watched={movies.filter((m) => watched.includes(m.id))} - onClose={() => setSidebarOpen(false)} + mode={homePage} + favorites={favorites} + watched={watched} + onSelectView={(mode) => { + setViewMode(mode); + setSidebarOpen(false); // close after click + }} /> + )} +
{selectedMovie && ( { title={movie.title} posterPath={movie.poster_path} voteAverage={movie.vote_average} - isFavorite={favorites.includes(movie.id)} - onToggleFavorite={() => toggleFavorite(movie.id)} - hasWatched={watched.includes(movie.id)} - onToggleWatched={() => toggleWatched(movie.id)} + isFavorite={favorites.some((fav) => fav.id === movie.id)} + onToggleFavorite={() => toggleFavorite(movie)} + hasWatched={watched.some((w) => w.id === movie.id)} + onToggleWatched={() => toggleWatched(movie)} /> +
))}
diff --git a/src/components/Sidebar.css b/src/components/Sidebar.css index f1491f83..04cebf4c 100644 --- a/src/components/Sidebar.css +++ b/src/components/Sidebar.css @@ -1,5 +1,5 @@ -.sidebar { +/* .sidebar { width: 250px; background-color: #fff0f5; padding: 1rem; @@ -8,8 +8,21 @@ overflow-y: auto; position: sticky; top: 0; +} */ + +.sidebar { + position: fixed; + top: 0; + left: 0; + width: 250px; + height: 100%; + background-color: rgba(255, 182, 185, 0.6); + z-index: 1000; + overflow-y: auto; + padding: 20px; } + .sidebar-section { margin-bottom: 2rem; } diff --git a/src/components/Sidebar.jsx b/src/components/Sidebar.jsx index dbba7386..a341e911 100644 --- a/src/components/Sidebar.jsx +++ b/src/components/Sidebar.jsx @@ -2,17 +2,15 @@ import PropTypes from 'prop-types'; import './Sidebar.css'; -const Sidebar = ({mode, favorites, watched }) => { - - +const Sidebar = ({ mode, favorites, watched, onSelectView }) => { return ( ); }; Sidebar.propTypes = { + mode: PropTypes.func.isRequired, favorites: PropTypes.array.isRequired, watched: PropTypes.array.isRequired, - mode: PropTypes.func.isRequired, + onSelectView: PropTypes.func.isRequired, }; -export default Sidebar; \ No newline at end of file +export default Sidebar; From 9c43cedc50fc617671065f38ac9688bd4b68ded8 Mon Sep 17 00:00:00 2001 From: Jennifer Obinwanne Date: Fri, 13 Jun 2025 04:18:12 -0700 Subject: [PATCH 08/12] modified my README file --- README.md | 131 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 125 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 22e9653f..5bb3b6e6 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,129 @@ -# React + Vite +deployed Link = [https://flixster-starter-l0cd.onrender.com] -This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. +## Unit Assignment: Flixster -Currently, two official plugins are available: +Submitted by: **Jennifer Obinwanne** -- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh -- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh +Estimated time spent: **36+** hours spent in total -deployed Link = [https://flixster-starter-l0cd.onrender.com] +Deployed Application (**required**): [Flixster Deployed Site](https://flixster-starter-l0cd.onrender.com) + +### Application Features + +#### REQUIRED FEATURES + +- [x] **Display Movies** + - [x] Users can view a list of current movies from The Movie Database API in a grid view. + - [x] Movie tiles should be reasonably sized (at least 6 playlists on your laptop when full screen; large enough that the playlist components detailed in the next feature are legible). + - [x] For each movie displayed, users can see the movie's: + - [x] Title + - [x] Poster image + - [x] Vote average + - [x] Users can load more current movies by clicking a button which adds more movies to the grid without reloading the entire page. +- [x] **Search Functionality** + - [x] Users can use a search bar to search for movies by title. + - [x] The search bar should include: + - [x] Text input field + - [x] Submit/Search button + - [ ] Clear button + - [x] Movies with a title containing the search query in the text input field are displayed in a grid view when the user either: + - [x] Presses the Enter key + - [x] Clicks the Submit/Search button + - [ ] Users can click the Clear button. When clicked: + - [ ] Most recent search results are cleared from the text input field and the grid view and all current movies are displayed in a grid view +- [x] **Design Features** + - [x] Website implements all of the following accessibility features: + - [x] Semantic HTML + - [x] [Color contrast](https://webaim.org/resources/contrastchecker/) + - [x] Alt text for images + - [x] Website implements responsive web design. + - [x] Uses CSS Flexbox or CSS Grid + - [x] Movie tiles and images shrink/grow in response to window size + - [x] Users can click on a movie tile to view more details about a movie in a pop-up modal. + - [x] The pop-up window is centered in the screen and does not occupy the entire screen. + - [x] The pop-up window has a shadow to show that it is a pop-up and appears floating on the screen. + - [x] The backdrop of the pop-up appears darker or in a different shade than before. including: + - [x] The pop-up displays additional details about the movie including: + - [x] Runtime in minutes + - [x] Backdrop poster + - [x] Release date + - [x] Genres + - [x] An overview + - [x] Users can use a drop-down menu to sort movies. + - [x] Drop-down allows movies to be sorted by: + - [x] Title (alphabetic, A-Z) + - [x] Release date (chronologically, most recent to oldest) + - [x] Vote average (descending, highest to lowest) + - [x] When a sort option is clicked, movies display in a grid according to selected criterion. + - [x] Website displays: + - [x] Header section + - [x] Banner section + - [x] Search bar + - [x] Movie grid + - [x] Footer section + - [x] **VIDEO WALKTHROUGH SPECIAL INSTRUCTIONS**: To ease the grading process, please use the [color contrast checker](https://webaim.org/resources/contrastchecker/) to demonstrate to the grading team that text and background colors on your website have appropriate contrast. The Contrast Ratio should be above 4.5:1 and should have a green box surrounding it. + - [x] **Deployment** + - [x] Website is deployed via Render. + - [x] **VIDEO WALKTHROUGH SPECIAL INSTRUCTIONS**: For ease of grading, please use the deployed version of your website when creating your walkthrough. + +#### STRETCH FEATURES + +- [x] **Embedded Movie Trailers** + - [x] Within the pop-up modal displaying a movie's details, the movie trailer is viewable. + - [x] When the trailer is clicked, users can play the movie trailer. +- [x] **Favorite Button** + - [x] For each movie displayed, users can favorite the movie. + - [x] There should be visual element (such as a heart icon) on each movie's tile to show whether or not the movie has been favorited. + - [x] If the movie is not favorited: + - [x] Clicking on the visual element should mark the movie as favorited + - [x] There should be visual feedback (such as the heart turning a different color) to show that the movie has been favorited by the user. + - [x] If the movie is already favorited: + - [x] Clicking on the visual element should mark the movie as _not_ favorited. + - [x] There should be visual feedback (such as the heart turning a different color) to show that the movie has been unfavorited. +- [x] **Watched Checkbox** + - [x] For each movie displayed, users can mark the movie as watched. + - [x] There should be visual element (such as an eye icon) on each movie's tile to show whether or not the movie has been watched. + - [x] If the movie has not been watched: + - [x] Clicking on the visual element should mark the movie as watched + - [x] There should be visual feedback (such as the eye turning a different color) to show that the movie has been watched by the user. + - [x] If the movie is already watched: + - [x] Clicking on the visual element should mark the movie as _not_ watched. + - [x] There should be visual feedback (such as the eye turning a different color) to show that the movie has not been watched. +- [x] **Sidebar** + - [x] The website includes a side navigation bar. + - [x] The sidebar has three pages: + - [x] Home + - [x] Favorites + - [x] Watched + - [x] The Home page displays all current movies in a grid view, the search bar, and the sort movies drop-down. + - [x] The Favorites page displays all favorited movies in a grid view. + - [x] The Watched page displays all watched movies in a grid view. + +### Walkthrough Video + +`TODO://` Add the embedded URL code to your animated app walkthrough below. + +`ADD_EMBEDDED_CODE_HERE` + +### Reflection + +- Did the topics discussed in your labs prepare you to complete the assignment? Be specific, which features in your weekly assignment did you feel unprepared to complete? + +Yes, the labs definitely laid the foundation I needed to build the core of this project. Topics like using props, lifting state, conditional rendering, and React hooks were all essential in helping me navigate the dynamic behaviors of this project. However, the sidebar navigation stretch feature was definitely more complex than what we directly covered. It pushed me to learn more about conditional rendering, component structure, and view toggling in React. + +- If you had more time, what would you have done differently? Would you have added additional features? Changed the way your project responded to a particular event, etc. + +If I had more time, I would’ve implemented local storage or a persistent backend so users' favorite and watched movies don’t reset on refresh. I also would've loved to experiment with animations—for example, smooth transitions between views, or slight scaling effects when hovering over movie tiles to make the interface feel more interactive and modern. + +- Reflect on your project demo, what went well? Were there things that maybe didn't go as planned? Did you notice something that your peer did that you would like to try next time? + +I was really happy with how the core functionality came together in the demo—especially being able to embed trailers and switch between views using the sidebar. The modal pop-up also felt clean and polished. One thing I saw others do that I’d love to try next time is integrating a theme switcher (light/dark mode) and possibly using a component library to speed up UI development without starting from scratch every time. + +### Open-source libraries used + +- [The Movie Database (TMDb) API](https://developer.themoviedb.org/) +- [YouTube API for trailers](https://developers.google.com/youtube/v3) + +### Shout out + +Shout out to Codepath TAs and my peers who helped me debug the sidebar logic! 🙌🏽 From 640cc05968e48e43f15ecc4eab112d100486d8c0 Mon Sep 17 00:00:00 2001 From: Obinwanne Jennifer <124430261+Jenn-jaee@users.noreply.github.com> Date: Fri, 13 Jun 2025 04:31:11 -0700 Subject: [PATCH 09/12] Update README.md Added image visuals --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index 5bb3b6e6..e0a298d5 100644 --- a/README.md +++ b/README.md @@ -98,6 +98,13 @@ Deployed Application (**required**): [Flixster Deployed Site](https://flixster-s - [x] The Home page displays all current movies in a grid view, the search bar, and the sort movies drop-down. - [x] The Favorites page displays all favorited movies in a grid view. - [x] The Watched page displays all watched movies in a grid view. + + + +### Image display +![image](https://github.com/user-attachments/assets/525a3462-506c-4cd6-a459-2e75b892e8d7) +![image](https://github.com/user-attachments/assets/67347613-abe0-4758-bf96-6b288cba1343) + ### Walkthrough Video From e000b56c646c8e875b9d210460cecded3a4ea930 Mon Sep 17 00:00:00 2001 From: Obinwanne Jennifer <124430261+Jenn-jaee@users.noreply.github.com> Date: Fri, 13 Jun 2025 15:02:18 -0700 Subject: [PATCH 10/12] Update README.md Added my video walklthrough --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e0a298d5..0664f8dd 100644 --- a/README.md +++ b/README.md @@ -108,7 +108,7 @@ Deployed Application (**required**): [Flixster Deployed Site](https://flixster-s ### Walkthrough Video -`TODO://` Add the embedded URL code to your animated app walkthrough below. +`TODO://` (https://www.loom.com/share/26f53bf9a2ec427f91070bd75caaae84). `ADD_EMBEDDED_CODE_HERE` From 19aac6000caf1c0daebcee99c9dc9024764c5e2c Mon Sep 17 00:00:00 2001 From: Jennifer Obinwanne Date: Fri, 13 Jun 2025 12:00:37 -0700 Subject: [PATCH 11/12] made chages to my CSS to make it more moibile responsive --- src/App.css | 76 +++++++++++++++++++++--------------- src/components/MovieList.jsx | 2 +- src/components/Sidebar.css | 6 +++ src/components/Sidebar.jsx | 6 +-- 4 files changed, 55 insertions(+), 35 deletions(-) diff --git a/src/App.css b/src/App.css index 6ccc0335..e1f59797 100644 --- a/src/App.css +++ b/src/App.css @@ -1,3 +1,12 @@ +@viewport { + width: device-width; + initial-scale: 1; +} + +* { + box-sizing: border-box; +} + html, body { height: 100%; margin: 0; @@ -9,15 +18,6 @@ html, body { text-align: center; } -/* .App-header { - background-color: #282c34; - display: flex; - flex-direction: row; - align-items: center; - justify-content: space-evenly; - color: white; - padding: 20px; -} */ header{ width: 100%; @@ -32,15 +32,34 @@ header{ align-items: center; } -@media (max-width: 1200px) { - .movie-list { - grid-template-columns: repeat(3, 1fr); /* for tablets */ + +@media (max-width: 768px) { + .movie-card { + grid-template-columns: 1fr; /* for phones */ } } -@media (max-width: 768px) { - .movie-list { - grid-template-columns: repeat(2, 1fr); /* for phones */ +.grid-container { + display: flex; + flex-wrap: wrap; + gap: 18px; + grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); +} + +/* Adjust grid columns based on screen size */ +@media only screen and (max-width: 768px) { + .grid-container { + display: flex; + flex-wrap: wrap; + grid-template-columns: 1fr; + } +} + +/* Tablet and iPad layout */ +@media (min-width: 769px) and (max-width: 1024px) { + .grid-container { + + grid-template-columns: repeat(3, 1fr); } } @@ -65,18 +84,6 @@ header{ } } -@media (max-width: 900px) and (min-width: 601px) { - .movie-list { - grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); - } - - .controls { - flex-direction: row; - flex-wrap: wrap; - justify-content: center; - gap: 12px; - } -} @@ -131,7 +138,7 @@ h2 { } .controls button:disabled { - background-color: #ccc; + background-color: black; cursor: not-allowed; } @@ -139,15 +146,21 @@ h2 { background-color: #0056b3; } +.sort-box { + border-radius: 10px; +} + /* Movie list layout */ .movie-list { - display: grid; - grid-template-columns: repeat(6, 1fr); /* Lock to 6 cards per row */ - gap: 20px; + display: flex; + /* grid-template-columns: repeat(6, 1fr); Lock to 6 cards per row */ + gap: 2rem; margin-top: 20px; padding: 0 20px; flex-grow: 1; transition: all 0.3s ease; + flex-wrap: wrap; + margin-left: 85px; } /* Individual movie card */ @@ -164,6 +177,7 @@ h2 { display: flex; flex-direction: column; justify-content: space-between; + margin-bottom: 10px; } .movie-card:hover { diff --git a/src/components/MovieList.jsx b/src/components/MovieList.jsx index 5d48a9f8..b4c5d32e 100644 --- a/src/components/MovieList.jsx +++ b/src/components/MovieList.jsx @@ -195,7 +195,7 @@ const MovieList = () => { -