@alkimi.org/ui-kit 0.1.7 → 0.1.9

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.
Files changed (48) hide show
  1. package/README.github.md +107 -28
  2. package/dist/components/GlitchLink.d.mts +12 -0
  3. package/dist/components/GlitchLink.d.ts +12 -0
  4. package/dist/components/GlitchLink.js +74 -0
  5. package/dist/components/GlitchLink.js.map +1 -0
  6. package/dist/components/GlitchLink.mjs +44 -0
  7. package/dist/components/GlitchLink.mjs.map +1 -0
  8. package/dist/components/PixelLoad.d.mts +20 -0
  9. package/dist/components/PixelLoad.d.ts +20 -0
  10. package/dist/components/PixelLoad.js +182 -0
  11. package/dist/components/PixelLoad.js.map +1 -0
  12. package/dist/components/PixelLoad.mjs +148 -0
  13. package/dist/components/PixelLoad.mjs.map +1 -0
  14. package/dist/components/TextDecoder.d.mts +15 -0
  15. package/dist/components/TextDecoder.d.ts +15 -0
  16. package/dist/components/TextDecoder.js +293 -0
  17. package/dist/components/TextDecoder.js.map +1 -0
  18. package/dist/components/TextDecoder.mjs +265 -0
  19. package/dist/components/TextDecoder.mjs.map +1 -0
  20. package/dist/components/button.d.mts +14 -0
  21. package/dist/components/button.d.ts +14 -0
  22. package/dist/components/button.js +95 -0
  23. package/dist/components/button.js.map +1 -0
  24. package/dist/components/button.mjs +60 -0
  25. package/dist/components/button.mjs.map +1 -0
  26. package/dist/components/card.d.mts +10 -0
  27. package/dist/components/card.d.ts +10 -0
  28. package/dist/components/card.js +115 -0
  29. package/dist/components/card.js.map +1 -0
  30. package/dist/components/card.mjs +76 -0
  31. package/dist/components/card.mjs.map +1 -0
  32. package/dist/index.css +172 -0
  33. package/dist/index.css.map +1 -1
  34. package/dist/index.d.mts +12 -24
  35. package/dist/index.d.ts +12 -24
  36. package/dist/index.js +420 -0
  37. package/dist/index.js.map +1 -1
  38. package/dist/index.mjs +423 -0
  39. package/dist/index.mjs.map +1 -1
  40. package/dist/lib/utils.d.mts +5 -0
  41. package/dist/lib/utils.d.ts +5 -0
  42. package/dist/lib/utils.js +36 -0
  43. package/dist/lib/utils.js.map +1 -0
  44. package/dist/lib/utils.mjs +12 -0
  45. package/dist/lib/utils.mjs.map +1 -0
  46. package/dist/styles.css +172 -0
  47. package/dist/styles.css.map +1 -1
  48. package/package.json +41 -16
package/README.github.md CHANGED
@@ -140,10 +140,59 @@ Or if you prefer, add the CSS variables to your own CSS file:
140
140
 
141
141
  ## Usage
142
142
 
143
+ You can import components in two ways:
144
+
145
+ ### Option 1: Import from Main Package (All Components)
146
+
147
+ ```tsx
148
+ import { Button, Card } from "@alkimi.org/ui-kit"
149
+ ```
150
+
151
+ ### Option 2: Import Individual Components (Tree-Shakeable)
152
+
153
+ For better tree-shaking and smaller bundle sizes, import components individually:
154
+
155
+ ```tsx
156
+ // Import only the Button component
157
+ import { Button } from "@alkimi.org/ui-kit/button"
158
+
159
+ // Import only the Card components
160
+ import { Card, CardHeader, CardTitle } from "@alkimi.org/ui-kit/card"
161
+
162
+ // Import utilities
163
+ import { cn } from "@alkimi.org/ui-kit/utils"
164
+ ```
165
+
166
+ ### Available Component Paths
167
+
168
+ - `@alkimi.org/ui-kit/button` - Button component
169
+ - `@alkimi.org/ui-kit/card` - Card components
170
+ - `@alkimi.org/ui-kit/text-decoder` - TextDecoder component
171
+ - `@alkimi.org/ui-kit/glitch-link` - GlitchLink component (requires Next.js)
172
+ - `@alkimi.org/ui-kit/pixel-load` - PixelLoad component (requires Next.js)
173
+ - `@alkimi.org/ui-kit/utils` - Utility functions
174
+
175
+ ### Next.js Components
176
+
177
+ Some components require Next.js to be installed:
178
+
179
+ ```bash
180
+ npm install next
181
+ ```
182
+
183
+ Then you can use:
184
+
185
+ ```tsx
186
+ import GlitchLink from "@alkimi.org/ui-kit/glitch-link"
187
+ import { PixelLoad } from "@alkimi.org/ui-kit/pixel-load"
188
+ ```
189
+
190
+ > **Note:** If you're not using Next.js, you can still use all other components. Next.js is marked as an optional peer dependency.
191
+
143
192
  ### Button Component
