404lab 2.0.1 → 2.0.2
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/cli/core/templates.js +1 -0
- package/package.json +3 -3
- package/templates/AmongUs.tsx +213 -119
- package/templates/BlueGlitch.tsx +190 -100
- package/templates/GeeksforGeeks.tsx +125 -37
- package/templates/Google.tsx +97 -29
- package/templates/MacOs.tsx +116 -212
- package/templates/ModernPage.tsx +73 -11
- package/templates/Particles.tsx +173 -67
- package/templates/Poet.tsx +139 -54
- package/templates/RetroTv.tsx +182 -130
- package/templates/SimplePage.tsx +60 -16
- package/templates/Snow.tsx +113 -179
- package/templates/StoneAge.tsx +91 -23
- package/templates/StrangerThings.tsx +79 -193
- package/templates/Terminal404.tsx +124 -242
- package/templates/Vercel.tsx +127 -0
package/templates/RetroTv.tsx
CHANGED
|
@@ -1,164 +1,216 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import { useEffect, useRef } from "react";
|
|
4
|
-
import
|
|
3
|
+
import { useEffect, useRef, useState } from "react";
|
|
4
|
+
import Link from "next/link";
|
|
5
|
+
import { motion, AnimatePresence } from "framer-motion";
|
|
6
|
+
import { cn } from "@/components/ui/cn";
|
|
5
7
|
|
|
6
|
-
const RetroTv = () => {
|
|
8
|
+
const RetroTv = ({ className }: { className?: string }) => {
|
|
7
9
|
const canvasRef = useRef<HTMLCanvasElement>(null);
|
|
10
|
+
const [isOn, setIsOn] = useState(false);
|
|
11
|
+
const [noiseIntensity, setNoiseIntensity] = useState(0.8);
|
|
12
|
+
const [channel, setChannel] = useState(404);
|
|
13
|
+
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
const timer = setTimeout(() => setIsOn(true), 500);
|
|
16
|
+
return () => clearTimeout(timer);
|
|
17
|
+
}, []);
|
|
8
18
|
|
|
9
19
|
useEffect(() => {
|
|
10
20
|
const canvas = canvasRef.current;
|
|
11
|
-
if (!canvas) return;
|
|
21
|
+
if (!canvas || !isOn) return;
|
|
12
22
|
|
|
13
23
|
const ctx = canvas.getContext("2d");
|
|
14
24
|
if (!ctx) return;
|
|
15
25
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
26
|
+
let animationFrame: number;
|
|
27
|
+
|
|
28
|
+
const resize = () => {
|
|
29
|
+
canvas.width = canvas.offsetWidth;
|
|
30
|
+
canvas.height = canvas.offsetHeight;
|
|
31
|
+
};
|
|
32
|
+
resize();
|
|
33
|
+
window.addEventListener("resize", resize);
|
|
34
|
+
|
|
35
|
+
const render = () => {
|
|
36
|
+
const w = canvas.width;
|
|
37
|
+
const h = canvas.height;
|
|
38
|
+
const imageData = ctx.createImageData(w, h);
|
|
39
|
+
const data = imageData.data;
|
|
40
|
+
|
|
41
|
+
for (let i = 0; i < data.length; i += 4) {
|
|
42
|
+
const val = Math.random() * 255 * noiseIntensity;
|
|
43
|
+
data[i] = val;
|
|
44
|
+
data[i + 1] = val;
|
|
45
|
+
data[i + 2] = val;
|
|
46
|
+
data[i + 3] = 255;
|
|
34
47
|
}
|
|
35
|
-
ctx.putImageData(imgData, 0, 0);
|
|
36
|
-
}, 30);
|
|
37
48
|
|
|
38
|
-
|
|
39
|
-
|
|
49
|
+
ctx.putImageData(imageData, 0, 0);
|
|
50
|
+
animationFrame = requestAnimationFrame(render);
|
|
51
|
+
};
|
|
40
52
|
|
|
41
|
-
|
|
42
|
-
<div className="relative h-screen w-screen overflow-hidden bg-black">
|
|
43
|
-
<h1 className="absolute left-1/2 top-1/2 z-3 -translate-x-1/2 -translate-y-1/2 text-[200px] font-bold text-transparent glitch-text">
|
|
44
|
-
404
|
|
45
|
-
</h1>
|
|
46
|
-
|
|
47
|
-
<div className="absolute inset-0 z-3 frame">
|
|
48
|
-
<div />
|
|
49
|
-
<div />
|
|
50
|
-
<div />
|
|
51
|
-
</div>
|
|
52
|
-
|
|
53
|
-
<div className="absolute inset-0 z-2 opacity-0 caps">
|
|
54
|
-
<Image
|
|
55
|
-
src="http://ademilter.com/caps.png"
|
|
56
|
-
alt="caps"
|
|
57
|
-
className="h-full w-full"
|
|
58
|
-
fill
|
|
59
|
-
/>
|
|
60
|
-
</div>
|
|
61
|
-
|
|
62
|
-
<canvas
|
|
63
|
-
ref={canvasRef}
|
|
64
|
-
className="absolute left-0 top-0 z-1 h-full w-full"
|
|
65
|
-
/>
|
|
53
|
+
render();
|
|
66
54
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
@keyframes glitch {
|
|
74
|
-
0% {
|
|
75
|
-
text-shadow: 0 0 30px rgba(0, 0, 0, 0.5);
|
|
76
|
-
}
|
|
77
|
-
33% {
|
|
78
|
-
text-shadow: 0 0 10px rgba(0, 0, 0, 0.4);
|
|
79
|
-
}
|
|
80
|
-
66% {
|
|
81
|
-
text-shadow: 0 0 20px rgba(0, 0, 0, 0.2);
|
|
82
|
-
}
|
|
83
|
-
100% {
|
|
84
|
-
text-shadow: 0 0 40px rgba(0, 0, 0, 0.8);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
55
|
+
return () => {
|
|
56
|
+
cancelAnimationFrame(animationFrame);
|
|
57
|
+
window.removeEventListener("resize", resize);
|
|
58
|
+
};
|
|
59
|
+
}, [isOn, noiseIntensity]);
|
|
87
60
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
opacity: 0.1;
|
|
101
|
-
}
|
|
102
|
-
30% {
|
|
103
|
-
opacity: 0.5;
|
|
104
|
-
}
|
|
105
|
-
40% {
|
|
106
|
-
opacity: 0;
|
|
107
|
-
}
|
|
108
|
-
50% {
|
|
109
|
-
opacity: 0.8;
|
|
110
|
-
}
|
|
111
|
-
55% {
|
|
112
|
-
opacity: 0;
|
|
113
|
-
}
|
|
114
|
-
100% {
|
|
115
|
-
opacity: 0;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
.frame {
|
|
120
|
-
background: radial-gradient(
|
|
121
|
-
ellipse at center,
|
|
122
|
-
rgba(0, 0, 0, 0) 0%,
|
|
123
|
-
rgba(0, 0, 0, 0) 19%,
|
|
124
|
-
rgba(0, 0, 0, 0.9) 100%
|
|
125
|
-
);
|
|
61
|
+
return (
|
|
62
|
+
<div
|
|
63
|
+
className={cn(
|
|
64
|
+
"min-h-screen bg-[#1a1a1a] flex items-center justify-center p-4 sm:p-8 font-mono overflow-hidden select-none",
|
|
65
|
+
className
|
|
66
|
+
)}
|
|
67
|
+
>
|
|
68
|
+
<style jsx global>{`
|
|
69
|
+
.crt-curve {
|
|
70
|
+
position: relative;
|
|
71
|
+
overflow: hidden;
|
|
72
|
+
background: #000;
|
|
126
73
|
}
|
|
127
|
-
|
|
128
|
-
.
|
|
74
|
+
|
|
75
|
+
.crt-curve::after {
|
|
76
|
+
content: " ";
|
|
77
|
+
display: block;
|
|
129
78
|
position: absolute;
|
|
79
|
+
top: 0;
|
|
130
80
|
left: 0;
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
81
|
+
bottom: 0;
|
|
82
|
+
right: 0;
|
|
83
|
+
background: linear-gradient(rgba(18, 16, 16, 0.1) 50%, rgba(0, 0, 0, 0.2) 50%), linear-gradient(90deg, rgba(255, 0, 0, 0.04), rgba(0, 255, 0, 0.01), rgba(0, 0, 255, 0.04));
|
|
84
|
+
z-index: 2;
|
|
85
|
+
background-size: 100% 4px, 6px 100%;
|
|
86
|
+
pointer-events: none;
|
|
137
87
|
}
|
|
138
88
|
|
|
139
|
-
.
|
|
140
|
-
|
|
89
|
+
.crt-curve::before {
|
|
90
|
+
content: " ";
|
|
91
|
+
display: block;
|
|
92
|
+
position: absolute;
|
|
93
|
+
top: 0;
|
|
94
|
+
left: 0;
|
|
95
|
+
bottom: 0;
|
|
96
|
+
right: 0;
|
|
97
|
+
background: radial-gradient(rgba(18, 16, 16, 0) 50%, rgba(0, 0, 0, 0.3) 100%), linear-gradient(to bottom, rgba(18, 16, 16, 0) 0%, rgba(18, 16, 16, 0.1) 50%, rgba(18, 16, 16, 0) 100%);
|
|
98
|
+
z-index: 2;
|
|
99
|
+
pointer-events: none;
|
|
141
100
|
}
|
|
142
101
|
|
|
143
|
-
.frame
|
|
144
|
-
|
|
102
|
+
.tv-frame {
|
|
103
|
+
box-shadow:
|
|
104
|
+
inset 0 0 40px rgba(0,0,0,0.8),
|
|
105
|
+
0 0 100px rgba(0,0,0,0.5),
|
|
106
|
+
0 20px 50px rgba(0,0,0,0.4);
|
|
145
107
|
}
|
|
146
108
|
|
|
147
|
-
|
|
148
|
-
|
|
109
|
+
@keyframes scanline {
|
|
110
|
+
0% { transform: translateY(-100%); }
|
|
111
|
+
100% { transform: translateY(100%); }
|
|
149
112
|
}
|
|
150
113
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
114
|
+
.scanline-overlay {
|
|
115
|
+
width: 100%;
|
|
116
|
+
height: 100px;
|
|
117
|
+
background: linear-gradient(to bottom, transparent 0%, rgba(255,255,255,0.03) 50%, transparent 100%);
|
|
118
|
+
position: absolute;
|
|
119
|
+
top: 0;
|
|
120
|
+
left: 0;
|
|
121
|
+
animation: scanline 8s linear infinite;
|
|
122
|
+
z-index: 3;
|
|
158
123
|
}
|
|
159
124
|
`}</style>
|
|
125
|
+
|
|
126
|
+
<div className="relative w-full max-w-4xl flex flex-col items-center">
|
|
127
|
+
<div className="w-full bg-[#2a2a2a] p-4 sm:p-8 rounded-[3rem] border-8 border-[#333] tv-frame">
|
|
128
|
+
<div className="aspect-[4/3] w-full bg-black rounded-[2rem] overflow-hidden crt-curve border-4 border-black box-content relative">
|
|
129
|
+
<AnimatePresence>
|
|
130
|
+
{!isOn && (
|
|
131
|
+
<motion.div
|
|
132
|
+
initial={{ scaleY: 1 }}
|
|
133
|
+
exit={{ scaleY: 0, opacity: 0 }}
|
|
134
|
+
transition={{ duration: 0.1 }}
|
|
135
|
+
className="absolute inset-0 bg-black z-[100] flex items-center justify-center"
|
|
136
|
+
/>
|
|
137
|
+
)}
|
|
138
|
+
</AnimatePresence>
|
|
139
|
+
|
|
140
|
+
{isOn && (
|
|
141
|
+
<>
|
|
142
|
+
<canvas ref={canvasRef} className="absolute inset-0 w-full h-full opacity-30" />
|
|
143
|
+
<div className="scanline-overlay" />
|
|
144
|
+
|
|
145
|
+
<div className="absolute inset-0 flex flex-col items-center justify-center z-10">
|
|
146
|
+
<motion.div
|
|
147
|
+
initial={{ scale: 0.8, opacity: 0 }}
|
|
148
|
+
animate={{ scale: 1, opacity: 1 }}
|
|
149
|
+
className="text-white text-center"
|
|
150
|
+
>
|
|
151
|
+
<h1 className="text-[6rem] sm:text-[10rem] font-bold tracking-tighter mix-blend-difference">
|
|
152
|
+
404
|
|
153
|
+
</h1>
|
|
154
|
+
<div className="px-4 py-2 bg-white text-black font-bold text-xl uppercase skew-x-[-12deg]">
|
|
155
|
+
No Signal
|
|
156
|
+
</div>
|
|
157
|
+
</motion.div>
|
|
158
|
+
</div>
|
|
159
|
+
|
|
160
|
+
<div className="absolute top-6 left-6 z-20 bg-green-500/80 text-black px-3 py-1 text-sm font-bold rounded-sm animate-pulse">
|
|
161
|
+
CH {channel}
|
|
162
|
+
</div>
|
|
163
|
+
</>
|
|
164
|
+
)}
|
|
165
|
+
</div>
|
|
166
|
+
|
|
167
|
+
<div className="grid grid-cols-2 sm:grid-cols-4 gap-4 mt-8 px-4">
|
|
168
|
+
<div className="flex flex-col gap-2">
|
|
169
|
+
<label className="text-[10px] uppercase text-white/40 tracking-widest">Intensity</label>
|
|
170
|
+
<input
|
|
171
|
+
type="range"
|
|
172
|
+
min="0" max="1" step="0.01"
|
|
173
|
+
value={noiseIntensity}
|
|
174
|
+
onChange={(e) => setNoiseIntensity(parseFloat(e.target.value))}
|
|
175
|
+
className="w-full h-1 bg-white/10 appearance-none rounded-full accent-white"
|
|
176
|
+
/>
|
|
177
|
+
</div>
|
|
178
|
+
|
|
179
|
+
<button
|
|
180
|
+
onClick={() => setChannel(prev => (prev === 404 ? 13 : 404))}
|
|
181
|
+
className="px-4 py-2 bg-[#333] hover:bg-[#444] text-white/60 text-xs rounded-md transition-colors border-b-2 border-black"
|
|
182
|
+
>
|
|
183
|
+
CHANNEL
|
|
184
|
+
</button>
|
|
185
|
+
|
|
186
|
+
<button
|
|
187
|
+
onClick={() => setIsOn(!isOn)}
|
|
188
|
+
className={cn(
|
|
189
|
+
"px-4 py-2 text-xs rounded-md transition-all border-b-2 border-black font-bold",
|
|
190
|
+
isOn ? "bg-red-900 text-red-100" : "bg-green-900 text-green-100"
|
|
191
|
+
)}
|
|
192
|
+
>
|
|
193
|
+
{isOn ? "POWER OFF" : "POWER ON"}
|
|
194
|
+
</button>
|
|
195
|
+
|
|
196
|
+
<Link
|
|
197
|
+
href="/"
|
|
198
|
+
className="px-4 py-2 bg-white text-black text-xs rounded-md font-bold text-center hover:bg-gray-200 transition-colors"
|
|
199
|
+
>
|
|
200
|
+
HOME
|
|
201
|
+
</Link>
|
|
202
|
+
</div>
|
|
203
|
+
</div>
|
|
204
|
+
|
|
205
|
+
<div className="w-1/2 h-4 sm:h-8 bg-[#222] rounded-b-[2rem] mx-auto mt-[-4px] z-[-1]" />
|
|
206
|
+
|
|
207
|
+
<div className="mt-12 text-white/10 text-xs tracking-[0.5em] uppercase pointer-events-none">
|
|
208
|
+
Solid State Electronics // Model 404-X
|
|
209
|
+
</div>
|
|
210
|
+
</div>
|
|
160
211
|
</div>
|
|
161
212
|
);
|
|
162
213
|
};
|
|
163
214
|
|
|
164
215
|
export default RetroTv;
|
|
216
|
+
|
package/templates/SimplePage.tsx
CHANGED
|
@@ -1,25 +1,69 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
+
import { motion } from "framer-motion";
|
|
3
4
|
import Link from "next/link";
|
|
5
|
+
import { cn } from "@/components/ui/cn";
|
|
4
6
|
|
|
5
|
-
const SimplePage = () => {
|
|
7
|
+
const SimplePage = ({ className }: { className?: string }) => {
|
|
6
8
|
return (
|
|
7
|
-
<
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
9
|
+
<div
|
|
10
|
+
className={cn(
|
|
11
|
+
"min-h-screen bg-white dark:bg-[#050505] flex items-center justify-center p-6 font-sans relative",
|
|
12
|
+
className
|
|
13
|
+
)}
|
|
14
|
+
>
|
|
15
|
+
<div className="absolute inset-0 z-0 bg-[radial-gradient(circle_at_center,_transparent_0%,_rgba(0,0,0,0.02)_100%)] pointer-events-none" />
|
|
16
|
+
|
|
17
|
+
<motion.div
|
|
18
|
+
initial={{ opacity: 0, y: 10 }}
|
|
19
|
+
animate={{ opacity: 1, y: 0 }}
|
|
20
|
+
transition={{ duration: 0.6, ease: [0.22, 1, 0.36, 1] }}
|
|
21
|
+
className="relative z-10 w-full max-w-[480px] text-center"
|
|
22
|
+
>
|
|
23
|
+
<div className="mb-12">
|
|
24
|
+
<motion.h1
|
|
25
|
+
initial={{ scale: 0.95 }}
|
|
26
|
+
animate={{ scale: 1 }}
|
|
27
|
+
className="text-[120px] md:text-[160px] font-black tracking-tighter text-black dark:text-white leading-none select-none"
|
|
28
|
+
>
|
|
29
|
+
404
|
|
30
|
+
</motion.h1>
|
|
31
|
+
<div className="h-px w-24 bg-black/5 dark:bg-white/5 mx-auto mt-4" />
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
<div className="space-y-6">
|
|
35
|
+
<h2 className="text-2xl font-semibold text-black dark:text-white tracking-tight">
|
|
36
|
+
Something went sideways.
|
|
37
|
+
</h2>
|
|
38
|
+
<p className="text-gray-500 dark:text-gray-400 text-lg leading-relaxed max-w-sm mx-auto font-medium">
|
|
39
|
+
The page you requested is currently unavailable.
|
|
40
|
+
It may have been moved or doesn't exist.
|
|
41
|
+
</p>
|
|
42
|
+
</div>
|
|
43
|
+
|
|
44
|
+
<div className="mt-16 flex flex-col gap-4">
|
|
45
|
+
<Link
|
|
46
|
+
href="/"
|
|
47
|
+
className="w-full bg-black dark:bg-white text-white dark:text-black font-bold py-5 rounded-2xl hover:opacity-90 transition-all active:scale-[0.98] shadow-2xl shadow-black/10 text-lg"
|
|
48
|
+
>
|
|
49
|
+
Return to Safety
|
|
50
|
+
</Link>
|
|
51
|
+
<button className="w-full text-gray-400 dark:text-gray-500 font-bold py-4 hover:text-black dark:hover:text-white transition-colors">
|
|
52
|
+
Contact Support
|
|
53
|
+
</button>
|
|
54
|
+
</div>
|
|
55
|
+
|
|
56
|
+
<div className="mt-24 pt-12 border-t border-black/[0.03] dark:border-white/[0.03] flex justify-between items-center text-[10px] text-gray-300 dark:text-gray-600 font-bold uppercase tracking-[0.2em]">
|
|
57
|
+
<span>© 2024 NOTFOUND</span>
|
|
58
|
+
<div className="flex gap-4">
|
|
59
|
+
<span>Status 404</span>
|
|
60
|
+
<span>Uptime 99.9%</span>
|
|
61
|
+
</div>
|
|
62
|
+
</div>
|
|
63
|
+
</motion.div>
|
|
64
|
+
</div>
|
|
22
65
|
);
|
|
23
66
|
};
|
|
24
67
|
|
|
25
68
|
export default SimplePage;
|
|
69
|
+
|