├── .gitignore ├── .prettierrc.json ├── README.md ├── index.html ├── package.json ├── pnpm-lock.yaml └── src ├── css └── index.scss ├── img └── slides │ ├── s1 │ ├── comp │ │ ├── c.jpg │ │ ├── l.jpg │ │ └── r.jpg │ └── raw │ │ ├── c.jpg │ │ ├── l.jpg │ │ └── r.jpg │ ├── s2 │ ├── comp │ │ ├── c.jpg │ │ ├── l.jpg │ │ └── r.jpg │ └── raw │ │ ├── c.jpg │ │ ├── l.jpg │ │ └── r.jpg │ └── s3 │ ├── comp │ ├── c.jpg │ ├── l.jpg │ └── r.jpg │ └── raw │ ├── c.jpg │ ├── l.jpg │ └── r.jpg └── js ├── Cursor.js ├── Cursors.js ├── Slide.js ├── Slideinfo.js ├── Slideshow.js ├── events ├── Events.js ├── Raf.js ├── Resize.js └── index.js ├── index.js └── utils ├── Mouse.js ├── Splitter.js ├── colorConfig.js ├── index.js └── preload.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "semi": true, 3 | "tabWidth": 2, 4 | "printWidth": 100 5 | } 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # collections-slider 2 | 3 | ## Based on a design demo by [Tom Anderson](https://dribbble.com/tom-anderson) on [Dribbble](https://dribbble.com/shots/14558451-Beginnings-Collections-Slider) 4 | 5 | ![Imgur](https://i.imgur.com/ohcbWju.png) 6 | 7 | **`css` : `clip-path` is used to clip the image element from its parent** 8 | 9 | ## Credits 10 | 11 | - **[GSAP](https://greensock.com/gsap/)** by Greensock 12 | - Photos from **[Unsplash](https://unsplash.com/)** 13 | 14 | --- 15 | 16 | Made with ❤️ by **[Sikriti Dakua](https://twitter.com/DevLoop01)** 17 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Collection Slider 7 | 8 | 9 | 10 |
11 |
12 | 15 | 18 | 19 |

20 | Inspired from this — 22 | Dribbble shot 28 |

29 |
30 | 31 |
32 |
33 | 36 | // 37 | 40 |
41 | 42 |
43 |
44 |
45 |
46 |
47 |
48 | 49 |
50 |
51 |
52 |
53 | 54 |
55 |
56 |
57 |
58 | 59 |
60 |
61 |
62 |
63 |
64 | 65 |
66 |
67 |
68 |
69 |
70 | 71 |
72 |
73 |
74 |
75 | 76 |
77 |
78 |
79 |
80 | 81 |
82 |
83 |
84 |
85 |
86 | 87 |
88 |
89 |
90 |
91 |
92 | 93 |
94 |
95 |
96 |
97 | 98 |
99 |
100 |
101 |
102 | 103 |
104 |
105 |
106 |
107 |
108 |
109 | 110 |
111 |
112 |

Optimism

113 |

114 | Attitude is a choice. Happiness is a choice. Optimism is a choice. Kindness is a 115 | choice. Giving is a choice. Respect is a choice. Whatever choice you make makes you. 116 | Choose wisely. 117 |

118 |
119 |
120 |

Relations

121 |

122 | If you want to forget something or someone, never hate it, or never hate him/her. 123 | Everything and everyone that you hate is engraved upon your heart; if you want to let 124 | go of something, if you want to forget, you cannot hate. 125 |

126 |
127 |
128 |

Choices

129 |

130 | Attitude is a choice. Happiness is a choice. Optimism is a choice. Kindness is a 131 | choice. Giving is a choice. Respect is a choice. Whatever choice you make makes you. 132 | Choose wisely. 133 |

134 |
135 |
136 |
137 |
138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 |
151 |

152 | Loading... 153 |

