apex-ui-kit 2.6.0 → 2.7.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/ReadMe.md +22 -10
- package/dist/ApexUI-Kit/templates/AccordionMarquee/AccordionMarquee.jsx +340 -161
- package/dist/ApexUI-Kit/templates/AnimatedTabs/AnimatedTabs.jsx +1 -1
- package/dist/ApexUI-Kit/templates/ArcGallery/ArcGallery.jsx +356 -0
- package/dist/ApexUI-Kit/templates/BounceCards/BounceCards.jsx +22 -2
- package/dist/ApexUI-Kit/templates/CircularCarousel/CircularCarousel.jsx +381 -0
- package/dist/ApexUI-Kit/templates/EdgeBlur/EdgeBlur.jsx +92 -0
- package/dist/ApexUI-Kit/templates/FlipClock/FlipClock.jsx +5 -1
- package/dist/ApexUI-Kit/templates/GooeyNav/GooeyNav.jsx +2 -2
- package/dist/ApexUI-Kit/templates/HorizonGlow/HorizonGlow.jsx +259 -0
- package/dist/ApexUI-Kit/templates/MagneticButton/MagneticButton.jsx +69 -0
- package/dist/ApexUI-Kit/templates/Marquee3D/Marquee3D.jsx +68 -0
- package/dist/ApexUI-Kit/templates/NavDropDown/NavDropDown.jsx +123 -1
- package/dist/ApexUI-Kit/templates/ParticleText/ParticleText.jsx +328 -0
- package/dist/ApexUI-Kit/templates/RadialMenu/RadialMenu.jsx +103 -0
- package/dist/ApexUI-Kit/templates/ScrollStack/ScrollStack.jsx +88 -0
- package/dist/ApexUI-Kit/templates/SidebarNav/SidebarNav.jsx +22 -1
- package/dist/ApexUI-Kit/templates/SunriseBackground/SunriseBackground.jsx +290 -0
- package/dist/ApexUI-Kit/templates/WireframeKnot3D/WireframeKnot3D.jsx +112 -0
- package/dist/cli/index.js +11 -0
- package/package.json +2 -2
- package/dist/ApexUI-Kit/templates/AccordionMarquee/AccordionMarquee.css +0 -1
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
import React, { useEffect, useRef } from "react";
|
|
2
|
+
import { Color, Mesh, OrthographicCamera, PlaneGeometry, Scene, ShaderMaterial, Vector2, WebGLRenderer } from "three";
|
|
3
|
+
|
|
4
|
+
/*
|
|
5
|
+
* Sunrise Background: a sun rising out of the valley between two mountain
|
|
6
|
+
* ranges, drawn in one WebGL shader. The sky warms from night to dawn as it
|
|
7
|
+
* climbs, light rays fan out, the ridges catch a rim of light, mist glows in
|
|
8
|
+
* the valley and the stars fade. The mountains drift a little with the
|
|
9
|
+
* pointer. Put your hero content on top as children.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const PRESETS = {
|
|
13
|
+
dawn: { sunColor: "#ffb15c", skyTop: "#1d2350", skyHorizon: "#ff7a59", mountainColor: "#140f24" },
|
|
14
|
+
golden: { sunColor: "#ffd36e", skyTop: "#2b3a67", skyHorizon: "#ffa94d", mountainColor: "#1b1420" },
|
|
15
|
+
dusk: { sunColor: "#ff8fb1", skyTop: "#1a1033", skyHorizon: "#c86dd7", mountainColor: "#100a1c" },
|
|
16
|
+
arctic: { sunColor: "#b8f3ff", skyTop: "#0c1f33", skyHorizon: "#5fd4e6", mountainColor: "#08141f" },
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const VERT = `void main(){ gl_Position = vec4(position.xy, 0.0, 1.0); }`;
|
|
20
|
+
|
|
21
|
+
const FRAG = `
|
|
22
|
+
precision highp float;
|
|
23
|
+
uniform vec2 uRes; uniform float uTime; uniform float uRise; uniform vec2 uMouse;
|
|
24
|
+
uniform vec3 uSun; uniform vec3 uSkyTop; uniform vec3 uSkyLow; uniform vec3 uMount;
|
|
25
|
+
uniform float uRays; uniform float uStars; uniform float uHaze; uniform float uSunSize; uniform float uSunHeight;
|
|
26
|
+
|
|
27
|
+
float h1(float x){ return fract(sin(x * 127.1) * 43758.5453); }
|
|
28
|
+
float h2(vec2 p){ return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453); }
|
|
29
|
+
float n1(float x){ float i = floor(x); float f = fract(x); return mix(h1(i), h1(i + 1.0), f * f * (3.0 - 2.0 * f)); }
|
|
30
|
+
float n2(vec2 p){
|
|
31
|
+
vec2 i = floor(p); vec2 f = fract(p); vec2 u = f * f * (3.0 - 2.0 * f);
|
|
32
|
+
return mix(mix(h2(i), h2(i + vec2(1, 0)), u.x), mix(h2(i + vec2(0, 1)), h2(i + vec2(1, 1)), u.x), u.y);
|
|
33
|
+
}
|
|
34
|
+
// Craggy ridge detail: a few octaves of folded noise.
|
|
35
|
+
float crag(float x){
|
|
36
|
+
float v = 0.0; float a = 0.5;
|
|
37
|
+
for (int i = 0; i < 5; i++) { v += a * (1.0 - abs(n1(x) * 2.0 - 1.0)); x *= 2.03; a *= 0.5; }
|
|
38
|
+
return v;
|
|
39
|
+
}
|
|
40
|
+
// Two peaks with a valley between them, plus detail.
|
|
41
|
+
float range(float x, float c, float w, float peak, float base, float amp, float freq, float seed){
|
|
42
|
+
float tl = clamp(1.0 - abs(x + c) / w, 0.0, 1.0);
|
|
43
|
+
float tr = clamp(1.0 - abs(x - c) / w, 0.0, 1.0);
|
|
44
|
+
float sl = mix(tl, tl * tl * (3.0 - 2.0 * tl), 0.45);
|
|
45
|
+
float sr = mix(tr, tr * tr * (3.0 - 2.0 * tr), 0.45);
|
|
46
|
+
float s = max(sl, sr);
|
|
47
|
+
return base + s * peak + (crag(x * freq + seed) - 0.45) * amp * (0.35 + s);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
void main(){
|
|
51
|
+
vec2 uv = gl_FragCoord.xy / uRes;
|
|
52
|
+
float asp = uRes.x / uRes.y;
|
|
53
|
+
// x normalised to the half width (clamped so phones still show both slopes).
|
|
54
|
+
float xn = (uv.x - 0.5) * asp / (0.5 * clamp(asp, 0.7, 2.2));
|
|
55
|
+
float y = uv.y;
|
|
56
|
+
float rise = uRise;
|
|
57
|
+
|
|
58
|
+
vec2 sp = vec2(0.0, mix(-0.16, uSunHeight, rise));
|
|
59
|
+
vec2 q = vec2((uv.x - 0.5) * asp, y);
|
|
60
|
+
float d = length(q - sp);
|
|
61
|
+
|
|
62
|
+
// Sky: night blue warming toward the horizon as the sun climbs.
|
|
63
|
+
vec3 top = mix(uSkyTop * 0.28, uSkyTop, smoothstep(0.0, 0.8, rise));
|
|
64
|
+
vec3 low = mix(uSkyTop * 0.5, uSkyLow, smoothstep(0.05, 0.9, rise));
|
|
65
|
+
vec3 col = mix(low, top, smoothstep(0.0, 0.9, y + 0.15 * (1.0 - rise)));
|
|
66
|
+
float warm = exp(-max(y - sp.y * 0.6, 0.0) * 3.2) * exp(-abs(q.x) * 0.9);
|
|
67
|
+
col += uSun * warm * (0.15 + 0.75 * rise);
|
|
68
|
+
|
|
69
|
+
// Stars fade out with the dawn.
|
|
70
|
+
vec2 cell = floor(gl_FragCoord.xy / 3.0);
|
|
71
|
+
float star = step(0.9965, h2(cell)) * (0.6 + 0.4 * sin(uTime * 2.0 + h2(cell + 7.0) * 30.0));
|
|
72
|
+
col += star * uStars * (1.0 - smoothstep(0.1, 0.75, rise)) * smoothstep(0.35, 0.9, y);
|
|
73
|
+
|
|
74
|
+
// Sun disc, halo and rays.
|
|
75
|
+
float r = uSunSize;
|
|
76
|
+
float disc = smoothstep(r + 0.003, r - 0.003, d);
|
|
77
|
+
vec3 sunCore = mix(uSun, vec3(1.0, 0.98, 0.92), 0.65);
|
|
78
|
+
col = mix(col, sunCore, disc);
|
|
79
|
+
col += uSun * (exp(-d * 9.0 / (r * 10.0)) * 0.55 + exp(-d * 2.2) * 0.35) * (0.4 + 0.6 * rise);
|
|
80
|
+
float ang = atan(q.x - sp.x, q.y - sp.y);
|
|
81
|
+
float beam = n2(vec2(ang * 7.0, uTime * 0.12)) * 0.7 + n2(vec2(ang * 17.0, -uTime * 0.07)) * 0.3;
|
|
82
|
+
float rays = smoothstep(0.45, 0.95, beam) * exp(-d * 1.6) * smoothstep(r, r * 2.5, d);
|
|
83
|
+
col += uSun * rays * uRays * 0.55 * rise;
|
|
84
|
+
|
|
85
|
+
// Mountains, far to near. Each layer drifts with the pointer by depth.
|
|
86
|
+
float mx = uMouse.x; float my = uMouse.y;
|
|
87
|
+
float hf = range(xn + mx * 0.012, 0.6, 0.85, 0.36, 0.16, 0.06, 2.6, 3.0) + my * 0.004;
|
|
88
|
+
float hm = range(xn + mx * 0.028, 0.42, 0.78, 0.33, 0.08, 0.07, 3.8, 11.0) + my * 0.008;
|
|
89
|
+
float hn = range(xn + mx * 0.05, 0.66, 0.86, 0.30, -0.02, 0.06, 5.2, 27.0) + my * 0.014;
|
|
90
|
+
|
|
91
|
+
float toSun = exp(-abs(xn) * 1.4) * rise;
|
|
92
|
+
vec3 haze = mix(low, uSun, 0.35 + 0.3 * rise);
|
|
93
|
+
|
|
94
|
+
// Far range: soft and hazy.
|
|
95
|
+
float mf = smoothstep(hf + 0.0025, hf - 0.0025, y);
|
|
96
|
+
vec3 cf = mix(uMount, haze, 0.62 * uHaze + 0.1);
|
|
97
|
+
cf += uSun * exp(-max(hf - y, 0.0) * 40.0) * toSun * 0.5;
|
|
98
|
+
col = mix(col, cf, mf);
|
|
99
|
+
|
|
100
|
+
// Valley mist lit by the sun.
|
|
101
|
+
float mist = exp(-abs(y - (hm - 0.03)) * 9.0) * exp(-abs(xn) * 1.1) * uHaze;
|
|
102
|
+
col += uSun * mist * 0.35 * rise;
|
|
103
|
+
|
|
104
|
+
// Middle range.
|
|
105
|
+
float mm = smoothstep(hm + 0.002, hm - 0.002, y);
|
|
106
|
+
vec3 cm = mix(uMount, haze, 0.32 * uHaze + 0.04);
|
|
107
|
+
cm *= 0.75 + 0.35 * smoothstep(hm - 0.35, hm, y);
|
|
108
|
+
cm += uSun * exp(-max(hm - y, 0.0) * 70.0) * toSun * 0.7;
|
|
109
|
+
col = mix(col, cm, mm);
|
|
110
|
+
|
|
111
|
+
// Near range: darkest, with a sharp rim of light on the ridge.
|
|
112
|
+
float mn = smoothstep(hn + 0.0018, hn - 0.0018, y);
|
|
113
|
+
vec3 cn = uMount * (0.65 + 0.35 * smoothstep(hn - 0.3, hn, y));
|
|
114
|
+
cn += uSun * exp(-max(hn - y, 0.0) * 120.0) * toSun * 0.9;
|
|
115
|
+
col = mix(col, cn, mn);
|
|
116
|
+
|
|
117
|
+
// Low fog over everything and light bleeding over the ridges.
|
|
118
|
+
col += haze * exp(-y * 7.0) * 0.12 * uHaze * rise;
|
|
119
|
+
col += uSun * exp(-d * 3.0) * 0.18 * rise;
|
|
120
|
+
|
|
121
|
+
// Gentle tone curve and dither (no banding in the gradients).
|
|
122
|
+
col = col / (1.0 + col * 0.35);
|
|
123
|
+
col += (h2(gl_FragCoord.xy + fract(uTime) * 61.0) - 0.5) / 255.0;
|
|
124
|
+
gl_FragColor = vec4(col, 1.0);
|
|
125
|
+
}`;
|
|
126
|
+
|
|
127
|
+
const SunriseBackground = ({
|
|
128
|
+
preset = "dawn",
|
|
129
|
+
sunColor,
|
|
130
|
+
skyTop,
|
|
131
|
+
skyHorizon,
|
|
132
|
+
mountainColor,
|
|
133
|
+
duration = 6,
|
|
134
|
+
autoRise = true,
|
|
135
|
+
sunHeight = 0.36,
|
|
136
|
+
sunSize = 0.075,
|
|
137
|
+
rays = 1,
|
|
138
|
+
stars = 1,
|
|
139
|
+
haze = 1,
|
|
140
|
+
speed = 1,
|
|
141
|
+
interactive = true,
|
|
142
|
+
replay = 0,
|
|
143
|
+
className = "",
|
|
144
|
+
children,
|
|
145
|
+
}) => {
|
|
146
|
+
const wrap = useRef(null);
|
|
147
|
+
const live = useRef({});
|
|
148
|
+
const p = PRESETS[preset] ?? PRESETS.dawn;
|
|
149
|
+
live.current = {
|
|
150
|
+
sun: sunColor ?? p.sunColor,
|
|
151
|
+
top: skyTop ?? p.skyTop,
|
|
152
|
+
low: skyHorizon ?? p.skyHorizon,
|
|
153
|
+
mount: mountainColor ?? p.mountainColor,
|
|
154
|
+
duration,
|
|
155
|
+
autoRise,
|
|
156
|
+
sunHeight,
|
|
157
|
+
sunSize,
|
|
158
|
+
rays,
|
|
159
|
+
stars,
|
|
160
|
+
haze,
|
|
161
|
+
speed,
|
|
162
|
+
interactive,
|
|
163
|
+
};
|
|
164
|
+
const rise = useRef({ start: 0 });
|
|
165
|
+
|
|
166
|
+
// Replaying (or turning autoRise back on) starts the climb again.
|
|
167
|
+
useEffect(() => {
|
|
168
|
+
rise.current.start = performance.now();
|
|
169
|
+
}, [replay, autoRise]);
|
|
170
|
+
|
|
171
|
+
useEffect(() => {
|
|
172
|
+
const el = wrap.current;
|
|
173
|
+
const renderer = new WebGLRenderer({ antialias: false, alpha: false, powerPreference: "high-performance" });
|
|
174
|
+
renderer.setPixelRatio(Math.min(window.devicePixelRatio || 1, 1.75));
|
|
175
|
+
Object.assign(renderer.domElement.style, { position: "absolute", inset: "0", width: "100%", height: "100%", display: "block" });
|
|
176
|
+
el.prepend(renderer.domElement);
|
|
177
|
+
const scene = new Scene();
|
|
178
|
+
const camera = new OrthographicCamera(-1, 1, 1, -1, 0, 1);
|
|
179
|
+
const u = {
|
|
180
|
+
uRes: { value: new Vector2(1, 1) },
|
|
181
|
+
uTime: { value: 0 },
|
|
182
|
+
uRise: { value: 0 },
|
|
183
|
+
uMouse: { value: new Vector2() },
|
|
184
|
+
uSun: { value: new Color() },
|
|
185
|
+
uSkyTop: { value: new Color() },
|
|
186
|
+
uSkyLow: { value: new Color() },
|
|
187
|
+
uMount: { value: new Color() },
|
|
188
|
+
uRays: { value: 1 },
|
|
189
|
+
uStars: { value: 1 },
|
|
190
|
+
uHaze: { value: 1 },
|
|
191
|
+
uSunSize: { value: 0.075 },
|
|
192
|
+
uSunHeight: { value: 0.3 },
|
|
193
|
+
};
|
|
194
|
+
const material = new ShaderMaterial({ vertexShader: VERT, fragmentShader: FRAG, uniforms: u, depthTest: false, depthWrite: false });
|
|
195
|
+
const geometry = new PlaneGeometry(2, 2);
|
|
196
|
+
scene.add(new Mesh(geometry, material));
|
|
197
|
+
|
|
198
|
+
const reduced = window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
|
|
199
|
+
const mouse = { x: 0, y: 0, tx: 0, ty: 0 };
|
|
200
|
+
let raf = 0;
|
|
201
|
+
let last = 0;
|
|
202
|
+
let time = 0;
|
|
203
|
+
let visible = true;
|
|
204
|
+
|
|
205
|
+
const fit = () => {
|
|
206
|
+
const { width, height } = el.getBoundingClientRect();
|
|
207
|
+
if (!width || !height) return;
|
|
208
|
+
renderer.setSize(width, height, false);
|
|
209
|
+
renderer.getDrawingBufferSize(u.uRes.value);
|
|
210
|
+
if (!raf) draw(performance.now());
|
|
211
|
+
};
|
|
212
|
+
const draw = (now) => {
|
|
213
|
+
const o = live.current;
|
|
214
|
+
const dt = last ? Math.min(0.05, (now - last) / 1000) : 1 / 60;
|
|
215
|
+
last = now;
|
|
216
|
+
time += dt * o.speed;
|
|
217
|
+
const t = o.autoRise && !reduced ? Math.min(1, (now - rise.current.start) / (Math.max(0.1, o.duration) * 1000)) : 1;
|
|
218
|
+
// Ease out: quick at first, then a slow settle at the top.
|
|
219
|
+
u.uRise.value = 1 - Math.pow(1 - t, 3);
|
|
220
|
+
const k = 1 - Math.exp(-dt / 0.35);
|
|
221
|
+
mouse.x += ((o.interactive ? mouse.tx : 0) - mouse.x) * k;
|
|
222
|
+
mouse.y += ((o.interactive ? mouse.ty : 0) - mouse.y) * k;
|
|
223
|
+
u.uMouse.value.set(mouse.x, mouse.y);
|
|
224
|
+
u.uTime.value = time;
|
|
225
|
+
u.uSun.value.set(o.sun);
|
|
226
|
+
u.uSkyTop.value.set(o.top);
|
|
227
|
+
u.uSkyLow.value.set(o.low);
|
|
228
|
+
u.uMount.value.set(o.mount);
|
|
229
|
+
u.uRays.value = o.rays;
|
|
230
|
+
u.uStars.value = o.stars;
|
|
231
|
+
u.uHaze.value = o.haze;
|
|
232
|
+
u.uSunSize.value = o.sunSize;
|
|
233
|
+
u.uSunHeight.value = o.sunHeight;
|
|
234
|
+
renderer.render(scene, camera);
|
|
235
|
+
};
|
|
236
|
+
const loop = (now) => {
|
|
237
|
+
raf = 0;
|
|
238
|
+
draw(now);
|
|
239
|
+
if (visible && !reduced) raf = requestAnimationFrame(loop);
|
|
240
|
+
};
|
|
241
|
+
const start = () => {
|
|
242
|
+
if (!raf && visible && !reduced) {
|
|
243
|
+
last = 0;
|
|
244
|
+
raf = requestAnimationFrame(loop);
|
|
245
|
+
}
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
const onMove = (e) => {
|
|
249
|
+
const r = el.getBoundingClientRect();
|
|
250
|
+
mouse.tx = ((e.clientX - r.left) / r.width) * 2 - 1;
|
|
251
|
+
mouse.ty = ((e.clientY - r.top) / r.height) * 2 - 1;
|
|
252
|
+
};
|
|
253
|
+
const onLeave = () => {
|
|
254
|
+
mouse.tx = 0;
|
|
255
|
+
mouse.ty = 0;
|
|
256
|
+
};
|
|
257
|
+
el.addEventListener("pointermove", onMove);
|
|
258
|
+
el.addEventListener("pointerleave", onLeave);
|
|
259
|
+
const ro = new ResizeObserver(fit);
|
|
260
|
+
ro.observe(el);
|
|
261
|
+
const io = new IntersectionObserver(([entry]) => {
|
|
262
|
+
visible = entry.isIntersecting;
|
|
263
|
+
if (visible) start();
|
|
264
|
+
});
|
|
265
|
+
io.observe(el);
|
|
266
|
+
fit();
|
|
267
|
+
start();
|
|
268
|
+
|
|
269
|
+
return () => {
|
|
270
|
+
cancelAnimationFrame(raf);
|
|
271
|
+
ro.disconnect();
|
|
272
|
+
io.disconnect();
|
|
273
|
+
el.removeEventListener("pointermove", onMove);
|
|
274
|
+
el.removeEventListener("pointerleave", onLeave);
|
|
275
|
+
geometry.dispose();
|
|
276
|
+
material.dispose();
|
|
277
|
+
renderer.dispose();
|
|
278
|
+
renderer.forceContextLoss();
|
|
279
|
+
renderer.domElement.remove();
|
|
280
|
+
};
|
|
281
|
+
}, []);
|
|
282
|
+
|
|
283
|
+
return (
|
|
284
|
+
<div ref={wrap} className={`relative h-full w-full overflow-hidden bg-[#0b0b18] ${className}`}>
|
|
285
|
+
{children && <div className="relative z-10 h-full w-full">{children}</div>}
|
|
286
|
+
</div>
|
|
287
|
+
);
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
export default SunriseBackground;
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import React, { useEffect, useRef } from "react";
|
|
2
|
+
import { AdditiveBlending, Color, IcosahedronGeometry, LineBasicMaterial, LineSegments, PerspectiveCamera, Points, PointsMaterial, Scene, TorusKnotGeometry, WebGLRenderer, WireframeGeometry } from "three";
|
|
3
|
+
|
|
4
|
+
/*
|
|
5
|
+
* Wireframe Knot 3D: a glowing wireframe shape (torus knot, sphere or
|
|
6
|
+
* icosahedron) with bright points at its corners, slowly turning and
|
|
7
|
+
* leaning toward the pointer. Additive lines make it glow without any
|
|
8
|
+
* post-processing, so it stays light. Pauses off screen and frees the GPU
|
|
9
|
+
* on unmount.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const SHAPES = {
|
|
13
|
+
knot: () => new TorusKnotGeometry(1, 0.32, 140, 14, 2, 3),
|
|
14
|
+
sphere: () => new IcosahedronGeometry(1.35, 3),
|
|
15
|
+
gem: () => new IcosahedronGeometry(1.4, 1),
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const WireframeKnot3D = ({ shape = "knot", color = "#a3e635", pointColor = "#ffffff", speed = 1, interactive = true, size = 24, className = "" }) => {
|
|
19
|
+
const mount = useRef(null);
|
|
20
|
+
const opts = useRef({ color, pointColor, speed, interactive });
|
|
21
|
+
opts.current = { color, pointColor, speed, interactive };
|
|
22
|
+
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
const el = mount.current;
|
|
25
|
+
const renderer = new WebGLRenderer({ antialias: true, alpha: true, powerPreference: "high-performance" });
|
|
26
|
+
renderer.setPixelRatio(Math.min(window.devicePixelRatio || 1, 2));
|
|
27
|
+
Object.assign(renderer.domElement.style, { display: "block", width: "100%", height: "100%" });
|
|
28
|
+
el.appendChild(renderer.domElement);
|
|
29
|
+
const scene = new Scene();
|
|
30
|
+
const camera = new PerspectiveCamera(40, 1, 0.1, 50);
|
|
31
|
+
camera.position.z = 5.2;
|
|
32
|
+
|
|
33
|
+
const geometry = (SHAPES[shape] ?? SHAPES.knot)();
|
|
34
|
+
const wire = new WireframeGeometry(geometry);
|
|
35
|
+
const lineMat = new LineBasicMaterial({ color: new Color(color), transparent: true, opacity: 0.55, blending: AdditiveBlending, depthWrite: false });
|
|
36
|
+
const lines = new LineSegments(wire, lineMat);
|
|
37
|
+
const pointMat = new PointsMaterial({ color: new Color(pointColor), size: 0.035, transparent: true, opacity: 0.9, blending: AdditiveBlending, depthWrite: false });
|
|
38
|
+
const points = new Points(geometry, pointMat);
|
|
39
|
+
const group = new Scene();
|
|
40
|
+
group.add(lines, points);
|
|
41
|
+
scene.add(group);
|
|
42
|
+
|
|
43
|
+
const resize = () => {
|
|
44
|
+
const { width, height } = el.getBoundingClientRect();
|
|
45
|
+
if (!width || !height) return;
|
|
46
|
+
renderer.setSize(width, height, false);
|
|
47
|
+
camera.aspect = width / height;
|
|
48
|
+
camera.updateProjectionMatrix();
|
|
49
|
+
};
|
|
50
|
+
const ro = new ResizeObserver(resize);
|
|
51
|
+
ro.observe(el);
|
|
52
|
+
resize();
|
|
53
|
+
|
|
54
|
+
const pointer = { x: 0, y: 0 };
|
|
55
|
+
const onMove = (e) => {
|
|
56
|
+
const r = el.getBoundingClientRect();
|
|
57
|
+
pointer.x = ((e.clientX - r.left) / r.width) * 2 - 1;
|
|
58
|
+
pointer.y = ((e.clientY - r.top) / r.height) * 2 - 1;
|
|
59
|
+
};
|
|
60
|
+
const onLeave = () => {
|
|
61
|
+
pointer.x = 0;
|
|
62
|
+
pointer.y = 0;
|
|
63
|
+
};
|
|
64
|
+
el.addEventListener("pointermove", onMove);
|
|
65
|
+
el.addEventListener("pointerleave", onLeave);
|
|
66
|
+
const reduced = window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
|
|
67
|
+
let visible = true;
|
|
68
|
+
const io = new IntersectionObserver(([entry]) => (visible = entry.isIntersecting));
|
|
69
|
+
io.observe(el);
|
|
70
|
+
|
|
71
|
+
let raf = 0;
|
|
72
|
+
let last = performance.now();
|
|
73
|
+
let spin = 0;
|
|
74
|
+
const frame = (now) => {
|
|
75
|
+
raf = requestAnimationFrame(frame);
|
|
76
|
+
const dt = Math.min(0.05, (now - last) / 1000);
|
|
77
|
+
last = now;
|
|
78
|
+
if (!visible) return;
|
|
79
|
+
const o = opts.current;
|
|
80
|
+
spin += dt * 0.35 * o.speed * (reduced ? 0.15 : 1);
|
|
81
|
+
const px = o.interactive ? pointer.y * 0.6 : 0;
|
|
82
|
+
const py = o.interactive ? pointer.x * 0.8 : 0;
|
|
83
|
+
group.rotation.x += (px + spin * 0.5 - group.rotation.x) * 0.06;
|
|
84
|
+
group.rotation.y += (py + spin - group.rotation.y) * 0.06;
|
|
85
|
+
lineMat.color.set(o.color);
|
|
86
|
+
pointMat.color.set(o.pointColor);
|
|
87
|
+
renderer.render(scene, camera);
|
|
88
|
+
};
|
|
89
|
+
raf = requestAnimationFrame(frame);
|
|
90
|
+
|
|
91
|
+
return () => {
|
|
92
|
+
cancelAnimationFrame(raf);
|
|
93
|
+
ro.disconnect();
|
|
94
|
+
io.disconnect();
|
|
95
|
+
el.removeEventListener("pointermove", onMove);
|
|
96
|
+
el.removeEventListener("pointerleave", onLeave);
|
|
97
|
+
geometry.dispose();
|
|
98
|
+
wire.dispose();
|
|
99
|
+
lineMat.dispose();
|
|
100
|
+
pointMat.dispose();
|
|
101
|
+
renderer.dispose();
|
|
102
|
+
renderer.forceContextLoss();
|
|
103
|
+
renderer.domElement.remove();
|
|
104
|
+
};
|
|
105
|
+
// Colors, speed and interaction are read live; only the shape rebuilds.
|
|
106
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
107
|
+
}, [shape]);
|
|
108
|
+
|
|
109
|
+
return <div ref={mount} aria-hidden="true" className={`relative touch-none ${className}`} style={{ width: `min(${size}rem, 90vw)`, aspectRatio: "1" }} />;
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
export default WireframeKnot3D;
|
package/dist/cli/index.js
CHANGED
|
@@ -120,6 +120,17 @@ const componentMap = {
|
|
|
120
120
|
"distortion-image": "DistortionImage",
|
|
121
121
|
"galaxy-3d": "Galaxy3D",
|
|
122
122
|
"warp-tunnel": "WarpTunnel",
|
|
123
|
+
"magnetic-button": "MagneticButton",
|
|
124
|
+
"radial-menu": "RadialMenu",
|
|
125
|
+
"marquee-3d": "Marquee3D",
|
|
126
|
+
"wireframe-knot-3d": "WireframeKnot3D",
|
|
127
|
+
"particle-text": "ParticleText",
|
|
128
|
+
"edge-blur": "EdgeBlur",
|
|
129
|
+
"circular-carousel": "CircularCarousel",
|
|
130
|
+
"arc-gallery": "ArcGallery",
|
|
131
|
+
"scroll-stack": "ScrollStack",
|
|
132
|
+
"sunrise-background": "SunriseBackground",
|
|
133
|
+
"horizon-glow": "HorizonGlow",
|
|
123
134
|
"water-drop-reveal": "MaskView",
|
|
124
135
|
};
|
|
125
136
|
// Packages only some components need, installed on top of the shared ones.
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "apex-ui-kit",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.7.0",
|
|
4
4
|
"license": "MIT",
|
|
5
|
-
"description": "
|
|
5
|
+
"description": "107 free, animated UI components for React, styled with Tailwind CSS. Add any of them with one CLI command.",
|
|
6
6
|
"homepage": "https://apex-ui.in",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
@import url("https://fonts.googleapis.com/css2?family=Righteous&display=swap");
|