@opencosmos/ui 1.3.1
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/.claude/CLAUDE.md +239 -0
- package/README.md +161 -0
- package/dist/cli.mjs +151 -0
- package/dist/dates.d.mts +20 -0
- package/dist/dates.d.ts +20 -0
- package/dist/dates.js +240 -0
- package/dist/dates.js.map +1 -0
- package/dist/dates.mjs +203 -0
- package/dist/dates.mjs.map +1 -0
- package/dist/dnd.d.mts +126 -0
- package/dist/dnd.d.ts +126 -0
- package/dist/dnd.js +274 -0
- package/dist/dnd.js.map +1 -0
- package/dist/dnd.mjs +250 -0
- package/dist/dnd.mjs.map +1 -0
- package/dist/fontThemes-Dh8mtXES.d.mts +868 -0
- package/dist/fontThemes-Dh8mtXES.d.ts +868 -0
- package/dist/forms.d.mts +38 -0
- package/dist/forms.d.ts +38 -0
- package/dist/forms.js +198 -0
- package/dist/forms.js.map +1 -0
- package/dist/forms.mjs +159 -0
- package/dist/forms.mjs.map +1 -0
- package/dist/hooks-1b8WaQf1.d.mts +225 -0
- package/dist/hooks-CKW8vE9H.d.ts +225 -0
- package/dist/hooks.d.mts +3 -0
- package/dist/hooks.d.ts +3 -0
- package/dist/hooks.js +971 -0
- package/dist/hooks.js.map +1 -0
- package/dist/hooks.mjs +943 -0
- package/dist/hooks.mjs.map +1 -0
- package/dist/index-DscTIrZ2.d.mts +29 -0
- package/dist/index-DscTIrZ2.d.ts +29 -0
- package/dist/index.d.mts +3382 -0
- package/dist/index.d.ts +3382 -0
- package/dist/index.js +15146 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +14802 -0
- package/dist/index.mjs.map +1 -0
- package/dist/providers-CXPDMsl7.d.mts +30 -0
- package/dist/providers-Dn_Msjvz.d.ts +30 -0
- package/dist/providers.d.mts +3 -0
- package/dist/providers.d.ts +3 -0
- package/dist/providers.js +1885 -0
- package/dist/providers.js.map +1 -0
- package/dist/providers.mjs +1859 -0
- package/dist/providers.mjs.map +1 -0
- package/dist/tables.d.mts +10 -0
- package/dist/tables.d.ts +10 -0
- package/dist/tables.js +248 -0
- package/dist/tables.js.map +1 -0
- package/dist/tables.mjs +218 -0
- package/dist/tables.mjs.map +1 -0
- package/dist/tokens.d.mts +1065 -0
- package/dist/tokens.d.ts +1065 -0
- package/dist/tokens.js +2637 -0
- package/dist/tokens.js.map +1 -0
- package/dist/tokens.mjs +2555 -0
- package/dist/tokens.mjs.map +1 -0
- package/dist/utils-CIIM7dAC.d.ts +986 -0
- package/dist/utils-Cs04sxth.d.mts +986 -0
- package/dist/utils.d.mts +4 -0
- package/dist/utils.d.ts +4 -0
- package/dist/utils.js +874 -0
- package/dist/utils.js.map +1 -0
- package/dist/utils.mjs +806 -0
- package/dist/utils.mjs.map +1 -0
- package/dist/validation-Bj1ye-v_.d.mts +114 -0
- package/dist/validation-Bj1ye-v_.d.ts +114 -0
- package/dist/webgl.d.mts +104 -0
- package/dist/webgl.d.ts +104 -0
- package/dist/webgl.js +226 -0
- package/dist/webgl.js.map +1 -0
- package/dist/webgl.mjs +195 -0
- package/dist/webgl.mjs.map +1 -0
- package/package.json +267 -0
- package/src/cli.ts +206 -0
- package/src/component-registry.ts +183 -0
- package/src/components/actions/Button.test.tsx +61 -0
- package/src/components/actions/Button.tsx +70 -0
- package/src/components/actions/Link.tsx +78 -0
- package/src/components/actions/Magnetic.tsx +68 -0
- package/src/components/actions/Toggle.test.tsx +40 -0
- package/src/components/actions/Toggle.tsx +47 -0
- package/src/components/actions/ToggleGroup.tsx +70 -0
- package/src/components/actions/index.ts +5 -0
- package/src/components/backgrounds/FaultyTerminal.tsx +426 -0
- package/src/components/backgrounds/OrbBackground.tsx +424 -0
- package/src/components/backgrounds/WarpBackground.tsx +358 -0
- package/src/components/backgrounds/index.ts +3 -0
- package/src/components/blocks/Hero.tsx +142 -0
- package/src/components/blocks/social/OpenGraphCard.tsx +243 -0
- package/src/components/cursor/SplashCursor.tsx +1315 -0
- package/src/components/cursor/TargetCursor.tsx +187 -0
- package/src/components/cursor/index.ts +2 -0
- package/src/components/data-display/AspectImage.tsx +73 -0
- package/src/components/data-display/Avatar.test.tsx +35 -0
- package/src/components/data-display/Avatar.tsx +55 -0
- package/src/components/data-display/Badge.test.tsx +43 -0
- package/src/components/data-display/Badge.tsx +84 -0
- package/src/components/data-display/Brand.tsx +123 -0
- package/src/components/data-display/Calendar.tsx +70 -0
- package/src/components/data-display/Card.test.tsx +92 -0
- package/src/components/data-display/Card.tsx +115 -0
- package/src/components/data-display/Code.tsx +210 -0
- package/src/components/data-display/CollapsibleCodeBlock.tsx +238 -0
- package/src/components/data-display/DataTable.tsx +119 -0
- package/src/components/data-display/DescriptionList.tsx +41 -0
- package/src/components/data-display/GitHubIcon.tsx +44 -0
- package/src/components/data-display/Heading.test.tsx +36 -0
- package/src/components/data-display/Heading.tsx +83 -0
- package/src/components/data-display/StatCard.tsx +195 -0
- package/src/components/data-display/Table.tsx +133 -0
- package/src/components/data-display/Text.test.tsx +48 -0
- package/src/components/data-display/Text.tsx +144 -0
- package/src/components/data-display/Timeline.tsx +194 -0
- package/src/components/data-display/TreeView.tsx +226 -0
- package/src/components/data-display/Typewriter.tsx +119 -0
- package/src/components/data-display/VariableWeightText.tsx +130 -0
- package/src/components/data-display/index.ts +19 -0
- package/src/components/feedback/Alert.test.tsx +44 -0
- package/src/components/feedback/Alert.tsx +65 -0
- package/src/components/feedback/EmptyState.tsx +113 -0
- package/src/components/feedback/Progress.test.tsx +60 -0
- package/src/components/feedback/Progress.tsx +30 -0
- package/src/components/feedback/ProgressBar.tsx +158 -0
- package/src/components/feedback/Skeleton.test.tsx +39 -0
- package/src/components/feedback/Skeleton.tsx +45 -0
- package/src/components/feedback/Sonner.tsx +28 -0
- package/src/components/feedback/Spinner.test.tsx +33 -0
- package/src/components/feedback/Spinner.tsx +99 -0
- package/src/components/feedback/Stepper.tsx +307 -0
- package/src/components/feedback/Toast/Toast.tsx +243 -0
- package/src/components/feedback/Toast/index.ts +2 -0
- package/src/components/feedback/index.ts +9 -0
- package/src/components/forms/Checkbox.test.tsx +40 -0
- package/src/components/forms/Checkbox.tsx +31 -0
- package/src/components/forms/ColorPicker.tsx +118 -0
- package/src/components/forms/Combobox.tsx +96 -0
- package/src/components/forms/DragDrop.tsx +440 -0
- package/src/components/forms/FileUpload.tsx +252 -0
- package/src/components/forms/FilterButton.tsx +65 -0
- package/src/components/forms/Form.tsx +197 -0
- package/src/components/forms/Input.test.tsx +46 -0
- package/src/components/forms/Input.tsx +43 -0
- package/src/components/forms/InputOTP.tsx +81 -0
- package/src/components/forms/Label.test.tsx +20 -0
- package/src/components/forms/Label.tsx +25 -0
- package/src/components/forms/RadioGroup.tsx +51 -0
- package/src/components/forms/SearchBar.tsx +215 -0
- package/src/components/forms/Select.test.tsx +118 -0
- package/src/components/forms/Select.tsx +274 -0
- package/src/components/forms/Slider.tsx +29 -0
- package/src/components/forms/Switch.test.tsx +76 -0
- package/src/components/forms/Switch.tsx +30 -0
- package/src/components/forms/TextField.tsx +152 -0
- package/src/components/forms/Textarea.test.tsx +41 -0
- package/src/components/forms/Textarea.tsx +29 -0
- package/src/components/forms/ThemeSwitcher.tsx +290 -0
- package/src/components/forms/ThemeToggle.tsx +151 -0
- package/src/components/forms/index.ts +19 -0
- package/src/components/layout/Accordion.test.tsx +66 -0
- package/src/components/layout/Accordion.tsx +64 -0
- package/src/components/layout/AspectRatio.tsx +7 -0
- package/src/components/layout/Carousel.tsx +277 -0
- package/src/components/layout/Collapsible.test.tsx +40 -0
- package/src/components/layout/Collapsible.tsx +31 -0
- package/src/components/layout/Container.test.tsx +45 -0
- package/src/components/layout/Container.tsx +99 -0
- package/src/components/layout/CustomizerPanel.tsx +400 -0
- package/src/components/layout/DatePicker.tsx +57 -0
- package/src/components/layout/Footer/Footer.tsx +175 -0
- package/src/components/layout/Footer/index.ts +2 -0
- package/src/components/layout/GlassSurface.tsx +82 -0
- package/src/components/layout/Grid.test.tsx +31 -0
- package/src/components/layout/Grid.tsx +130 -0
- package/src/components/layout/Header/Header.tsx +450 -0
- package/src/components/layout/Header/index.ts +2 -0
- package/src/components/layout/PageLayout.tsx +180 -0
- package/src/components/layout/PageTemplate.tsx +158 -0
- package/src/components/layout/Resizable.tsx +48 -0
- package/src/components/layout/ScrollArea.tsx +53 -0
- package/src/components/layout/Separator.test.tsx +28 -0
- package/src/components/layout/Separator.tsx +29 -0
- package/src/components/layout/Sidebar.tsx +171 -0
- package/src/components/layout/Stack.test.tsx +41 -0
- package/src/components/layout/Stack.tsx +89 -0
- package/src/components/layout/glass-surface.css +60 -0
- package/src/components/layout/index.ts +18 -0
- package/src/components/motion/AnimatedBeam.tsx +159 -0
- package/src/components/navigation/Breadcrumb.test.tsx +57 -0
- package/src/components/navigation/Breadcrumb.tsx +119 -0
- package/src/components/navigation/Breadcrumbs.tsx +221 -0
- package/src/components/navigation/Command.tsx +159 -0
- package/src/components/navigation/Menubar.tsx +115 -0
- package/src/components/navigation/NavLink.tsx +55 -0
- package/src/components/navigation/NavigationMenu.tsx +125 -0
- package/src/components/navigation/Pagination.tsx +121 -0
- package/src/components/navigation/SecondaryNav.tsx +100 -0
- package/src/components/navigation/Tabs.test.tsx +47 -0
- package/src/components/navigation/Tabs.tsx +60 -0
- package/src/components/navigation/TertiaryNav.tsx +90 -0
- package/src/components/navigation/index.ts +10 -0
- package/src/components/overlays/AlertDialog.test.tsx +69 -0
- package/src/components/overlays/AlertDialog.tsx +166 -0
- package/src/components/overlays/ContextMenu.tsx +243 -0
- package/src/components/overlays/Dialog.test.tsx +79 -0
- package/src/components/overlays/Dialog.tsx +158 -0
- package/src/components/overlays/Drawer.tsx +128 -0
- package/src/components/overlays/Dropdown.tsx +253 -0
- package/src/components/overlays/DropdownMenu.tsx +242 -0
- package/src/components/overlays/HoverCard.tsx +32 -0
- package/src/components/overlays/Modal.tsx +250 -0
- package/src/components/overlays/NotificationCenter.tsx +364 -0
- package/src/components/overlays/Popover.test.tsx +40 -0
- package/src/components/overlays/Popover.tsx +46 -0
- package/src/components/overlays/Sheet.tsx +163 -0
- package/src/components/overlays/Tooltip.test.tsx +33 -0
- package/src/components/overlays/Tooltip.tsx +32 -0
- package/src/components/overlays/index.ts +12 -0
- package/src/dates.ts +2 -0
- package/src/dnd.ts +1 -0
- package/src/forms.ts +1 -0
- package/src/globals.css +187 -0
- package/src/hooks/index.ts +6 -0
- package/src/hooks/useForm.ts +247 -0
- package/src/hooks/useMotionPreference.test.ts +102 -0
- package/src/hooks/useMotionPreference.ts +78 -0
- package/src/hooks/useTheme.ts +58 -0
- package/src/hooks.ts +9 -0
- package/src/index.ts +168 -0
- package/src/lib/animations.ts +356 -0
- package/src/lib/breadcrumbs.ts +94 -0
- package/src/lib/colors.ts +493 -0
- package/src/lib/store/customizer.ts +482 -0
- package/src/lib/store/index.ts +3 -0
- package/src/lib/store/theme.ts +55 -0
- package/src/lib/syntax-parser/index.ts +50 -0
- package/src/lib/syntax-parser/patterns.ts +64 -0
- package/src/lib/syntax-parser/tokenizer.ts +117 -0
- package/src/lib/syntax-parser/types.ts +27 -0
- package/src/lib/utils.ts +6 -0
- package/src/lib/validation.ts +204 -0
- package/src/lib/webgl/Color.ts +11 -0
- package/src/lib/webgl/Mesh.ts +41 -0
- package/src/lib/webgl/Program.ts +118 -0
- package/src/lib/webgl/Renderer.ts +51 -0
- package/src/lib/webgl/Triangle.ts +27 -0
- package/src/lib/webgl/Vec3.ts +18 -0
- package/src/lib/webgl/index.ts +13 -0
- package/src/nativewind-env.d.ts +1 -0
- package/src/providers/ThemeProvider.tsx +461 -0
- package/src/providers/index.ts +1 -0
- package/src/providers.ts +7 -0
- package/src/tables.ts +1 -0
- package/src/test/setup.ts +39 -0
- package/src/theme.css +158 -0
- package/src/tokens.ts +7 -0
- package/src/utils.ts +12 -0
- package/src/webgl.ts +1 -0
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { Renderer, Program, Mesh, Color, Triangle } from '../../lib/webgl';
|
|
4
|
+
import { useEffect, useRef } from 'react';
|
|
5
|
+
|
|
6
|
+
const vertexShader = `
|
|
7
|
+
attribute vec2 uv;
|
|
8
|
+
attribute vec2 position;
|
|
9
|
+
|
|
10
|
+
varying vec2 vUv;
|
|
11
|
+
|
|
12
|
+
void main() {
|
|
13
|
+
vUv = uv;
|
|
14
|
+
gl_Position = vec4(position, 0, 1);
|
|
15
|
+
}
|
|
16
|
+
`;
|
|
17
|
+
|
|
18
|
+
const fragmentShader = `
|
|
19
|
+
precision highp float;
|
|
20
|
+
|
|
21
|
+
uniform float uTime;
|
|
22
|
+
uniform vec3 uResolution;
|
|
23
|
+
uniform vec2 uFocal;
|
|
24
|
+
uniform vec2 uRotation;
|
|
25
|
+
uniform float uStarSpeed;
|
|
26
|
+
uniform float uDensity;
|
|
27
|
+
uniform float uHueShift;
|
|
28
|
+
uniform float uSpeed;
|
|
29
|
+
uniform vec2 uMouse;
|
|
30
|
+
uniform float uGlowIntensity;
|
|
31
|
+
uniform float uSaturation;
|
|
32
|
+
uniform bool uMouseRepulsion;
|
|
33
|
+
uniform float uTwinkleIntensity;
|
|
34
|
+
uniform float uRotationSpeed;
|
|
35
|
+
uniform float uRepulsionStrength;
|
|
36
|
+
uniform float uMouseActiveFactor;
|
|
37
|
+
uniform float uAutoCenterRepulsion;
|
|
38
|
+
uniform bool uTransparent;
|
|
39
|
+
|
|
40
|
+
varying vec2 vUv;
|
|
41
|
+
|
|
42
|
+
#define NUM_LAYER 4.0
|
|
43
|
+
#define STAR_COLOR_CUTOFF 0.2
|
|
44
|
+
#define MAT45 mat2(0.7071, -0.7071, 0.7071, 0.7071)
|
|
45
|
+
#define PERIOD 3.0
|
|
46
|
+
|
|
47
|
+
float Hash21(vec2 p) {
|
|
48
|
+
p = fract(p * vec2(123.34, 456.21));
|
|
49
|
+
p += dot(p, p + 45.32);
|
|
50
|
+
return fract(p.x * p.y);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
float tri(float x) {
|
|
54
|
+
return abs(fract(x) * 2.0 - 1.0);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
float tris(float x) {
|
|
58
|
+
float t = fract(x);
|
|
59
|
+
return 1.0 - smoothstep(0.0, 1.0, abs(2.0 * t - 1.0));
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
float trisn(float x) {
|
|
63
|
+
float t = fract(x);
|
|
64
|
+
return 2.0 * (1.0 - smoothstep(0.0, 1.0, abs(2.0 * t - 1.0))) - 1.0;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
vec3 hsv2rgb(vec3 c) {
|
|
68
|
+
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
|
|
69
|
+
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
|
|
70
|
+
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
float Star(vec2 uv, float flare) {
|
|
74
|
+
float d = length(uv);
|
|
75
|
+
float m = (0.05 * uGlowIntensity) / d;
|
|
76
|
+
float rays = smoothstep(0.0, 1.0, 1.0 - abs(uv.x * uv.y * 1000.0));
|
|
77
|
+
m += rays * flare * uGlowIntensity;
|
|
78
|
+
uv *= MAT45;
|
|
79
|
+
rays = smoothstep(0.0, 1.0, 1.0 - abs(uv.x * uv.y * 1000.0));
|
|
80
|
+
m += rays * 0.3 * flare * uGlowIntensity;
|
|
81
|
+
m *= smoothstep(1.0, 0.2, d);
|
|
82
|
+
return m;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
vec3 StarLayer(vec2 uv) {
|
|
86
|
+
vec3 col = vec3(0.0);
|
|
87
|
+
|
|
88
|
+
vec2 gv = fract(uv) - 0.5;
|
|
89
|
+
vec2 id = floor(uv);
|
|
90
|
+
|
|
91
|
+
for (int y = -1; y <= 1; y++) {
|
|
92
|
+
for (int x = -1; x <= 1; x++) {
|
|
93
|
+
vec2 offset = vec2(float(x), float(y));
|
|
94
|
+
vec2 si = id + vec2(float(x), float(y));
|
|
95
|
+
float seed = Hash21(si);
|
|
96
|
+
float size = fract(seed * 345.32);
|
|
97
|
+
float glossLocal = tri(uStarSpeed / (PERIOD * seed + 1.0));
|
|
98
|
+
float flareSize = smoothstep(0.9, 1.0, size) * glossLocal;
|
|
99
|
+
|
|
100
|
+
float red = smoothstep(STAR_COLOR_CUTOFF, 1.0, Hash21(si + 1.0)) + STAR_COLOR_CUTOFF;
|
|
101
|
+
float blu = smoothstep(STAR_COLOR_CUTOFF, 1.0, Hash21(si + 3.0)) + STAR_COLOR_CUTOFF;
|
|
102
|
+
float grn = min(red, blu) * seed;
|
|
103
|
+
vec3 base = vec3(red, grn, blu);
|
|
104
|
+
|
|
105
|
+
float hue = atan(base.g - base.r, base.b - base.r) / (2.0 * 3.14159) + 0.5;
|
|
106
|
+
hue = fract(hue + uHueShift / 360.0);
|
|
107
|
+
float sat = length(base - vec3(dot(base, vec3(0.299, 0.587, 0.114)))) * uSaturation;
|
|
108
|
+
float val = max(max(base.r, base.g), base.b);
|
|
109
|
+
base = hsv2rgb(vec3(hue, sat, val));
|
|
110
|
+
|
|
111
|
+
vec2 pad = vec2(tris(seed * 34.0 + uTime * uSpeed / 10.0), tris(seed * 38.0 + uTime * uSpeed / 30.0)) - 0.5;
|
|
112
|
+
|
|
113
|
+
float star = Star(gv - offset - pad, flareSize);
|
|
114
|
+
vec3 color = base;
|
|
115
|
+
|
|
116
|
+
float twinkle = trisn(uTime * uSpeed + seed * 6.2831) * 0.5 + 1.0;
|
|
117
|
+
twinkle = mix(1.0, twinkle, uTwinkleIntensity);
|
|
118
|
+
star *= twinkle;
|
|
119
|
+
|
|
120
|
+
col += star * size * color;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return col;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
void main() {
|
|
128
|
+
vec2 focalPx = uFocal * uResolution.xy;
|
|
129
|
+
vec2 uv = (vUv * uResolution.xy - focalPx) / uResolution.y;
|
|
130
|
+
|
|
131
|
+
vec2 mouseNorm = uMouse - vec2(0.5);
|
|
132
|
+
|
|
133
|
+
if (uAutoCenterRepulsion > 0.0) {
|
|
134
|
+
vec2 centerUV = vec2(0.0, 0.0);
|
|
135
|
+
float centerDist = length(uv - centerUV);
|
|
136
|
+
vec2 repulsion = normalize(uv - centerUV) * (uAutoCenterRepulsion / (centerDist + 0.1));
|
|
137
|
+
uv += repulsion * 0.05;
|
|
138
|
+
} else if (uMouseRepulsion) {
|
|
139
|
+
vec2 mousePosUV = (uMouse * uResolution.xy - focalPx) / uResolution.y;
|
|
140
|
+
float mouseDist = length(uv - mousePosUV);
|
|
141
|
+
vec2 repulsion = normalize(uv - mousePosUV) * (uRepulsionStrength / (mouseDist + 0.1));
|
|
142
|
+
uv += repulsion * 0.05 * uMouseActiveFactor;
|
|
143
|
+
} else {
|
|
144
|
+
vec2 mouseOffset = mouseNorm * 0.1 * uMouseActiveFactor;
|
|
145
|
+
uv += mouseOffset;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
float autoRotAngle = uTime * uRotationSpeed;
|
|
149
|
+
mat2 autoRot = mat2(cos(autoRotAngle), -sin(autoRotAngle), sin(autoRotAngle), cos(autoRotAngle));
|
|
150
|
+
uv = autoRot * uv;
|
|
151
|
+
|
|
152
|
+
uv = mat2(uRotation.x, -uRotation.y, uRotation.y, uRotation.x) * uv;
|
|
153
|
+
|
|
154
|
+
vec3 col = vec3(0.0);
|
|
155
|
+
|
|
156
|
+
for (float i = 0.0; i < 1.0; i += 1.0 / NUM_LAYER) {
|
|
157
|
+
float depth = fract(i + uStarSpeed * uSpeed);
|
|
158
|
+
float scale = mix(20.0 * uDensity, 0.5 * uDensity, depth);
|
|
159
|
+
float fade = depth * smoothstep(1.0, 0.9, depth);
|
|
160
|
+
col += StarLayer(uv * scale + i * 453.32) * fade;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (uTransparent) {
|
|
164
|
+
float alpha = length(col);
|
|
165
|
+
alpha = smoothstep(0.0, 0.3, alpha);
|
|
166
|
+
alpha = min(alpha, 1.0);
|
|
167
|
+
gl_FragColor = vec4(col, alpha);
|
|
168
|
+
} else {
|
|
169
|
+
gl_FragColor = vec4(col, 1.0);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
`;
|
|
173
|
+
|
|
174
|
+
interface WarpBackgroundProps {
|
|
175
|
+
focal?: [number, number];
|
|
176
|
+
rotation?: [number, number];
|
|
177
|
+
starSpeed?: number;
|
|
178
|
+
density?: number;
|
|
179
|
+
hueShift?: number;
|
|
180
|
+
disableAnimation?: boolean;
|
|
181
|
+
speed?: number;
|
|
182
|
+
mouseInteraction?: boolean;
|
|
183
|
+
glowIntensity?: number;
|
|
184
|
+
saturation?: number;
|
|
185
|
+
mouseRepulsion?: boolean;
|
|
186
|
+
repulsionStrength?: number;
|
|
187
|
+
twinkleIntensity?: number;
|
|
188
|
+
rotationSpeed?: number;
|
|
189
|
+
autoCenterRepulsion?: number;
|
|
190
|
+
transparent?: boolean;
|
|
191
|
+
className?: string;
|
|
192
|
+
[key: string]: any;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
export function WarpBackground({
|
|
196
|
+
focal = [0.5, 0.5],
|
|
197
|
+
rotation = [1.0, 0.0],
|
|
198
|
+
starSpeed = 0.5,
|
|
199
|
+
density = 1,
|
|
200
|
+
hueShift = 140,
|
|
201
|
+
disableAnimation = false,
|
|
202
|
+
speed = 1.0,
|
|
203
|
+
mouseInteraction = true,
|
|
204
|
+
glowIntensity = 0.3,
|
|
205
|
+
saturation = 0.0,
|
|
206
|
+
mouseRepulsion = true,
|
|
207
|
+
repulsionStrength = 2,
|
|
208
|
+
twinkleIntensity = 0.3,
|
|
209
|
+
rotationSpeed = 0.1,
|
|
210
|
+
autoCenterRepulsion = 0,
|
|
211
|
+
transparent = true,
|
|
212
|
+
className = '',
|
|
213
|
+
...rest
|
|
214
|
+
}: WarpBackgroundProps) {
|
|
215
|
+
const ctnDom = useRef<HTMLDivElement>(null);
|
|
216
|
+
const targetMousePos = useRef({ x: 0.5, y: 0.5 });
|
|
217
|
+
const smoothMousePos = useRef({ x: 0.5, y: 0.5 });
|
|
218
|
+
const targetMouseActive = useRef(0.0);
|
|
219
|
+
const smoothMouseActive = useRef(0.0);
|
|
220
|
+
|
|
221
|
+
useEffect(() => {
|
|
222
|
+
if (!ctnDom.current) return;
|
|
223
|
+
const ctn = ctnDom.current;
|
|
224
|
+
const renderer = new Renderer({
|
|
225
|
+
alpha: transparent,
|
|
226
|
+
premultipliedAlpha: false
|
|
227
|
+
});
|
|
228
|
+
const gl = renderer.gl;
|
|
229
|
+
|
|
230
|
+
if (transparent) {
|
|
231
|
+
gl.enable(gl.BLEND);
|
|
232
|
+
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
|
|
233
|
+
gl.clearColor(0, 0, 0, 0);
|
|
234
|
+
} else {
|
|
235
|
+
gl.clearColor(0, 0, 0, 1);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
let program: Program; // eslint-disable-line prefer-const -- reassigned after conditional init below
|
|
239
|
+
|
|
240
|
+
function resize() {
|
|
241
|
+
const scale = 1;
|
|
242
|
+
renderer.setSize(ctn.offsetWidth * scale, ctn.offsetHeight * scale);
|
|
243
|
+
if (program) {
|
|
244
|
+
program.uniforms.uResolution.value = new Color(
|
|
245
|
+
gl.canvas.width,
|
|
246
|
+
gl.canvas.height,
|
|
247
|
+
gl.canvas.width / gl.canvas.height
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
window.addEventListener('resize', resize, false);
|
|
252
|
+
resize();
|
|
253
|
+
|
|
254
|
+
const geometry = new Triangle(gl);
|
|
255
|
+
program = new Program(gl, {
|
|
256
|
+
vertex: vertexShader,
|
|
257
|
+
fragment: fragmentShader,
|
|
258
|
+
uniforms: {
|
|
259
|
+
uTime: { value: 0 },
|
|
260
|
+
uResolution: {
|
|
261
|
+
value: new Color(gl.canvas.width, gl.canvas.height, gl.canvas.width / gl.canvas.height)
|
|
262
|
+
},
|
|
263
|
+
uFocal: { value: new Float32Array(focal) },
|
|
264
|
+
uRotation: { value: new Float32Array(rotation) },
|
|
265
|
+
uStarSpeed: { value: starSpeed },
|
|
266
|
+
uDensity: { value: density },
|
|
267
|
+
uHueShift: { value: hueShift },
|
|
268
|
+
uSpeed: { value: speed },
|
|
269
|
+
uMouse: {
|
|
270
|
+
value: new Float32Array([smoothMousePos.current.x, smoothMousePos.current.y])
|
|
271
|
+
},
|
|
272
|
+
uGlowIntensity: { value: glowIntensity },
|
|
273
|
+
uSaturation: { value: saturation },
|
|
274
|
+
uMouseRepulsion: { value: mouseRepulsion },
|
|
275
|
+
uTwinkleIntensity: { value: twinkleIntensity },
|
|
276
|
+
uRotationSpeed: { value: rotationSpeed },
|
|
277
|
+
uRepulsionStrength: { value: repulsionStrength },
|
|
278
|
+
uMouseActiveFactor: { value: 0.0 },
|
|
279
|
+
uAutoCenterRepulsion: { value: autoCenterRepulsion },
|
|
280
|
+
uTransparent: { value: transparent }
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
const mesh = new Mesh(gl, { geometry, program });
|
|
285
|
+
let animateId: number;
|
|
286
|
+
|
|
287
|
+
function update(t: number) {
|
|
288
|
+
animateId = requestAnimationFrame(update);
|
|
289
|
+
if (!disableAnimation) {
|
|
290
|
+
program.uniforms.uTime.value = t * 0.001;
|
|
291
|
+
program.uniforms.uStarSpeed.value = (t * 0.001 * starSpeed) / 10.0;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
const lerpFactor = 0.05;
|
|
295
|
+
smoothMousePos.current.x += (targetMousePos.current.x - smoothMousePos.current.x) * lerpFactor;
|
|
296
|
+
smoothMousePos.current.y += (targetMousePos.current.y - smoothMousePos.current.y) * lerpFactor;
|
|
297
|
+
|
|
298
|
+
smoothMouseActive.current += (targetMouseActive.current - smoothMouseActive.current) * lerpFactor;
|
|
299
|
+
|
|
300
|
+
program.uniforms.uMouse.value[0] = smoothMousePos.current.x;
|
|
301
|
+
program.uniforms.uMouse.value[1] = smoothMousePos.current.y;
|
|
302
|
+
program.uniforms.uMouseActiveFactor.value = smoothMouseActive.current;
|
|
303
|
+
|
|
304
|
+
renderer.render({ scene: mesh });
|
|
305
|
+
}
|
|
306
|
+
animateId = requestAnimationFrame(update);
|
|
307
|
+
ctn.appendChild(gl.canvas);
|
|
308
|
+
|
|
309
|
+
function handleMouseMove(e: MouseEvent) {
|
|
310
|
+
const rect = ctn.getBoundingClientRect();
|
|
311
|
+
const x = (e.clientX - rect.left) / rect.width;
|
|
312
|
+
const y = 1.0 - (e.clientY - rect.top) / rect.height;
|
|
313
|
+
targetMousePos.current = { x, y };
|
|
314
|
+
targetMouseActive.current = 1.0;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
function handleMouseLeave() {
|
|
318
|
+
targetMouseActive.current = 0.0;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
if (mouseInteraction) {
|
|
322
|
+
ctn.addEventListener('mousemove', handleMouseMove);
|
|
323
|
+
ctn.addEventListener('mouseleave', handleMouseLeave);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
return () => {
|
|
327
|
+
cancelAnimationFrame(animateId);
|
|
328
|
+
window.removeEventListener('resize', resize);
|
|
329
|
+
if (mouseInteraction) {
|
|
330
|
+
ctn.removeEventListener('mousemove', handleMouseMove);
|
|
331
|
+
ctn.removeEventListener('mouseleave', handleMouseLeave);
|
|
332
|
+
}
|
|
333
|
+
if (ctn.contains(gl.canvas)) {
|
|
334
|
+
ctn.removeChild(gl.canvas);
|
|
335
|
+
}
|
|
336
|
+
gl.getExtension('WEBGL_lose_context')?.loseContext();
|
|
337
|
+
};
|
|
338
|
+
}, [
|
|
339
|
+
focal,
|
|
340
|
+
rotation,
|
|
341
|
+
starSpeed,
|
|
342
|
+
density,
|
|
343
|
+
hueShift,
|
|
344
|
+
disableAnimation,
|
|
345
|
+
speed,
|
|
346
|
+
mouseInteraction,
|
|
347
|
+
glowIntensity,
|
|
348
|
+
saturation,
|
|
349
|
+
mouseRepulsion,
|
|
350
|
+
twinkleIntensity,
|
|
351
|
+
rotationSpeed,
|
|
352
|
+
repulsionStrength,
|
|
353
|
+
autoCenterRepulsion,
|
|
354
|
+
transparent
|
|
355
|
+
]);
|
|
356
|
+
|
|
357
|
+
return <div ref={ctnDom} className={`w-full h-full relative ${className}`} {...rest} />;
|
|
358
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { cn } from '../../lib/utils';
|
|
4
|
+
import { Badge } from '../data-display/Badge';
|
|
5
|
+
import { Button } from '../actions/Button';
|
|
6
|
+
import { Text } from '../data-display/Text';
|
|
7
|
+
import { ArrowRight } from 'lucide-react';
|
|
8
|
+
import { motion, Variants } from 'framer-motion';
|
|
9
|
+
import { useMotionPreference } from '../../hooks/useMotionPreference';
|
|
10
|
+
|
|
11
|
+
export interface HeroBlockProps {
|
|
12
|
+
className?: string;
|
|
13
|
+
badge?: string;
|
|
14
|
+
headline: string | React.ReactNode;
|
|
15
|
+
description: string;
|
|
16
|
+
primaryCta?: {
|
|
17
|
+
label: string;
|
|
18
|
+
onClick?: () => void;
|
|
19
|
+
href?: string;
|
|
20
|
+
variant?: "default" | "secondary" | "outline" | "ghost" | "link" | "destructive";
|
|
21
|
+
};
|
|
22
|
+
secondaryCta?: {
|
|
23
|
+
label: string;
|
|
24
|
+
onClick?: () => void;
|
|
25
|
+
href?: string;
|
|
26
|
+
};
|
|
27
|
+
background?: React.ReactNode;
|
|
28
|
+
children?: React.ReactNode; // For extra slots like animations
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function HeroBlock({
|
|
32
|
+
className,
|
|
33
|
+
badge,
|
|
34
|
+
headline,
|
|
35
|
+
description,
|
|
36
|
+
primaryCta,
|
|
37
|
+
secondaryCta,
|
|
38
|
+
background,
|
|
39
|
+
children,
|
|
40
|
+
}: HeroBlockProps) {
|
|
41
|
+
const { shouldAnimate, scale } = useMotionPreference();
|
|
42
|
+
const durationMultiplier = shouldAnimate && scale > 0 ? (5 / scale) : 0;
|
|
43
|
+
|
|
44
|
+
const containerVariants: Variants = {
|
|
45
|
+
hidden: { opacity: 0 },
|
|
46
|
+
visible: {
|
|
47
|
+
opacity: 1,
|
|
48
|
+
transition: {
|
|
49
|
+
staggerChildren: shouldAnimate ? 0.1 * durationMultiplier : 0,
|
|
50
|
+
delayChildren: shouldAnimate ? 0.2 * durationMultiplier : 0
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const itemVariants: Variants = {
|
|
56
|
+
hidden: { opacity: 0, y: shouldAnimate ? 20 : 0 },
|
|
57
|
+
visible: {
|
|
58
|
+
opacity: 1,
|
|
59
|
+
y: 0,
|
|
60
|
+
transition: shouldAnimate ? {
|
|
61
|
+
type: 'spring',
|
|
62
|
+
stiffness: 100,
|
|
63
|
+
// Adjust mass/damping if we really want to speed up spring based on intensity,
|
|
64
|
+
// but usually spring stiffness is enough.
|
|
65
|
+
// To obey strictly the speed:
|
|
66
|
+
duration: 0.5 * durationMultiplier
|
|
67
|
+
} : { duration: 0 }
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
return (
|
|
72
|
+
<div className={cn("relative min-h-[80vh] flex flex-col items-center justify-center overflow-hidden w-full", className)}>
|
|
73
|
+
{/* Background with Full-Frame & Smooth Falloff */}
|
|
74
|
+
{background && (
|
|
75
|
+
<div className="absolute inset-0 z-0 select-none pointer-events-none">
|
|
76
|
+
{/* The Background Layer */}
|
|
77
|
+
<div className="absolute inset-0">
|
|
78
|
+
{background}
|
|
79
|
+
</div>
|
|
80
|
+
|
|
81
|
+
{/* Smooth Falloff Gradient (Bottom Fade) */}
|
|
82
|
+
<div className="absolute inset-0 bg-gradient-to-b from-transparent via-transparent to-[var(--color-background)] z-10" />
|
|
83
|
+
</div>
|
|
84
|
+
)}
|
|
85
|
+
|
|
86
|
+
{/* Content */}
|
|
87
|
+
<motion.div
|
|
88
|
+
className="relative z-20 container max-w-4xl px-4 text-center space-y-8"
|
|
89
|
+
variants={containerVariants}
|
|
90
|
+
initial="hidden"
|
|
91
|
+
whileInView="visible"
|
|
92
|
+
viewport={{ once: true }}
|
|
93
|
+
>
|
|
94
|
+
{/* Badge Slot */}
|
|
95
|
+
{badge && (
|
|
96
|
+
<motion.div variants={itemVariants} className="flex justify-center">
|
|
97
|
+
<Badge variant="outline" className="backdrop-blur-md bg-[var(--color-surface)]/30 border-[var(--color-border)] px-4 py-1.5">
|
|
98
|
+
{badge}
|
|
99
|
+
</Badge>
|
|
100
|
+
</motion.div>
|
|
101
|
+
)}
|
|
102
|
+
|
|
103
|
+
{/* Headline Slot */}
|
|
104
|
+
<motion.h1
|
|
105
|
+
variants={itemVariants}
|
|
106
|
+
className="text-5xl md:text-7xl font-bold tracking-tight text-[var(--color-text-primary)]"
|
|
107
|
+
>
|
|
108
|
+
{headline}
|
|
109
|
+
</motion.h1>
|
|
110
|
+
|
|
111
|
+
{/* Description Slot */}
|
|
112
|
+
<motion.div variants={itemVariants}>
|
|
113
|
+
<Text variant="secondary" className="text-xl md:text-2xl max-w-2xl mx-auto">
|
|
114
|
+
{description}
|
|
115
|
+
</Text>
|
|
116
|
+
</motion.div>
|
|
117
|
+
|
|
118
|
+
{/* Extra Slot (e.g. Typewriter) */}
|
|
119
|
+
{children && (
|
|
120
|
+
<motion.div variants={itemVariants} className="flex justify-center">
|
|
121
|
+
{children}
|
|
122
|
+
</motion.div>
|
|
123
|
+
)}
|
|
124
|
+
|
|
125
|
+
{/* CTAs */}
|
|
126
|
+
<motion.div variants={itemVariants} className="flex flex-col sm:flex-row gap-4 justify-center items-center pt-4">
|
|
127
|
+
{primaryCta && (
|
|
128
|
+
<Button size="lg" variant={primaryCta.variant || "default"} onClick={primaryCta.onClick}>
|
|
129
|
+
{primaryCta.label}
|
|
130
|
+
<ArrowRight className="w-4 h-4 ml-2" />
|
|
131
|
+
</Button>
|
|
132
|
+
)}
|
|
133
|
+
{secondaryCta && (
|
|
134
|
+
<Button size="lg" variant="outline" className="bg-[var(--color-surface)]/50 backdrop-blur-md" onClick={secondaryCta.onClick}>
|
|
135
|
+
{secondaryCta.label}
|
|
136
|
+
</Button>
|
|
137
|
+
)}
|
|
138
|
+
</motion.div>
|
|
139
|
+
</motion.div>
|
|
140
|
+
</div>
|
|
141
|
+
);
|
|
142
|
+
}
|