@alkimi.org/ui-kit 0.1.13 → 0.1.15
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.github.md +166 -100
- package/README.md +182 -97
- package/README.npm.md +182 -97
- package/dist/HelveticaNowDisplay-Medium-CXVMKHU3.ttf +0 -0
- package/dist/HelveticaNowDisplay-Regular-O4IVE4NP.ttf +0 -0
- package/dist/chunk-2XHWLYXD.mjs +3 -0
- package/dist/chunk-2XHWLYXD.mjs.map +1 -0
- package/dist/chunk-74PDRKS7.js +3 -0
- package/dist/chunk-74PDRKS7.js.map +1 -0
- package/dist/chunk-BCAQUOTY.mjs +3 -0
- package/dist/chunk-BCAQUOTY.mjs.map +1 -0
- package/dist/chunk-FUYXCJOQ.js +3 -0
- package/dist/chunk-FUYXCJOQ.js.map +1 -0
- package/dist/chunk-IK3C7KV5.mjs +3 -0
- package/dist/chunk-IK3C7KV5.mjs.map +1 -0
- package/dist/chunk-JNEIOQGF.js +3 -0
- package/dist/chunk-JNEIOQGF.js.map +1 -0
- package/dist/chunk-R74QDO2Z.js +3 -0
- package/dist/chunk-R74QDO2Z.js.map +1 -0
- package/dist/chunk-S5TKCF6T.mjs +3 -0
- package/dist/chunk-S5TKCF6T.mjs.map +1 -0
- package/dist/chunk-SVWC2KRP.js +3 -0
- package/dist/chunk-SVWC2KRP.js.map +1 -0
- package/dist/chunk-WF73K6X2.mjs +3 -0
- package/dist/chunk-WF73K6X2.mjs.map +1 -0
- package/dist/chunk-WJXJQZGO.js +3 -0
- package/dist/chunk-WJXJQZGO.js.map +1 -0
- package/dist/chunk-XNHJPYUV.mjs +3 -0
- package/dist/chunk-XNHJPYUV.mjs.map +1 -0
- package/dist/components/GlitchLink.js +2 -88
- package/dist/components/GlitchLink.js.map +1 -1
- package/dist/components/GlitchLink.mjs +1 -57
- package/dist/components/GlitchLink.mjs.map +1 -1
- package/dist/components/PixelLoad.js +2 -181
- package/dist/components/PixelLoad.js.map +1 -1
- package/dist/components/PixelLoad.mjs +1 -146
- package/dist/components/PixelLoad.mjs.map +1 -1
- package/dist/components/TextDecoder.js +2 -284
- package/dist/components/TextDecoder.js.map +1 -1
- package/dist/components/TextDecoder.mjs +1 -257
- package/dist/components/TextDecoder.mjs.map +1 -1
- package/dist/components/button.d.mts +1 -1
- package/dist/components/button.d.ts +1 -1
- package/dist/components/button.js +2 -108
- package/dist/components/button.js.map +1 -1
- package/dist/components/button.mjs +2 -73
- package/dist/components/button.mjs.map +1 -1
- package/dist/components/card.js +2 -114
- package/dist/components/card.js.map +1 -1
- package/dist/components/card.mjs +2 -75
- package/dist/components/card.mjs.map +1 -1
- package/dist/components/tabs.d.mts +9 -0
- package/dist/components/tabs.d.ts +9 -0
- package/dist/components/tabs.js +3 -0
- package/dist/components/tabs.js.map +1 -0
- package/dist/components/tabs.mjs +3 -0
- package/dist/components/tabs.mjs.map +1 -0
- package/dist/fonts/fonts/HelveticaNowDisplay-Medium.ttf +0 -0
- package/dist/fonts/fonts/HelveticaNowDisplay-Regular.ttf +0 -0
- package/dist/index.css +2 -807
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +6 -9
- package/dist/index.d.ts +6 -9
- package/dist/index.js +2 -598
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2 -563
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +2 -807
- package/dist/styles.css.map +1 -1
- package/package.json +18 -40
- package/dist/lib/utils.d.mts +0 -5
- package/dist/lib/utils.d.ts +0 -5
- package/dist/lib/utils.js +0 -36
- package/dist/lib/utils.js.map +0 -1
- package/dist/lib/utils.mjs +0 -12
- package/dist/lib/utils.mjs.map +0 -1
package/README.npm.md
CHANGED
|
@@ -10,95 +10,59 @@ npm install @alkimi.org/ui-kit
|
|
|
10
10
|
|
|
11
11
|
## Setup
|
|
12
12
|
|
|
13
|
-
### 1. Install Tailwind CSS
|
|
13
|
+
### 1. Install Tailwind CSS v4
|
|
14
14
|
|
|
15
|
-
If you haven't already, install Tailwind CSS in your project:
|
|
15
|
+
If you haven't already, install Tailwind CSS v4 and its dependencies in your project:
|
|
16
16
|
|
|
17
17
|
```bash
|
|
18
|
-
npm install -D tailwindcss postcss autoprefixer
|
|
19
|
-
npx tailwindcss init -p
|
|
18
|
+
npm install -D tailwindcss@next @tailwindcss/postcss@next postcss autoprefixer
|
|
20
19
|
```
|
|
21
20
|
|
|
22
|
-
### 2. Configure
|
|
21
|
+
### 2. Configure PostCSS
|
|
23
22
|
|
|
24
|
-
|
|
23
|
+
Create or update your `postcss.config.js`:
|
|
24
|
+
|
|
25
|
+
```js
|
|
26
|
+
module.exports = {
|
|
27
|
+
plugins: {
|
|
28
|
+
"@tailwindcss/postcss": {},
|
|
29
|
+
autoprefixer: {},
|
|
30
|
+
},
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### 3. Configure Tailwind
|
|
35
|
+
|
|
36
|
+
Create a `tailwind.config.js` to specify your content paths:
|
|
25
37
|
|
|
26
38
|
```js
|
|
27
39
|
/** @type {import('tailwindcss').Config} */
|
|
28
40
|
module.exports = {
|
|
29
|
-
darkMode: ["class"],
|
|
30
41
|
content: [
|
|
42
|
+
// Scans YOUR project files for Tailwind classes
|
|
31
43
|
"./src/**/*.{js,jsx,ts,tsx}",
|
|
44
|
+
"./app/**/*.{js,jsx,ts,tsx}", // If using Next.js App Router
|
|
45
|
+
"./pages/**/*.{js,jsx,ts,tsx}", // If using Next.js Pages Router
|
|
46
|
+
"./components/**/*.{js,jsx,ts,tsx}",
|
|
47
|
+
|
|
48
|
+
// Scans the UI Kit's components for their Tailwind classes
|
|
49
|
+
// (Required for library components to be styled correctly)
|
|
32
50
|
"./node_modules/@alkimi.org/ui-kit/dist/**/*.{js,mjs}",
|
|
33
51
|
],
|
|
34
|
-
theme: {
|
|
35
|
-
fontSize: {
|
|
36
|
-
xs: ['0.75rem', '1rem'],
|
|
37
|
-
sm: ['12px', '1.25rem'],
|
|
38
|
-
base: ['14px', '1.5rem'],
|
|
39
|
-
lg: ['1.125rem', '1.75rem'],
|
|
40
|
-
xl: ['1.25rem', '1.75rem'],
|
|
41
|
-
'2xl': ['1.5rem', '2rem'],
|
|
42
|
-
'3xl': ['1.875rem', '2.25rem'],
|
|
43
|
-
'4xl': ['2.25rem', '2.5rem'],
|
|
44
|
-
'5xl': ['3rem', '1'],
|
|
45
|
-
'6xl': ['3.75rem', '1'],
|
|
46
|
-
'7xl': ['4.5rem', '1'],
|
|
47
|
-
'8xl': ['6rem', '1'],
|
|
48
|
-
'9xl': ['8rem', '1'],
|
|
49
|
-
},
|
|
50
|
-
extend: {
|
|
51
|
-
colors: {
|
|
52
|
-
border: "hsl(var(--border))",
|
|
53
|
-
input: "hsl(var(--input))",
|
|
54
|
-
ring: "hsl(var(--ring))",
|
|
55
|
-
background: "hsl(var(--background))",
|
|
56
|
-
foreground: "hsl(var(--foreground))",
|
|
57
|
-
primary: {
|
|
58
|
-
DEFAULT: "hsl(var(--primary))",
|
|
59
|
-
foreground: "hsl(var(--primary-foreground))",
|
|
60
|
-
},
|
|
61
|
-
secondary: {
|
|
62
|
-
DEFAULT: "hsl(var(--secondary))",
|
|
63
|
-
foreground: "hsl(var(--secondary-foreground))",
|
|
64
|
-
},
|
|
65
|
-
destructive: {
|
|
66
|
-
DEFAULT: "hsl(var(--destructive))",
|
|
67
|
-
foreground: "hsl(var(--destructive-foreground))",
|
|
68
|
-
},
|
|
69
|
-
muted: {
|
|
70
|
-
DEFAULT: "hsl(var(--muted))",
|
|
71
|
-
foreground: "hsl(var(--muted-foreground))",
|
|
72
|
-
},
|
|
73
|
-
accent: {
|
|
74
|
-
DEFAULT: "hsl(var(--accent))",
|
|
75
|
-
foreground: "hsl(var(--accent-foreground))",
|
|
76
|
-
},
|
|
77
|
-
popover: {
|
|
78
|
-
DEFAULT: "hsl(var(--popover))",
|
|
79
|
-
foreground: "hsl(var(--popover-foreground))",
|
|
80
|
-
},
|
|
81
|
-
card: {
|
|
82
|
-
DEFAULT: "hsl(var(--card))",
|
|
83
|
-
foreground: "hsl(var(--card-foreground))",
|
|
84
|
-
},
|
|
85
|
-
},
|
|
86
|
-
borderRadius: {
|
|
87
|
-
DEFAULT: "var(--radius)",
|
|
88
|
-
lg: "calc(var(--radius) + 2px)",
|
|
89
|
-
md: "var(--radius)",
|
|
90
|
-
sm: "calc(var(--radius) - 2px)",
|
|
91
|
-
xl: "calc(var(--radius) + 4px)",
|
|
92
|
-
"2xl": "calc(var(--radius) + 6px)",
|
|
93
|
-
"3xl": "3.75rem",
|
|
94
|
-
},
|
|
95
|
-
},
|
|
96
|
-
},
|
|
97
|
-
plugins: [require("tailwindcss-animate")],
|
|
98
52
|
}
|
|
99
53
|
```
|
|
100
54
|
|
|
101
|
-
|
|
55
|
+
**Important**: The second path (`node_modules/@alkimi.org/ui-kit/dist/...`) is **required** for the library components to display correctly. It tells Tailwind to scan the library's compiled files and generate CSS for the utility classes used inside the components (like `bg-primary`, `rounded-3xl`, etc.).
|
|
56
|
+
|
|
57
|
+
### 4. Import Tailwind in Your CSS
|
|
58
|
+
|
|
59
|
+
Create or update your main CSS file (e.g., `app.css` or `globals.css`):
|
|
60
|
+
|
|
61
|
+
```css
|
|
62
|
+
@import "tailwindcss";
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### 5. Import Styles
|
|
102
66
|
|
|
103
67
|
Import the library's CSS in your main application file (e.g., `App.tsx` or `index.tsx`):
|
|
104
68
|
|
|
@@ -106,46 +70,145 @@ Import the library's CSS in your main application file (e.g., `App.tsx` or `inde
|
|
|
106
70
|
import "@alkimi.org/ui-kit/styles.css"
|
|
107
71
|
```
|
|
108
72
|
|
|
109
|
-
|
|
73
|
+
## Customizing Colors
|
|
74
|
+
|
|
75
|
+
The library uses CSS variables for colors, making it easy to customize. You have two approaches:
|
|
76
|
+
|
|
77
|
+
### Option A: Override CSS Variables (Recommended)
|
|
78
|
+
|
|
79
|
+
Add custom color values to your CSS file **after** importing the library styles:
|
|
80
|
+
|
|
81
|
+
```css
|
|
82
|
+
/* In your app.css or globals.css */
|
|
83
|
+
@import "tailwindcss";
|
|
84
|
+
@import "@alkimi.org/ui-kit/styles.css";
|
|
85
|
+
|
|
86
|
+
/* 👇 Override the library's default colors */
|
|
87
|
+
@layer base {
|
|
88
|
+
:root {
|
|
89
|
+
/* Your custom colors (HSL format: Hue Saturation% Lightness%) */
|
|
90
|
+
--primary: 220 100% 50%; /* Custom blue primary color */
|
|
91
|
+
--primary-foreground: 0 0% 100%; /* White text on primary */
|
|
92
|
+
--secondary: 280 60% 60%; /* Custom purple secondary */
|
|
93
|
+
--background: 0 0% 100%; /* White background */
|
|
94
|
+
--foreground: 0 0% 0%; /* Black text */
|
|
95
|
+
|
|
96
|
+
/* You can override any of these variables:
|
|
97
|
+
--muted, --muted-foreground
|
|
98
|
+
--accent, --accent-foreground
|
|
99
|
+
--destructive, --destructive-foreground
|
|
100
|
+
--border, --input, --ring
|
|
101
|
+
--radius (border radius)
|
|
102
|
+
*/
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Option B: Don't Import Library CSS (Manual Setup)
|
|
108
|
+
|
|
109
|
+
If you want complete control, skip importing the library CSS and define all variables yourself:
|
|
110
110
|
|
|
111
111
|
```css
|
|
112
|
+
/* In your app.css or globals.css */
|
|
113
|
+
@import "tailwindcss";
|
|
114
|
+
|
|
112
115
|
@layer base {
|
|
113
116
|
:root {
|
|
114
|
-
/*
|
|
115
|
-
--background:
|
|
116
|
-
--foreground:
|
|
117
|
-
--card: 0 0%
|
|
118
|
-
--card-foreground:
|
|
119
|
-
--popover: 0 0%
|
|
120
|
-
--popover-foreground:
|
|
121
|
-
--primary:
|
|
122
|
-
--primary-foreground:
|
|
123
|
-
--secondary:
|
|
124
|
-
--secondary-foreground:
|
|
125
|
-
--muted:
|
|
126
|
-
--muted-foreground:
|
|
127
|
-
--accent: 0 0%
|
|
128
|
-
--accent-foreground:
|
|
129
|
-
--destructive: 0
|
|
130
|
-
--destructive-foreground:
|
|
131
|
-
--border:
|
|
132
|
-
--input:
|
|
133
|
-
--ring:
|
|
134
|
-
--radius: 0.
|
|
117
|
+
/* Define ALL color variables used by the library */
|
|
118
|
+
--background: 0 0% 100%;
|
|
119
|
+
--foreground: 0 0% 0%;
|
|
120
|
+
--card: 0 0% 100%;
|
|
121
|
+
--card-foreground: 0 0% 0%;
|
|
122
|
+
--popover: 0 0% 100%;
|
|
123
|
+
--popover-foreground: 0 0% 0%;
|
|
124
|
+
--primary: 220 100% 50%;
|
|
125
|
+
--primary-foreground: 0 0% 100%;
|
|
126
|
+
--secondary: 280 60% 60%;
|
|
127
|
+
--secondary-foreground: 0 0% 100%;
|
|
128
|
+
--muted: 0 0% 96%;
|
|
129
|
+
--muted-foreground: 0 0% 45%;
|
|
130
|
+
--accent: 0 0% 96%;
|
|
131
|
+
--accent-foreground: 0 0% 0%;
|
|
132
|
+
--destructive: 0 84% 60%;
|
|
133
|
+
--destructive-foreground: 0 0% 100%;
|
|
134
|
+
--border: 0 0% 90%;
|
|
135
|
+
--input: 0 0% 90%;
|
|
136
|
+
--ring: 220 100% 50%;
|
|
137
|
+
--radius: 0.5rem;
|
|
135
138
|
}
|
|
136
139
|
|
|
137
140
|
body {
|
|
138
|
-
|
|
141
|
+
@apply bg-background text-foreground;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
**Note**: When using Option B, don't import `@alkimi.org/ui-kit/styles.css` in your code.
|
|
147
|
+
|
|
148
|
+
## Typography & Sizing
|
|
149
|
+
|
|
150
|
+
### Default Font
|
|
151
|
+
|
|
152
|
+
The library uses **Helvetica Now Display** as the default font family. This font is included in the library and will be automatically loaded when you import the styles.
|
|
153
|
+
|
|
154
|
+
### Font Sizes
|
|
155
|
+
|
|
156
|
+
The library uses **rem-based sizing** with a base font size of **1rem (16px)**. All font sizes use rem units for better accessibility and scalability:
|
|
157
|
+
|
|
158
|
+
- **Base text**: 1rem (16px)
|
|
159
|
+
- **Small text**: 0.875rem (14px) - Used in small buttons, captions, etc.
|
|
160
|
+
- **Large text**: 1.125rem (18px) and above
|
|
161
|
+
|
|
162
|
+
### Button Sizes
|
|
163
|
+
|
|
164
|
+
Buttons have the following font sizes by default:
|
|
165
|
+
|
|
166
|
+
- **Small** (`size="sm"`): 0.875rem (14px)
|
|
167
|
+
- **Default**: 1rem (16px)
|
|
168
|
+
- **Large** (`size="lg"`): 1rem (16px)
|
|
169
|
+
|
|
170
|
+
You can override these sizes using Tailwind's text utility classes (e.g., `className="text-lg"`) on any component.
|
|
171
|
+
|
|
172
|
+
## Customizing Font
|
|
173
|
+
|
|
174
|
+
You can override the default font family by setting the `--font-family` CSS variable in your own CSS file:
|
|
175
|
+
|
|
176
|
+
```css
|
|
177
|
+
/* In your app.css or globals.css */
|
|
178
|
+
@import "tailwindcss";
|
|
179
|
+
@import "@alkimi.org/ui-kit/styles.css";
|
|
180
|
+
|
|
181
|
+
@layer base {
|
|
182
|
+
:root {
|
|
183
|
+
/* Override the library's default font */
|
|
184
|
+
--font-family: 'Your Custom Font', 'Helvetica', sans-serif;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Make sure to include your custom font using `@font-face` or a web font service like Google Fonts:
|
|
190
|
+
|
|
191
|
+
```css
|
|
192
|
+
/* Example: Using Google Fonts */
|
|
193
|
+
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
|
|
194
|
+
|
|
195
|
+
@layer base {
|
|
196
|
+
:root {
|
|
197
|
+
--font-family: 'Inter', system-ui, sans-serif;
|
|
139
198
|
}
|
|
140
199
|
}
|
|
141
200
|
```
|
|
142
201
|
|
|
143
202
|
## Usage
|
|
144
203
|
|
|
145
|
-
|
|
204
|
+
You can import components in two ways:
|
|
205
|
+
|
|
206
|
+
### Option 1: Import from Main Package
|
|
207
|
+
|
|
208
|
+
Import all components from the main package entry point:
|
|
146
209
|
|
|
147
210
|
```tsx
|
|
148
|
-
import { Button } from "@alkimi.org/ui-kit"
|
|
211
|
+
import { Button, Tabs } from "@alkimi.org/ui-kit"
|
|
149
212
|
|
|
150
213
|
function App() {
|
|
151
214
|
return (
|
|
@@ -163,6 +226,28 @@ function App() {
|
|
|
163
226
|
}
|
|
164
227
|
```
|
|
165
228
|
|
|
229
|
+
### Option 2: Import Individual Components (Optimized Bundle Size)
|
|
230
|
+
|
|
231
|
+
For better code splitting and smaller production bundles, import components individually:
|
|
232
|
+
|
|
233
|
+
```tsx
|
|
234
|
+
// Import only the Button component
|
|
235
|
+
import { Button } from "@alkimi.org/ui-kit/button"
|
|
236
|
+
|
|
237
|
+
// Import only the Tabs components
|
|
238
|
+
import {
|
|
239
|
+
Tabs,
|
|
240
|
+
TabsList,
|
|
241
|
+
TabsTrigger,
|
|
242
|
+
TabsContent,
|
|
243
|
+
} from "@alkimi.org/ui-kit/tabs"
|
|
244
|
+
|
|
245
|
+
// Import utilities
|
|
246
|
+
import { cn } from "@alkimi.org/ui-kit/utils"
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
**Note**: Both import methods require installing the full `@alkimi.org/ui-kit` package. The individual imports help optimize your production bundle size (only used components are included), but don't reduce installation size.
|
|
250
|
+
|
|
166
251
|
## License
|
|
167
252
|
|
|
168
253
|
MIT
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import{a as o}from"./chunk-S5TKCF6T.mjs";import*as e from"@radix-ui/react-tabs";import{forwardRef as a,useCallback as p,useEffect as g,useRef as T,useState as R}from"react";import{jsx as l,jsxs as L}from"react/jsx-runtime";var C=e.Root,y=a(({className:r,...n},t)=>{let[c,b]=R({left:0,width:0}),s=T(null);g(()=>{let i=()=>{if(!s.current)return;let f=s.current.querySelector('[data-state="active"]');if(f){let v=s.current.getBoundingClientRect(),m=f.getBoundingClientRect();b({left:m.left-v.left,width:m.width})}};i();let u=new MutationObserver(i);return s.current&&u.observe(s.current,{attributes:!0,attributeFilter:["data-state"],subtree:!0}),window.addEventListener("resize",i),()=>{u.disconnect(),window.removeEventListener("resize",i)}},[]);let d=p(i=>{s.current=i,typeof t=="function"?t(i):t&&(t.current=i)},[t]);return L(e.List,{ref:d,className:o("relative inline-flex items-center justify-center rounded-3xl bg-muted p-1 text-muted-foreground",r),...n,children:[l("span",{className:"absolute h-[calc(100%-0.5rem)] rounded-3xl bg-background shadow-sm transition-all duration-200 ease-out",style:{left:`${c.left}px`,width:`${c.width}px`}}),n.children]})});y.displayName=e.List.displayName;var P=a(({className:r,...n},t)=>l(e.Trigger,{ref:t,className:o("cursor-pointer relative inline-flex items-center justify-center whitespace-nowrap rounded-3xl px-3 py-1 text-sm font-medium ring-offset-background transition-colors duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:text-foreground z-10",r),...n}));P.displayName=e.Trigger.displayName;var w=a(({className:r,...n},t)=>l(e.Content,{ref:t,className:o("mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",r),...n}));w.displayName=e.Content.displayName;export{C as a,y as b,P as c,w as d};
|
|
3
|
+
//# sourceMappingURL=chunk-2XHWLYXD.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/tabs.tsx"],"sourcesContent":["import * as TabsPrimitive from \"@radix-ui/react-tabs\"\n\nimport { cn } from \"@/lib/utils\"\nimport { forwardRef, useCallback, useEffect, useRef, useState } from \"react\"\n\nconst Tabs = TabsPrimitive.Root\n\nconst TabsList = forwardRef<\n React.ElementRef<typeof TabsPrimitive.List>,\n React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>\n>(({ className, ...props }, ref) => {\n const [indicatorStyle, setIndicatorStyle] = useState({\n left: 0,\n width: 0,\n })\n const listRef = useRef<HTMLDivElement>(null)\n\n useEffect(() => {\n const updateIndicator = () => {\n if (!listRef.current) return\n\n const activeTab = listRef.current.querySelector(\n '[data-state=\"active\"]'\n ) as HTMLElement\n\n if (activeTab) {\n const listRect = listRef.current.getBoundingClientRect()\n const tabRect = activeTab.getBoundingClientRect()\n\n setIndicatorStyle({\n left: tabRect.left - listRect.left,\n width: tabRect.width,\n })\n }\n }\n\n updateIndicator()\n\n // Use MutationObserver to detect when data-state changes\n const observer = new MutationObserver(updateIndicator)\n\n if (listRef.current) {\n observer.observe(listRef.current, {\n attributes: true,\n attributeFilter: [\"data-state\"],\n subtree: true,\n })\n }\n\n // Also update on window resize\n window.addEventListener(\"resize\", updateIndicator)\n\n return () => {\n observer.disconnect()\n window.removeEventListener(\"resize\", updateIndicator)\n }\n }, [])\n\n // Combine refs\n const combinedRef = useCallback(\n (node: HTMLDivElement | null) => {\n ;(listRef as React.MutableRefObject<HTMLDivElement | null>).current = node\n\n if (typeof ref === \"function\") {\n ref(node)\n } else if (ref) {\n ;(ref as React.MutableRefObject<HTMLDivElement | null>).current = node\n }\n },\n [ref]\n )\n\n return (\n <TabsPrimitive.List\n ref={combinedRef}\n className={cn(\n \"relative inline-flex items-center justify-center rounded-3xl bg-muted p-1 text-muted-foreground\",\n className\n )}\n {...props}\n >\n {/* Animated indicator */}\n <span\n className=\"absolute h-[calc(100%-0.5rem)] rounded-3xl bg-background shadow-sm transition-all duration-200 ease-out\"\n style={{\n left: `${indicatorStyle.left}px`,\n width: `${indicatorStyle.width}px`,\n }}\n />\n {props.children}\n </TabsPrimitive.List>\n )\n})\nTabsList.displayName = TabsPrimitive.List.displayName\n\nconst TabsTrigger = forwardRef<\n React.ElementRef<typeof TabsPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>\n>(({ className, ...props }, ref) => (\n <TabsPrimitive.Trigger\n ref={ref}\n className={cn(\n \"cursor-pointer relative inline-flex items-center justify-center whitespace-nowrap rounded-3xl px-3 py-1 text-sm font-medium ring-offset-background transition-colors duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:text-foreground z-10\",\n className\n )}\n {...props}\n />\n))\nTabsTrigger.displayName = TabsPrimitive.Trigger.displayName\n\nconst TabsContent = forwardRef<\n React.ElementRef<typeof TabsPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>\n>(({ className, ...props }, ref) => (\n <TabsPrimitive.Content\n ref={ref}\n className={cn(\n \"mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\",\n className\n )}\n {...props}\n />\n))\nTabsContent.displayName = TabsPrimitive.Content.displayName\n\nexport { Tabs, TabsList, TabsTrigger, TabsContent }\n"],"mappings":";yCAAA,UAAYA,MAAmB,uBAG/B,OAAS,cAAAC,EAAY,eAAAC,EAAa,aAAAC,EAAW,UAAAC,EAAQ,YAAAC,MAAgB,QAsEjE,OASE,OAAAC,EATF,QAAAC,MAAA,oBApEJ,IAAMC,EAAqB,OAErBC,EAAWR,EAGf,CAAC,CAAE,UAAAS,EAAW,GAAGC,CAAM,EAAGC,IAAQ,CAClC,GAAM,CAACC,EAAgBC,CAAiB,EAAIT,EAAS,CACnD,KAAM,EACN,MAAO,CACT,CAAC,EACKU,EAAUX,EAAuB,IAAI,EAE3CD,EAAU,IAAM,CACd,IAAMa,EAAkB,IAAM,CAC5B,GAAI,CAACD,EAAQ,QAAS,OAEtB,IAAME,EAAYF,EAAQ,QAAQ,cAChC,uBACF,EAEA,GAAIE,EAAW,CACb,IAAMC,EAAWH,EAAQ,QAAQ,sBAAsB,EACjDI,EAAUF,EAAU,sBAAsB,EAEhDH,EAAkB,CAChB,KAAMK,EAAQ,KAAOD,EAAS,KAC9B,MAAOC,EAAQ,KACjB,CAAC,CACH,CACF,EAEAH,EAAgB,EAGhB,IAAMI,EAAW,IAAI,iBAAiBJ,CAAe,EAErD,OAAID,EAAQ,SACVK,EAAS,QAAQL,EAAQ,QAAS,CAChC,WAAY,GACZ,gBAAiB,CAAC,YAAY,EAC9B,QAAS,EACX,CAAC,EAIH,OAAO,iBAAiB,SAAUC,CAAe,EAE1C,IAAM,CACXI,EAAS,WAAW,EACpB,OAAO,oBAAoB,SAAUJ,CAAe,CACtD,CACF,EAAG,CAAC,CAAC,EAGL,IAAMK,EAAcnB,EACjBoB,GAAgC,CAC7BP,EAA0D,QAAUO,EAElE,OAAOV,GAAQ,WACjBA,EAAIU,CAAI,EACCV,IACPA,EAAsD,QAAUU,EAEtE,EACA,CAACV,CAAG,CACN,EAEA,OACEL,EAAe,OAAd,CACC,IAAKc,EACL,UAAWE,EACT,kGACAb,CACF,EACC,GAAGC,EAGJ,UAAAL,EAAC,QACC,UAAU,0GACV,MAAO,CACL,KAAM,GAAGO,EAAe,IAAI,KAC5B,MAAO,GAAGA,EAAe,KAAK,IAChC,EACF,EACCF,EAAM,UACT,CAEJ,CAAC,EACDF,EAAS,YAA4B,OAAK,YAE1C,IAAMe,EAAcvB,EAGlB,CAAC,CAAE,UAAAS,EAAW,GAAGC,CAAM,EAAGC,IAC1BN,EAAe,UAAd,CACC,IAAKM,EACL,UAAWW,EACT,kXACAb,CACF,EACC,GAAGC,EACN,CACD,EACDa,EAAY,YAA4B,UAAQ,YAEhD,IAAMC,EAAcxB,EAGlB,CAAC,CAAE,UAAAS,EAAW,GAAGC,CAAM,EAAGC,IAC1BN,EAAe,UAAd,CACC,IAAKM,EACL,UAAWW,EACT,kIACAb,CACF,EACC,GAAGC,EACN,CACD,EACDc,EAAY,YAA4B,UAAQ","names":["TabsPrimitive","forwardRef","useCallback","useEffect","useRef","useState","jsx","jsxs","Tabs","TabsList","className","props","ref","indicatorStyle","setIndicatorStyle","listRef","updateIndicator","activeTab","listRect","tabRect","observer","combinedRef","node","cn","TabsTrigger","TabsContent"]}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } }"use client";
|
|
2
|
+
var _chunkFUYXCJOQjs = require('./chunk-FUYXCJOQ.js');var _reacttabs = require('@radix-ui/react-tabs'); var e = _interopRequireWildcard(_reacttabs);var _react = require('react');var _jsxruntime = require('react/jsx-runtime');var C=e.Root,y= exports.b =_react.forwardRef.call(void 0, ({className:r,...n},t)=>{let[c,b]=_react.useState.call(void 0, {left:0,width:0}),s=_react.useRef.call(void 0, null);_react.useEffect.call(void 0, ()=>{let i=()=>{if(!s.current)return;let f=s.current.querySelector('[data-state="active"]');if(f){let v=s.current.getBoundingClientRect(),m=f.getBoundingClientRect();b({left:m.left-v.left,width:m.width})}};i();let u=new MutationObserver(i);return s.current&&u.observe(s.current,{attributes:!0,attributeFilter:["data-state"],subtree:!0}),window.addEventListener("resize",i),()=>{u.disconnect(),window.removeEventListener("resize",i)}},[]);let d=_react.useCallback.call(void 0, i=>{s.current=i,typeof t=="function"?t(i):t&&(t.current=i)},[t]);return _jsxruntime.jsxs.call(void 0, e.List,{ref:d,className:_chunkFUYXCJOQjs.a.call(void 0, "relative inline-flex items-center justify-center rounded-3xl bg-muted p-1 text-muted-foreground",r),...n,children:[_jsxruntime.jsx.call(void 0, "span",{className:"absolute h-[calc(100%-0.5rem)] rounded-3xl bg-background shadow-sm transition-all duration-200 ease-out",style:{left:`${c.left}px`,width:`${c.width}px`}}),n.children]})});y.displayName=e.List.displayName;var P=_react.forwardRef.call(void 0, ({className:r,...n},t)=>_jsxruntime.jsx.call(void 0, e.Trigger,{ref:t,className:_chunkFUYXCJOQjs.a.call(void 0, "cursor-pointer relative inline-flex items-center justify-center whitespace-nowrap rounded-3xl px-3 py-1 text-sm font-medium ring-offset-background transition-colors duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:text-foreground z-10",r),...n}));P.displayName=e.Trigger.displayName;var w=_react.forwardRef.call(void 0, ({className:r,...n},t)=>_jsxruntime.jsx.call(void 0, e.Content,{ref:t,className:_chunkFUYXCJOQjs.a.call(void 0, "mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",r),...n}));w.displayName=e.Content.displayName;exports.a = C; exports.b = y; exports.c = P; exports.d = w;
|
|
3
|
+
//# sourceMappingURL=chunk-74PDRKS7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/admin/Desktop/PROJECTS/alkimi-ui-kit/dist/chunk-74PDRKS7.js","../src/components/tabs.tsx"],"names":["Tabs","TabsList","forwardRef","className","props","ref","indicatorStyle","setIndicatorStyle","useState","listRef","useRef","useEffect","updateIndicator","activeTab","listRect","tabRect","observer","combinedRef","useCallback","node","jsxs","cn","jsx"],"mappings":"AAAA,uWAAY;AACZ,sDAAuC,8FCDR,8BAGsC,+CAsEjE,IApEEA,CAAAA,CAAqB,CAAA,CAAA,IAAA,CAErBC,CAAAA,aAAWC,+BAAAA,CAGd,CAAE,SAAA,CAAAC,CAAAA,CAAW,GAAGC,CAAM,CAAA,CAAGC,CAAAA,CAAAA,EAAQ,CAClC,GAAM,CAACC,CAAAA,CAAgBC,CAAiB,CAAA,CAAIC,6BAAAA,CAC1C,IAAA,CAAM,CAAA,CACN,KAAA,CAAO,CACT,CAAC,CAAA,CACKC,CAAAA,CAAUC,2BAAAA,IAA2B,CAAA,CAE3CC,8BAAAA,CAAU,CAAA,EAAM,CACd,IAAMC,CAAAA,CAAkB,CAAA,CAAA,EAAM,CAC5B,EAAA,CAAI,CAACH,CAAAA,CAAQ,OAAA,CAAS,MAAA,CAEtB,IAAMI,CAAAA,CAAYJ,CAAAA,CAAQ,OAAA,CAAQ,aAAA,CAChC,uBACF,CAAA,CAEA,EAAA,CAAII,CAAAA,CAAW,CACb,IAAMC,CAAAA,CAAWL,CAAAA,CAAQ,OAAA,CAAQ,qBAAA,CAAsB,CAAA,CACjDM,CAAAA,CAAUF,CAAAA,CAAU,qBAAA,CAAsB,CAAA,CAEhDN,CAAAA,CAAkB,CAChB,IAAA,CAAMQ,CAAAA,CAAQ,IAAA,CAAOD,CAAAA,CAAS,IAAA,CAC9B,KAAA,CAAOC,CAAAA,CAAQ,KACjB,CAAC,CACH,CACF,CAAA,CAEAH,CAAAA,CAAgB,CAAA,CAGhB,IAAMI,CAAAA,CAAW,IAAI,gBAAA,CAAiBJ,CAAe,CAAA,CAErD,OAAIH,CAAAA,CAAQ,OAAA,EACVO,CAAAA,CAAS,OAAA,CAAQP,CAAAA,CAAQ,OAAA,CAAS,CAChC,UAAA,CAAY,CAAA,CAAA,CACZ,eAAA,CAAiB,CAAC,YAAY,CAAA,CAC9B,OAAA,CAAS,CAAA,CACX,CAAC,CAAA,CAIH,MAAA,CAAO,gBAAA,CAAiB,QAAA,CAAUG,CAAe,CAAA,CAE1C,CAAA,CAAA,EAAM,CACXI,CAAAA,CAAS,UAAA,CAAW,CAAA,CACpB,MAAA,CAAO,mBAAA,CAAoB,QAAA,CAAUJ,CAAe,CACtD,CACF,CAAA,CAAG,CAAC,CAAC,CAAA,CAGL,IAAMK,CAAAA,CAAcC,gCAAAA,CACjBC,EAAgC,CAC7BV,CAAAA,CAA0D,OAAA,CAAUU,CAAAA,CAElE,OAAOd,CAAAA,EAAQ,UAAA,CACjBA,CAAAA,CAAIc,CAAI,CAAA,CACCd,CAAAA,EAAAA,CACPA,CAAAA,CAAsD,OAAA,CAAUc,CAAAA,CAEtE,CAAA,CACA,CAACd,CAAG,CACN,CAAA,CAEA,OACEe,8BAAAA,CAAe,CAAA,IAAA,CAAd,CACC,GAAA,CAAKH,CAAAA,CACL,SAAA,CAAWI,gCAAAA,iGACT,CACAlB,CACF,CAAA,CACC,GAAGC,CAAAA,CAGJ,QAAA,CAAA,CAAAkB,6BAAAA,MAAC,CAAA,CACC,SAAA,CAAU,yGAAA,CACV,KAAA,CAAO,CACL,IAAA,CAAM,CAAA,EAAA","file":"/Users/admin/Desktop/PROJECTS/alkimi-ui-kit/dist/chunk-74PDRKS7.js","sourcesContent":[null,"import * as TabsPrimitive from \"@radix-ui/react-tabs\"\n\nimport { cn } from \"@/lib/utils\"\nimport { forwardRef, useCallback, useEffect, useRef, useState } from \"react\"\n\nconst Tabs = TabsPrimitive.Root\n\nconst TabsList = forwardRef<\n React.ElementRef<typeof TabsPrimitive.List>,\n React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>\n>(({ className, ...props }, ref) => {\n const [indicatorStyle, setIndicatorStyle] = useState({\n left: 0,\n width: 0,\n })\n const listRef = useRef<HTMLDivElement>(null)\n\n useEffect(() => {\n const updateIndicator = () => {\n if (!listRef.current) return\n\n const activeTab = listRef.current.querySelector(\n '[data-state=\"active\"]'\n ) as HTMLElement\n\n if (activeTab) {\n const listRect = listRef.current.getBoundingClientRect()\n const tabRect = activeTab.getBoundingClientRect()\n\n setIndicatorStyle({\n left: tabRect.left - listRect.left,\n width: tabRect.width,\n })\n }\n }\n\n updateIndicator()\n\n // Use MutationObserver to detect when data-state changes\n const observer = new MutationObserver(updateIndicator)\n\n if (listRef.current) {\n observer.observe(listRef.current, {\n attributes: true,\n attributeFilter: [\"data-state\"],\n subtree: true,\n })\n }\n\n // Also update on window resize\n window.addEventListener(\"resize\", updateIndicator)\n\n return () => {\n observer.disconnect()\n window.removeEventListener(\"resize\", updateIndicator)\n }\n }, [])\n\n // Combine refs\n const combinedRef = useCallback(\n (node: HTMLDivElement | null) => {\n ;(listRef as React.MutableRefObject<HTMLDivElement | null>).current = node\n\n if (typeof ref === \"function\") {\n ref(node)\n } else if (ref) {\n ;(ref as React.MutableRefObject<HTMLDivElement | null>).current = node\n }\n },\n [ref]\n )\n\n return (\n <TabsPrimitive.List\n ref={combinedRef}\n className={cn(\n \"relative inline-flex items-center justify-center rounded-3xl bg-muted p-1 text-muted-foreground\",\n className\n )}\n {...props}\n >\n {/* Animated indicator */}\n <span\n className=\"absolute h-[calc(100%-0.5rem)] rounded-3xl bg-background shadow-sm transition-all duration-200 ease-out\"\n style={{\n left: `${indicatorStyle.left}px`,\n width: `${indicatorStyle.width}px`,\n }}\n />\n {props.children}\n </TabsPrimitive.List>\n )\n})\nTabsList.displayName = TabsPrimitive.List.displayName\n\nconst TabsTrigger = forwardRef<\n React.ElementRef<typeof TabsPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>\n>(({ className, ...props }, ref) => (\n <TabsPrimitive.Trigger\n ref={ref}\n className={cn(\n \"cursor-pointer relative inline-flex items-center justify-center whitespace-nowrap rounded-3xl px-3 py-1 text-sm font-medium ring-offset-background transition-colors duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:text-foreground z-10\",\n className\n )}\n {...props}\n />\n))\nTabsTrigger.displayName = TabsPrimitive.Trigger.displayName\n\nconst TabsContent = forwardRef<\n React.ElementRef<typeof TabsPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>\n>(({ className, ...props }, ref) => (\n <TabsPrimitive.Content\n ref={ref}\n className={cn(\n \"mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\",\n className\n )}\n {...props}\n />\n))\nTabsContent.displayName = TabsPrimitive.Content.displayName\n\nexport { Tabs, TabsList, TabsTrigger, TabsContent }\n"]}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import{a as b}from"./chunk-S5TKCF6T.mjs";import a,{useState as E,useEffect as A,useMemo as S,useRef as V,Suspense as L}from"react";import{jsx as m,jsxs as _}from"react/jsx-runtime";var D=["\\","-","?","/","#","!","_","+","<",">"],O=3,H=200,v=e=>e?e.split(" ").map(n=>n?D[Math.floor(Math.random()*D.length)].repeat(n.length):"").join(" "):"",d=e=>{if(typeof e=="string"||typeof e=="number")return String(e);if(Array.isArray(e))return e.map(d).join("");if(a.isValidElement(e)){let n=e.props,r="";return typeof n.text=="string"&&(r+=n.text),typeof n.label=="string"&&(r+=n.label),typeof n.title=="string"&&(r+=n.title),n.children&&(r+=d(n.children)),r}return""},p=(e,n,r)=>{if(typeof e=="string"||typeof e=="number"){let s=String(e),i="";for(let t=0;t<s.length;t++)r.current<n.length?(i+=n[r.current],r.current++):i+=s[t];return i}if(Array.isArray(e))return e.map((s,i)=>{let t=p(s,n,r);if(a.isValidElement(t)){let l=a.isValidElement(s)?s.key:null;if(t.key==null&&l==null)return a.cloneElement(t,{key:`decoded-${i}`});if(t.key==null&&l!=null)return a.cloneElement(t,{key:l})}return t});if(a.isValidElement(e)){let s=e.props,i={...s};if(typeof s.text=="string"){let t=s.text,l="";for(let o=0;o<t.length;o++)r.current<n.length?(l+=n[r.current],r.current++):l+=t[o];i.text=l}if(typeof s.label=="string"){let t=s.label,l="";for(let o=0;o<t.length;o++)r.current<n.length?(l+=n[r.current],r.current++):l+=t[o];i.label=l}if(typeof s.title=="string"){let t=s.title,l="";for(let o=0;o<t.length;o++)r.current<n.length?(l+=n[r.current],r.current++):l+=t[o];i.title=l}return s.children&&(i.children=p(s.children,n,r)),a.cloneElement(e,i)}return e},I=({children:e,className:n,delay:r=0})=>{let[s,i]=E(null),[t,l]=E(!1),[o,u]=E(!0),k=V(null),c=S(()=>d(e),[e]),g=S(()=>v(c),[c]);A(()=>{if(!t&&c){let y=p(e,g,{current:0});i(y),u(!0)}},[e,g,t,c]),A(()=>{if(!c){i(null),u(!1);return}if(t){u(!1);return}let N=k.current;if(!N)return;let y=0,f=null,h=null,R=new IntersectionObserver(T=>{T[0].isIntersecting&&!t&&(h=setTimeout(()=>{let C=p(e,g,{current:0});i(C),u(!0),f=setInterval(()=>{if(y++,y>=O)l(!0),u(!1),f&&clearInterval(f);else{let M=v(c),P=p(e,M,{current:0});i(P)}},H)},r),R.disconnect())},{threshold:.1});return R.observe(N),()=>{R.disconnect(),f&&clearInterval(f),h&&clearTimeout(h)}},[e,c,g,t,r]);let w=S(()=>d(e),[e]);return _("span",{ref:k,"aria-label":w,className:b("inline-grid *:col-start-1 *:row-start-1",n),children:[m("span",{className:b("transition-opacity duration-300",t?"opacity-100":"opacity-0"),children:e}),o&&s&&m("span",{className:"transition-opacity duration-300",children:s})]})},J=e=>m(L,{fallback:m("span",{className:b("opacity-0",e.className),children:e.children}),children:m(I,{...e})}),q=J;export{q as a};
|
|
3
|
+
//# sourceMappingURL=chunk-BCAQUOTY.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/TextDecoder.tsx"],"sourcesContent":["\"use client\"\nimport { cn } from \"@/lib/utils\"\nimport React, {\n useState,\n useEffect,\n useMemo,\n useRef,\n Suspense,\n ReactNode,\n} from \"react\"\n\n// The symbols to use for the scrambling effect (moved outside to avoid recreation)\nconst SYMBOLS = [\"\\\\\", \"-\", \"?\", \"/\", \"#\", \"!\", \"_\", \"+\", \"<\", \">\"]\nconst MAX_ITERATIONS = 3 // How many times to scramble\nconst SPEED = 200 // Speed in milliseconds between scrambles\n\n// Helper function moved outside component to avoid recreation\nconst scrambleText = (input: string): string => {\n if (!input) return \"\"\n\n return input\n .split(\" \")\n .map((word: string) => {\n if (!word) return \"\"\n const randomSymbol = SYMBOLS[Math.floor(Math.random() * SYMBOLS.length)]\n return randomSymbol.repeat(word.length)\n })\n .join(\" \")\n}\n\n// Extract text content from React nodes recursively\n// Also checks common text props like 'text', 'label', 'title', etc.\nconst extractText = (node: ReactNode): string => {\n if (typeof node === \"string\" || typeof node === \"number\") {\n return String(node)\n }\n\n if (Array.isArray(node)) {\n return node.map(extractText).join(\"\")\n }\n\n if (React.isValidElement(node)) {\n const props = node.props as {\n children?: ReactNode\n text?: string\n label?: string\n title?: string\n [key: string]: unknown\n }\n\n let result = \"\"\n\n // Extract text from props first (in order: text, label, title)\n if (typeof props.text === \"string\") {\n result += props.text\n }\n if (typeof props.label === \"string\") {\n result += props.label\n }\n if (typeof props.title === \"string\") {\n result += props.title\n }\n\n // Then extract from children\n if (props.children) {\n result += extractText(props.children)\n }\n\n return result\n }\n\n return \"\"\n}\n\n// Clone React nodes and replace text content with scrambled text\n// This function maps scrambled text back to the original structure\nconst scrambleReactNode = (\n node: ReactNode,\n scrambledText: string,\n textStartIndex: { current: number }\n): ReactNode => {\n if (typeof node === \"string\" || typeof node === \"number\") {\n const text = String(node)\n // For each character in the original text, take the corresponding scrambled character\n // This preserves the length and structure\n let scrambled = \"\"\n for (let i = 0; i < text.length; i++) {\n if (textStartIndex.current < scrambledText.length) {\n scrambled += scrambledText[textStartIndex.current]\n textStartIndex.current++\n } else {\n // Fallback if scrambled text is shorter (shouldn't happen, but safety check)\n scrambled += text[i]\n }\n }\n return scrambled\n }\n\n if (Array.isArray(node)) {\n return node.map((child, index) => {\n const scrambledChild = scrambleReactNode(\n child,\n scrambledText,\n textStartIndex\n )\n // Preserve original key if it exists, otherwise add one for React elements\n if (React.isValidElement(scrambledChild)) {\n const originalKey = React.isValidElement(child) ? child.key : null\n if (scrambledChild.key == null && originalKey == null) {\n return React.cloneElement(scrambledChild, { key: `decoded-${index}` })\n }\n // If original had a key but scrambled doesn't, preserve it\n if (scrambledChild.key == null && originalKey != null) {\n return React.cloneElement(scrambledChild, { key: originalKey })\n }\n }\n return scrambledChild\n })\n }\n\n if (React.isValidElement(node)) {\n // Regular element handling - works for all components\n const props = node.props as {\n children?: ReactNode\n text?: string\n label?: string\n title?: string\n [key: string]: unknown\n }\n const newProps = { ...props }\n\n // Handle text props in the same order as extraction (text, label, title)\n if (typeof props.text === \"string\") {\n const text = props.text\n let scrambled = \"\"\n for (let i = 0; i < text.length; i++) {\n if (textStartIndex.current < scrambledText.length) {\n scrambled += scrambledText[textStartIndex.current]\n textStartIndex.current++\n } else {\n scrambled += text[i]\n }\n }\n newProps.text = scrambled\n }\n\n if (typeof props.label === \"string\") {\n const label = props.label\n let scrambled = \"\"\n for (let i = 0; i < label.length; i++) {\n if (textStartIndex.current < scrambledText.length) {\n scrambled += scrambledText[textStartIndex.current]\n textStartIndex.current++\n } else {\n scrambled += label[i]\n }\n }\n newProps.label = scrambled\n }\n\n if (typeof props.title === \"string\") {\n const title = props.title\n let scrambled = \"\"\n for (let i = 0; i < title.length; i++) {\n if (textStartIndex.current < scrambledText.length) {\n scrambled += scrambledText[textStartIndex.current]\n textStartIndex.current++\n } else {\n scrambled += title[i]\n }\n }\n newProps.title = scrambled\n }\n\n // Handle children after props\n if (props.children) {\n newProps.children = scrambleReactNode(\n props.children,\n scrambledText,\n textStartIndex\n )\n }\n return React.cloneElement(node, newProps)\n }\n\n return node\n}\n\nexport interface TextDecoderProps {\n children: ReactNode\n className?: string\n delay?: number // Delay in milliseconds before starting animation\n}\n\nconst TextDecoder = ({ children, className, delay = 0 }: TextDecoderProps) => {\n const [displayContent, setDisplayContent] = useState<ReactNode>(null)\n const [hasAnimated, setHasAnimated] = useState(false)\n const [showDecoded, setShowDecoded] = useState(true)\n const elementRef = useRef<HTMLSpanElement>(null)\n\n // Extract full text for scrambling\n const fullText = useMemo(() => extractText(children), [children])\n\n // Memoize initial scrambled text\n const initialScrambled = useMemo(() => scrambleText(fullText), [fullText])\n\n // Initialize with scrambled content to prevent layout shift\n useEffect(() => {\n if (!hasAnimated && fullText) {\n const textStartIndex = { current: 0 }\n const scrambledContent = scrambleReactNode(\n children,\n initialScrambled,\n textStartIndex\n )\n setDisplayContent(scrambledContent)\n setShowDecoded(true)\n }\n }, [children, initialScrambled, hasAnimated, fullText])\n\n useEffect(() => {\n if (!fullText) {\n setDisplayContent(null)\n setShowDecoded(false)\n return\n }\n\n // If already animated, hide decoded and show children\n if (hasAnimated) {\n setShowDecoded(false)\n return\n }\n\n const element = elementRef.current\n if (!element) return\n\n let iteration = 0\n let intervalId: NodeJS.Timeout | null = null\n let delayTimeoutId: NodeJS.Timeout | null = null\n\n // Intersection Observer to detect when element is visible\n const observer = new IntersectionObserver(\n (entries) => {\n const entry = entries[0]\n if (entry.isIntersecting && !hasAnimated) {\n // Start animation after delay\n delayTimeoutId = setTimeout(() => {\n // 1. Initial scramble\n const textStartIndex = { current: 0 }\n const scrambledContent = scrambleReactNode(\n children,\n initialScrambled,\n textStartIndex\n )\n setDisplayContent(scrambledContent)\n setShowDecoded(true)\n\n // 2. Set up the interval\n intervalId = setInterval(() => {\n iteration++\n\n if (iteration >= MAX_ITERATIONS) {\n // Stop scrambling, fade out decoded and fade in children\n setHasAnimated(true)\n setShowDecoded(false)\n if (intervalId) clearInterval(intervalId)\n } else {\n // Continue scrambling\n const newScrambled = scrambleText(fullText)\n const textStartIndex = { current: 0 }\n const scrambledContent = scrambleReactNode(\n children,\n newScrambled,\n textStartIndex\n )\n setDisplayContent(scrambledContent)\n }\n }, SPEED)\n }, delay)\n\n // Disconnect observer once animation starts\n observer.disconnect()\n }\n },\n {\n threshold: 0.1, // Trigger when 10% of the element is visible\n }\n )\n\n observer.observe(element)\n\n // Cleanup function\n return () => {\n observer.disconnect()\n if (intervalId) clearInterval(intervalId)\n if (delayTimeoutId) clearTimeout(delayTimeoutId)\n }\n }, [children, fullText, initialScrambled, hasAnimated, delay])\n\n const ariaLabel = useMemo(() => extractText(children), [children])\n\n return (\n <span\n ref={elementRef}\n aria-label={ariaLabel} // Accessibility: Screen readers read the real text\n className={cn(\"inline-grid *:col-start-1 *:row-start-1\", className)}\n >\n {/* Both elements in the same grid cell - prevents width changes */}\n <span\n className={cn(\n \"transition-opacity duration-300\",\n hasAnimated ? \"opacity-100\" : \"opacity-0\"\n )}\n >\n {children}\n </span>\n {/* Decoded animation overlay in the same grid cell */}\n {showDecoded && displayContent && (\n <span className=\"transition-opacity duration-300\">\n {displayContent}\n </span>\n )}\n </span>\n )\n}\n\nconst SuspenseDecodedText = (props: TextDecoderProps) => {\n return (\n <Suspense\n fallback={\n <span className={cn(\"opacity-0\", props.className)}>\n {props.children}\n </span>\n }\n >\n <TextDecoder {...props} />\n </Suspense>\n )\n}\n\nexport default SuspenseDecodedText\n"],"mappings":"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","names":["React","useState","useEffect","useMemo","useRef","Suspense","jsx","jsxs","SYMBOLS","MAX_ITERATIONS","SPEED","scrambleText","input","word","extractText","node","props","result","scrambleReactNode","scrambledText","textStartIndex","text","scrambled","i","child","index","scrambledChild","originalKey","newProps","label","title","TextDecoder","children","className","delay","displayContent","setDisplayContent","hasAnimated","setHasAnimated","showDecoded","setShowDecoded","elementRef","fullText","initialScrambled","scrambledContent","element","iteration","intervalId","delayTimeoutId","observer","entries","newScrambled","ariaLabel","cn","SuspenseDecodedText","TextDecoder_default"]}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});"use client";
|
|
2
|
+
var _clsx = require('clsx');var _tailwindmerge = require('tailwind-merge');function s(...r){return _tailwindmerge.twMerge.call(void 0, _clsx.clsx.call(void 0, r))}exports.a = s;
|
|
3
|
+
//# sourceMappingURL=chunk-FUYXCJOQ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/admin/Desktop/PROJECTS/alkimi-ui-kit/dist/chunk-FUYXCJOQ.js","../src/lib/utils.ts"],"names":["cn","inputs","twMerge","clsx"],"mappings":"AAAA,qFAAY;ACAZ,4BAAsC,+CACd,SAERA,CAAAA,CAAAA,GAAMC,CAAAA,CAAsB,CAC1C,OAAOC,oCAAAA,wBAAQC,CAAW,CAAC,CAC7B,CAAA,cAAA","file":"/Users/admin/Desktop/PROJECTS/alkimi-ui-kit/dist/chunk-FUYXCJOQ.js","sourcesContent":[null,"import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n"]}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import M from"next/link";import{useState as R,cloneElement as E,isValidElement as l}from"react";import{Slot as k}from"@radix-ui/react-slot";import{jsx as f}from"react/jsx-runtime";var S=["/","#","*"],x=({href:m,children:e,symbols:r=S,className:p,asChild:u=!1,...g})=>{let[o,s]=R(!1),i=t=>typeof t=="string"?t:l(t)&&t.props.children?i(t.props.children):"",n=i(e),a=()=>!o||!n?n:n.split(" ").map(t=>{let L=Math.floor(Math.random()*t.length);return t.replace(t[L],r[Math.floor(Math.random()*r.length)])}).join(" "),c={className:p,onMouseEnter:()=>s(!0),onMouseLeave:()=>s(!1),...g};if(u&&l(e)){let t=n?o?a():n:e;return f(k,{...c,children:E(e,{},t)})}let h=n&&o?a():e;return f(M,{href:m||"#",...c,children:h})},v=x;export{S as a,v as b};
|
|
3
|
+
//# sourceMappingURL=chunk-IK3C7KV5.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/GlitchLink.tsx"],"sourcesContent":["\"use client\"\nimport Link from \"next/link\"\nimport {\n RefAttributes,\n useState,\n ReactNode,\n cloneElement,\n isValidElement,\n} from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\n\nexport const DEFAULT_SYMBOLS = [\"/\", \"#\", \"*\"]\n\ntype GlitchLinkProps = RefAttributes<HTMLAnchorElement> & {\n href?: string\n children: ReactNode\n symbols?: string[]\n className?: string\n asChild?: boolean\n}\n\nconst GlitchLink = ({\n href,\n children,\n symbols = DEFAULT_SYMBOLS,\n className,\n asChild = false,\n ...props\n}: GlitchLinkProps) => {\n const [isHovering, setIsHovering] = useState(false)\n\n // Extract text from children - either direct string or from child element\n const getTextContent = (node: ReactNode): string => {\n if (typeof node === \"string\") return node\n if (isValidElement(node) && node.props.children) {\n return getTextContent(node.props.children)\n }\n return \"\"\n }\n\n const text = getTextContent(children)\n\n const getRandomGlitch = () => {\n if (!isHovering || !text) return text\n return text\n .split(\" \")\n .map((word: string) => {\n // take one random letter from the word\n const randomLetterIndex = Math.floor(Math.random() * word.length)\n\n // replace the letter with a random symbol\n return word.replace(\n word[randomLetterIndex],\n symbols[Math.floor(Math.random() * symbols.length)]\n )\n })\n .join(\" \")\n }\n\n const commonProps = {\n className,\n onMouseEnter: () => setIsHovering(true),\n onMouseLeave: () => setIsHovering(false),\n ...props,\n }\n\n if (asChild && isValidElement(children)) {\n const content = text ? (isHovering ? getRandomGlitch() : text) : children\n return (\n <Slot {...commonProps}>\n {cloneElement(children as React.ReactElement, {}, content)}\n </Slot>\n )\n }\n\n const content = text ? (isHovering ? getRandomGlitch() : children) : children\n\n return (\n <Link href={href || \"#\"} {...commonProps}>\n {content}\n </Link>\n )\n}\n\nexport default GlitchLink\n"],"mappings":";AACA,OAAOA,MAAU,YACjB,OAEE,YAAAC,EAEA,gBAAAC,EACA,kBAAAC,MACK,QACP,OAAS,QAAAC,MAAY,uBA4Df,cAAAC,MAAA,oBA1DC,IAAMC,EAAkB,CAAC,IAAK,IAAK,GAAG,EAUvCC,EAAa,CAAC,CAClB,KAAAC,EACA,SAAAC,EACA,QAAAC,EAAUJ,EACV,UAAAK,EACA,QAAAC,EAAU,GACV,GAAGC,CACL,IAAuB,CACrB,GAAM,CAACC,EAAYC,CAAa,EAAId,EAAS,EAAK,EAG5Ce,EAAkBC,GAClB,OAAOA,GAAS,SAAiBA,EACjCd,EAAec,CAAI,GAAKA,EAAK,MAAM,SAC9BD,EAAeC,EAAK,MAAM,QAAQ,EAEpC,GAGHC,EAAOF,EAAeP,CAAQ,EAE9BU,EAAkB,IAClB,CAACL,GAAc,CAACI,EAAaA,EAC1BA,EACJ,MAAM,GAAG,EACT,IAAKE,GAAiB,CAErB,IAAMC,EAAoB,KAAK,MAAM,KAAK,OAAO,EAAID,EAAK,MAAM,EAGhE,OAAOA,EAAK,QACVA,EAAKC,CAAiB,EACtBX,EAAQ,KAAK,MAAM,KAAK,OAAO,EAAIA,EAAQ,MAAM,CAAC,CACpD,CACF,CAAC,EACA,KAAK,GAAG,EAGPY,EAAc,CAClB,UAAAX,EACA,aAAc,IAAMI,EAAc,EAAI,EACtC,aAAc,IAAMA,EAAc,EAAK,EACvC,GAAGF,CACL,EAEA,GAAID,GAAWT,EAAeM,CAAQ,EAAG,CACvC,IAAMc,EAAUL,EAAQJ,EAAaK,EAAgB,EAAID,EAAQT,EACjE,OACEJ,EAACD,EAAA,CAAM,GAAGkB,EACP,SAAApB,EAAaO,EAAgC,CAAC,EAAGc,CAAO,EAC3D,CAEJ,CAEA,IAAMA,EAAUL,GAAQJ,EAAaK,EAAgB,EAAgBV,EAErE,OACEJ,EAACL,EAAA,CAAK,KAAMQ,GAAQ,IAAM,GAAGc,EAC1B,SAAAC,EACH,CAEJ,EAEOC,EAAQjB","names":["Link","useState","cloneElement","isValidElement","Slot","jsx","DEFAULT_SYMBOLS","GlitchLink","href","children","symbols","className","asChild","props","isHovering","setIsHovering","getTextContent","node","text","getRandomGlitch","word","randomLetterIndex","commonProps","content","GlitchLink_default"]}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }"use client";
|
|
2
|
+
var _link = require('next/link'); var _link2 = _interopRequireDefault(_link);var _react = require('react');var _reactslot = require('@radix-ui/react-slot');var _jsxruntime = require('react/jsx-runtime');var S=["/","#","*"],x=({href:m,children:e,symbols:r=S,className:p,asChild:u=!1,...g})=>{let[o,s]=_react.useState.call(void 0, !1),i=t=>typeof t=="string"?t:_react.isValidElement.call(void 0, t)&&t.props.children?i(t.props.children):"",n=i(e),a=()=>!o||!n?n:n.split(" ").map(t=>{let L=Math.floor(Math.random()*t.length);return t.replace(t[L],r[Math.floor(Math.random()*r.length)])}).join(" "),c={className:p,onMouseEnter:()=>s(!0),onMouseLeave:()=>s(!1),...g};if(u&&_react.isValidElement.call(void 0, e)){let t=n?o?a():n:e;return _jsxruntime.jsx.call(void 0, _reactslot.Slot,{...c,children:_react.cloneElement.call(void 0, e,{},t)})}let h=n&&o?a():e;return _jsxruntime.jsx.call(void 0, _link2.default,{href:m||"#",...c,children:h})},v= exports.b =x;exports.a = S; exports.b = v;
|
|
3
|
+
//# sourceMappingURL=chunk-JNEIOQGF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/admin/Desktop/PROJECTS/alkimi-ui-kit/dist/chunk-JNEIOQGF.js","../src/components/GlitchLink.tsx"],"names":["DEFAULT_SYMBOLS","GlitchLink","href","children","symbols","className","asChild","props","isHovering","setIsHovering","useState","getTextContent","node","isValidElement","text","getRandomGlitch","word","randomLetterIndex","commonProps","content","jsx","Slot","cloneElement","Link","GlitchLink_default"],"mappings":"AAAA,qLAAY;ACCZ,6EAAiB,8BAOV,iDACc,+CA4Df,IA1DOA,CAAAA,CAAkB,CAAC,GAAA,CAAK,GAAA,CAAK,GAAG,CAAA,CAUvCC,CAAAA,CAAa,CAAC,CAClB,IAAA,CAAAC,CAAAA,CACA,QAAA,CAAAC,CAAAA,CACA,OAAA,CAAAC,CAAAA,CAAUJ,CAAAA,CACV,SAAA,CAAAK,CAAAA,CACA,OAAA,CAAAC,CAAAA,CAAU,CAAA,CAAA,CACV,GAAGC,CACL,CAAA,CAAA,EAAuB,CACrB,GAAM,CAACC,CAAAA,CAAYC,CAAa,CAAA,CAAIC,6BAAAA,CAAS,CAAK,CAAA,CAG5CC,CAAAA,CAAkBC,CAAAA,EAClB,OAAOA,CAAAA,EAAS,QAAA,CAAiBA,CAAAA,CACjCC,mCAAAA,CAAmB,CAAA,EAAKD,CAAAA,CAAK,KAAA,CAAM,QAAA,CAC9BD,CAAAA,CAAeC,CAAAA,CAAK,KAAA,CAAM,QAAQ,CAAA,CAEpC,EAAA,CAGHE,CAAAA,CAAOH,CAAAA,CAAeR,CAAQ,CAAA,CAE9BY,CAAAA,CAAkB,CAAA,CAAA,EAClB,CAACP,CAAAA,EAAc,CAACM,CAAAA,CAAaA,CAAAA,CAC1BA,CAAAA,CACJ,KAAA,CAAM,GAAG,CAAA,CACT,GAAA,CAAKE,CAAAA,EAAiB,CAErB,IAAMC,CAAAA,CAAoB,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,MAAA,CAAO,CAAA,CAAID,CAAAA,CAAK,MAAM,CAAA,CAGhE,OAAOA,CAAAA,CAAK,OAAA,CACVA,CAAAA,CAAKC,CAAiB,CAAA,CACtBb,CAAAA,CAAQ,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,MAAA,CAAO,CAAA,CAAIA,CAAAA,CAAQ,MAAM,CAAC,CACpD,CACF,CAAC,CAAA,CACA,IAAA,CAAK,GAAG,CAAA,CAGPc,CAAAA,CAAc,CAClB,SAAA,CAAAb,CAAAA,CACA,YAAA,CAAc,CAAA,CAAA,EAAMI,CAAAA,CAAc,CAAA,CAAI,CAAA,CACtC,YAAA,CAAc,CAAA,CAAA,EAAMA,CAAAA,CAAc,CAAA,CAAK,CAAA,CACvC,GAAGF,CACL,CAAA,CAEA,EAAA,CAAID,CAAAA,EAAWO,mCAAAA,CAAuB,CAAA,CAAG,CACvC,IAAMM,CAAAA,CAAUL,CAAAA,CAAQN,CAAAA,CAAaO,CAAAA,CAAgB,CAAA,CAAID,CAAAA,CAAQX,CAAAA,CACjE,OACEiB,6BAAAA,eAACC,CAAA,CAAM,GAAGH,CAAAA,CACP,QAAA,CAAAI,iCAAAA,CAAanB,CAAgC,CAAC,CAAA,CAAGgB,CAAO,CAAA,CAC3D,CAEJ,CAEA,IAAMA,CAAAA,CAAUL,CAAAA,EAAQN,CAAAA,CAAaO,CAAAA,CAAgB,CAAA,CAAgBZ,CAAAA,CAErE,OACEiB,6BAAAA,cAACG,CAAA,CAAK,IAAA,CAAMrB,CAAAA,EAAQ,GAAA,CAAM,GAAGgB,CAAAA,CAC1B,QAAA,CAAAC,CAAAA,CACH,CAEJ,CAAA,CAEOK,CAAAA,aAAQvB,CAAAA,CAAAA,6BAAAA","file":"/Users/admin/Desktop/PROJECTS/alkimi-ui-kit/dist/chunk-JNEIOQGF.js","sourcesContent":[null,"\"use client\"\nimport Link from \"next/link\"\nimport {\n RefAttributes,\n useState,\n ReactNode,\n cloneElement,\n isValidElement,\n} from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\n\nexport const DEFAULT_SYMBOLS = [\"/\", \"#\", \"*\"]\n\ntype GlitchLinkProps = RefAttributes<HTMLAnchorElement> & {\n href?: string\n children: ReactNode\n symbols?: string[]\n className?: string\n asChild?: boolean\n}\n\nconst GlitchLink = ({\n href,\n children,\n symbols = DEFAULT_SYMBOLS,\n className,\n asChild = false,\n ...props\n}: GlitchLinkProps) => {\n const [isHovering, setIsHovering] = useState(false)\n\n // Extract text from children - either direct string or from child element\n const getTextContent = (node: ReactNode): string => {\n if (typeof node === \"string\") return node\n if (isValidElement(node) && node.props.children) {\n return getTextContent(node.props.children)\n }\n return \"\"\n }\n\n const text = getTextContent(children)\n\n const getRandomGlitch = () => {\n if (!isHovering || !text) return text\n return text\n .split(\" \")\n .map((word: string) => {\n // take one random letter from the word\n const randomLetterIndex = Math.floor(Math.random() * word.length)\n\n // replace the letter with a random symbol\n return word.replace(\n word[randomLetterIndex],\n symbols[Math.floor(Math.random() * symbols.length)]\n )\n })\n .join(\" \")\n }\n\n const commonProps = {\n className,\n onMouseEnter: () => setIsHovering(true),\n onMouseLeave: () => setIsHovering(false),\n ...props,\n }\n\n if (asChild && isValidElement(children)) {\n const content = text ? (isHovering ? getRandomGlitch() : text) : children\n return (\n <Slot {...commonProps}>\n {cloneElement(children as React.ReactElement, {}, content)}\n </Slot>\n )\n }\n\n const content = text ? (isHovering ? getRandomGlitch() : children) : children\n\n return (\n <Link href={href || \"#\"} {...commonProps}>\n {content}\n </Link>\n )\n}\n\nexport default GlitchLink\n"]}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }"use client";
|
|
2
|
+
var _image = require('next/image'); var _image2 = _interopRequireDefault(_image);var _react = require('react');var _jsxruntime = require('react/jsx-runtime');function J(o){return typeof o=="object"&&"src"in o}function U(o){return J(o)?o.src:o}function $({src:o,alt:P,duration:h=600,steps:l=15,className:R,onAnimationComplete:f,priority:C,quality:E,placeholder:z="empty",blurDataURL:T,objectFit:p="cover"}){let v=_react.useRef.call(void 0, null),u=_react.useRef.call(void 0, null),[d,b]=_react.useState.call(void 0, "loading"),[n,H]=_react.useState.call(void 0, null),S=U(o),c=_react.useCallback.call(void 0, (t,a,e,i,r)=>{t.imageSmoothingEnabled=!1;let m=Math.max(1,Math.floor(i/e)),s=Math.max(1,Math.floor(r/e));t.clearRect(0,0,i,r),t.drawImage(a,0,0,m,s),t.drawImage(u.current,0,0,m,s,0,0,i,r)},[]),w=_react.useCallback.call(void 0, (t,a,e,i)=>{let r=Math.max(e,i)/4,m=h/l,s=0;b("animating");let x=()=>{let O=s/l,q=Math.max(1,Math.floor(r*(1-O)));c(t,a,q,e,i),s++,s<=l?window.setTimeout(x,m):(b("complete"),_optionalChain([f, 'optionalCall', _ => _()]))};x()},[h,l,c,f]);_react.useEffect.call(void 0, ()=>{let t=v.current;if(!t)return;let a=()=>{let{width:i,height:r}=t.getBoundingClientRect();H({width:Math.floor(i),height:Math.floor(r)})},e=new ResizeObserver(a);return e.observe(t),a(),()=>{e.disconnect()}},[]),_react.useEffect.call(void 0, ()=>{if(!n||n.width<=0||n.height<=0)return;let t=u.current;if(!t)return;let a=t.getContext("2d");if(!a)return;t.width=n.width,t.height=n.height;let e=new window.Image;return e.crossOrigin="anonymous",e.onload=()=>{let i=Math.max(n.width,n.height)/4;c(a,e,i,n.width,n.height),w(a,e,n.width,n.height)},e.onerror=()=>{console.error("PixelLoad: Failed to load image")},e.src=S,()=>{e.onload=null,e.onerror=null}},[S,n,w,c]);let g=d==="complete",N=d==="animating"||d==="loading";return _jsxruntime.jsxs.call(void 0, "div",{ref:v,className:`relative w-full h-full ${R||""}`,children:[_jsxruntime.jsx.call(void 0, "canvas",{ref:u,className:"absolute top-0 left-0 w-full h-full",style:{objectFit:p,opacity:g?0:1,zIndex:N?2:1},"aria-hidden":g}),g&&_jsxruntime.jsx.call(void 0, _image2.default,{src:o,alt:P,fill:!0,priority:C,quality:E,placeholder:z,blurDataURL:T,className:"opacity-100 transition-opacity duration-150 ease-out z-[1]",style:{objectFit:p}})]})}exports.a = $;
|
|
3
|
+
//# sourceMappingURL=chunk-R74QDO2Z.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/admin/Desktop/PROJECTS/alkimi-ui-kit/dist/chunk-R74QDO2Z.js","../src/components/PixelLoad.tsx"],"names":["isStaticImageData","src","getImageSrc","PixelLoad","alt","duration","steps","className","onAnimationComplete","priority","quality","placeholder","blurDataURL","objectFit","containerRef","useRef","canvasRef","status","setStatus","useState","dimensions","setDimensions","imageSrc","drawPixelated","useCallback","ctx","img","pixelSize","w","h","sw","sh","runAnimation","minPixelSize","intervalMs","currentStep","animate","progress","useEffect","container","updateDimensions","width","height","resizeObserver","canvas","isComplete","isAnimating","jsxs"],"mappings":"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","file":"/Users/admin/Desktop/PROJECTS/alkimi-ui-kit/dist/chunk-R74QDO2Z.js","sourcesContent":[null,"\"use client\"\n\nimport Image, { type StaticImageData } from \"next/image\"\nimport { JSX, useCallback, useEffect, useRef, useState } from \"react\"\n\ntype PixelLoadStatus = \"loading\" | \"animating\" | \"complete\"\n\ntype ImageSrc = string | StaticImageData\n\nexport interface PixelLoadProps {\n src: ImageSrc\n alt: string\n duration?: number\n steps?: number\n className?: string\n onAnimationComplete?: () => void\n priority?: boolean\n quality?: number\n placeholder?: \"blur\" | \"empty\"\n blurDataURL?: string\n objectFit?: \"contain\" | \"cover\" | \"fill\" | \"none\" | \"scale-down\"\n}\n\nfunction isStaticImageData(src: ImageSrc): src is StaticImageData {\n return typeof src === \"object\" && \"src\" in src\n}\n\nfunction getImageSrc(src: ImageSrc): string {\n return isStaticImageData(src) ? src.src : src\n}\n\nexport function PixelLoad({\n src,\n alt,\n duration = 600,\n steps = 15,\n className,\n onAnimationComplete,\n priority,\n quality,\n placeholder = \"empty\",\n blurDataURL,\n objectFit = \"cover\",\n}: PixelLoadProps): JSX.Element {\n const containerRef = useRef<HTMLDivElement>(null)\n const canvasRef = useRef<HTMLCanvasElement>(null)\n const [status, setStatus] = useState<PixelLoadStatus>(\"loading\")\n const [dimensions, setDimensions] = useState<{\n width: number\n height: number\n } | null>(null)\n\n const imageSrc = getImageSrc(src)\n\n const drawPixelated = useCallback(\n (\n ctx: CanvasRenderingContext2D,\n img: HTMLImageElement,\n pixelSize: number,\n w: number,\n h: number\n ): void => {\n ctx.imageSmoothingEnabled = false\n\n const sw = Math.max(1, Math.floor(w / pixelSize))\n const sh = Math.max(1, Math.floor(h / pixelSize))\n\n ctx.clearRect(0, 0, w, h)\n ctx.drawImage(img, 0, 0, sw, sh)\n ctx.drawImage(canvasRef.current!, 0, 0, sw, sh, 0, 0, w, h)\n },\n []\n )\n\n const runAnimation = useCallback(\n (\n ctx: CanvasRenderingContext2D,\n img: HTMLImageElement,\n w: number,\n h: number\n ): void => {\n const minPixelSize = Math.max(w, h) / 4\n const intervalMs = duration / steps\n let currentStep = 0\n\n setStatus(\"animating\")\n\n const animate = (): void => {\n const progress = currentStep / steps\n const pixelSize = Math.max(1, Math.floor(minPixelSize * (1 - progress)))\n\n drawPixelated(ctx, img, pixelSize, w, h)\n\n currentStep++\n\n if (currentStep <= steps) {\n window.setTimeout(animate, intervalMs)\n } else {\n setStatus(\"complete\")\n onAnimationComplete?.()\n }\n }\n\n animate()\n },\n [duration, steps, drawPixelated, onAnimationComplete]\n )\n\n useEffect(() => {\n const container = containerRef.current\n if (!container) return\n\n const updateDimensions = (): void => {\n const { width, height } = container.getBoundingClientRect()\n setDimensions({ width: Math.floor(width), height: Math.floor(height) })\n }\n\n const resizeObserver = new ResizeObserver(updateDimensions)\n resizeObserver.observe(container)\n updateDimensions()\n\n return (): void => {\n resizeObserver.disconnect()\n }\n }, [])\n\n useEffect(() => {\n if (!dimensions) return\n\n // Guard against invalid dimensions\n if (dimensions.width <= 0 || dimensions.height <= 0) return\n\n const canvas = canvasRef.current\n if (!canvas) return\n\n const ctx = canvas.getContext(\"2d\")\n if (!ctx) return\n\n // Set canvas dimensions immediately to ensure it covers the area\n canvas.width = dimensions.width\n canvas.height = dimensions.height\n\n const img = new window.Image()\n img.crossOrigin = \"anonymous\"\n\n img.onload = (): void => {\n // Draw first frame immediately to prevent original image from showing\n const minPixelSize = Math.max(dimensions.width, dimensions.height) / 4\n drawPixelated(ctx, img, minPixelSize, dimensions.width, dimensions.height)\n // Then start animation\n runAnimation(ctx, img, dimensions.width, dimensions.height)\n }\n\n img.onerror = (): void => {\n console.error(\"PixelLoad: Failed to load image\")\n }\n\n img.src = imageSrc\n\n return (): void => {\n img.onload = null\n img.onerror = null\n }\n }, [imageSrc, dimensions, runAnimation, drawPixelated])\n\n const isComplete = status === \"complete\"\n const isAnimating = status === \"animating\" || status === \"loading\"\n\n return (\n <div\n ref={containerRef}\n className={`relative w-full h-full ${className || \"\"}`}\n >\n <canvas\n ref={canvasRef}\n className=\"absolute top-0 left-0 w-full h-full\"\n style={{\n objectFit,\n opacity: isComplete ? 0 : 1,\n zIndex: isAnimating ? 2 : 1,\n }}\n aria-hidden={isComplete}\n />\n {isComplete && (\n <Image\n src={src}\n alt={alt}\n fill\n priority={priority}\n quality={quality}\n placeholder={placeholder}\n blurDataURL={blurDataURL}\n className=\"opacity-100 transition-opacity duration-150 ease-out z-[1]\"\n style={{\n objectFit,\n }}\n />\n )}\n </div>\n )\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/utils.ts"],"sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n"],"mappings":";AAAA,OAA0B,QAAAA,MAAY,OACtC,OAAS,WAAAC,MAAe,iBAEjB,SAASC,KAAMC,EAAsB,CAC1C,OAAOF,EAAQD,EAAKG,CAAM,CAAC,CAC7B","names":["clsx","twMerge","cn","inputs"]}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }"use client";
|
|
2
|
+
var _chunkFUYXCJOQjs = require('./chunk-FUYXCJOQ.js');var _react = require('react'); var _react2 = _interopRequireDefault(_react);var _jsxruntime = require('react/jsx-runtime');var D=["\\","-","?","/","#","!","_","+","<",">"],O=3,H=200,v=e=>e?e.split(" ").map(n=>n?D[Math.floor(Math.random()*D.length)].repeat(n.length):"").join(" "):"",d=e=>{if(typeof e=="string"||typeof e=="number")return String(e);if(Array.isArray(e))return e.map(d).join("");if(_react2.default.isValidElement(e)){let n=e.props,r="";return typeof n.text=="string"&&(r+=n.text),typeof n.label=="string"&&(r+=n.label),typeof n.title=="string"&&(r+=n.title),n.children&&(r+=d(n.children)),r}return""},p=(e,n,r)=>{if(typeof e=="string"||typeof e=="number"){let s=String(e),i="";for(let t=0;t<s.length;t++)r.current<n.length?(i+=n[r.current],r.current++):i+=s[t];return i}if(Array.isArray(e))return e.map((s,i)=>{let t=p(s,n,r);if(_react2.default.isValidElement(t)){let l=_react2.default.isValidElement(s)?s.key:null;if(t.key==null&&l==null)return _react2.default.cloneElement(t,{key:`decoded-${i}`});if(t.key==null&&l!=null)return _react2.default.cloneElement(t,{key:l})}return t});if(_react2.default.isValidElement(e)){let s=e.props,i={...s};if(typeof s.text=="string"){let t=s.text,l="";for(let o=0;o<t.length;o++)r.current<n.length?(l+=n[r.current],r.current++):l+=t[o];i.text=l}if(typeof s.label=="string"){let t=s.label,l="";for(let o=0;o<t.length;o++)r.current<n.length?(l+=n[r.current],r.current++):l+=t[o];i.label=l}if(typeof s.title=="string"){let t=s.title,l="";for(let o=0;o<t.length;o++)r.current<n.length?(l+=n[r.current],r.current++):l+=t[o];i.title=l}return s.children&&(i.children=p(s.children,n,r)),_react2.default.cloneElement(e,i)}return e},I=({children:e,className:n,delay:r=0})=>{let[s,i]=_react.useState.call(void 0, null),[t,l]=_react.useState.call(void 0, !1),[o,u]=_react.useState.call(void 0, !0),k=_react.useRef.call(void 0, null),c=_react.useMemo.call(void 0, ()=>d(e),[e]),g=_react.useMemo.call(void 0, ()=>v(c),[c]);_react.useEffect.call(void 0, ()=>{if(!t&&c){let y=p(e,g,{current:0});i(y),u(!0)}},[e,g,t,c]),_react.useEffect.call(void 0, ()=>{if(!c){i(null),u(!1);return}if(t){u(!1);return}let N=k.current;if(!N)return;let y=0,f=null,h=null,R=new IntersectionObserver(T=>{T[0].isIntersecting&&!t&&(h=setTimeout(()=>{let C=p(e,g,{current:0});i(C),u(!0),f=setInterval(()=>{if(y++,y>=O)l(!0),u(!1),f&&clearInterval(f);else{let M=v(c),P=p(e,M,{current:0});i(P)}},H)},r),R.disconnect())},{threshold:.1});return R.observe(N),()=>{R.disconnect(),f&&clearInterval(f),h&&clearTimeout(h)}},[e,c,g,t,r]);let w=_react.useMemo.call(void 0, ()=>d(e),[e]);return _jsxruntime.jsxs.call(void 0, "span",{ref:k,"aria-label":w,className:_chunkFUYXCJOQjs.a.call(void 0, "inline-grid *:col-start-1 *:row-start-1",n),children:[_jsxruntime.jsx.call(void 0, "span",{className:_chunkFUYXCJOQjs.a.call(void 0, "transition-opacity duration-300",t?"opacity-100":"opacity-0"),children:e}),o&&s&&_jsxruntime.jsx.call(void 0, "span",{className:"transition-opacity duration-300",children:s})]})},J=e=>_jsxruntime.jsx.call(void 0, _react.Suspense,{fallback:_jsxruntime.jsx.call(void 0, "span",{className:_chunkFUYXCJOQjs.a.call(void 0, "opacity-0",e.className),children:e.children}),children:_jsxruntime.jsx.call(void 0, I,{...e})}),q= exports.a =J;exports.a = q;
|
|
3
|
+
//# sourceMappingURL=chunk-SVWC2KRP.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/admin/Desktop/PROJECTS/alkimi-ui-kit/dist/chunk-SVWC2KRP.js","../src/components/TextDecoder.tsx"],"names":["SYMBOLS","MAX_ITERATIONS","SPEED","scrambleText","input","word","extractText","node","React","props","result","scrambleReactNode","scrambledText","textStartIndex","text","scrambled","i","child","index","scrambledChild","originalKey"],"mappings":"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","file":"/Users/admin/Desktop/PROJECTS/alkimi-ui-kit/dist/chunk-SVWC2KRP.js","sourcesContent":[null,"\"use client\"\nimport { cn } from \"@/lib/utils\"\nimport React, {\n useState,\n useEffect,\n useMemo,\n useRef,\n Suspense,\n ReactNode,\n} from \"react\"\n\n// The symbols to use for the scrambling effect (moved outside to avoid recreation)\nconst SYMBOLS = [\"\\\\\", \"-\", \"?\", \"/\", \"#\", \"!\", \"_\", \"+\", \"<\", \">\"]\nconst MAX_ITERATIONS = 3 // How many times to scramble\nconst SPEED = 200 // Speed in milliseconds between scrambles\n\n// Helper function moved outside component to avoid recreation\nconst scrambleText = (input: string): string => {\n if (!input) return \"\"\n\n return input\n .split(\" \")\n .map((word: string) => {\n if (!word) return \"\"\n const randomSymbol = SYMBOLS[Math.floor(Math.random() * SYMBOLS.length)]\n return randomSymbol.repeat(word.length)\n })\n .join(\" \")\n}\n\n// Extract text content from React nodes recursively\n// Also checks common text props like 'text', 'label', 'title', etc.\nconst extractText = (node: ReactNode): string => {\n if (typeof node === \"string\" || typeof node === \"number\") {\n return String(node)\n }\n\n if (Array.isArray(node)) {\n return node.map(extractText).join(\"\")\n }\n\n if (React.isValidElement(node)) {\n const props = node.props as {\n children?: ReactNode\n text?: string\n label?: string\n title?: string\n [key: string]: unknown\n }\n\n let result = \"\"\n\n // Extract text from props first (in order: text, label, title)\n if (typeof props.text === \"string\") {\n result += props.text\n }\n if (typeof props.label === \"string\") {\n result += props.label\n }\n if (typeof props.title === \"string\") {\n result += props.title\n }\n\n // Then extract from children\n if (props.children) {\n result += extractText(props.children)\n }\n\n return result\n }\n\n return \"\"\n}\n\n// Clone React nodes and replace text content with scrambled text\n// This function maps scrambled text back to the original structure\nconst scrambleReactNode = (\n node: ReactNode,\n scrambledText: string,\n textStartIndex: { current: number }\n): ReactNode => {\n if (typeof node === \"string\" || typeof node === \"number\") {\n const text = String(node)\n // For each character in the original text, take the corresponding scrambled character\n // This preserves the length and structure\n let scrambled = \"\"\n for (let i = 0; i < text.length; i++) {\n if (textStartIndex.current < scrambledText.length) {\n scrambled += scrambledText[textStartIndex.current]\n textStartIndex.current++\n } else {\n // Fallback if scrambled text is shorter (shouldn't happen, but safety check)\n scrambled += text[i]\n }\n }\n return scrambled\n }\n\n if (Array.isArray(node)) {\n return node.map((child, index) => {\n const scrambledChild = scrambleReactNode(\n child,\n scrambledText,\n textStartIndex\n )\n // Preserve original key if it exists, otherwise add one for React elements\n if (React.isValidElement(scrambledChild)) {\n const originalKey = React.isValidElement(child) ? child.key : null\n if (scrambledChild.key == null && originalKey == null) {\n return React.cloneElement(scrambledChild, { key: `decoded-${index}` })\n }\n // If original had a key but scrambled doesn't, preserve it\n if (scrambledChild.key == null && originalKey != null) {\n return React.cloneElement(scrambledChild, { key: originalKey })\n }\n }\n return scrambledChild\n })\n }\n\n if (React.isValidElement(node)) {\n // Regular element handling - works for all components\n const props = node.props as {\n children?: ReactNode\n text?: string\n label?: string\n title?: string\n [key: string]: unknown\n }\n const newProps = { ...props }\n\n // Handle text props in the same order as extraction (text, label, title)\n if (typeof props.text === \"string\") {\n const text = props.text\n let scrambled = \"\"\n for (let i = 0; i < text.length; i++) {\n if (textStartIndex.current < scrambledText.length) {\n scrambled += scrambledText[textStartIndex.current]\n textStartIndex.current++\n } else {\n scrambled += text[i]\n }\n }\n newProps.text = scrambled\n }\n\n if (typeof props.label === \"string\") {\n const label = props.label\n let scrambled = \"\"\n for (let i = 0; i < label.length; i++) {\n if (textStartIndex.current < scrambledText.length) {\n scrambled += scrambledText[textStartIndex.current]\n textStartIndex.current++\n } else {\n scrambled += label[i]\n }\n }\n newProps.label = scrambled\n }\n\n if (typeof props.title === \"string\") {\n const title = props.title\n let scrambled = \"\"\n for (let i = 0; i < title.length; i++) {\n if (textStartIndex.current < scrambledText.length) {\n scrambled += scrambledText[textStartIndex.current]\n textStartIndex.current++\n } else {\n scrambled += title[i]\n }\n }\n newProps.title = scrambled\n }\n\n // Handle children after props\n if (props.children) {\n newProps.children = scrambleReactNode(\n props.children,\n scrambledText,\n textStartIndex\n )\n }\n return React.cloneElement(node, newProps)\n }\n\n return node\n}\n\nexport interface TextDecoderProps {\n children: ReactNode\n className?: string\n delay?: number // Delay in milliseconds before starting animation\n}\n\nconst TextDecoder = ({ children, className, delay = 0 }: TextDecoderProps) => {\n const [displayContent, setDisplayContent] = useState<ReactNode>(null)\n const [hasAnimated, setHasAnimated] = useState(false)\n const [showDecoded, setShowDecoded] = useState(true)\n const elementRef = useRef<HTMLSpanElement>(null)\n\n // Extract full text for scrambling\n const fullText = useMemo(() => extractText(children), [children])\n\n // Memoize initial scrambled text\n const initialScrambled = useMemo(() => scrambleText(fullText), [fullText])\n\n // Initialize with scrambled content to prevent layout shift\n useEffect(() => {\n if (!hasAnimated && fullText) {\n const textStartIndex = { current: 0 }\n const scrambledContent = scrambleReactNode(\n children,\n initialScrambled,\n textStartIndex\n )\n setDisplayContent(scrambledContent)\n setShowDecoded(true)\n }\n }, [children, initialScrambled, hasAnimated, fullText])\n\n useEffect(() => {\n if (!fullText) {\n setDisplayContent(null)\n setShowDecoded(false)\n return\n }\n\n // If already animated, hide decoded and show children\n if (hasAnimated) {\n setShowDecoded(false)\n return\n }\n\n const element = elementRef.current\n if (!element) return\n\n let iteration = 0\n let intervalId: NodeJS.Timeout | null = null\n let delayTimeoutId: NodeJS.Timeout | null = null\n\n // Intersection Observer to detect when element is visible\n const observer = new IntersectionObserver(\n (entries) => {\n const entry = entries[0]\n if (entry.isIntersecting && !hasAnimated) {\n // Start animation after delay\n delayTimeoutId = setTimeout(() => {\n // 1. Initial scramble\n const textStartIndex = { current: 0 }\n const scrambledContent = scrambleReactNode(\n children,\n initialScrambled,\n textStartIndex\n )\n setDisplayContent(scrambledContent)\n setShowDecoded(true)\n\n // 2. Set up the interval\n intervalId = setInterval(() => {\n iteration++\n\n if (iteration >= MAX_ITERATIONS) {\n // Stop scrambling, fade out decoded and fade in children\n setHasAnimated(true)\n setShowDecoded(false)\n if (intervalId) clearInterval(intervalId)\n } else {\n // Continue scrambling\n const newScrambled = scrambleText(fullText)\n const textStartIndex = { current: 0 }\n const scrambledContent = scrambleReactNode(\n children,\n newScrambled,\n textStartIndex\n )\n setDisplayContent(scrambledContent)\n }\n }, SPEED)\n }, delay)\n\n // Disconnect observer once animation starts\n observer.disconnect()\n }\n },\n {\n threshold: 0.1, // Trigger when 10% of the element is visible\n }\n )\n\n observer.observe(element)\n\n // Cleanup function\n return () => {\n observer.disconnect()\n if (intervalId) clearInterval(intervalId)\n if (delayTimeoutId) clearTimeout(delayTimeoutId)\n }\n }, [children, fullText, initialScrambled, hasAnimated, delay])\n\n const ariaLabel = useMemo(() => extractText(children), [children])\n\n return (\n <span\n ref={elementRef}\n aria-label={ariaLabel} // Accessibility: Screen readers read the real text\n className={cn(\"inline-grid *:col-start-1 *:row-start-1\", className)}\n >\n {/* Both elements in the same grid cell - prevents width changes */}\n <span\n className={cn(\n \"transition-opacity duration-300\",\n hasAnimated ? \"opacity-100\" : \"opacity-0\"\n )}\n >\n {children}\n </span>\n {/* Decoded animation overlay in the same grid cell */}\n {showDecoded && displayContent && (\n <span className=\"transition-opacity duration-300\">\n {displayContent}\n </span>\n )}\n </span>\n )\n}\n\nconst SuspenseDecodedText = (props: TextDecoderProps) => {\n return (\n <Suspense\n fallback={\n <span className={cn(\"opacity-0\", props.className)}>\n {props.children}\n </span>\n }\n >\n <TextDecoder {...props} />\n </Suspense>\n )\n}\n\nexport default SuspenseDecodedText\n"]}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import A from"next/image";import{useCallback as y,useEffect as I,useRef as M,useState as L}from"react";import{jsx as D,jsxs as X}from"react/jsx-runtime";function J(o){return typeof o=="object"&&"src"in o}function U(o){return J(o)?o.src:o}function $({src:o,alt:P,duration:h=600,steps:l=15,className:R,onAnimationComplete:f,priority:C,quality:E,placeholder:z="empty",blurDataURL:T,objectFit:p="cover"}){let v=M(null),u=M(null),[d,b]=L("loading"),[n,H]=L(null),S=U(o),c=y((t,a,e,i,r)=>{t.imageSmoothingEnabled=!1;let m=Math.max(1,Math.floor(i/e)),s=Math.max(1,Math.floor(r/e));t.clearRect(0,0,i,r),t.drawImage(a,0,0,m,s),t.drawImage(u.current,0,0,m,s,0,0,i,r)},[]),w=y((t,a,e,i)=>{let r=Math.max(e,i)/4,m=h/l,s=0;b("animating");let x=()=>{let O=s/l,q=Math.max(1,Math.floor(r*(1-O)));c(t,a,q,e,i),s++,s<=l?window.setTimeout(x,m):(b("complete"),f?.())};x()},[h,l,c,f]);I(()=>{let t=v.current;if(!t)return;let a=()=>{let{width:i,height:r}=t.getBoundingClientRect();H({width:Math.floor(i),height:Math.floor(r)})},e=new ResizeObserver(a);return e.observe(t),a(),()=>{e.disconnect()}},[]),I(()=>{if(!n||n.width<=0||n.height<=0)return;let t=u.current;if(!t)return;let a=t.getContext("2d");if(!a)return;t.width=n.width,t.height=n.height;let e=new window.Image;return e.crossOrigin="anonymous",e.onload=()=>{let i=Math.max(n.width,n.height)/4;c(a,e,i,n.width,n.height),w(a,e,n.width,n.height)},e.onerror=()=>{console.error("PixelLoad: Failed to load image")},e.src=S,()=>{e.onload=null,e.onerror=null}},[S,n,w,c]);let g=d==="complete",N=d==="animating"||d==="loading";return X("div",{ref:v,className:`relative w-full h-full ${R||""}`,children:[D("canvas",{ref:u,className:"absolute top-0 left-0 w-full h-full",style:{objectFit:p,opacity:g?0:1,zIndex:N?2:1},"aria-hidden":g}),g&&D(A,{src:o,alt:P,fill:!0,priority:C,quality:E,placeholder:z,blurDataURL:T,className:"opacity-100 transition-opacity duration-150 ease-out z-[1]",style:{objectFit:p}})]})}export{$ as a};
|
|
3
|
+
//# sourceMappingURL=chunk-WF73K6X2.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/PixelLoad.tsx"],"sourcesContent":["\"use client\"\n\nimport Image, { type StaticImageData } from \"next/image\"\nimport { JSX, useCallback, useEffect, useRef, useState } from \"react\"\n\ntype PixelLoadStatus = \"loading\" | \"animating\" | \"complete\"\n\ntype ImageSrc = string | StaticImageData\n\nexport interface PixelLoadProps {\n src: ImageSrc\n alt: string\n duration?: number\n steps?: number\n className?: string\n onAnimationComplete?: () => void\n priority?: boolean\n quality?: number\n placeholder?: \"blur\" | \"empty\"\n blurDataURL?: string\n objectFit?: \"contain\" | \"cover\" | \"fill\" | \"none\" | \"scale-down\"\n}\n\nfunction isStaticImageData(src: ImageSrc): src is StaticImageData {\n return typeof src === \"object\" && \"src\" in src\n}\n\nfunction getImageSrc(src: ImageSrc): string {\n return isStaticImageData(src) ? src.src : src\n}\n\nexport function PixelLoad({\n src,\n alt,\n duration = 600,\n steps = 15,\n className,\n onAnimationComplete,\n priority,\n quality,\n placeholder = \"empty\",\n blurDataURL,\n objectFit = \"cover\",\n}: PixelLoadProps): JSX.Element {\n const containerRef = useRef<HTMLDivElement>(null)\n const canvasRef = useRef<HTMLCanvasElement>(null)\n const [status, setStatus] = useState<PixelLoadStatus>(\"loading\")\n const [dimensions, setDimensions] = useState<{\n width: number\n height: number\n } | null>(null)\n\n const imageSrc = getImageSrc(src)\n\n const drawPixelated = useCallback(\n (\n ctx: CanvasRenderingContext2D,\n img: HTMLImageElement,\n pixelSize: number,\n w: number,\n h: number\n ): void => {\n ctx.imageSmoothingEnabled = false\n\n const sw = Math.max(1, Math.floor(w / pixelSize))\n const sh = Math.max(1, Math.floor(h / pixelSize))\n\n ctx.clearRect(0, 0, w, h)\n ctx.drawImage(img, 0, 0, sw, sh)\n ctx.drawImage(canvasRef.current!, 0, 0, sw, sh, 0, 0, w, h)\n },\n []\n )\n\n const runAnimation = useCallback(\n (\n ctx: CanvasRenderingContext2D,\n img: HTMLImageElement,\n w: number,\n h: number\n ): void => {\n const minPixelSize = Math.max(w, h) / 4\n const intervalMs = duration / steps\n let currentStep = 0\n\n setStatus(\"animating\")\n\n const animate = (): void => {\n const progress = currentStep / steps\n const pixelSize = Math.max(1, Math.floor(minPixelSize * (1 - progress)))\n\n drawPixelated(ctx, img, pixelSize, w, h)\n\n currentStep++\n\n if (currentStep <= steps) {\n window.setTimeout(animate, intervalMs)\n } else {\n setStatus(\"complete\")\n onAnimationComplete?.()\n }\n }\n\n animate()\n },\n [duration, steps, drawPixelated, onAnimationComplete]\n )\n\n useEffect(() => {\n const container = containerRef.current\n if (!container) return\n\n const updateDimensions = (): void => {\n const { width, height } = container.getBoundingClientRect()\n setDimensions({ width: Math.floor(width), height: Math.floor(height) })\n }\n\n const resizeObserver = new ResizeObserver(updateDimensions)\n resizeObserver.observe(container)\n updateDimensions()\n\n return (): void => {\n resizeObserver.disconnect()\n }\n }, [])\n\n useEffect(() => {\n if (!dimensions) return\n\n // Guard against invalid dimensions\n if (dimensions.width <= 0 || dimensions.height <= 0) return\n\n const canvas = canvasRef.current\n if (!canvas) return\n\n const ctx = canvas.getContext(\"2d\")\n if (!ctx) return\n\n // Set canvas dimensions immediately to ensure it covers the area\n canvas.width = dimensions.width\n canvas.height = dimensions.height\n\n const img = new window.Image()\n img.crossOrigin = \"anonymous\"\n\n img.onload = (): void => {\n // Draw first frame immediately to prevent original image from showing\n const minPixelSize = Math.max(dimensions.width, dimensions.height) / 4\n drawPixelated(ctx, img, minPixelSize, dimensions.width, dimensions.height)\n // Then start animation\n runAnimation(ctx, img, dimensions.width, dimensions.height)\n }\n\n img.onerror = (): void => {\n console.error(\"PixelLoad: Failed to load image\")\n }\n\n img.src = imageSrc\n\n return (): void => {\n img.onload = null\n img.onerror = null\n }\n }, [imageSrc, dimensions, runAnimation, drawPixelated])\n\n const isComplete = status === \"complete\"\n const isAnimating = status === \"animating\" || status === \"loading\"\n\n return (\n <div\n ref={containerRef}\n className={`relative w-full h-full ${className || \"\"}`}\n >\n <canvas\n ref={canvasRef}\n className=\"absolute top-0 left-0 w-full h-full\"\n style={{\n objectFit,\n opacity: isComplete ? 0 : 1,\n zIndex: isAnimating ? 2 : 1,\n }}\n aria-hidden={isComplete}\n />\n {isComplete && (\n <Image\n src={src}\n alt={alt}\n fill\n priority={priority}\n quality={quality}\n placeholder={placeholder}\n blurDataURL={blurDataURL}\n className=\"opacity-100 transition-opacity duration-150 ease-out z-[1]\"\n style={{\n objectFit,\n }}\n />\n )}\n </div>\n )\n}\n"],"mappings":"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","names":["Image","useCallback","useEffect","useRef","useState","jsx","jsxs","isStaticImageData","src","getImageSrc","PixelLoad","alt","duration","steps","className","onAnimationComplete","priority","quality","placeholder","blurDataURL","objectFit","containerRef","canvasRef","status","setStatus","dimensions","setDimensions","imageSrc","drawPixelated","ctx","img","pixelSize","w","h","sw","sh","runAnimation","minPixelSize","intervalMs","currentStep","animate","progress","container","updateDimensions","width","height","resizeObserver","canvas","isComplete","isAnimating"]}
|