144
193
 
145
194
  ```tsx
146
- import { Button } from "@alkimi/ui-kit"
195
+ import { Button } from "@alkimi.org/ui-kit/button"
147
196
 
148
197
  function App() {
149
198
  return (
@@ -171,8 +220,8 @@ import {
171
220
  CardDescription,
172
221
  CardContent,
173
222
  CardFooter,
174
- Button,
175
- } from "@alkimi/ui-kit"
223
+ } from "@alkimi.org/ui-kit/card"
224
+ import { Button } from "@alkimi.org/ui-kit/button"
176
225
 
177
226
  function App() {
178
227
  return (
@@ -208,9 +257,62 @@ To add more shadcn/ui components to this library:
208
257
  export { ComponentName } from "./components/component-name"
209
258
  ```
210
259
 
211
- 3. Rebuild the library:
260
+ 3. Create a story file in the `stories/` folder:
261
+
262
+ ```tsx
263
+ // stories/ComponentName.stories.tsx
264
+ import type { Meta, StoryObj } from "@storybook/react"
265
+ import { ComponentName } from "../src/components/component-name"
266
+
267
+ const meta = {
268
+ title: "Components/ComponentName",
269
+ component: ComponentName,
270
+ parameters: {
271
+ layout: "centered",
272
+ },
273
+ tags: ["autodocs"],
274
+ } satisfies Meta<typeof ComponentName>
275
+
276
+ export default meta
277
+ type Story = StoryObj<typeof meta>
278
+
279
+ export const Default: Story = {
280
+ args: {
281
+ // your component props
282
+ },
283
+ }
284
+ ```
285
+
286
+ 4. Test locally with Storybook:
287
+
288
+ ```bash
289
+ npm run storybook
290
+ ```
291
+
292
+ 5. Commit and push to main:
293
+
212
294
  ```bash
295
+ git add .
296
+ git commit -m "feat: add ComponentName"
297
+ git push
298
+ ```
299
+
300
+ 6. Update the Storybook deployment:
301
+
302
+ ```bash
303
+ git checkout storybook
304
+ git merge main
305
+ git push
306
+ ```
307
+
308
+ Vercel will automatically rebuild and deploy the updated Storybook.
309
+
310
+ 7. (Optional) Publish to npm:
311
+ ```bash
312
+ git checkout main
313
+ # Update version in package.json
213
314
  npm run build
315
+ npm publish
214
316
  ```
215
317
 
216
318
  ## Development
@@ -225,7 +327,7 @@ npm install
225
327
  npm run dev
