404lab 2.0.2 → 2.0.4

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.
@@ -1,22 +1,11 @@
1
1
  "use client";
2
2
 
3
- import { motion } from "framer-motion";
3
+
4
4
  import Link from "next/link";
5
5
  import { cn } from "@/components/ui/cn";
6
6
 
7
7
  const Poet = ({ className }: { className?: string }) => {
8
- const containerVariants = {
9
- hidden: { opacity: 0 },
10
- visible: {
11
- opacity: 1,
12
- transition: { staggerChildren: 0.15, delayChildren: 0.5 }
13
- }
14
- };
15
-
16
- const lineVariants = {
17
- hidden: { opacity: 0, x: -10 },
18
- visible: { opacity: 1, x: 0, transition: { duration: 0.8 } }
19
- };
8
+
20
9
 
21
10
  return (
22
11
  <div
@@ -50,73 +39,117 @@ const Poet = ({ className }: { className?: string }) => {
50
39
  }
51
40
  `}</style>
52
41
 
53
- <motion.div
54
- initial={{ x: "-120%", y: "20%", rotate: -10, opacity: 0 }}
55
- animate={{
56
- x: "120%",
57
- y: "80%",
58
- opacity: [0, 0.1, 0.1, 0]
59
- }}
60
- transition={{
61
- duration: 15,
62
- repeat: Infinity,
63
- ease: "linear",
64
- delay: 2
65
- }}
66
- className="absolute z-0 pointer-events-none scale-[2]"
42
+ <style jsx global>{`
43
+ @keyframes floatRotate {
44
+ 0% { transform: translateY(20%) rotate(-10deg); opacity: 0; }
45
+ 10% { opacity: 0.1; }
46
+ 90% { opacity: 0.1; }
47
+ 100% { transform: translateY(80%) rotate(0deg); opacity: 0; left: 120%; }
48
+ }
49
+
50
+ @keyframes fadeIn {
51
+ from { opacity: 0; }
52
+ to { opacity: 1; }
53
+ }
54
+
55
+ @keyframes slideInLeft {
56
+ from { opacity: 0; transform: translateX(-10px); }
57
+ to { opacity: 1; transform: translateX(0); }
58
+ }
59
+
60
+ @keyframes slideInUp {
61
+ from { opacity: 0; transform: translateY(20px); }
62
+ to { opacity: 1; transform: translateY(0); }
63
+ }
64
+
65
+ @keyframes gentleFloat {
66
+ 0%, 100% { transform: translateY(0) rotate(0); }
67
+ 50% { transform: translateY(-10px) rotate(2deg); }
68
+ }
69
+
70
+ .animate-float-bg {
71
+ animation: floatRotate 15s linear infinite;
72
+ animation-delay: 2s;
73
+ }
74
+
75
+ .animate-slide-up {
76
+ animation: slideInUp 0.8s ease-out forwards;
77
+ opacity: 0;
78
+ }
79
+
80
+ .animate-fade-in {
81
+ animation: fadeIn 0.8s ease-out forwards;
82
+ opacity: 0;
83
+ }
84
+
85
+ .animate-slide-in-left {
86
+ animation: slideInLeft 0.8s ease-out forwards;
87
+ opacity: 0;
88
+ }
89
+
90
+ .animate-gentle-float {
91
+ animation: gentleFloat 5s ease-in-out infinite;
92
+ }
93
+
94
+ .delay-100 { animation-delay: 100ms; }
95
+ .delay-200 { animation-delay: 200ms; }
96
+ .delay-300 { animation-delay: 300ms; }
97
+ .delay-400 { animation-delay: 400ms; }
98
+ .delay-500 { animation-delay: 500ms; }
99
+ .delay-600 { animation-delay: 600ms; }
100
+ .delay-700 { animation-delay: 700ms; }
101
+ .delay-800 { animation-delay: 800ms; }
102
+ .delay-900 { animation-delay: 900ms; }
103
+ .delay-3000 { animation-delay: 3s; }
104
+ `}</style>
105
+
106
+ <div
107
+ className="absolute z-0 pointer-events-none scale-[2] left-[-120%] top-[20%] animate-float-bg"
67
108
  >
68
109
  <svg width="200" height="100" viewBox="0 0 200 100" fill="currentColor" className="text-black">
69
110
  <path d="M100 50 C120 40 150 20 180 20 C160 40 140 50 100 50 C60 50 40 40 20 20 C50 20 80 40 100 50 Z" />
70
111
  <path d="M100 50 C110 55 120 65 100 80 C80 65 90 55 100 50 Z" />
71
112
  </svg>
72
- </motion.div>
113
+ </div>
73
114
 
74
- <motion.div
75
- initial={{ opacity: 0, y: 20 }}
76
- animate={{ opacity: 1, y: 0 }}
77
- className="parchment w-full max-w-4xl min-h-[70vh] rounded-sm p-8 md:p-16 flex flex-col md:flex-row gap-12 border border-[#d4c5a1] relative z-10"
115
+ <div
116
+ className="parchment w-full max-w-4xl min-h-[70vh] rounded-sm p-6 xs:p-8 md:p-16 flex flex-col md:flex-row gap-8 md:gap-12 border border-[#d4c5a1] relative z-10 animate-slide-up m-4"
78
117
  >
79
118
  <div className="flex-1 gothic-font">
80
- <motion.div
81
- variants={containerVariants}
82
- initial="hidden"
83
- animate="visible"
119
+ <div
84
120
  className="text-[#2c241a] space-y-2 md:space-y-3"
85
121
  >
86
- <motion.p variants={lineVariants} className="text-sm md:text-base opacity-60 mb-8 tracking-widest uppercase">
122
+ <p className="text-sm md:text-base opacity-60 mb-8 tracking-widest uppercase animate-slide-in-left delay-500">
87
123
  // Archive: /missing.pdf
88
- </motion.p>
89
-
90
- <motion.p variants={lineVariants}>Once upon a midnight dreary,</motion.p>
91
- <motion.p variants={lineVariants}>While I web surfed, weak and weary,</motion.p>
92
- <motion.p variants={lineVariants}>For pages long forgotten yore.</motion.p>
93
- <motion.p variants={lineVariants}>When I clicked my fav&apos;rite href,</motion.p>
94
- <motion.p variants={lineVariants}>Suddenly there came a warning,</motion.p>
95
- <motion.p variants={lineVariants}>and my heart was filled with mourning,</motion.p>
124
+ </p>
125
+
126
+ <p className="animate-slide-in-left delay-600">Once upon a midnight dreary,</p>
127
+ <p className="animate-slide-in-left delay-700">While I web surfed, weak and weary,</p>
128
+ <p className="animate-slide-in-left delay-800">For pages long forgotten yore.</p>
129
+ <p className="animate-slide-in-left delay-900">When I clicked my fav&apos;rite href,</p>
130
+ <p className="animate-slide-in-left" style={{ animationDelay: '1050ms' }}>Suddenly there came a warning,</p>
131
+ <p className="animate-slide-in-left" style={{ animationDelay: '1200ms' }}>and my heart was filled with mourning,</p>
96
132
 
97
- <motion.p variants={lineVariants} className="pt-4 text-xl md:text-2xl italic font-medium">
133
+ <p className="pt-2 sm:pt-4 text-lg sm:text-xl md:text-2xl italic font-medium animate-slide-in-left" style={{ animationDelay: '1350ms' }}>
98
134
  Mourning for my dear &quot;/missing.pdf&quot;,
99
- </motion.p>
135
+ </p>
100
136
 
101
- <motion.p variants={lineVariants} className="pt-4">&quot;Tis not possible!&quot; I muttered,</motion.p>
137
+ <p className="pt-2 sm:pt-4 animate-slide-in-left" style={{ animationDelay: '1500ms' }}>&quot;Tis not possible!&quot; I muttered,</p>
102
138
 
103
- <motion.p variants={lineVariants} className="text-2xl md:text-3xl font-bold leading-tight">
139
+ <p className="text-xl sm:text-2xl md:text-3xl font-bold leading-tight animate-slide-in-left" style={{ animationDelay: '1650ms' }}>
104
140
  &quot;Give thine pages, I implore!&quot;
105
- </motion.p>
141
+ </p>
106
142
 
107
- <motion.div variants={lineVariants} className="pt-12">
108
- <span className="text-5xl md:text-7xl font-black text-[#8b0000] drop-shadow-sm">404</span>
109
- <p className="text-lg md:text-xl font-bold mt-2 opacity-80 uppercase tracking-tighter">
143
+ <div className="pt-8 sm:pt-12 animate-slide-in-left" style={{ animationDelay: '1800ms' }}>
144
+ <span className="text-4xl sm:text-5xl md:text-7xl font-black text-[#8b0000] drop-shadow-sm">404</span>
145
+ <p className="text-base sm:text-lg md:text-xl font-bold mt-2 opacity-80 uppercase tracking-tighter">
110
146
  Quoth the server, &quot;Nevermore.&quot;
111
147
  </p>
112
- </motion.div>
113
- </motion.div>
114
-
115
- <motion.div
116
- initial={{ opacity: 0 }}
117
- animate={{ opacity: 1 }}
118
- transition={{ delay: 3 }}
119
- className="mt-12 flex gap-6"
148
+ </div>
149
+ </div>
150
+
151
+ <div
152
+ className="mt-12 flex gap-6 animate-fade-in delay-3000"
120
153
  >
121
154
  <Link
122
155
  href="/"
@@ -127,17 +160,12 @@ const Poet = ({ className }: { className?: string }) => {
127
160
  <button className="px-6 py-2 text-[#2c241a]/60 font-bold hover:text-[#2c241a] transition-all">
128
161
  Mourn Again
129
162
  </button>
130
- </motion.div>
163
+ </div>
131
164
  </div>
132
165
 
133
166
  <div className="w-full md:w-1/3 flex flex-col items-center justify-center grayscale opacity-80 contrast-125">
134
- <motion.div
135
- animate={{
136
- y: [0, -10, 0],
137
- rotate: [0, 2, 0]
138
- }}
139
- transition={{ duration: 5, repeat: Infinity, ease: "easeInOut" }}
140
- className="relative"
167
+ <div
168
+ className="relative animate-gentle-float"
141
169
  >
142
170
  <svg width="200" height="280" viewBox="0 0 200 280" className="text-[#2c241a]">
143
171
  <path fill="currentColor" d="M100 20 C120 20 160 40 160 100 C160 160 120 200 100 220 C80 200 40 160 40 100 C40 40 80 20 100 20 Z" opacity="0.1" />
@@ -145,9 +173,9 @@ const Poet = ({ className }: { className?: string }) => {
145
173
  <path stroke="currentColor" strokeWidth="2" d="M100 150 L100 240 M80 220 L120 220" />
146
174
  <circle cx="100" cy="80" r="40" fill="none" stroke="currentColor" strokeWidth="1" opacity="0.2" />
147
175
  </svg>
148
- </motion.div>
176
+ </div>
149
177
  </div>
150
- </motion.div>
178
+ </div>
151
179
  </div>
152
180
  );
153
181
  };
@@ -2,7 +2,7 @@
2
2
 
3
3
  import { useEffect, useRef, useState } from "react";
4
4
  import Link from "next/link";
5
- import { motion, AnimatePresence } from "framer-motion";
5
+
6
6
  import { cn } from "@/components/ui/cn";
7
7
 
8
8
  const RetroTv = ({ className }: { className?: string }) => {
@@ -121,21 +121,27 @@ const RetroTv = ({ className }: { className?: string }) => {
121
121
  animation: scanline 8s linear infinite;
122
122
  z-index: 3;
123
123
  }
124
+
125
+ @keyframes tvOn {
126
+ from { transform: scale(0.8); opacity: 0; }
127
+ to { transform: scale(1); opacity: 1; }
128
+ }
129
+
130
+ .animate-tv-on {
131
+ animation: tvOn 0.3s ease-out forwards;
132
+ }
124
133
  `}</style>
125
134
 
126
135
  <div className="relative w-full max-w-4xl flex flex-col items-center">
127
136
  <div className="w-full bg-[#2a2a2a] p-4 sm:p-8 rounded-[3rem] border-8 border-[#333] tv-frame">
128
137
  <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>
138
+ {/* <AnimatePresence> was here, replaced with conditional rendering and CSS based transitions */}
139
+ {!isOn && (
140
+ <div
141
+ className="absolute inset-0 bg-black z-[100] flex items-center justify-center transition-all duration-100 origin-center"
142
+ style={{ transform: isOn ? 'scaleY(0)' : 'scaleY(1)', opacity: isOn ? 0 : 1 }}
143
+ />
144
+ )}
139
145
 
140
146
  {isOn && (
141
147
  <>
@@ -143,18 +149,16 @@ const RetroTv = ({ className }: { className?: string }) => {
143
149
  <div className="scanline-overlay" />
144
150
 
145
151
  <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"
152
+ <div
153
+ className="text-white text-center animate-tv-on px-4"
150
154
  >
151
- <h1 className="text-[6rem] sm:text-[10rem] font-bold tracking-tighter mix-blend-difference">
155
+ <h1 className="text-[4rem] xs:text-[6rem] sm:text-[10rem] font-bold tracking-tighter mix-blend-difference">
152
156
  404
153
157
  </h1>
154
- <div className="px-4 py-2 bg-white text-black font-bold text-xl uppercase skew-x-[-12deg]">
158
+ <div className="px-3 sm:px-4 py-1 sm:py-2 bg-white text-black font-bold text-sm xs:text-base sm:text-xl uppercase skew-x-[-12deg] inline-block">
155
159
  No Signal
156
160
  </div>
157
- </motion.div>
161
+ </div>
158
162
  </div>
159
163
 
160
164
  <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">
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- import { motion } from "framer-motion";
3
+
4
4
  import Link from "next/link";
5
5
  import { cn } from "@/components/ui/cn";
6
6
 
@@ -12,30 +12,45 @@ const SimplePage = ({ className }: { className?: string }) => {
12
12
  className
13
13
  )}
14
14
  >
15
+ <style jsx global>{`
16
+ @keyframes fadeInUp {
17
+ from { opacity: 0; transform: translateY(10px); }
18
+ to { opacity: 1; transform: translateY(0); }
19
+ }
20
+
21
+ @keyframes scaleIn {
22
+ from { transform: scale(0.95); }
23
+ to { transform: scale(1); }
24
+ }
25
+
26
+ .animate-fade-in-up {
27
+ animation: fadeInUp 0.6s cubic-bezier(0.22, 1, 0.36, 1) forwards;
28
+ opacity: 0;
29
+ }
30
+
31
+ .animate-scale-in {
32
+ animation: scaleIn 0.6s cubic-bezier(0.22, 1, 0.36, 1) forwards;
33
+ }
34
+ `}</style>
15
35
  <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
36
 
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"
37
+ <div
38
+ className="relative z-10 w-full max-w-[480px] text-center animate-fade-in-up"
22
39
  >
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"
40
+ <div className="mb-8 sm:mb-12">
41
+ <h1
42
+ className="text-[100px] xs:text-[120px] md:text-[160px] font-black tracking-tighter text-black dark:text-white leading-none select-none animate-scale-in"
28
43
  >
29
44
  404
30
- </motion.h1>
31
- <div className="h-px w-24 bg-black/5 dark:bg-white/5 mx-auto mt-4" />
45
+ </h1>
46
+ <div className="h-px w-16 sm:w-24 bg-black/5 dark:bg-white/5 mx-auto mt-4" />
32
47
  </div>
33
48
 
34
- <div className="space-y-6">
35
- <h2 className="text-2xl font-semibold text-black dark:text-white tracking-tight">
49
+ <div className="space-y-4 sm:space-y-6 px-4">
50
+ <h2 className="text-xl sm:text-2xl font-semibold text-black dark:text-white tracking-tight">
36
51
  Something went sideways.
37
52
  </h2>
38
- <p className="text-gray-500 dark:text-gray-400 text-lg leading-relaxed max-w-sm mx-auto font-medium">
53
+ <p className="text-gray-500 dark:text-gray-400 text-base sm:text-lg leading-relaxed max-w-sm mx-auto font-medium">
39
54
  The page you requested is currently unavailable.
40
55
  It may have been moved or doesn&apos;t exist.
41
56
  </p>
@@ -60,7 +75,7 @@ const SimplePage = ({ className }: { className?: string }) => {
60
75
  <span>Uptime 99.9%</span>
61
76
  </div>
62
77
  </div>
63
- </motion.div>
78
+ </div>
64
79
  </div>
65
80
  );
66
81
  };
@@ -2,14 +2,20 @@
2
2
 
3
3
  import { useEffect, useRef, useState } from "react";
4
4
  import Link from "next/link";
5
- import { motion, AnimatePresence } from "framer-motion";
5
+
6
6
  import { cn } from "@/components/ui/cn";
7
7
 
8
8
  const Snow = ({ className }: { className?: string }) => {
9
9
  const canvasRef = useRef<HTMLCanvasElement>(null);
10
10
  const [isHovered, setIsHovered] = useState(false);
11
+ const [mounted, setMounted] = useState(false);
11
12
 
12
13
  useEffect(() => {
14
+ setMounted(true);
15
+ }, []);
16
+
17
+ useEffect(() => {
18
+ if (!mounted) return;
13
19
  const canvas = canvasRef.current;
14
20
  if (!canvas) return;
15
21
  const ctx = canvas.getContext("2d");
@@ -68,12 +74,14 @@ const Snow = ({ className }: { className?: string }) => {
68
74
  window.removeEventListener("resize", resize);
69
75
  cancelAnimationFrame(animationFrame);
70
76
  };
71
- }, []);
77
+ }, [mounted]);
78
+
79
+ if (!mounted) return null;
72
80
 
73
81
  return (
74
82
  <div
75
83
  className={cn(
76
- "min-h-screen flex flex-col items-center justify-center overflow-hidden bg-gradient-to-b from-[#b7d1e5] via-[#e8f2f6] to-white relative",
84
+ "min-h-screen w-full flex flex-col items-center justify-center overflow-hidden bg-gradient-to-b from-[#b7d1e5] via-[#e8f2f6] to-white relative",
77
85
  className
78
86
  )}
79
87
  >
@@ -81,15 +89,42 @@ const Snow = ({ className }: { className?: string }) => {
81
89
 
82
90
  <div className="absolute inset-0 z-0 bg-[radial-gradient(circle_at_center,_transparent_0%,_rgba(255,255,255,0.4)_100%)]" />
83
91
 
84
- <motion.main
85
- initial={{ opacity: 0, y: 20 }}
86
- animate={{ opacity: 1, y: 0 }}
87
- className="z-20 text-center px-4"
92
+ <style jsx global>{`
93
+ @keyframes fadeInUp {
94
+ from { opacity: 0; transform: translateY(20px); }
95
+ to { opacity: 1; transform: translateY(0); }
96
+ }
97
+
98
+ .animate-fade-in-up {
99
+ animation: fadeInUp 0.8s ease-out forwards;
100
+ opacity: 0;
101
+ }
102
+
103
+ .hover-404:hover .text-404 {
104
+ transform: scale(1.05);
105
+ opacity: 0.3;
106
+ }
107
+
108
+ .hover-404:hover .decoration-404 {
109
+ transform: translate(5px, -5px) rotate(10deg);
110
+ }
111
+
112
+ .text-404 {
113
+ transition: transform 0.3s ease, opacity 0.3s ease;
114
+ }
115
+
116
+ .decoration-404 {
117
+ transition: transform 0.3s ease;
118
+ }
119
+ `}</style>
120
+
121
+ <main
122
+ className="z-20 text-center px-4 animate-fade-in-up"
88
123
  >
89
- <h1 className="text-4xl md:text-7xl font-bold text-[#5d7399] mb-4 tracking-tight">
124
+ <h1 className="text-3xl xs:text-4xl md:text-7xl font-bold text-[#5d7399] mb-4 tracking-tight">
90
125
  Frozen in Time.
91
126
  </h1>
92
- <p className="text-[#5d7399]/70 text-lg md:text-2xl mb-12 max-w-2xl mx-auto font-medium">
127
+ <p className="text-[#5d7399]/70 text-base xs:text-lg md:text-2xl mb-8 sm:mb-12 max-w-xs xs:max-w-lg md:max-w-2xl mx-auto font-medium px-4">
93
128
  The page you are looking for has been buried under a heavy snowfall.
94
129
  Let&apos;s get you somewhere warmer.
95
130
  </p>
@@ -100,35 +135,33 @@ const Snow = ({ className }: { className?: string }) => {
100
135
  >
101
136
  Hitch a ride back home
102
137
  </Link>
103
- </motion.main>
138
+ </main>
104
139
 
105
140
  <div className="absolute bottom-0 w-full h-[30vh] z-10">
106
141
  <svg viewBox="0 0 1440 320" className="absolute bottom-0 w-full h-full drop-shadow-[-20px_-20px_40px_rgba(255,255,255,0.5)]">
107
142
  <path fill="#f8f9fa" d="M0,192L48,197.3C96,203,192,213,288,192C384,171,480,117,576,117.3C672,117,768,171,864,197.3C960,224,1056,224,1152,202.7C1248,181,1344,139,1392,117.3L1440,96L1440,320L1392,320C1344,320,1248,320,1152,320C1056,320,960,320,864,320C768,320,672,320,576,320C480,320,384,320,288,320C192,320,96,320,48,320L0,320Z"></path>
108
143
  </svg>
109
144
 
110
- <motion.div
111
- className="absolute bottom-[10%] left-1/2 -translate-x-1/2 z-20"
145
+ <div
146
+ className="absolute bottom-[10%] left-1/2 -translate-x-1/2 z-20 hover-404"
112
147
  onMouseEnter={() => setIsHovered(true)}
113
148
  onMouseLeave={() => setIsHovered(false)}
114
149
  >
115
150
  <div className="relative group cursor-pointer">
116
- <motion.h2
117
- className="text-8xl md:text-[12rem] font-black text-[#6b85b2] opacity-20 select-none tracking-tighter"
118
- animate={isHovered ? { scale: 1.05, opacity: 0.3 } : {}}
151
+ <h2
152
+ className="text-7xl xs:text-8xl md:text-[12rem] font-black text-[#6b85b2] opacity-20 select-none tracking-tighter text-404"
119
153
  >
120
154
  404
121
- </motion.h2>
155
+ </h2>
122
156
 
123
- <motion.div
124
- className="absolute -right-12 -top-12 w-16 h-16 pointer-events-none"
125
- animate={isHovered ? { rotate: [0, -20, 10, 0], x: [0, -5, 5, 0] } : {}}
157
+ <div
158
+ className="absolute -right-12 -top-12 w-16 h-16 pointer-events-none decoration-404"
126
159
  >
127
160
  <div className="w-1 h-20 bg-[#dd4040]/20 absolute left-1/2 -translate-x-1/2 top-0" />
128
161
  <div className="w-10 h-8 bg-[#dd4040] absolute bottom-0 left-0 rounded-sm" />
129
- </motion.div>
162
+ </div>
130
163
  </div>
131
- </motion.div>
164
+ </div>
132
165
  </div>
133
166
 
134
167
  <div className="absolute top-10 right-10 flex gap-4 opacity-20">