visionary-image 1.0.2 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,18 +2,25 @@
2
2
 
3
3
  React image component with built-in Blurhash placeholders for better UX and Core Web Vitals.
4
4
 
5
- ![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/visionary-ux/visionary-image/.github%2Fworkflows%2Fci-cd-workflow.yml?branch=master&style=flat-square) ![npm package size (minzipped, via Bundlephobia)](https://img.shields.io/bundlephobia/minzip/visionary-image?style=flat-square&color=blue)
5
+ ![GitHub Release](https://img.shields.io/github/v/release/visionary-ux/visionary-image?color=beige) [![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/visionary-ux/visionary-image/.github%2Fworkflows%2Fci-cd-workflow.yml?branch=master)](https://github.com/visionary-ux/visionary-image/actions/workflows/ci-cd-workflow.yml?query=branch%3Amaster) [![npm package size (minzipped, via Bundlephobia)](https://img.shields.io/bundlephobia/minzip/visionary-image?color=blue)](https://bundlephobia.com/package/visionary-image) ![NPM Downloads](https://img.shields.io/npm/d18m/visionary-image?color=lightgray) [![Storybook demo](https://img.shields.io/badge/-Storybook-FF4785?logo=storybook&logoColor=white)](https://visionary-ux.github.io/visionary-image/)
6
6
 
7
- **Features:**
7
+ ## Features
8
8
 
9
- - Blurhash data encoded in the image URL via [visionary-url](https://github.com/visionary-ux/visionary-url) for instant image placeholders
10
- - Renders a true-to-size, responsive Blurhash placeholder while the image loads, eliminating Cumulative Layout Shift (CLS)
11
- - Images below the fold are lazily loaded, reducing initial page load size and request count, optimizing Interaction to Next Paint (INP)
12
- - Framework-tested (Remix, Next.js, Vite) with support for both client and server-side rendering (SSR, SSG) environments
13
- - Additional features: Prevent dragging, user-selection of image
14
- - Improves Core Web Vitals scores which Google notes as an important ranking signal in Search.
9
+ - **Easy Blurhash:** Get started with Blurhash in 60 seconds.
10
+ - **Layout stability**: Eliminates Cumulative Layout Shift (CLS) with true-to-size, responsive placeholders.
11
+ - **Automatic lazy loading**: Off-screen images are deferred, reducing initial pageload size and optimizing Interaction to Next Paint (INP).
12
+ - **Lighning-fast previews**: Renders placeholders early (by initial DOM layout) using URL-embedded Blurhash data, powered by [`visionary-url`](https://github.com/visionary-ux/visionary-url).
13
+ - **Framework tested**: Compatible with Remix, Next.js, and Vite and supports both client and server-side rendering (SSR, SSG).
14
+ - **Additional features**: Prevent image dragging; prevent user selecting image
15
+ - **Developer friendly**: Written in Typescript and [unit tested](./src/components/Image/__test__/).
16
+ - Check out the [interactive Storybook sandbox](https://visionary-ux.github.io/visionary-image/)
17
+ - **Search performance**: Enhance search ranking potential by improving Core Web Vitals scores.
18
+ > "We highly recommend site owners achieve good Core Web Vitals for success with Search" — [Google Search Central](https://developers.google.com/search/docs/appearance/core-web-vitals)
15
19
 
16
- > "We highly recommend site owners achieve good Core Web Vitals for success with Search", [Google Search Central](https://developers.google.com/search/docs/appearance/core-web-vitals)
20
+ ### Lighthouse Performance
21
+
22
+ Lighthouse report filmstrip showing three-layer image loading process
23
+ ![Lighthouse report loading stage filmstrip](https://github.com/user-attachments/assets/20fd15ad-6801-4105-b75d-bf12cc8c704e)
17
24
 
18
25
  ## Installation
19
26
 
@@ -25,7 +32,7 @@ npm install --save visionary-image
25
32
 
26
33
  ## Usage
27
34
 
28
- Create a Visionary image URL to get started.
35
+ Begin by creating a Visionary image URL. This is then passed to the `src` prop of the Image component.
29
36
 
30
37
  ### Creating a Visionary Image URL
31
38
 
@@ -40,14 +47,7 @@ There are several ways to create a Visionary URL.
40
47
  ```tsx
41
48
  import { Image } from "visionary-image";
42
49
 
43
- const imageUrl = "<visionary url or code>";
44
- const altText = "Nighttime stroll in Tokyo, neon-lit with a purple glow";
45
-
46
- const App = () => {
47
- <div>
48
- <Image alt={altText} src={imageUrl} />
49
- </div>;
50
- };
50
+ const ImageDetails = () => <Image alt="..." src="<Visionary URL>" />;
51
51
  ```
52
52
 
53
53
  ## Component Props
@@ -60,8 +60,9 @@ const App = () => {
60
60
  | `debug` <br/> boolean | Prints handy debug info to the console (Visionary URL data, render times). |
61
61
  | `disableBlurLayer` <br/> boolean | Disables rendering of the blur (canvas) layer. |
62
62
  | `disableImageLayer` <br/> boolean | Disables rendering of the image layer. |
63
+ | `height` <br/>number, string | If set, will override internally computed image height. By default, Visionary renders optimally sized images, using the aspect-ratio and max-width placeholder data. |
63
64
  | `hideImageLayer` <br/> boolean | Hides the image layer, revealing the blur layer underneath. |
64
- | `lazy` <br/> boolean | Should image lazily load. <br/> Default: `true` |
65
+ | `lazy` <br/> boolean | Should image load lazily. <br/> Default: `true` |
65
66
  | `onClick` <br/> function | Callback function to invoke when the image is clicked. function. |
66
67
  | `onError` <br/> function | Error callback function. |
67
68
  | `onLoad` <br/> function | Image loaded callback function. |
@@ -69,9 +70,18 @@ const App = () => {
69
70
  | `preventSelection` <br/>boolean | Prevents user from highlighting the image element. |
70
71
  | `punch` <br/>number | Blurhash punch parameter.<br /> Default: `1` |
71
72
  | `src` <br/>string | Visionary URL, Visionary Code, or ordinary image URL.<br/> If `src` contains Visionary data, placeholders will be rendered, otherwise falls back to an `img` element. <br/> **required** |
73
+ | `width` <br/>number, string | If set, will override internally computed image width. By default, Visionary renders optimally sized images, using the aspect-ratio and max-width placeholder data. |
74
+
75
+ ## Relevant Questions
76
+
77
+ ### Do image placeholders render server-side?
78
+
79
+ Yes, Visionary Image supports server-side rendering (SSR) and static site generation (SSG), as well as client-side rendering. In server-rendered scenarios, the first layer (background color) renders immediately, followed by the Blurhash and image layers once the page loads in the client's browser.
80
+
81
+ ### How long does the Blurhash canvas take to load?
82
+
83
+ Canvas operations are highly efficient in modern browsers. Rendering the 24x24 pixel Blurhash placeholder typically takes around 1ms.
72
84
 
73
- ### More Props
85
+ ### What is Blurhash and where can I learn more?
74
86
 
75
- | | |
76
- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
77
- | `height`, `width` | If set, will override internally computed image dimensions. By default, Visionary renders optimally sized images, using the aspect-ratio and max-width placeholder data. |
87
+ Blurhash uses Discrete Cosine Transforms to represent a color-accurate image placeholder as a compact string (in 20-30 characters). Check out the official [Blurhash docs](https://github.com/woltapp/blurhash) for more info.
@@ -1,10 +1,10 @@
1
1
  (function(){"use strict";try{if(typeof document<"u"){var e=document.createElement("style");e.id="v7y-styles",e.appendChild(document.createTextNode('.v7y_7587:before{content:"";display:block;padding-top:var(--v-ar)}.v7y_b8c0{-webkit-user-drag:none;pointer-events:none}.v7y_e0dd{-webkit-user-select:none;user-select:none}')),document.head.appendChild(e)}}catch(n){console.error("vite-plugin-css-injected-by-js",n)}})();
2
- import { jsx as G, jsxs as vt } from "react/jsx-runtime";
3
- import { useRef as Y, useCallback as q, useState as wt, useEffect as It, useLayoutEffect as Et, useMemo as At } from "react";
2
+ import { jsx as U, jsxs as yt } from "react/jsx-runtime";
3
+ import { useRef as Y, useCallback as q, useState as Rt, useEffect as At, useLayoutEffect as It, useMemo as Et } from "react";
4
4
  function xt(t) {
5
5
  return t && t.__esModule && Object.prototype.hasOwnProperty.call(t, "default") ? t.default : t;
6
6
  }
7
- var nt = { exports: {} };
7
+ var et = { exports: {} };
8
8
  /*!
9
9
  Copyright (c) 2018 Jed Watson.
10
10
  Licensed under the MIT License (MIT), see
@@ -39,43 +39,48 @@ var nt = { exports: {} };
39
39
  }
40
40
  t.exports ? (e.default = e, t.exports = e) : window.classNames = e;
41
41
  })();
42
- })(nt);
43
- var Rt = nt.exports;
44
- const St = /* @__PURE__ */ xt(Rt), Ut = (t, { root: n, rootMargin: e, threshold: o } = {}, i = []) => {
42
+ })(et);
43
+ var Tt = et.exports;
44
+ const Pt = /* @__PURE__ */ xt(Tt), Ot = (t, { root: n, rootMargin: e, threshold: o } = {}, i = []) => {
45
45
  const r = Y(null), s = Y(null);
46
46
  return q((c) => {
47
47
  r.current && s.current && (s.current.unobserve(r.current), s.current.disconnect(), s.current = null), c && (s.current = new IntersectionObserver(t, { root: n, rootMargin: e, threshold: o }), s.current.observe(c), r.current = c);
48
48
  }, [r, n, e, JSON.stringify(o), ...i]);
49
- }, Nt = ({ root: t, rootMargin: n, threshold: e, unobserveOnEnter: o, target: i, onEnter: r, onLeave: s, defaultInView: u } = {}, c = []) => {
50
- const [a, p] = wt({
49
+ }, Ut = ({ root: t, rootMargin: n, threshold: e, unobserveOnEnter: o, target: i, onEnter: r, onLeave: s, defaultInView: u } = {}, c = []) => {
50
+ const [a, p] = Rt({
51
51
  inView: u || !1,
52
52
  entry: null,
53
53
  observer: null
54
- }), l = q(([h], f) => {
55
- const b = f.thresholds.some((g) => h.intersectionRatio >= g) && h.isIntersecting;
54
+ }), l = q(([m], d) => {
55
+ const v = d.thresholds.some((b) => m.intersectionRatio >= b) && m.isIntersecting;
56
56
  p({
57
- inView: b,
58
- entry: h,
59
- observer: f
60
- }), b && o && (f.unobserve(h.target), f.disconnect()), b ? r == null || r(h, f) : s == null || s(h, f);
61
- }, [r, s, o]), m = Ut(l, { root: t, rootMargin: n, threshold: e }, [o, ...c]);
62
- return It(() => {
63
- i != null && i.current && m(i.current);
64
- }, [i, m]), [m, a.inView, a.entry, a.observer];
57
+ inView: v,
58
+ entry: m,
59
+ observer: d
60
+ }), v && o && (d.unobserve(m.target), d.disconnect()), v ? r == null || r(m, d) : s == null || s(m, d);
61
+ }, [r, s, o]), g = Ot(l, { root: t, rootMargin: n, threshold: e }, [o, ...c]);
62
+ return At(() => {
63
+ i != null && i.current && g(i.current);
64
+ }, [i, g]), [g, a.inView, a.entry, a.observer];
65
+ }, V = {
66
+ ASPECT_RATIO_WRAPPER: "aspect-ratio-wrapper",
67
+ CANVAS: "canvas",
68
+ CONTAINER: "container",
69
+ IMAGE: "image"
65
70
  };
66
- var V = /* @__PURE__ */ ((t) => (t.AUTO = "auto", t.AVIF = "avif", t.JPEG = "jpeg", t.WEBP = "webp", t))(V || {}), v = /* @__PURE__ */ ((t) => (t.xs = "xs", t.sm = "sm", t.md = "md", t.lg = "lg", t.xl = "xl", t.xxl = "xxl", t["4k"] = "4k", t["5k"] = "5k", t.full = "full", t))(v || {}), T = /* @__PURE__ */ ((t) => (t.DEBUG = "debug", t.DOWNLOAD = "download", t))(T || {});
67
- const Ot = "https://link.visionary.cloud";
68
- V.AUTO, v.lg;
71
+ var W = /* @__PURE__ */ ((t) => (t.AUTO = "auto", t.AVIF = "avif", t.JPEG = "jpeg", t.WEBP = "webp", t))(W || {}), y = /* @__PURE__ */ ((t) => (t.xs = "xs", t.sm = "sm", t.md = "md", t.lg = "lg", t.xl = "xl", t.xxl = "xxl", t["4k"] = "4k", t["5k"] = "5k", t.full = "full", t))(y || {}), N = /* @__PURE__ */ ((t) => (t.DEBUG = "debug", t.DOWNLOAD = "download", t))(N || {});
72
+ const Ct = "https://link.visionary.cloud";
73
+ W.AUTO, y.lg;
69
74
  const Z = {
70
- [v.xs]: 160,
71
- [v.sm]: 320,
72
- [v.md]: 640,
73
- [v.lg]: 1280,
74
- [v.xl]: 1920,
75
- [v.xxl]: 2560,
76
- [v["4k"]]: 3840,
77
- [v["5k"]]: 5120,
78
- [v.full]: 0
75
+ [y.xs]: 160,
76
+ [y.sm]: 320,
77
+ [y.md]: 640,
78
+ [y.lg]: 1280,
79
+ [y.xl]: 1920,
80
+ [y.xxl]: 2560,
81
+ [y["4k"]]: 3840,
82
+ [y["5k"]]: 5120,
83
+ [y.full]: 0
79
84
  };
80
85
  Object.keys(Z).reduce(
81
86
  (t, n) => {
@@ -84,118 +89,118 @@ Object.keys(Z).reduce(
84
89
  },
85
90
  {}
86
91
  );
87
- const et = "!";
88
- var Tt = Object.defineProperty, Ct = (t, n, e) => n in t ? Tt(t, n, { enumerable: !0, configurable: !0, writable: !0, value: e }) : t[n] = e, Dt = (t, n, e) => Ct(t, typeof n != "symbol" ? n + "" : n, e), J = {}, $ = {};
89
- Object.defineProperty($, "__esModule", { value: !0 });
90
- function Pt(t) {
92
+ const rt = "!";
93
+ var Nt = Object.defineProperty, _t = (t, n, e) => n in t ? Nt(t, n, { enumerable: !0, configurable: !0, writable: !0, value: e }) : t[n] = e, Dt = (t, n, e) => _t(t, typeof n != "symbol" ? n + "" : n, e), J = {}, z = {};
94
+ Object.defineProperty(z, "__esModule", { value: !0 });
95
+ function Lt(t) {
91
96
  return String.fromCharCode(parseInt(t.slice(1), 16));
92
97
  }
93
- function _t(t) {
94
- return btoa(encodeURIComponent(t).replace(/%[0-9A-F]{2}/g, Pt));
98
+ function St(t) {
99
+ return btoa(encodeURIComponent(t).replace(/%[0-9A-F]{2}/g, Lt));
95
100
  }
96
- $.encode = _t;
97
- function Lt(t) {
101
+ z.encode = St;
102
+ function Vt(t) {
98
103
  return `%${`00${t.charCodeAt(0).toString(16)}`.slice(-2)}`;
99
104
  }
100
- function Vt(t) {
101
- return decodeURIComponent(Array.from(atob(t), Lt).join(""));
105
+ function $t(t) {
106
+ return decodeURIComponent(Array.from(atob(t), Vt).join(""));
102
107
  }
103
- $.decode = Vt;
108
+ z.decode = $t;
104
109
  Object.defineProperty(J, "__esModule", { value: !0 });
105
- const rt = $;
106
- function $t(t) {
107
- return rt.decode(t.replace(/\-/g, "+").replace(/_/g, "/"));
110
+ const ot = z;
111
+ function jt(t) {
112
+ return ot.decode(t.replace(/\-/g, "+").replace(/_/g, "/"));
108
113
  }
109
- var jt = J.decode = $t;
110
- function kt(t) {
111
- return rt.encode(t).replace(/\//g, "_").replace(/\+/g, "-").replace(/=+$/, "");
114
+ var kt = J.decode = jt;
115
+ function Wt(t) {
116
+ return ot.encode(t).replace(/\//g, "_").replace(/\+/g, "-").replace(/=+$/, "");
112
117
  }
113
- var zt = J.encode = kt;
114
- const Bt = (t) => t.filter(Boolean), K = (t) => {
118
+ var zt = J.encode = Wt;
119
+ const Bt = (t) => t.filter(Boolean), Q = (t) => {
115
120
  try {
116
121
  return new URL(t);
117
122
  } catch {
118
123
  return null;
119
124
  }
120
- }, j = (t = "") => /^[A-Za-z0-9_-]*$/.test(t), Mt = (t) => {
125
+ }, B = (t = "") => /^[A-Za-z0-9_-]*$/.test(t), Mt = (t) => {
121
126
  const { altText: n, bcc: e, blurhash: o, blurhashX: i, blurhashY: r, sourceHeight: s, sourceWidth: u, url: c } = t;
122
127
  if (!c || !u || !s)
123
128
  return new Error("Cannot construct visionary code: missing required url/width/height");
124
129
  const a = [c, u, s];
125
130
  return !e || (a.push(e), !o || !i || !r) || (a.push(o, i, r), n && n.length && a.push(n)), Gt(a);
126
- }, Gt = (t) => zt(t.join(et)), ot = (t) => {
131
+ }, Gt = (t) => zt(t.join(rt)), st = (t) => {
127
132
  if (typeof t != "string")
128
133
  return null;
129
134
  const n = t.trim();
130
- if (!n.length || !j(n))
135
+ if (!n.length || !B(n))
131
136
  return null;
132
- const e = jt(n);
137
+ const e = kt(n);
133
138
  if (!e)
134
139
  return null;
135
- const o = e.split(et);
140
+ const o = e.split(rt);
136
141
  if (o.length < 3)
137
142
  return null;
138
- const [i, r, s, u, c, a, p, l] = o, m = i.trim();
139
- if (!m.length)
143
+ const [i, r, s, u, c, a, p, l] = o, g = i.trim();
144
+ if (!g.length)
140
145
  return console.error("Cannot parse code, empty file id"), null;
141
- const h = Number(r.trim()), f = Number(s.trim());
142
- if (isNaN(h) || isNaN(f) || !h || !f)
146
+ const m = Number(r.trim()), d = Number(s.trim());
147
+ if (isNaN(m) || isNaN(d) || !m || !d)
143
148
  return console.error("Cannot parse Visionary Code: invalid image dimensions", r, s), null;
144
- const y = Number(a) ?? 0, b = Number(p) ?? 0;
145
- return y < 1 || b < 1 ? (console.error(
149
+ const w = Number(a) ?? 0, v = Number(p) ?? 0;
150
+ return w < 1 || v < 1 ? (console.error(
146
151
  "Cannot parse Visionary Code: invalid blurhash x, y component dimensions",
147
- y,
148
- b
152
+ w,
153
+ v
149
154
  ), null) : {
150
155
  altText: l,
151
156
  bcc: u,
152
157
  blurhash: c,
153
- blurhashX: y,
154
- blurhashY: b,
155
- sourceHeight: f,
156
- sourceWidth: h,
157
- url: m
158
+ blurhashX: w,
159
+ blurhashY: v,
160
+ sourceHeight: d,
161
+ sourceWidth: m,
162
+ url: g
158
163
  };
159
164
  };
160
- class Wt extends Error {
165
+ class Ft extends Error {
161
166
  constructor() {
162
167
  super(...arguments), Dt(this, "message", "invalid endpoint URL (does it contain http/https?)");
163
168
  }
164
169
  }
165
- const Ft = (t) => t === T.DEBUG, Ht = (t) => t === T.DOWNLOAD, Xt = (t) => Object.values(V).includes(t), st = (t) => Object.values(v).includes(t), Yt = (t = []) => {
170
+ const Ht = (t) => t === N.DEBUG, Xt = (t) => t === N.DOWNLOAD, Yt = (t) => Object.values(W).includes(t), ct = (t) => Object.values(y).includes(t), Zt = (t = []) => {
166
171
  const n = {};
167
172
  for (const e of t)
168
- st(e) ? n.size = v[e] : Ft(e) ? n.debug = !0 : Ht(e) ? n.download = !0 : Xt(e) && (n.format = e);
173
+ ct(e) ? n.size = y[e] : Ht(e) ? n.debug = !0 : Xt(e) ? n.download = !0 : Yt(e) && (n.format = e);
169
174
  return n;
170
- }, Zt = (t) => {
175
+ }, qt = (t) => {
171
176
  if (!t || typeof t != "object")
172
177
  return null;
173
178
  const n = [];
174
- return t.debug && n.push(T.DEBUG), t.download && n.push(T.DOWNLOAD), t.format && t.format !== V.AUTO && n.push(t.format), t.size && st(t.size) && n.push(t.size), n.length ? n.sort().join(",") : null;
175
- }, qt = (t) => {
176
- if (j(t)) {
177
- const n = ot(t);
179
+ return t.debug && n.push(N.DEBUG), t.download && n.push(N.DOWNLOAD), t.format && t.format !== W.AUTO && n.push(t.format), t.size && ct(t.size) && n.push(t.size), n.length ? n.sort().join(",") : null;
180
+ }, Jt = (t) => {
181
+ if (B(t)) {
182
+ const n = st(t);
178
183
  if (n)
179
184
  return {
180
185
  fields: n,
181
186
  options: {}
182
187
  };
183
188
  }
184
- return Jt(t);
185
- }, Jt = (t) => {
189
+ return Kt(t);
190
+ }, Kt = (t) => {
186
191
  if (!t)
187
192
  return null;
188
193
  const n = t.trim();
189
194
  if (!n)
190
195
  return null;
191
196
  try {
192
- const e = Qt(n);
197
+ const e = tn(n);
193
198
  if (!e)
194
199
  return null;
195
- const { code: o, optionTokens: i } = e, r = ot(o);
200
+ const { code: o, optionTokens: i } = e, r = st(o);
196
201
  if (!r)
197
202
  return null;
198
- const s = Yt(i);
203
+ const s = Zt(i);
199
204
  return {
200
205
  fields: r,
201
206
  options: s
@@ -204,25 +209,25 @@ const Ft = (t) => t === T.DEBUG, Ht = (t) => t === T.DOWNLOAD, Xt = (t) => Objec
204
209
  e instanceof Error ? console.error(`Error parsing URL: ${e.message}`, e) : console.error("uncaught error", e);
205
210
  }
206
211
  return null;
207
- }, Kt = (t, n) => {
212
+ }, Qt = (t, n) => {
208
213
  const e = Mt(t);
209
214
  if (e instanceof Error)
210
215
  return null;
211
216
  let o = null;
212
- if (n != null && n.endpoint && (o = K(n == null ? void 0 : n.endpoint), !o))
213
- throw new Wt(
217
+ if (n != null && n.endpoint && (o = Q(n == null ? void 0 : n.endpoint), !o))
218
+ throw new Ft(
214
219
  "Cannot construct URL: bad endpoint. Ensure endpoint starts with http:// or https://"
215
220
  );
216
- o || (o = K(Ot));
217
- const i = [o.origin, "image", e], r = n ? Zt(n) : null;
221
+ o || (o = Q(Ct));
222
+ const i = [o.origin, "image", e], r = n ? qt(n) : null;
218
223
  return r && i.push(r), n != null && n.filename ? i.push(n.filename) : i.push("image.jpg"), i.join("/");
219
- }, Qt = (t) => {
224
+ }, tn = (t) => {
220
225
  try {
221
226
  const n = new URL(t), e = Bt(n.pathname.split("/"));
222
227
  if (e[0] !== "image" || ![3, 4].includes(e.length))
223
228
  throw new Error("Unrecognized URL");
224
229
  const o = e[1].trim();
225
- if (!o.length || !j(o))
230
+ if (!o.length || !B(o))
226
231
  throw new Error("URL is not formatted as base64url");
227
232
  if (e.length === 4) {
228
233
  const i = e[2].split(",");
@@ -240,152 +245,150 @@ const Ft = (t) => t === T.DEBUG, Ht = (t) => t === T.DOWNLOAD, Xt = (t) => Objec
240
245
  return null;
241
246
  }
242
247
  return null;
243
- }, ct = 0.7, it = 1, S = 24, tn = v.lg, at = process.env.NODE_ENV, nn = at === "development", lt = typeof document > "u", en = at === "test", rn = lt ? () => {
244
- } : Et, on = "<visionary>", R = (t, ...n) => {
245
- !console || typeof console.log != "function" || console.log(`${on} ${t}`, ...n);
246
- }, ut = new Uint8Array(128);
248
+ }, it = 0.7, at = 1, T = 24, nn = y.lg, lt = process.env.NODE_ENV, en = lt === "development", ut = typeof document > "u", rn = lt === "test", k = (t) => {
249
+ try {
250
+ return new URL(t);
251
+ } catch {
252
+ return null;
253
+ }
254
+ }, on = (t, n) => `rgba(${t.r},${t.g},${t.b},${n})`, $ = (t) => en || rn ? {
255
+ "data-testid": t
256
+ } : {}, sn = (t, n) => n ? {
257
+ "data-fileid": t
258
+ } : {}, tt = (t, n) => Math.min(t, n), cn = (t) => {
259
+ let n = t.replace(/^#/, "");
260
+ if (n.length !== 3 && n.length !== 6)
261
+ return null;
262
+ n.length === 3 && (n = `${n[0]}${n[0]}${n[1]}${n[1]}${n[2]}${n[2]}`);
263
+ const e = parseInt(n.slice(0, 2), 16), o = parseInt(n.slice(2, 4), 16);
264
+ return { b: parseInt(n.slice(4, 6), 16), g: o, r: e };
265
+ }, E = (t, n = 0) => {
266
+ const e = Math.pow(10, n);
267
+ return Math.round(t * e) / e;
268
+ }, an = (t, n) => {
269
+ const e = k(t), o = k(n);
270
+ return !e || !o ? t : (o.pathname = e.pathname, o.search = e.search, o.toString());
271
+ }, ln = {
272
+ overflow: "hidden"
273
+ }, un = ({ aspectRatio: t, children: n }) => /* @__PURE__ */ U("div", { style: { aspectRatio: t, ...ln }, ...$(V.ASPECT_RATIO_WRAPPER), children: n }), dn = ut ? () => {
274
+ } : It, fn = "<visionary>", x = (t, ...n) => {
275
+ !console || typeof console.log != "function" || console.log(`${fn} ${t}`, ...n);
276
+ }, dt = new Uint8Array(128);
247
277
  for (let t = 0; t < 83; t++)
248
- ut["0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz#$%*+,-.:;=?@[]^_{|}~".charCodeAt(
278
+ dt["0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz#$%*+,-.:;=?@[]^_{|}~".charCodeAt(
249
279
  t
250
280
  )] = t;
251
- const _ = (t, n, e) => {
281
+ const j = (t, n, e) => {
252
282
  let o = 0;
253
283
  for (; n < e; )
254
- o *= 83, o += ut[t.charCodeAt(n++)];
284
+ o *= 83, o += dt[t.charCodeAt(n++)];
255
285
  return o;
256
- }, ft = Math.pow, C = Math.PI, sn = C * 2, dt = 3294.6, pt = 269.025, cn = (t) => t > 10.31475 ? ft(t / pt + 0.052132, 2.4) : t / dt, W = (t) => ~~(t > 1227e-8 ? pt * ft(t, 0.416666) - 13.025 : t * dt + 1), O = (t) => (t < 0 ? -1 : 1) * t * t, Q = (t) => {
257
- for (t += C / 2; t > C; )
258
- t -= sn;
259
- const n = 1.27323954 * t - 0.405284735 * O(t);
260
- return 0.225 * (O(n) - n) + n;
286
+ }, ft = Math.pow, _ = Math.PI, pn = _ * 2, pt = 3294.6, ht = 269.025, hn = (t) => t > 10.31475 ? ft(t / ht + 0.052132, 2.4) : t / pt, H = (t) => ~~(t > 1227e-8 ? ht * ft(t, 0.416666) - 13.025 : t * pt + 1), C = (t) => (t < 0 ? -1 : 1) * t * t, nt = (t) => {
287
+ for (t += _ / 2; t > _; )
288
+ t -= pn;
289
+ const n = 1.27323954 * t - 0.405284735 * C(t);
290
+ return 0.225 * (C(n) - n) + n;
261
291
  };
262
- function an(t) {
263
- const n = _(t, 2, 6);
292
+ function mn(t) {
293
+ const n = j(t, 2, 6);
264
294
  return [n >> 16, n >> 8 & 255, n & 255];
265
295
  }
266
- function ln(t, n, e, o) {
267
- const i = _(t, 0, 1), r = i % 9 + 1, s = ~~(i / 9) + 1, u = r * s;
268
- let c = 0, a = 0, p = 0, l = 0, m = 0, h = 0, f = 0, y = 0, b = 0, g = 0, w = 0, E = 0;
269
- const d = (_(t, 1, 2) + 1) / 13446 * (o | 1), I = new Float64Array(u * 3), k = an(t);
296
+ function gn(t, n, e, o) {
297
+ const i = j(t, 0, 1), r = i % 9 + 1, s = ~~(i / 9) + 1, u = r * s;
298
+ let c = 0, a = 0, p = 0, l = 0, g = 0, m = 0, d = 0, w = 0, v = 0, b = 0, h = 0, A = 0;
299
+ const f = (j(t, 1, 2) + 1) / 13446 * (o | 1), R = new Float64Array(u * 3), M = mn(t);
270
300
  for (c = 0; c < 3; c++)
271
- I[c] = cn(k[c]);
301
+ R[c] = hn(M[c]);
272
302
  for (c = 1; c < u; c++)
273
- E = _(t, 4 + c * 2, 6 + c * 2), I[c * 3] = O(~~(E / 361) - 9) * d, I[c * 3 + 1] = O(~~(E / 19) % 19 - 9) * d, I[c * 3 + 2] = O(E % 19 - 9) * d;
274
- const D = new Float64Array(s * e), P = new Float64Array(r * n);
303
+ A = j(t, 4 + c * 2, 6 + c * 2), R[c * 3] = C(~~(A / 361) - 9) * f, R[c * 3 + 1] = C(~~(A / 19) % 19 - 9) * f, R[c * 3 + 2] = C(A % 19 - 9) * f;
304
+ const D = new Float64Array(s * e), L = new Float64Array(r * n);
275
305
  for (a = 0; a < s; a++)
276
306
  for (l = 0; l < e; l++)
277
- D[a * e + l] = Q(C * l * a / e);
307
+ D[a * e + l] = nt(_ * l * a / e);
278
308
  for (c = 0; c < r; c++)
279
309
  for (p = 0; p < n; p++)
280
- P[c * n + p] = Q(C * p * c / n);
281
- const U = n * 4, A = new Uint8ClampedArray(U * e);
310
+ L[c * n + p] = nt(_ * p * c / n);
311
+ const P = n * 4, I = new Uint8ClampedArray(P * e);
282
312
  for (l = 0; l < e; l++)
283
313
  for (p = 0; p < n; p++) {
284
- for (m = h = f = 0, a = 0; a < s; a++)
285
- for (b = D[a * e + l], c = 0; c < r; c++)
286
- y = P[c * n + p] * b, g = (c + a * r) * 3, m += I[g] * y, h += I[g + 1] * y, f += I[g + 2] * y;
287
- w = 4 * p + l * U, A[w] = W(m), A[w + 1] = W(h), A[w + 2] = W(f), A[w + 3] = 255;
314
+ for (g = m = d = 0, a = 0; a < s; a++)
315
+ for (v = D[a * e + l], c = 0; c < r; c++)
316
+ w = L[c * n + p] * v, b = (c + a * r) * 3, g += R[b] * w, m += R[b + 1] * w, d += R[b + 2] * w;
317
+ h = 4 * p + l * P, I[h] = H(g), I[h + 1] = H(m), I[h + 2] = H(d), I[h + 3] = 255;
288
318
  }
289
- return A;
319
+ return I;
290
320
  }
291
- const L = (t) => {
292
- try {
293
- return new URL(t);
294
- } catch {
295
- return null;
296
- }
297
- }, un = (t, n) => `rgba(${t.r},${t.g},${t.b},${n})`, F = (t) => nn || en ? {
298
- "data-testid": t
299
- } : {}, fn = (t, n) => n ? {
300
- "data-fileid": t
301
- } : {}, tt = (t, n) => Math.min(t, n), dn = (t) => {
302
- let n = t.replace(/^#/, "");
303
- if (n.length !== 3 && n.length !== 6)
304
- return null;
305
- n.length === 3 && (n = `${n[0]}${n[0]}${n[1]}${n[1]}${n[2]}${n[2]}`);
306
- const e = parseInt(n.slice(0, 2), 16), o = parseInt(n.slice(2, 4), 16);
307
- return { b: parseInt(n.slice(4, 6), 16), g: o, r: e };
308
- }, x = (t, n = 0) => {
309
- const e = Math.pow(10, n);
310
- return Math.round(t * e) / e;
311
- }, pn = (t, n) => {
312
- const e = L(t), o = L(n);
313
- return !e || !o ? t : (o.pathname = e.pathname, o.search = e.search, o.toString());
314
- }, hn = (t, n = {}, e = ct, o = it) => {
321
+ const bn = (t, n = {}, e = it, o = at) => {
315
322
  if (!t)
316
323
  return null;
317
324
  try {
318
- n.debug && R("input imageSrc:", t);
319
- const i = qt(t);
320
- if (n.debug && R("Visionary URL data: ", i), !i)
325
+ n.debug && x("input imageSrc:", t);
326
+ const i = Jt(t);
327
+ if (n.debug && x("Visionary URL data: ", i), !i)
321
328
  throw new Error("Could not parse Visionary URL");
322
329
  const { fields: r, options: s } = i;
323
330
  if (r.sourceWidth < 1 || r.sourceHeight < 1)
324
331
  throw new Error("Invalid image dimensions");
325
- const u = r.sourceWidth / r.sourceHeight, c = (n == null ? void 0 : n.size) ?? s.size ?? tn, a = Z[c];
326
- let p = 0, l = 0, m = 0;
332
+ const u = r.sourceWidth / r.sourceHeight, c = (n == null ? void 0 : n.size) ?? s.size ?? nn, a = Z[c];
333
+ let p = 0, l = 0, g = 0;
327
334
  if (u >= 1) {
328
335
  l = p = tt(a, r.sourceWidth);
329
- const g = x(l / u);
330
- m = x(l / g, 6);
336
+ const b = E(l / u);
337
+ g = E(l / b, 6);
331
338
  } else
332
- p = tt(a, r.sourceHeight), l = x(p * u), m = x(l / p, 6);
333
- const h = x(100 / m, 6), f = {
339
+ p = tt(a, r.sourceHeight), l = E(p * u), g = E(l / p, 6);
340
+ const m = E(100 / g, 6), d = {
334
341
  ...r,
335
- arPaddingTop: `${h}%`,
336
- aspectRatio: m,
342
+ arPaddingTop: `${m}%`,
343
+ aspectRatio: g,
337
344
  maxWidth: l,
338
345
  src: t
339
- }, y = L(r.url);
340
- if (y)
341
- f.src = y.toString();
342
- else if (!L(t) && j(r.url)) {
343
- const g = Kt(r, {
346
+ }, w = k(r.url);
347
+ if (w)
348
+ d.src = w.toString();
349
+ else if (!k(t) && B(r.url)) {
350
+ const b = Qt(r, {
344
351
  endpoint: n.endpoint,
345
352
  size: c
346
353
  });
347
- g && (f.src = g);
354
+ b && (d.src = b);
348
355
  }
349
- n.endpoint && (f.src = pn(f.src, n.endpoint));
350
- const b = r.bcc ? dn(r.bcc) : null;
351
- if (b && (f.backgroundColor = un(b, e)), !lt && r.blurhash && !n.disableBlurLayer) {
352
- const g = performance.now(), w = ln(r.blurhash, S, S, o), E = performance.now() - g;
353
- n.debug && R(`Blurhash decode time: ${x(E, 1)} ms`), w && (f.pixels = w);
356
+ n.endpoint && (d.src = an(d.src, n.endpoint));
357
+ const v = r.bcc ? cn(r.bcc) : null;
358
+ if (v && (d.backgroundColor = on(v, e)), !ut && r.blurhash && !n.disableBlurLayer) {
359
+ const b = performance.now(), h = gn(r.blurhash, T, T, o), A = performance.now() - b;
360
+ n.debug && x(`Blurhash decode time: ${E(A, 1)} ms`), h && (d.pixels = h);
354
361
  }
355
- return n.debug && R("Visionary Image state: ", f), f;
362
+ return n.debug && x("Visionary Image state: ", d), d;
356
363
  } catch {
357
364
  return null;
358
365
  }
359
- }, ht = {
366
+ }, mt = {
360
367
  bottom: 0,
361
368
  left: 0,
362
369
  position: "absolute",
363
370
  right: 0,
364
371
  top: 0
365
- }, mn = {
366
- ...ht,
372
+ }, vn = {
373
+ ...mt,
367
374
  maxHeight: "100%",
368
375
  maxWidth: "100%"
369
- }, gn = {
370
- ...ht,
376
+ }, wn = {
377
+ ...mt,
371
378
  height: "100%",
372
379
  width: "100%"
373
- }, bn = (t) => {
380
+ }, yn = (t) => {
374
381
  const n = {
375
- ...mn
382
+ ...vn
376
383
  };
377
384
  return t && (n.display = "none"), n;
378
- }, H = {
379
- CANVAS: "canvas",
380
- CONTAINER: "container",
381
- IMAGE: "image"
382
- }, yn = "v7y_7587", vn = "v7y_b8c0", wn = "v7y_e0dd", X = {
383
- container: yn,
384
- preventDrag: vn,
385
- preventSelection: wn
386
- }, Rn = ({
385
+ }, Rn = "v7y_7587", An = "v7y_b8c0", In = "v7y_e0dd", X = {
386
+ container: Rn,
387
+ preventDrag: An,
388
+ preventSelection: In
389
+ }, On = ({
387
390
  alt: t,
388
- bgColorAlpha: n = ct,
391
+ bgColorAlpha: n = it,
389
392
  className: e,
390
393
  debug: o = !1,
391
394
  disableBlurLayer: i = !1,
@@ -396,123 +399,123 @@ const L = (t) => {
396
399
  lazy: a = !0,
397
400
  onClick: p,
398
401
  onError: l,
399
- onLoad: m,
400
- preventDrag: h = !1,
401
- preventSelection: f = !1,
402
- punch: y = it,
403
- size: b,
404
- src: g,
405
- style: w,
406
- width: E
402
+ onLoad: g,
403
+ preventDrag: m = !1,
404
+ preventSelection: d = !1,
405
+ punch: w = at,
406
+ size: v,
407
+ src: b,
408
+ style: h,
409
+ width: A
407
410
  }) => {
408
- const d = At(() => hn(g, {
411
+ const f = Et(() => bn(b, {
409
412
  debug: o,
410
413
  disableBlurLayer: i,
411
414
  endpoint: s,
412
- size: b
413
- }, n, y), [n, o, i, s, y, b, g]), I = Y(null), [k, D] = Nt();
414
- rn(
415
+ size: v
416
+ }, n, w), [n, o, i, s, w, v, b]), R = Y(null), [M, D] = Ut();
417
+ dn(
415
418
  function() {
416
- if (!I.current || !(d != null && d.blurhash))
419
+ if (!R.current || !(f != null && f.blurhash))
417
420
  return;
418
- if (!d.pixels) {
421
+ if (!f.pixels) {
419
422
  console.warn("No pixel data passed in, skipping");
420
423
  return;
421
424
  }
422
- const bt = performance.now(), B = I.current.getContext("2d");
423
- if (!B) {
425
+ const vt = performance.now(), G = R.current.getContext("2d");
426
+ if (!G) {
424
427
  console.warn("Cannot access canvasRenderingContext, skipping");
425
428
  return;
426
429
  }
427
- const M = B.createImageData(S, S);
428
- if (!M) {
430
+ const F = G.createImageData(T, T);
431
+ if (!F) {
429
432
  console.warn("Could not create ImageData on CanvasRenderingContext");
430
433
  return;
431
434
  }
432
- if (M.data.set(d.pixels), B.putImageData(M, 0, 0), o) {
433
- const yt = performance.now() - bt;
434
- R(`Canvas render time: ${x(yt, 1)} ms`);
435
+ if (F.data.set(f.pixels), G.putImageData(F, 0, 0), o) {
436
+ const wt = performance.now() - vt;
437
+ x(`Canvas render time: ${E(wt, 1)} ms`);
435
438
  }
436
439
  },
437
- [d == null ? void 0 : d.blurhash, d == null ? void 0 : d.pixels, o]
440
+ [f == null ? void 0 : f.blurhash, f == null ? void 0 : f.pixels, o]
438
441
  );
439
- const P = q(
440
- (N) => {
441
- o && R("Image load error ", N), l && l();
442
+ const L = q(
443
+ (O) => {
444
+ o && x("Image load error ", O), l && l();
442
445
  },
443
446
  [o, l]
444
- ), U = {
447
+ ), P = {
445
448
  alt: t,
446
449
  loading: !a || D ? "eager" : "lazy",
447
- onLoad: m
450
+ onLoad: g
448
451
  };
449
- if (!d) {
450
- o && R("Not a Visionary URL, rendering fallback <img />");
451
- const N = {
452
- ...U,
452
+ if (!f) {
453
+ o && x("Not a Visionary URL, rendering fallback <img />");
454
+ const O = {
455
+ ...P,
453
456
  className: e,
454
457
  height: u,
455
458
  onClick: p,
456
459
  onError: l,
457
- src: g,
458
- style: w,
459
- width: E
460
+ src: b,
461
+ style: h,
462
+ width: A
460
463
  };
461
- return /* @__PURE__ */ G("img", { ...N });
464
+ return /* @__PURE__ */ U("img", { ...O });
462
465
  }
463
- const A = St(X.container, e, {
464
- [X.preventDrag]: !!h,
465
- [X.preventSelection]: !!f
466
- }), z = {
466
+ const I = Pt(X.container, e, {
467
+ [X.preventDrag]: !!m,
468
+ [X.preventSelection]: !!d
469
+ }), S = {
467
470
  ...{
468
- "--v-ar": d.arPaddingTop
471
+ "--v-ar": f.arPaddingTop
469
472
  },
470
- aspectRatio: d.aspectRatio,
471
- backgroundColor: (d == null ? void 0 : d.backgroundColor) ?? void 0,
472
- maxWidth: d.maxWidth,
473
+ ...h,
474
+ aspectRatio: f.aspectRatio,
475
+ backgroundColor: (f == null ? void 0 : f.backgroundColor) ?? void 0,
476
+ maxWidth: f.maxWidth,
473
477
  position: "relative",
474
- width: "100%",
475
- ...w
478
+ width: "100%"
476
479
  };
477
- E && (z.width = E), u && (z.height = u);
478
- const mt = {
480
+ A && (S.width = A), u && (S.height = u), h != null && h.maxWidth && (S.maxWidth = h.maxWidth);
481
+ const gt = {
479
482
  onClick: p
480
- }, gt = bn(c);
481
- return /* @__PURE__ */ vt(
483
+ }, bt = yn(c), K = /* @__PURE__ */ yt(
482
484
  "div",
483
485
  {
484
- className: A,
485
- ref: k,
486
- style: z,
487
- ...fn(d.url, o),
488
- ...F(H.CONTAINER),
489
- ...mt,
486
+ className: I,
487
+ ref: M,
488
+ style: S,
489
+ ...sn(f.url, o),
490
+ ...$(V.CONTAINER),
491
+ ...gt,
490
492
  children: [
491
- !i && /* @__PURE__ */ G(
493
+ !i && /* @__PURE__ */ U(
492
494
  "canvas",
493
495
  {
494
- height: S,
495
- ref: I,
496
- style: gn,
497
- width: S,
498
- ...F(H.CANVAS)
496
+ height: T,
497
+ ref: R,
498
+ style: wn,
499
+ width: T,
500
+ ...$(V.CANVAS)
499
501
  }
500
502
  ),
501
503
  !r && // eslint-disable-next-line jsx-a11y/alt-text -- `sharedImgProps` includes alt tag
502
- /* @__PURE__ */ G(
504
+ /* @__PURE__ */ U(
503
505
  "img",
504
506
  {
505
- ...U,
506
- ...F(H.IMAGE),
507
- onError: P,
508
- src: d.src,
509
- style: gt
507
+ ...P,
508
+ ...$(V.IMAGE),
509
+ onError: L,
510
+ src: f.src,
511
+ style: bt
510
512
  }
511
513
  )
512
514
  ]
513
515
  }
514
516
  );
517
+ return h != null && h.aspectRatio ? /* @__PURE__ */ U(un, { aspectRatio: h.aspectRatio, children: K }) : K;
515
518
  };
516
519
  export {
517
- Rn as Image
520
+ On as Image
518
521
  };
@@ -1,6 +1,6 @@
1
1
  (function(){"use strict";try{if(typeof document<"u"){var e=document.createElement("style");e.id="v7y-styles",e.appendChild(document.createTextNode('.v7y_7587:before{content:"";display:block;padding-top:var(--v-ar)}.v7y_b8c0{-webkit-user-drag:none;pointer-events:none}.v7y_e0dd{-webkit-user-select:none;user-select:none}')),document.head.appendChild(e)}}catch(n){console.error("vite-plugin-css-injected-by-js",n)}})();
2
- (function(A,R){typeof exports=="object"&&typeof module<"u"?R(exports,require("react/jsx-runtime"),require("react")):typeof define=="function"&&define.amd?define(["exports","react/jsx-runtime","react"],R):(A=typeof globalThis<"u"?globalThis:A||self,R(A.VisionaryImage={},A.jsxRuntime,A.React))})(this,function(A,R,x){"use strict";function me(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var K={exports:{}};/*!
2
+ (function(E,A){typeof exports=="object"&&typeof module<"u"?A(exports,require("react/jsx-runtime"),require("react")):typeof define=="function"&&define.amd?define(["exports","react/jsx-runtime","react"],A):(E=typeof globalThis<"u"?globalThis:E||self,A(E.VisionaryImage={},E.jsxRuntime,E.React))})(this,function(E,A,R){"use strict";function gt(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}var K={exports:{}};/*!
3
3
  Copyright (c) 2018 Jed Watson.
4
4
  Licensed under the MIT License (MIT), see
5
5
  http://jedwatson.github.io/classnames
6
- */(function(e){(function(){var t={}.hasOwnProperty;function n(){for(var r="",s=0;s<arguments.length;s++){var u=arguments[s];u&&(r=i(r,o(u)))}return r}function o(r){if(typeof r=="string"||typeof r=="number")return r;if(typeof r!="object")return"";if(Array.isArray(r))return n.apply(null,r);if(r.toString!==Object.prototype.toString&&!r.toString.toString().includes("[native code]"))return r.toString();var s="";for(var u in r)t.call(r,u)&&r[u]&&(s=i(s,u));return s}function i(r,s){return s?r?r+" "+s:r+s:r}e.exports?(n.default=n,e.exports=n):window.classNames=n})()})(K);var ge=K.exports;const be=me(ge),ye=(e,{root:t,rootMargin:n,threshold:o}={},i=[])=>{const r=x.useRef(null),s=x.useRef(null);return x.useCallback(c=>{r.current&&s.current&&(s.current.unobserve(r.current),s.current.disconnect(),s.current=null),c&&(s.current=new IntersectionObserver(e,{root:t,rootMargin:n,threshold:o}),s.current.observe(c),r.current=c)},[r,t,n,JSON.stringify(o),...i])},ve=({root:e,rootMargin:t,threshold:n,unobserveOnEnter:o,target:i,onEnter:r,onLeave:s,defaultInView:u}={},c=[])=>{const[a,p]=x.useState({inView:u||!1,entry:null,observer:null}),l=x.useCallback(([h],f)=>{const b=f.thresholds.some(g=>h.intersectionRatio>=g)&&h.isIntersecting;p({inView:b,entry:h,observer:f}),b&&o&&(f.unobserve(h.target),f.disconnect()),b?r==null||r(h,f):s==null||s(h,f)},[r,s,o]),m=ye(l,{root:e,rootMargin:t,threshold:n},[o,...c]);return x.useEffect(()=>{i!=null&&i.current&&m(i.current)},[i,m]),[m,a.inView,a.entry,a.observer]};var j=(e=>(e.AUTO="auto",e.AVIF="avif",e.JPEG="jpeg",e.WEBP="webp",e))(j||{}),v=(e=>(e.xs="xs",e.sm="sm",e.md="md",e.lg="lg",e.xl="xl",e.xxl="xxl",e["4k"]="4k",e["5k"]="5k",e.full="full",e))(v||{}),O=(e=>(e.DEBUG="debug",e.DOWNLOAD="download",e))(O||{});const we="https://link.visionary.cloud";j.AUTO,v.lg;const M={[v.xs]:160,[v.sm]:320,[v.md]:640,[v.lg]:1280,[v.xl]:1920,[v.xxl]:2560,[v["4k"]]:3840,[v["5k"]]:5120,[v.full]:0};Object.keys(M).reduce((e,t)=>{const n=t,o=M[n];return o&&(e[o]=n),e},{});const Q="!";var Ie=Object.defineProperty,xe=(e,t,n)=>t in e?Ie(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n,Ee=(e,t,n)=>xe(e,typeof t!="symbol"?t+"":t,n),G={},V={};Object.defineProperty(V,"__esModule",{value:!0});function Ae(e){return String.fromCharCode(parseInt(e.slice(1),16))}function Re(e){return btoa(encodeURIComponent(e).replace(/%[0-9A-F]{2}/g,Ae))}V.encode=Re;function Se(e){return`%${`00${e.charCodeAt(0).toString(16)}`.slice(-2)}`}function Te(e){return decodeURIComponent(Array.from(atob(e),Se).join(""))}V.decode=Te,Object.defineProperty(G,"__esModule",{value:!0});const ee=V;function Ue(e){return ee.decode(e.replace(/\-/g,"+").replace(/_/g,"/"))}var Ne=G.decode=Ue;function Oe(e){return ee.encode(e).replace(/\//g,"_").replace(/\+/g,"-").replace(/=+$/,"")}var Ce=G.encode=Oe;const De=e=>e.filter(Boolean),te=e=>{try{return new URL(e)}catch{return null}},L=(e="")=>/^[A-Za-z0-9_-]*$/.test(e),Pe=e=>{const{altText:t,bcc:n,blurhash:o,blurhashX:i,blurhashY:r,sourceHeight:s,sourceWidth:u,url:c}=e;if(!c||!u||!s)return new Error("Cannot construct visionary code: missing required url/width/height");const a=[c,u,s];return!n||(a.push(n),!o||!i||!r)||(a.push(o,i,r),t&&t.length&&a.push(t)),_e(a)},_e=e=>Ce(e.join(Q)),ne=e=>{if(typeof e!="string")return null;const t=e.trim();if(!t.length||!L(t))return null;const n=Ne(t);if(!n)return null;const o=n.split(Q);if(o.length<3)return null;const[i,r,s,u,c,a,p,l]=o,m=i.trim();if(!m.length)return console.error("Cannot parse code, empty file id"),null;const h=Number(r.trim()),f=Number(s.trim());if(isNaN(h)||isNaN(f)||!h||!f)return console.error("Cannot parse Visionary Code: invalid image dimensions",r,s),null;const y=Number(a)??0,b=Number(p)??0;return y<1||b<1?(console.error("Cannot parse Visionary Code: invalid blurhash x, y component dimensions",y,b),null):{altText:l,bcc:u,blurhash:c,blurhashX:y,blurhashY:b,sourceHeight:f,sourceWidth:h,url:m}};class je extends Error{constructor(){super(...arguments),Ee(this,"message","invalid endpoint URL (does it contain http/https?)")}}const Ve=e=>e===O.DEBUG,Le=e=>e===O.DOWNLOAD,$e=e=>Object.values(j).includes(e),re=e=>Object.values(v).includes(e),ke=(e=[])=>{const t={};for(const n of e)re(n)?t.size=v[n]:Ve(n)?t.debug=!0:Le(n)?t.download=!0:$e(n)&&(t.format=n);return t},ze=e=>{if(!e||typeof e!="object")return null;const t=[];return e.debug&&t.push(O.DEBUG),e.download&&t.push(O.DOWNLOAD),e.format&&e.format!==j.AUTO&&t.push(e.format),e.size&&re(e.size)&&t.push(e.size),t.length?t.sort().join(","):null},Be=e=>{if(L(e)){const t=ne(e);if(t)return{fields:t,options:{}}}return Me(e)},Me=e=>{if(!e)return null;const t=e.trim();if(!t)return null;try{const n=We(t);if(!n)return null;const{code:o,optionTokens:i}=n,r=ne(o);if(!r)return null;const s=ke(i);return{fields:r,options:s}}catch(n){n instanceof Error?console.error(`Error parsing URL: ${n.message}`,n):console.error("uncaught error",n)}return null},Ge=(e,t)=>{const n=Pe(e);if(n instanceof Error)return null;let o=null;if(t!=null&&t.endpoint&&(o=te(t==null?void 0:t.endpoint),!o))throw new je("Cannot construct URL: bad endpoint. Ensure endpoint starts with http:// or https://");o||(o=te(we));const i=[o.origin,"image",n],r=t?ze(t):null;return r&&i.push(r),t!=null&&t.filename?i.push(t.filename):i.push("image.jpg"),i.join("/")},We=e=>{try{const t=new URL(e),n=De(t.pathname.split("/"));if(n[0]!=="image"||![3,4].includes(n.length))throw new Error("Unrecognized URL");const o=n[1].trim();if(!o.length||!L(o))throw new Error("URL is not formatted as base64url");if(n.length===4){const i=n[2].split(",");return{code:o,optionTokens:i}}if(n.length===3)return{code:o,optionTokens:[]}}catch{return null}return null},oe=.7,se=1,N=24,Fe=v.lg,ce=process.env.NODE_ENV,He=ce==="development",ie=typeof document>"u",Xe=ce==="test",Ye=ie?()=>{}:x.useLayoutEffect,qe="<visionary>",S=(e,...t)=>{!console||typeof console.log!="function"||console.log(`${qe} ${e}`,...t)},ae=new Uint8Array(128);for(let e=0;e<83;e++)ae["0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz#$%*+,-.:;=?@[]^_{|}~".charCodeAt(e)]=e;const $=(e,t,n)=>{let o=0;for(;t<n;)o*=83,o+=ae[e.charCodeAt(t++)];return o},le=Math.pow,C=Math.PI,Ze=C*2,ue=3294.6,fe=269.025,Je=e=>e>10.31475?le(e/fe+.052132,2.4):e/ue,W=e=>~~(e>1227e-8?fe*le(e,.416666)-13.025:e*ue+1),D=e=>(e<0?-1:1)*e*e,de=e=>{for(e+=C/2;e>C;)e-=Ze;const t=1.27323954*e-.405284735*D(e);return .225*(D(t)-t)+t};function Ke(e){const t=$(e,2,6);return[t>>16,t>>8&255,t&255]}function Qe(e,t,n,o){const i=$(e,0,1),r=i%9+1,s=~~(i/9)+1,u=r*s;let c=0,a=0,p=0,l=0,m=0,h=0,f=0,y=0,b=0,g=0,w=0,E=0;const d=($(e,1,2)+1)/13446*(o|1),I=new Float64Array(u*3),Y=Ke(e);for(c=0;c<3;c++)I[c]=Je(Y[c]);for(c=1;c<u;c++)E=$(e,4+c*2,6+c*2),I[c*3]=D(~~(E/361)-9)*d,I[c*3+1]=D(~~(E/19)%19-9)*d,I[c*3+2]=D(E%19-9)*d;const z=new Float64Array(s*n),B=new Float64Array(r*t);for(a=0;a<s;a++)for(l=0;l<n;l++)z[a*n+l]=de(C*l*a/n);for(c=0;c<r;c++)for(p=0;p<t;p++)B[c*t+p]=de(C*p*c/t);const P=t*4,U=new Uint8ClampedArray(P*n);for(l=0;l<n;l++)for(p=0;p<t;p++){for(m=h=f=0,a=0;a<s;a++)for(b=z[a*n+l],c=0;c<r;c++)y=B[c*t+p]*b,g=(c+a*r)*3,m+=I[g]*y,h+=I[g+1]*y,f+=I[g+2]*y;w=4*p+l*P,U[w]=W(m),U[w+1]=W(h),U[w+2]=W(f),U[w+3]=255}return U}const k=e=>{try{return new URL(e)}catch{return null}},et=(e,t)=>`rgba(${e.r},${e.g},${e.b},${t})`,F=e=>He||Xe?{"data-testid":e}:{},tt=(e,t)=>t?{"data-fileid":e}:{},pe=(e,t)=>Math.min(e,t),nt=e=>{let t=e.replace(/^#/,"");if(t.length!==3&&t.length!==6)return null;t.length===3&&(t=`${t[0]}${t[0]}${t[1]}${t[1]}${t[2]}${t[2]}`);const n=parseInt(t.slice(0,2),16),o=parseInt(t.slice(2,4),16);return{b:parseInt(t.slice(4,6),16),g:o,r:n}},T=(e,t=0)=>{const n=Math.pow(10,t);return Math.round(e*n)/n},rt=(e,t)=>{const n=k(e),o=k(t);return!n||!o?e:(o.pathname=n.pathname,o.search=n.search,o.toString())},ot=(e,t={},n=oe,o=se)=>{if(!e)return null;try{t.debug&&S("input imageSrc:",e);const i=Be(e);if(t.debug&&S("Visionary URL data: ",i),!i)throw new Error("Could not parse Visionary URL");const{fields:r,options:s}=i;if(r.sourceWidth<1||r.sourceHeight<1)throw new Error("Invalid image dimensions");const u=r.sourceWidth/r.sourceHeight,c=(t==null?void 0:t.size)??s.size??Fe,a=M[c];let p=0,l=0,m=0;if(u>=1){l=p=pe(a,r.sourceWidth);const g=T(l/u);m=T(l/g,6)}else p=pe(a,r.sourceHeight),l=T(p*u),m=T(l/p,6);const h=T(100/m,6),f={...r,arPaddingTop:`${h}%`,aspectRatio:m,maxWidth:l,src:e},y=k(r.url);if(y)f.src=y.toString();else if(!k(e)&&L(r.url)){const g=Ge(r,{endpoint:t.endpoint,size:c});g&&(f.src=g)}t.endpoint&&(f.src=rt(f.src,t.endpoint));const b=r.bcc?nt(r.bcc):null;if(b&&(f.backgroundColor=et(b,n)),!ie&&r.blurhash&&!t.disableBlurLayer){const g=performance.now(),w=Qe(r.blurhash,N,N,o),E=performance.now()-g;t.debug&&S(`Blurhash decode time: ${T(E,1)} ms`),w&&(f.pixels=w)}return t.debug&&S("Visionary Image state: ",f),f}catch{return null}},he={bottom:0,left:0,position:"absolute",right:0,top:0},st={...he,maxHeight:"100%",maxWidth:"100%"},ct={...he,height:"100%",width:"100%"},it=e=>{const t={...st};return e&&(t.display="none"),t},H={CANVAS:"canvas",CONTAINER:"container",IMAGE:"image"},X={container:"v7y_7587",preventDrag:"v7y_b8c0",preventSelection:"v7y_e0dd"},at=({alt:e,bgColorAlpha:t=oe,className:n,debug:o=!1,disableBlurLayer:i=!1,disableImageLayer:r=!1,endpoint:s,height:u,hideImageLayer:c=!1,lazy:a=!0,onClick:p,onError:l,onLoad:m,preventDrag:h=!1,preventSelection:f=!1,punch:y=se,size:b,src:g,style:w,width:E})=>{const d=x.useMemo(()=>ot(g,{debug:o,disableBlurLayer:i,endpoint:s,size:b},t,y),[t,o,i,s,y,b,g]),I=x.useRef(null),[Y,z]=ve();Ye(function(){if(!I.current||!(d!=null&&d.blurhash))return;if(!d.pixels){console.warn("No pixel data passed in, skipping");return}const ft=performance.now(),Z=I.current.getContext("2d");if(!Z){console.warn("Cannot access canvasRenderingContext, skipping");return}const J=Z.createImageData(N,N);if(!J){console.warn("Could not create ImageData on CanvasRenderingContext");return}if(J.data.set(d.pixels),Z.putImageData(J,0,0),o){const dt=performance.now()-ft;S(`Canvas render time: ${T(dt,1)} ms`)}},[d==null?void 0:d.blurhash,d==null?void 0:d.pixels,o]);const B=x.useCallback(_=>{o&&S("Image load error ",_),l&&l()},[o,l]),P={alt:e,loading:!a||z?"eager":"lazy",onLoad:m};if(!d){o&&S("Not a Visionary URL, rendering fallback <img />");const _={...P,className:n,height:u,onClick:p,onError:l,src:g,style:w,width:E};return R.jsx("img",{..._})}const U=be(X.container,n,{[X.preventDrag]:!!h,[X.preventSelection]:!!f}),q={...{"--v-ar":d.arPaddingTop},aspectRatio:d.aspectRatio,backgroundColor:(d==null?void 0:d.backgroundColor)??void 0,maxWidth:d.maxWidth,position:"relative",width:"100%",...w};E&&(q.width=E),u&&(q.height=u);const lt={onClick:p},ut=it(c);return R.jsxs("div",{className:U,ref:Y,style:q,...tt(d.url,o),...F(H.CONTAINER),...lt,children:[!i&&R.jsx("canvas",{height:N,ref:I,style:ct,width:N,...F(H.CANVAS)}),!r&&R.jsx("img",{...P,...F(H.IMAGE),onError:B,src:d.src,style:ut})]})};A.Image=at,Object.defineProperty(A,Symbol.toStringTag,{value:"Module"})});
6
+ */(function(t){(function(){var e={}.hasOwnProperty;function n(){for(var r="",s=0;s<arguments.length;s++){var u=arguments[s];u&&(r=c(r,o(u)))}return r}function o(r){if(typeof r=="string"||typeof r=="number")return r;if(typeof r!="object")return"";if(Array.isArray(r))return n.apply(null,r);if(r.toString!==Object.prototype.toString&&!r.toString.toString().includes("[native code]"))return r.toString();var s="";for(var u in r)e.call(r,u)&&r[u]&&(s=c(s,u));return s}function c(r,s){return s?r?r+" "+s:r+s:r}t.exports?(n.default=n,t.exports=n):window.classNames=n})()})(K);var bt=K.exports;const vt=gt(bt),yt=(t,{root:e,rootMargin:n,threshold:o}={},c=[])=>{const r=R.useRef(null),s=R.useRef(null);return R.useCallback(i=>{r.current&&s.current&&(s.current.unobserve(r.current),s.current.disconnect(),s.current=null),i&&(s.current=new IntersectionObserver(t,{root:e,rootMargin:n,threshold:o}),s.current.observe(i),r.current=i)},[r,e,n,JSON.stringify(o),...c])},wt=({root:t,rootMargin:e,threshold:n,unobserveOnEnter:o,target:c,onEnter:r,onLeave:s,defaultInView:u}={},i=[])=>{const[a,p]=R.useState({inView:u||!1,entry:null,observer:null}),l=R.useCallback(([m],d)=>{const v=d.thresholds.some(b=>m.intersectionRatio>=b)&&m.isIntersecting;p({inView:v,entry:m,observer:d}),v&&o&&(d.unobserve(m.target),d.disconnect()),v?r==null||r(m,d):s==null||s(m,d)},[r,s,o]),g=yt(l,{root:t,rootMargin:e,threshold:n},[o,...i]);return R.useEffect(()=>{c!=null&&c.current&&g(c.current)},[c,g]),[g,a.inView,a.entry,a.observer]},j={ASPECT_RATIO_WRAPPER:"aspect-ratio-wrapper",CANVAS:"canvas",CONTAINER:"container",IMAGE:"image"};var V=(t=>(t.AUTO="auto",t.AVIF="avif",t.JPEG="jpeg",t.WEBP="webp",t))(V||{}),w=(t=>(t.xs="xs",t.sm="sm",t.md="md",t.lg="lg",t.xl="xl",t.xxl="xxl",t["4k"]="4k",t["5k"]="5k",t.full="full",t))(w||{}),U=(t=>(t.DEBUG="debug",t.DOWNLOAD="download",t))(U||{});const It="https://link.visionary.cloud";V.AUTO,w.lg;const F={[w.xs]:160,[w.sm]:320,[w.md]:640,[w.lg]:1280,[w.xl]:1920,[w.xxl]:2560,[w["4k"]]:3840,[w["5k"]]:5120,[w.full]:0};Object.keys(F).reduce((t,e)=>{const n=e,o=F[n];return o&&(t[o]=n),t},{});const Q="!";var At=Object.defineProperty,Rt=(t,e,n)=>e in t?At(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n,xt=(t,e,n)=>Rt(t,typeof e!="symbol"?e+"":e,n),H={},L={};Object.defineProperty(L,"__esModule",{value:!0});function Et(t){return String.fromCharCode(parseInt(t.slice(1),16))}function Tt(t){return btoa(encodeURIComponent(t).replace(/%[0-9A-F]{2}/g,Et))}L.encode=Tt;function Pt(t){return`%${`00${t.charCodeAt(0).toString(16)}`.slice(-2)}`}function Ct(t){return decodeURIComponent(Array.from(atob(t),Pt).join(""))}L.decode=Ct,Object.defineProperty(H,"__esModule",{value:!0});const tt=L;function Ot(t){return tt.decode(t.replace(/\-/g,"+").replace(/_/g,"/"))}var Ut=H.decode=Ot;function Nt(t){return tt.encode(t).replace(/\//g,"_").replace(/\+/g,"-").replace(/=+$/,"")}var _t=H.encode=Nt;const Dt=t=>t.filter(Boolean),et=t=>{try{return new URL(t)}catch{return null}},$=(t="")=>/^[A-Za-z0-9_-]*$/.test(t),St=t=>{const{altText:e,bcc:n,blurhash:o,blurhashX:c,blurhashY:r,sourceHeight:s,sourceWidth:u,url:i}=t;if(!i||!u||!s)return new Error("Cannot construct visionary code: missing required url/width/height");const a=[i,u,s];return!n||(a.push(n),!o||!c||!r)||(a.push(o,c,r),e&&e.length&&a.push(e)),jt(a)},jt=t=>_t(t.join(Q)),nt=t=>{if(typeof t!="string")return null;const e=t.trim();if(!e.length||!$(e))return null;const n=Ut(e);if(!n)return null;const o=n.split(Q);if(o.length<3)return null;const[c,r,s,u,i,a,p,l]=o,g=c.trim();if(!g.length)return console.error("Cannot parse code, empty file id"),null;const m=Number(r.trim()),d=Number(s.trim());if(isNaN(m)||isNaN(d)||!m||!d)return console.error("Cannot parse Visionary Code: invalid image dimensions",r,s),null;const y=Number(a)??0,v=Number(p)??0;return y<1||v<1?(console.error("Cannot parse Visionary Code: invalid blurhash x, y component dimensions",y,v),null):{altText:l,bcc:u,blurhash:i,blurhashX:y,blurhashY:v,sourceHeight:d,sourceWidth:m,url:g}};class Vt extends Error{constructor(){super(...arguments),xt(this,"message","invalid endpoint URL (does it contain http/https?)")}}const Lt=t=>t===U.DEBUG,$t=t=>t===U.DOWNLOAD,kt=t=>Object.values(V).includes(t),rt=t=>Object.values(w).includes(t),Wt=(t=[])=>{const e={};for(const n of t)rt(n)?e.size=w[n]:Lt(n)?e.debug=!0:$t(n)?e.download=!0:kt(n)&&(e.format=n);return e},zt=t=>{if(!t||typeof t!="object")return null;const e=[];return t.debug&&e.push(U.DEBUG),t.download&&e.push(U.DOWNLOAD),t.format&&t.format!==V.AUTO&&e.push(t.format),t.size&&rt(t.size)&&e.push(t.size),e.length?e.sort().join(","):null},Bt=t=>{if($(t)){const e=nt(t);if(e)return{fields:e,options:{}}}return Mt(t)},Mt=t=>{if(!t)return null;const e=t.trim();if(!e)return null;try{const n=Ft(e);if(!n)return null;const{code:o,optionTokens:c}=n,r=nt(o);if(!r)return null;const s=Wt(c);return{fields:r,options:s}}catch(n){n instanceof Error?console.error(`Error parsing URL: ${n.message}`,n):console.error("uncaught error",n)}return null},Gt=(t,e)=>{const n=St(t);if(n instanceof Error)return null;let o=null;if(e!=null&&e.endpoint&&(o=et(e==null?void 0:e.endpoint),!o))throw new Vt("Cannot construct URL: bad endpoint. Ensure endpoint starts with http:// or https://");o||(o=et(It));const c=[o.origin,"image",n],r=e?zt(e):null;return r&&c.push(r),e!=null&&e.filename?c.push(e.filename):c.push("image.jpg"),c.join("/")},Ft=t=>{try{const e=new URL(t),n=Dt(e.pathname.split("/"));if(n[0]!=="image"||![3,4].includes(n.length))throw new Error("Unrecognized URL");const o=n[1].trim();if(!o.length||!$(o))throw new Error("URL is not formatted as base64url");if(n.length===4){const c=n[2].split(",");return{code:o,optionTokens:c}}if(n.length===3)return{code:o,optionTokens:[]}}catch{return null}return null},ot=.7,st=1,O=24,Ht=w.lg,it=process.env.NODE_ENV,Xt=it==="development",ct=typeof document>"u",Yt=it==="test",k=t=>{try{return new URL(t)}catch{return null}},qt=(t,e)=>`rgba(${t.r},${t.g},${t.b},${e})`,W=t=>Xt||Yt?{"data-testid":t}:{},Zt=(t,e)=>e?{"data-fileid":t}:{},at=(t,e)=>Math.min(t,e),Jt=t=>{let e=t.replace(/^#/,"");if(e.length!==3&&e.length!==6)return null;e.length===3&&(e=`${e[0]}${e[0]}${e[1]}${e[1]}${e[2]}${e[2]}`);const n=parseInt(e.slice(0,2),16),o=parseInt(e.slice(2,4),16);return{b:parseInt(e.slice(4,6),16),g:o,r:n}},T=(t,e=0)=>{const n=Math.pow(10,e);return Math.round(t*n)/n},Kt=(t,e)=>{const n=k(t),o=k(e);return!n||!o?t:(o.pathname=n.pathname,o.search=n.search,o.toString())},Qt={overflow:"hidden"},te=({aspectRatio:t,children:e})=>A.jsx("div",{style:{aspectRatio:t,...Qt},...W(j.ASPECT_RATIO_WRAPPER),children:e}),ee=ct?()=>{}:R.useLayoutEffect,ne="<visionary>",P=(t,...e)=>{!console||typeof console.log!="function"||console.log(`${ne} ${t}`,...e)},lt=new Uint8Array(128);for(let t=0;t<83;t++)lt["0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz#$%*+,-.:;=?@[]^_{|}~".charCodeAt(t)]=t;const z=(t,e,n)=>{let o=0;for(;e<n;)o*=83,o+=lt[t.charCodeAt(e++)];return o},ut=Math.pow,N=Math.PI,re=N*2,dt=3294.6,ft=269.025,oe=t=>t>10.31475?ut(t/ft+.052132,2.4):t/dt,X=t=>~~(t>1227e-8?ft*ut(t,.416666)-13.025:t*dt+1),_=t=>(t<0?-1:1)*t*t,pt=t=>{for(t+=N/2;t>N;)t-=re;const e=1.27323954*t-.405284735*_(t);return .225*(_(e)-e)+e};function se(t){const e=z(t,2,6);return[e>>16,e>>8&255,e&255]}function ie(t,e,n,o){const c=z(t,0,1),r=c%9+1,s=~~(c/9)+1,u=r*s;let i=0,a=0,p=0,l=0,g=0,m=0,d=0,y=0,v=0,b=0,h=0,x=0;const f=(z(t,1,2)+1)/13446*(o|1),I=new Float64Array(u*3),q=se(t);for(i=0;i<3;i++)I[i]=oe(q[i]);for(i=1;i<u;i++)x=z(t,4+i*2,6+i*2),I[i*3]=_(~~(x/361)-9)*f,I[i*3+1]=_(~~(x/19)%19-9)*f,I[i*3+2]=_(x%19-9)*f;const B=new Float64Array(s*n),M=new Float64Array(r*e);for(a=0;a<s;a++)for(l=0;l<n;l++)B[a*n+l]=pt(N*l*a/n);for(i=0;i<r;i++)for(p=0;p<e;p++)M[i*e+p]=pt(N*p*i/e);const D=e*4,C=new Uint8ClampedArray(D*n);for(l=0;l<n;l++)for(p=0;p<e;p++){for(g=m=d=0,a=0;a<s;a++)for(v=B[a*n+l],i=0;i<r;i++)y=M[i*e+p]*v,b=(i+a*r)*3,g+=I[b]*y,m+=I[b+1]*y,d+=I[b+2]*y;h=4*p+l*D,C[h]=X(g),C[h+1]=X(m),C[h+2]=X(d),C[h+3]=255}return C}const ce=(t,e={},n=ot,o=st)=>{if(!t)return null;try{e.debug&&P("input imageSrc:",t);const c=Bt(t);if(e.debug&&P("Visionary URL data: ",c),!c)throw new Error("Could not parse Visionary URL");const{fields:r,options:s}=c;if(r.sourceWidth<1||r.sourceHeight<1)throw new Error("Invalid image dimensions");const u=r.sourceWidth/r.sourceHeight,i=(e==null?void 0:e.size)??s.size??Ht,a=F[i];let p=0,l=0,g=0;if(u>=1){l=p=at(a,r.sourceWidth);const b=T(l/u);g=T(l/b,6)}else p=at(a,r.sourceHeight),l=T(p*u),g=T(l/p,6);const m=T(100/g,6),d={...r,arPaddingTop:`${m}%`,aspectRatio:g,maxWidth:l,src:t},y=k(r.url);if(y)d.src=y.toString();else if(!k(t)&&$(r.url)){const b=Gt(r,{endpoint:e.endpoint,size:i});b&&(d.src=b)}e.endpoint&&(d.src=Kt(d.src,e.endpoint));const v=r.bcc?Jt(r.bcc):null;if(v&&(d.backgroundColor=qt(v,n)),!ct&&r.blurhash&&!e.disableBlurLayer){const b=performance.now(),h=ie(r.blurhash,O,O,o),x=performance.now()-b;e.debug&&P(`Blurhash decode time: ${T(x,1)} ms`),h&&(d.pixels=h)}return e.debug&&P("Visionary Image state: ",d),d}catch{return null}},ht={bottom:0,left:0,position:"absolute",right:0,top:0},ae={...ht,maxHeight:"100%",maxWidth:"100%"},le={...ht,height:"100%",width:"100%"},ue=t=>{const e={...ae};return t&&(e.display="none"),e},Y={container:"v7y_7587",preventDrag:"v7y_b8c0",preventSelection:"v7y_e0dd"},de=({alt:t,bgColorAlpha:e=ot,className:n,debug:o=!1,disableBlurLayer:c=!1,disableImageLayer:r=!1,endpoint:s,height:u,hideImageLayer:i=!1,lazy:a=!0,onClick:p,onError:l,onLoad:g,preventDrag:m=!1,preventSelection:d=!1,punch:y=st,size:v,src:b,style:h,width:x})=>{const f=R.useMemo(()=>ce(b,{debug:o,disableBlurLayer:c,endpoint:s,size:v},e,y),[e,o,c,s,y,v,b]),I=R.useRef(null),[q,B]=wt();ee(function(){if(!I.current||!(f!=null&&f.blurhash))return;if(!f.pixels){console.warn("No pixel data passed in, skipping");return}const he=performance.now(),Z=I.current.getContext("2d");if(!Z){console.warn("Cannot access canvasRenderingContext, skipping");return}const J=Z.createImageData(O,O);if(!J){console.warn("Could not create ImageData on CanvasRenderingContext");return}if(J.data.set(f.pixels),Z.putImageData(J,0,0),o){const me=performance.now()-he;P(`Canvas render time: ${T(me,1)} ms`)}},[f==null?void 0:f.blurhash,f==null?void 0:f.pixels,o]);const M=R.useCallback(S=>{o&&P("Image load error ",S),l&&l()},[o,l]),D={alt:t,loading:!a||B?"eager":"lazy",onLoad:g};if(!f){o&&P("Not a Visionary URL, rendering fallback <img />");const S={...D,className:n,height:u,onClick:p,onError:l,src:b,style:h,width:x};return A.jsx("img",{...S})}const C=vt(Y.container,n,{[Y.preventDrag]:!!m,[Y.preventSelection]:!!d}),G={...{"--v-ar":f.arPaddingTop},...h,aspectRatio:f.aspectRatio,backgroundColor:(f==null?void 0:f.backgroundColor)??void 0,maxWidth:f.maxWidth,position:"relative",width:"100%"};x&&(G.width=x),u&&(G.height=u),h!=null&&h.maxWidth&&(G.maxWidth=h.maxWidth);const fe={onClick:p},pe=ue(i),mt=A.jsxs("div",{className:C,ref:q,style:G,...Zt(f.url,o),...W(j.CONTAINER),...fe,children:[!c&&A.jsx("canvas",{height:O,ref:I,style:le,width:O,...W(j.CANVAS)}),!r&&A.jsx("img",{...D,...W(j.IMAGE),onError:M,src:f.src,style:pe})]});return h!=null&&h.aspectRatio?A.jsx(te,{aspectRatio:h.aspectRatio,children:mt}):mt};E.Image=de,Object.defineProperty(E,Symbol.toStringTag,{value:"Module"})});
package/package.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "name": "visionary-image",
3
3
  "description": "React image component with built-in Blurhash placeholders for better UX and Core Web Vitals.",
4
- "version": "1.0.2",
4
+ "version": "1.0.4",
5
+ "homepage": "https://visionary.cloud",
5
6
  "type": "module",
6
7
  "main": "./dist/visionary-image.umd.js",
7
8
  "module": "./dist/visionary-image.es.js",