226
328
  ```
227
329
 
228
- Then open [http://localhost:5173](http://localhost:5173) in your browser.
330
+ Then open [http://localhost:3000](http://localhost:3000) in your browser.
229
331
 
230
332
  The demo showcases all available components with interactive examples, including:
231
333
 
@@ -278,29 +380,6 @@ npm run build-storybook
278
380
 
279
381
  This will generate a static site in the `storybook-static` directory that you can deploy to any static hosting service.
280
382
 
281
- #### Deploying to Vercel
282
-
283
- **Option 1: Using Vercel Dashboard (No Terminal Required)**
284
-
285
- 1. Build Storybook locally: `npm run build-storybook`
286
- 2. Go to [vercel.com](https://vercel.com) and log in
287
- 3. Click "Add New..." → "Project"
288
- 4. If this is your first time:
289
- - Import your repository from GitHub/GitLab/Bitbucket
290
- - In the project settings, configure:
291
- - **Build Command**: `npm run build-storybook`
292
- - **Output Directory**: `storybook-static`
293
- - **Install Command**: `npm install`
294
- 5. Click "Deploy"
295
-
296
- Vercel will automatically deploy your Storybook and provide you with a URL. Every time you push to your main branch, Vercel will rebuild and redeploy automatically.
297
-
298
- **Option 2: Using Vercel CLI**
299
-
300
- 1. Build Storybook: `npm run build-storybook`
301
- 2. Install Vercel CLI (if not already installed): `npm i -g vercel`
302
- 3. Deploy: `vercel storybook-static`
303
-
304
383
  ## Publishing to npm
305
384
 
306
385
  1. Update the version number in [package.json](package.json) (e.g., from `0.1.3` to `0.1.4`)
@@ -0,0 +1,12 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { RefAttributes, ReactNode } from 'react';
3
+
4
+ type GlitchLinkProps = RefAttributes<HTMLAnchorElement> & {
5
+ href: string;
6
+ children: ReactNode;
7
+ symbols?: string[];
8
+ className?: string;
9
+ };
10
+ declare const GlitchLink: ({ href, children, symbols, className, ...props }: GlitchLinkProps) => react_jsx_runtime.JSX.Element;
11
+
12
+ export { GlitchLink as default };
@@ -0,0 +1,12 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { RefAttributes, ReactNode } from 'react';
3
+
4
+ type GlitchLinkProps = RefAttributes<HTMLAnchorElement> & {
5
+ href: string;
6
+ children: ReactNode;
7
+ symbols?: string[];
8
+ className?: string;
9
+ };
10
+ declare const GlitchLink: ({ href, children, symbols, className, ...props }: GlitchLinkProps) => react_jsx_runtime.JSX.Element;
11
+
12
+ export { GlitchLink as default };
@@ -0,0 +1,74 @@
1
+ "use client"
2
+ "use strict";
3
+ "use client";
4
+ var __create = Object.create;
5
+ var __defProp = Object.defineProperty;
6
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
7
+ var __getOwnPropNames = Object.getOwnPropertyNames;
8
+ var __getProtoOf = Object.getPrototypeOf;
9
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
10
+ var __export = (target, all) => {
11
+ for (var name in all)
12
+ __defProp(target, name, { get: all[name], enumerable: true });
13
+ };
14
+ var __copyProps = (to, from, except, desc) => {
15
+ if (from && typeof from === "object" || typeof from === "function") {
16
+ for (let key of __getOwnPropNames(from))
17
+ if (!__hasOwnProp.call(to, key) && key !== except)
18
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
19
+ }
20
+ return to;
21
+ };
22
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
23
+ // If the importer is in node compatibility mode or this is not an ESM
24
+ // file that has been converted to a CommonJS file using a Babel-
25
+ // compatible transform (i.e. "__esModule" has not been set), then set
26
+ // "default" to the CommonJS "module.exports" for node compatibility.
27
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
28
+ mod
29
+ ));
30
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
31
+
32
+ // src/components/GlitchLink.tsx
33
+ var GlitchLink_exports = {};
34
+ __export(GlitchLink_exports, {
35
+ default: () => GlitchLink_default
36
+ });
37
+ module.exports = __toCommonJS(GlitchLink_exports);
38
+ var import_link = __toESM(require("next/link"));
39
+ var import_react = require("react");
40
+ var import_jsx_runtime = require("react/jsx-runtime");
41
+ var DEFAULT_SYMBOLS = ["/", "#", "*"];
42
+ var GlitchLink = ({
43
+ href,
44
+ children,
45
+ symbols = DEFAULT_SYMBOLS,
46
+ className = "underline",
47
+ ...props
48
+ }) => {
49
+ const [isHovering, setIsHovering] = (0, import_react.useState)(false);
50
+ const text = typeof children === "string" ? children : "";
51
+ const getRandomGlitch = () => {
52
+ if (!isHovering || !text) return children;
53
+ return text.split(" ").map((word) => {
54
+ const randomLetterIndex = Math.floor(Math.random() * word.length);
55
+ return word.replace(
56
+ word[randomLetterIndex],
57
+ symbols[Math.floor(Math.random() * symbols.length)]
58
+ );
59
+ }).join(" ");
60
+ };
61
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
62
+ import_link.default,
63
+ {
64
+ href,
65
+ className,
66
+ onMouseEnter: () => setIsHovering(true),
67
+ onMouseLeave: () => setIsHovering(false),
68
+ ...props,
69
+ children: text ? isHovering ? getRandomGlitch() : children : children
70
+ }
71
+ );
72
+ };
73
+ var GlitchLink_default = GlitchLink;
74
+ //# sourceMappingURL=GlitchLink.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/GlitchLink.tsx"],"sourcesContent":["\"use client\"\nimport Link from \"next/link\"\nimport { RefAttributes, useState, ReactNode } from \"react\"\n\ntype GlitchLinkProps = RefAttributes<HTMLAnchorElement> & {\n href: string\n children: ReactNode\n symbols?: string[]\n className?: string\n}\n\nconst DEFAULT_SYMBOLS = [\"/\", \"#\", \"*\"]\n\nconst GlitchLink = ({\n href,\n children,\n symbols = DEFAULT_SYMBOLS,\n className = \"underline\",\n ...props\n}: GlitchLinkProps) => {\n const [isHovering, setIsHovering] = useState(false)\n\n const text = typeof children === \"string\" ? children : \"\"\n\n const getRandomGlitch = () => {\n if (!isHovering || !text) return children\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 return (\n <Link\n href={href}\n className={className}\n onMouseEnter={() => setIsHovering(true)}\n onMouseLeave={() => setIsHovering(false)}\n {...props}\n >\n {text ? (isHovering ? getRandomGlitch() : children) : children}\n </Link>\n )\n}\n\nexport default GlitchLink\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,kBAAiB;AACjB,mBAAmD;AAwC/C;AA/BJ,IAAM,kBAAkB,CAAC,KAAK,KAAK,GAAG;AAEtC,IAAM,aAAa,CAAC;AAAA,EAClB;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,GAAG;AACL,MAAuB;AACrB,QAAM,CAAC,YAAY,aAAa,QAAI,uBAAS,KAAK;AAElD,QAAM,OAAO,OAAO,aAAa,WAAW,WAAW;AAEvD,QAAM,kBAAkB,MAAM;AAC5B,QAAI,CAAC,cAAc,CAAC,KAAM,QAAO;AACjC,WAAO,KACJ,MAAM,GAAG,EACT,IAAI,CAAC,SAAiB;AAErB,YAAM,oBAAoB,KAAK,MAAM,KAAK,OAAO,IAAI,KAAK,MAAM;AAGhE,aAAO,KAAK;AAAA,QACV,KAAK,iBAAiB;AAAA,QACtB,QAAQ,KAAK,MAAM,KAAK,OAAO,IAAI,QAAQ,MAAM,CAAC;AAAA,MACpD;AAAA,IACF,CAAC,EACA,KAAK,GAAG;AAAA,EACb;AAEA,SACE;AAAA,IAAC,YAAAA;AAAA,IAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA,cAAc,MAAM,cAAc,IAAI;AAAA,MACtC,cAAc,MAAM,cAAc,KAAK;AAAA,MACtC,GAAG;AAAA,MAEH,iBAAQ,aAAa,gBAAgB,IAAI,WAAY;AAAA;AAAA,EACxD;AAEJ;AAEA,IAAO,qBAAQ;","names":["Link"]}
@@ -0,0 +1,44 @@
1
+ "use client"
2
+ "use client";
3
+
4
+ // src/components/GlitchLink.tsx
5
+ import Link from "next/link";
6
+ import { useState } from "react";
7
+ import { jsx } from "react/jsx-runtime";
8
+ var DEFAULT_SYMBOLS = ["/", "#", "*"];
9
+ var GlitchLink = ({
10
+ href,
11
+ children,
12
+ symbols = DEFAULT_SYMBOLS,
13
+ className = "underline",
14
+ ...props
15
+ }) => {
16
+ const [isHovering, setIsHovering] = useState(false);
17
+ const text = typeof children === "string" ? children : "";
18
+ const getRandomGlitch = () => {
19
+ if (!isHovering || !text) return children;
20
+ return text.split(" ").map((word) => {
21
+ const randomLetterIndex = Math.floor(Math.random() * word.length);
22
+ return word.replace(
23
+ word[randomLetterIndex],
24
+ symbols[Math.floor(Math.random() * symbols.length)]
25
+ );
26
+ }).join(" ");
27
+ };
28
+ return /* @__PURE__ */ jsx(
29
+ Link,
30
+ {
31
+ href,
32
+ className,
33
+ onMouseEnter: () => setIsHovering(true),
34
+ onMouseLeave: () => setIsHovering(false),
35
+ ...props,
36
+ children: text ? isHovering ? getRandomGlitch() : children : children
37
+ }
38
+ );
39
+ };
40
+ var GlitchLink_default = GlitchLink;
41
+ export {
42
+ GlitchLink_default as default
43
+ };
44
+ //# sourceMappingURL=GlitchLink.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/GlitchLink.tsx"],"sourcesContent":["\"use client\"\nimport Link from \"next/link\"\nimport { RefAttributes, useState, ReactNode } from \"react\"\n\ntype GlitchLinkProps = RefAttributes<HTMLAnchorElement> & {\n href: string\n children: ReactNode\n symbols?: string[]\n className?: string\n}\n\nconst DEFAULT_SYMBOLS = [\"/\", \"#\", \"*\"]\n\nconst GlitchLink = ({\n href,\n children,\n symbols = DEFAULT_SYMBOLS,\n className = \"underline\",\n ...props\n}: GlitchLinkProps) => {\n const [isHovering, setIsHovering] = useState(false)\n\n const text = typeof children === \"string\" ? children : \"\"\n\n const getRandomGlitch = () => {\n if (!isHovering || !text) return children\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 return (\n <Link\n href={href}\n className={className}\n onMouseEnter={() => setIsHovering(true)}\n onMouseLeave={() => setIsHovering(false)}\n {...props}\n >\n {text ? (isHovering ? getRandomGlitch() : children) : children}\n </Link>\n )\n}\n\nexport default GlitchLink\n"],"mappings":";;;;AACA,OAAO,UAAU;AACjB,SAAwB,gBAA2B;AAwC/C;AA/BJ,IAAM,kBAAkB,CAAC,KAAK,KAAK,GAAG;AAEtC,IAAM,aAAa,CAAC;AAAA,EAClB;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,GAAG;AACL,MAAuB;AACrB,QAAM,CAAC,YAAY,aAAa,IAAI,SAAS,KAAK;AAElD,QAAM,OAAO,OAAO,aAAa,WAAW,WAAW;AAEvD,QAAM,kBAAkB,MAAM;AAC5B,QAAI,CAAC,cAAc,CAAC,KAAM,QAAO;AACjC,WAAO,KACJ,MAAM,GAAG,EACT,IAAI,CAAC,SAAiB;AAErB,YAAM,oBAAoB,KAAK,MAAM,KAAK,OAAO,IAAI,KAAK,MAAM;AAGhE,aAAO,KAAK;AAAA,QACV,KAAK,iBAAiB;AAAA,QACtB,QAAQ,KAAK,MAAM,KAAK,OAAO,IAAI,QAAQ,MAAM,CAAC;AAAA,MACpD;AAAA,IACF,CAAC,EACA,KAAK,GAAG;AAAA,EACb;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA,cAAc,MAAM,cAAc,IAAI;AAAA,MACtC,cAAc,MAAM,cAAc,KAAK;AAAA,MACtC,GAAG;AAAA,MAEH,iBAAQ,aAAa,gBAAgB,IAAI,WAAY;AAAA;AAAA,EACxD;AAEJ;AAEA,IAAO,qBAAQ;","names":[]}
@@ -0,0 +1,20 @@
1
+ import { StaticImageData } from 'next/image';
2
+ import { JSX } from 'react';
3
+
4
+ type ImageSrc = string | StaticImageData;
5
+ interface PixelLoadProps {
6
+ src: ImageSrc;
7
+ alt: string;
8
+ duration?: number;
9
+ steps?: number;
10
+ className?: string;
11
+ onAnimationComplete?: () => void;
12
+ priority?: boolean;
13
+ quality?: number;
14
+ placeholder?: "blur" | "empty";
15
+ blurDataURL?: string;
16
+ objectFit?: "contain" | "cover" | "fill" | "none" | "scale-down";
17
+ }
18
+ declare function PixelLoad({ src, alt, duration, steps, className, onAnimationComplete, priority, quality, placeholder, blurDataURL, objectFit, }: PixelLoadProps): JSX.Element;
19
+
20
+ export { PixelLoad, type PixelLoadProps };
@@ -0,0 +1,20 @@
1
+ import { StaticImageData } from 'next/image';
2
+ import { JSX } from 'react';
3
+
4
+ type ImageSrc = string | StaticImageData;
5
+ interface PixelLoadProps {
6
+ src: ImageSrc;
7
+ alt: string;
8
+ duration?: number;
9
+ steps?: number;
10
+ className?: string;
11
+ onAnimationComplete?: () => void;
12
+ priority?: boolean;
13
+ quality?: number;
14
+ placeholder?: "blur" | "empty";
15
+ blurDataURL?: string;
16
+ objectFit?: "contain" | "cover" | "fill" | "none" | "scale-down";
17
+ }
18
+ declare function PixelLoad({ src, alt, duration, steps, className, onAnimationComplete, priority, quality, placeholder, blurDataURL, objectFit, }: PixelLoadProps): JSX.Element;
19
+
20
+ export { PixelLoad, type PixelLoadProps };
@@ -0,0 +1,182 @@
1
+ "use client"
2
+ "use strict";
3
+ "use client";
4
+ var __create = Object.create;
5
+ var __defProp = Object.defineProperty;
6
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
7
+ var __getOwnPropNames = Object.getOwnPropertyNames;
8
+ var __getProtoOf = Object.getPrototypeOf;
9
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
10
+ var __export = (target, all) => {
11
+ for (var name in all)
12
+ __defProp(target, name, { get: all[name], enumerable: true });
13
+ };
14
+ var __copyProps = (to, from, except, desc) => {
15
+ if (from && typeof from === "object" || typeof from === "function") {
16
+ for (let key of __getOwnPropNames(from))
17
+ if (!__hasOwnProp.call(to, key) && key !== except)
18
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
19
+ }
20
+ return to;
21
+ };
22
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
23
+ // If the importer is in node compatibility mode or this is not an ESM
24
+ // file that has been converted to a CommonJS file using a Babel-
25
+ // compatible transform (i.e. "__esModule" has not been set), then set
26
+ // "default" to the CommonJS "module.exports" for node compatibility.
27
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
28
+ mod
29
+ ));
30
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
31
+
32
+ // src/components/PixelLoad.tsx
33
+ var PixelLoad_exports = {};
34
+ __export(PixelLoad_exports, {
35
+ PixelLoad: () => PixelLoad
36
+ });
37
+ module.exports = __toCommonJS(PixelLoad_exports);
38
+ var import_image = __toESM(require("next/image"));
39
+ var import_react = require("react");
40
+ var import_jsx_runtime = require("react/jsx-runtime");
41
+ function isStaticImageData(src) {
42
+ return typeof src === "object" && "src" in src;
43
+ }
44
+ function getImageSrc(src) {
45
+ return isStaticImageData(src) ? src.src : src;
46
+ }
47
+ function PixelLoad({
48
+ src,
49
+ alt,
50
+ duration = 600,
51
+ steps = 15,
52
+ className,
53
+ onAnimationComplete,
54
+ priority,
55
+ quality,
56
+ placeholder = "empty",
57
+ blurDataURL,
58
+ objectFit = "cover"
59
+ }) {
60
+ const containerRef = (0, import_react.useRef)(null);
61
+ const canvasRef = (0, import_react.useRef)(null);
62
+ const [status, setStatus] = (0, import_react.useState)("loading");
63
+ const [dimensions, setDimensions] = (0, import_react.useState)(null);
64
+ const imageSrc = getImageSrc(src);
65
+ const drawPixelated = (0, import_react.useCallback)(
66
+ (ctx, img, pixelSize, w, h) => {
67
+ ctx.imageSmoothingEnabled = false;
68
+ const sw = Math.max(1, Math.floor(w / pixelSize));
69
+ const sh = Math.max(1, Math.floor(h / pixelSize));
70
+ ctx.clearRect(0, 0, w, h);
71
+ ctx.drawImage(img, 0, 0, sw, sh);
72
+ ctx.drawImage(canvasRef.current, 0, 0, sw, sh, 0, 0, w, h);
73
+ },
74
+ []
75
+ );
76
+ const runAnimation = (0, import_react.useCallback)(
77
+ (ctx, img, w, h) => {
78
+ const minPixelSize = Math.max(w, h) / 4;
79
+ const intervalMs = duration / steps;
80
+ let currentStep = 0;
81
+ setStatus("animating");
82
+ const animate = () => {
83
+ const progress = currentStep / steps;
84
+ const pixelSize = Math.max(1, Math.floor(minPixelSize * (1 - progress)));
85
+ drawPixelated(ctx, img, pixelSize, w, h);
86
+ currentStep++;
87
+ if (currentStep <= steps) {
88
+ window.setTimeout(animate, intervalMs);
89
+ } else {
90
+ setStatus("complete");
91
+ onAnimationComplete?.();
92
+ }
93
+ };
94
+ animate();
95
+ },
96
+ [duration, steps, drawPixelated, onAnimationComplete]
97
+ );
98
+ (0, import_react.useEffect)(() => {
99
+ const container = containerRef.current;
100
+ if (!container) return;
101
+ const updateDimensions = () => {
102
+ const { width, height } = container.getBoundingClientRect();
103
+ setDimensions({ width: Math.floor(width), height: Math.floor(height) });
104
+ };
105
+ const resizeObserver = new ResizeObserver(updateDimensions);
106
+ resizeObserver.observe(container);
107
+ updateDimensions();
108
+ return () => {
109
+ resizeObserver.disconnect();
110
+ };
111
+ }, []);
112
+ (0, import_react.useEffect)(() => {
113
+ if (!dimensions) return;
114
+ if (dimensions.width <= 0 || dimensions.height <= 0) return;
115
+ const canvas = canvasRef.current;
116
+ if (!canvas) return;
117
+ const ctx = canvas.getContext("2d");
118
+ if (!ctx) return;
119
+ canvas.width = dimensions.width;
120
+ canvas.height = dimensions.height;
121
+ const img = new window.Image();
122
+ img.crossOrigin = "anonymous";
123
+ img.onload = () => {
124
+ const minPixelSize = Math.max(dimensions.width, dimensions.height) / 4;
125
+ drawPixelated(ctx, img, minPixelSize, dimensions.width, dimensions.height);
126
+ runAnimation(ctx, img, dimensions.width, dimensions.height);
127
+ };
128
+ img.onerror = () => {
129
+ console.error("PixelLoad: Failed to load image");
130
+ };
131
+ img.src = imageSrc;
132
+ return () => {
133
+ img.onload = null;
134
+ img.onerror = null;
135
+ };
136
+ }, [imageSrc, dimensions, runAnimation, drawPixelated]);
137
+ const isComplete = status === "complete";
138
+ const isAnimating = status === "animating" || status === "loading";
139
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
140
+ "div",
141
+ {
142
+ ref: containerRef,
143
+ className: `relative w-full h-full ${className || ""}`,
144
+ children: [
145
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
146
+ "canvas",
147
+ {
148
+ ref: canvasRef,
149
+ className: "absolute top-0 left-0 w-full h-full",
150
+ style: {
151
+ objectFit,
152
+ opacity: isComplete ? 0 : 1,
153
+ zIndex: isAnimating ? 2 : 1
154
+ },
155
+ "aria-hidden": isComplete
156
+ }
157
+ ),
158
+ isComplete && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
159
+ import_image.default,
160
+ {
161
+ src,
162
+ alt,
163
+ fill: true,
164
+ priority,
165
+ quality,
166
+ placeholder,
167
+ blurDataURL,
168
+ className: "opacity-100 transition-opacity duration-150 ease-out z-[1]",
169
+ style: {
170
+ objectFit
171
+ }
172
+ }
173
+ )
174
+ ]
175
+ }
176
+ );
177
+ }
178
+ // Annotate the CommonJS export names for ESM import in node:
179
+ 0 && (module.exports = {
180
+ PixelLoad
181
+ });
182
+ //# sourceMappingURL=PixelLoad.js.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"]}