154 |
155 |
156 | 157 | 158 | 159 | 160 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "collection-slider", 3 | "version": "1.0.0", 4 | "type": "module", 5 | "scripts": { 6 | "dev": "vite dev", 7 | "build": "vite build", 8 | "preview": "vite preview", 9 | "format": "prettier --write ." 10 | }, 11 | "author": "Sikriti Dakua", 12 | "license": "ISC", 13 | "dependencies": { 14 | "gsap": "^3.5.1", 15 | "imagesloaded": "^4.1.4", 16 | "splitting": "^1.0.6", 17 | "tiny-emitter": "^2.1.0" 18 | }, 19 | "devDependencies": { 20 | "prettier": "^3.3.3", 21 | "sass": "^1.80.6", 22 | "vite": "^5.4.10" 23 | }, 24 | "packageManager": "pnpm@9.9.0" 25 | } 26 | -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: '9.0' 2 | 3 | settings: 4 | autoInstallPeers: true 5 | excludeLinksFromLockfile: false 6 | 7 | importers: 8 | 9 | .: 10 | dependencies: 11 | gsap: 12 | specifier: ^3.5.1 13 | version: 3.12.5 14 | imagesloaded: 15 | specifier: ^4.1.4 16 | version: 4.1.4 17 | splitting: 18 | specifier: ^1.0.6 19 | version: 1.1.0 20 | tiny-emitter: 21 | specifier: ^2.1.0 22 | version: 2.1.0 23 | devDependencies: 24 | prettier: 25 | specifier: ^3.3.3 26 | version: 3.3.3 27 | sass: 28 | specifier: ^1.80.6 29 | version: 1.80.6 30 | vite: 31 | specifier: ^5.4.10 32 | version: 5.4.10(sass@1.80.6) 33 | 34 | packages: 35 | 36 | '@esbuild/aix-ppc64@0.21.5': 37 | resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} 38 | engines: {node: '>=12'} 39 | cpu: [ppc64] 40 | os: [aix] 41 | 42 | '@esbuild/android-arm64@0.21.5': 43 | resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} 44 | engines: {node: '>=12'} 45 | cpu: [arm64] 46 | os: [android] 47 | 48 | '@esbuild/android-arm@0.21.5': 49 | resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} 50 | engines: {node: '>=12'} 51 | cpu: [arm] 52 | os: [android] 53 | 54 | '@esbuild/android-x64@0.21.5': 55 | resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} 56 | engines: {node: '>=12'} 57 | cpu: [x64] 58 | os: [android] 59 | 60 | '@esbuild/darwin-arm64@0.21.5': 61 | resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} 62 | engines: {node: '>=12'} 63 | cpu: [arm64] 64 | os: [darwin] 65 | 66 | '@esbuild/darwin-x64@0.21.5': 67 | resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} 68 | engines: {node: '>=12'} 69 | cpu: [x64] 70 | os: [darwin] 71 | 72 | '@esbuild/freebsd-arm64@0.21.5': 73 | resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} 74 | engines: {node: '>=12'} 75 | cpu: [arm64] 76 | os: [freebsd] 77 | 78 | '@esbuild/freebsd-x64@0.21.5': 79 | resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} 80 | engines: {node: '>=12'} 81 | cpu: [x64] 82 | os: [freebsd] 83 | 84 | '@esbuild/linux-arm64@0.21.5': 85 | resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} 86 | engines: {node: '>=12'} 87 | cpu: [arm64] 88 | os: [linux] 89 | 90 | '@esbuild/linux-arm@0.21.5': 91 | resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} 92 | engines: {node: '>=12'} 93 | cpu: [arm] 94 | os: [linux] 95 | 96 | '@esbuild/linux-ia32@0.21.5': 97 | resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} 98 | engines: {node: '>=12'} 99 | cpu: [ia32] 100 | os: [linux] 101 | 102 | '@esbuild/linux-loong64@0.21.5': 103 | resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} 104 | engines: {node: '>=12'} 105 | cpu: [loong64] 106 | os: [linux] 107 | 108 | '@esbuild/linux-mips64el@0.21.5': 109 | resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} 110 | engines: {node: '>=12'} 111 | cpu: [mips64el] 112 | os: [linux] 113 | 114 | '@esbuild/linux-ppc64@0.21.5': 115 | resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} 116 | engines: {node: '>=12'} 117 | cpu: [ppc64] 118 | os: [linux] 119 | 120 | '@esbuild/linux-riscv64@0.21.5': 121 | resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} 122 | engines: {node: '>=12'} 123 | cpu: [riscv64] 124 | os: [linux] 125 | 126 | '@esbuild/linux-s390x@0.21.5': 127 | resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} 128 | engines: {node: '>=12'} 129 | cpu: [s390x] 130 | os: [linux] 131 | 132 | '@esbuild/linux-x64@0.21.5': 133 | resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} 134 | engines: {node: '>=12'} 135 | cpu: [x64] 136 | os: [linux] 137 | 138 | '@esbuild/netbsd-x64@0.21.5': 139 | resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} 140 | engines: {node: '>=12'} 141 | cpu: [x64] 142 | os: [netbsd] 143 | 144 | '@esbuild/openbsd-x64@0.21.5': 145 | resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} 146 | engines: {node: '>=12'} 147 | cpu: [x64] 148 | os: [openbsd] 149 | 150 | '@esbuild/sunos-x64@0.21.5': 151 | resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} 152 | engines: {node: '>=12'} 153 | cpu: [x64] 154 | os: [sunos] 155 | 156 | '@esbuild/win32-arm64@0.21.5': 157 | resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} 158 | engines: {node: '>=12'} 159 | cpu: [arm64] 160 | os: [win32] 161 | 162 | '@esbuild/win32-ia32@0.21.5': 163 | resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} 164 | engines: {node: '>=12'} 165 | cpu: [ia32] 166 | os: [win32] 167 | 168 | '@esbuild/win32-x64@0.21.5': 169 | resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} 170 | engines: {node: '>=12'} 171 | cpu: [x64] 172 | os: [win32] 173 | 174 | '@parcel/watcher-android-arm64@2.5.0': 175 | resolution: {integrity: sha512-qlX4eS28bUcQCdribHkg/herLe+0A9RyYC+mm2PXpncit8z5b3nSqGVzMNR3CmtAOgRutiZ02eIJJgP/b1iEFQ==} 176 | engines: {node: '>= 10.0.0'} 177 | cpu: [arm64] 178 | os: [android] 179 | 180 | '@parcel/watcher-darwin-arm64@2.5.0': 181 | resolution: {integrity: sha512-hyZ3TANnzGfLpRA2s/4U1kbw2ZI4qGxaRJbBH2DCSREFfubMswheh8TeiC1sGZ3z2jUf3s37P0BBlrD3sjVTUw==} 182 | engines: {node: '>= 10.0.0'} 183 | cpu: [arm64] 184 | os: [darwin] 185 | 186 | '@parcel/watcher-darwin-x64@2.5.0': 187 | resolution: {integrity: sha512-9rhlwd78saKf18fT869/poydQK8YqlU26TMiNg7AIu7eBp9adqbJZqmdFOsbZ5cnLp5XvRo9wcFmNHgHdWaGYA==} 188 | engines: {node: '>= 10.0.0'} 189 | cpu: [x64] 190 | os: [darwin] 191 | 192 | '@parcel/watcher-freebsd-x64@2.5.0': 193 | resolution: {integrity: sha512-syvfhZzyM8kErg3VF0xpV8dixJ+RzbUaaGaeb7uDuz0D3FK97/mZ5AJQ3XNnDsXX7KkFNtyQyFrXZzQIcN49Tw==} 194 | engines: {node: '>= 10.0.0'} 195 | cpu: [x64] 196 | os: [freebsd] 197 | 198 | '@parcel/watcher-linux-arm-glibc@2.5.0': 199 | resolution: {integrity: sha512-0VQY1K35DQET3dVYWpOaPFecqOT9dbuCfzjxoQyif1Wc574t3kOSkKevULddcR9znz1TcklCE7Ht6NIxjvTqLA==} 200 | engines: {node: '>= 10.0.0'} 201 | cpu: [arm] 202 | os: [linux] 203 | 204 | '@parcel/watcher-linux-arm-musl@2.5.0': 205 | resolution: {integrity: sha512-6uHywSIzz8+vi2lAzFeltnYbdHsDm3iIB57d4g5oaB9vKwjb6N6dRIgZMujw4nm5r6v9/BQH0noq6DzHrqr2pA==} 206 | engines: {node: '>= 10.0.0'} 207 | cpu: [arm] 208 | os: [linux] 209 | 210 | '@parcel/watcher-linux-arm64-glibc@2.5.0': 211 | resolution: {integrity: sha512-BfNjXwZKxBy4WibDb/LDCriWSKLz+jJRL3cM/DllnHH5QUyoiUNEp3GmL80ZqxeumoADfCCP19+qiYiC8gUBjA==} 212 | engines: {node: '>= 10.0.0'} 213 | cpu: [arm64] 214 | os: [linux] 215 | 216 | '@parcel/watcher-linux-arm64-musl@2.5.0': 217 | resolution: {integrity: sha512-S1qARKOphxfiBEkwLUbHjCY9BWPdWnW9j7f7Hb2jPplu8UZ3nes7zpPOW9bkLbHRvWM0WDTsjdOTUgW0xLBN1Q==} 218 | engines: {node: '>= 10.0.0'} 219 | cpu: [arm64] 220 | os: [linux] 221 | 222 | '@parcel/watcher-linux-x64-glibc@2.5.0': 223 | resolution: {integrity: sha512-d9AOkusyXARkFD66S6zlGXyzx5RvY+chTP9Jp0ypSTC9d4lzyRs9ovGf/80VCxjKddcUvnsGwCHWuF2EoPgWjw==} 224 | engines: {node: '>= 10.0.0'} 225 | cpu: [x64] 226 | os: [linux] 227 | 228 | '@parcel/watcher-linux-x64-musl@2.5.0': 229 | resolution: {integrity: sha512-iqOC+GoTDoFyk/VYSFHwjHhYrk8bljW6zOhPuhi5t9ulqiYq1togGJB5e3PwYVFFfeVgc6pbz3JdQyDoBszVaA==} 230 | engines: {node: '>= 10.0.0'} 231 | cpu: [x64] 232 | os: [linux] 233 | 234 | '@parcel/watcher-win32-arm64@2.5.0': 235 | resolution: {integrity: sha512-twtft1d+JRNkM5YbmexfcH/N4znDtjgysFaV9zvZmmJezQsKpkfLYJ+JFV3uygugK6AtIM2oADPkB2AdhBrNig==} 236 | engines: {node: '>= 10.0.0'} 237 | cpu: [arm64] 238 | os: [win32] 239 | 240 | '@parcel/watcher-win32-ia32@2.5.0': 241 | resolution: {integrity: sha512-+rgpsNRKwo8A53elqbbHXdOMtY/tAtTzManTWShB5Kk54N8Q9mzNWV7tV+IbGueCbcj826MfWGU3mprWtuf1TA==} 242 | engines: {node: '>= 10.0.0'} 243 | cpu: [ia32] 244 | os: [win32] 245 | 246 | '@parcel/watcher-win32-x64@2.5.0': 247 | resolution: {integrity: sha512-lPrxve92zEHdgeff3aiu4gDOIt4u7sJYha6wbdEZDCDUhtjTsOMiaJzG5lMY4GkWH8p0fMmO2Ppq5G5XXG+DQw==} 248 | engines: {node: '>= 10.0.0'} 249 | cpu: [x64] 250 | os: [win32] 251 | 252 | '@parcel/watcher@2.5.0': 253 | resolution: {integrity: sha512-i0GV1yJnm2n3Yq1qw6QrUrd/LI9bE8WEBOTtOkpCXHHdyN3TAGgqAK/DAT05z4fq2x04cARXt2pDmjWjL92iTQ==} 254 | engines: {node: '>= 10.0.0'} 255 | 256 | '@rollup/rollup-android-arm-eabi@4.25.0': 257 | resolution: {integrity: sha512-CC/ZqFZwlAIbU1wUPisHyV/XRc5RydFrNLtgl3dGYskdwPZdt4HERtKm50a/+DtTlKeCq9IXFEWR+P6blwjqBA==} 258 | cpu: [arm] 259 | os: [android] 260 | 261 | '@rollup/rollup-android-arm64@4.25.0': 262 | resolution: {integrity: sha512-/Y76tmLGUJqVBXXCfVS8Q8FJqYGhgH4wl4qTA24E9v/IJM0XvJCGQVSW1QZ4J+VURO9h8YCa28sTFacZXwK7Rg==} 263 | cpu: [arm64] 264 | os: [android] 265 | 266 | '@rollup/rollup-darwin-arm64@4.25.0': 267 | resolution: {integrity: sha512-YVT6L3UrKTlC0FpCZd0MGA7NVdp7YNaEqkENbWQ7AOVOqd/7VzyHpgIpc1mIaxRAo1ZsJRH45fq8j4N63I/vvg==} 268 | cpu: [arm64] 269 | os: [darwin] 270 | 271 | '@rollup/rollup-darwin-x64@4.25.0': 272 | resolution: {integrity: sha512-ZRL+gexs3+ZmmWmGKEU43Bdn67kWnMeWXLFhcVv5Un8FQcx38yulHBA7XR2+KQdYIOtD0yZDWBCudmfj6lQJoA==} 273 | cpu: [x64] 274 | os: [darwin] 275 | 276 | '@rollup/rollup-freebsd-arm64@4.25.0': 277 | resolution: {integrity: sha512-xpEIXhiP27EAylEpreCozozsxWQ2TJbOLSivGfXhU4G1TBVEYtUPi2pOZBnvGXHyOdLAUUhPnJzH3ah5cqF01g==} 278 | cpu: [arm64] 279 | os: [freebsd] 280 | 281 | '@rollup/rollup-freebsd-x64@4.25.0': 282 | resolution: {integrity: sha512-sC5FsmZGlJv5dOcURrsnIK7ngc3Kirnx3as2XU9uER+zjfyqIjdcMVgzy4cOawhsssqzoAX19qmxgJ8a14Qrqw==} 283 | cpu: [x64] 284 | os: [freebsd] 285 | 286 | '@rollup/rollup-linux-arm-gnueabihf@4.25.0': 287 | resolution: {integrity: sha512-uD/dbLSs1BEPzg564TpRAQ/YvTnCds2XxyOndAO8nJhaQcqQGFgv/DAVko/ZHap3boCvxnzYMa3mTkV/B/3SWA==} 288 | cpu: [arm] 289 | os: [linux] 290 | 291 | '@rollup/rollup-linux-arm-musleabihf@4.25.0': 292 | resolution: {integrity: sha512-ZVt/XkrDlQWegDWrwyC3l0OfAF7yeJUF4fq5RMS07YM72BlSfn2fQQ6lPyBNjt+YbczMguPiJoCfaQC2dnflpQ==} 293 | cpu: [arm] 294 | os: [linux] 295 | 296 | '@rollup/rollup-linux-arm64-gnu@4.25.0': 297 | resolution: {integrity: sha512-qboZ+T0gHAW2kkSDPHxu7quaFaaBlynODXpBVnPxUgvWYaE84xgCKAPEYE+fSMd3Zv5PyFZR+L0tCdYCMAtG0A==} 298 | cpu: [arm64] 299 | os: [linux] 300 | 301 | '@rollup/rollup-linux-arm64-musl@4.25.0': 302 | resolution: {integrity: sha512-ndWTSEmAaKr88dBuogGH2NZaxe7u2rDoArsejNslugHZ+r44NfWiwjzizVS1nUOHo+n1Z6qV3X60rqE/HlISgw==} 303 | cpu: [arm64] 304 | os: [linux] 305 | 306 | '@rollup/rollup-linux-powerpc64le-gnu@4.25.0': 307 | resolution: {integrity: sha512-BVSQvVa2v5hKwJSy6X7W1fjDex6yZnNKy3Kx1JGimccHft6HV0THTwNtC2zawtNXKUu+S5CjXslilYdKBAadzA==} 308 | cpu: [ppc64] 309 | os: [linux] 310 | 311 | '@rollup/rollup-linux-riscv64-gnu@4.25.0': 312 | resolution: {integrity: sha512-G4hTREQrIdeV0PE2JruzI+vXdRnaK1pg64hemHq2v5fhv8C7WjVaeXc9P5i4Q5UC06d/L+zA0mszYIKl+wY8oA==} 313 | cpu: [riscv64] 314 | os: [linux] 315 | 316 | '@rollup/rollup-linux-s390x-gnu@4.25.0': 317 | resolution: {integrity: sha512-9T/w0kQ+upxdkFL9zPVB6zy9vWW1deA3g8IauJxojN4bnz5FwSsUAD034KpXIVX5j5p/rn6XqumBMxfRkcHapQ==} 318 | cpu: [s390x] 319 | os: [linux] 320 | 321 | '@rollup/rollup-linux-x64-gnu@4.25.0': 322 | resolution: {integrity: sha512-ThcnU0EcMDn+J4B9LD++OgBYxZusuA7iemIIiz5yzEcFg04VZFzdFjuwPdlURmYPZw+fgVrFzj4CA64jSTG4Ig==} 323 | cpu: [x64] 324 | os: [linux] 325 | 326 | '@rollup/rollup-linux-x64-musl@4.25.0': 327 | resolution: {integrity: sha512-zx71aY2oQxGxAT1JShfhNG79PnjYhMC6voAjzpu/xmMjDnKNf6Nl/xv7YaB/9SIa9jDYf8RBPWEnjcdlhlv1rQ==} 328 | cpu: [x64] 329 | os: [linux] 330 | 331 | '@rollup/rollup-win32-arm64-msvc@4.25.0': 332 | resolution: {integrity: sha512-JT8tcjNocMs4CylWY/CxVLnv8e1lE7ff1fi6kbGocWwxDq9pj30IJ28Peb+Y8yiPNSF28oad42ApJB8oUkwGww==} 333 | cpu: [arm64] 334 | os: [win32] 335 | 336 | '@rollup/rollup-win32-ia32-msvc@4.25.0': 337 | resolution: {integrity: sha512-dRLjLsO3dNOfSN6tjyVlG+Msm4IiZnGkuZ7G5NmpzwF9oOc582FZG05+UdfTbz5Jd4buK/wMb6UeHFhG18+OEg==} 338 | cpu: [ia32] 339 | os: [win32] 340 | 341 | '@rollup/rollup-win32-x64-msvc@4.25.0': 342 | resolution: {integrity: sha512-/RqrIFtLB926frMhZD0a5oDa4eFIbyNEwLLloMTEjmqfwZWXywwVVOVmwTsuyhC9HKkVEZcOOi+KV4U9wmOdlg==} 343 | cpu: [x64] 344 | os: [win32] 345 | 346 | '@types/estree@1.0.6': 347 | resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} 348 | 349 | braces@3.0.3: 350 | resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} 351 | engines: {node: '>=8'} 352 | 353 | chokidar@4.0.1: 354 | resolution: {integrity: sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==} 355 | engines: {node: '>= 14.16.0'} 356 | 357 | detect-libc@1.0.3: 358 | resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==} 359 | engines: {node: '>=0.10'} 360 | hasBin: true 361 | 362 | esbuild@0.21.5: 363 | resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} 364 | engines: {node: '>=12'} 365 | hasBin: true 366 | 367 | ev-emitter@1.1.1: 368 | resolution: {integrity: sha512-ipiDYhdQSCZ4hSbX4rMW+XzNKMD1prg/sTvoVmSLkuQ1MVlwjJQQA+sW8tMYR3BLUr9KjodFV4pvzunvRhd33Q==} 369 | 370 | fill-range@7.1.1: 371 | resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} 372 | engines: {node: '>=8'} 373 | 374 | fsevents@2.3.3: 375 | resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} 376 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} 377 | os: [darwin] 378 | 379 | gsap@3.12.5: 380 | resolution: {integrity: sha512-srBfnk4n+Oe/ZnMIOXt3gT605BX9x5+rh/prT2F1SsNJsU1XuMiP0E2aptW481OnonOGACZWBqseH5Z7csHxhQ==} 381 | 382 | imagesloaded@4.1.4: 383 | resolution: {integrity: sha512-ltiBVcYpc/TYTF5nolkMNsnREHW+ICvfQ3Yla2Sgr71YFwQ86bDwV9hgpFhFtrGPuwEx5+LqOHIrdXBdoWwwsA==} 384 | 385 | immutable@4.3.7: 386 | resolution: {integrity: sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==} 387 | 388 | is-extglob@2.1.1: 389 | resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} 390 | engines: {node: '>=0.10.0'} 391 | 392 | is-glob@4.0.3: 393 | resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} 394 | engines: {node: '>=0.10.0'} 395 | 396 | is-number@7.0.0: 397 | resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} 398 | engines: {node: '>=0.12.0'} 399 | 400 | micromatch@4.0.8: 401 | resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} 402 | engines: {node: '>=8.6'} 403 | 404 | nanoid@3.3.7: 405 | resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} 406 | engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} 407 | hasBin: true 408 | 409 | node-addon-api@7.1.1: 410 | resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==} 411 | 412 | picocolors@1.1.1: 413 | resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} 414 | 415 | picomatch@2.3.1: 416 | resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} 417 | engines: {node: '>=8.6'} 418 | 419 | postcss@8.4.47: 420 | resolution: {integrity: sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==} 421 | engines: {node: ^10 || ^12 || >=14} 422 | 423 | prettier@3.3.3: 424 | resolution: {integrity: sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==} 425 | engines: {node: '>=14'} 426 | hasBin: true 427 | 428 | readdirp@4.0.2: 429 | resolution: {integrity: sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==} 430 | engines: {node: '>= 14.16.0'} 431 | 432 | rollup@4.25.0: 433 | resolution: {integrity: sha512-uVbClXmR6wvx5R1M3Od4utyLUxrmOcEm3pAtMphn73Apq19PDtHpgZoEvqH2YnnaNUuvKmg2DgRd2Sqv+odyqg==} 434 | engines: {node: '>=18.0.0', npm: '>=8.0.0'} 435 | hasBin: true 436 | 437 | sass@1.80.6: 438 | resolution: {integrity: sha512-ccZgdHNiBF1NHBsWvacvT5rju3y1d/Eu+8Ex6c21nHp2lZGLBEtuwc415QfiI1PJa1TpCo3iXwwSRjRpn2Ckjg==} 439 | engines: {node: '>=14.0.0'} 440 | hasBin: true 441 | 442 | source-map-js@1.2.1: 443 | resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} 444 | engines: {node: '>=0.10.0'} 445 | 446 | splitting@1.1.0: 447 | resolution: {integrity: sha512-6Tj+4mvlSti4DUu1yl0PnkHIIoLchFYJHqz2DnwYkvEehXbjrR2epa4ds/xdto6ZdZsC+NP5IOOehi9VGjNlMQ==} 448 | 449 | tiny-emitter@2.1.0: 450 | resolution: {integrity: sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==} 451 | 452 | to-regex-range@5.0.1: 453 | resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} 454 | engines: {node: '>=8.0'} 455 | 456 | vite@5.4.10: 457 | resolution: {integrity: sha512-1hvaPshuPUtxeQ0hsVH3Mud0ZanOLwVTneA1EgbAM5LhaZEqyPWGRQ7BtaMvUrTDeEaC8pxtj6a6jku3x4z6SQ==} 458 | engines: {node: ^18.0.0 || >=20.0.0} 459 | hasBin: true 460 | peerDependencies: 461 | '@types/node': ^18.0.0 || >=20.0.0 462 | less: '*' 463 | lightningcss: ^1.21.0 464 | sass: '*' 465 | sass-embedded: '*' 466 | stylus: '*' 467 | sugarss: '*' 468 | terser: ^5.4.0 469 | peerDependenciesMeta: 470 | '@types/node': 471 | optional: true 472 | less: 473 | optional: true 474 | lightningcss: 475 | optional: true 476 | sass: 477 | optional: true 478 | sass-embedded: 479 | optional: true 480 | stylus: 481 | optional: true 482 | sugarss: 483 | optional: true 484 | terser: 485 | optional: true 486 | 487 | snapshots: 488 | 489 | '@esbuild/aix-ppc64@0.21.5': 490 | optional: true 491 | 492 | '@esbuild/android-arm64@0.21.5': 493 | optional: true 494 | 495 | '@esbuild/android-arm@0.21.5': 496 | optional: true 497 | 498 | '@esbuild/android-x64@0.21.5': 499 | optional: true 500 | 501 | '@esbuild/darwin-arm64@0.21.5': 502 | optional: true 503 | 504 | '@esbuild/darwin-x64@0.21.5': 505 | optional: true 506 | 507 | '@esbuild/freebsd-arm64@0.21.5': 508 | optional: true 509 | 510 | '@esbuild/freebsd-x64@0.21.5': 511 | optional: true 512 | 513 | '@esbuild/linux-arm64@0.21.5': 514 | optional: true 515 | 516 | '@esbuild/linux-arm@0.21.5': 517 | optional: true 518 | 519 | '@esbuild/linux-ia32@0.21.5': 520 | optional: true 521 | 522 | '@esbuild/linux-loong64@0.21.5': 523 | optional: true 524 | 525 | '@esbuild/linux-mips64el@0.21.5': 526 | optional: true 527 | 528 | '@esbuild/linux-ppc64@0.21.5': 529 | optional: true 530 | 531 | '@esbuild/linux-riscv64@0.21.5': 532 | optional: true 533 | 534 | '@esbuild/linux-s390x@0.21.5': 535 | optional: true 536 | 537 | '@esbuild/linux-x64@0.21.5': 538 | optional: true 539 | 540 | '@esbuild/netbsd-x64@0.21.5': 541 | optional: true 542 | 543 | '@esbuild/openbsd-x64@0.21.5': 544 | optional: true 545 | 546 | '@esbuild/sunos-x64@0.21.5': 547 | optional: true 548 | 549 | '@esbuild/win32-arm64@0.21.5': 550 | optional: true 551 | 552 | '@esbuild/win32-ia32@0.21.5': 553 | optional: true 554 | 555 | '@esbuild/win32-x64@0.21.5': 556 | optional: true 557 | 558 | '@parcel/watcher-android-arm64@2.5.0': 559 | optional: true 560 | 561 | '@parcel/watcher-darwin-arm64@2.5.0': 562 | optional: true 563 | 564 | '@parcel/watcher-darwin-x64@2.5.0': 565 | optional: true 566 | 567 | '@parcel/watcher-freebsd-x64@2.5.0': 568 | optional: true 569 | 570 | '@parcel/watcher-linux-arm-glibc@2.5.0': 571 | optional: true 572 | 573 | '@parcel/watcher-linux-arm-musl@2.5.0': 574 | optional: true 575 | 576 | '@parcel/watcher-linux-arm64-glibc@2.5.0': 577 | optional: true 578 | 579 | '@parcel/watcher-linux-arm64-musl@2.5.0': 580 | optional: true 581 | 582 | '@parcel/watcher-linux-x64-glibc@2.5.0': 583 | optional: true 584 | 585 | '@parcel/watcher-linux-x64-musl@2.5.0': 586 | optional: true 587 | 588 | '@parcel/watcher-win32-arm64@2.5.0': 589 | optional: true 590 | 591 | '@parcel/watcher-win32-ia32@2.5.0': 592 | optional: true 593 | 594 | '@parcel/watcher-win32-x64@2.5.0': 595 | optional: true 596 | 597 | '@parcel/watcher@2.5.0': 598 | dependencies: 599 | detect-libc: 1.0.3 600 | is-glob: 4.0.3 601 | micromatch: 4.0.8 602 | node-addon-api: 7.1.1 603 | optionalDependencies: 604 | '@parcel/watcher-android-arm64': 2.5.0 605 | '@parcel/watcher-darwin-arm64': 2.5.0 606 | '@parcel/watcher-darwin-x64': 2.5.0 607 | '@parcel/watcher-freebsd-x64': 2.5.0 608 | '@parcel/watcher-linux-arm-glibc': 2.5.0 609 | '@parcel/watcher-linux-arm-musl': 2.5.0 610 | '@parcel/watcher-linux-arm64-glibc': 2.5.0 611 | '@parcel/watcher-linux-arm64-musl': 2.5.0 612 | '@parcel/watcher-linux-x64-glibc': 2.5.0 613 | '@parcel/watcher-linux-x64-musl': 2.5.0 614 | '@parcel/watcher-win32-arm64': 2.5.0 615 | '@parcel/watcher-win32-ia32': 2.5.0 616 | '@parcel/watcher-win32-x64': 2.5.0 617 | optional: true 618 | 619 | '@rollup/rollup-android-arm-eabi@4.25.0': 620 | optional: true 621 | 622 | '@rollup/rollup-android-arm64@4.25.0': 623 | optional: true 624 | 625 | '@rollup/rollup-darwin-arm64@4.25.0': 626 | optional: true 627 | 628 | '@rollup/rollup-darwin-x64@4.25.0': 629 | optional: true 630 | 631 | '@rollup/rollup-freebsd-arm64@4.25.0': 632 | optional: true 633 | 634 | '@rollup/rollup-freebsd-x64@4.25.0': 635 | optional: true 636 | 637 | '@rollup/rollup-linux-arm-gnueabihf@4.25.0': 638 | optional: true 639 | 640 | '@rollup/rollup-linux-arm-musleabihf@4.25.0': 641 | optional: true 642 | 643 | '@rollup/rollup-linux-arm64-gnu@4.25.0': 644 | optional: true 645 | 646 | '@rollup/rollup-linux-arm64-musl@4.25.0': 647 | optional: true 648 | 649 | '@rollup/rollup-linux-powerpc64le-gnu@4.25.0': 650 | optional: true 651 | 652 | '@rollup/rollup-linux-riscv64-gnu@4.25.0': 653 | optional: true 654 | 655 | '@rollup/rollup-linux-s390x-gnu@4.25.0': 656 | optional: true 657 | 658 | '@rollup/rollup-linux-x64-gnu@4.25.0': 659 | optional: true 660 | 661 | '@rollup/rollup-linux-x64-musl@4.25.0': 662 | optional: true 663 | 664 | '@rollup/rollup-win32-arm64-msvc@4.25.0': 665 | optional: true 666 | 667 | '@rollup/rollup-win32-ia32-msvc@4.25.0': 668 | optional: true 669 | 670 | '@rollup/rollup-win32-x64-msvc@4.25.0': 671 | optional: true 672 | 673 | '@types/estree@1.0.6': {} 674 | 675 | braces@3.0.3: 676 | dependencies: 677 | fill-range: 7.1.1 678 | optional: true 679 | 680 | chokidar@4.0.1: 681 | dependencies: 682 | readdirp: 4.0.2 683 | 684 | detect-libc@1.0.3: 685 | optional: true 686 | 687 | esbuild@0.21.5: 688 | optionalDependencies: 689 | '@esbuild/aix-ppc64': 0.21.5 690 | '@esbuild/android-arm': 0.21.5 691 | '@esbuild/android-arm64': 0.21.5 692 | '@esbuild/android-x64': 0.21.5 693 | '@esbuild/darwin-arm64': 0.21.5 694 | '@esbuild/darwin-x64': 0.21.5 695 | '@esbuild/freebsd-arm64': 0.21.5 696 | '@esbuild/freebsd-x64': 0.21.5 697 | '@esbuild/linux-arm': 0.21.5 698 | '@esbuild/linux-arm64': 0.21.5 699 | '@esbuild/linux-ia32': 0.21.5 700 | '@esbuild/linux-loong64': 0.21.5 701 | '@esbuild/linux-mips64el': 0.21.5 702 | '@esbuild/linux-ppc64': 0.21.5 703 | '@esbuild/linux-riscv64': 0.21.5 704 | '@esbuild/linux-s390x': 0.21.5 705 | '@esbuild/linux-x64': 0.21.5 706 | '@esbuild/netbsd-x64': 0.21.5 707 | '@esbuild/openbsd-x64': 0.21.5 708 | '@esbuild/sunos-x64': 0.21.5 709 | '@esbuild/win32-arm64': 0.21.5 710 | '@esbuild/win32-ia32': 0.21.5 711 | '@esbuild/win32-x64': 0.21.5 712 | 713 | ev-emitter@1.1.1: {} 714 | 715 | fill-range@7.1.1: 716 | dependencies: 717 | to-regex-range: 5.0.1 718 | optional: true 719 | 720 | fsevents@2.3.3: 721 | optional: true 722 | 723 | gsap@3.12.5: {} 724 | 725 | imagesloaded@4.1.4: 726 | dependencies: 727 | ev-emitter: 1.1.1 728 | 729 | immutable@4.3.7: {} 730 | 731 | is-extglob@2.1.1: 732 | optional: true 733 | 734 | is-glob@4.0.3: 735 | dependencies: 736 | is-extglob: 2.1.1 737 | optional: true 738 | 739 | is-number@7.0.0: 740 | optional: true 741 | 742 | micromatch@4.0.8: 743 | dependencies: 744 | braces: 3.0.3 745 | picomatch: 2.3.1 746 | optional: true 747 | 748 | nanoid@3.3.7: {} 749 | 750 | node-addon-api@7.1.1: 751 | optional: true 752 | 753 | picocolors@1.1.1: {} 754 | 755 | picomatch@2.3.1: 756 | optional: true 757 | 758 | postcss@8.4.47: 759 | dependencies: 760 | nanoid: 3.3.7 761 | picocolors: 1.1.1 762 | source-map-js: 1.2.1 763 | 764 | prettier@3.3.3: {} 765 | 766 | readdirp@4.0.2: {} 767 | 768 | rollup@4.25.0: 769 | dependencies: 770 | '@types/estree': 1.0.6 771 | optionalDependencies: 772 | '@rollup/rollup-android-arm-eabi': 4.25.0 773 | '@rollup/rollup-android-arm64': 4.25.0 774 | '@rollup/rollup-darwin-arm64': 4.25.0 775 | '@rollup/rollup-darwin-x64': 4.25.0 776 | '@rollup/rollup-freebsd-arm64': 4.25.0 777 | '@rollup/rollup-freebsd-x64': 4.25.0 778 | '@rollup/rollup-linux-arm-gnueabihf': 4.25.0 779 | '@rollup/rollup-linux-arm-musleabihf': 4.25.0 780 | '@rollup/rollup-linux-arm64-gnu': 4.25.0 781 | '@rollup/rollup-linux-arm64-musl': 4.25.0 782 | '@rollup/rollup-linux-powerpc64le-gnu': 4.25.0 783 | '@rollup/rollup-linux-riscv64-gnu': 4.25.0 784 | '@rollup/rollup-linux-s390x-gnu': 4.25.0 785 | '@rollup/rollup-linux-x64-gnu': 4.25.0 786 | '@rollup/rollup-linux-x64-musl': 4.25.0 787 | '@rollup/rollup-win32-arm64-msvc': 4.25.0 788 | '@rollup/rollup-win32-ia32-msvc': 4.25.0 789 | '@rollup/rollup-win32-x64-msvc': 4.25.0 790 | fsevents: 2.3.3 791 | 792 | sass@1.80.6: 793 | dependencies: 794 | chokidar: 4.0.1 795 | immutable: 4.3.7 796 | source-map-js: 1.2.1 797 | optionalDependencies: 798 | '@parcel/watcher': 2.5.0 799 | 800 | source-map-js@1.2.1: {} 801 | 802 | splitting@1.1.0: {} 803 | 804 | tiny-emitter@2.1.0: {} 805 | 806 | to-regex-range@5.0.1: 807 | dependencies: 808 | is-number: 7.0.0 809 | optional: true 810 | 811 | vite@5.4.10(sass@1.80.6): 812 | dependencies: 813 | esbuild: 0.21.5 814 | postcss: 8.4.47 815 | rollup: 4.25.0 816 | optionalDependencies: 817 | fsevents: 2.3.3 818 | sass: 1.80.6 819 | -------------------------------------------------------------------------------- /src/css/index.scss: -------------------------------------------------------------------------------- 1 | @import url("https://fonts.googleapis.com/css2?family=Elsie+Swash+Caps:wght@400;900&display=swap"); 2 | @import url("https://fonts.googleapis.com/css2?family=Elsie:wght@400;900&display=swap"); 3 | @import url("https://fonts.googleapis.com/css2?family=Lato:wght@300;400;700&display=swap"); 4 | @import url("https://fonts.googleapis.com/css2?family=Red+Rose:wght@300;400;700&display=swap"); 5 | 6 | :root { 7 | --cursor-stroke-width: 1px; 8 | 9 | --card-size-ratio: calc(3 / 3.8); 10 | --card-height: 550px; 11 | --card-width: calc(var(--card-size-ratio) * var(--card-height)); 12 | 13 | --bg: #cacaca; 14 | } 15 | 16 | *, 17 | *::before, 18 | *::after { 19 | box-sizing: border-box; 20 | margin: 0; 21 | padding: 0; 22 | } 23 | 24 | html, 25 | body { 26 | width: 100%; 27 | height: 100%; 28 | } 29 | 30 | body { 31 | overflow: hidden; 32 | background: var(--bg); 33 | } 34 | 35 | main { 36 | width: 100%; 37 | height: 100%; 38 | } 39 | 40 | button { 41 | outline: none; 42 | border: none; 43 | background: none; 44 | color: inherit; 45 | font-family: inherit; 46 | // &:focus { 47 | // outline: none; 48 | // border: none; 49 | // } 50 | } 51 | 52 | a { 53 | text-decoration: none; 54 | color: inherit; 55 | } 56 | 57 | .slider { 58 | position: fixed; 59 | left: 0; 60 | top: 0; 61 | width: 100%; 62 | height: 100%; 63 | } 64 | 65 | .slider__slides { 66 | display: grid; 67 | user-select: none; 68 | 69 | .slide { 70 | grid-area: 1/-1; 71 | &.slide--current { 72 | z-index: 10; 73 | } 74 | } 75 | 76 | .slide, 77 | .cards__wrapper, 78 | .cards { 79 | width: 100%; 80 | height: 100vh; 81 | } 82 | 83 | .cards { 84 | display: grid; 85 | place-items: center; 86 | } 87 | 88 | .card { 89 | width: var(--card-width); 90 | height: var(--card-height); 91 | grid-area: 1/-1; 92 | z-index: 5; 93 | 94 | &__inner { 95 | width: 100%; 96 | height: 100%; 97 | overflow: hidden; 98 | } 99 | &__image { 100 | width: 100%; 101 | } 102 | 103 | &--primary { 104 | width: 100%; 105 | height: 100%; 106 | display: grid; 107 | place-items: center; 108 | .card__inner { 109 | width: var(--card-width); 110 | height: var(--card-height); 111 | cursor: pointer; 112 | } 113 | } 114 | 115 | &--secondary { 116 | z-index: 2; 117 | } 118 | } 119 | } 120 | 121 | .slider__nav { 122 | position: fixed; 123 | bottom: 0; 124 | left: 0; 125 | padding: 2rem 3rem; 126 | z-index: 20; 127 | 128 | button, 129 | span { 130 | text-transform: uppercase; 131 | font-family: "Elsie"; 132 | font-weight: 900; 133 | font-size: 1.25rem; 134 | color: #000000; 135 | } 136 | button { 137 | padding: 5px; 138 | cursor: pointer; 139 | span { 140 | letter-spacing: 2px; 141 | } 142 | } 143 | } 144 | 145 | .slider__slide-info--wrapper { 146 | width: 100%; 147 | height: 100%; 148 | position: fixed; 149 | left: 0; 150 | top: 0; 151 | display: grid; 152 | z-index: 25; 153 | pointer-events: none; 154 | 155 | .slider__slide-info { 156 | width: 100%; 157 | height: 100%; 158 | grid-area: -1/1; 159 | &:not(.slide-info--current) { 160 | opacity: 0; 161 | } 162 | } 163 | 164 | .slide__title, 165 | .slide__text--description { 166 | position: absolute; 167 | transform: translate(-50%, -50%); 168 | } 169 | .slide__title { 170 | top: 50%; 171 | left: 50%; 172 | font-size: 10rem; 173 | font-family: "Elsie Swash Caps"; 174 | font-weight: 400; 175 | overflow: hidden; 176 | letter-spacing: -6px; 177 | color: #f55786; 178 | 179 | .word { 180 | display: flex; 181 | } 182 | } 183 | .slide__text--description { 184 | top: 70%; 185 | left: 70%; 186 | width: 300px; 187 | font-size: 0.675rem; 188 | line-height: 16px; 189 | font-family: "Lato"; 190 | font-weight: 300; 191 | color: #fff; 192 | opacity: 0; 193 | 194 | .line { 195 | overflow: hidden; 196 | } 197 | } 198 | } 199 | 200 | .frame { 201 | position: fixed; 202 | width: 100%; 203 | height: 100%; 204 | padding: 2rem 3rem; 205 | color: #000000; 206 | font-family: "Montserrat"; 207 | font-weight: 400; 208 | display: grid; 209 | justify-content: space-between; 210 | align-content: space-between; 211 | grid-template-columns: repeat(3, 1fr); 212 | grid-template-areas: 213 | "logo .. btn" 214 | "nav ... credits"; 215 | z-index: 30; 216 | pointer-events: none; 217 | 218 | > * { 219 | pointer-events: auto; 220 | overflow: hidden; 221 | span { 222 | display: block; 223 | } 224 | } 225 | 226 | &__logo { 227 | grid-area: logo; 228 | font-size: 1.25rem; 229 | justify-self: left; 230 | color: #f55786; 231 | } 232 | &__button { 233 | grid-area: btn; 234 | justify-self: right; 235 | } 236 | &__credits { 237 | grid-area: credits; 238 | justify-self: right; 239 | } 240 | 241 | &__logo, 242 | &__button { 243 | font-family: "Elsie"; 244 | font-weight: 900; 245 | } 246 | 247 | &__credits { 248 | font-size: 0.8rem; 249 | overflow: hidden; 250 | span { 251 | display: inline-block; 252 | } 253 | a { 254 | font-weight: 700; 255 | opacity: 0.8; 256 | &:hover { 257 | opacity: 1; 258 | } 259 | } 260 | } 261 | } 262 | 263 | .cursor { 264 | display: none; 265 | } 266 | 267 | @media (any-pointer: fine) { 268 | .cursor { 269 | position: fixed; 270 | top: 0; 271 | left: 0; 272 | display: block; 273 | pointer-events: none; 274 | z-index: 100; 275 | 276 | fill: var(--cursor-fill); 277 | stroke: var(--cursor-stroke); 278 | stroke-width: var(--cursor-stroke-width); 279 | 280 | .cursor__inner { 281 | opacity: 0.7; 282 | } 283 | 284 | &--large, 285 | &--close { 286 | --cursor-stroke: #f55786; 287 | --cursor-fill: transparent; 288 | } 289 | &--small { 290 | --cursor-stroke: transparent; 291 | --cursor-fill: #f55786; 292 | } 293 | 294 | &--close { 295 | --cursor-stroke: #fff; 296 | stroke-linecap: round; 297 | stroke-linejoin: round; 298 | stroke-width: 32px; 299 | // mix-blend-mode: difference; 300 | } 301 | } 302 | } 303 | 304 | .loading__wrapper { 305 | position: fixed; 306 | left: 0; 307 | top: 0; 308 | width: 100%; 309 | height: 100vh; 310 | z-index: 1000; 311 | display: flex; 312 | justify-content: center; 313 | align-items: center; 314 | 315 | .loading__text { 316 | position: absolute; 317 | top: 50%; 318 | left: 50%; 319 | transform: translate(-50%, -50%); 320 | font-size: 2vmin; 321 | font-family: "Red Rose", sans-serif; 322 | color: #fff; 323 | 324 | &--inner { 325 | animation: blink 1s infinite alternate-reverse; 326 | } 327 | 328 | @keyframes blink { 329 | from { 330 | opacity: 1; 331 | } 332 | to { 333 | opacity: 0.55; 334 | } 335 | } 336 | } 337 | 338 | .bg__transition--slide { 339 | background: #171717; 340 | position: absolute; 341 | left: 0; 342 | top: 0; 343 | width: 100%; 344 | height: 100%; 345 | z-index: -1; 346 | } 347 | } 348 | -------------------------------------------------------------------------------- /src/img/slides/s1/comp/c.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devloop01/collections-slider/75c49d92d703a54192f807ca7ab03024443811a7/src/img/slides/s1/comp/c.jpg -------------------------------------------------------------------------------- /src/img/slides/s1/comp/l.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devloop01/collections-slider/75c49d92d703a54192f807ca7ab03024443811a7/src/img/slides/s1/comp/l.jpg -------------------------------------------------------------------------------- /src/img/slides/s1/comp/r.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devloop01/collections-slider/75c49d92d703a54192f807ca7ab03024443811a7/src/img/slides/s1/comp/r.jpg -------------------------------------------------------------------------------- /src/img/slides/s1/raw/c.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devloop01/collections-slider/75c49d92d703a54192f807ca7ab03024443811a7/src/img/slides/s1/raw/c.jpg -------------------------------------------------------------------------------- /src/img/slides/s1/raw/l.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devloop01/collections-slider/75c49d92d703a54192f807ca7ab03024443811a7/src/img/slides/s1/raw/l.jpg -------------------------------------------------------------------------------- /src/img/slides/s1/raw/r.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devloop01/collections-slider/75c49d92d703a54192f807ca7ab03024443811a7/src/img/slides/s1/raw/r.jpg -------------------------------------------------------------------------------- /src/img/slides/s2/comp/c.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devloop01/collections-slider/75c49d92d703a54192f807ca7ab03024443811a7/src/img/slides/s2/comp/c.jpg -------------------------------------------------------------------------------- /src/img/slides/s2/comp/l.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devloop01/collections-slider/75c49d92d703a54192f807ca7ab03024443811a7/src/img/slides/s2/comp/l.jpg -------------------------------------------------------------------------------- /src/img/slides/s2/comp/r.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devloop01/collections-slider/75c49d92d703a54192f807ca7ab03024443811a7/src/img/slides/s2/comp/r.jpg -------------------------------------------------------------------------------- /src/img/slides/s2/raw/c.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devloop01/collections-slider/75c49d92d703a54192f807ca7ab03024443811a7/src/img/slides/s2/raw/c.jpg -------------------------------------------------------------------------------- /src/img/slides/s2/raw/l.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devloop01/collections-slider/75c49d92d703a54192f807ca7ab03024443811a7/src/img/slides/s2/raw/l.jpg -------------------------------------------------------------------------------- /src/img/slides/s2/raw/r.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devloop01/collections-slider/75c49d92d703a54192f807ca7ab03024443811a7/src/img/slides/s2/raw/r.jpg -------------------------------------------------------------------------------- /src/img/slides/s3/comp/c.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devloop01/collections-slider/75c49d92d703a54192f807ca7ab03024443811a7/src/img/slides/s3/comp/c.jpg -------------------------------------------------------------------------------- /src/img/slides/s3/comp/l.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devloop01/collections-slider/75c49d92d703a54192f807ca7ab03024443811a7/src/img/slides/s3/comp/l.jpg -------------------------------------------------------------------------------- /src/img/slides/s3/comp/r.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devloop01/collections-slider/75c49d92d703a54192f807ca7ab03024443811a7/src/img/slides/s3/comp/r.jpg -------------------------------------------------------------------------------- /src/img/slides/s3/raw/c.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devloop01/collections-slider/75c49d92d703a54192f807ca7ab03024443811a7/src/img/slides/s3/raw/c.jpg -------------------------------------------------------------------------------- /src/img/slides/s3/raw/l.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devloop01/collections-slider/75c49d92d703a54192f807ca7ab03024443811a7/src/img/slides/s3/raw/l.jpg -------------------------------------------------------------------------------- /src/img/slides/s3/raw/r.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devloop01/collections-slider/75c49d92d703a54192f807ca7ab03024443811a7/src/img/slides/s3/raw/r.jpg -------------------------------------------------------------------------------- /src/js/Cursor.js: -------------------------------------------------------------------------------- 1 | import { gsap } from "gsap"; 2 | import { lerp, Mouse } from "./utils"; 3 | import { Events } from "./events"; 4 | 5 | let mouse = new Mouse(); 6 | 7 | export default class Cursor { 8 | constructor(el) { 9 | this.DOM = { el: el }; 10 | this.DOM.el.style.opacity = 0; 11 | 12 | this.bounds = this.DOM.el.getBoundingClientRect(); 13 | 14 | this.renderedStyles = { 15 | tx: { previous: 0, current: 0, amt: 0.2 }, 16 | ty: { previous: 0, current: 0, amt: 0.2 }, 17 | scale: { previous: 0, current: 1, amt: 0.2 }, 18 | opacity: { previous: 0, current: 1, amt: 0.15 }, 19 | }; 20 | } 21 | 22 | init() { 23 | this.onMouseMoveEv = () => { 24 | this.renderedStyles.tx.previous = this.renderedStyles.tx.current = 25 | mouse.position.x - this.bounds.width / 2; 26 | this.renderedStyles.ty.previous = this.renderedStyles.ty.previous = 27 | mouse.position.y - this.bounds.height / 2; 28 | Events.on("tick", this.render.bind(this)); 29 | window.removeEventListener("mousemove", this.onMouseMoveEv); 30 | }; 31 | window.addEventListener("mousemove", this.onMouseMoveEv); 32 | } 33 | 34 | setTranslateLerpAmount(amount) { 35 | this.renderedStyles["tx"].amt = amount; 36 | this.renderedStyles["ty"].amt = amount; 37 | return this; 38 | } 39 | scale(amount = 1) { 40 | this.renderedStyles["scale"].current = amount; 41 | return this; 42 | } 43 | opaque(amount = 1) { 44 | this.renderedStyles["opacity"].current = amount; 45 | return this; 46 | } 47 | render() { 48 | this.renderedStyles["tx"].current = mouse.position.x - this.bounds.width / 2; 49 | this.renderedStyles["ty"].current = mouse.position.y - this.bounds.height / 2; 50 | 51 | for (const key in this.renderedStyles) { 52 | this.renderedStyles[key].previous = lerp( 53 | this.renderedStyles[key].previous, 54 | this.renderedStyles[key].current, 55 | this.renderedStyles[key].amt, 56 | ); 57 | } 58 | 59 | gsap.set(this.DOM.el, { 60 | translateX: this.renderedStyles["tx"].previous, 61 | translateY: this.renderedStyles["ty"].previous, 62 | scale: this.renderedStyles["scale"].previous, 63 | opacity: this.renderedStyles["opacity"].previous, 64 | }); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/js/Cursors.js: -------------------------------------------------------------------------------- 1 | import Cursor from "./Cursor"; 2 | 3 | export default new (class { 4 | constructor() { 5 | this.DOM = {}; 6 | 7 | this.DOM.cursorEls = { 8 | large: document.querySelector(".cursor--large"), 9 | small: document.querySelector(".cursor--small"), 10 | close: document.querySelector(".cursor--close"), 11 | }; 12 | 13 | this.cursors = { 14 | large: new Cursor(this.DOM.cursorEls.large), 15 | small: new Cursor(this.DOM.cursorEls.small), 16 | close: new Cursor(this.DOM.cursorEls.close), 17 | }; 18 | 19 | this.cursors.small.setTranslateLerpAmount(0.85); 20 | this.cursors.close.opaque(0).scale(0.5).setTranslateLerpAmount(0.5); 21 | } 22 | 23 | init() { 24 | Object.values(this.cursors).forEach((cursor) => { 25 | cursor.init(); 26 | }); 27 | this.initEvents(); 28 | } 29 | 30 | initEvents() { 31 | this.initEventsOnElements(); 32 | this.initEventsOnImage(); 33 | } 34 | 35 | initEventsOnElements() { 36 | const onMouseEnter = () => { 37 | this.cursors.large.scale(2).opaque(0); 38 | this.cursors.small.scale(5); 39 | }; 40 | 41 | const onMouseLeave = () => { 42 | this.cursors.large.scale(1).opaque(1); 43 | this.cursors.small.scale(1); 44 | }; 45 | 46 | const onMouseDown = () => { 47 | this.cursors.small.scale(4); 48 | }; 49 | 50 | const onMouseUp = () => { 51 | this.cursors.small.scale(5); 52 | }; 53 | 54 | [...document.querySelectorAll("a"), ...document.querySelectorAll("button")].forEach( 55 | (element) => { 56 | element.addEventListener("mouseenter", onMouseEnter); 57 | element.addEventListener("mouseleave", onMouseLeave); 58 | element.addEventListener("mousedown", onMouseDown); 59 | element.addEventListener("mouseup", onMouseUp); 60 | }, 61 | ); 62 | } 63 | 64 | initEventsOnImage() { 65 | const onMouseDown = () => { 66 | this.cursors.large.scale(2).opaque(0); 67 | this.cursors.small.scale(5); 68 | }; 69 | 70 | const onMouseUp = () => { 71 | this.cursors.large.scale(1).opaque(1); 72 | this.cursors.small.scale(1); 73 | }; 74 | 75 | [...document.querySelectorAll(".card.card--primary img")].forEach((image) => { 76 | image.addEventListener("mousedown", onMouseDown); 77 | image.addEventListener("mouseup", onMouseUp); 78 | }); 79 | } 80 | 81 | initEventsOnSlider(slider) { 82 | const onMouseEnter = () => { 83 | this.cursors.large.scale(2).opaque(0); 84 | this.cursors.small.scale(5).setTranslateLerpAmount(0.25); 85 | this.cursors.close.opaque(1).scale(1); 86 | }; 87 | 88 | const onMouseLeave = () => { 89 | this.cursors.large.scale(1).opaque(1); 90 | this.cursors.small.scale(1).setTranslateLerpAmount(0.85); 91 | this.cursors.close.opaque(0).scale(0.5); 92 | }; 93 | 94 | const slides = slider.slides; 95 | 96 | slides.forEach((slide) => { 97 | slide.onFullscreen(() => { 98 | onMouseEnter(); 99 | [...document.querySelectorAll(".card.card--primary img")].forEach((image) => { 100 | image.addEventListener("mouseenter", onMouseEnter); 101 | image.addEventListener("mouseleave", onMouseLeave); 102 | }); 103 | }); 104 | slide.offFullscreen(() => { 105 | onMouseLeave(); 106 | [...document.querySelectorAll(".card.card--primary img")].forEach((image) => { 107 | image.removeEventListener("mouseenter", onMouseEnter); 108 | image.removeEventListener("mouseleave", onMouseLeave); 109 | }); 110 | }); 111 | }); 112 | } 113 | })(); 114 | -------------------------------------------------------------------------------- /src/js/Slide.js: -------------------------------------------------------------------------------- 1 | import gsap from "gsap"; 2 | import { calculateClipPath } from "./utils"; 3 | 4 | let clicked = false; 5 | 6 | export default class Slide { 7 | constructor(el) { 8 | this.DOM = { el }; 9 | this.DOM.cardsWrapperEl = this.DOM.el.querySelector(".cards__wrapper"); 10 | this.DOM.cards = { 11 | center: this.DOM.cardsWrapperEl.querySelector(".card.card--center .card__inner"), 12 | left: this.DOM.cardsWrapperEl.querySelector(".card.card--left .card__inner"), 13 | right: this.DOM.cardsWrapperEl.querySelector(".card.card--right .card__inner"), 14 | }; 15 | 16 | this.isAnimating = false; 17 | this.isFullScreen = false; 18 | 19 | this.onFullscreenCallbackFns = []; 20 | this.offFullscreenCallbackFns = []; 21 | 22 | this.init(); 23 | this.initEvents(); 24 | } 25 | 26 | init() { 27 | gsap.set(this.DOM.cards.center.parentElement, { 28 | clipPath: calculateClipPath(this.DOM.cards.center).clipPath, 29 | }); 30 | gsap.set([this.DOM.cards.left, this.DOM.cards.right], { 31 | scale: 0.9, 32 | translateX: gsap.utils.wrap([-250, 250]), 33 | rotate: gsap.utils.wrap([-8, 8]), 34 | }); 35 | } 36 | 37 | setClip() { 38 | gsap.set(this.DOM.cards.center.parentElement, { 39 | clipPath: calculateClipPath( 40 | this.isFullScreen ? this.DOM.cardsWrapperEl : this.DOM.cards.center, 41 | ).clipPath, 42 | }); 43 | } 44 | 45 | initEvents() { 46 | this.initCardEvents(); 47 | const onResizeEv = () => { 48 | if (this.isAnimating) return; 49 | 50 | const scaleAmount = window.innerWidth / this.DOM.cards.center.clientWidth; 51 | 52 | this.setClip(); 53 | 54 | gsap.set(this.DOM.cards.center.querySelector(".card__image"), { 55 | scale: this.isFullScreen ? Math.max(scaleAmount, 1.5) : 1, 56 | }); 57 | }; 58 | 59 | window.addEventListener("resize", onResizeEv); 60 | } 61 | 62 | onFullscreen(callback) { 63 | if (typeof callback == "function") { 64 | this.onFullscreenCallbackFns.push(callback); 65 | } 66 | } 67 | 68 | offFullscreen(callback) { 69 | if (typeof callback == "function") { 70 | this.offFullscreenCallbackFns.push(callback); 71 | } 72 | } 73 | 74 | initCardEvents() { 75 | const onCardClickEv = () => { 76 | if (this.isAnimating) return; 77 | 78 | const scaleAmount = window.innerWidth / this.DOM.cards.center.clientWidth; 79 | 80 | clicked = !clicked; 81 | 82 | const tl = gsap 83 | .timeline({ 84 | defaults: { 85 | duration: 2, 86 | ease: "expo.inOut", 87 | }, 88 | onStart: () => { 89 | this.isAnimating = true; 90 | if (clicked) { 91 | if (this.onFullscreenCallbackFns) this.onFullscreenCallbackFns.forEach((fn) => fn()); 92 | } else { 93 | if (this.offFullscreenCallbackFns) 94 | this.offFullscreenCallbackFns.forEach((fn) => fn()); 95 | } 96 | }, 97 | onComplete: () => { 98 | this.isAnimating = false; 99 | this.isFullScreen = clicked; 100 | }, 101 | }) 102 | .addLabel("start", 0) 103 | .addLabel("upcoming", 1); 104 | 105 | tl.to( 106 | [this.DOM.cards.left, this.DOM.cards.right], 107 | { 108 | translateX: clicked ? 0 : gsap.utils.wrap([-250, 250]), 109 | rotate: clicked ? 0 : gsap.utils.wrap([-8, 8]), 110 | }, 111 | clicked ? "start" : "upcoming", 112 | ) 113 | .to( 114 | this.DOM.cards.center.querySelector(".card__image"), 115 | { 116 | scale: clicked ? scaleAmount : 1, 117 | }, 118 | clicked ? "upcoming" : "start", 119 | ) 120 | .to( 121 | this.DOM.cards.center.parentElement, 122 | { 123 | clipPath: calculateClipPath(clicked ? this.DOM.cardsWrapperEl : this.DOM.cards.center) 124 | .clipPath, 125 | }, 126 | clicked ? "upcoming" : "start", 127 | ); 128 | }; 129 | 130 | const onCardHoverEv = () => { 131 | gsap.to([this.DOM.cards.left.parentElement, this.DOM.cards.right.parentElement], { 132 | duration: 1, 133 | translateX: gsap.utils.wrap([-10, 10]), 134 | ease: "elastic.out(1, 1)", 135 | }); 136 | }; 137 | 138 | const offCardHoverEv = () => { 139 | gsap.to([this.DOM.cards.left.parentElement, this.DOM.cards.right.parentElement], { 140 | duration: 1, 141 | translateX: 0, 142 | ease: "elastic.out(1, 1)", 143 | }); 144 | }; 145 | 146 | this.DOM.cards.center.addEventListener("click", onCardClickEv); 147 | this.DOM.cards.center.children[0].addEventListener("mouseenter", onCardHoverEv); 148 | this.DOM.cards.center.children[0].addEventListener("mouseleave", offCardHoverEv); 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /src/js/Slideinfo.js: -------------------------------------------------------------------------------- 1 | import { Splitter } from "./utils"; 2 | 3 | export default class Slideinfo { 4 | constructor(el) { 5 | this.DOM = { el: el }; 6 | 7 | this.DOM.text = { 8 | // index: this.DOM.el.querySelectorAll(".slide__index .char"), 9 | title: this.DOM.el.querySelectorAll(".slide__title .char"), 10 | description: this.DOM.el.querySelector(".slide__text--description"), 11 | }; 12 | 13 | const split = new Splitter(this.DOM.text.description); 14 | 15 | const lines = [...split.linesEl.children].map((c) => [...c.children][0]); 16 | this.DOM.text.descriptionLines = lines; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/js/Slideshow.js: -------------------------------------------------------------------------------- 1 | import gsap from "gsap"; 2 | import CustomEase from "gsap/CustomEase"; 3 | 4 | import Slide from "./Slide"; 5 | import Slideinfo from "./Slideinfo"; 6 | import { colors } from "./utils"; 7 | 8 | gsap.registerPlugin(CustomEase); 9 | 10 | CustomEase.create( 11 | "customExpo", 12 | "M0,0 C0.25,0 0.294,0.023 0.335,0.05 0.428,0.11 0.468,0.254 0.498,0.502 0.528,0.782 0.574,0.902 0.626,0.954 0.672,1 0.698,1 1,1 ", 13 | ); 14 | 15 | export default class Slideshow { 16 | constructor(el) { 17 | this.DOM = { el }; 18 | this.DOM.navigation = { 19 | el: this.DOM.el.querySelector(".slider__nav"), 20 | prev: this.DOM.el.querySelector(".slider__nav--prev"), 21 | next: this.DOM.el.querySelector(".slider__nav--next"), 22 | }; 23 | 24 | this.slides = Array.from(this.DOM.el.querySelectorAll(".slide")).map( 25 | (slide) => new Slide(slide), 26 | ); 27 | this.slideInfos = Array.from(this.DOM.el.querySelectorAll(".slider__slide-info")).map( 28 | (slideInfo) => new Slideinfo(slideInfo), 29 | ); 30 | 31 | this.isAnimatingSlide = false; 32 | 33 | this.current = 0; 34 | this.slidesTotal = this.slides.length; 35 | 36 | this.onSlideChangeCallbackFns = []; 37 | } 38 | 39 | init() { 40 | const currentSlide = this.slides[this.current]; 41 | const currentSlideInfo = this.slideInfos[this.current]; 42 | 43 | this.slides.forEach((slide, index) => { 44 | if (currentSlide != slide) { 45 | gsap.set( 46 | [ 47 | slide.DOM.cards.left.parentElement, 48 | slide.DOM.cards.center, 49 | slide.DOM.cards.right.parentElement, 50 | ], 51 | { 52 | x: "100vw", 53 | }, 54 | ); 55 | } 56 | gsap.set(this.slideInfos[index].DOM.text.title, { color: colors[index].titleColor }); 57 | }); 58 | 59 | gsap 60 | .timeline() 61 | .set([this.DOM.navigation.el], { opacity: 0, pointerEvents: "none" }) 62 | .set(currentSlide.DOM.el, { pointerEvents: "none" }) 63 | .set([currentSlide.DOM.cards.left, currentSlide.DOM.cards.right], { 64 | translateX: 0, 65 | rotate: 0, 66 | opacity: 0, 67 | }) 68 | .set(currentSlide.DOM.cards.center, { 69 | translateY: -currentSlide.DOM.cards.center.clientHeight * 1.15, 70 | }) 71 | .set(currentSlide.DOM.cards.center.children[0], { 72 | translateY: currentSlide.DOM.cards.center.clientHeight * 1.15, 73 | }) 74 | .set(currentSlideInfo.DOM.text.title, { yPercent: 120 }); 75 | 76 | this.initEvents(); 77 | } 78 | 79 | initAnimation() { 80 | const currentSlide = this.slides[this.current]; 81 | const currentSlideInfo = this.slideInfos[this.current]; 82 | const delay = 0.25; 83 | 84 | const tl = gsap 85 | .timeline({ defaults: { duration: 2, ease: "expo.inOut" } }) 86 | .addLabel("start", delay) 87 | .addLabel("upcoming", delay + 0.85); 88 | 89 | tl.to(currentSlide.DOM.el, { yPercent: 0 }, "start") 90 | .to([this.DOM.navigation.el], { opacity: 1, pointerEvents: "all" }, "upcoming") 91 | .to( 92 | [currentSlide.DOM.cards.left, currentSlide.DOM.cards.right], 93 | { 94 | translateX: gsap.utils.wrap([-250, 250]), 95 | rotate: gsap.utils.wrap([-8, 8]), 96 | opacity: 1, 97 | }, 98 | "upcoming", 99 | ) 100 | .to( 101 | [currentSlide.DOM.cards.center, currentSlide.DOM.cards.center.children[0]], 102 | { translateY: 0 }, 103 | "start", 104 | ) 105 | .to(currentSlideInfo.DOM.text.title, { yPercent: 0, stagger: 0.025 }, "upcoming") 106 | .set(".card--primary .card__inner", { overflow: "visible" }) 107 | .set(currentSlide.DOM.el, { pointerEvents: "all" }); 108 | } 109 | 110 | initEvents() { 111 | const onClickPrevEv = () => this.navigate("prev"); 112 | const onClickNextEv = () => this.navigate("next"); 113 | 114 | this.DOM.navigation.prev.addEventListener("click", onClickPrevEv); 115 | this.DOM.navigation.next.addEventListener("click", onClickNextEv); 116 | 117 | this.slides.forEach((slide) => { 118 | slide.onFullscreen(() => { 119 | const currentSlideInfo = this.slideInfos[this.current]; 120 | gsap 121 | .timeline({ 122 | delay: 0.45, 123 | defaults: { duration: 3, ease: "expo.inOut" }, 124 | }) 125 | .addLabel("start", 0) 126 | .to(currentSlideInfo.DOM.el, { background: "rgba(0, 0, 0, 0.5)" }, "start") 127 | .to(currentSlideInfo.DOM.text.description, { opacity: 1 }, "start") 128 | .fromTo( 129 | currentSlideInfo.DOM.text.descriptionLines, 130 | { yPercent: 100 }, 131 | { yPercent: 0, stagger: 0.05 }, 132 | "start", 133 | ) 134 | .to(currentSlideInfo.DOM.el, { scale: 1.25 }, "start") 135 | .to(this.DOM.navigation.el, { opacity: 0, pointerEvents: "none" }, "start") 136 | .to(".frame__credits, .frame__button", { color: "#fff" }, "start"); 137 | }); 138 | slide.offFullscreen(() => { 139 | const currentSlideInfo = this.slideInfos[this.current]; 140 | gsap 141 | .timeline({ defaults: { duration: 2, ease: "expo.inOut" } }) 142 | .addLabel("start", 0) 143 | .to(currentSlideInfo.DOM.el, { background: "rgba(0, 0, 0, 0)" }, "start") 144 | .to(currentSlideInfo.DOM.text.description, { opacity: 0 }, "start") 145 | .to( 146 | currentSlideInfo.DOM.text.descriptionLines, 147 | { yPercent: -100, stagger: -0.05 }, 148 | "start", 149 | ) 150 | .to(currentSlideInfo.DOM.el, { scale: 1 }, "start") 151 | .to(this.DOM.navigation.el, { opacity: 1, pointerEvents: "all" }, "start") 152 | .to(".frame__credits, .frame__button", { color: "#000" }, "start"); 153 | }); 154 | }); 155 | } 156 | 157 | onSlideChange(callback) { 158 | if (typeof callback == "function") { 159 | this.onSlideChangeCallbackFns.push(callback); 160 | } 161 | } 162 | 163 | navigate(direction) { 164 | if (this.isAnimatingSlide) return; 165 | 166 | const incrementSlideIndex = (val) => { 167 | if (val > 0 && this.current + val < this.slidesTotal) { 168 | this.current += val; 169 | } else if (val > 0) { 170 | this.current = 0; 171 | } else if (val < 0 && this.current + val < 0) { 172 | this.current = this.slidesTotal - 1; 173 | } else { 174 | this.current += val; 175 | } 176 | }; 177 | 178 | const increment = direction == "prev" ? -1 : 1; 179 | 180 | const currentSlide = this.slides[this.current]; 181 | const currentSlideInfo = this.slideInfos[this.current]; 182 | incrementSlideIndex(increment); 183 | const nextSlide = this.slides[this.current]; 184 | const nextSlideInfo = this.slideInfos[this.current]; 185 | 186 | const slideTl = gsap 187 | .timeline({ 188 | defaults: { 189 | stagger: 0.095 * increment, 190 | duration: 2, 191 | ease: "customExpo", 192 | }, 193 | onStart: () => { 194 | this.isAnimatingSlide = true; 195 | if (this.onSlideChangeCallbackFns) 196 | this.onSlideChangeCallbackFns.forEach((fn) => fn(this.current)); 197 | }, 198 | onComplete: () => { 199 | this.isAnimatingSlide = false; 200 | currentSlide.DOM.el.classList.remove("slide--current"); 201 | nextSlide.DOM.el.classList.add("slide--current"); 202 | }, 203 | }) 204 | .addLabel("start", 0) 205 | .addLabel("upcoming", 0.3); 206 | 207 | slideTl 208 | .to( 209 | [ 210 | currentSlide.DOM.cards.left.parentElement, 211 | currentSlide.DOM.cards.center, 212 | currentSlide.DOM.cards.right.parentElement, 213 | ], 214 | { 215 | x: direction === "next" ? "-100vw" : "100vw", 216 | onUpdate: () => { 217 | currentSlide.setClip(); 218 | }, 219 | }, 220 | "start", 221 | ) 222 | .to( 223 | [currentSlide.DOM.cards.left, currentSlide.DOM.cards.right], 224 | { rotate: gsap.utils.random(-20, 20) }, 225 | "start", 226 | ) 227 | .fromTo( 228 | [ 229 | nextSlide.DOM.cards.left.parentElement, 230 | nextSlide.DOM.cards.center, 231 | nextSlide.DOM.cards.right.parentElement, 232 | ], 233 | { x: direction === "next" ? "100vw" : "-100vw" }, 234 | { 235 | x: 0, 236 | onUpdate: () => { 237 | nextSlide.setClip(); 238 | }, 239 | }, 240 | "upcoming", 241 | ) 242 | .fromTo( 243 | [nextSlide.DOM.cards.left, nextSlide.DOM.cards.right], 244 | { rotate: gsap.utils.random(-20, 20) }, 245 | { rotate: gsap.utils.wrap([-8, 8]) }, 246 | "upcoming", 247 | ); 248 | 249 | const slideInfoTl = gsap 250 | .timeline({ 251 | defaults: { duration: 2, ease: "expo.inOut" }, 252 | onComplete: () => { 253 | currentSlideInfo.DOM.el.classList.remove("slide-info--current"); 254 | }, 255 | }) 256 | .addLabel("start", 0) 257 | .addLabel("upcoming", 0.3); 258 | 259 | slideInfoTl 260 | .to( 261 | currentSlideInfo.DOM.text.title, 262 | { 263 | yPercent: direction === "next" ? -120 : 120, 264 | rotation: direction === "next" ? 3 : -3, 265 | stagger: direction === "next" ? 0.02 : -0.02, 266 | }, 267 | "start", 268 | ) 269 | .add(() => { 270 | gsap.set(nextSlideInfo.DOM.text.title, { 271 | yPercent: direction === "next" ? 120 : -120, 272 | rotation: direction === "next" ? -3 : 3, 273 | }); 274 | nextSlideInfo.DOM.el.classList.add("slide-info--current"); 275 | }, "upcoming") 276 | .to( 277 | nextSlideInfo.DOM.text.title, 278 | { 279 | yPercent: 0, 280 | rotation: 0, 281 | stagger: direction === "next" ? 0.02 : -0.02, 282 | }, 283 | "upcoming", 284 | ); 285 | } 286 | } 287 | -------------------------------------------------------------------------------- /src/js/events/Events.js: -------------------------------------------------------------------------------- 1 | import Emitter from "tiny-emitter"; 2 | 3 | export default new Emitter(); 4 | -------------------------------------------------------------------------------- /src/js/events/Raf.js: -------------------------------------------------------------------------------- 1 | import gsap from "gsap"; 2 | import Events from "./Events"; 3 | 4 | class Raf { 5 | constructor() { 6 | this.init(); 7 | } 8 | 9 | tick() { 10 | Events.emit("tick"); 11 | } 12 | 13 | on() { 14 | gsap.ticker.add(this.tick.bind(this)); 15 | } 16 | 17 | init() { 18 | this.on(); 19 | } 20 | } 21 | 22 | export default new Raf(); 23 | -------------------------------------------------------------------------------- /src/js/events/Resize.js: -------------------------------------------------------------------------------- 1 | import Events from "./Events"; 2 | 3 | class Resize { 4 | constructor() { 5 | this.init(); 6 | } 7 | 8 | onResize() { 9 | Events.emit("resize"); 10 | } 11 | 12 | on() { 13 | window.addEventListener("resize", this.onResize); 14 | } 15 | 16 | init() { 17 | this.on(); 18 | } 19 | } 20 | 21 | export default new Resize(); 22 | -------------------------------------------------------------------------------- /src/js/events/index.js: -------------------------------------------------------------------------------- 1 | import Events from "./Events"; 2 | import GlobalResize from "./Resize"; 3 | import GlobalRaf from "./Raf"; 4 | 5 | export { Events, GlobalResize, GlobalRaf }; 6 | -------------------------------------------------------------------------------- /src/js/index.js: -------------------------------------------------------------------------------- 1 | import "splitting/dist/splitting.css"; 2 | import "splitting/dist/splitting-cells.css"; 3 | 4 | import gsap from "gsap"; 5 | import Splitting from "splitting"; 6 | 7 | import Slideshow from "./Slideshow"; 8 | import Cursors from "./Cursors"; 9 | import { colors, preloadImages } from "./utils"; 10 | 11 | Splitting(); 12 | 13 | class App { 14 | constructor() { 15 | this.slider = new Slideshow(document.querySelector(".slider")); 16 | this.masterTl = gsap.timeline(); 17 | } 18 | 19 | init() { 20 | preloadImages(document.querySelectorAll(".card")).then(() => { 21 | this.slider.init(); 22 | this.initEvents(); 23 | this.initAnimation(); 24 | }); 25 | } 26 | 27 | initAnimation() { 28 | const loadedAnimationTl = gsap 29 | .timeline() 30 | .to(".loading__text", { duration: 1, opacity: 0 }) 31 | .to(".bg__transition--slide", { 32 | duration: 1, 33 | scaleY: 0, 34 | transformOrigin: "top center", 35 | ease: "expo.out", 36 | onComplete: () => { 37 | gsap.set(".loading__wrapper", { pointerEvents: "none", autoAlpha: 0 }); 38 | }, 39 | }) 40 | .add(() => { 41 | this.slider.initAnimation(); 42 | }, "<"); 43 | 44 | const pageAnimationTl = gsap 45 | .timeline({ 46 | delay: loadedAnimationTl.duration(), 47 | onComplete: () => { 48 | Cursors.init(); 49 | Cursors.initEventsOnSlider(this.slider); 50 | }, 51 | }) 52 | .from([".frame > * > span"], { 53 | duration: 1, 54 | opacity: 0, 55 | yPercent: 100, 56 | ease: "expo.out", 57 | }); 58 | 59 | this.masterTl.add(loadedAnimationTl, 0); 60 | this.masterTl.add(pageAnimationTl, pageAnimationTl.duration() - 0.5); 61 | } 62 | 63 | initEvents() { 64 | this.slider.onSlideChange((currentSlideIndex) => { 65 | const color = colors[currentSlideIndex]; 66 | gsap 67 | .timeline({ 68 | delay: 1.25, 69 | defaults: { 70 | duration: 1.25, 71 | }, 72 | }) 73 | .addLabel("start", 0) 74 | .to("body", { backgroundColor: color.bgColor }, "start") 75 | .to(".frame__logo", { color: color.logoColor }, "start") 76 | .to(Cursors.cursors.large.DOM.el, { "--cursor-stroke": color.cursor }, "start") 77 | .to(Cursors.cursors.small.DOM.el, { "--cursor-fill": color.cursor }, "start"); 78 | }); 79 | } 80 | } 81 | 82 | const app = new App(); 83 | app.init(); 84 | -------------------------------------------------------------------------------- /src/js/utils/Mouse.js: -------------------------------------------------------------------------------- 1 | import { getMousePos } from "./index"; 2 | 3 | export default class Mouse { 4 | constructor() { 5 | this.position = { 6 | x: 0, 7 | y: 0, 8 | }; 9 | this.isMoving = false; 10 | 11 | this.mouseEvent = { 12 | previous: null, 13 | current: null, 14 | }; 15 | 16 | this.initEvents(); 17 | this.updateMovingState(); 18 | } 19 | initEvents() { 20 | window.addEventListener("mousemove", (ev) => { 21 | this.mouseEvent.current = ev; 22 | this.position = getMousePos(ev); 23 | }); 24 | } 25 | updateMovingState() { 26 | setInterval(() => { 27 | if (this.mouseEvent.previous && this.mouseEvent.current) { 28 | const moveX = Math.abs(this.mouseEvent.current.screenX - this.mouseEvent.previous.screenX); 29 | const moveY = Math.abs(this.mouseEvent.current.screenY - this.mouseEvent.previous.screenY); 30 | const movement = Math.sqrt(moveX * moveX + moveY * moveY); 31 | 32 | if (movement == 0) this.isMoving = false; 33 | else this.isMoving = true; 34 | } 35 | 36 | this.mouseEvent.previous = this.mouseEvent.current; 37 | }, 100); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/js/utils/Splitter.js: -------------------------------------------------------------------------------- 1 | export default class Splitter { 2 | constructor(el) { 3 | this.DOM = { el }; 4 | this.DOMElComputedStyles = getComputedStyle(this.DOM.el); 5 | 6 | this.init(); 7 | } 8 | 9 | init() { 10 | const lines = this.split(); 11 | this.clearElement(); 12 | this.insertLines(lines); 13 | } 14 | 15 | split() { 16 | const maxwidth = this.DOM.el.getBoundingClientRect().width; 17 | const textContent = this.DOM.el.innerText; 18 | const words = textContent.split(" "); 19 | 20 | const lines = []; 21 | let curline = []; 22 | 23 | const fontWeight = this.DOMElComputedStyles["font-weight"]; 24 | const fontSize = this.DOMElComputedStyles["font-size"]; 25 | const fontFamily = this.DOMElComputedStyles["font-family"]; 26 | 27 | const canvasEl = document.createElement("canvas"); 28 | const ghost = "OffscreenCanvas" in window ? canvasEl.transferControlToOffscreen() : canvasEl; 29 | const context = ghost.getContext("2d"); 30 | 31 | context.font = `${fontWeight} ${fontSize} ${fontFamily}`; 32 | 33 | for (let i = 0; i < words.length; i++) { 34 | curline.push(words[i]); 35 | if (context.measureText(curline.join(" ")).width >= maxwidth) { 36 | const cache = curline.pop(); 37 | lines.push(curline.join(" ")); 38 | curline = [cache]; 39 | } 40 | } 41 | lines.push(curline.join(" ")); 42 | return lines; 43 | } 44 | 45 | insertLines(lines) { 46 | this.linesEl = document.createElement("span"); 47 | this.linesEl.className = "lines"; 48 | this.linesEl.style.display = "block"; 49 | 50 | lines.forEach((line) => { 51 | const lineEl = document.createElement("span"); 52 | const lineInnerTextEl = document.createElement("span"); 53 | 54 | lineEl.className = "line"; 55 | lineInnerTextEl.className = "line--innertext"; 56 | 57 | lineEl.style.display = "block"; 58 | lineInnerTextEl.style.display = "block"; 59 | 60 | lineInnerTextEl.innerText = line; 61 | 62 | lineEl.appendChild(lineInnerTextEl); 63 | this.linesEl.appendChild(lineEl); 64 | }); 65 | 66 | this.DOM.el.appendChild(this.linesEl); 67 | } 68 | 69 | clearElement() { 70 | this.DOM.el.innerHTML = ""; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/js/utils/colorConfig.js: -------------------------------------------------------------------------------- 1 | export default [ 2 | { 3 | index: 1, 4 | bgColor: "#d1c1c6", 5 | titleColor: "#f55786", 6 | logoColor: "#f55786", 7 | cursor: "#f55786", 8 | }, 9 | { 10 | index: 2, 11 | bgColor: "#ffe1c0", 12 | titleColor: "#efb77a", 13 | logoColor: "#efb77a", 14 | cursor: "#efb77a", 15 | }, 16 | { 17 | index: 3, 18 | bgColor: "#cacaca", 19 | titleColor: "#fff", 20 | logoColor: "#000", 21 | cursor: "#fff", 22 | }, 23 | ]; 24 | -------------------------------------------------------------------------------- /src/js/utils/index.js: -------------------------------------------------------------------------------- 1 | import Splitter from "./Splitter"; 2 | import colors from "./colorConfig"; 3 | import { preloadImages } from "./preload"; 4 | import Mouse from "./Mouse"; 5 | 6 | const lerp = (a, b, n) => (1 - n) * a + n * b; 7 | 8 | const calculateClipPath = (el) => { 9 | const bounds = el.getBoundingClientRect(); 10 | let pointsArray = []; 11 | let clipPath = [ 12 | [bounds.left, bounds.top], 13 | [bounds.left + bounds.width, bounds.top], 14 | [bounds.left + bounds.width, bounds.top + bounds.height], 15 | [bounds.left, bounds.top + bounds.height], 16 | ]; 17 | pointsArray = clipPath; 18 | clipPath = clipPath 19 | .map((coordinates) => { 20 | return coordinates.map((coordinate) => coordinate + "px").join(" "); 21 | }) 22 | .join(","); 23 | 24 | clipPath = `polygon(${clipPath})`; 25 | return { 26 | clipPath, 27 | pointsArray, 28 | }; 29 | }; 30 | 31 | const getMousePos = (e) => { 32 | let posx = 0; 33 | let posy = 0; 34 | if (!e) e = window.event; 35 | if (e.pageX || e.pageY) { 36 | posx = e.pageX; 37 | posy = e.pageY; 38 | } else if (e.clientX || e.clientY) { 39 | posx = e.clientX + body.scrollLeft + document.documentElement.scrollLeft; 40 | posy = e.clientY + body.scrollTop + document.documentElement.scrollTop; 41 | } 42 | 43 | return { x: posx, y: posy }; 44 | }; 45 | 46 | export { lerp, colors, getMousePos, preloadImages, calculateClipPath, Mouse, Splitter }; 47 | -------------------------------------------------------------------------------- /src/js/utils/preload.js: -------------------------------------------------------------------------------- 1 | import imagesLoaded from "imagesloaded"; 2 | 3 | export function preloadImages(selector) { 4 | return new Promise((resolve, reject) => { 5 | imagesLoaded(selector, { background: true }, resolve); 6 | }); 7 | } 8 | --------------------------------------------------------------------------------