Compare commits
No commits in common. "54217e7adfa9fd50c3f0f25159ada415e16d3723" and "e287f6c9d223e59b76d631c1b982634edfd5c817" have entirely different histories.
54217e7adf
...
e287f6c9d2
|
@ -16,12 +16,9 @@
|
||||||
"@types/node": "^24.2.0",
|
"@types/node": "^24.2.0",
|
||||||
"@types/react": "^19.1.9",
|
"@types/react": "^19.1.9",
|
||||||
"@types/react-dom": "^19.1.7",
|
"@types/react-dom": "^19.1.7",
|
||||||
"framer-motion": "^12.23.12",
|
|
||||||
"react": "^19.1.1",
|
"react": "^19.1.1",
|
||||||
"react-confetti": "^6.4.0",
|
|
||||||
"react-dom": "^19.1.1",
|
"react-dom": "^19.1.1",
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
"recharts": "^3.1.0",
|
|
||||||
"typescript": "^5.9.2",
|
"typescript": "^5.9.2",
|
||||||
"web-vitals": "^2.1.4"
|
"web-vitals": "^2.1.4"
|
||||||
}
|
}
|
||||||
|
@ -2929,40 +2926,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@reduxjs/toolkit": {
|
|
||||||
"version": "2.8.2",
|
|
||||||
"resolved": "https://registry.npmmirror.com/@reduxjs/toolkit/-/toolkit-2.8.2.tgz",
|
|
||||||
"integrity": "sha512-MYlOhQ0sLdw4ud48FoC5w0dH9VfWQjtCjreKwYTT3l+r427qYC5Y8PihNutepr8XrNaBUDQo9khWUwQxZaqt5A==",
|
|
||||||
"dependencies": {
|
|
||||||
"@standard-schema/spec": "^1.0.0",
|
|
||||||
"@standard-schema/utils": "^0.3.0",
|
|
||||||
"immer": "^10.0.3",
|
|
||||||
"redux": "^5.0.1",
|
|
||||||
"redux-thunk": "^3.1.0",
|
|
||||||
"reselect": "^5.1.0"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"react": "^16.9.0 || ^17.0.0 || ^18 || ^19",
|
|
||||||
"react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"react": {
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"react-redux": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@reduxjs/toolkit/node_modules/immer": {
|
|
||||||
"version": "10.1.1",
|
|
||||||
"resolved": "https://registry.npmmirror.com/immer/-/immer-10.1.1.tgz",
|
|
||||||
"integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==",
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/immer"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@rollup/plugin-babel": {
|
"node_modules/@rollup/plugin-babel": {
|
||||||
"version": "5.3.1",
|
"version": "5.3.1",
|
||||||
"resolved": "https://registry.npmmirror.com/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz",
|
"resolved": "https://registry.npmmirror.com/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz",
|
||||||
|
@ -3068,16 +3031,6 @@
|
||||||
"@sinonjs/commons": "^1.7.0"
|
"@sinonjs/commons": "^1.7.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@standard-schema/spec": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmmirror.com/@standard-schema/spec/-/spec-1.0.0.tgz",
|
|
||||||
"integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA=="
|
|
||||||
},
|
|
||||||
"node_modules/@standard-schema/utils": {
|
|
||||||
"version": "0.3.0",
|
|
||||||
"resolved": "https://registry.npmmirror.com/@standard-schema/utils/-/utils-0.3.0.tgz",
|
|
||||||
"integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g=="
|
|
||||||
},
|
|
||||||
"node_modules/@surma/rollup-plugin-off-main-thread": {
|
"node_modules/@surma/rollup-plugin-off-main-thread": {
|
||||||
"version": "2.2.3",
|
"version": "2.2.3",
|
||||||
"resolved": "https://registry.npmmirror.com/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz",
|
"resolved": "https://registry.npmmirror.com/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz",
|
||||||
|
@ -3479,60 +3432,6 @@
|
||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/d3-array": {
|
|
||||||
"version": "3.2.1",
|
|
||||||
"resolved": "https://registry.npmmirror.com/@types/d3-array/-/d3-array-3.2.1.tgz",
|
|
||||||
"integrity": "sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg=="
|
|
||||||
},
|
|
||||||
"node_modules/@types/d3-color": {
|
|
||||||
"version": "3.1.3",
|
|
||||||
"resolved": "https://registry.npmmirror.com/@types/d3-color/-/d3-color-3.1.3.tgz",
|
|
||||||
"integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A=="
|
|
||||||
},
|
|
||||||
"node_modules/@types/d3-ease": {
|
|
||||||
"version": "3.0.2",
|
|
||||||
"resolved": "https://registry.npmmirror.com/@types/d3-ease/-/d3-ease-3.0.2.tgz",
|
|
||||||
"integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA=="
|
|
||||||
},
|
|
||||||
"node_modules/@types/d3-interpolate": {
|
|
||||||
"version": "3.0.4",
|
|
||||||
"resolved": "https://registry.npmmirror.com/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz",
|
|
||||||
"integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==",
|
|
||||||
"dependencies": {
|
|
||||||
"@types/d3-color": "*"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@types/d3-path": {
|
|
||||||
"version": "3.1.1",
|
|
||||||
"resolved": "https://registry.npmmirror.com/@types/d3-path/-/d3-path-3.1.1.tgz",
|
|
||||||
"integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg=="
|
|
||||||
},
|
|
||||||
"node_modules/@types/d3-scale": {
|
|
||||||
"version": "4.0.9",
|
|
||||||
"resolved": "https://registry.npmmirror.com/@types/d3-scale/-/d3-scale-4.0.9.tgz",
|
|
||||||
"integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==",
|
|
||||||
"dependencies": {
|
|
||||||
"@types/d3-time": "*"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@types/d3-shape": {
|
|
||||||
"version": "3.1.7",
|
|
||||||
"resolved": "https://registry.npmmirror.com/@types/d3-shape/-/d3-shape-3.1.7.tgz",
|
|
||||||
"integrity": "sha512-VLvUQ33C+3J+8p+Daf+nYSOsjB4GXp19/S/aGo60m9h1v6XaxjiT82lKVWJCfzhtuZ3yD7i/TPeC/fuKLLOSmg==",
|
|
||||||
"dependencies": {
|
|
||||||
"@types/d3-path": "*"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@types/d3-time": {
|
|
||||||
"version": "3.0.4",
|
|
||||||
"resolved": "https://registry.npmmirror.com/@types/d3-time/-/d3-time-3.0.4.tgz",
|
|
||||||
"integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g=="
|
|
||||||
},
|
|
||||||
"node_modules/@types/d3-timer": {
|
|
||||||
"version": "3.0.2",
|
|
||||||
"resolved": "https://registry.npmmirror.com/@types/d3-timer/-/d3-timer-3.0.2.tgz",
|
|
||||||
"integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw=="
|
|
||||||
},
|
|
||||||
"node_modules/@types/eslint": {
|
"node_modules/@types/eslint": {
|
||||||
"version": "8.56.12",
|
"version": "8.56.12",
|
||||||
"resolved": "https://registry.npmmirror.com/@types/eslint/-/eslint-8.56.12.tgz",
|
"resolved": "https://registry.npmmirror.com/@types/eslint/-/eslint-8.56.12.tgz",
|
||||||
|
@ -3967,11 +3866,6 @@
|
||||||
"resolved": "https://registry.npmmirror.com/@types/trusted-types/-/trusted-types-2.0.7.tgz",
|
"resolved": "https://registry.npmmirror.com/@types/trusted-types/-/trusted-types-2.0.7.tgz",
|
||||||
"integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="
|
"integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="
|
||||||
},
|
},
|
||||||
"node_modules/@types/use-sync-external-store": {
|
|
||||||
"version": "0.0.6",
|
|
||||||
"resolved": "https://registry.npmmirror.com/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz",
|
|
||||||
"integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg=="
|
|
||||||
},
|
|
||||||
"node_modules/@types/ws": {
|
"node_modules/@types/ws": {
|
||||||
"version": "8.18.1",
|
"version": "8.18.1",
|
||||||
"resolved": "https://registry.npmmirror.com/@types/ws/-/ws-8.18.1.tgz",
|
"resolved": "https://registry.npmmirror.com/@types/ws/-/ws-8.18.1.tgz",
|
||||||
|
@ -5590,14 +5484,6 @@
|
||||||
"wrap-ansi": "^7.0.0"
|
"wrap-ansi": "^7.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/clsx": {
|
|
||||||
"version": "2.1.1",
|
|
||||||
"resolved": "https://registry.npmmirror.com/clsx/-/clsx-2.1.1.tgz",
|
|
||||||
"integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/co": {
|
"node_modules/co": {
|
||||||
"version": "4.6.0",
|
"version": "4.6.0",
|
||||||
"resolved": "https://registry.npmmirror.com/co/-/co-4.6.0.tgz",
|
"resolved": "https://registry.npmmirror.com/co/-/co-4.6.0.tgz",
|
||||||
|
@ -6271,116 +6157,6 @@
|
||||||
"resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.1.3.tgz",
|
"resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.1.3.tgz",
|
||||||
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
|
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
|
||||||
},
|
},
|
||||||
"node_modules/d3-array": {
|
|
||||||
"version": "3.2.4",
|
|
||||||
"resolved": "https://registry.npmmirror.com/d3-array/-/d3-array-3.2.4.tgz",
|
|
||||||
"integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==",
|
|
||||||
"dependencies": {
|
|
||||||
"internmap": "1 - 2"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=12"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/d3-color": {
|
|
||||||
"version": "3.1.0",
|
|
||||||
"resolved": "https://registry.npmmirror.com/d3-color/-/d3-color-3.1.0.tgz",
|
|
||||||
"integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=12"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/d3-ease": {
|
|
||||||
"version": "3.0.1",
|
|
||||||
"resolved": "https://registry.npmmirror.com/d3-ease/-/d3-ease-3.0.1.tgz",
|
|
||||||
"integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=12"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/d3-format": {
|
|
||||||
"version": "3.1.0",
|
|
||||||
"resolved": "https://registry.npmmirror.com/d3-format/-/d3-format-3.1.0.tgz",
|
|
||||||
"integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=12"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/d3-interpolate": {
|
|
||||||
"version": "3.0.1",
|
|
||||||
"resolved": "https://registry.npmmirror.com/d3-interpolate/-/d3-interpolate-3.0.1.tgz",
|
|
||||||
"integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==",
|
|
||||||
"dependencies": {
|
|
||||||
"d3-color": "1 - 3"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=12"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/d3-path": {
|
|
||||||
"version": "3.1.0",
|
|
||||||
"resolved": "https://registry.npmmirror.com/d3-path/-/d3-path-3.1.0.tgz",
|
|
||||||
"integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=12"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/d3-scale": {
|
|
||||||
"version": "4.0.2",
|
|
||||||
"resolved": "https://registry.npmmirror.com/d3-scale/-/d3-scale-4.0.2.tgz",
|
|
||||||
"integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==",
|
|
||||||
"dependencies": {
|
|
||||||
"d3-array": "2.10.0 - 3",
|
|
||||||
"d3-format": "1 - 3",
|
|
||||||
"d3-interpolate": "1.2.0 - 3",
|
|
||||||
"d3-time": "2.1.1 - 3",
|
|
||||||
"d3-time-format": "2 - 4"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=12"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/d3-shape": {
|
|
||||||
"version": "3.2.0",
|
|
||||||
"resolved": "https://registry.npmmirror.com/d3-shape/-/d3-shape-3.2.0.tgz",
|
|
||||||
"integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==",
|
|
||||||
"dependencies": {
|
|
||||||
"d3-path": "^3.1.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=12"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/d3-time": {
|
|
||||||
"version": "3.1.0",
|
|
||||||
"resolved": "https://registry.npmmirror.com/d3-time/-/d3-time-3.1.0.tgz",
|
|
||||||
"integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==",
|
|
||||||
"dependencies": {
|
|
||||||
"d3-array": "2 - 3"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=12"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/d3-time-format": {
|
|
||||||
"version": "4.1.0",
|
|
||||||
"resolved": "https://registry.npmmirror.com/d3-time-format/-/d3-time-format-4.1.0.tgz",
|
|
||||||
"integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==",
|
|
||||||
"dependencies": {
|
|
||||||
"d3-time": "1 - 3"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=12"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/d3-timer": {
|
|
||||||
"version": "3.0.1",
|
|
||||||
"resolved": "https://registry.npmmirror.com/d3-timer/-/d3-timer-3.0.1.tgz",
|
|
||||||
"integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=12"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/damerau-levenshtein": {
|
"node_modules/damerau-levenshtein": {
|
||||||
"version": "1.0.8",
|
"version": "1.0.8",
|
||||||
"resolved": "https://registry.npmmirror.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
|
"resolved": "https://registry.npmmirror.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
|
||||||
|
@ -6468,11 +6244,6 @@
|
||||||
"resolved": "https://registry.npmmirror.com/decimal.js/-/decimal.js-10.6.0.tgz",
|
"resolved": "https://registry.npmmirror.com/decimal.js/-/decimal.js-10.6.0.tgz",
|
||||||
"integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg=="
|
"integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg=="
|
||||||
},
|
},
|
||||||
"node_modules/decimal.js-light": {
|
|
||||||
"version": "2.5.1",
|
|
||||||
"resolved": "https://registry.npmmirror.com/decimal.js-light/-/decimal.js-light-2.5.1.tgz",
|
|
||||||
"integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg=="
|
|
||||||
},
|
|
||||||
"node_modules/dedent": {
|
"node_modules/dedent": {
|
||||||
"version": "0.7.0",
|
"version": "0.7.0",
|
||||||
"resolved": "https://registry.npmmirror.com/dedent/-/dedent-0.7.0.tgz",
|
"resolved": "https://registry.npmmirror.com/dedent/-/dedent-0.7.0.tgz",
|
||||||
|
@ -7060,15 +6831,6 @@
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/es-toolkit": {
|
|
||||||
"version": "1.39.8",
|
|
||||||
"resolved": "https://registry.npmmirror.com/es-toolkit/-/es-toolkit-1.39.8.tgz",
|
|
||||||
"integrity": "sha512-A8QO9TfF+rltS8BXpdu8OS+rpGgEdnRhqIVxO/ZmNvnXBYgOdSsxukT55ELyP94gZIntWJ+Li9QRrT2u1Kitpg==",
|
|
||||||
"workspaces": [
|
|
||||||
"docs",
|
|
||||||
"benchmarks"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/escalade": {
|
"node_modules/escalade": {
|
||||||
"version": "3.2.0",
|
"version": "3.2.0",
|
||||||
"resolved": "https://registry.npmmirror.com/escalade/-/escalade-3.2.0.tgz",
|
"resolved": "https://registry.npmmirror.com/escalade/-/escalade-3.2.0.tgz",
|
||||||
|
@ -8246,32 +8008,6 @@
|
||||||
"url": "https://github.com/sponsors/rawify"
|
"url": "https://github.com/sponsors/rawify"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/framer-motion": {
|
|
||||||
"version": "12.23.12",
|
|
||||||
"resolved": "https://registry.npmmirror.com/framer-motion/-/framer-motion-12.23.12.tgz",
|
|
||||||
"integrity": "sha512-6e78rdVtnBvlEVgu6eFEAgG9v3wLnYEboM8I5O5EXvfKC8gxGQB8wXJdhkMy10iVcn05jl6CNw7/HTsTCfwcWg==",
|
|
||||||
"dependencies": {
|
|
||||||
"motion-dom": "^12.23.12",
|
|
||||||
"motion-utils": "^12.23.6",
|
|
||||||
"tslib": "^2.4.0"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@emotion/is-prop-valid": "*",
|
|
||||||
"react": "^18.0.0 || ^19.0.0",
|
|
||||||
"react-dom": "^18.0.0 || ^19.0.0"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"@emotion/is-prop-valid": {
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"react": {
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"react-dom": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/fresh": {
|
"node_modules/fresh": {
|
||||||
"version": "0.5.2",
|
"version": "0.5.2",
|
||||||
"resolved": "https://registry.npmmirror.com/fresh/-/fresh-0.5.2.tgz",
|
"resolved": "https://registry.npmmirror.com/fresh/-/fresh-0.5.2.tgz",
|
||||||
|
@ -9084,14 +8820,6 @@
|
||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/internmap": {
|
|
||||||
"version": "2.0.3",
|
|
||||||
"resolved": "https://registry.npmmirror.com/internmap/-/internmap-2.0.3.tgz",
|
|
||||||
"integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=12"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/ipaddr.js": {
|
"node_modules/ipaddr.js": {
|
||||||
"version": "2.2.0",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmmirror.com/ipaddr.js/-/ipaddr.js-2.2.0.tgz",
|
"resolved": "https://registry.npmmirror.com/ipaddr.js/-/ipaddr.js-2.2.0.tgz",
|
||||||
|
@ -11137,19 +10865,6 @@
|
||||||
"mkdirp": "bin/cmd.js"
|
"mkdirp": "bin/cmd.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/motion-dom": {
|
|
||||||
"version": "12.23.12",
|
|
||||||
"resolved": "https://registry.npmmirror.com/motion-dom/-/motion-dom-12.23.12.tgz",
|
|
||||||
"integrity": "sha512-RcR4fvMCTESQBD/uKQe49D5RUeDOokkGRmz4ceaJKDBgHYtZtntC/s2vLvY38gqGaytinij/yi3hMcWVcEF5Kw==",
|
|
||||||
"dependencies": {
|
|
||||||
"motion-utils": "^12.23.6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/motion-utils": {
|
|
||||||
"version": "12.23.6",
|
|
||||||
"resolved": "https://registry.npmmirror.com/motion-utils/-/motion-utils-12.23.6.tgz",
|
|
||||||
"integrity": "sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ=="
|
|
||||||
},
|
|
||||||
"node_modules/ms": {
|
"node_modules/ms": {
|
||||||
"version": "2.1.3",
|
"version": "2.1.3",
|
||||||
"resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz",
|
"resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz",
|
||||||
|
@ -13288,20 +13003,6 @@
|
||||||
"node": ">=14"
|
"node": ">=14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-confetti": {
|
|
||||||
"version": "6.4.0",
|
|
||||||
"resolved": "https://registry.npmmirror.com/react-confetti/-/react-confetti-6.4.0.tgz",
|
|
||||||
"integrity": "sha512-5MdGUcqxrTU26I2EU7ltkWPwxvucQTuqMm8dUz72z2YMqTD6s9vMcDUysk7n9jnC+lXuCPeJJ7Knf98VEYE9Rg==",
|
|
||||||
"dependencies": {
|
|
||||||
"tween-functions": "^1.2.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=16"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"react": "^16.3.0 || ^17.0.1 || ^18.0.0 || ^19.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/react-dev-utils": {
|
"node_modules/react-dev-utils": {
|
||||||
"version": "12.0.1",
|
"version": "12.0.1",
|
||||||
"resolved": "https://registry.npmmirror.com/react-dev-utils/-/react-dev-utils-12.0.1.tgz",
|
"resolved": "https://registry.npmmirror.com/react-dev-utils/-/react-dev-utils-12.0.1.tgz",
|
||||||
|
@ -13422,28 +13123,6 @@
|
||||||
"resolved": "https://registry.npmmirror.com/react-is/-/react-is-17.0.2.tgz",
|
"resolved": "https://registry.npmmirror.com/react-is/-/react-is-17.0.2.tgz",
|
||||||
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="
|
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="
|
||||||
},
|
},
|
||||||
"node_modules/react-redux": {
|
|
||||||
"version": "9.2.0",
|
|
||||||
"resolved": "https://registry.npmmirror.com/react-redux/-/react-redux-9.2.0.tgz",
|
|
||||||
"integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==",
|
|
||||||
"dependencies": {
|
|
||||||
"@types/use-sync-external-store": "^0.0.6",
|
|
||||||
"use-sync-external-store": "^1.4.0"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@types/react": "^18.2.25 || ^19",
|
|
||||||
"react": "^18.0 || ^19",
|
|
||||||
"redux": "^5.0.0"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"@types/react": {
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"redux": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/react-refresh": {
|
"node_modules/react-refresh": {
|
||||||
"version": "0.11.0",
|
"version": "0.11.0",
|
||||||
"resolved": "https://registry.npmmirror.com/react-refresh/-/react-refresh-0.11.0.tgz",
|
"resolved": "https://registry.npmmirror.com/react-refresh/-/react-refresh-0.11.0.tgz",
|
||||||
|
@ -13556,46 +13235,6 @@
|
||||||
"node": ">=8.10.0"
|
"node": ">=8.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/recharts": {
|
|
||||||
"version": "3.1.0",
|
|
||||||
"resolved": "https://registry.npmmirror.com/recharts/-/recharts-3.1.0.tgz",
|
|
||||||
"integrity": "sha512-NqAqQcGBmLrfDs2mHX/bz8jJCQtG2FeXfE0GqpZmIuXIjkpIwj8sd9ad0WyvKiBKPd8ZgNG0hL85c8sFDwascw==",
|
|
||||||
"dependencies": {
|
|
||||||
"@reduxjs/toolkit": "1.x.x || 2.x.x",
|
|
||||||
"clsx": "^2.1.1",
|
|
||||||
"decimal.js-light": "^2.5.1",
|
|
||||||
"es-toolkit": "^1.39.3",
|
|
||||||
"eventemitter3": "^5.0.1",
|
|
||||||
"immer": "^10.1.1",
|
|
||||||
"react-redux": "8.x.x || 9.x.x",
|
|
||||||
"reselect": "5.1.1",
|
|
||||||
"tiny-invariant": "^1.3.3",
|
|
||||||
"use-sync-external-store": "^1.2.2",
|
|
||||||
"victory-vendor": "^37.0.2"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
|
|
||||||
"react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
|
|
||||||
"react-is": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/recharts/node_modules/eventemitter3": {
|
|
||||||
"version": "5.0.1",
|
|
||||||
"resolved": "https://registry.npmmirror.com/eventemitter3/-/eventemitter3-5.0.1.tgz",
|
|
||||||
"integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="
|
|
||||||
},
|
|
||||||
"node_modules/recharts/node_modules/immer": {
|
|
||||||
"version": "10.1.1",
|
|
||||||
"resolved": "https://registry.npmmirror.com/immer/-/immer-10.1.1.tgz",
|
|
||||||
"integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==",
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/immer"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/recursive-readdir": {
|
"node_modules/recursive-readdir": {
|
||||||
"version": "2.2.3",
|
"version": "2.2.3",
|
||||||
"resolved": "https://registry.npmmirror.com/recursive-readdir/-/recursive-readdir-2.2.3.tgz",
|
"resolved": "https://registry.npmmirror.com/recursive-readdir/-/recursive-readdir-2.2.3.tgz",
|
||||||
|
@ -13619,19 +13258,6 @@
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/redux": {
|
|
||||||
"version": "5.0.1",
|
|
||||||
"resolved": "https://registry.npmmirror.com/redux/-/redux-5.0.1.tgz",
|
|
||||||
"integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w=="
|
|
||||||
},
|
|
||||||
"node_modules/redux-thunk": {
|
|
||||||
"version": "3.1.0",
|
|
||||||
"resolved": "https://registry.npmmirror.com/redux-thunk/-/redux-thunk-3.1.0.tgz",
|
|
||||||
"integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==",
|
|
||||||
"peerDependencies": {
|
|
||||||
"redux": "^5.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/reflect.getprototypeof": {
|
"node_modules/reflect.getprototypeof": {
|
||||||
"version": "1.0.10",
|
"version": "1.0.10",
|
||||||
"resolved": "https://registry.npmmirror.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz",
|
"resolved": "https://registry.npmmirror.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz",
|
||||||
|
@ -13782,11 +13408,6 @@
|
||||||
"resolved": "https://registry.npmmirror.com/requires-port/-/requires-port-1.0.0.tgz",
|
"resolved": "https://registry.npmmirror.com/requires-port/-/requires-port-1.0.0.tgz",
|
||||||
"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ=="
|
"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ=="
|
||||||
},
|
},
|
||||||
"node_modules/reselect": {
|
|
||||||
"version": "5.1.1",
|
|
||||||
"resolved": "https://registry.npmmirror.com/reselect/-/reselect-5.1.1.tgz",
|
|
||||||
"integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w=="
|
|
||||||
},
|
|
||||||
"node_modules/resolve": {
|
"node_modules/resolve": {
|
||||||
"version": "1.22.10",
|
"version": "1.22.10",
|
||||||
"resolved": "https://registry.npmmirror.com/resolve/-/resolve-1.22.10.tgz",
|
"resolved": "https://registry.npmmirror.com/resolve/-/resolve-1.22.10.tgz",
|
||||||
|
@ -15502,11 +15123,6 @@
|
||||||
"resolved": "https://registry.npmmirror.com/thunky/-/thunky-1.1.0.tgz",
|
"resolved": "https://registry.npmmirror.com/thunky/-/thunky-1.1.0.tgz",
|
||||||
"integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA=="
|
"integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA=="
|
||||||
},
|
},
|
||||||
"node_modules/tiny-invariant": {
|
|
||||||
"version": "1.3.3",
|
|
||||||
"resolved": "https://registry.npmmirror.com/tiny-invariant/-/tiny-invariant-1.3.3.tgz",
|
|
||||||
"integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg=="
|
|
||||||
},
|
|
||||||
"node_modules/tmpl": {
|
"node_modules/tmpl": {
|
||||||
"version": "1.0.5",
|
"version": "1.0.5",
|
||||||
"resolved": "https://registry.npmmirror.com/tmpl/-/tmpl-1.0.5.tgz",
|
"resolved": "https://registry.npmmirror.com/tmpl/-/tmpl-1.0.5.tgz",
|
||||||
|
@ -15628,11 +15244,6 @@
|
||||||
"resolved": "https://registry.npmmirror.com/tslib/-/tslib-1.14.1.tgz",
|
"resolved": "https://registry.npmmirror.com/tslib/-/tslib-1.14.1.tgz",
|
||||||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
|
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
|
||||||
},
|
},
|
||||||
"node_modules/tween-functions": {
|
|
||||||
"version": "1.2.0",
|
|
||||||
"resolved": "https://registry.npmmirror.com/tween-functions/-/tween-functions-1.2.0.tgz",
|
|
||||||
"integrity": "sha512-PZBtLYcCLtEcjL14Fzb1gSxPBeL7nWvGhO5ZFPGqziCcr8uvHp0NDmdjBchp6KHL+tExcg0m3NISmKxhU394dA=="
|
|
||||||
},
|
|
||||||
"node_modules/type-check": {
|
"node_modules/type-check": {
|
||||||
"version": "0.4.0",
|
"version": "0.4.0",
|
||||||
"resolved": "https://registry.npmmirror.com/type-check/-/type-check-0.4.0.tgz",
|
"resolved": "https://registry.npmmirror.com/type-check/-/type-check-0.4.0.tgz",
|
||||||
|
@ -15915,14 +15526,6 @@
|
||||||
"requires-port": "^1.0.0"
|
"requires-port": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/use-sync-external-store": {
|
|
||||||
"version": "1.5.0",
|
|
||||||
"resolved": "https://registry.npmmirror.com/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz",
|
|
||||||
"integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==",
|
|
||||||
"peerDependencies": {
|
|
||||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/util-deprecate": {
|
"node_modules/util-deprecate": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
"resolved": "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
|
@ -15989,27 +15592,6 @@
|
||||||
"node": ">= 0.8"
|
"node": ">= 0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/victory-vendor": {
|
|
||||||
"version": "37.3.6",
|
|
||||||
"resolved": "https://registry.npmmirror.com/victory-vendor/-/victory-vendor-37.3.6.tgz",
|
|
||||||
"integrity": "sha512-SbPDPdDBYp+5MJHhBCAyI7wKM3d5ivekigc2Dk2s7pgbZ9wIgIBYGVw4zGHBml/qTFbexrofXW6Gu4noGxrOwQ==",
|
|
||||||
"dependencies": {
|
|
||||||
"@types/d3-array": "^3.0.3",
|
|
||||||
"@types/d3-ease": "^3.0.0",
|
|
||||||
"@types/d3-interpolate": "^3.0.1",
|
|
||||||
"@types/d3-scale": "^4.0.2",
|
|
||||||
"@types/d3-shape": "^3.1.0",
|
|
||||||
"@types/d3-time": "^3.0.0",
|
|
||||||
"@types/d3-timer": "^3.0.0",
|
|
||||||
"d3-array": "^3.1.6",
|
|
||||||
"d3-ease": "^3.0.1",
|
|
||||||
"d3-interpolate": "^3.0.1",
|
|
||||||
"d3-scale": "^4.0.2",
|
|
||||||
"d3-shape": "^3.1.0",
|
|
||||||
"d3-time": "^3.0.0",
|
|
||||||
"d3-timer": "^3.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/w3c-hr-time": {
|
"node_modules/w3c-hr-time": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmmirror.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz",
|
"resolved": "https://registry.npmmirror.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz",
|
||||||
|
|
|
@ -11,12 +11,9 @@
|
||||||
"@types/node": "^24.2.0",
|
"@types/node": "^24.2.0",
|
||||||
"@types/react": "^19.1.9",
|
"@types/react": "^19.1.9",
|
||||||
"@types/react-dom": "^19.1.7",
|
"@types/react-dom": "^19.1.7",
|
||||||
"framer-motion": "^12.23.12",
|
|
||||||
"react": "^19.1.1",
|
"react": "^19.1.1",
|
||||||
"react-confetti": "^6.4.0",
|
|
||||||
"react-dom": "^19.1.1",
|
"react-dom": "^19.1.1",
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
"recharts": "^3.1.0",
|
|
||||||
"typescript": "^5.9.2",
|
"typescript": "^5.9.2",
|
||||||
"web-vitals": "^2.1.4"
|
"web-vitals": "^2.1.4"
|
||||||
},
|
},
|
||||||
|
|
14
src/App.tsx
14
src/App.tsx
|
@ -7,9 +7,8 @@ import VueStyleExamples from './examples/VueStyleExamples';
|
||||||
import AdvancedConcepts from './examples/AdvancedConcepts';
|
import AdvancedConcepts from './examples/AdvancedConcepts';
|
||||||
import PerformanceDemo from './examples/PerformanceDemo';
|
import PerformanceDemo from './examples/PerformanceDemo';
|
||||||
import InteractiveGames from './examples/InteractiveGames';
|
import InteractiveGames from './examples/InteractiveGames';
|
||||||
import CoolLibrariesDemo from './examples/CoolLibrariesDemo';
|
|
||||||
|
|
||||||
type ViewType = 'jsx-tsx' | 'react-vue' | 'advanced' | 'performance' | 'games' | 'libraries';
|
type ViewType = 'jsx-tsx' | 'react-vue' | 'advanced' | 'performance' | 'games';
|
||||||
|
|
||||||
const App: React.FC = () => {
|
const App: React.FC = () => {
|
||||||
const [currentView, setCurrentView] = useState<ViewType>('jsx-tsx');
|
const [currentView, setCurrentView] = useState<ViewType>('jsx-tsx');
|
||||||
|
@ -19,8 +18,7 @@ const App: React.FC = () => {
|
||||||
{ key: 'react-vue', label: 'React vs Vue', emoji: '⚔️' },
|
{ key: 'react-vue', label: 'React vs Vue', emoji: '⚔️' },
|
||||||
{ key: 'advanced', label: '高级概念', emoji: '🚀' },
|
{ key: 'advanced', label: '高级概念', emoji: '🚀' },
|
||||||
{ key: 'performance', label: '性能优化', emoji: '⚡' },
|
{ key: 'performance', label: '性能优化', emoji: '⚡' },
|
||||||
{ key: 'games', label: '交互游戏', emoji: '🎮' },
|
{ key: 'games', label: '交互游戏', emoji: '🎮' }
|
||||||
{ key: 'libraries', label: '炫酷组件库', emoji: '✨' }
|
|
||||||
];
|
];
|
||||||
|
|
||||||
const renderContent = () => {
|
const renderContent = () => {
|
||||||
|
@ -98,9 +96,6 @@ const App: React.FC = () => {
|
||||||
case 'games':
|
case 'games':
|
||||||
return <InteractiveGames />;
|
return <InteractiveGames />;
|
||||||
|
|
||||||
case 'libraries':
|
|
||||||
return <CoolLibrariesDemo />;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -111,7 +106,7 @@ const App: React.FC = () => {
|
||||||
<header className="App-header" style={{ padding: '20px 20px 10px 20px' }}>
|
<header className="App-header" style={{ padding: '20px 20px 10px 20px' }}>
|
||||||
<h1 style={{ margin: '0 0 10px 0' }}>React 全面学习演示</h1>
|
<h1 style={{ margin: '0 0 10px 0' }}>React 全面学习演示</h1>
|
||||||
<p style={{ margin: '0 0 20px 0', color: '#666' }}>
|
<p style={{ margin: '0 0 20px 0', color: '#666' }}>
|
||||||
深入理解JSX、TSX、设计思想、高级概念、性能优化和炫酷组件库
|
深入理解JSX、TSX、设计思想、高级概念、性能优化和实战应用
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
{/* 导航按钮 */}
|
{/* 导航按钮 */}
|
||||||
|
@ -171,7 +166,6 @@ const App: React.FC = () => {
|
||||||
{currentView === 'advanced' && '掌握Context、自定义Hooks、HOC、Render Props等高级模式'}
|
{currentView === 'advanced' && '掌握Context、自定义Hooks、HOC、Render Props等高级模式'}
|
||||||
{currentView === 'performance' && '学习React性能优化技巧:memo、虚拟滚动、懒加载等'}
|
{currentView === 'performance' && '学习React性能优化技巧:memo、虚拟滚动、懒加载等'}
|
||||||
{currentView === 'games' && '通过交互游戏实践React状态管理和事件处理'}
|
{currentView === 'games' && '通过交互游戏实践React状态管理和事件处理'}
|
||||||
{currentView === 'libraries' && '体验最受欢迎的React组件库:动画、图表、特效等'}
|
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
@ -190,7 +184,7 @@ const App: React.FC = () => {
|
||||||
}}>
|
}}>
|
||||||
<div style={{ marginBottom: '10px' }}>
|
<div style={{ marginBottom: '10px' }}>
|
||||||
<span style={{ marginRight: '20px' }}>🛠️ 技术栈: React 19 + TypeScript</span>
|
<span style={{ marginRight: '20px' }}>🛠️ 技术栈: React 19 + TypeScript</span>
|
||||||
<span style={{ marginRight: '20px' }}>📚 包含: 基础语法 + 设计模式 + 性能优化 + 组件库</span>
|
<span style={{ marginRight: '20px' }}>📚 包含: 基础语法 + 设计模式 + 性能优化</span>
|
||||||
<span>🎯 目标: 全面掌握React开发</span>
|
<span>🎯 目标: 全面掌握React开发</span>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
|
|
@ -1,634 +0,0 @@
|
||||||
import React, { useState, useEffect } from 'react';
|
|
||||||
import { motion, AnimatePresence } from 'framer-motion';
|
|
||||||
import Confetti from 'react-confetti';
|
|
||||||
import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer, BarChart, Bar, PieChart, Pie, Cell } from 'recharts';
|
|
||||||
|
|
||||||
// ========== 炫酷组件库演示 ==========
|
|
||||||
|
|
||||||
// 1. Framer Motion 动画演示
|
|
||||||
const FramerMotionDemo: React.FC = () => {
|
|
||||||
const [isVisible, setIsVisible] = useState(true);
|
|
||||||
const [selectedCard, setSelectedCard] = useState<number | null>(null);
|
|
||||||
|
|
||||||
const cards = [
|
|
||||||
{ id: 1, title: '卡片 1', color: '#FF6B6B', icon: '🚀' },
|
|
||||||
{ id: 2, title: '卡片 2', color: '#4ECDC4', icon: '🎨' },
|
|
||||||
{ id: 3, title: '卡片 3', color: '#45B7D1', icon: '⚡' },
|
|
||||||
{ id: 4, title: '卡片 4', color: '#96CEB4', icon: '🌟' }
|
|
||||||
];
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div style={{
|
|
||||||
padding: '20px',
|
|
||||||
border: '2px solid #6c5ce7',
|
|
||||||
borderRadius: '12px',
|
|
||||||
margin: '15px',
|
|
||||||
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
|
|
||||||
color: 'white'
|
|
||||||
}}>
|
|
||||||
<h3>🎬 Framer Motion 动画库</h3>
|
|
||||||
|
|
||||||
<div style={{ marginBottom: '20px' }}>
|
|
||||||
<motion.button
|
|
||||||
whileHover={{ scale: 1.05 }}
|
|
||||||
whileTap={{ scale: 0.95 }}
|
|
||||||
onClick={() => setIsVisible(!isVisible)}
|
|
||||||
style={{
|
|
||||||
padding: '12px 24px',
|
|
||||||
backgroundColor: '#ff7675',
|
|
||||||
color: 'white',
|
|
||||||
border: 'none',
|
|
||||||
borderRadius: '25px',
|
|
||||||
cursor: 'pointer',
|
|
||||||
fontSize: '16px',
|
|
||||||
marginRight: '10px'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{isVisible ? '隐藏动画元素' : '显示动画元素'}
|
|
||||||
</motion.button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<AnimatePresence>
|
|
||||||
{isVisible && (
|
|
||||||
<motion.div
|
|
||||||
initial={{ opacity: 0, y: 50 }}
|
|
||||||
animate={{ opacity: 1, y: 0 }}
|
|
||||||
exit={{ opacity: 0, y: -50 }}
|
|
||||||
transition={{ duration: 0.5 }}
|
|
||||||
style={{
|
|
||||||
padding: '20px',
|
|
||||||
backgroundColor: 'rgba(255, 255, 255, 0.1)',
|
|
||||||
borderRadius: '10px',
|
|
||||||
marginBottom: '20px'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<h4>✨ 入场/退场动画</h4>
|
|
||||||
<p>这个元素有平滑的进入和退出动画效果!</p>
|
|
||||||
</motion.div>
|
|
||||||
)}
|
|
||||||
</AnimatePresence>
|
|
||||||
|
|
||||||
<div style={{
|
|
||||||
display: 'grid',
|
|
||||||
gridTemplateColumns: 'repeat(auto-fit, minmax(150px, 1fr))',
|
|
||||||
gap: '15px',
|
|
||||||
marginTop: '20px'
|
|
||||||
}}>
|
|
||||||
{cards.map((card) => (
|
|
||||||
<motion.div
|
|
||||||
key={card.id}
|
|
||||||
layoutId={`card-${card.id}`}
|
|
||||||
onClick={() => setSelectedCard(selectedCard === card.id ? null : card.id)}
|
|
||||||
whileHover={{
|
|
||||||
scale: 1.05,
|
|
||||||
rotate: selectedCard === card.id ? 0 : 5,
|
|
||||||
transition: { duration: 0.2 }
|
|
||||||
}}
|
|
||||||
whileTap={{ scale: 0.95 }}
|
|
||||||
animate={{
|
|
||||||
backgroundColor: selectedCard === card.id ? '#2d3436' : card.color,
|
|
||||||
scale: selectedCard === card.id ? 1.1 : 1
|
|
||||||
}}
|
|
||||||
style={{
|
|
||||||
padding: '20px',
|
|
||||||
borderRadius: '15px',
|
|
||||||
cursor: 'pointer',
|
|
||||||
textAlign: 'center',
|
|
||||||
backgroundColor: card.color
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<motion.div
|
|
||||||
animate={{
|
|
||||||
rotate: selectedCard === card.id ? 360 : 0,
|
|
||||||
scale: selectedCard === card.id ? 1.2 : 1
|
|
||||||
}}
|
|
||||||
transition={{ duration: 0.5 }}
|
|
||||||
style={{ fontSize: '32px', marginBottom: '10px' }}
|
|
||||||
>
|
|
||||||
{card.icon}
|
|
||||||
</motion.div>
|
|
||||||
<h4 style={{ margin: 0, color: 'white' }}>{card.title}</h4>
|
|
||||||
{selectedCard === card.id && (
|
|
||||||
<motion.p
|
|
||||||
initial={{ opacity: 0 }}
|
|
||||||
animate={{ opacity: 1 }}
|
|
||||||
style={{ marginTop: '10px', fontSize: '14px' }}
|
|
||||||
>
|
|
||||||
选中状态!
|
|
||||||
</motion.p>
|
|
||||||
)}
|
|
||||||
</motion.div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<motion.div
|
|
||||||
animate={{ rotate: 360 }}
|
|
||||||
transition={{ duration: 2, repeat: Infinity, ease: "linear" }}
|
|
||||||
style={{
|
|
||||||
width: '60px',
|
|
||||||
height: '60px',
|
|
||||||
backgroundColor: '#fdcb6e',
|
|
||||||
borderRadius: '50%',
|
|
||||||
margin: '20px auto',
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
fontSize: '24px'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
🌀
|
|
||||||
</motion.div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 2. React Confetti 彩纸效果演示
|
|
||||||
const ConfettiDemo: React.FC = () => {
|
|
||||||
const [showConfetti, setShowConfetti] = useState(false);
|
|
||||||
const [confettiConfig, setConfettiConfig] = useState({
|
|
||||||
numberOfPieces: 200,
|
|
||||||
gravity: 0.1
|
|
||||||
});
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (showConfetti) {
|
|
||||||
const timer = setTimeout(() => setShowConfetti(false), 5000);
|
|
||||||
return () => clearTimeout(timer);
|
|
||||||
}
|
|
||||||
}, [showConfetti]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div style={{
|
|
||||||
padding: '20px',
|
|
||||||
border: '2px solid #00b894',
|
|
||||||
borderRadius: '12px',
|
|
||||||
margin: '15px',
|
|
||||||
background: 'linear-gradient(135deg, #00b894 0%, #00cec9 100%)',
|
|
||||||
color: 'white',
|
|
||||||
position: 'relative'
|
|
||||||
}}>
|
|
||||||
{showConfetti && (
|
|
||||||
<Confetti
|
|
||||||
width={window.innerWidth}
|
|
||||||
height={window.innerHeight}
|
|
||||||
numberOfPieces={confettiConfig.numberOfPieces}
|
|
||||||
gravity={confettiConfig.gravity}
|
|
||||||
style={{ position: 'fixed', top: 0, left: 0, zIndex: 1000 }}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<h3>🎉 React Confetti 彩纸效果</h3>
|
|
||||||
<p>点击按钮释放彩纸庆祝效果!</p>
|
|
||||||
|
|
||||||
<div style={{ marginBottom: '20px' }}>
|
|
||||||
<label style={{ display: 'block', marginBottom: '10px' }}>
|
|
||||||
彩纸数量: {confettiConfig.numberOfPieces}
|
|
||||||
<input
|
|
||||||
type="range"
|
|
||||||
min="50"
|
|
||||||
max="500"
|
|
||||||
value={confettiConfig.numberOfPieces}
|
|
||||||
onChange={(e) => setConfettiConfig(prev => ({
|
|
||||||
...prev,
|
|
||||||
numberOfPieces: Number(e.target.value)
|
|
||||||
}))}
|
|
||||||
style={{ marginLeft: '10px', width: '200px' }}
|
|
||||||
/>
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<label style={{ display: 'block', marginBottom: '15px' }}>
|
|
||||||
重力: {confettiConfig.gravity}
|
|
||||||
<input
|
|
||||||
type="range"
|
|
||||||
min="0.05"
|
|
||||||
max="0.3"
|
|
||||||
step="0.01"
|
|
||||||
value={confettiConfig.gravity}
|
|
||||||
onChange={(e) => setConfettiConfig(prev => ({
|
|
||||||
...prev,
|
|
||||||
gravity: Number(e.target.value)
|
|
||||||
}))}
|
|
||||||
style={{ marginLeft: '10px', width: '200px' }}
|
|
||||||
/>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<motion.button
|
|
||||||
whileHover={{ scale: 1.05 }}
|
|
||||||
whileTap={{ scale: 0.95 }}
|
|
||||||
onClick={() => setShowConfetti(true)}
|
|
||||||
disabled={showConfetti}
|
|
||||||
style={{
|
|
||||||
padding: '15px 30px',
|
|
||||||
backgroundColor: showConfetti ? '#95a5a6' : '#e74c3c',
|
|
||||||
color: 'white',
|
|
||||||
border: 'none',
|
|
||||||
borderRadius: '25px',
|
|
||||||
cursor: showConfetti ? 'not-allowed' : 'pointer',
|
|
||||||
fontSize: '18px',
|
|
||||||
fontWeight: 'bold'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{showConfetti ? '彩纸飞舞中...' : '🎊 释放彩纸!'}
|
|
||||||
</motion.button>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 3. Recharts 图表演示
|
|
||||||
const ChartsDemo: React.FC = () => {
|
|
||||||
const [chartType, setChartType] = useState<'line' | 'bar' | 'pie'>('line');
|
|
||||||
|
|
||||||
const lineData = [
|
|
||||||
{ name: '1月', 用户: 400, 销售: 240, 访问: 300 },
|
|
||||||
{ name: '2月', 用户: 300, 销售: 139, 访问: 200 },
|
|
||||||
{ name: '3月', 用户: 200, 销售: 980, 访问: 400 },
|
|
||||||
{ name: '4月', 用户: 278, 销售: 390, 访问: 350 },
|
|
||||||
{ name: '5月', 用户: 189, 销售: 480, 访问: 200 },
|
|
||||||
{ name: '6月', 用户: 239, 销售: 380, 访问: 500 },
|
|
||||||
];
|
|
||||||
|
|
||||||
const pieData = [
|
|
||||||
{ name: 'React', value: 35, color: '#61dafb' },
|
|
||||||
{ name: 'Vue', value: 25, color: '#4fc08d' },
|
|
||||||
{ name: 'Angular', value: 20, color: '#dd1b16' },
|
|
||||||
{ name: 'Svelte', value: 10, color: '#ff3e00' },
|
|
||||||
{ name: '其他', value: 10, color: '#9ca3af' }
|
|
||||||
];
|
|
||||||
|
|
||||||
const renderChart = () => {
|
|
||||||
switch (chartType) {
|
|
||||||
case 'line':
|
|
||||||
return (
|
|
||||||
<ResponsiveContainer width="100%" height={300}>
|
|
||||||
<LineChart data={lineData}>
|
|
||||||
<CartesianGrid strokeDasharray="3 3" />
|
|
||||||
<XAxis dataKey="name" />
|
|
||||||
<YAxis />
|
|
||||||
<Tooltip />
|
|
||||||
<Legend />
|
|
||||||
<Line type="monotone" dataKey="用户" stroke="#8884d8" strokeWidth={2} />
|
|
||||||
<Line type="monotone" dataKey="销售" stroke="#82ca9d" strokeWidth={2} />
|
|
||||||
<Line type="monotone" dataKey="访问" stroke="#ffc658" strokeWidth={2} />
|
|
||||||
</LineChart>
|
|
||||||
</ResponsiveContainer>
|
|
||||||
);
|
|
||||||
case 'bar':
|
|
||||||
return (
|
|
||||||
<ResponsiveContainer width="100%" height={300}>
|
|
||||||
<BarChart data={lineData}>
|
|
||||||
<CartesianGrid strokeDasharray="3 3" />
|
|
||||||
<XAxis dataKey="name" />
|
|
||||||
<YAxis />
|
|
||||||
<Tooltip />
|
|
||||||
<Legend />
|
|
||||||
<Bar dataKey="用户" fill="#8884d8" />
|
|
||||||
<Bar dataKey="销售" fill="#82ca9d" />
|
|
||||||
<Bar dataKey="访问" fill="#ffc658" />
|
|
||||||
</BarChart>
|
|
||||||
</ResponsiveContainer>
|
|
||||||
);
|
|
||||||
case 'pie':
|
|
||||||
return (
|
|
||||||
<ResponsiveContainer width="100%" height={300}>
|
|
||||||
<PieChart>
|
|
||||||
<Pie
|
|
||||||
data={pieData}
|
|
||||||
cx="50%"
|
|
||||||
cy="50%"
|
|
||||||
labelLine={false}
|
|
||||||
label={({ name, percent }) => `${name} ${((percent || 0) * 100).toFixed(0)}%`}
|
|
||||||
outerRadius={80}
|
|
||||||
fill="#8884d8"
|
|
||||||
dataKey="value"
|
|
||||||
>
|
|
||||||
{pieData.map((entry, index) => (
|
|
||||||
<Cell key={`cell-${index}`} fill={entry.color} />
|
|
||||||
))}
|
|
||||||
</Pie>
|
|
||||||
<Tooltip />
|
|
||||||
</PieChart>
|
|
||||||
</ResponsiveContainer>
|
|
||||||
);
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div style={{
|
|
||||||
padding: '20px',
|
|
||||||
border: '2px solid #e17055',
|
|
||||||
borderRadius: '12px',
|
|
||||||
margin: '15px',
|
|
||||||
backgroundColor: '#f8f9fa'
|
|
||||||
}}>
|
|
||||||
<h3 style={{ color: '#2d3436' }}>📊 Recharts 图表库</h3>
|
|
||||||
|
|
||||||
<div style={{ marginBottom: '20px' }}>
|
|
||||||
{(['line', 'bar', 'pie'] as const).map((type) => (
|
|
||||||
<motion.button
|
|
||||||
key={type}
|
|
||||||
whileHover={{ scale: 1.05 }}
|
|
||||||
whileTap={{ scale: 0.95 }}
|
|
||||||
onClick={() => setChartType(type)}
|
|
||||||
style={{
|
|
||||||
padding: '8px 16px',
|
|
||||||
marginRight: '10px',
|
|
||||||
backgroundColor: chartType === type ? '#e17055' : '#ddd',
|
|
||||||
color: chartType === type ? 'white' : '#333',
|
|
||||||
border: 'none',
|
|
||||||
borderRadius: '20px',
|
|
||||||
cursor: 'pointer'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{type === 'line' ? '📈 折线图' : type === 'bar' ? '📊 柱状图' : '🥧 饼图'}
|
|
||||||
</motion.button>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<motion.div
|
|
||||||
key={chartType}
|
|
||||||
initial={{ opacity: 0, scale: 0.9 }}
|
|
||||||
animate={{ opacity: 1, scale: 1 }}
|
|
||||||
transition={{ duration: 0.3 }}
|
|
||||||
>
|
|
||||||
{renderChart()}
|
|
||||||
</motion.div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 4. 炫酷加载动画演示
|
|
||||||
const LoadingAnimationsDemo: React.FC = () => {
|
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
|
||||||
|
|
||||||
const startLoading = () => {
|
|
||||||
setIsLoading(true);
|
|
||||||
setTimeout(() => setIsLoading(false), 3000);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div style={{
|
|
||||||
padding: '20px',
|
|
||||||
border: '2px solid #a29bfe',
|
|
||||||
borderRadius: '12px',
|
|
||||||
margin: '15px',
|
|
||||||
background: 'linear-gradient(135deg, #a29bfe 0%, #6c5ce7 100%)',
|
|
||||||
color: 'white'
|
|
||||||
}}>
|
|
||||||
<h3>⏳ 炫酷加载动画</h3>
|
|
||||||
|
|
||||||
<motion.button
|
|
||||||
whileHover={{ scale: 1.05 }}
|
|
||||||
whileTap={{ scale: 0.95 }}
|
|
||||||
onClick={startLoading}
|
|
||||||
disabled={isLoading}
|
|
||||||
style={{
|
|
||||||
padding: '12px 24px',
|
|
||||||
backgroundColor: isLoading ? '#95a5a6' : '#fd79a8',
|
|
||||||
color: 'white',
|
|
||||||
border: 'none',
|
|
||||||
borderRadius: '25px',
|
|
||||||
cursor: isLoading ? 'not-allowed' : 'pointer',
|
|
||||||
fontSize: '16px',
|
|
||||||
marginBottom: '20px'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{isLoading ? '加载中...' : '开始加载'}
|
|
||||||
</motion.button>
|
|
||||||
|
|
||||||
<AnimatePresence>
|
|
||||||
{isLoading && (
|
|
||||||
<motion.div
|
|
||||||
initial={{ opacity: 0 }}
|
|
||||||
animate={{ opacity: 1 }}
|
|
||||||
exit={{ opacity: 0 }}
|
|
||||||
style={{ textAlign: 'center' }}
|
|
||||||
>
|
|
||||||
{/* 旋转圆环 */}
|
|
||||||
<motion.div
|
|
||||||
animate={{ rotate: 360 }}
|
|
||||||
transition={{ duration: 1, repeat: Infinity, ease: "linear" }}
|
|
||||||
style={{
|
|
||||||
width: '60px',
|
|
||||||
height: '60px',
|
|
||||||
border: '4px solid rgba(255,255,255,0.3)',
|
|
||||||
borderTop: '4px solid white',
|
|
||||||
borderRadius: '50%',
|
|
||||||
margin: '20px auto'
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* 脉冲圆点 */}
|
|
||||||
<div style={{ display: 'flex', justifyContent: 'center', gap: '10px', marginBottom: '20px' }}>
|
|
||||||
{[0, 1, 2].map((i) => (
|
|
||||||
<motion.div
|
|
||||||
key={i}
|
|
||||||
animate={{
|
|
||||||
scale: [1, 1.5, 1],
|
|
||||||
opacity: [0.5, 1, 0.5]
|
|
||||||
}}
|
|
||||||
transition={{
|
|
||||||
duration: 1,
|
|
||||||
repeat: Infinity,
|
|
||||||
delay: i * 0.2
|
|
||||||
}}
|
|
||||||
style={{
|
|
||||||
width: '15px',
|
|
||||||
height: '15px',
|
|
||||||
backgroundColor: 'white',
|
|
||||||
borderRadius: '50%'
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* 波浪进度条 */}
|
|
||||||
<div style={{
|
|
||||||
width: '200px',
|
|
||||||
height: '6px',
|
|
||||||
backgroundColor: 'rgba(255,255,255,0.3)',
|
|
||||||
borderRadius: '3px',
|
|
||||||
margin: '0 auto',
|
|
||||||
overflow: 'hidden'
|
|
||||||
}}>
|
|
||||||
<motion.div
|
|
||||||
animate={{ x: [-200, 200] }}
|
|
||||||
transition={{ duration: 1.5, repeat: Infinity, ease: "easeInOut" }}
|
|
||||||
style={{
|
|
||||||
width: '100px',
|
|
||||||
height: '100%',
|
|
||||||
background: 'linear-gradient(90deg, transparent, white, transparent)',
|
|
||||||
borderRadius: '3px'
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</motion.div>
|
|
||||||
)}
|
|
||||||
</AnimatePresence>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 5. 交互式卡片网格
|
|
||||||
const InteractiveCardsDemo: React.FC = () => {
|
|
||||||
const [hoveredCard, setHoveredCard] = useState<number | null>(null);
|
|
||||||
|
|
||||||
const features = [
|
|
||||||
{ id: 1, title: '高性能', icon: '⚡', description: '极致的性能优化' },
|
|
||||||
{ id: 2, title: '易使用', icon: '🎯', description: '简单直观的API' },
|
|
||||||
{ id: 3, title: '可定制', icon: '🎨', description: '灵活的主题配置' },
|
|
||||||
{ id: 4, title: '响应式', icon: '📱', description: '完美适配各种设备' },
|
|
||||||
{ id: 5, title: '现代化', icon: '🚀', description: '最新技术栈支持' },
|
|
||||||
{ id: 6, title: '文档完善', icon: '📚', description: '详细的使用指南' }
|
|
||||||
];
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div style={{
|
|
||||||
padding: '20px',
|
|
||||||
border: '2px solid #00cec9',
|
|
||||||
borderRadius: '12px',
|
|
||||||
margin: '15px',
|
|
||||||
backgroundColor: '#f8f9fa'
|
|
||||||
}}>
|
|
||||||
<h3 style={{ color: '#2d3436', textAlign: 'center' }}>🎴 交互式卡片网格</h3>
|
|
||||||
|
|
||||||
<motion.div
|
|
||||||
layout
|
|
||||||
style={{
|
|
||||||
display: 'grid',
|
|
||||||
gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))',
|
|
||||||
gap: '20px',
|
|
||||||
marginTop: '20px'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{features.map((feature) => (
|
|
||||||
<motion.div
|
|
||||||
key={feature.id}
|
|
||||||
layout
|
|
||||||
onHoverStart={() => setHoveredCard(feature.id)}
|
|
||||||
onHoverEnd={() => setHoveredCard(null)}
|
|
||||||
whileHover={{
|
|
||||||
scale: 1.05,
|
|
||||||
rotateY: 5,
|
|
||||||
z: 50
|
|
||||||
}}
|
|
||||||
whileTap={{ scale: 0.95 }}
|
|
||||||
style={{
|
|
||||||
padding: '20px',
|
|
||||||
backgroundColor: hoveredCard === feature.id ? '#00cec9' : 'white',
|
|
||||||
color: hoveredCard === feature.id ? 'white' : '#2d3436',
|
|
||||||
borderRadius: '15px',
|
|
||||||
boxShadow: hoveredCard === feature.id
|
|
||||||
? '0 10px 30px rgba(0, 206, 201, 0.3)'
|
|
||||||
: '0 5px 15px rgba(0,0,0,0.1)',
|
|
||||||
cursor: 'pointer',
|
|
||||||
textAlign: 'center',
|
|
||||||
transition: 'all 0.3s ease'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<motion.div
|
|
||||||
animate={{
|
|
||||||
scale: hoveredCard === feature.id ? 1.2 : 1,
|
|
||||||
rotate: hoveredCard === feature.id ? 360 : 0
|
|
||||||
}}
|
|
||||||
transition={{ duration: 0.3 }}
|
|
||||||
style={{ fontSize: '32px', marginBottom: '10px' }}
|
|
||||||
>
|
|
||||||
{feature.icon}
|
|
||||||
</motion.div>
|
|
||||||
<h4 style={{ margin: '10px 0' }}>{feature.title}</h4>
|
|
||||||
<AnimatePresence>
|
|
||||||
{hoveredCard === feature.id && (
|
|
||||||
<motion.p
|
|
||||||
initial={{ opacity: 0, height: 0 }}
|
|
||||||
animate={{ opacity: 1, height: 'auto' }}
|
|
||||||
exit={{ opacity: 0, height: 0 }}
|
|
||||||
style={{ margin: 0, fontSize: '14px' }}
|
|
||||||
>
|
|
||||||
{feature.description}
|
|
||||||
</motion.p>
|
|
||||||
)}
|
|
||||||
</AnimatePresence>
|
|
||||||
</motion.div>
|
|
||||||
))}
|
|
||||||
</motion.div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 主组件
|
|
||||||
const CoolLibrariesDemo: React.FC = () => {
|
|
||||||
return (
|
|
||||||
<div style={{ padding: '20px' }}>
|
|
||||||
<motion.div
|
|
||||||
initial={{ opacity: 0, y: -20 }}
|
|
||||||
animate={{ opacity: 1, y: 0 }}
|
|
||||||
transition={{ duration: 0.5 }}
|
|
||||||
>
|
|
||||||
<h2 style={{ textAlign: 'center', color: '#2d3436', marginBottom: '10px' }}>
|
|
||||||
✨ 炫酷React组件库演示
|
|
||||||
</h2>
|
|
||||||
<p style={{ textAlign: 'center', color: '#636e72', marginBottom: '30px' }}>
|
|
||||||
探索最受欢迎的React UI库和动画库,提升用户体验
|
|
||||||
</p>
|
|
||||||
</motion.div>
|
|
||||||
|
|
||||||
<FramerMotionDemo />
|
|
||||||
<ConfettiDemo />
|
|
||||||
<ChartsDemo />
|
|
||||||
<LoadingAnimationsDemo />
|
|
||||||
<InteractiveCardsDemo />
|
|
||||||
|
|
||||||
<motion.div
|
|
||||||
initial={{ opacity: 0 }}
|
|
||||||
animate={{ opacity: 1 }}
|
|
||||||
transition={{ delay: 0.5 }}
|
|
||||||
style={{
|
|
||||||
marginTop: '30px',
|
|
||||||
padding: '25px',
|
|
||||||
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
|
|
||||||
borderRadius: '15px',
|
|
||||||
color: 'white',
|
|
||||||
textAlign: 'center'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<h3>🎯 组件库推荐总结</h3>
|
|
||||||
<div style={{
|
|
||||||
display: 'grid',
|
|
||||||
gridTemplateColumns: 'repeat(auto-fit, minmax(250px, 1fr))',
|
|
||||||
gap: '20px',
|
|
||||||
marginTop: '20px'
|
|
||||||
}}>
|
|
||||||
<div>
|
|
||||||
<h4>🎬 动画库</h4>
|
|
||||||
<ul style={{ textAlign: 'left', lineHeight: '1.8' }}>
|
|
||||||
<li><strong>Framer Motion</strong>: 最强大的React动画库</li>
|
|
||||||
<li><strong>React Spring</strong>: 基于物理的动画</li>
|
|
||||||
<li><strong>React Transition Group</strong>: 过渡动画</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h4>🎨 UI组件库</h4>
|
|
||||||
<ul style={{ textAlign: 'left', lineHeight: '1.8' }}>
|
|
||||||
<li><strong>Ant Design</strong>: 企业级UI设计语言</li>
|
|
||||||
<li><strong>Material-UI</strong>: Google Material Design</li>
|
|
||||||
<li><strong>Chakra UI</strong>: 简单、模块化、易用</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h4>📊 数据可视化</h4>
|
|
||||||
<ul style={{ textAlign: 'left', lineHeight: '1.8' }}>
|
|
||||||
<li><strong>Recharts</strong>: 基于D3的图表库</li>
|
|
||||||
<li><strong>Victory</strong>: 模块化图表库</li>
|
|
||||||
<li><strong>React-vis</strong>: Uber开源图表库</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</motion.div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default CoolLibrariesDemo;
|
|
Loading…
Reference in New Issue