@alkimi.org/ui-kit 0.1.8 → 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 +62 -10
  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 -12
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 (
@@ -212,8 +261,8 @@ To add more shadcn/ui components to this library:
212
261
 
213
262
  ```tsx
214
263
  // stories/ComponentName.stories.tsx
215
- import type { Meta, StoryObj } from "@storybook/react";
216
- import { ComponentName } from "../src/components/component-name";
264
+ import type { Meta, StoryObj } from "@storybook/react"
265
+ import { ComponentName } from "../src/components/component-name"
217
266
 
218
267
  const meta = {
219
268
  title: "Components/ComponentName",
@@ -222,24 +271,26 @@ To add more shadcn/ui components to this library:
222
271
  layout: "centered",
223
272
  },
224
273
  tags: ["autodocs"],
225
- } satisfies Meta<typeof ComponentName>;
274
+ } satisfies Meta<typeof ComponentName>
226
275
 
227
- export default meta;
228
- type Story = StoryObj<typeof meta>;
276
+ export default meta
277
+ type Story = StoryObj<typeof meta>
229
278
 
230
279
  export const Default: Story = {
231
280
  args: {
232
281
  // your component props
233
282
  },
234
- };
283
+ }
235
284
  ```
236
285
 
237
286
  4. Test locally with Storybook:
287
+
238
288
  ```bash
239
289
  npm run storybook
240
290
  ```
241
291
 
242
292
  5. Commit and push to main:
293
+
243
294
  ```bash
244
295
  git add .
245
296
  git commit -m "feat: add ComponentName"
@@ -247,6 +298,7 @@ To add more shadcn/ui components to this library:
247
298
  ```
248
299
 
249
300
  6. Update the Storybook deployment:
301
+
250
302
  ```bash
251
303
  git checkout storybook
252
304
  git merge main
@@ -275,7 +327,7 @@ npm install
275
327
  npm run dev
276
328
  ```
277
329
 
278
- Then open [http://localhost:5173](http://localhost:5173) in your browser.
330
+ Then open [http://localhost:3000](http://localhost:3000) in your browser.
279
331
 
280
332
  The demo showcases all available components with interactive examples, including:
281
333
 
@@ -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"]}
@@ -0,0 +1,148 @@
1
+ "use client"
2
+ "use client";
3
+
4
+ // src/components/PixelLoad.tsx
5
+ import Image from "next/image";
6
+ import { useCallback, useEffect, useRef, useState } from "react";
7
+ import { jsx, jsxs } from "react/jsx-runtime";
8
+ function isStaticImageData(src) {
9
+ return typeof src === "object" && "src" in src;
10
+ }
11
+ function getImageSrc(src) {
12
+ return isStaticImageData(src) ? src.src : src;
13
+ }
14
+ function PixelLoad({
15
+ src,
16
+ alt,
17
+ duration = 600,
18
+ steps = 15,
19
+ className,
20
+ onAnimationComplete,
21
+ priority,
22
+ quality,
23
+ placeholder = "empty",
24
+ blurDataURL,
25
+ objectFit = "cover"
26
+ }) {
27
+ const containerRef = useRef(null);
28
+ const canvasRef = useRef(null);
29
+ const [status, setStatus] = useState("loading");
30
+ const [dimensions, setDimensions] = useState(null);
31
+ const imageSrc = getImageSrc(src);
32
+ const drawPixelated = useCallback(
33
+ (ctx, img, pixelSize, w, h) => {
34
+ ctx.imageSmoothingEnabled = false;
35
+ const sw = Math.max(1, Math.floor(w / pixelSize));
36
+ const sh = Math.max(1, Math.floor(h / pixelSize));
37
+ ctx.clearRect(0, 0, w, h);
38
+ ctx.drawImage(img, 0, 0, sw, sh);
39
+ ctx.drawImage(canvasRef.current, 0, 0, sw, sh, 0, 0, w, h);
40
+ },
41
+ []
42
+ );
43
+ const runAnimation = useCallback(
44
+ (ctx, img, w, h) => {
45
+ const minPixelSize = Math.max(w, h) / 4;
46
+ const intervalMs = duration / steps;
47
+ let currentStep = 0;
48
+ setStatus("animating");
49
+ const animate = () => {
50
+ const progress = currentStep / steps;
51
+ const pixelSize = Math.max(1, Math.floor(minPixelSize * (1 - progress)));
52
+ drawPixelated(ctx, img, pixelSize, w, h);
53
+ currentStep++;
54
+ if (currentStep <= steps) {
55
+ window.setTimeout(animate, intervalMs);
56
+ } else {
57
+ setStatus("complete");
58
+ onAnimationComplete?.();
59
+ }
60
+ };
61
+ animate();
62
+ },
63
+ [duration, steps, drawPixelated, onAnimationComplete]
64
+ );
65
+ useEffect(() => {
66
+ const container = containerRef.current;
67
+ if (!container) return;
68
+ const updateDimensions = () => {
69
+ const { width, height } = container.getBoundingClientRect();
70
+ setDimensions({ width: Math.floor(width), height: Math.floor(height) });
71
+ };
72
+ const resizeObserver = new ResizeObserver(updateDimensions);
73
+ resizeObserver.observe(container);
74
+ updateDimensions();
75
+ return () => {
76
+ resizeObserver.disconnect();
77
+ };
78
+ }, []);
79
+ useEffect(() => {
80
+ if (!dimensions) return;
81
+ if (dimensions.width <= 0 || dimensions.height <= 0) return;
82
+ const canvas = canvasRef.current;
83
+ if (!canvas) return;
84
+ const ctx = canvas.getContext("2d");
85
+ if (!ctx) return;
86
+ canvas.width = dimensions.width;
87
+ canvas.height = dimensions.height;
88
+ const img = new window.Image();
89
+ img.crossOrigin = "anonymous";
90
+ img.onload = () => {
91
+ const minPixelSize = Math.max(dimensions.width, dimensions.height) / 4;
92
+ drawPixelated(ctx, img, minPixelSize, dimensions.width, dimensions.height);
93
+ runAnimation(ctx, img, dimensions.width, dimensions.height);
94
+ };
95
+ img.onerror = () => {
96
+ console.error("PixelLoad: Failed to load image");
97
+ };
98
+ img.src = imageSrc;
99
+ return () => {
100
+ img.onload = null;
101
+ img.onerror = null;
102
+ };
103
+ }, [imageSrc, dimensions, runAnimation, drawPixelated]);
104
+ const isComplete = status === "complete";
105
+ const isAnimating = status === "animating" || status === "loading";
106
+ return /* @__PURE__ */ jsxs(
107
+ "div",
108
+ {
109
+ ref: containerRef,
110
+ className: `relative w-full h-full ${className || ""}`,
111
+ children: [
112
+ /* @__PURE__ */ jsx(
113
+ "canvas",
114
+ {
115
+ ref: canvasRef,
116
+ className: "absolute top-0 left-0 w-full h-full",
117
+ style: {
118
+ objectFit,
119
+ opacity: isComplete ? 0 : 1,
120
+ zIndex: isAnimating ? 2 : 1
121
+ },
122
+ "aria-hidden": isComplete
123
+ }
124
+ ),
125
+ isComplete && /* @__PURE__ */ jsx(
126
+ Image,
127
+ {
128
+ src,
129
+ alt,
130
+ fill: true,
131
+ priority,
132
+ quality,
133
+ placeholder,
134
+ blurDataURL,
135
+ className: "opacity-100 transition-opacity duration-150 ease-out z-[1]",
136
+ style: {
137
+ objectFit
138
+ }
139
+ }
140
+ )
141
+ ]
142
+ }
143
+ );
144
+ }
145
+ export {
146
+ PixelLoad
147
+ };
148
+ //# sourceMappingURL=PixelLoad.mjs.map