visionary-image 1.0.0 → 1.0.1
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 +14 -16
- package/dist/visionary-image.es.js +202 -201
- package/dist/visionary-image.umd.js +3 -3
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Visionary Image
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
React image component with built-in Blurhash placeholders for better UX and Core Web Vitals.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
 
|
|
6
6
|
|
|
7
7
|
**Features:**
|
|
8
8
|
|
|
9
|
-
- Blurhash data encoded in the image URL via [visionary-url](https://github.com/visionary-ux/visionary-url)
|
|
10
|
-
- Renders a true-to-size, responsive
|
|
11
|
-
-
|
|
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
12
|
- Framework-tested (Remix, Next.js, Vite) with support for both client and server-side rendering (SSR, SSG) environments
|
|
13
13
|
- Additional features: Prevent dragging, user-selection of image
|
|
14
|
-
- Improves Core Web Vitals scores
|
|
14
|
+
- Improves Core Web Vitals scores which Google notes as an important ranking signal in Search.
|
|
15
15
|
|
|
16
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)
|
|
17
17
|
|
|
@@ -23,21 +23,19 @@ Install via npm, yarn, or pnpm.
|
|
|
23
23
|
npm install --save visionary-image
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
##
|
|
26
|
+
## Usage
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
Create a Visionary image URL to get started.
|
|
29
29
|
|
|
30
30
|
### Creating a Visionary Image URL
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
There are several ways to create a Visionary URL.
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
1. Use the [Visionary URL Maker](https://visionary.cloud/url-maker) for public image URLs
|
|
35
|
+
2. Use the [Drag & Drop Blurhash Generator](https://visionary.cloud/image-to-blurhash) for local image files
|
|
36
|
+
3. Use [visionary-url](https://github.com/visionary-ux/visionary-url) to programmatically generate a URL
|
|
35
37
|
|
|
36
|
-
|
|
37
|
-
- Copy a URL from your [Visionary Dashboard](https://visionary.cloud/dashboard)
|
|
38
|
-
- Use this [sample URL]()
|
|
39
|
-
|
|
40
|
-
### Render image component
|
|
38
|
+
### Render Image
|
|
41
39
|
|
|
42
40
|
```tsx
|
|
43
41
|
import { Image } from "visionary-image";
|
|
@@ -1,7 +1,7 @@
|
|
|
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)}.
|
|
2
|
-
import { jsx as
|
|
3
|
-
import { useRef as Y, useCallback as q, useState as
|
|
4
|
-
function
|
|
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 yt, useEffect as wt, useLayoutEffect as It, useMemo as xt } from "react";
|
|
4
|
+
function Et(t) {
|
|
5
5
|
return t && t.__esModule && Object.prototype.hasOwnProperty.call(t, "default") ? t.default : t;
|
|
6
6
|
}
|
|
7
7
|
var et = { exports: {} };
|
|
@@ -12,8 +12,8 @@ var et = { exports: {} };
|
|
|
12
12
|
*/
|
|
13
13
|
(function(t) {
|
|
14
14
|
(function() {
|
|
15
|
-
var
|
|
16
|
-
function
|
|
15
|
+
var e = {}.hasOwnProperty;
|
|
16
|
+
function n() {
|
|
17
17
|
for (var r = "", s = 0; s < arguments.length; s++) {
|
|
18
18
|
var a = arguments[s];
|
|
19
19
|
a && (r = c(r, o(a)));
|
|
@@ -26,28 +26,28 @@ var et = { exports: {} };
|
|
|
26
26
|
if (typeof r != "object")
|
|
27
27
|
return "";
|
|
28
28
|
if (Array.isArray(r))
|
|
29
|
-
return
|
|
29
|
+
return n.apply(null, r);
|
|
30
30
|
if (r.toString !== Object.prototype.toString && !r.toString.toString().includes("[native code]"))
|
|
31
31
|
return r.toString();
|
|
32
32
|
var s = "";
|
|
33
33
|
for (var a in r)
|
|
34
|
-
|
|
34
|
+
e.call(r, a) && r[a] && (s = c(s, a));
|
|
35
35
|
return s;
|
|
36
36
|
}
|
|
37
37
|
function c(r, s) {
|
|
38
38
|
return s ? r ? r + " " + s : r + s : r;
|
|
39
39
|
}
|
|
40
|
-
t.exports ? (
|
|
40
|
+
t.exports ? (n.default = n, t.exports = n) : window.classNames = n;
|
|
41
41
|
})();
|
|
42
42
|
})(et);
|
|
43
|
-
var
|
|
44
|
-
const
|
|
43
|
+
var Rt = et.exports;
|
|
44
|
+
const At = /* @__PURE__ */ Et(Rt), St = (t, { root: e, rootMargin: n, threshold: o } = {}, c = []) => {
|
|
45
45
|
const r = Y(null), s = Y(null);
|
|
46
46
|
return q((i) => {
|
|
47
|
-
r.current && s.current && (s.current.unobserve(r.current), s.current.disconnect(), s.current = null), i && (s.current = new IntersectionObserver(t, { root:
|
|
48
|
-
}, [r,
|
|
49
|
-
},
|
|
50
|
-
const [d, h] =
|
|
47
|
+
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);
|
|
48
|
+
}, [r, e, n, JSON.stringify(o), ...c]);
|
|
49
|
+
}, Nt = ({ root: t, rootMargin: e, threshold: n, unobserveOnEnter: o, target: c, onEnter: r, onLeave: s, defaultInView: a } = {}, i = []) => {
|
|
50
|
+
const [d, h] = yt({
|
|
51
51
|
inView: a || !1,
|
|
52
52
|
entry: null,
|
|
53
53
|
observer: null
|
|
@@ -58,14 +58,14 @@ const K = /* @__PURE__ */ Rt(At), Nt = (t, { root: n, rootMargin: e, threshold:
|
|
|
58
58
|
entry: p,
|
|
59
59
|
observer: l
|
|
60
60
|
}), b && o && (l.unobserve(p.target), l.disconnect()), b ? r == null || r(p, l) : s == null || s(p, l);
|
|
61
|
-
}, [r, s, o]), m =
|
|
62
|
-
return
|
|
61
|
+
}, [r, s, o]), m = St(f, { root: t, rootMargin: e, threshold: n }, [o, ...i]);
|
|
62
|
+
return wt(() => {
|
|
63
63
|
c != null && c.current && m(c.current);
|
|
64
64
|
}, [c, m]), [m, d.inView, d.entry, d.observer];
|
|
65
65
|
};
|
|
66
|
-
var
|
|
67
|
-
const
|
|
68
|
-
|
|
66
|
+
var $ = /* @__PURE__ */ ((t) => (t.AUTO = "auto", t.AVIF = "avif", t.JPEG = "jpeg", t.WEBP = "webp", t))($ || {}), 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 || {}), P = /* @__PURE__ */ ((t) => (t.DEBUG = "debug", t.DOWNLOAD = "download", t))(P || {});
|
|
67
|
+
const Ot = "https://link.visionary.cloud";
|
|
68
|
+
$.AUTO, y.lg;
|
|
69
69
|
const Z = {
|
|
70
70
|
[y.xs]: 160,
|
|
71
71
|
[y.sm]: 320,
|
|
@@ -78,61 +78,61 @@ const Z = {
|
|
|
78
78
|
[y.full]: 0
|
|
79
79
|
};
|
|
80
80
|
Object.keys(Z).reduce(
|
|
81
|
-
(t,
|
|
82
|
-
const
|
|
83
|
-
return o && (t[o] =
|
|
81
|
+
(t, e) => {
|
|
82
|
+
const n = e, o = Z[n];
|
|
83
|
+
return o && (t[o] = n), t;
|
|
84
84
|
},
|
|
85
85
|
{}
|
|
86
86
|
);
|
|
87
|
-
const
|
|
88
|
-
var
|
|
89
|
-
Object.defineProperty(
|
|
90
|
-
function
|
|
87
|
+
const nt = "!";
|
|
88
|
+
var Ut = Object.defineProperty, Tt = (t, e, n) => e in t ? Ut(t, e, { enumerable: !0, configurable: !0, writable: !0, value: n }) : t[e] = n, Dt = (t, e, n) => Tt(t, typeof e != "symbol" ? e + "" : e, n), J = {}, L = {};
|
|
89
|
+
Object.defineProperty(L, "__esModule", { value: !0 });
|
|
90
|
+
function Pt(t) {
|
|
91
91
|
return String.fromCharCode(parseInt(t.slice(1), 16));
|
|
92
92
|
}
|
|
93
|
-
function
|
|
94
|
-
return btoa(encodeURIComponent(t).replace(/%[0-9A-F]{2}/g,
|
|
93
|
+
function _t(t) {
|
|
94
|
+
return btoa(encodeURIComponent(t).replace(/%[0-9A-F]{2}/g, Pt));
|
|
95
95
|
}
|
|
96
|
-
|
|
97
|
-
function
|
|
96
|
+
L.encode = _t;
|
|
97
|
+
function Ct(t) {
|
|
98
98
|
return `%${`00${t.charCodeAt(0).toString(16)}`.slice(-2)}`;
|
|
99
99
|
}
|
|
100
100
|
function Vt(t) {
|
|
101
|
-
return decodeURIComponent(Array.from(atob(t),
|
|
101
|
+
return decodeURIComponent(Array.from(atob(t), Ct).join(""));
|
|
102
102
|
}
|
|
103
|
-
|
|
103
|
+
L.decode = Vt;
|
|
104
104
|
Object.defineProperty(J, "__esModule", { value: !0 });
|
|
105
|
-
const
|
|
105
|
+
const rt = L;
|
|
106
106
|
function $t(t) {
|
|
107
|
-
return
|
|
107
|
+
return rt.decode(t.replace(/\-/g, "+").replace(/_/g, "/"));
|
|
108
108
|
}
|
|
109
109
|
var Lt = J.decode = $t;
|
|
110
110
|
function jt(t) {
|
|
111
|
-
return
|
|
111
|
+
return rt.encode(t).replace(/\//g, "_").replace(/\+/g, "-").replace(/=+$/, "");
|
|
112
112
|
}
|
|
113
113
|
var kt = J.encode = jt;
|
|
114
|
-
const zt = (t) => t.filter(Boolean),
|
|
114
|
+
const zt = (t) => t.filter(Boolean), K = (t) => {
|
|
115
115
|
try {
|
|
116
116
|
return new URL(t);
|
|
117
117
|
} catch {
|
|
118
118
|
return null;
|
|
119
119
|
}
|
|
120
|
-
},
|
|
121
|
-
const { altText:
|
|
120
|
+
}, j = (t = "") => /^[A-Za-z0-9_-]*$/.test(t), Bt = (t) => {
|
|
121
|
+
const { altText: e, bcc: n, blurhash: o, blurhashX: c, blurhashY: r, sourceHeight: s, sourceWidth: a, url: i } = t;
|
|
122
122
|
if (!i || !a || !s)
|
|
123
123
|
return new Error("Cannot construct visionary code: missing required url/width/height");
|
|
124
124
|
const d = [i, a, s];
|
|
125
|
-
return !
|
|
126
|
-
}, Mt = (t) => kt(t.join(
|
|
125
|
+
return !n || (d.push(n), !o || !c || !r) || (d.push(o, c, r), e && e.length && d.push(e)), Mt(d);
|
|
126
|
+
}, Mt = (t) => kt(t.join(nt)), ot = (t) => {
|
|
127
127
|
if (typeof t != "string")
|
|
128
128
|
return null;
|
|
129
|
-
const
|
|
130
|
-
if (!
|
|
129
|
+
const e = t.trim();
|
|
130
|
+
if (!e.length || !j(e))
|
|
131
131
|
return null;
|
|
132
|
-
const
|
|
133
|
-
if (!
|
|
132
|
+
const n = Lt(e);
|
|
133
|
+
if (!n)
|
|
134
134
|
return null;
|
|
135
|
-
const o =
|
|
135
|
+
const o = n.split(nt);
|
|
136
136
|
if (o.length < 3)
|
|
137
137
|
return null;
|
|
138
138
|
const [c, r, s, a, i, d, h, f] = o, m = c.trim();
|
|
@@ -159,25 +159,25 @@ const zt = (t) => t.filter(Boolean), Q = (t) => {
|
|
|
159
159
|
};
|
|
160
160
|
class Gt extends Error {
|
|
161
161
|
constructor() {
|
|
162
|
-
super(...arguments),
|
|
162
|
+
super(...arguments), Dt(this, "message", "invalid endpoint URL (does it contain http/https?)");
|
|
163
163
|
}
|
|
164
164
|
}
|
|
165
|
-
const Wt = (t) => t ===
|
|
166
|
-
const
|
|
167
|
-
for (const
|
|
168
|
-
|
|
169
|
-
return
|
|
165
|
+
const Wt = (t) => t === P.DEBUG, Ft = (t) => t === P.DOWNLOAD, Ht = (t) => Object.values($).includes(t), st = (t) => Object.values(y).includes(t), Xt = (t = []) => {
|
|
166
|
+
const e = {};
|
|
167
|
+
for (const n of t)
|
|
168
|
+
st(n) ? e.size = y[n] : Wt(n) ? e.debug = !0 : Ft(n) ? e.download = !0 : Ht(n) && (e.format = n);
|
|
169
|
+
return e;
|
|
170
170
|
}, Yt = (t) => {
|
|
171
171
|
if (!t || typeof t != "object")
|
|
172
172
|
return null;
|
|
173
|
-
const
|
|
174
|
-
return t.debug &&
|
|
173
|
+
const e = [];
|
|
174
|
+
return t.debug && e.push(P.DEBUG), t.download && e.push(P.DOWNLOAD), t.format && t.format !== $.AUTO && e.push(t.format), t.size && st(t.size) && e.push(t.size), e.length ? e.sort().join(",") : null;
|
|
175
175
|
}, Zt = (t) => {
|
|
176
|
-
if (
|
|
177
|
-
const
|
|
178
|
-
if (
|
|
176
|
+
if (j(t)) {
|
|
177
|
+
const e = ot(t);
|
|
178
|
+
if (e)
|
|
179
179
|
return {
|
|
180
|
-
fields:
|
|
180
|
+
fields: e,
|
|
181
181
|
options: {}
|
|
182
182
|
};
|
|
183
183
|
}
|
|
@@ -185,14 +185,14 @@ const Wt = (t) => t === C.DEBUG, Ft = (t) => t === C.DOWNLOAD, Ht = (t) => Objec
|
|
|
185
185
|
}, qt = (t) => {
|
|
186
186
|
if (!t)
|
|
187
187
|
return null;
|
|
188
|
-
const
|
|
189
|
-
if (!
|
|
188
|
+
const e = t.trim();
|
|
189
|
+
if (!e)
|
|
190
190
|
return null;
|
|
191
191
|
try {
|
|
192
|
-
const
|
|
193
|
-
if (!
|
|
192
|
+
const n = Kt(e);
|
|
193
|
+
if (!n)
|
|
194
194
|
return null;
|
|
195
|
-
const { code: o, optionTokens: c } =
|
|
195
|
+
const { code: o, optionTokens: c } = n, r = ot(o);
|
|
196
196
|
if (!r)
|
|
197
197
|
return null;
|
|
198
198
|
const s = Xt(c);
|
|
@@ -200,38 +200,38 @@ const Wt = (t) => t === C.DEBUG, Ft = (t) => t === C.DOWNLOAD, Ht = (t) => Objec
|
|
|
200
200
|
fields: r,
|
|
201
201
|
options: s
|
|
202
202
|
};
|
|
203
|
-
} catch (
|
|
204
|
-
|
|
203
|
+
} catch (n) {
|
|
204
|
+
n instanceof Error ? console.error(`Error parsing URL: ${n.message}`, n) : console.error("uncaught error", n);
|
|
205
205
|
}
|
|
206
206
|
return null;
|
|
207
|
-
}, Jt = (t,
|
|
208
|
-
const
|
|
209
|
-
if (
|
|
207
|
+
}, Jt = (t, e) => {
|
|
208
|
+
const n = Bt(t);
|
|
209
|
+
if (n instanceof Error)
|
|
210
210
|
return null;
|
|
211
211
|
let o = null;
|
|
212
|
-
if (
|
|
212
|
+
if (e != null && e.endpoint && (o = K(e == null ? void 0 : e.endpoint), !o))
|
|
213
213
|
throw new Gt(
|
|
214
214
|
"Cannot construct URL: bad endpoint. Ensure endpoint starts with http:// or https://"
|
|
215
215
|
);
|
|
216
|
-
o || (o =
|
|
217
|
-
const c = [o.origin, "image",
|
|
218
|
-
return r && c.push(r),
|
|
216
|
+
o || (o = K(Ot));
|
|
217
|
+
const c = [o.origin, "image", n], r = e ? Yt(e) : null;
|
|
218
|
+
return r && c.push(r), e != null && e.filename ? c.push(e.filename) : c.push("image.jpg"), c.join("/");
|
|
219
219
|
}, Kt = (t) => {
|
|
220
220
|
try {
|
|
221
|
-
const
|
|
222
|
-
if (
|
|
221
|
+
const e = new URL(t), n = zt(e.pathname.split("/"));
|
|
222
|
+
if (n[0] !== "image" || ![3, 4].includes(n.length))
|
|
223
223
|
throw new Error("Unrecognized URL");
|
|
224
|
-
const o =
|
|
225
|
-
if (!o.length || !
|
|
224
|
+
const o = n[1].trim();
|
|
225
|
+
if (!o.length || !j(o))
|
|
226
226
|
throw new Error("URL is not formatted as base64url");
|
|
227
|
-
if (
|
|
228
|
-
const c =
|
|
227
|
+
if (n.length === 4) {
|
|
228
|
+
const c = n[2].split(",");
|
|
229
229
|
return {
|
|
230
230
|
code: o,
|
|
231
231
|
optionTokens: c
|
|
232
232
|
};
|
|
233
233
|
}
|
|
234
|
-
if (
|
|
234
|
+
if (n.length === 3)
|
|
235
235
|
return {
|
|
236
236
|
code: o,
|
|
237
237
|
optionTokens: []
|
|
@@ -240,214 +240,218 @@ const Wt = (t) => t === C.DEBUG, Ft = (t) => t === C.DOWNLOAD, Ht = (t) => Objec
|
|
|
240
240
|
return null;
|
|
241
241
|
}
|
|
242
242
|
return null;
|
|
243
|
-
},
|
|
244
|
-
} :
|
|
245
|
-
!console || typeof console.log != "function" || console.log(`${
|
|
246
|
-
},
|
|
243
|
+
}, ct = 0.7, it = 1, N = 24, Qt = y.lg, at = process.env.NODE_ENV, te = at === "development", lt = typeof document > "u", ee = at === "test", ne = lt ? () => {
|
|
244
|
+
} : It, re = "<visionary>", S = (t, ...e) => {
|
|
245
|
+
!console || typeof console.log != "function" || console.log(`${re} ${t}`, ...e);
|
|
246
|
+
}, oe = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz#$%*+,-.:;=?@[]^_{|}~", C = (t, e, n) => {
|
|
247
247
|
let o = 0;
|
|
248
|
-
for (;
|
|
249
|
-
o *= 83, o +=
|
|
248
|
+
for (; e < n; )
|
|
249
|
+
o *= 83, o += oe.indexOf(t[e++]);
|
|
250
250
|
return o;
|
|
251
|
-
},
|
|
252
|
-
for (t +=
|
|
253
|
-
t -=
|
|
254
|
-
const
|
|
255
|
-
return 0.225 * (
|
|
251
|
+
}, ut = Math.pow, _ = Math.PI, se = _ * 2, dt = 3294.6, ft = 269.025, ce = (t) => t > 10.31475 ? ut(t / ft + 0.052132, 2.4) : t / dt, W = (t) => ~~(t > 1227e-8 ? ft * ut(t, 0.416666) - 13.025 : t * dt + 1), D = (t) => (t < 0 ? -1 : 1) * t * t, Q = (t) => {
|
|
252
|
+
for (t += _ / 2; t > _; )
|
|
253
|
+
t -= se;
|
|
254
|
+
const e = 1.27323954 * t - 0.405284735 * D(t);
|
|
255
|
+
return 0.225 * (D(e) - e) + e;
|
|
256
256
|
};
|
|
257
|
-
function
|
|
258
|
-
const
|
|
259
|
-
return [
|
|
257
|
+
function ie(t) {
|
|
258
|
+
const e = C(t, 2, 6);
|
|
259
|
+
return [e >> 16, e >> 8 & 255, e & 255];
|
|
260
260
|
}
|
|
261
|
-
function
|
|
262
|
-
const c =
|
|
263
|
-
let i = 0, d = 0, h = 0, f = 0, m = 0, p = 0, l = 0, v = 0, b = 0, g = 0, w = 0,
|
|
264
|
-
const
|
|
261
|
+
function ae(t, e, n, o) {
|
|
262
|
+
const c = C(t, 0, 1), r = c % 9 + 1, s = ~~(c / 9) + 1, a = r * s;
|
|
263
|
+
let i = 0, d = 0, h = 0, f = 0, m = 0, p = 0, l = 0, v = 0, b = 0, g = 0, w = 0, x = 0, u = 0, E = 0;
|
|
264
|
+
const O = (C(t, 1, 2) + 1) / 13446 * (o | 1), I = new Float64Array(a * 3), k = ie(t);
|
|
265
265
|
for (i = 0; i < 3; i++)
|
|
266
|
-
|
|
266
|
+
I[i] = ce(k[i]);
|
|
267
267
|
for (i = 1; i < a; i++)
|
|
268
|
-
|
|
269
|
-
const
|
|
270
|
-
for (f = 0; f <
|
|
271
|
-
for (
|
|
272
|
-
for (m = 0, p = 0, l = 0, u =
|
|
273
|
-
for (b =
|
|
274
|
-
v =
|
|
275
|
-
w = 4 * h + f *
|
|
268
|
+
E = C(t, 4 + i * 2, 6 + i * 2), I[i * 3] = D(~~(E / (19 * 19)) - 9) * O, I[i * 3 + 1] = D(~~(E / 19) % 19 - 9) * O, I[i * 3 + 2] = D(E % 19 - 9) * O;
|
|
269
|
+
const U = e * 4, R = new Uint8ClampedArray(U * n);
|
|
270
|
+
for (f = 0; f < n; f++)
|
|
271
|
+
for (x = _ * f / n, h = 0; h < e; h++) {
|
|
272
|
+
for (m = 0, p = 0, l = 0, u = _ * h / e, d = 0; d < s; d++)
|
|
273
|
+
for (b = Q(x * d), i = 0; i < r; i++)
|
|
274
|
+
v = Q(u * i) * b, g = (i + d * r) * 3, m += I[g] * v, p += I[g + 1] * v, l += I[g + 2] * v;
|
|
275
|
+
w = 4 * h + f * U, R[w] = W(m), R[w + 1] = W(p), R[w + 2] = W(l), R[w + 3] = 255;
|
|
276
276
|
}
|
|
277
277
|
return R;
|
|
278
278
|
}
|
|
279
|
-
const
|
|
279
|
+
const V = (t) => {
|
|
280
280
|
try {
|
|
281
281
|
return new URL(t);
|
|
282
282
|
} catch {
|
|
283
283
|
return null;
|
|
284
284
|
}
|
|
285
|
-
},
|
|
285
|
+
}, le = (t, e) => `rgba(${t.r},${t.g},${t.b},${e})`, F = (t) => te || ee ? {
|
|
286
286
|
"data-testid": t
|
|
287
|
-
} : {},
|
|
287
|
+
} : {}, ue = (t, e) => e ? {
|
|
288
288
|
"data-fileid": t
|
|
289
|
-
} : {},
|
|
290
|
-
let
|
|
291
|
-
if (
|
|
289
|
+
} : {}, tt = (t, e) => Math.min(t, e), de = (t) => {
|
|
290
|
+
let e = t.replace(/^#/, "");
|
|
291
|
+
if (e.length !== 3 && e.length !== 6)
|
|
292
292
|
return null;
|
|
293
|
-
|
|
294
|
-
const
|
|
295
|
-
return { b: parseInt(
|
|
296
|
-
}, A = (t,
|
|
297
|
-
const
|
|
298
|
-
return Math.round(t *
|
|
299
|
-
},
|
|
300
|
-
const
|
|
301
|
-
return !
|
|
302
|
-
},
|
|
293
|
+
e.length === 3 && (e = `${e[0]}${e[0]}${e[1]}${e[1]}${e[2]}${e[2]}`);
|
|
294
|
+
const n = parseInt(e.slice(0, 2), 16), o = parseInt(e.slice(2, 4), 16);
|
|
295
|
+
return { b: parseInt(e.slice(4, 6), 16), g: o, r: n };
|
|
296
|
+
}, A = (t, e = 0) => {
|
|
297
|
+
const n = Math.pow(10, e);
|
|
298
|
+
return Math.round(t * n) / n;
|
|
299
|
+
}, fe = (t, e) => {
|
|
300
|
+
const n = V(t), o = V(e);
|
|
301
|
+
return !n || !o ? t : (o.pathname = n.pathname, o.search = n.search, o.toString());
|
|
302
|
+
}, pe = (t, e = {}, n = ct, o = it) => {
|
|
303
303
|
if (!t)
|
|
304
304
|
return null;
|
|
305
305
|
try {
|
|
306
|
-
|
|
306
|
+
e.debug && S("input imageSrc:", t);
|
|
307
307
|
const c = Zt(t);
|
|
308
|
-
if (
|
|
308
|
+
if (e.debug && S("Visionary URL data: ", c), !c)
|
|
309
309
|
throw new Error("Could not parse Visionary URL");
|
|
310
310
|
const { fields: r, options: s } = c;
|
|
311
311
|
if (r.sourceWidth < 1 || r.sourceHeight < 1)
|
|
312
312
|
throw new Error("Invalid image dimensions");
|
|
313
|
-
const a = r.sourceWidth / r.sourceHeight, i = (
|
|
313
|
+
const a = r.sourceWidth / r.sourceHeight, i = (e == null ? void 0 : e.size) ?? s.size ?? Qt, d = Z[i];
|
|
314
314
|
let h = 0, f = 0, m = 0;
|
|
315
315
|
if (a >= 1) {
|
|
316
|
-
f = h =
|
|
316
|
+
f = h = tt(d, r.sourceWidth);
|
|
317
317
|
const g = A(f / a);
|
|
318
318
|
m = A(f / g, 6);
|
|
319
319
|
} else
|
|
320
|
-
h =
|
|
320
|
+
h = tt(d, r.sourceHeight), f = A(h * a), m = A(f / h, 6);
|
|
321
321
|
const p = A(100 / m, 6), l = {
|
|
322
322
|
...r,
|
|
323
323
|
arPaddingTop: `${p}%`,
|
|
324
324
|
aspectRatio: m,
|
|
325
325
|
maxWidth: f,
|
|
326
326
|
src: t
|
|
327
|
-
}, v =
|
|
327
|
+
}, v = V(r.url);
|
|
328
328
|
if (v)
|
|
329
329
|
l.src = v.toString();
|
|
330
|
-
else if (
|
|
330
|
+
else if (!V(t) && j(r.url)) {
|
|
331
331
|
const g = Jt(r, {
|
|
332
|
-
endpoint:
|
|
332
|
+
endpoint: e.endpoint,
|
|
333
333
|
size: i
|
|
334
334
|
});
|
|
335
335
|
g && (l.src = g);
|
|
336
336
|
}
|
|
337
|
-
|
|
338
|
-
const b = r.bcc ?
|
|
339
|
-
if (b && (l.backgroundColor =
|
|
340
|
-
const g = performance.now(), w =
|
|
341
|
-
|
|
337
|
+
e.endpoint && (l.src = fe(l.src, e.endpoint));
|
|
338
|
+
const b = r.bcc ? de(r.bcc) : null;
|
|
339
|
+
if (b && (l.backgroundColor = le(b, n)), !lt && r.blurhash && !e.disableBlurLayer) {
|
|
340
|
+
const g = performance.now(), w = ae(r.blurhash, N, N, o), x = performance.now() - g;
|
|
341
|
+
e.debug && S(`Blurhash decode time: ${A(x, 1)} ms`), w && (l.pixels = w);
|
|
342
342
|
}
|
|
343
|
-
return
|
|
343
|
+
return e.debug && S("Visionary Image state: ", l), l;
|
|
344
344
|
} catch {
|
|
345
345
|
return null;
|
|
346
346
|
}
|
|
347
|
-
},
|
|
347
|
+
}, pt = {
|
|
348
348
|
bottom: 0,
|
|
349
349
|
left: 0,
|
|
350
350
|
position: "absolute",
|
|
351
351
|
right: 0,
|
|
352
352
|
top: 0
|
|
353
|
-
},
|
|
354
|
-
...
|
|
353
|
+
}, he = {
|
|
354
|
+
...pt,
|
|
355
355
|
maxHeight: "100%",
|
|
356
356
|
maxWidth: "100%"
|
|
357
|
-
},
|
|
358
|
-
...
|
|
357
|
+
}, me = {
|
|
358
|
+
...pt,
|
|
359
359
|
height: "100%",
|
|
360
360
|
width: "100%"
|
|
361
|
-
},
|
|
361
|
+
}, ge = (t) => {
|
|
362
|
+
const e = {
|
|
363
|
+
...he
|
|
364
|
+
};
|
|
365
|
+
return t && (e.display = "none"), e;
|
|
366
|
+
}, H = {
|
|
362
367
|
CANVAS: "canvas",
|
|
363
368
|
CONTAINER: "container",
|
|
364
369
|
IMAGE: "image"
|
|
365
|
-
},
|
|
366
|
-
container:
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
}, An = ({
|
|
370
|
+
}, be = "v7y_7587", ve = "v7y_b8c0", ye = "v7y_e0dd", X = {
|
|
371
|
+
container: be,
|
|
372
|
+
preventDrag: ve,
|
|
373
|
+
preventSelection: ye
|
|
374
|
+
}, Re = ({
|
|
371
375
|
alt: t,
|
|
372
|
-
bgColorAlpha:
|
|
373
|
-
className:
|
|
376
|
+
bgColorAlpha: e = ct,
|
|
377
|
+
className: n,
|
|
374
378
|
debug: o = !1,
|
|
375
379
|
disableBlurLayer: c = !1,
|
|
376
380
|
disableImageLayer: r = !1,
|
|
377
381
|
endpoint: s,
|
|
378
382
|
height: a,
|
|
379
|
-
hideImageLayer: i,
|
|
383
|
+
hideImageLayer: i = !1,
|
|
380
384
|
lazy: d = !0,
|
|
381
385
|
onClick: h,
|
|
382
386
|
onError: f,
|
|
383
387
|
onLoad: m,
|
|
384
388
|
preventDrag: p = !1,
|
|
385
389
|
preventSelection: l = !1,
|
|
386
|
-
punch: v =
|
|
390
|
+
punch: v = it,
|
|
387
391
|
size: b,
|
|
388
392
|
src: g,
|
|
389
393
|
style: w,
|
|
390
|
-
width:
|
|
394
|
+
width: x
|
|
391
395
|
}) => {
|
|
392
|
-
const u =
|
|
396
|
+
const u = xt(() => pe(g, {
|
|
393
397
|
debug: o,
|
|
394
398
|
disableBlurLayer: c,
|
|
395
399
|
endpoint: s,
|
|
396
400
|
size: b
|
|
397
|
-
},
|
|
398
|
-
|
|
401
|
+
}, e, v), [e, o, c, s, v, b, g]), E = Y(null), [O, I] = Nt();
|
|
402
|
+
ne(
|
|
399
403
|
function() {
|
|
400
|
-
if (!
|
|
404
|
+
if (!E.current || !(u != null && u.blurhash))
|
|
401
405
|
return;
|
|
402
406
|
if (!u.pixels) {
|
|
403
407
|
console.warn("No pixel data passed in, skipping");
|
|
404
408
|
return;
|
|
405
409
|
}
|
|
406
|
-
const
|
|
407
|
-
if (!
|
|
410
|
+
const gt = performance.now(), B = E.current.getContext("2d");
|
|
411
|
+
if (!B) {
|
|
408
412
|
console.warn("Cannot access canvasRenderingContext, skipping");
|
|
409
413
|
return;
|
|
410
414
|
}
|
|
411
|
-
const
|
|
412
|
-
if (!
|
|
415
|
+
const M = B.createImageData(N, N);
|
|
416
|
+
if (!M) {
|
|
413
417
|
console.warn("Could not create ImageData on CanvasRenderingContext");
|
|
414
418
|
return;
|
|
415
419
|
}
|
|
416
|
-
if (
|
|
417
|
-
const
|
|
418
|
-
|
|
420
|
+
if (M.data.set(u.pixels), B.putImageData(M, 0, 0), o) {
|
|
421
|
+
const bt = performance.now() - gt;
|
|
422
|
+
S(`Canvas render time: ${A(bt, 1)} ms`);
|
|
419
423
|
}
|
|
420
424
|
},
|
|
421
425
|
[u == null ? void 0 : u.blurhash, u == null ? void 0 : u.pixels, o]
|
|
422
426
|
);
|
|
423
|
-
const
|
|
427
|
+
const k = q(
|
|
424
428
|
(T) => {
|
|
425
|
-
o &&
|
|
429
|
+
o && S("Image load error ", T), f && f();
|
|
426
430
|
},
|
|
427
431
|
[o, f]
|
|
428
|
-
),
|
|
432
|
+
), U = {
|
|
429
433
|
alt: t,
|
|
430
|
-
loading: !d ||
|
|
434
|
+
loading: !d || I ? "eager" : "lazy",
|
|
431
435
|
onLoad: m
|
|
432
436
|
};
|
|
433
437
|
if (!u) {
|
|
434
|
-
o &&
|
|
438
|
+
o && S("Not a Visionary URL, rendering fallback <img />");
|
|
435
439
|
const T = {
|
|
436
|
-
...
|
|
437
|
-
className:
|
|
440
|
+
...U,
|
|
441
|
+
className: n,
|
|
438
442
|
height: a,
|
|
439
443
|
onClick: h,
|
|
440
444
|
onError: f,
|
|
441
445
|
src: g,
|
|
442
446
|
style: w,
|
|
443
|
-
width:
|
|
447
|
+
width: x
|
|
444
448
|
};
|
|
445
|
-
return /* @__PURE__ */
|
|
449
|
+
return /* @__PURE__ */ G("img", { ...T });
|
|
446
450
|
}
|
|
447
|
-
const R =
|
|
448
|
-
[
|
|
449
|
-
[
|
|
450
|
-
}),
|
|
451
|
+
const R = At(X.container, n, {
|
|
452
|
+
[X.preventDrag]: !!p,
|
|
453
|
+
[X.preventSelection]: !!l
|
|
454
|
+
}), z = {
|
|
451
455
|
...{
|
|
452
456
|
"--v-ar": u.arPaddingTop
|
|
453
457
|
},
|
|
@@ -458,42 +462,39 @@ const $ = (t) => {
|
|
|
458
462
|
width: "100%",
|
|
459
463
|
...w
|
|
460
464
|
};
|
|
461
|
-
|
|
462
|
-
const
|
|
465
|
+
x && (z.width = x), a && (z.height = a);
|
|
466
|
+
const ht = {
|
|
463
467
|
onClick: h
|
|
464
|
-
},
|
|
465
|
-
|
|
466
|
-
});
|
|
467
|
-
return /* @__PURE__ */ yt(
|
|
468
|
+
}, mt = ge(i);
|
|
469
|
+
return /* @__PURE__ */ vt(
|
|
468
470
|
"div",
|
|
469
471
|
{
|
|
470
472
|
className: R,
|
|
471
|
-
ref:
|
|
472
|
-
style:
|
|
473
|
-
...
|
|
474
|
-
...H
|
|
475
|
-
...
|
|
473
|
+
ref: O,
|
|
474
|
+
style: z,
|
|
475
|
+
...ue(u.url, o),
|
|
476
|
+
...F(H.CONTAINER),
|
|
477
|
+
...ht,
|
|
476
478
|
children: [
|
|
477
|
-
!c && /* @__PURE__ */
|
|
479
|
+
!c && /* @__PURE__ */ G(
|
|
478
480
|
"canvas",
|
|
479
481
|
{
|
|
480
|
-
height:
|
|
481
|
-
ref:
|
|
482
|
-
style:
|
|
483
|
-
width:
|
|
484
|
-
...H
|
|
482
|
+
height: N,
|
|
483
|
+
ref: E,
|
|
484
|
+
style: me,
|
|
485
|
+
width: N,
|
|
486
|
+
...F(H.CANVAS)
|
|
485
487
|
}
|
|
486
488
|
),
|
|
487
489
|
!r && // eslint-disable-next-line jsx-a11y/alt-text -- `sharedImgProps` includes alt tag
|
|
488
|
-
/* @__PURE__ */
|
|
490
|
+
/* @__PURE__ */ G(
|
|
489
491
|
"img",
|
|
490
492
|
{
|
|
491
|
-
...
|
|
492
|
-
...H
|
|
493
|
-
|
|
494
|
-
onError: z,
|
|
493
|
+
...U,
|
|
494
|
+
...F(H.IMAGE),
|
|
495
|
+
onError: k,
|
|
495
496
|
src: u.src,
|
|
496
|
-
style:
|
|
497
|
+
style: mt
|
|
497
498
|
}
|
|
498
499
|
)
|
|
499
500
|
]
|
|
@@ -501,5 +502,5 @@ const $ = (t) => {
|
|
|
501
502
|
);
|
|
502
503
|
};
|
|
503
504
|
export {
|
|
504
|
-
|
|
505
|
+
Re as Image
|
|
505
506
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
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)}.
|
|
2
|
-
(function(E,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):(E=typeof globalThis<"u"?globalThis:E||self,R(E.VisionaryImage={},E.jsxRuntime,E.React))})(this,function(E,R,
|
|
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(E,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):(E=typeof globalThis<"u"?globalThis:E||self,R(E.VisionaryImage={},E.jsxRuntime,E.React))})(this,function(E,R,I){"use strict";function ht(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 a=arguments[s];a&&(r=i(r,o(a)))}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 a in r)t.call(r,a)&&r[a]&&(s=i(s,a));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 Q=me(ge),be=(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:a}={},c=[])=>{const[d,h]=x.useState({inView:a||!1,entry:null,observer:null}),f=x.useCallback(([p],l)=>{const b=l.thresholds.some(g=>p.intersectionRatio>=g)&&p.isIntersecting;h({inView:b,entry:p,observer:l}),b&&o&&(l.unobserve(p.target),l.disconnect()),b?r==null||r(p,l):s==null||s(p,l)},[r,s,o]),m=be(f,{root:e,rootMargin:t,threshold:n},[o,...c]);return x.useEffect(()=>{i!=null&&i.current&&m(i.current)},[i,m]),[m,d.inView,d.entry,d.observer]};var $=(e=>(e.AUTO="auto",e.AVIF="avif",e.JPEG="jpeg",e.WEBP="webp",e))($||{}),y=(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))(y||{}),C=(e=>(e.DEBUG="debug",e.DOWNLOAD="download",e))(C||{});const ye="https://link.visionary.cloud";$.AUTO,y.lg;const G={[y.xs]:160,[y.sm]:320,[y.md]:640,[y.lg]:1280,[y.xl]:1920,[y.xxl]:2560,[y["4k"]]:3840,[y["5k"]]:5120,[y.full]:0};Object.keys(G).reduce((e,t)=>{const n=t,o=G[n];return o&&(e[o]=n),e},{});const ee="!";var we=Object.defineProperty,xe=(e,t,n)=>t in e?we(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n,Ie=(e,t,n)=>xe(e,typeof t!="symbol"?t+"":t,n),W={},L={};Object.defineProperty(L,"__esModule",{value:!0});function Ee(e){return String.fromCharCode(parseInt(e.slice(1),16))}function Re(e){return btoa(encodeURIComponent(e).replace(/%[0-9A-F]{2}/g,Ee))}L.encode=Re;function Ae(e){return`%${`00${e.charCodeAt(0).toString(16)}`.slice(-2)}`}function Se(e){return decodeURIComponent(Array.from(atob(e),Ae).join(""))}L.decode=Se,Object.defineProperty(W,"__esModule",{value:!0});const te=L;function Te(e){return te.decode(e.replace(/\-/g,"+").replace(/_/g,"/"))}var Ne=W.decode=Te;function Oe(e){return te.encode(e).replace(/\//g,"_").replace(/\+/g,"-").replace(/=+$/,"")}var Ue=W.encode=Oe;const Ce=e=>e.filter(Boolean),ne=e=>{try{return new URL(e)}catch{return null}},k=(e="")=>/^[A-Za-z0-9_-]*$/.test(e),De=e=>{const{altText:t,bcc:n,blurhash:o,blurhashX:i,blurhashY:r,sourceHeight:s,sourceWidth:a,url:c}=e;if(!c||!a||!s)return new Error("Cannot construct visionary code: missing required url/width/height");const d=[c,a,s];return!n||(d.push(n),!o||!i||!r)||(d.push(o,i,r),t&&t.length&&d.push(t)),Pe(d)},Pe=e=>Ue(e.join(ee)),re=e=>{if(typeof e!="string")return null;const t=e.trim();if(!t.length||!k(t))return null;const n=Ne(t);if(!n)return null;const o=n.split(ee);if(o.length<3)return null;const[i,r,s,a,c,d,h,f]=o,m=i.trim();if(!m.length)return console.error("Cannot parse code, empty file id"),null;const p=Number(r.trim()),l=Number(s.trim());if(isNaN(p)||isNaN(l)||!p||!l)return console.error("Cannot parse Visionary Code: invalid image dimensions",r,s),null;const v=Number(d)??0,b=Number(h)??0;return v<1||b<1?(console.error("Cannot parse Visionary Code: invalid blurhash x, y component dimensions",v,b),null):{altText:f,bcc:a,blurhash:c,blurhashX:v,blurhashY:b,sourceHeight:l,sourceWidth:p,url:m}};class _e extends Error{constructor(){super(...arguments),Ie(this,"message","invalid endpoint URL (does it contain http/https?)")}}const je=e=>e===C.DEBUG,Ve=e=>e===C.DOWNLOAD,$e=e=>Object.values($).includes(e),oe=e=>Object.values(y).includes(e),Le=(e=[])=>{const t={};for(const n of e)oe(n)?t.size=y[n]:je(n)?t.debug=!0:Ve(n)?t.download=!0:$e(n)&&(t.format=n);return t},ke=e=>{if(!e||typeof e!="object")return null;const t=[];return e.debug&&t.push(C.DEBUG),e.download&&t.push(C.DOWNLOAD),e.format&&e.format!==$.AUTO&&t.push(e.format),e.size&&oe(e.size)&&t.push(e.size),t.length?t.sort().join(","):null},ze=e=>{if(k(e)){const t=re(e);if(t)return{fields:t,options:{}}}return Be(e)},Be=e=>{if(!e)return null;const t=e.trim();if(!t)return null;try{const n=Ge(t);if(!n)return null;const{code:o,optionTokens:i}=n,r=re(o);if(!r)return null;const s=Le(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},Me=(e,t)=>{const n=De(e);if(n instanceof Error)return null;let o=null;if(t!=null&&t.endpoint&&(o=ne(t==null?void 0:t.endpoint),!o))throw new _e("Cannot construct URL: bad endpoint. Ensure endpoint starts with http:// or https://");o||(o=ne(ye));const i=[o.origin,"image",n],r=t?ke(t):null;return r&&i.push(r),t!=null&&t.filename?i.push(t.filename):i.push("image.jpg"),i.join("/")},Ge=e=>{try{const t=new URL(e),n=Ce(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||!k(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},se=.7,ie=1,U=24,We=y.lg,ce=process.env.NODE_ENV,Fe=ce==="development",ae=typeof document>"u",He=ce==="test",qe=ae?()=>{}:x.useLayoutEffect,Xe="<visionary>",T=(e,...t)=>{!console||typeof console.log!="function"||console.log(`${Xe} ${e}`,...t)},Ye="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz#$%*+,-.:;=?@[]^_{|}~",z=(e,t,n)=>{let o=0;for(;t<n;)o*=83,o+=Ye.indexOf(e[t++]);return o},le=Math.pow,D=Math.PI,Ze=D*2,ue=3294.6,de=269.025,Je=e=>e>10.31475?le(e/de+.052132,2.4):e/ue,F=e=>~~(e>1227e-8?de*le(e,.416666)-13.025:e*ue+1),P=e=>(e<0?-1:1)*e*e,fe=e=>{for(e+=D/2;e>D;)e-=Ze;const t=1.27323954*e-.405284735*P(e);return .225*(P(t)-t)+t};function Ke(e){const t=z(e,2,6);return[t>>16,t>>8&255,t&255]}function Qe(e,t,n,o){const i=z(e,0,1),r=i%9+1,s=~~(i/9)+1,a=r*s;let c=0,d=0,h=0,f=0,m=0,p=0,l=0,v=0,b=0,g=0,w=0,A=0,u=0,S=0;const _=(z(e,1,2)+1)/13446*(o|1),I=new Float64Array(a*3),X=Ke(e);for(c=0;c<3;c++)I[c]=Je(X[c]);for(c=1;c<a;c++)S=z(e,4+c*2,6+c*2),I[c*3]=P(~~(S/(19*19))-9)*_,I[c*3+1]=P(~~(S/19)%19-9)*_,I[c*3+2]=P(S%19-9)*_;const j=t*4,O=new Uint8ClampedArray(j*n);for(f=0;f<n;f++)for(A=D*f/n,h=0;h<t;h++){for(m=0,p=0,l=0,u=D*h/t,d=0;d<s;d++)for(b=fe(A*d),c=0;c<r;c++)v=fe(u*c)*b,g=(c+d*r)*3,m+=I[g]*v,p+=I[g+1]*v,l+=I[g+2]*v;w=4*h+f*j,O[w]=F(m),O[w+1]=F(p),O[w+2]=F(l),O[w+3]=255}return O}const B=e=>{try{return new URL(e)}catch{return null}},et=(e,t)=>`rgba(${e.r},${e.g},${e.b},${t})`,H=e=>Fe||He?{"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}},N=(e,t=0)=>{const n=Math.pow(10,t);return Math.round(e*n)/n},rt=(e,t)=>{const n=B(e),o=B(t);return!n||!o?e:(o.pathname=n.pathname,o.search=n.search,o.toString())},ot=(e,t={},n=se,o=ie)=>{if(!e)return null;try{t.debug&&T("input imageSrc:",e);const i=ze(e);if(t.debug&&T("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 a=r.sourceWidth/r.sourceHeight,c=(t==null?void 0:t.size)??s.size??We,d=G[c];let h=0,f=0,m=0;if(a>=1){f=h=pe(d,r.sourceWidth);const g=N(f/a);m=N(f/g,6)}else h=pe(d,r.sourceHeight),f=N(h*a),m=N(f/h,6);const p=N(100/m,6),l={...r,arPaddingTop:`${p}%`,aspectRatio:m,maxWidth:f,src:e},v=B(r.url);if(v)l.src=v.toString();else if(!B(e)&&k(r.url)){const g=Me(r,{endpoint:t.endpoint,size:c});g&&(l.src=g)}t.endpoint&&(l.src=rt(l.src,t.endpoint));const b=r.bcc?nt(r.bcc):null;if(b&&(l.backgroundColor=et(b,n)),!ae&&r.blurhash&&!t.disableBlurLayer){const g=performance.now(),w=Qe(r.blurhash,U,U,o),A=performance.now()-g;t.debug&&T(`Blurhash decode time: ${N(A,1)} ms`),w&&(l.pixels=w)}return t.debug&&T("Visionary Image state: ",l),l}catch{return null}},he={bottom:0,left:0,position:"absolute",right:0,top:0},st={...he,maxHeight:"100%",maxWidth:"100%"},it={...he,height:"100%",width:"100%"},q={CANVAS:"canvas",CONTAINER:"container",IMAGE:"image"},M={container:"v7y_7587",hidden:"v7y_f2b7",preventDrag:"v7y_b8c0",preventSelection:"v7y_e0dd"},ct=({alt:e,bgColorAlpha:t=se,className:n,debug:o=!1,disableBlurLayer:i=!1,disableImageLayer:r=!1,endpoint:s,height:a,hideImageLayer:c,lazy:d=!0,onClick:h,onError:f,onLoad:m,preventDrag:p=!1,preventSelection:l=!1,punch:v=ie,size:b,src:g,style:w,width:A})=>{const u=x.useMemo(()=>ot(g,{debug:o,disableBlurLayer:i,endpoint:s,size:b},t,v),[t,o,i,s,v,b,g]),S=x.useRef(null),[_,I]=ve();qe(function(){if(!S.current||!(u!=null&&u.blurhash))return;if(!u.pixels){console.warn("No pixel data passed in, skipping");return}const ut=performance.now(),Z=S.current.getContext("2d");if(!Z){console.warn("Cannot access canvasRenderingContext, skipping");return}const J=Z.createImageData(U,U);if(!J){console.warn("Could not create ImageData on CanvasRenderingContext");return}if(J.data.set(u.pixels),Z.putImageData(J,0,0),o){const dt=performance.now()-ut;T(`Canvas render time: ${N(dt,1)} ms`)}},[u==null?void 0:u.blurhash,u==null?void 0:u.pixels,o]);const X=x.useCallback(V=>{o&&T("Image load error ",V),f&&f()},[o,f]),j={alt:e,loading:!d||I?"eager":"lazy",onLoad:m};if(!u){o&&T("Not a Visionary URL, rendering fallback <img />");const V={...j,className:n,height:a,onClick:h,onError:f,src:g,style:w,width:A};return R.jsx("img",{...V})}const O=Q(M.container,n,{[M.preventDrag]:!!p,[M.preventSelection]:!!l}),Y={...{"--v-ar":u.arPaddingTop},aspectRatio:u.aspectRatio,backgroundColor:(u==null?void 0:u.backgroundColor)??void 0,maxWidth:u.maxWidth,position:"relative",width:"100%",...w};A&&(Y.width=A),a&&(Y.height=a);const at={onClick:h},lt=Q({[M.hidden]:!!c});return R.jsxs("div",{className:O,ref:_,style:Y,...tt(u.url,o),...H(q.CONTAINER),...at,children:[!i&&R.jsx("canvas",{height:U,ref:S,style:it,width:U,...H(q.CANVAS)}),!r&&R.jsx("img",{...j,...H(q.IMAGE),className:lt,onError:X,src:u.src,style:st})]})};E.Image=ct,Object.defineProperty(E,Symbol.toStringTag,{value:"Module"})});
|
|
6
|
+
*/(function(t){(function(){var e={}.hasOwnProperty;function n(){for(var r="",s=0;s<arguments.length;s++){var a=arguments[s];a&&(r=i(r,o(a)))}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 a in r)e.call(r,a)&&r[a]&&(s=i(s,a));return s}function i(r,s){return s?r?r+" "+s:r+s:r}t.exports?(n.default=n,t.exports=n):window.classNames=n})()})(K);var gt=K.exports;const mt=ht(gt),bt=(t,{root:e,rootMargin:n,threshold:o}={},i=[])=>{const r=I.useRef(null),s=I.useRef(null);return I.useCallback(c=>{r.current&&s.current&&(s.current.unobserve(r.current),s.current.disconnect(),s.current=null),c&&(s.current=new IntersectionObserver(t,{root:e,rootMargin:n,threshold:o}),s.current.observe(c),r.current=c)},[r,e,n,JSON.stringify(o),...i])},yt=({root:t,rootMargin:e,threshold:n,unobserveOnEnter:o,target:i,onEnter:r,onLeave:s,defaultInView:a}={},c=[])=>{const[d,h]=I.useState({inView:a||!1,entry:null,observer:null}),f=I.useCallback(([p],l)=>{const b=l.thresholds.some(m=>p.intersectionRatio>=m)&&p.isIntersecting;h({inView:b,entry:p,observer:l}),b&&o&&(l.unobserve(p.target),l.disconnect()),b?r==null||r(p,l):s==null||s(p,l)},[r,s,o]),g=bt(f,{root:t,rootMargin:e,threshold:n},[o,...c]);return I.useEffect(()=>{i!=null&&i.current&&g(i.current)},[i,g]),[g,d.inView,d.entry,d.observer]};var $=(t=>(t.AUTO="auto",t.AVIF="avif",t.JPEG="jpeg",t.WEBP="webp",t))($||{}),v=(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||{}),C=(t=>(t.DEBUG="debug",t.DOWNLOAD="download",t))(C||{});const vt="https://link.visionary.cloud";$.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((t,e)=>{const n=e,o=M[n];return o&&(t[o]=n),t},{});const Q="!";var wt=Object.defineProperty,It=(t,e,n)=>e in t?wt(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n,xt=(t,e,n)=>It(t,typeof e!="symbol"?e+"":e,n),G={},L={};Object.defineProperty(L,"__esModule",{value:!0});function Et(t){return String.fromCharCode(parseInt(t.slice(1),16))}function Rt(t){return btoa(encodeURIComponent(t).replace(/%[0-9A-F]{2}/g,Et))}L.encode=Rt;function At(t){return`%${`00${t.charCodeAt(0).toString(16)}`.slice(-2)}`}function St(t){return decodeURIComponent(Array.from(atob(t),At).join(""))}L.decode=St,Object.defineProperty(G,"__esModule",{value:!0});const tt=L;function Tt(t){return tt.decode(t.replace(/\-/g,"+").replace(/_/g,"/"))}var Ot=G.decode=Tt;function Nt(t){return tt.encode(t).replace(/\//g,"_").replace(/\+/g,"-").replace(/=+$/,"")}var Ut=G.encode=Nt;const Ct=t=>t.filter(Boolean),et=t=>{try{return new URL(t)}catch{return null}},k=(t="")=>/^[A-Za-z0-9_-]*$/.test(t),Dt=t=>{const{altText:e,bcc:n,blurhash:o,blurhashX:i,blurhashY:r,sourceHeight:s,sourceWidth:a,url:c}=t;if(!c||!a||!s)return new Error("Cannot construct visionary code: missing required url/width/height");const d=[c,a,s];return!n||(d.push(n),!o||!i||!r)||(d.push(o,i,r),e&&e.length&&d.push(e)),Pt(d)},Pt=t=>Ut(t.join(Q)),nt=t=>{if(typeof t!="string")return null;const e=t.trim();if(!e.length||!k(e))return null;const n=Ot(e);if(!n)return null;const o=n.split(Q);if(o.length<3)return null;const[i,r,s,a,c,d,h,f]=o,g=i.trim();if(!g.length)return console.error("Cannot parse code, empty file id"),null;const p=Number(r.trim()),l=Number(s.trim());if(isNaN(p)||isNaN(l)||!p||!l)return console.error("Cannot parse Visionary Code: invalid image dimensions",r,s),null;const y=Number(d)??0,b=Number(h)??0;return y<1||b<1?(console.error("Cannot parse Visionary Code: invalid blurhash x, y component dimensions",y,b),null):{altText:f,bcc:a,blurhash:c,blurhashX:y,blurhashY:b,sourceHeight:l,sourceWidth:p,url:g}};class _t extends Error{constructor(){super(...arguments),xt(this,"message","invalid endpoint URL (does it contain http/https?)")}}const jt=t=>t===C.DEBUG,Vt=t=>t===C.DOWNLOAD,$t=t=>Object.values($).includes(t),rt=t=>Object.values(v).includes(t),Lt=(t=[])=>{const e={};for(const n of t)rt(n)?e.size=v[n]:jt(n)?e.debug=!0:Vt(n)?e.download=!0:$t(n)&&(e.format=n);return e},kt=t=>{if(!t||typeof t!="object")return null;const e=[];return t.debug&&e.push(C.DEBUG),t.download&&e.push(C.DOWNLOAD),t.format&&t.format!==$.AUTO&&e.push(t.format),t.size&&rt(t.size)&&e.push(t.size),e.length?e.sort().join(","):null},zt=t=>{if(k(t)){const e=nt(t);if(e)return{fields:e,options:{}}}return Bt(t)},Bt=t=>{if(!t)return null;const e=t.trim();if(!e)return null;try{const n=Gt(e);if(!n)return null;const{code:o,optionTokens:i}=n,r=nt(o);if(!r)return null;const s=Lt(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},Mt=(t,e)=>{const n=Dt(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 _t("Cannot construct URL: bad endpoint. Ensure endpoint starts with http:// or https://");o||(o=et(vt));const i=[o.origin,"image",n],r=e?kt(e):null;return r&&i.push(r),e!=null&&e.filename?i.push(e.filename):i.push("image.jpg"),i.join("/")},Gt=t=>{try{const e=new URL(t),n=Ct(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||!k(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},ot=.7,st=1,U=24,Wt=v.lg,it=process.env.NODE_ENV,Ft=it==="development",ct=typeof document>"u",Ht=it==="test",qt=ct?()=>{}:I.useLayoutEffect,Xt="<visionary>",T=(t,...e)=>{!console||typeof console.log!="function"||console.log(`${Xt} ${t}`,...e)},Yt="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz#$%*+,-.:;=?@[]^_{|}~",z=(t,e,n)=>{let o=0;for(;e<n;)o*=83,o+=Yt.indexOf(t[e++]);return o},at=Math.pow,D=Math.PI,Zt=D*2,lt=3294.6,ut=269.025,Jt=t=>t>10.31475?at(t/ut+.052132,2.4):t/lt,W=t=>~~(t>1227e-8?ut*at(t,.416666)-13.025:t*lt+1),P=t=>(t<0?-1:1)*t*t,dt=t=>{for(t+=D/2;t>D;)t-=Zt;const e=1.27323954*t-.405284735*P(t);return .225*(P(e)-e)+e};function Kt(t){const e=z(t,2,6);return[e>>16,e>>8&255,e&255]}function Qt(t,e,n,o){const i=z(t,0,1),r=i%9+1,s=~~(i/9)+1,a=r*s;let c=0,d=0,h=0,f=0,g=0,p=0,l=0,y=0,b=0,m=0,w=0,A=0,u=0,S=0;const _=(z(t,1,2)+1)/13446*(o|1),x=new Float64Array(a*3),X=Kt(t);for(c=0;c<3;c++)x[c]=Jt(X[c]);for(c=1;c<a;c++)S=z(t,4+c*2,6+c*2),x[c*3]=P(~~(S/(19*19))-9)*_,x[c*3+1]=P(~~(S/19)%19-9)*_,x[c*3+2]=P(S%19-9)*_;const j=e*4,N=new Uint8ClampedArray(j*n);for(f=0;f<n;f++)for(A=D*f/n,h=0;h<e;h++){for(g=0,p=0,l=0,u=D*h/e,d=0;d<s;d++)for(b=dt(A*d),c=0;c<r;c++)y=dt(u*c)*b,m=(c+d*r)*3,g+=x[m]*y,p+=x[m+1]*y,l+=x[m+2]*y;w=4*h+f*j,N[w]=W(g),N[w+1]=W(p),N[w+2]=W(l),N[w+3]=255}return N}const B=t=>{try{return new URL(t)}catch{return null}},te=(t,e)=>`rgba(${t.r},${t.g},${t.b},${e})`,F=t=>Ft||Ht?{"data-testid":t}:{},ee=(t,e)=>e?{"data-fileid":t}:{},ft=(t,e)=>Math.min(t,e),ne=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}},O=(t,e=0)=>{const n=Math.pow(10,e);return Math.round(t*n)/n},re=(t,e)=>{const n=B(t),o=B(e);return!n||!o?t:(o.pathname=n.pathname,o.search=n.search,o.toString())},oe=(t,e={},n=ot,o=st)=>{if(!t)return null;try{e.debug&&T("input imageSrc:",t);const i=zt(t);if(e.debug&&T("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 a=r.sourceWidth/r.sourceHeight,c=(e==null?void 0:e.size)??s.size??Wt,d=M[c];let h=0,f=0,g=0;if(a>=1){f=h=ft(d,r.sourceWidth);const m=O(f/a);g=O(f/m,6)}else h=ft(d,r.sourceHeight),f=O(h*a),g=O(f/h,6);const p=O(100/g,6),l={...r,arPaddingTop:`${p}%`,aspectRatio:g,maxWidth:f,src:t},y=B(r.url);if(y)l.src=y.toString();else if(!B(t)&&k(r.url)){const m=Mt(r,{endpoint:e.endpoint,size:c});m&&(l.src=m)}e.endpoint&&(l.src=re(l.src,e.endpoint));const b=r.bcc?ne(r.bcc):null;if(b&&(l.backgroundColor=te(b,n)),!ct&&r.blurhash&&!e.disableBlurLayer){const m=performance.now(),w=Qt(r.blurhash,U,U,o),A=performance.now()-m;e.debug&&T(`Blurhash decode time: ${O(A,1)} ms`),w&&(l.pixels=w)}return e.debug&&T("Visionary Image state: ",l),l}catch{return null}},pt={bottom:0,left:0,position:"absolute",right:0,top:0},se={...pt,maxHeight:"100%",maxWidth:"100%"},ie={...pt,height:"100%",width:"100%"},ce=t=>{const e={...se};return t&&(e.display="none"),e},H={CANVAS:"canvas",CONTAINER:"container",IMAGE:"image"},q={container:"v7y_7587",preventDrag:"v7y_b8c0",preventSelection:"v7y_e0dd"},ae=({alt:t,bgColorAlpha:e=ot,className:n,debug:o=!1,disableBlurLayer:i=!1,disableImageLayer:r=!1,endpoint:s,height:a,hideImageLayer:c=!1,lazy:d=!0,onClick:h,onError:f,onLoad:g,preventDrag:p=!1,preventSelection:l=!1,punch:y=st,size:b,src:m,style:w,width:A})=>{const u=I.useMemo(()=>oe(m,{debug:o,disableBlurLayer:i,endpoint:s,size:b},e,y),[e,o,i,s,y,b,m]),S=I.useRef(null),[_,x]=yt();qt(function(){if(!S.current||!(u!=null&&u.blurhash))return;if(!u.pixels){console.warn("No pixel data passed in, skipping");return}const de=performance.now(),Z=S.current.getContext("2d");if(!Z){console.warn("Cannot access canvasRenderingContext, skipping");return}const J=Z.createImageData(U,U);if(!J){console.warn("Could not create ImageData on CanvasRenderingContext");return}if(J.data.set(u.pixels),Z.putImageData(J,0,0),o){const fe=performance.now()-de;T(`Canvas render time: ${O(fe,1)} ms`)}},[u==null?void 0:u.blurhash,u==null?void 0:u.pixels,o]);const X=I.useCallback(V=>{o&&T("Image load error ",V),f&&f()},[o,f]),j={alt:t,loading:!d||x?"eager":"lazy",onLoad:g};if(!u){o&&T("Not a Visionary URL, rendering fallback <img />");const V={...j,className:n,height:a,onClick:h,onError:f,src:m,style:w,width:A};return R.jsx("img",{...V})}const N=mt(q.container,n,{[q.preventDrag]:!!p,[q.preventSelection]:!!l}),Y={...{"--v-ar":u.arPaddingTop},aspectRatio:u.aspectRatio,backgroundColor:(u==null?void 0:u.backgroundColor)??void 0,maxWidth:u.maxWidth,position:"relative",width:"100%",...w};A&&(Y.width=A),a&&(Y.height=a);const le={onClick:h},ue=ce(c);return R.jsxs("div",{className:N,ref:_,style:Y,...ee(u.url,o),...F(H.CONTAINER),...le,children:[!i&&R.jsx("canvas",{height:U,ref:S,style:ie,width:U,...F(H.CANVAS)}),!r&&R.jsx("img",{...j,...F(H.IMAGE),onError:X,src:u.src,style:ue})]})};E.Image=ae,Object.defineProperty(E,Symbol.toStringTag,{value:"Module"})});
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
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.1",
|
|
4
5
|
"type": "module",
|
|
5
6
|
"main": "./dist/visionary-image.umd.js",
|
|
6
7
|
"module": "./dist/visionary-image.es.js",
|
|
@@ -85,12 +86,13 @@
|
|
|
85
86
|
"core-web-vitals",
|
|
86
87
|
"fid",
|
|
87
88
|
"image",
|
|
88
|
-
"
|
|
89
|
+
"inp",
|
|
89
90
|
"performance",
|
|
90
91
|
"placeholder",
|
|
91
92
|
"react",
|
|
92
93
|
"seo",
|
|
93
94
|
"speed",
|
|
95
|
+
"typescript",
|
|
94
96
|
"visionary",
|
|
95
97
|
"web-vitals"
|
|
96
98
|
]
|