diff --git a/hooks/useSwipeGesture.ts b/hooks/useSwipeGesture.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/lib/theme/animations.ts b/lib/theme/animations.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/lib/theme/tokens.ts b/lib/theme/tokens.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/package.json b/package.json index 4319a0a3e5..a1e666c85c 100644 --- a/package.json +++ b/package.json @@ -51,8 +51,11 @@ "@emotion/styled": "^11.14.1", "@mui/icons-material": "^5.15.0", "@mui/material": "^5.18.0", + "@react-spring/web": "^10.0.3", "@spotify/web-api-ts-sdk": "^1.2.0", "express": "^5.1.0", + "framer-motion": "^12.23.24", + "lodash": "^4.17.21", "next": "16.0.1", "next-auth": "^4.24.13", "pino": "^10.1.0", @@ -74,6 +77,7 @@ "@testing-library/user-event": "^14.6.1", "@types/express": "^5.0.5", "@types/jest": "^30.0.0", + "@types/lodash": "^4.17.21", "@types/next": "^8.0.7", "@types/node": "^24.10.1", "@types/react": "^19.2.6", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 470d45195c..e707fb159e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -23,12 +23,21 @@ importers: '@mui/material': specifier: ^5.18.0 version: 5.18.0(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.0))(@types/react@19.2.7)(react@19.2.0))(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@react-spring/web': + specifier: ^10.0.3 + version: 10.0.3(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@spotify/web-api-ts-sdk': specifier: ^1.2.0 version: 1.2.0 express: specifier: ^5.1.0 version: 5.1.0 + framer-motion: + specifier: ^12.23.24 + version: 12.23.24(@emotion/is-prop-valid@1.4.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + lodash: + specifier: ^4.17.21 + version: 4.17.21 next: specifier: 16.0.1 version: 16.0.1(@babel/core@7.28.5)(@playwright/test@1.57.0)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) @@ -87,6 +96,9 @@ importers: '@types/jest': specifier: ^30.0.0 version: 30.0.0 + '@types/lodash': + specifier: ^4.17.21 + version: 4.17.21 '@types/next': specifier: ^8.0.7 version: 8.0.7(react-dom@19.2.0(react@19.2.0))(react@19.2.0) @@ -1014,6 +1026,33 @@ packages: '@popperjs/core@2.11.8': resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==} + '@react-spring/animated@10.0.3': + resolution: {integrity: sha512-7MrxADV3vaUADn2V9iYhaIL6iOWRx9nCJjYrsk2AHD2kwPr6fg7Pt0v+deX5RnCDmCKNnD6W5fasiyM8D+wzJQ==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + + '@react-spring/core@10.0.3': + resolution: {integrity: sha512-D4DwNO68oohDf/0HG2G0Uragzb9IA1oXblxrd6MZAcBcUQG2EHUWXewjdECMPLNmQvlYVyyBRH6gPxXM5DX7DQ==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + + '@react-spring/rafz@10.0.3': + resolution: {integrity: sha512-Ri2/xqt8OnQ2iFKkxKMSF4Nqv0LSWnxXT4jXFzBDsHgeeH/cHxTLupAWUwmV9hAGgmEhBmh5aONtj3J6R/18wg==} + + '@react-spring/shared@10.0.3': + resolution: {integrity: sha512-geCal66nrkaQzUVhPkGomylo+Jpd5VPK8tPMEDevQEfNSWAQP15swHm+MCRG4wVQrQlTi9lOzKzpRoTL3CA84Q==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + + '@react-spring/types@10.0.3': + resolution: {integrity: sha512-H5Ixkd2OuSIgHtxuHLTt7aJYfhMXKXT/rK32HPD/kSrOB6q6ooeiWAXkBy7L8F3ZxdkBb9ini9zP9UwnEFzWgQ==} + + '@react-spring/web@10.0.3': + resolution: {integrity: sha512-ndU+kWY81rHsT7gTFtCJ6mrVhaJ6grFmgTnENipzmKqot4HGf5smPNK+cZZJqoGeDsj9ZsiWPW4geT/NyD484A==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + '@rtsao/scc@1.1.0': resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==} @@ -1139,6 +1178,9 @@ packages: '@types/json5@0.0.29': resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} + '@types/lodash@4.17.21': + resolution: {integrity: sha512-FOvQ0YPD5NOfPgMzJihoT+Za5pdkDJWcbpuj1DjaKZIr/gxodQjY/uWEFlTNqW2ugXHUiL8lRQgw63dzKHZdeQ==} + '@types/mime@1.3.5': resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} @@ -2403,6 +2445,20 @@ packages: resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} engines: {node: '>= 0.6'} + framer-motion@12.23.24: + resolution: {integrity: sha512-HMi5HRoRCTou+3fb3h9oTLyJGBxHfW+HnNE25tAXOvVx/IvwMHK0cx7IR4a2ZU6sh3IX1Z+4ts32PcYBOqka8w==} + 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 + fresh@0.5.2: resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} engines: {node: '>= 0.6'} @@ -3222,6 +3278,12 @@ packages: module-details-from-path@1.0.4: resolution: {integrity: sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==} + motion-dom@12.23.23: + resolution: {integrity: sha512-n5yolOs0TQQBRUFImrRfs/+6X4p3Q4n1dUEqt/H58Vx7OW6RF+foWEgmTVDhIWJIMXOuNNL0apKH2S16en9eiA==} + + motion-utils@12.23.6: + resolution: {integrity: sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ==} + mrmime@2.0.1: resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==} engines: {node: '>=10'} @@ -5532,6 +5594,38 @@ snapshots: '@popperjs/core@2.11.8': {} + '@react-spring/animated@10.0.3(react@19.2.0)': + dependencies: + '@react-spring/shared': 10.0.3(react@19.2.0) + '@react-spring/types': 10.0.3 + react: 19.2.0 + + '@react-spring/core@10.0.3(react@19.2.0)': + dependencies: + '@react-spring/animated': 10.0.3(react@19.2.0) + '@react-spring/shared': 10.0.3(react@19.2.0) + '@react-spring/types': 10.0.3 + react: 19.2.0 + + '@react-spring/rafz@10.0.3': {} + + '@react-spring/shared@10.0.3(react@19.2.0)': + dependencies: + '@react-spring/rafz': 10.0.3 + '@react-spring/types': 10.0.3 + react: 19.2.0 + + '@react-spring/types@10.0.3': {} + + '@react-spring/web@10.0.3(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': + dependencies: + '@react-spring/animated': 10.0.3(react@19.2.0) + '@react-spring/core': 10.0.3(react@19.2.0) + '@react-spring/shared': 10.0.3(react@19.2.0) + '@react-spring/types': 10.0.3 + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) + '@rtsao/scc@1.1.0': {} '@scarf/scarf@1.4.0': {} @@ -5677,6 +5771,8 @@ snapshots: '@types/json5@0.0.29': {} + '@types/lodash@4.17.21': {} + '@types/mime@1.3.5': {} '@types/minimatch@3.0.5': {} @@ -7157,6 +7253,16 @@ snapshots: forwarded@0.2.0: {} + framer-motion@12.23.24(@emotion/is-prop-valid@1.4.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0): + dependencies: + motion-dom: 12.23.23 + motion-utils: 12.23.6 + tslib: 2.8.1 + optionalDependencies: + '@emotion/is-prop-valid': 1.4.0 + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) + fresh@0.5.2: {} fresh@2.0.0: {} @@ -8169,6 +8275,12 @@ snapshots: module-details-from-path@1.0.4: {} + motion-dom@12.23.23: + dependencies: + motion-utils: 12.23.6 + + motion-utils@12.23.6: {} + mrmime@2.0.1: {} ms@2.0.0: {}