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 +33 -23
- package/dist/visionary-image.es.js +251 -248
- package/dist/visionary-image.umd.js +2 -2
- package/package.json +2 -1
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
|
-
 [](https://github.com/visionary-ux/visionary-image/actions/workflows/ci-cd-workflow.yml?query=branch%3Amaster) [](https://bundlephobia.com/package/visionary-image)  [](https://visionary-ux.github.io/visionary-image/)
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## Features
|
|
8
8
|
|
|
9
|
-
- Blurhash
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
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
|
-
|
|
20
|
+
### Lighthouse Performance
|
|
21
|
+
|
|
22
|
+
Lighthouse report filmstrip showing three-layer image loading process
|
|
23
|
+

|
|
17
24
|
|
|
18
25
|
## Installation
|
|
19
26
|
|
|
@@ -25,7 +32,7 @@ npm install --save visionary-image
|
|
|
25
32
|
|
|
26
33
|
## Usage
|
|
27
34
|
|
|
28
|
-
|
|
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
|
|
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
|
|
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
|
-
###
|
|
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
|
|
3
|
-
import { useRef as Y, useCallback as q, useState as
|
|
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
|
|
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
|
-
})(
|
|
43
|
-
var
|
|
44
|
-
const
|
|
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
|
-
},
|
|
50
|
-
const [a, p] =
|
|
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(([
|
|
55
|
-
const
|
|
54
|
+
}), l = q(([m], d) => {
|
|
55
|
+
const v = d.thresholds.some((b) => m.intersectionRatio >= b) && m.isIntersecting;
|
|
56
56
|
p({
|
|
57
|
-
inView:
|
|
58
|
-
entry:
|
|
59
|
-
observer:
|
|
60
|
-
}),
|
|
61
|
-
}, [r, s, o]),
|
|
62
|
-
return
|
|
63
|
-
i != null && i.current &&
|
|
64
|
-
}, [i,
|
|
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
|
|
67
|
-
const
|
|
68
|
-
|
|
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
|
-
[
|
|
71
|
-
[
|
|
72
|
-
[
|
|
73
|
-
[
|
|
74
|
-
[
|
|
75
|
-
[
|
|
76
|
-
[
|
|
77
|
-
[
|
|
78
|
-
[
|
|
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
|
|
88
|
-
var
|
|
89
|
-
Object.defineProperty(
|
|
90
|
-
function
|
|
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
|
|
94
|
-
return btoa(encodeURIComponent(t).replace(/%[0-9A-F]{2}/g,
|
|
98
|
+
function St(t) {
|
|
99
|
+
return btoa(encodeURIComponent(t).replace(/%[0-9A-F]{2}/g, Lt));
|
|
95
100
|
}
|
|
96
|
-
|
|
97
|
-
function
|
|
101
|
+
z.encode = St;
|
|
102
|
+
function Vt(t) {
|
|
98
103
|
return `%${`00${t.charCodeAt(0).toString(16)}`.slice(-2)}`;
|
|
99
104
|
}
|
|
100
|
-
function
|
|
101
|
-
return decodeURIComponent(Array.from(atob(t),
|
|
105
|
+
function $t(t) {
|
|
106
|
+
return decodeURIComponent(Array.from(atob(t), Vt).join(""));
|
|
102
107
|
}
|
|
103
|
-
|
|
108
|
+
z.decode = $t;
|
|
104
109
|
Object.defineProperty(J, "__esModule", { value: !0 });
|
|
105
|
-
const
|
|
106
|
-
function
|
|
107
|
-
return
|
|
110
|
+
const ot = z;
|
|
111
|
+
function jt(t) {
|
|
112
|
+
return ot.decode(t.replace(/\-/g, "+").replace(/_/g, "/"));
|
|
108
113
|
}
|
|
109
|
-
var
|
|
110
|
-
function
|
|
111
|
-
return
|
|
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 =
|
|
114
|
-
const Bt = (t) => t.filter(Boolean),
|
|
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
|
-
},
|
|
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(
|
|
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 || !
|
|
135
|
+
if (!n.length || !B(n))
|
|
131
136
|
return null;
|
|
132
|
-
const e =
|
|
137
|
+
const e = kt(n);
|
|
133
138
|
if (!e)
|
|
134
139
|
return null;
|
|
135
|
-
const o = e.split(
|
|
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,
|
|
139
|
-
if (!
|
|
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
|
|
142
|
-
if (isNaN(
|
|
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
|
|
145
|
-
return
|
|
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
|
-
|
|
148
|
-
|
|
152
|
+
w,
|
|
153
|
+
v
|
|
149
154
|
), null) : {
|
|
150
155
|
altText: l,
|
|
151
156
|
bcc: u,
|
|
152
157
|
blurhash: c,
|
|
153
|
-
blurhashX:
|
|
154
|
-
blurhashY:
|
|
155
|
-
sourceHeight:
|
|
156
|
-
sourceWidth:
|
|
157
|
-
url:
|
|
158
|
+
blurhashX: w,
|
|
159
|
+
blurhashY: v,
|
|
160
|
+
sourceHeight: d,
|
|
161
|
+
sourceWidth: m,
|
|
162
|
+
url: g
|
|
158
163
|
};
|
|
159
164
|
};
|
|
160
|
-
class
|
|
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
|
|
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
|
-
|
|
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
|
-
},
|
|
175
|
+
}, qt = (t) => {
|
|
171
176
|
if (!t || typeof t != "object")
|
|
172
177
|
return null;
|
|
173
178
|
const n = [];
|
|
174
|
-
return t.debug && n.push(
|
|
175
|
-
},
|
|
176
|
-
if (
|
|
177
|
-
const n =
|
|
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
|
|
185
|
-
},
|
|
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 =
|
|
197
|
+
const e = tn(n);
|
|
193
198
|
if (!e)
|
|
194
199
|
return null;
|
|
195
|
-
const { code: o, optionTokens: i } = e, r =
|
|
200
|
+
const { code: o, optionTokens: i } = e, r = st(o);
|
|
196
201
|
if (!r)
|
|
197
202
|
return null;
|
|
198
|
-
const s =
|
|
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
|
-
},
|
|
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 =
|
|
213
|
-
throw new
|
|
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 =
|
|
217
|
-
const i = [o.origin, "image", e], r = n ?
|
|
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
|
-
},
|
|
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 || !
|
|
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
|
-
},
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
}
|
|
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
|
-
|
|
278
|
+
dt["0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz#$%*+,-.:;=?@[]^_{|}~".charCodeAt(
|
|
249
279
|
t
|
|
250
280
|
)] = t;
|
|
251
|
-
const
|
|
281
|
+
const j = (t, n, e) => {
|
|
252
282
|
let o = 0;
|
|
253
283
|
for (; n < e; )
|
|
254
|
-
o *= 83, o +=
|
|
284
|
+
o *= 83, o += dt[t.charCodeAt(n++)];
|
|
255
285
|
return o;
|
|
256
|
-
}, ft = Math.pow,
|
|
257
|
-
for (t +=
|
|
258
|
-
t -=
|
|
259
|
-
const n = 1.27323954 * t - 0.405284735 *
|
|
260
|
-
return 0.225 * (
|
|
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
|
|
263
|
-
const n =
|
|
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
|
|
267
|
-
const i =
|
|
268
|
-
let c = 0, a = 0, p = 0, l = 0,
|
|
269
|
-
const
|
|
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
|
-
|
|
301
|
+
R[c] = hn(M[c]);
|
|
272
302
|
for (c = 1; c < u; c++)
|
|
273
|
-
|
|
274
|
-
const D = new Float64Array(s * e),
|
|
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] =
|
|
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
|
-
|
|
281
|
-
const
|
|
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 (
|
|
285
|
-
for (
|
|
286
|
-
|
|
287
|
-
|
|
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
|
|
319
|
+
return I;
|
|
290
320
|
}
|
|
291
|
-
const
|
|
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 &&
|
|
319
|
-
const i =
|
|
320
|
-
if (n.debug &&
|
|
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 ??
|
|
326
|
-
let p = 0, l = 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
|
|
330
|
-
|
|
336
|
+
const b = E(l / u);
|
|
337
|
+
g = E(l / b, 6);
|
|
331
338
|
} else
|
|
332
|
-
p = tt(a, r.sourceHeight), l =
|
|
333
|
-
const
|
|
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: `${
|
|
336
|
-
aspectRatio:
|
|
342
|
+
arPaddingTop: `${m}%`,
|
|
343
|
+
aspectRatio: g,
|
|
337
344
|
maxWidth: l,
|
|
338
345
|
src: t
|
|
339
|
-
},
|
|
340
|
-
if (
|
|
341
|
-
|
|
342
|
-
else if (!
|
|
343
|
-
const
|
|
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
|
-
|
|
354
|
+
b && (d.src = b);
|
|
348
355
|
}
|
|
349
|
-
n.endpoint && (
|
|
350
|
-
const
|
|
351
|
-
if (
|
|
352
|
-
const
|
|
353
|
-
n.debug &&
|
|
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 &&
|
|
362
|
+
return n.debug && x("Visionary Image state: ", d), d;
|
|
356
363
|
} catch {
|
|
357
364
|
return null;
|
|
358
365
|
}
|
|
359
|
-
},
|
|
366
|
+
}, mt = {
|
|
360
367
|
bottom: 0,
|
|
361
368
|
left: 0,
|
|
362
369
|
position: "absolute",
|
|
363
370
|
right: 0,
|
|
364
371
|
top: 0
|
|
365
|
-
},
|
|
366
|
-
...
|
|
372
|
+
}, vn = {
|
|
373
|
+
...mt,
|
|
367
374
|
maxHeight: "100%",
|
|
368
375
|
maxWidth: "100%"
|
|
369
|
-
},
|
|
370
|
-
...
|
|
376
|
+
}, wn = {
|
|
377
|
+
...mt,
|
|
371
378
|
height: "100%",
|
|
372
379
|
width: "100%"
|
|
373
|
-
},
|
|
380
|
+
}, yn = (t) => {
|
|
374
381
|
const n = {
|
|
375
|
-
...
|
|
382
|
+
...vn
|
|
376
383
|
};
|
|
377
384
|
return t && (n.display = "none"), n;
|
|
378
|
-
},
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
},
|
|
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 =
|
|
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:
|
|
400
|
-
preventDrag:
|
|
401
|
-
preventSelection:
|
|
402
|
-
punch:
|
|
403
|
-
size:
|
|
404
|
-
src:
|
|
405
|
-
style:
|
|
406
|
-
width:
|
|
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
|
|
411
|
+
const f = Et(() => bn(b, {
|
|
409
412
|
debug: o,
|
|
410
413
|
disableBlurLayer: i,
|
|
411
414
|
endpoint: s,
|
|
412
|
-
size:
|
|
413
|
-
}, n,
|
|
414
|
-
|
|
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 (!
|
|
419
|
+
if (!R.current || !(f != null && f.blurhash))
|
|
417
420
|
return;
|
|
418
|
-
if (!
|
|
421
|
+
if (!f.pixels) {
|
|
419
422
|
console.warn("No pixel data passed in, skipping");
|
|
420
423
|
return;
|
|
421
424
|
}
|
|
422
|
-
const
|
|
423
|
-
if (!
|
|
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
|
|
428
|
-
if (!
|
|
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 (
|
|
433
|
-
const
|
|
434
|
-
|
|
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
|
-
[
|
|
440
|
+
[f == null ? void 0 : f.blurhash, f == null ? void 0 : f.pixels, o]
|
|
438
441
|
);
|
|
439
|
-
const
|
|
440
|
-
(
|
|
441
|
-
o &&
|
|
442
|
+
const L = q(
|
|
443
|
+
(O) => {
|
|
444
|
+
o && x("Image load error ", O), l && l();
|
|
442
445
|
},
|
|
443
446
|
[o, l]
|
|
444
|
-
),
|
|
447
|
+
), P = {
|
|
445
448
|
alt: t,
|
|
446
449
|
loading: !a || D ? "eager" : "lazy",
|
|
447
|
-
onLoad:
|
|
450
|
+
onLoad: g
|
|
448
451
|
};
|
|
449
|
-
if (!
|
|
450
|
-
o &&
|
|
451
|
-
const
|
|
452
|
-
...
|
|
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:
|
|
458
|
-
style:
|
|
459
|
-
width:
|
|
460
|
+
src: b,
|
|
461
|
+
style: h,
|
|
462
|
+
width: A
|
|
460
463
|
};
|
|
461
|
-
return /* @__PURE__ */
|
|
464
|
+
return /* @__PURE__ */ U("img", { ...O });
|
|
462
465
|
}
|
|
463
|
-
const
|
|
464
|
-
[X.preventDrag]: !!
|
|
465
|
-
[X.preventSelection]: !!
|
|
466
|
-
}),
|
|
466
|
+
const I = Pt(X.container, e, {
|
|
467
|
+
[X.preventDrag]: !!m,
|
|
468
|
+
[X.preventSelection]: !!d
|
|
469
|
+
}), S = {
|
|
467
470
|
...{
|
|
468
|
-
"--v-ar":
|
|
471
|
+
"--v-ar": f.arPaddingTop
|
|
469
472
|
},
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
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
|
-
|
|
478
|
-
const
|
|
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
|
-
},
|
|
481
|
-
return /* @__PURE__ */ vt(
|
|
483
|
+
}, bt = yn(c), K = /* @__PURE__ */ yt(
|
|
482
484
|
"div",
|
|
483
485
|
{
|
|
484
|
-
className:
|
|
485
|
-
ref:
|
|
486
|
-
style:
|
|
487
|
-
...
|
|
488
|
-
|
|
489
|
-
...
|
|
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__ */
|
|
493
|
+
!i && /* @__PURE__ */ U(
|
|
492
494
|
"canvas",
|
|
493
495
|
{
|
|
494
|
-
height:
|
|
495
|
-
ref:
|
|
496
|
-
style:
|
|
497
|
-
width:
|
|
498
|
-
|
|
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__ */
|
|
504
|
+
/* @__PURE__ */ U(
|
|
503
505
|
"img",
|
|
504
506
|
{
|
|
505
|
-
...
|
|
506
|
-
|
|
507
|
-
onError:
|
|
508
|
-
src:
|
|
509
|
-
style:
|
|
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
|
-
|
|
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
|
|
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.
|
|
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",
|