@xdy-npm/react-particle-backgrounds 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +177 -0
- package/dist/index.d.mts +131 -0
- package/dist/index.d.ts +131 -0
- package/dist/index.js +1103 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1081 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +64 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,1081 @@
|
|
|
1
|
+
import { createContext, useState, useEffect, useCallback, useContext, useRef, useMemo } from 'react';
|
|
2
|
+
import Particles, { initParticlesEngine } from '@tsparticles/react';
|
|
3
|
+
import { loadSlim } from '@tsparticles/slim';
|
|
4
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
5
|
+
|
|
6
|
+
// src/components/ParticlesBackground.tsx
|
|
7
|
+
|
|
8
|
+
// src/themes/base.ts
|
|
9
|
+
var baseConfig = {
|
|
10
|
+
fullScreen: {
|
|
11
|
+
enable: true,
|
|
12
|
+
zIndex: 0
|
|
13
|
+
},
|
|
14
|
+
background: {
|
|
15
|
+
color: { value: "transparent" }
|
|
16
|
+
},
|
|
17
|
+
fpsLimit: 120,
|
|
18
|
+
detectRetina: true
|
|
19
|
+
};
|
|
20
|
+
var DEFAULT_COLORS = [
|
|
21
|
+
"#ffb3d9",
|
|
22
|
+
"#f43f5e",
|
|
23
|
+
"#a78bfa",
|
|
24
|
+
"#3b82f6",
|
|
25
|
+
"#10b981",
|
|
26
|
+
"#f59e0b",
|
|
27
|
+
"#ff6b6b",
|
|
28
|
+
"#8b5cf6",
|
|
29
|
+
"#06b6d4",
|
|
30
|
+
"#fb7185"
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
// src/themes/starline.ts
|
|
34
|
+
var starlineTheme = {
|
|
35
|
+
id: "starline",
|
|
36
|
+
name: "Star Links",
|
|
37
|
+
icon: "\u2728",
|
|
38
|
+
description: "Classic particle linking effect",
|
|
39
|
+
backgroundGradient: "linear-gradient(180deg, #0f172a 0%, #1e293b 50%, #334155 100%)",
|
|
40
|
+
options: (isDark) => {
|
|
41
|
+
const colors = DEFAULT_COLORS;
|
|
42
|
+
return {
|
|
43
|
+
...baseConfig,
|
|
44
|
+
interactivity: {
|
|
45
|
+
detectsOn: "window",
|
|
46
|
+
events: {
|
|
47
|
+
onClick: { enable: true, mode: "push" },
|
|
48
|
+
onHover: { enable: true, mode: "grab" },
|
|
49
|
+
resize: { enable: true }
|
|
50
|
+
},
|
|
51
|
+
modes: {
|
|
52
|
+
push: { quantity: 6 },
|
|
53
|
+
grab: {
|
|
54
|
+
distance: 200,
|
|
55
|
+
links: { opacity: 1, color: colors }
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
particles: {
|
|
60
|
+
color: { value: colors },
|
|
61
|
+
links: {
|
|
62
|
+
color: colors,
|
|
63
|
+
distance: 150,
|
|
64
|
+
enable: true,
|
|
65
|
+
opacity: 0.5,
|
|
66
|
+
width: 1
|
|
67
|
+
},
|
|
68
|
+
move: {
|
|
69
|
+
direction: "none",
|
|
70
|
+
enable: true,
|
|
71
|
+
outModes: { default: "out" },
|
|
72
|
+
random: false,
|
|
73
|
+
speed: 2,
|
|
74
|
+
straight: false
|
|
75
|
+
},
|
|
76
|
+
number: {
|
|
77
|
+
density: { enable: true, width: 1920, height: 1080 },
|
|
78
|
+
value: 100
|
|
79
|
+
},
|
|
80
|
+
opacity: { value: 0.7 },
|
|
81
|
+
shape: { type: "circle" },
|
|
82
|
+
size: { value: { min: 2, max: 6 } },
|
|
83
|
+
shadow: {
|
|
84
|
+
blur: 8,
|
|
85
|
+
color: { value: colors },
|
|
86
|
+
enable: true,
|
|
87
|
+
offset: { x: 0, y: 0 }
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
// src/themes/snow.ts
|
|
95
|
+
var snowTheme = {
|
|
96
|
+
id: "snow",
|
|
97
|
+
name: "Snowfall",
|
|
98
|
+
icon: "\u2744\uFE0F",
|
|
99
|
+
description: "Romantic falling snowflakes",
|
|
100
|
+
backgroundGradient: "linear-gradient(180deg, #1e3a5f 0%, #2d4a6b 50%, #3d5a7b 100%)",
|
|
101
|
+
options: (isDark) => ({
|
|
102
|
+
...baseConfig,
|
|
103
|
+
interactivity: {
|
|
104
|
+
detectsOn: "window",
|
|
105
|
+
events: {
|
|
106
|
+
onHover: { enable: true, mode: "repulse" },
|
|
107
|
+
resize: { enable: true }
|
|
108
|
+
},
|
|
109
|
+
modes: {
|
|
110
|
+
repulse: { distance: 100, duration: 0.4 }
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
particles: {
|
|
114
|
+
color: { value: isDark ? "#ffffff" : "#87CEEB" },
|
|
115
|
+
move: {
|
|
116
|
+
direction: "bottom",
|
|
117
|
+
enable: true,
|
|
118
|
+
outModes: { default: "out" },
|
|
119
|
+
speed: { min: 1, max: 3 },
|
|
120
|
+
straight: false,
|
|
121
|
+
drift: { min: -0.5, max: 0.5 }
|
|
122
|
+
},
|
|
123
|
+
number: {
|
|
124
|
+
density: { enable: true, width: 1920, height: 1080 },
|
|
125
|
+
value: 80
|
|
126
|
+
},
|
|
127
|
+
opacity: {
|
|
128
|
+
value: { min: 0.3, max: 0.8 },
|
|
129
|
+
animation: { enable: true, speed: 1, minimumValue: 0.3, sync: false }
|
|
130
|
+
},
|
|
131
|
+
shape: { type: "circle" },
|
|
132
|
+
size: { value: { min: 2, max: 6 } },
|
|
133
|
+
wobble: {
|
|
134
|
+
enable: true,
|
|
135
|
+
distance: 10,
|
|
136
|
+
speed: { min: -5, max: 5 }
|
|
137
|
+
},
|
|
138
|
+
shadow: {
|
|
139
|
+
blur: 5,
|
|
140
|
+
color: { value: isDark ? "#ffffff" : "#87CEEB" },
|
|
141
|
+
enable: true,
|
|
142
|
+
offset: { x: 0, y: 0 }
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
})
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
// src/themes/bubble.ts
|
|
149
|
+
var bubbleTheme = {
|
|
150
|
+
id: "bubble",
|
|
151
|
+
name: "Bubbles",
|
|
152
|
+
icon: "\u{1FAE7}",
|
|
153
|
+
description: "Dreamy rising bubbles",
|
|
154
|
+
backgroundGradient: "linear-gradient(180deg, #0a2647 0%, #144272 50%, #205295 100%)",
|
|
155
|
+
options: (isDark) => ({
|
|
156
|
+
...baseConfig,
|
|
157
|
+
interactivity: {
|
|
158
|
+
detectsOn: "window",
|
|
159
|
+
events: {
|
|
160
|
+
onClick: { enable: true, mode: "pop" },
|
|
161
|
+
onHover: { enable: true, mode: "bubble" },
|
|
162
|
+
resize: { enable: true }
|
|
163
|
+
},
|
|
164
|
+
modes: {
|
|
165
|
+
bubble: { distance: 200, size: 15, duration: 2, opacity: 0.8 },
|
|
166
|
+
pop: {}
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
particles: {
|
|
170
|
+
color: {
|
|
171
|
+
value: isDark ? ["#00d9ff", "#00ff9d", "#ff00e6", "#ffee00"] : ["#ffb3d9", "#ff91c7", "#ffc0e5", "#ffd6e8"]
|
|
172
|
+
},
|
|
173
|
+
move: {
|
|
174
|
+
direction: "top",
|
|
175
|
+
enable: true,
|
|
176
|
+
outModes: { default: "out" },
|
|
177
|
+
speed: { min: 1, max: 2 },
|
|
178
|
+
straight: false
|
|
179
|
+
},
|
|
180
|
+
number: {
|
|
181
|
+
density: { enable: true, width: 1920, height: 1080 },
|
|
182
|
+
value: 50
|
|
183
|
+
},
|
|
184
|
+
opacity: {
|
|
185
|
+
value: { min: 0.2, max: 0.6 },
|
|
186
|
+
animation: { enable: true, speed: 0.5, minimumValue: 0.1, sync: false }
|
|
187
|
+
},
|
|
188
|
+
shape: { type: "circle" },
|
|
189
|
+
size: {
|
|
190
|
+
value: { min: 5, max: 15 },
|
|
191
|
+
animation: { enable: true, speed: 3, minimumValue: 3, sync: false }
|
|
192
|
+
},
|
|
193
|
+
stroke: {
|
|
194
|
+
width: 1,
|
|
195
|
+
color: { value: isDark ? "rgba(255,255,255,0.3)" : "rgba(0,0,0,0.1)" }
|
|
196
|
+
},
|
|
197
|
+
shadow: {
|
|
198
|
+
blur: 10,
|
|
199
|
+
color: { value: isDark ? "#ffb3d9" : "#ff91c7" },
|
|
200
|
+
enable: true,
|
|
201
|
+
offset: { x: 0, y: 0 }
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
})
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
// src/themes/stars.ts
|
|
208
|
+
var starsTheme = {
|
|
209
|
+
id: "stars",
|
|
210
|
+
name: "Twinkling Stars",
|
|
211
|
+
icon: "\u2B50",
|
|
212
|
+
description: "Sparkling starry sky",
|
|
213
|
+
backgroundGradient: "linear-gradient(180deg, #000000 0%, #1a1a2e 50%, #16213e 100%)",
|
|
214
|
+
options: (isDark) => ({
|
|
215
|
+
...baseConfig,
|
|
216
|
+
interactivity: {
|
|
217
|
+
detectsOn: "window",
|
|
218
|
+
events: {
|
|
219
|
+
onClick: { enable: true, mode: "push" },
|
|
220
|
+
onHover: { enable: true, mode: "connect" },
|
|
221
|
+
resize: { enable: true }
|
|
222
|
+
},
|
|
223
|
+
modes: {
|
|
224
|
+
push: { quantity: 3 },
|
|
225
|
+
connect: { distance: 100, links: { opacity: 0.3 }, radius: 150 }
|
|
226
|
+
}
|
|
227
|
+
},
|
|
228
|
+
particles: {
|
|
229
|
+
color: {
|
|
230
|
+
value: isDark ? ["#ffffff", "#ffffd4", "#ffecd2", "#d4f1ff"] : ["#ffd700", "#ffb347", "#ff6b6b", "#4ecdc4"]
|
|
231
|
+
},
|
|
232
|
+
move: {
|
|
233
|
+
direction: "none",
|
|
234
|
+
enable: true,
|
|
235
|
+
outModes: { default: "out" },
|
|
236
|
+
random: true,
|
|
237
|
+
speed: 0.5,
|
|
238
|
+
straight: false
|
|
239
|
+
},
|
|
240
|
+
number: {
|
|
241
|
+
density: { enable: true, width: 1920, height: 1080 },
|
|
242
|
+
value: 120
|
|
243
|
+
},
|
|
244
|
+
opacity: {
|
|
245
|
+
value: { min: 0.2, max: 1 },
|
|
246
|
+
animation: {
|
|
247
|
+
enable: true,
|
|
248
|
+
speed: 1,
|
|
249
|
+
minimumValue: 0.1,
|
|
250
|
+
sync: false
|
|
251
|
+
}
|
|
252
|
+
},
|
|
253
|
+
shape: { type: "star", options: { star: { sides: 5 } } },
|
|
254
|
+
size: { value: { min: 1, max: 4 } },
|
|
255
|
+
twinkle: {
|
|
256
|
+
lines: { enable: false },
|
|
257
|
+
particles: {
|
|
258
|
+
enable: true,
|
|
259
|
+
frequency: 0.05,
|
|
260
|
+
opacity: 1,
|
|
261
|
+
color: { value: isDark ? "#ffffff" : "#ffd700" }
|
|
262
|
+
}
|
|
263
|
+
},
|
|
264
|
+
shadow: {
|
|
265
|
+
blur: 6,
|
|
266
|
+
color: { value: isDark ? "#ffffff" : "#ffd700" },
|
|
267
|
+
enable: true,
|
|
268
|
+
offset: { x: 0, y: 0 }
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
})
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
// src/themes/firefly.ts
|
|
275
|
+
var fireflyTheme = {
|
|
276
|
+
id: "firefly",
|
|
277
|
+
name: "Fireflies",
|
|
278
|
+
icon: "\u{1FAB2}",
|
|
279
|
+
description: "Warm glowing firefly effect",
|
|
280
|
+
backgroundGradient: "linear-gradient(180deg, #1a1a1a 0%, #2d2d2d 50%, #1a1a1a 100%)",
|
|
281
|
+
options: (isDark) => ({
|
|
282
|
+
...baseConfig,
|
|
283
|
+
interactivity: {
|
|
284
|
+
detectsOn: "window",
|
|
285
|
+
events: {
|
|
286
|
+
onHover: { enable: true, mode: "slow" },
|
|
287
|
+
resize: { enable: true }
|
|
288
|
+
},
|
|
289
|
+
modes: {
|
|
290
|
+
slow: { factor: 3, radius: 200 }
|
|
291
|
+
}
|
|
292
|
+
},
|
|
293
|
+
particles: {
|
|
294
|
+
color: {
|
|
295
|
+
value: isDark ? ["#ffff00", "#adff2f", "#7fff00", "#00ff7f"] : ["#ffc107", "#ff9800", "#ff5722", "#4caf50"]
|
|
296
|
+
},
|
|
297
|
+
move: {
|
|
298
|
+
direction: "none",
|
|
299
|
+
enable: true,
|
|
300
|
+
outModes: { default: "bounce" },
|
|
301
|
+
random: true,
|
|
302
|
+
speed: 1,
|
|
303
|
+
straight: false,
|
|
304
|
+
trail: {
|
|
305
|
+
enable: true,
|
|
306
|
+
length: 5,
|
|
307
|
+
fill: { color: "transparent" }
|
|
308
|
+
}
|
|
309
|
+
},
|
|
310
|
+
number: {
|
|
311
|
+
density: { enable: true, width: 1920, height: 1080 },
|
|
312
|
+
value: 40
|
|
313
|
+
},
|
|
314
|
+
opacity: {
|
|
315
|
+
value: { min: 0.3, max: 1 },
|
|
316
|
+
animation: {
|
|
317
|
+
enable: true,
|
|
318
|
+
speed: 2,
|
|
319
|
+
minimumValue: 0.1,
|
|
320
|
+
sync: false
|
|
321
|
+
}
|
|
322
|
+
},
|
|
323
|
+
shape: { type: "circle" },
|
|
324
|
+
size: { value: { min: 2, max: 5 } },
|
|
325
|
+
shadow: {
|
|
326
|
+
blur: 15,
|
|
327
|
+
color: { value: isDark ? "#adff2f" : "#ffc107" },
|
|
328
|
+
enable: true,
|
|
329
|
+
offset: { x: 0, y: 0 }
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
})
|
|
333
|
+
};
|
|
334
|
+
|
|
335
|
+
// src/themes/geometry.ts
|
|
336
|
+
var geometryTheme = {
|
|
337
|
+
id: "geometry",
|
|
338
|
+
name: "Geometry",
|
|
339
|
+
icon: "\u{1F537}",
|
|
340
|
+
description: "Floating abstract geometric shapes",
|
|
341
|
+
backgroundGradient: "linear-gradient(180deg, #0f0c29 0%, #302b63 50%, #24243e 100%)",
|
|
342
|
+
options: (isDark) => ({
|
|
343
|
+
...baseConfig,
|
|
344
|
+
interactivity: {
|
|
345
|
+
detectsOn: "window",
|
|
346
|
+
events: {
|
|
347
|
+
onClick: { enable: true, mode: "push" },
|
|
348
|
+
onHover: { enable: true, mode: "repulse" },
|
|
349
|
+
resize: { enable: true }
|
|
350
|
+
},
|
|
351
|
+
modes: {
|
|
352
|
+
push: { quantity: 2 },
|
|
353
|
+
repulse: { distance: 150, duration: 0.4 }
|
|
354
|
+
}
|
|
355
|
+
},
|
|
356
|
+
particles: {
|
|
357
|
+
color: {
|
|
358
|
+
value: ["#ffb3d9", "#ff91c7", "#ffc0e5", "#ffd6e8"]
|
|
359
|
+
},
|
|
360
|
+
move: {
|
|
361
|
+
direction: "none",
|
|
362
|
+
enable: true,
|
|
363
|
+
outModes: { default: "bounce" },
|
|
364
|
+
random: false,
|
|
365
|
+
speed: 1.5,
|
|
366
|
+
straight: false
|
|
367
|
+
},
|
|
368
|
+
number: {
|
|
369
|
+
density: { enable: true, width: 1920, height: 1080 },
|
|
370
|
+
value: 30
|
|
371
|
+
},
|
|
372
|
+
opacity: {
|
|
373
|
+
value: { min: 0.3, max: 0.7 }
|
|
374
|
+
},
|
|
375
|
+
rotate: {
|
|
376
|
+
value: { min: 0, max: 360 },
|
|
377
|
+
direction: "random",
|
|
378
|
+
animation: { enable: true, speed: 5 }
|
|
379
|
+
},
|
|
380
|
+
shape: {
|
|
381
|
+
type: ["triangle", "square", "polygon"],
|
|
382
|
+
options: {
|
|
383
|
+
polygon: { sides: 6 }
|
|
384
|
+
}
|
|
385
|
+
},
|
|
386
|
+
size: { value: { min: 10, max: 25 } },
|
|
387
|
+
stroke: {
|
|
388
|
+
width: 1,
|
|
389
|
+
color: { value: isDark ? "rgba(255,255,255,0.5)" : "rgba(0,0,0,0.2)" }
|
|
390
|
+
},
|
|
391
|
+
shadow: {
|
|
392
|
+
blur: 10,
|
|
393
|
+
color: { value: isDark ? "#ffb3d9" : "#ff91c7" },
|
|
394
|
+
enable: true,
|
|
395
|
+
offset: { x: 2, y: 2 }
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
})
|
|
399
|
+
};
|
|
400
|
+
|
|
401
|
+
// src/themes/wave.ts
|
|
402
|
+
var waveTheme = {
|
|
403
|
+
id: "wave",
|
|
404
|
+
name: "Particle Ocean",
|
|
405
|
+
icon: "\u{1F30A}",
|
|
406
|
+
description: "3D particle wave effect (requires three.js)",
|
|
407
|
+
isThreeJS: true,
|
|
408
|
+
backgroundGradient: "linear-gradient(180deg, #000000 0%, #0a1628 50%, #0d1f3c 100%)",
|
|
409
|
+
options: () => ({
|
|
410
|
+
...baseConfig,
|
|
411
|
+
particles: {
|
|
412
|
+
number: { value: 0 }
|
|
413
|
+
}
|
|
414
|
+
})
|
|
415
|
+
};
|
|
416
|
+
|
|
417
|
+
// src/themes/index.ts
|
|
418
|
+
var particleThemes = [
|
|
419
|
+
starlineTheme,
|
|
420
|
+
snowTheme,
|
|
421
|
+
bubbleTheme,
|
|
422
|
+
starsTheme,
|
|
423
|
+
fireflyTheme,
|
|
424
|
+
geometryTheme,
|
|
425
|
+
waveTheme
|
|
426
|
+
];
|
|
427
|
+
var getThemeById = (id) => {
|
|
428
|
+
return particleThemes.find((theme) => theme.id === id) || starlineTheme;
|
|
429
|
+
};
|
|
430
|
+
var DEFAULT_THEME_ID = "starline";
|
|
431
|
+
var ParticleContext = createContext(null);
|
|
432
|
+
var STORAGE_KEY = "rpb-theme-id";
|
|
433
|
+
var ParticleProvider = ({
|
|
434
|
+
defaultTheme = DEFAULT_THEME_ID,
|
|
435
|
+
isDark: isDarkProp = true,
|
|
436
|
+
persist = true,
|
|
437
|
+
children
|
|
438
|
+
}) => {
|
|
439
|
+
const [themeId, setThemeId] = useState(() => {
|
|
440
|
+
if (persist && typeof window !== "undefined") {
|
|
441
|
+
return localStorage.getItem(STORAGE_KEY) || defaultTheme;
|
|
442
|
+
}
|
|
443
|
+
return defaultTheme;
|
|
444
|
+
});
|
|
445
|
+
const [isDark, setDark] = useState(isDarkProp);
|
|
446
|
+
useEffect(() => {
|
|
447
|
+
setDark(isDarkProp);
|
|
448
|
+
}, [isDarkProp]);
|
|
449
|
+
const setTheme = useCallback((id) => {
|
|
450
|
+
setThemeId(id);
|
|
451
|
+
if (persist && typeof window !== "undefined") {
|
|
452
|
+
localStorage.setItem(STORAGE_KEY, id);
|
|
453
|
+
}
|
|
454
|
+
}, [persist]);
|
|
455
|
+
return /* @__PURE__ */ jsx(ParticleContext.Provider, { value: { themeId, isDark, setTheme, setDark }, children });
|
|
456
|
+
};
|
|
457
|
+
var useParticleTheme = () => {
|
|
458
|
+
const ctx = useContext(ParticleContext);
|
|
459
|
+
if (!ctx) {
|
|
460
|
+
throw new Error("useParticleTheme must be used within a <ParticleProvider>");
|
|
461
|
+
}
|
|
462
|
+
return ctx;
|
|
463
|
+
};
|
|
464
|
+
var useParticleThemeOptional = () => {
|
|
465
|
+
return useContext(ParticleContext);
|
|
466
|
+
};
|
|
467
|
+
var ParticleWave = ({
|
|
468
|
+
background = "linear-gradient(180deg, #000000 0%, #0a1628 50%, #0d1f3c 100%)",
|
|
469
|
+
className,
|
|
470
|
+
style
|
|
471
|
+
}) => {
|
|
472
|
+
const containerRef = useRef(null);
|
|
473
|
+
const animationRef = useRef();
|
|
474
|
+
const hasThree = useRef(true);
|
|
475
|
+
useEffect(() => {
|
|
476
|
+
let THREE;
|
|
477
|
+
try {
|
|
478
|
+
THREE = globalThis.require ? globalThis.require("three") : (() => {
|
|
479
|
+
throw new Error("no require");
|
|
480
|
+
})();
|
|
481
|
+
} catch (e) {
|
|
482
|
+
hasThree.current = false;
|
|
483
|
+
console.warn('[react-particle-backgrounds] "three" is not installed. The wave theme requires it as a peer dependency.');
|
|
484
|
+
return;
|
|
485
|
+
}
|
|
486
|
+
if (!containerRef.current) return;
|
|
487
|
+
const container = containerRef.current;
|
|
488
|
+
const width = container.clientWidth;
|
|
489
|
+
const height = container.clientHeight;
|
|
490
|
+
const scene = new THREE.Scene();
|
|
491
|
+
scene.background = null;
|
|
492
|
+
const camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 1e3);
|
|
493
|
+
camera.position.set(0, 50, 100);
|
|
494
|
+
camera.lookAt(0, 0, 0);
|
|
495
|
+
const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
|
|
496
|
+
renderer.setSize(width, height);
|
|
497
|
+
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
|
|
498
|
+
container.appendChild(renderer.domElement);
|
|
499
|
+
const particleCount = 15e3;
|
|
500
|
+
const waveWidth = 200;
|
|
501
|
+
const waveDepth = 100;
|
|
502
|
+
const geometry = new THREE.BufferGeometry();
|
|
503
|
+
const positions = new Float32Array(particleCount * 3);
|
|
504
|
+
const colors = new Float32Array(particleCount * 3);
|
|
505
|
+
const sizes = new Float32Array(particleCount);
|
|
506
|
+
for (let i = 0; i < particleCount; i++) {
|
|
507
|
+
const i3 = i * 3;
|
|
508
|
+
positions[i3] = (Math.random() - 0.5) * waveWidth;
|
|
509
|
+
positions[i3 + 1] = 0;
|
|
510
|
+
positions[i3 + 2] = (Math.random() - 0.5) * waveDepth;
|
|
511
|
+
const colorChoice = Math.random();
|
|
512
|
+
if (colorChoice < 0.5) {
|
|
513
|
+
colors[i3] = 0;
|
|
514
|
+
colors[i3 + 1] = 0.8 + Math.random() * 0.2;
|
|
515
|
+
colors[i3 + 2] = 1;
|
|
516
|
+
} else if (colorChoice < 0.8) {
|
|
517
|
+
colors[i3] = 0.1;
|
|
518
|
+
colors[i3 + 1] = 0.3 + Math.random() * 0.3;
|
|
519
|
+
colors[i3 + 2] = 0.9 + Math.random() * 0.1;
|
|
520
|
+
} else {
|
|
521
|
+
colors[i3] = 0.8 + Math.random() * 0.2;
|
|
522
|
+
colors[i3 + 1] = 0.9 + Math.random() * 0.1;
|
|
523
|
+
colors[i3 + 2] = 1;
|
|
524
|
+
}
|
|
525
|
+
sizes[i] = Math.random() * 2 + 0.5;
|
|
526
|
+
}
|
|
527
|
+
geometry.setAttribute("position", new THREE.BufferAttribute(positions, 3));
|
|
528
|
+
geometry.setAttribute("color", new THREE.BufferAttribute(colors, 3));
|
|
529
|
+
geometry.setAttribute("size", new THREE.BufferAttribute(sizes, 1));
|
|
530
|
+
const vertexShader = `
|
|
531
|
+
attribute float size;
|
|
532
|
+
varying vec3 vColor;
|
|
533
|
+
void main() {
|
|
534
|
+
vColor = color;
|
|
535
|
+
vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
|
|
536
|
+
gl_PointSize = size * (300.0 / -mvPosition.z);
|
|
537
|
+
gl_Position = projectionMatrix * mvPosition;
|
|
538
|
+
}
|
|
539
|
+
`;
|
|
540
|
+
const fragmentShader = `
|
|
541
|
+
varying vec3 vColor;
|
|
542
|
+
void main() {
|
|
543
|
+
float dist = length(gl_PointCoord - vec2(0.5));
|
|
544
|
+
if (dist > 0.5) discard;
|
|
545
|
+
float alpha = 1.0 - smoothstep(0.0, 0.5, dist);
|
|
546
|
+
float glow = exp(-dist * 3.0);
|
|
547
|
+
vec3 finalColor = vColor + glow * 0.5;
|
|
548
|
+
gl_FragColor = vec4(finalColor, alpha * 0.8);
|
|
549
|
+
}
|
|
550
|
+
`;
|
|
551
|
+
const material = new THREE.ShaderMaterial({
|
|
552
|
+
vertexShader,
|
|
553
|
+
fragmentShader,
|
|
554
|
+
transparent: true,
|
|
555
|
+
vertexColors: true,
|
|
556
|
+
blending: THREE.AdditiveBlending,
|
|
557
|
+
depthWrite: false
|
|
558
|
+
});
|
|
559
|
+
const particles = new THREE.Points(geometry, material);
|
|
560
|
+
scene.add(particles);
|
|
561
|
+
const bokehCount = 100;
|
|
562
|
+
const bokehGeometry = new THREE.BufferGeometry();
|
|
563
|
+
const bokehPositions = new Float32Array(bokehCount * 3);
|
|
564
|
+
const bokehColors = new Float32Array(bokehCount * 3);
|
|
565
|
+
const bokehSizes = new Float32Array(bokehCount);
|
|
566
|
+
for (let i = 0; i < bokehCount; i++) {
|
|
567
|
+
const i3 = i * 3;
|
|
568
|
+
bokehPositions[i3] = (Math.random() - 0.5) * waveWidth * 1.5;
|
|
569
|
+
bokehPositions[i3 + 1] = Math.random() * -30 - 10;
|
|
570
|
+
bokehPositions[i3 + 2] = (Math.random() - 0.5) * waveDepth * 2;
|
|
571
|
+
bokehColors[i3] = 0.2;
|
|
572
|
+
bokehColors[i3 + 1] = 0.5 + Math.random() * 0.3;
|
|
573
|
+
bokehColors[i3 + 2] = 1;
|
|
574
|
+
bokehSizes[i] = Math.random() * 15 + 8;
|
|
575
|
+
}
|
|
576
|
+
bokehGeometry.setAttribute("position", new THREE.BufferAttribute(bokehPositions, 3));
|
|
577
|
+
bokehGeometry.setAttribute("color", new THREE.BufferAttribute(bokehColors, 3));
|
|
578
|
+
bokehGeometry.setAttribute("size", new THREE.BufferAttribute(bokehSizes, 1));
|
|
579
|
+
const bokehMaterial = new THREE.ShaderMaterial({
|
|
580
|
+
vertexShader,
|
|
581
|
+
fragmentShader: `
|
|
582
|
+
varying vec3 vColor;
|
|
583
|
+
void main() {
|
|
584
|
+
float dist = length(gl_PointCoord - vec2(0.5));
|
|
585
|
+
if (dist > 0.5) discard;
|
|
586
|
+
float alpha = 1.0 - smoothstep(0.2, 0.5, dist);
|
|
587
|
+
gl_FragColor = vec4(vColor, alpha * 0.3);
|
|
588
|
+
}
|
|
589
|
+
`,
|
|
590
|
+
transparent: true,
|
|
591
|
+
vertexColors: true,
|
|
592
|
+
blending: THREE.AdditiveBlending,
|
|
593
|
+
depthWrite: false
|
|
594
|
+
});
|
|
595
|
+
const bokehParticles = new THREE.Points(bokehGeometry, bokehMaterial);
|
|
596
|
+
scene.add(bokehParticles);
|
|
597
|
+
const dropCount = 150;
|
|
598
|
+
const trailLength = 12;
|
|
599
|
+
const rainDrops = [];
|
|
600
|
+
for (let i = 0; i < dropCount; i++) {
|
|
601
|
+
const shouldActivate = Math.random() < 0.1;
|
|
602
|
+
const x = (Math.random() - 0.5) * waveWidth * 0.9;
|
|
603
|
+
const z = (Math.random() - 0.5) * waveDepth * 0.7;
|
|
604
|
+
const waveHeight = Math.sin(x * 0.05) * 8 + Math.sin(z * 0.08) * 5;
|
|
605
|
+
const startHeight = shouldActivate ? waveHeight + Math.random() * 40 : -200;
|
|
606
|
+
rainDrops.push({
|
|
607
|
+
x,
|
|
608
|
+
z,
|
|
609
|
+
y: startHeight,
|
|
610
|
+
velocity: shouldActivate ? 0.5 + Math.random() * 0.7 : 0,
|
|
611
|
+
active: shouldActivate,
|
|
612
|
+
maxHeight: waveHeight + 80 + Math.random() * 120,
|
|
613
|
+
trail: new Array(trailLength).fill(startHeight),
|
|
614
|
+
opacity: shouldActivate ? 1 : 0
|
|
615
|
+
});
|
|
616
|
+
}
|
|
617
|
+
const trailPointCount = dropCount * trailLength;
|
|
618
|
+
const dropTrailGeometry = new THREE.BufferGeometry();
|
|
619
|
+
const dropTrailPositions = new Float32Array(trailPointCount * 3);
|
|
620
|
+
const dropTrailColors = new Float32Array(trailPointCount * 3);
|
|
621
|
+
const dropTrailSizes = new Float32Array(trailPointCount);
|
|
622
|
+
for (let i = 0; i < dropCount; i++) {
|
|
623
|
+
for (let j = 0; j < trailLength; j++) {
|
|
624
|
+
dropTrailSizes[i * trailLength + j] = 4 * (1 - j / trailLength) * 0.5;
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
dropTrailGeometry.setAttribute("position", new THREE.BufferAttribute(dropTrailPositions, 3));
|
|
628
|
+
dropTrailGeometry.setAttribute("color", new THREE.BufferAttribute(dropTrailColors, 3));
|
|
629
|
+
dropTrailGeometry.setAttribute("size", new THREE.BufferAttribute(dropTrailSizes, 1));
|
|
630
|
+
const dropTrailMaterial = new THREE.ShaderMaterial({
|
|
631
|
+
vertexShader,
|
|
632
|
+
fragmentShader: `
|
|
633
|
+
varying vec3 vColor;
|
|
634
|
+
void main() {
|
|
635
|
+
float dist = length(gl_PointCoord - vec2(0.5));
|
|
636
|
+
if (dist > 0.5) discard;
|
|
637
|
+
float alpha = 1.0 - smoothstep(0.0, 0.5, dist);
|
|
638
|
+
gl_FragColor = vec4(vColor, alpha * 0.8);
|
|
639
|
+
}
|
|
640
|
+
`,
|
|
641
|
+
transparent: true,
|
|
642
|
+
vertexColors: true,
|
|
643
|
+
blending: THREE.AdditiveBlending,
|
|
644
|
+
depthWrite: false
|
|
645
|
+
});
|
|
646
|
+
const dropTrailParticles = new THREE.Points(dropTrailGeometry, dropTrailMaterial);
|
|
647
|
+
scene.add(dropTrailParticles);
|
|
648
|
+
const dropHeadGeometry = new THREE.BufferGeometry();
|
|
649
|
+
const dropHeadPositions = new Float32Array(dropCount * 3);
|
|
650
|
+
const dropHeadColors = new Float32Array(dropCount * 3);
|
|
651
|
+
const dropHeadSizes = new Float32Array(dropCount);
|
|
652
|
+
for (let i = 0; i < dropCount; i++) {
|
|
653
|
+
dropHeadSizes[i] = (6 + Math.random() * 4) * 0.5;
|
|
654
|
+
}
|
|
655
|
+
dropHeadGeometry.setAttribute("position", new THREE.BufferAttribute(dropHeadPositions, 3));
|
|
656
|
+
dropHeadGeometry.setAttribute("color", new THREE.BufferAttribute(dropHeadColors, 3));
|
|
657
|
+
dropHeadGeometry.setAttribute("size", new THREE.BufferAttribute(dropHeadSizes, 1));
|
|
658
|
+
const dropHeadMaterial = new THREE.ShaderMaterial({
|
|
659
|
+
vertexShader,
|
|
660
|
+
fragmentShader: `
|
|
661
|
+
varying vec3 vColor;
|
|
662
|
+
void main() {
|
|
663
|
+
float dist = length(gl_PointCoord - vec2(0.5));
|
|
664
|
+
if (dist > 0.5) discard;
|
|
665
|
+
float alpha = 1.0 - smoothstep(0.0, 0.5, dist);
|
|
666
|
+
float glow = exp(-dist * 2.0);
|
|
667
|
+
vec3 finalColor = vColor + glow * 0.8;
|
|
668
|
+
gl_FragColor = vec4(finalColor, alpha);
|
|
669
|
+
}
|
|
670
|
+
`,
|
|
671
|
+
transparent: true,
|
|
672
|
+
vertexColors: true,
|
|
673
|
+
blending: THREE.AdditiveBlending,
|
|
674
|
+
depthWrite: false
|
|
675
|
+
});
|
|
676
|
+
const dropHeadParticles = new THREE.Points(dropHeadGeometry, dropHeadMaterial);
|
|
677
|
+
scene.add(dropHeadParticles);
|
|
678
|
+
let time = 0;
|
|
679
|
+
let lastSpawnTime = 0;
|
|
680
|
+
const getWaveHeight = (x, z, t) => Math.sin(x * 0.05 + t) * 8 + Math.sin(z * 0.08 + t * 0.8) * 5 + Math.sin((x + z) * 0.03 + t * 1.2) * 3;
|
|
681
|
+
const activateDrop = (drop) => {
|
|
682
|
+
drop.x = (Math.random() - 0.5) * waveWidth * 0.9;
|
|
683
|
+
drop.z = (Math.random() - 0.5) * waveDepth * 0.7;
|
|
684
|
+
const wh = getWaveHeight(drop.x, drop.z, time);
|
|
685
|
+
drop.y = wh;
|
|
686
|
+
drop.velocity = 0.5 + Math.random() * 0.7;
|
|
687
|
+
drop.maxHeight = wh + 80 + Math.random() * 120;
|
|
688
|
+
drop.active = true;
|
|
689
|
+
drop.opacity = 0.5;
|
|
690
|
+
drop.trail.fill(wh);
|
|
691
|
+
};
|
|
692
|
+
const animate = () => {
|
|
693
|
+
time += 0.02;
|
|
694
|
+
const wavePos = particles.geometry.attributes.position.array;
|
|
695
|
+
for (let i = 0; i < particleCount; i++) {
|
|
696
|
+
const i3 = i * 3;
|
|
697
|
+
wavePos[i3 + 1] = getWaveHeight(wavePos[i3], wavePos[i3 + 2], time);
|
|
698
|
+
}
|
|
699
|
+
particles.geometry.attributes.position.needsUpdate = true;
|
|
700
|
+
const tPos = dropTrailParticles.geometry.attributes.position.array;
|
|
701
|
+
const tCol = dropTrailParticles.geometry.attributes.color.array;
|
|
702
|
+
const hPos = dropHeadParticles.geometry.attributes.position.array;
|
|
703
|
+
const hCol = dropHeadParticles.geometry.attributes.color.array;
|
|
704
|
+
let activeCount = 0;
|
|
705
|
+
const inactiveIndices = [];
|
|
706
|
+
for (let i = 0; i < dropCount; i++) {
|
|
707
|
+
const drop = rainDrops[i];
|
|
708
|
+
if (drop.active) {
|
|
709
|
+
activeCount++;
|
|
710
|
+
for (let j = trailLength - 1; j > 0; j--) drop.trail[j] = drop.trail[j - 1];
|
|
711
|
+
drop.trail[0] = drop.y;
|
|
712
|
+
drop.velocity = Math.max(drop.velocity * 0.995, 0.3);
|
|
713
|
+
drop.y += drop.velocity;
|
|
714
|
+
if (drop.opacity < 1) drop.opacity = Math.min(drop.opacity + 0.05, 1);
|
|
715
|
+
if (drop.y > drop.maxHeight) {
|
|
716
|
+
drop.opacity -= 0.03;
|
|
717
|
+
if (drop.opacity <= 0) {
|
|
718
|
+
drop.active = false;
|
|
719
|
+
drop.y = -200;
|
|
720
|
+
drop.trail.fill(-200);
|
|
721
|
+
inactiveIndices.push(i);
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
} else {
|
|
725
|
+
inactiveIndices.push(i);
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
if (time - lastSpawnTime >= 0.1 && inactiveIndices.length > 0) {
|
|
729
|
+
const spawnCount = Math.min(2 + Math.floor(Math.random() * 2), inactiveIndices.length);
|
|
730
|
+
const shuffled = [...inactiveIndices].sort(() => Math.random() - 0.5);
|
|
731
|
+
for (let n = 0; n < spawnCount; n++) activateDrop(rainDrops[shuffled[n]]);
|
|
732
|
+
lastSpawnTime = time;
|
|
733
|
+
}
|
|
734
|
+
const targetActive = 20;
|
|
735
|
+
const needActivate = Math.max(3, targetActive - activeCount);
|
|
736
|
+
const remaining = inactiveIndices.filter((i) => !rainDrops[i].active);
|
|
737
|
+
if (remaining.length > 0) {
|
|
738
|
+
const shuffled = [...remaining].sort(() => Math.random() - 0.5);
|
|
739
|
+
for (let n = 0; n < Math.min(needActivate, shuffled.length); n++) activateDrop(rainDrops[shuffled[n]]);
|
|
740
|
+
}
|
|
741
|
+
for (let i = 0; i < dropCount; i++) {
|
|
742
|
+
if (!rainDrops[i].active && Math.random() < 0.25) activateDrop(rainDrops[i]);
|
|
743
|
+
}
|
|
744
|
+
for (let i = 0; i < dropCount; i++) {
|
|
745
|
+
const drop = rainDrops[i];
|
|
746
|
+
const hi3 = i * 3;
|
|
747
|
+
hPos[hi3] = drop.x;
|
|
748
|
+
hPos[hi3 + 1] = drop.y;
|
|
749
|
+
hPos[hi3 + 2] = drop.z;
|
|
750
|
+
const brightness = drop.active ? 0.8 + Math.sin(time * 5 + i) * 0.2 : 0;
|
|
751
|
+
hCol[hi3] = 0.5 * brightness * drop.opacity;
|
|
752
|
+
hCol[hi3 + 1] = 1 * brightness * drop.opacity;
|
|
753
|
+
hCol[hi3 + 2] = 1 * brightness * drop.opacity;
|
|
754
|
+
for (let j = 0; j < trailLength; j++) {
|
|
755
|
+
const pi = (i * trailLength + j) * 3;
|
|
756
|
+
tPos[pi] = drop.x;
|
|
757
|
+
tPos[pi + 1] = drop.trail[j];
|
|
758
|
+
tPos[pi + 2] = drop.z;
|
|
759
|
+
const fade = 1 - j / trailLength;
|
|
760
|
+
tCol[pi] = 0.6 * fade * drop.opacity;
|
|
761
|
+
tCol[pi + 1] = 1 * fade * drop.opacity;
|
|
762
|
+
tCol[pi + 2] = 1 * fade * drop.opacity;
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
dropTrailParticles.geometry.attributes.position.needsUpdate = true;
|
|
766
|
+
dropTrailParticles.geometry.attributes.color.needsUpdate = true;
|
|
767
|
+
dropHeadParticles.geometry.attributes.position.needsUpdate = true;
|
|
768
|
+
dropHeadParticles.geometry.attributes.color.needsUpdate = true;
|
|
769
|
+
camera.position.x = Math.sin(time * 0.3) * 5;
|
|
770
|
+
camera.lookAt(0, 0, 0);
|
|
771
|
+
renderer.render(scene, camera);
|
|
772
|
+
animationRef.current = requestAnimationFrame(animate);
|
|
773
|
+
};
|
|
774
|
+
animate();
|
|
775
|
+
const handleResize = () => {
|
|
776
|
+
const w = container.clientWidth;
|
|
777
|
+
const h = container.clientHeight;
|
|
778
|
+
camera.aspect = w / h;
|
|
779
|
+
camera.updateProjectionMatrix();
|
|
780
|
+
renderer.setSize(w, h);
|
|
781
|
+
};
|
|
782
|
+
window.addEventListener("resize", handleResize);
|
|
783
|
+
return () => {
|
|
784
|
+
window.removeEventListener("resize", handleResize);
|
|
785
|
+
if (animationRef.current) cancelAnimationFrame(animationRef.current);
|
|
786
|
+
container.removeChild(renderer.domElement);
|
|
787
|
+
geometry.dispose();
|
|
788
|
+
material.dispose();
|
|
789
|
+
bokehGeometry.dispose();
|
|
790
|
+
bokehMaterial.dispose();
|
|
791
|
+
dropTrailGeometry.dispose();
|
|
792
|
+
dropTrailMaterial.dispose();
|
|
793
|
+
dropHeadGeometry.dispose();
|
|
794
|
+
dropHeadMaterial.dispose();
|
|
795
|
+
renderer.dispose();
|
|
796
|
+
};
|
|
797
|
+
}, [background]);
|
|
798
|
+
return /* @__PURE__ */ jsx(
|
|
799
|
+
"div",
|
|
800
|
+
{
|
|
801
|
+
ref: containerRef,
|
|
802
|
+
className,
|
|
803
|
+
style: {
|
|
804
|
+
position: "fixed",
|
|
805
|
+
top: 0,
|
|
806
|
+
left: 0,
|
|
807
|
+
width: "100%",
|
|
808
|
+
height: "100%",
|
|
809
|
+
zIndex: 1,
|
|
810
|
+
pointerEvents: "none",
|
|
811
|
+
background,
|
|
812
|
+
...style
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
);
|
|
816
|
+
};
|
|
817
|
+
var ParticleWave_default = ParticleWave;
|
|
818
|
+
var ParticlesBackground = ({
|
|
819
|
+
theme: themeProp,
|
|
820
|
+
isDark: isDarkProp,
|
|
821
|
+
onLoaded,
|
|
822
|
+
className,
|
|
823
|
+
style
|
|
824
|
+
}) => {
|
|
825
|
+
var _a, _b;
|
|
826
|
+
const [init, setInit] = useState(false);
|
|
827
|
+
const ctx = useParticleThemeOptional();
|
|
828
|
+
const themeId = (_a = themeProp != null ? themeProp : ctx == null ? void 0 : ctx.themeId) != null ? _a : DEFAULT_THEME_ID;
|
|
829
|
+
const isDark = (_b = isDarkProp != null ? isDarkProp : ctx == null ? void 0 : ctx.isDark) != null ? _b : true;
|
|
830
|
+
const theme = getThemeById(themeId);
|
|
831
|
+
useEffect(() => {
|
|
832
|
+
initParticlesEngine(async (engine) => {
|
|
833
|
+
await loadSlim(engine);
|
|
834
|
+
}).then(() => {
|
|
835
|
+
setInit(true);
|
|
836
|
+
}).catch(() => {
|
|
837
|
+
setInit(true);
|
|
838
|
+
});
|
|
839
|
+
}, []);
|
|
840
|
+
const options = useMemo(() => theme.options(isDark), [theme, isDark]);
|
|
841
|
+
if (themeId === "none") return null;
|
|
842
|
+
if (theme.isThreeJS) {
|
|
843
|
+
return /* @__PURE__ */ jsx(
|
|
844
|
+
ParticleWave_default,
|
|
845
|
+
{
|
|
846
|
+
background: theme.backgroundGradient || theme.backgroundColor,
|
|
847
|
+
className,
|
|
848
|
+
style
|
|
849
|
+
}
|
|
850
|
+
);
|
|
851
|
+
}
|
|
852
|
+
if (!init) return null;
|
|
853
|
+
return /* @__PURE__ */ jsx(
|
|
854
|
+
Particles,
|
|
855
|
+
{
|
|
856
|
+
id: "rpb-tsparticles",
|
|
857
|
+
className,
|
|
858
|
+
style,
|
|
859
|
+
particlesLoaded: async (container) => onLoaded == null ? void 0 : onLoaded(container),
|
|
860
|
+
options
|
|
861
|
+
},
|
|
862
|
+
themeId
|
|
863
|
+
);
|
|
864
|
+
};
|
|
865
|
+
var ParticlesBackground_default = ParticlesBackground;
|
|
866
|
+
var ThemeSelector = ({
|
|
867
|
+
position = "bottom-right",
|
|
868
|
+
accentColor = "#3b82f6"
|
|
869
|
+
}) => {
|
|
870
|
+
const [open, setOpen] = useState(false);
|
|
871
|
+
const { themeId, setTheme } = useParticleTheme();
|
|
872
|
+
const currentTheme = getThemeById(themeId);
|
|
873
|
+
const positionStyles = {
|
|
874
|
+
"bottom-right": { bottom: 80, right: 16 },
|
|
875
|
+
"bottom-left": { bottom: 80, left: 16 },
|
|
876
|
+
"top-right": { top: 80, right: 16 },
|
|
877
|
+
"top-left": { top: 80, left: 16 }
|
|
878
|
+
};
|
|
879
|
+
const drawerSide = position.includes("right") ? "right" : "left";
|
|
880
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
881
|
+
/* @__PURE__ */ jsx(
|
|
882
|
+
"button",
|
|
883
|
+
{
|
|
884
|
+
onClick: () => setOpen(true),
|
|
885
|
+
title: "Theme Settings",
|
|
886
|
+
style: {
|
|
887
|
+
position: "fixed",
|
|
888
|
+
...positionStyles[position],
|
|
889
|
+
zIndex: 9999,
|
|
890
|
+
width: 44,
|
|
891
|
+
height: 44,
|
|
892
|
+
borderRadius: 12,
|
|
893
|
+
display: "flex",
|
|
894
|
+
alignItems: "center",
|
|
895
|
+
justifyContent: "center",
|
|
896
|
+
background: "rgba(255, 255, 255, 0.7)",
|
|
897
|
+
backdropFilter: "blur(12px)",
|
|
898
|
+
WebkitBackdropFilter: "blur(12px)",
|
|
899
|
+
border: "1px solid rgba(255, 255, 255, 0.5)",
|
|
900
|
+
boxShadow: "0 4px 20px rgba(0, 0, 0, 0.08)",
|
|
901
|
+
cursor: "pointer",
|
|
902
|
+
fontSize: 20,
|
|
903
|
+
transition: "transform 0.3s, box-shadow 0.3s"
|
|
904
|
+
},
|
|
905
|
+
onMouseEnter: (e) => {
|
|
906
|
+
e.currentTarget.style.transform = "scale(1.05) translateY(-2px)";
|
|
907
|
+
},
|
|
908
|
+
onMouseLeave: (e) => {
|
|
909
|
+
e.currentTarget.style.transform = "";
|
|
910
|
+
},
|
|
911
|
+
children: currentTheme.icon
|
|
912
|
+
}
|
|
913
|
+
),
|
|
914
|
+
open && /* @__PURE__ */ jsx(
|
|
915
|
+
"div",
|
|
916
|
+
{
|
|
917
|
+
onClick: () => setOpen(false),
|
|
918
|
+
style: {
|
|
919
|
+
position: "fixed",
|
|
920
|
+
inset: 0,
|
|
921
|
+
zIndex: 1e4,
|
|
922
|
+
background: "rgba(0, 0, 0, 0.3)",
|
|
923
|
+
transition: "opacity 0.3s"
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
),
|
|
927
|
+
/* @__PURE__ */ jsxs(
|
|
928
|
+
"div",
|
|
929
|
+
{
|
|
930
|
+
style: {
|
|
931
|
+
position: "fixed",
|
|
932
|
+
top: 0,
|
|
933
|
+
[drawerSide]: 0,
|
|
934
|
+
width: 320,
|
|
935
|
+
maxWidth: "85vw",
|
|
936
|
+
height: "100vh",
|
|
937
|
+
zIndex: 10001,
|
|
938
|
+
background: "#fff",
|
|
939
|
+
boxShadow: "-4px 0 24px rgba(0, 0, 0, 0.12)",
|
|
940
|
+
transform: open ? "translateX(0)" : `translateX(${drawerSide === "right" ? "100%" : "-100%"})`,
|
|
941
|
+
transition: "transform 0.3s ease",
|
|
942
|
+
overflowY: "auto",
|
|
943
|
+
display: "flex",
|
|
944
|
+
flexDirection: "column"
|
|
945
|
+
},
|
|
946
|
+
children: [
|
|
947
|
+
/* @__PURE__ */ jsxs(
|
|
948
|
+
"div",
|
|
949
|
+
{
|
|
950
|
+
style: {
|
|
951
|
+
display: "flex",
|
|
952
|
+
alignItems: "center",
|
|
953
|
+
justifyContent: "space-between",
|
|
954
|
+
padding: "16px 20px",
|
|
955
|
+
borderBottom: "1px solid #f0f0f0"
|
|
956
|
+
},
|
|
957
|
+
children: [
|
|
958
|
+
/* @__PURE__ */ jsx("span", { style: { fontWeight: 600, fontSize: 16 }, children: "Particle Theme" }),
|
|
959
|
+
/* @__PURE__ */ jsx(
|
|
960
|
+
"button",
|
|
961
|
+
{
|
|
962
|
+
onClick: () => setOpen(false),
|
|
963
|
+
style: {
|
|
964
|
+
background: "none",
|
|
965
|
+
border: "none",
|
|
966
|
+
fontSize: 20,
|
|
967
|
+
cursor: "pointer",
|
|
968
|
+
color: "#999",
|
|
969
|
+
padding: 4
|
|
970
|
+
},
|
|
971
|
+
children: "\xD7"
|
|
972
|
+
}
|
|
973
|
+
)
|
|
974
|
+
]
|
|
975
|
+
}
|
|
976
|
+
),
|
|
977
|
+
/* @__PURE__ */ jsx("div", { style: { padding: 16, display: "flex", flexDirection: "column", gap: 12 }, children: [...particleThemes, {
|
|
978
|
+
id: "none",
|
|
979
|
+
name: "None",
|
|
980
|
+
icon: "\u{1F6AB}",
|
|
981
|
+
description: "Disable particle effects"
|
|
982
|
+
}].map((theme) => {
|
|
983
|
+
const isActive = theme.id === themeId;
|
|
984
|
+
return /* @__PURE__ */ jsxs(
|
|
985
|
+
"div",
|
|
986
|
+
{
|
|
987
|
+
onClick: () => setTheme(theme.id),
|
|
988
|
+
style: {
|
|
989
|
+
padding: 16,
|
|
990
|
+
borderRadius: 12,
|
|
991
|
+
cursor: "pointer",
|
|
992
|
+
display: "flex",
|
|
993
|
+
alignItems: "center",
|
|
994
|
+
gap: 12,
|
|
995
|
+
transition: "all 0.2s",
|
|
996
|
+
border: `2px solid ${isActive ? accentColor : "transparent"}`,
|
|
997
|
+
background: isActive ? `${accentColor}10` : "#f5f5f5"
|
|
998
|
+
},
|
|
999
|
+
onMouseEnter: (e) => {
|
|
1000
|
+
if (!isActive) e.currentTarget.style.borderColor = "#e0e0e0";
|
|
1001
|
+
},
|
|
1002
|
+
onMouseLeave: (e) => {
|
|
1003
|
+
if (!isActive) e.currentTarget.style.borderColor = "transparent";
|
|
1004
|
+
},
|
|
1005
|
+
children: [
|
|
1006
|
+
/* @__PURE__ */ jsx(
|
|
1007
|
+
"div",
|
|
1008
|
+
{
|
|
1009
|
+
style: {
|
|
1010
|
+
width: 48,
|
|
1011
|
+
height: 48,
|
|
1012
|
+
borderRadius: 12,
|
|
1013
|
+
display: "flex",
|
|
1014
|
+
alignItems: "center",
|
|
1015
|
+
justifyContent: "center",
|
|
1016
|
+
fontSize: 24,
|
|
1017
|
+
background: isActive ? accentColor : "#e5e5e5",
|
|
1018
|
+
flexShrink: 0
|
|
1019
|
+
},
|
|
1020
|
+
children: theme.icon
|
|
1021
|
+
}
|
|
1022
|
+
),
|
|
1023
|
+
/* @__PURE__ */ jsxs("div", { style: { flex: 1, minWidth: 0 }, children: [
|
|
1024
|
+
/* @__PURE__ */ jsx(
|
|
1025
|
+
"div",
|
|
1026
|
+
{
|
|
1027
|
+
style: {
|
|
1028
|
+
fontWeight: 600,
|
|
1029
|
+
fontSize: 14,
|
|
1030
|
+
color: isActive ? accentColor : "#1f2937"
|
|
1031
|
+
},
|
|
1032
|
+
children: theme.name
|
|
1033
|
+
}
|
|
1034
|
+
),
|
|
1035
|
+
/* @__PURE__ */ jsx("div", { style: { fontSize: 12, color: "#9ca3af", marginTop: 2 }, children: theme.description })
|
|
1036
|
+
] }),
|
|
1037
|
+
isActive && /* @__PURE__ */ jsx(
|
|
1038
|
+
"div",
|
|
1039
|
+
{
|
|
1040
|
+
style: {
|
|
1041
|
+
width: 24,
|
|
1042
|
+
height: 24,
|
|
1043
|
+
borderRadius: "50%",
|
|
1044
|
+
background: accentColor,
|
|
1045
|
+
display: "flex",
|
|
1046
|
+
alignItems: "center",
|
|
1047
|
+
justifyContent: "center",
|
|
1048
|
+
flexShrink: 0
|
|
1049
|
+
},
|
|
1050
|
+
children: /* @__PURE__ */ jsx("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "#fff", strokeWidth: "3", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M5 13l4 4L19 7" }) })
|
|
1051
|
+
}
|
|
1052
|
+
)
|
|
1053
|
+
]
|
|
1054
|
+
},
|
|
1055
|
+
theme.id
|
|
1056
|
+
);
|
|
1057
|
+
}) }),
|
|
1058
|
+
/* @__PURE__ */ jsx("div", { style: { padding: "0 16px 16px", marginTop: "auto" }, children: /* @__PURE__ */ jsx(
|
|
1059
|
+
"div",
|
|
1060
|
+
{
|
|
1061
|
+
style: {
|
|
1062
|
+
padding: 16,
|
|
1063
|
+
background: "#f9fafb",
|
|
1064
|
+
borderRadius: 12,
|
|
1065
|
+
fontSize: 13,
|
|
1066
|
+
color: "#6b7280",
|
|
1067
|
+
lineHeight: 1.6
|
|
1068
|
+
},
|
|
1069
|
+
children: "Your theme selection is automatically saved and will be remembered on your next visit."
|
|
1070
|
+
}
|
|
1071
|
+
) })
|
|
1072
|
+
]
|
|
1073
|
+
}
|
|
1074
|
+
)
|
|
1075
|
+
] });
|
|
1076
|
+
};
|
|
1077
|
+
var ThemeSelector_default = ThemeSelector;
|
|
1078
|
+
|
|
1079
|
+
export { DEFAULT_COLORS, DEFAULT_THEME_ID, ParticleProvider, ParticleWave_default as ParticleWave, ParticlesBackground_default as ParticlesBackground, ThemeSelector_default as ThemeSelector, baseConfig, bubbleTheme, fireflyTheme, geometryTheme, getThemeById, particleThemes, snowTheme, starlineTheme, starsTheme, useParticleTheme, waveTheme };
|
|
1080
|
+
//# sourceMappingURL=index.mjs.map
|
|
1081
|
+
//# sourceMappingURL=index.mjs.map
|