visionary-image 1.0.1 → 1.0.3
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 +299 -285
- package/dist/visionary-image.umd.js +2 -2
- package/package.json +6 -5
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
|
-
 
|
|
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,7 +1,7 @@
|
|
|
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
|
|
4
|
-
function
|
|
2
|
+
import { jsx as T, jsxs as wt } from "react/jsx-runtime";
|
|
3
|
+
import { useRef as Y, useCallback as q, useState as It, useEffect as Et, useLayoutEffect as Rt, useMemo as At } from "react";
|
|
4
|
+
function xt(t) {
|
|
5
5
|
return t && t.__esModule && Object.prototype.hasOwnProperty.call(t, "default") ? t.default : t;
|
|
6
6
|
}
|
|
7
7
|
var et = { exports: {} };
|
|
@@ -12,11 +12,11 @@ var et = { exports: {} };
|
|
|
12
12
|
*/
|
|
13
13
|
(function(t) {
|
|
14
14
|
(function() {
|
|
15
|
-
var
|
|
16
|
-
function
|
|
15
|
+
var n = {}.hasOwnProperty;
|
|
16
|
+
function e() {
|
|
17
17
|
for (var r = "", s = 0; s < arguments.length; s++) {
|
|
18
|
-
var
|
|
19
|
-
|
|
18
|
+
var u = arguments[s];
|
|
19
|
+
u && (r = i(r, o(u)));
|
|
20
20
|
}
|
|
21
21
|
return r;
|
|
22
22
|
}
|
|
@@ -26,212 +26,214 @@ var et = { exports: {} };
|
|
|
26
26
|
if (typeof r != "object")
|
|
27
27
|
return "";
|
|
28
28
|
if (Array.isArray(r))
|
|
29
|
-
return
|
|
29
|
+
return e.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
|
-
for (var
|
|
34
|
-
|
|
33
|
+
for (var u in r)
|
|
34
|
+
n.call(r, u) && r[u] && (s = i(s, u));
|
|
35
35
|
return s;
|
|
36
36
|
}
|
|
37
|
-
function
|
|
37
|
+
function i(r, s) {
|
|
38
38
|
return s ? r ? r + " " + s : r + s : r;
|
|
39
39
|
}
|
|
40
|
-
t.exports ? (
|
|
40
|
+
t.exports ? (e.default = e, t.exports = e) : window.classNames = e;
|
|
41
41
|
})();
|
|
42
42
|
})(et);
|
|
43
|
-
var
|
|
44
|
-
const
|
|
43
|
+
var Ut = et.exports;
|
|
44
|
+
const Nt = /* @__PURE__ */ xt(Ut), Ot = (t, { root: n, rootMargin: e, threshold: o } = {}, i = []) => {
|
|
45
45
|
const r = Y(null), s = Y(null);
|
|
46
|
-
return q((
|
|
47
|
-
r.current && s.current && (s.current.unobserve(r.current), s.current.disconnect(), s.current = null),
|
|
48
|
-
}, [r,
|
|
49
|
-
},
|
|
50
|
-
const [
|
|
51
|
-
inView:
|
|
46
|
+
return q((c) => {
|
|
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
|
+
}, [r, n, e, JSON.stringify(o), ...i]);
|
|
49
|
+
}, Tt = ({ root: t, rootMargin: n, threshold: e, unobserveOnEnter: o, target: i, onEnter: r, onLeave: s, defaultInView: u } = {}, c = []) => {
|
|
50
|
+
const [a, p] = It({
|
|
51
|
+
inView: u || !1,
|
|
52
52
|
entry: null,
|
|
53
53
|
observer: null
|
|
54
|
-
}),
|
|
55
|
-
const b =
|
|
56
|
-
|
|
54
|
+
}), l = q(([h], d) => {
|
|
55
|
+
const b = d.thresholds.some((g) => h.intersectionRatio >= g) && h.isIntersecting;
|
|
56
|
+
p({
|
|
57
57
|
inView: b,
|
|
58
|
-
entry:
|
|
59
|
-
observer:
|
|
60
|
-
}), b && o && (
|
|
61
|
-
}, [r, s, o]), m =
|
|
62
|
-
return
|
|
63
|
-
|
|
64
|
-
}, [
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
58
|
+
entry: h,
|
|
59
|
+
observer: d
|
|
60
|
+
}), b && o && (d.unobserve(h.target), d.disconnect()), b ? r == null || r(h, d) : s == null || s(h, d);
|
|
61
|
+
}, [r, s, o]), m = Ot(l, { root: t, rootMargin: n, threshold: e }, [o, ...c]);
|
|
62
|
+
return Et(() => {
|
|
63
|
+
i != null && i.current && m(i.current);
|
|
64
|
+
}, [i, m]), [m, a.inView, a.entry, a.observer];
|
|
65
|
+
}, Ct = {
|
|
66
|
+
overflow: "hidden"
|
|
67
|
+
}, Dt = ({ aspectRatio: t, children: n }) => /* @__PURE__ */ T("div", { style: { aspectRatio: t, ...Ct }, children: n });
|
|
68
|
+
var $ = /* @__PURE__ */ ((t) => (t.AUTO = "auto", t.AVIF = "avif", t.JPEG = "jpeg", t.WEBP = "webp", t))($ || {}), w = /* @__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))(w || {}), D = /* @__PURE__ */ ((t) => (t.DEBUG = "debug", t.DOWNLOAD = "download", t))(D || {});
|
|
69
|
+
const Pt = "https://link.visionary.cloud";
|
|
70
|
+
$.AUTO, w.lg;
|
|
69
71
|
const Z = {
|
|
70
|
-
[
|
|
71
|
-
[
|
|
72
|
-
[
|
|
73
|
-
[
|
|
74
|
-
[
|
|
75
|
-
[
|
|
76
|
-
[
|
|
77
|
-
[
|
|
78
|
-
[
|
|
72
|
+
[w.xs]: 160,
|
|
73
|
+
[w.sm]: 320,
|
|
74
|
+
[w.md]: 640,
|
|
75
|
+
[w.lg]: 1280,
|
|
76
|
+
[w.xl]: 1920,
|
|
77
|
+
[w.xxl]: 2560,
|
|
78
|
+
[w["4k"]]: 3840,
|
|
79
|
+
[w["5k"]]: 5120,
|
|
80
|
+
[w.full]: 0
|
|
79
81
|
};
|
|
80
82
|
Object.keys(Z).reduce(
|
|
81
|
-
(t,
|
|
82
|
-
const
|
|
83
|
-
return o && (t[o] =
|
|
83
|
+
(t, n) => {
|
|
84
|
+
const e = n, o = Z[e];
|
|
85
|
+
return o && (t[o] = e), t;
|
|
84
86
|
},
|
|
85
87
|
{}
|
|
86
88
|
);
|
|
87
|
-
const
|
|
88
|
-
var
|
|
89
|
-
Object.defineProperty(
|
|
90
|
-
function
|
|
89
|
+
const rt = "!";
|
|
90
|
+
var St = Object.defineProperty, _t = (t, n, e) => n in t ? St(t, n, { enumerable: !0, configurable: !0, writable: !0, value: e }) : t[n] = e, Lt = (t, n, e) => _t(t, typeof n != "symbol" ? n + "" : n, e), J = {}, j = {};
|
|
91
|
+
Object.defineProperty(j, "__esModule", { value: !0 });
|
|
92
|
+
function Vt(t) {
|
|
91
93
|
return String.fromCharCode(parseInt(t.slice(1), 16));
|
|
92
94
|
}
|
|
93
|
-
function
|
|
94
|
-
return btoa(encodeURIComponent(t).replace(/%[0-9A-F]{2}/g,
|
|
95
|
+
function $t(t) {
|
|
96
|
+
return btoa(encodeURIComponent(t).replace(/%[0-9A-F]{2}/g, Vt));
|
|
95
97
|
}
|
|
96
|
-
|
|
97
|
-
function
|
|
98
|
+
j.encode = $t;
|
|
99
|
+
function jt(t) {
|
|
98
100
|
return `%${`00${t.charCodeAt(0).toString(16)}`.slice(-2)}`;
|
|
99
101
|
}
|
|
100
|
-
function
|
|
101
|
-
return decodeURIComponent(Array.from(atob(t),
|
|
102
|
+
function kt(t) {
|
|
103
|
+
return decodeURIComponent(Array.from(atob(t), jt).join(""));
|
|
102
104
|
}
|
|
103
|
-
|
|
105
|
+
j.decode = kt;
|
|
104
106
|
Object.defineProperty(J, "__esModule", { value: !0 });
|
|
105
|
-
const
|
|
106
|
-
function
|
|
107
|
-
return
|
|
107
|
+
const ot = j;
|
|
108
|
+
function zt(t) {
|
|
109
|
+
return ot.decode(t.replace(/\-/g, "+").replace(/_/g, "/"));
|
|
108
110
|
}
|
|
109
|
-
var
|
|
110
|
-
function
|
|
111
|
-
return
|
|
111
|
+
var Bt = J.decode = zt;
|
|
112
|
+
function Mt(t) {
|
|
113
|
+
return ot.encode(t).replace(/\//g, "_").replace(/\+/g, "-").replace(/=+$/, "");
|
|
112
114
|
}
|
|
113
|
-
var
|
|
114
|
-
const
|
|
115
|
+
var Wt = J.encode = Mt;
|
|
116
|
+
const Gt = (t) => t.filter(Boolean), Q = (t) => {
|
|
115
117
|
try {
|
|
116
118
|
return new URL(t);
|
|
117
119
|
} catch {
|
|
118
120
|
return null;
|
|
119
121
|
}
|
|
120
|
-
},
|
|
121
|
-
const { altText:
|
|
122
|
-
if (!
|
|
122
|
+
}, k = (t = "") => /^[A-Za-z0-9_-]*$/.test(t), Ft = (t) => {
|
|
123
|
+
const { altText: n, bcc: e, blurhash: o, blurhashX: i, blurhashY: r, sourceHeight: s, sourceWidth: u, url: c } = t;
|
|
124
|
+
if (!c || !u || !s)
|
|
123
125
|
return new Error("Cannot construct visionary code: missing required url/width/height");
|
|
124
|
-
const
|
|
125
|
-
return !
|
|
126
|
-
},
|
|
126
|
+
const a = [c, u, s];
|
|
127
|
+
return !e || (a.push(e), !o || !i || !r) || (a.push(o, i, r), n && n.length && a.push(n)), Ht(a);
|
|
128
|
+
}, Ht = (t) => Wt(t.join(rt)), st = (t) => {
|
|
127
129
|
if (typeof t != "string")
|
|
128
130
|
return null;
|
|
129
|
-
const
|
|
130
|
-
if (!
|
|
131
|
+
const n = t.trim();
|
|
132
|
+
if (!n.length || !k(n))
|
|
131
133
|
return null;
|
|
132
|
-
const
|
|
133
|
-
if (!
|
|
134
|
+
const e = Bt(n);
|
|
135
|
+
if (!e)
|
|
134
136
|
return null;
|
|
135
|
-
const o =
|
|
137
|
+
const o = e.split(rt);
|
|
136
138
|
if (o.length < 3)
|
|
137
139
|
return null;
|
|
138
|
-
const [
|
|
140
|
+
const [i, r, s, u, c, a, p, l] = o, m = i.trim();
|
|
139
141
|
if (!m.length)
|
|
140
142
|
return console.error("Cannot parse code, empty file id"), null;
|
|
141
|
-
const
|
|
142
|
-
if (isNaN(
|
|
143
|
+
const h = Number(r.trim()), d = Number(s.trim());
|
|
144
|
+
if (isNaN(h) || isNaN(d) || !h || !d)
|
|
143
145
|
return console.error("Cannot parse Visionary Code: invalid image dimensions", r, s), null;
|
|
144
|
-
const v = Number(
|
|
146
|
+
const v = Number(a) ?? 0, b = Number(p) ?? 0;
|
|
145
147
|
return v < 1 || b < 1 ? (console.error(
|
|
146
148
|
"Cannot parse Visionary Code: invalid blurhash x, y component dimensions",
|
|
147
149
|
v,
|
|
148
150
|
b
|
|
149
151
|
), null) : {
|
|
150
|
-
altText:
|
|
151
|
-
bcc:
|
|
152
|
-
blurhash:
|
|
152
|
+
altText: l,
|
|
153
|
+
bcc: u,
|
|
154
|
+
blurhash: c,
|
|
153
155
|
blurhashX: v,
|
|
154
156
|
blurhashY: b,
|
|
155
|
-
sourceHeight:
|
|
156
|
-
sourceWidth:
|
|
157
|
+
sourceHeight: d,
|
|
158
|
+
sourceWidth: h,
|
|
157
159
|
url: m
|
|
158
160
|
};
|
|
159
161
|
};
|
|
160
|
-
class
|
|
162
|
+
class Xt extends Error {
|
|
161
163
|
constructor() {
|
|
162
|
-
super(...arguments),
|
|
164
|
+
super(...arguments), Lt(this, "message", "invalid endpoint URL (does it contain http/https?)");
|
|
163
165
|
}
|
|
164
166
|
}
|
|
165
|
-
const
|
|
166
|
-
const
|
|
167
|
-
for (const
|
|
168
|
-
|
|
169
|
-
return
|
|
170
|
-
},
|
|
167
|
+
const Yt = (t) => t === D.DEBUG, Zt = (t) => t === D.DOWNLOAD, qt = (t) => Object.values($).includes(t), ct = (t) => Object.values(w).includes(t), Jt = (t = []) => {
|
|
168
|
+
const n = {};
|
|
169
|
+
for (const e of t)
|
|
170
|
+
ct(e) ? n.size = w[e] : Yt(e) ? n.debug = !0 : Zt(e) ? n.download = !0 : qt(e) && (n.format = e);
|
|
171
|
+
return n;
|
|
172
|
+
}, Kt = (t) => {
|
|
171
173
|
if (!t || typeof t != "object")
|
|
172
174
|
return null;
|
|
173
|
-
const
|
|
174
|
-
return t.debug &&
|
|
175
|
-
},
|
|
176
|
-
if (
|
|
177
|
-
const
|
|
178
|
-
if (
|
|
175
|
+
const n = [];
|
|
176
|
+
return t.debug && n.push(D.DEBUG), t.download && n.push(D.DOWNLOAD), t.format && t.format !== $.AUTO && n.push(t.format), t.size && ct(t.size) && n.push(t.size), n.length ? n.sort().join(",") : null;
|
|
177
|
+
}, Qt = (t) => {
|
|
178
|
+
if (k(t)) {
|
|
179
|
+
const n = st(t);
|
|
180
|
+
if (n)
|
|
179
181
|
return {
|
|
180
|
-
fields:
|
|
182
|
+
fields: n,
|
|
181
183
|
options: {}
|
|
182
184
|
};
|
|
183
185
|
}
|
|
184
|
-
return
|
|
185
|
-
},
|
|
186
|
+
return tn(t);
|
|
187
|
+
}, tn = (t) => {
|
|
186
188
|
if (!t)
|
|
187
189
|
return null;
|
|
188
|
-
const
|
|
189
|
-
if (!
|
|
190
|
+
const n = t.trim();
|
|
191
|
+
if (!n)
|
|
190
192
|
return null;
|
|
191
193
|
try {
|
|
192
|
-
const
|
|
193
|
-
if (!
|
|
194
|
+
const e = en(n);
|
|
195
|
+
if (!e)
|
|
194
196
|
return null;
|
|
195
|
-
const { code: o, optionTokens:
|
|
197
|
+
const { code: o, optionTokens: i } = e, r = st(o);
|
|
196
198
|
if (!r)
|
|
197
199
|
return null;
|
|
198
|
-
const s =
|
|
200
|
+
const s = Jt(i);
|
|
199
201
|
return {
|
|
200
202
|
fields: r,
|
|
201
203
|
options: s
|
|
202
204
|
};
|
|
203
|
-
} catch (
|
|
204
|
-
|
|
205
|
+
} catch (e) {
|
|
206
|
+
e instanceof Error ? console.error(`Error parsing URL: ${e.message}`, e) : console.error("uncaught error", e);
|
|
205
207
|
}
|
|
206
208
|
return null;
|
|
207
|
-
},
|
|
208
|
-
const
|
|
209
|
-
if (
|
|
209
|
+
}, nn = (t, n) => {
|
|
210
|
+
const e = Ft(t);
|
|
211
|
+
if (e instanceof Error)
|
|
210
212
|
return null;
|
|
211
213
|
let o = null;
|
|
212
|
-
if (
|
|
213
|
-
throw new
|
|
214
|
+
if (n != null && n.endpoint && (o = Q(n == null ? void 0 : n.endpoint), !o))
|
|
215
|
+
throw new Xt(
|
|
214
216
|
"Cannot construct URL: bad endpoint. Ensure endpoint starts with http:// or https://"
|
|
215
217
|
);
|
|
216
|
-
o || (o =
|
|
217
|
-
const
|
|
218
|
-
return r &&
|
|
219
|
-
},
|
|
218
|
+
o || (o = Q(Pt));
|
|
219
|
+
const i = [o.origin, "image", e], r = n ? Kt(n) : null;
|
|
220
|
+
return r && i.push(r), n != null && n.filename ? i.push(n.filename) : i.push("image.jpg"), i.join("/");
|
|
221
|
+
}, en = (t) => {
|
|
220
222
|
try {
|
|
221
|
-
const
|
|
222
|
-
if (
|
|
223
|
+
const n = new URL(t), e = Gt(n.pathname.split("/"));
|
|
224
|
+
if (e[0] !== "image" || ![3, 4].includes(e.length))
|
|
223
225
|
throw new Error("Unrecognized URL");
|
|
224
|
-
const o =
|
|
225
|
-
if (!o.length || !
|
|
226
|
+
const o = e[1].trim();
|
|
227
|
+
if (!o.length || !k(o))
|
|
226
228
|
throw new Error("URL is not formatted as base64url");
|
|
227
|
-
if (
|
|
228
|
-
const
|
|
229
|
+
if (e.length === 4) {
|
|
230
|
+
const i = e[2].split(",");
|
|
229
231
|
return {
|
|
230
232
|
code: o,
|
|
231
|
-
optionTokens:
|
|
233
|
+
optionTokens: i
|
|
232
234
|
};
|
|
233
235
|
}
|
|
234
|
-
if (
|
|
236
|
+
if (e.length === 3)
|
|
235
237
|
return {
|
|
236
238
|
code: o,
|
|
237
239
|
optionTokens: []
|
|
@@ -240,39 +242,51 @@ const Wt = (t) => t === P.DEBUG, Ft = (t) => t === P.DOWNLOAD, Ht = (t) => Objec
|
|
|
240
242
|
return null;
|
|
241
243
|
}
|
|
242
244
|
return null;
|
|
243
|
-
},
|
|
244
|
-
} :
|
|
245
|
-
!console || typeof console.log != "function" || console.log(`${
|
|
246
|
-
},
|
|
245
|
+
}, it = 0.7, at = 1, U = 24, rn = w.lg, lt = process.env.NODE_ENV, on = lt === "development", ut = typeof document > "u", sn = lt === "test", cn = ut ? () => {
|
|
246
|
+
} : Rt, an = "<visionary>", x = (t, ...n) => {
|
|
247
|
+
!console || typeof console.log != "function" || console.log(`${an} ${t}`, ...n);
|
|
248
|
+
}, dt = new Uint8Array(128);
|
|
249
|
+
for (let t = 0; t < 83; t++)
|
|
250
|
+
dt["0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz#$%*+,-.:;=?@[]^_{|}~".charCodeAt(
|
|
251
|
+
t
|
|
252
|
+
)] = t;
|
|
253
|
+
const L = (t, n, e) => {
|
|
247
254
|
let o = 0;
|
|
248
|
-
for (;
|
|
249
|
-
o *= 83, o +=
|
|
255
|
+
for (; n < e; )
|
|
256
|
+
o *= 83, o += dt[t.charCodeAt(n++)];
|
|
250
257
|
return o;
|
|
251
|
-
},
|
|
252
|
-
for (t +=
|
|
253
|
-
t -=
|
|
254
|
-
const
|
|
255
|
-
return 0.225 * (
|
|
258
|
+
}, ft = Math.pow, P = Math.PI, ln = P * 2, pt = 3294.6, ht = 269.025, un = (t) => t > 10.31475 ? ft(t / ht + 0.052132, 2.4) : t / pt, G = (t) => ~~(t > 1227e-8 ? ht * ft(t, 0.416666) - 13.025 : t * pt + 1), C = (t) => (t < 0 ? -1 : 1) * t * t, tt = (t) => {
|
|
259
|
+
for (t += P / 2; t > P; )
|
|
260
|
+
t -= ln;
|
|
261
|
+
const n = 1.27323954 * t - 0.405284735 * C(t);
|
|
262
|
+
return 0.225 * (C(n) - n) + n;
|
|
256
263
|
};
|
|
257
|
-
function
|
|
258
|
-
const
|
|
259
|
-
return [
|
|
264
|
+
function dn(t) {
|
|
265
|
+
const n = L(t, 2, 6);
|
|
266
|
+
return [n >> 16, n >> 8 & 255, n & 255];
|
|
260
267
|
}
|
|
261
|
-
function
|
|
262
|
-
const
|
|
263
|
-
let
|
|
264
|
-
const
|
|
265
|
-
for (
|
|
266
|
-
I[
|
|
267
|
-
for (
|
|
268
|
-
E =
|
|
269
|
-
const
|
|
270
|
-
for (
|
|
271
|
-
for (
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
268
|
+
function fn(t, n, e, o) {
|
|
269
|
+
const i = L(t, 0, 1), r = i % 9 + 1, s = ~~(i / 9) + 1, u = r * s;
|
|
270
|
+
let c = 0, a = 0, p = 0, l = 0, m = 0, h = 0, d = 0, v = 0, b = 0, g = 0, y = 0, E = 0;
|
|
271
|
+
const f = (L(t, 1, 2) + 1) / 13446 * (o | 1), I = new Float64Array(u * 3), z = dn(t);
|
|
272
|
+
for (c = 0; c < 3; c++)
|
|
273
|
+
I[c] = un(z[c]);
|
|
274
|
+
for (c = 1; c < u; c++)
|
|
275
|
+
E = L(t, 4 + c * 2, 6 + c * 2), I[c * 3] = C(~~(E / 361) - 9) * f, I[c * 3 + 1] = C(~~(E / 19) % 19 - 9) * f, I[c * 3 + 2] = C(E % 19 - 9) * f;
|
|
276
|
+
const S = new Float64Array(s * e), _ = new Float64Array(r * n);
|
|
277
|
+
for (a = 0; a < s; a++)
|
|
278
|
+
for (l = 0; l < e; l++)
|
|
279
|
+
S[a * e + l] = tt(P * l * a / e);
|
|
280
|
+
for (c = 0; c < r; c++)
|
|
281
|
+
for (p = 0; p < n; p++)
|
|
282
|
+
_[c * n + p] = tt(P * p * c / n);
|
|
283
|
+
const N = n * 4, R = new Uint8ClampedArray(N * e);
|
|
284
|
+
for (l = 0; l < e; l++)
|
|
285
|
+
for (p = 0; p < n; p++) {
|
|
286
|
+
for (m = h = d = 0, a = 0; a < s; a++)
|
|
287
|
+
for (b = S[a * e + l], c = 0; c < r; c++)
|
|
288
|
+
v = _[c * n + p] * b, g = (c + a * r) * 3, m += I[g] * v, h += I[g + 1] * v, d += I[g + 2] * v;
|
|
289
|
+
y = 4 * p + l * N, R[y] = G(m), R[y + 1] = G(h), R[y + 2] = G(d), R[y + 3] = 255;
|
|
276
290
|
}
|
|
277
291
|
return R;
|
|
278
292
|
}
|
|
@@ -282,225 +296,225 @@ const V = (t) => {
|
|
|
282
296
|
} catch {
|
|
283
297
|
return null;
|
|
284
298
|
}
|
|
285
|
-
},
|
|
299
|
+
}, pn = (t, n) => `rgba(${t.r},${t.g},${t.b},${n})`, F = (t) => on || sn ? {
|
|
286
300
|
"data-testid": t
|
|
287
|
-
} : {},
|
|
301
|
+
} : {}, hn = (t, n) => n ? {
|
|
288
302
|
"data-fileid": t
|
|
289
|
-
} : {},
|
|
290
|
-
let
|
|
291
|
-
if (
|
|
303
|
+
} : {}, nt = (t, n) => Math.min(t, n), mn = (t) => {
|
|
304
|
+
let n = t.replace(/^#/, "");
|
|
305
|
+
if (n.length !== 3 && n.length !== 6)
|
|
292
306
|
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
|
-
},
|
|
307
|
+
n.length === 3 && (n = `${n[0]}${n[0]}${n[1]}${n[1]}${n[2]}${n[2]}`);
|
|
308
|
+
const e = parseInt(n.slice(0, 2), 16), o = parseInt(n.slice(2, 4), 16);
|
|
309
|
+
return { b: parseInt(n.slice(4, 6), 16), g: o, r: e };
|
|
310
|
+
}, A = (t, n = 0) => {
|
|
311
|
+
const e = Math.pow(10, n);
|
|
312
|
+
return Math.round(t * e) / e;
|
|
313
|
+
}, gn = (t, n) => {
|
|
314
|
+
const e = V(t), o = V(n);
|
|
315
|
+
return !e || !o ? t : (o.pathname = e.pathname, o.search = e.search, o.toString());
|
|
316
|
+
}, bn = (t, n = {}, e = it, o = at) => {
|
|
303
317
|
if (!t)
|
|
304
318
|
return null;
|
|
305
319
|
try {
|
|
306
|
-
|
|
307
|
-
const
|
|
308
|
-
if (
|
|
320
|
+
n.debug && x("input imageSrc:", t);
|
|
321
|
+
const i = Qt(t);
|
|
322
|
+
if (n.debug && x("Visionary URL data: ", i), !i)
|
|
309
323
|
throw new Error("Could not parse Visionary URL");
|
|
310
|
-
const { fields: r, options: s } =
|
|
324
|
+
const { fields: r, options: s } = i;
|
|
311
325
|
if (r.sourceWidth < 1 || r.sourceHeight < 1)
|
|
312
326
|
throw new Error("Invalid image dimensions");
|
|
313
|
-
const
|
|
314
|
-
let
|
|
315
|
-
if (
|
|
316
|
-
|
|
317
|
-
const g = A(
|
|
318
|
-
m = A(
|
|
327
|
+
const u = r.sourceWidth / r.sourceHeight, c = (n == null ? void 0 : n.size) ?? s.size ?? rn, a = Z[c];
|
|
328
|
+
let p = 0, l = 0, m = 0;
|
|
329
|
+
if (u >= 1) {
|
|
330
|
+
l = p = nt(a, r.sourceWidth);
|
|
331
|
+
const g = A(l / u);
|
|
332
|
+
m = A(l / g, 6);
|
|
319
333
|
} else
|
|
320
|
-
|
|
321
|
-
const
|
|
334
|
+
p = nt(a, r.sourceHeight), l = A(p * u), m = A(l / p, 6);
|
|
335
|
+
const h = A(100 / m, 6), d = {
|
|
322
336
|
...r,
|
|
323
|
-
arPaddingTop: `${
|
|
337
|
+
arPaddingTop: `${h}%`,
|
|
324
338
|
aspectRatio: m,
|
|
325
|
-
maxWidth:
|
|
339
|
+
maxWidth: l,
|
|
326
340
|
src: t
|
|
327
341
|
}, v = V(r.url);
|
|
328
342
|
if (v)
|
|
329
|
-
|
|
330
|
-
else if (!V(t) &&
|
|
331
|
-
const g =
|
|
332
|
-
endpoint:
|
|
333
|
-
size:
|
|
343
|
+
d.src = v.toString();
|
|
344
|
+
else if (!V(t) && k(r.url)) {
|
|
345
|
+
const g = nn(r, {
|
|
346
|
+
endpoint: n.endpoint,
|
|
347
|
+
size: c
|
|
334
348
|
});
|
|
335
|
-
g && (
|
|
349
|
+
g && (d.src = g);
|
|
336
350
|
}
|
|
337
|
-
|
|
338
|
-
const b = r.bcc ?
|
|
339
|
-
if (b && (
|
|
340
|
-
const g = performance.now(),
|
|
341
|
-
|
|
351
|
+
n.endpoint && (d.src = gn(d.src, n.endpoint));
|
|
352
|
+
const b = r.bcc ? mn(r.bcc) : null;
|
|
353
|
+
if (b && (d.backgroundColor = pn(b, e)), !ut && r.blurhash && !n.disableBlurLayer) {
|
|
354
|
+
const g = performance.now(), y = fn(r.blurhash, U, U, o), E = performance.now() - g;
|
|
355
|
+
n.debug && x(`Blurhash decode time: ${A(E, 1)} ms`), y && (d.pixels = y);
|
|
342
356
|
}
|
|
343
|
-
return
|
|
357
|
+
return n.debug && x("Visionary Image state: ", d), d;
|
|
344
358
|
} catch {
|
|
345
359
|
return null;
|
|
346
360
|
}
|
|
347
|
-
},
|
|
361
|
+
}, mt = {
|
|
348
362
|
bottom: 0,
|
|
349
363
|
left: 0,
|
|
350
364
|
position: "absolute",
|
|
351
365
|
right: 0,
|
|
352
366
|
top: 0
|
|
353
|
-
},
|
|
354
|
-
...
|
|
367
|
+
}, vn = {
|
|
368
|
+
...mt,
|
|
355
369
|
maxHeight: "100%",
|
|
356
370
|
maxWidth: "100%"
|
|
357
|
-
},
|
|
358
|
-
...
|
|
371
|
+
}, yn = {
|
|
372
|
+
...mt,
|
|
359
373
|
height: "100%",
|
|
360
374
|
width: "100%"
|
|
361
|
-
},
|
|
362
|
-
const
|
|
363
|
-
...
|
|
375
|
+
}, wn = (t) => {
|
|
376
|
+
const n = {
|
|
377
|
+
...vn
|
|
364
378
|
};
|
|
365
|
-
return t && (
|
|
379
|
+
return t && (n.display = "none"), n;
|
|
366
380
|
}, H = {
|
|
367
381
|
CANVAS: "canvas",
|
|
368
382
|
CONTAINER: "container",
|
|
369
383
|
IMAGE: "image"
|
|
370
|
-
},
|
|
371
|
-
container:
|
|
372
|
-
preventDrag:
|
|
373
|
-
preventSelection:
|
|
374
|
-
},
|
|
384
|
+
}, In = "v7y_7587", En = "v7y_b8c0", Rn = "v7y_e0dd", X = {
|
|
385
|
+
container: In,
|
|
386
|
+
preventDrag: En,
|
|
387
|
+
preventSelection: Rn
|
|
388
|
+
}, On = ({
|
|
375
389
|
alt: t,
|
|
376
|
-
bgColorAlpha:
|
|
377
|
-
className:
|
|
390
|
+
bgColorAlpha: n = it,
|
|
391
|
+
className: e,
|
|
378
392
|
debug: o = !1,
|
|
379
|
-
disableBlurLayer:
|
|
393
|
+
disableBlurLayer: i = !1,
|
|
380
394
|
disableImageLayer: r = !1,
|
|
381
395
|
endpoint: s,
|
|
382
|
-
height:
|
|
383
|
-
hideImageLayer:
|
|
384
|
-
lazy:
|
|
385
|
-
onClick:
|
|
386
|
-
onError:
|
|
396
|
+
height: u,
|
|
397
|
+
hideImageLayer: c = !1,
|
|
398
|
+
lazy: a = !0,
|
|
399
|
+
onClick: p,
|
|
400
|
+
onError: l,
|
|
387
401
|
onLoad: m,
|
|
388
|
-
preventDrag:
|
|
389
|
-
preventSelection:
|
|
390
|
-
punch: v =
|
|
402
|
+
preventDrag: h = !1,
|
|
403
|
+
preventSelection: d = !1,
|
|
404
|
+
punch: v = at,
|
|
391
405
|
size: b,
|
|
392
406
|
src: g,
|
|
393
|
-
style:
|
|
394
|
-
width:
|
|
407
|
+
style: y,
|
|
408
|
+
width: E
|
|
395
409
|
}) => {
|
|
396
|
-
const
|
|
410
|
+
const f = At(() => bn(g, {
|
|
397
411
|
debug: o,
|
|
398
|
-
disableBlurLayer:
|
|
412
|
+
disableBlurLayer: i,
|
|
399
413
|
endpoint: s,
|
|
400
414
|
size: b
|
|
401
|
-
},
|
|
402
|
-
|
|
415
|
+
}, n, v), [n, o, i, s, v, b, g]), I = Y(null), [z, S] = Tt();
|
|
416
|
+
cn(
|
|
403
417
|
function() {
|
|
404
|
-
if (!
|
|
418
|
+
if (!I.current || !(f != null && f.blurhash))
|
|
405
419
|
return;
|
|
406
|
-
if (!
|
|
420
|
+
if (!f.pixels) {
|
|
407
421
|
console.warn("No pixel data passed in, skipping");
|
|
408
422
|
return;
|
|
409
423
|
}
|
|
410
|
-
const
|
|
411
|
-
if (!
|
|
424
|
+
const vt = performance.now(), M = I.current.getContext("2d");
|
|
425
|
+
if (!M) {
|
|
412
426
|
console.warn("Cannot access canvasRenderingContext, skipping");
|
|
413
427
|
return;
|
|
414
428
|
}
|
|
415
|
-
const
|
|
416
|
-
if (!
|
|
429
|
+
const W = M.createImageData(U, U);
|
|
430
|
+
if (!W) {
|
|
417
431
|
console.warn("Could not create ImageData on CanvasRenderingContext");
|
|
418
432
|
return;
|
|
419
433
|
}
|
|
420
|
-
if (
|
|
421
|
-
const
|
|
422
|
-
|
|
434
|
+
if (W.data.set(f.pixels), M.putImageData(W, 0, 0), o) {
|
|
435
|
+
const yt = performance.now() - vt;
|
|
436
|
+
x(`Canvas render time: ${A(yt, 1)} ms`);
|
|
423
437
|
}
|
|
424
438
|
},
|
|
425
|
-
[
|
|
439
|
+
[f == null ? void 0 : f.blurhash, f == null ? void 0 : f.pixels, o]
|
|
426
440
|
);
|
|
427
|
-
const
|
|
428
|
-
(
|
|
429
|
-
o &&
|
|
441
|
+
const _ = q(
|
|
442
|
+
(O) => {
|
|
443
|
+
o && x("Image load error ", O), l && l();
|
|
430
444
|
},
|
|
431
|
-
[o,
|
|
432
|
-
),
|
|
445
|
+
[o, l]
|
|
446
|
+
), N = {
|
|
433
447
|
alt: t,
|
|
434
|
-
loading: !
|
|
448
|
+
loading: !a || S ? "eager" : "lazy",
|
|
435
449
|
onLoad: m
|
|
436
450
|
};
|
|
437
|
-
if (!
|
|
438
|
-
o &&
|
|
439
|
-
const
|
|
440
|
-
...
|
|
441
|
-
className:
|
|
442
|
-
height:
|
|
443
|
-
onClick:
|
|
444
|
-
onError:
|
|
451
|
+
if (!f) {
|
|
452
|
+
o && x("Not a Visionary URL, rendering fallback <img />");
|
|
453
|
+
const O = {
|
|
454
|
+
...N,
|
|
455
|
+
className: e,
|
|
456
|
+
height: u,
|
|
457
|
+
onClick: p,
|
|
458
|
+
onError: l,
|
|
445
459
|
src: g,
|
|
446
|
-
style:
|
|
447
|
-
width:
|
|
460
|
+
style: y,
|
|
461
|
+
width: E
|
|
448
462
|
};
|
|
449
|
-
return /* @__PURE__ */
|
|
463
|
+
return /* @__PURE__ */ T("img", { ...O });
|
|
450
464
|
}
|
|
451
|
-
const R =
|
|
452
|
-
[X.preventDrag]: !!
|
|
453
|
-
[X.preventSelection]: !!
|
|
454
|
-
}),
|
|
465
|
+
const R = Nt(X.container, e, {
|
|
466
|
+
[X.preventDrag]: !!h,
|
|
467
|
+
[X.preventSelection]: !!d
|
|
468
|
+
}), B = {
|
|
455
469
|
...{
|
|
456
|
-
"--v-ar":
|
|
470
|
+
"--v-ar": f.arPaddingTop
|
|
457
471
|
},
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
472
|
+
...y,
|
|
473
|
+
aspectRatio: f.aspectRatio,
|
|
474
|
+
backgroundColor: (f == null ? void 0 : f.backgroundColor) ?? void 0,
|
|
475
|
+
maxWidth: f.maxWidth,
|
|
461
476
|
position: "relative",
|
|
462
|
-
width: "100%"
|
|
463
|
-
...w
|
|
477
|
+
width: "100%"
|
|
464
478
|
};
|
|
465
|
-
|
|
466
|
-
const
|
|
467
|
-
onClick:
|
|
468
|
-
},
|
|
469
|
-
return /* @__PURE__ */ vt(
|
|
479
|
+
E && (B.width = E), u && (B.height = u);
|
|
480
|
+
const gt = {
|
|
481
|
+
onClick: p
|
|
482
|
+
}, bt = wn(c), K = /* @__PURE__ */ wt(
|
|
470
483
|
"div",
|
|
471
484
|
{
|
|
472
485
|
className: R,
|
|
473
|
-
ref:
|
|
474
|
-
style:
|
|
475
|
-
...
|
|
486
|
+
ref: z,
|
|
487
|
+
style: B,
|
|
488
|
+
...hn(f.url, o),
|
|
476
489
|
...F(H.CONTAINER),
|
|
477
|
-
...
|
|
490
|
+
...gt,
|
|
478
491
|
children: [
|
|
479
|
-
!
|
|
492
|
+
!i && /* @__PURE__ */ T(
|
|
480
493
|
"canvas",
|
|
481
494
|
{
|
|
482
|
-
height:
|
|
483
|
-
ref:
|
|
484
|
-
style:
|
|
485
|
-
width:
|
|
495
|
+
height: U,
|
|
496
|
+
ref: I,
|
|
497
|
+
style: yn,
|
|
498
|
+
width: U,
|
|
486
499
|
...F(H.CANVAS)
|
|
487
500
|
}
|
|
488
501
|
),
|
|
489
502
|
!r && // eslint-disable-next-line jsx-a11y/alt-text -- `sharedImgProps` includes alt tag
|
|
490
|
-
/* @__PURE__ */
|
|
503
|
+
/* @__PURE__ */ T(
|
|
491
504
|
"img",
|
|
492
505
|
{
|
|
493
|
-
...
|
|
506
|
+
...N,
|
|
494
507
|
...F(H.IMAGE),
|
|
495
|
-
onError:
|
|
496
|
-
src:
|
|
497
|
-
style:
|
|
508
|
+
onError: _,
|
|
509
|
+
src: f.src,
|
|
510
|
+
style: bt
|
|
498
511
|
}
|
|
499
512
|
)
|
|
500
513
|
]
|
|
501
514
|
}
|
|
502
515
|
);
|
|
516
|
+
return y != null && y.aspectRatio ? /* @__PURE__ */ T(Dt, { aspectRatio: y.aspectRatio, children: K }) : K;
|
|
503
517
|
};
|
|
504
518
|
export {
|
|
505
|
-
|
|
519
|
+
On as Image
|
|
506
520
|
};
|
|
@@ -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(
|
|
2
|
+
(function(R,x){typeof exports=="object"&&typeof module<"u"?x(exports,require("react/jsx-runtime"),require("react")):typeof define=="function"&&define.amd?define(["exports","react/jsx-runtime","react"],x):(R=typeof globalThis<"u"?globalThis:R||self,x(R.VisionaryImage={},R.jsxRuntime,R.React))})(this,function(R,x,E){"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(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"})});
|
|
6
|
+
*/(function(t){(function(){var e={}.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)e.call(r,u)&&r[u]&&(s=i(s,u));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 bt=K.exports;const vt=gt(bt),yt=(t,{root:e,rootMargin:n,threshold:o}={},i=[])=>{const r=E.useRef(null),s=E.useRef(null);return E.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])},wt=({root:t,rootMargin:e,threshold:n,unobserveOnEnter:o,target:i,onEnter:r,onLeave:s,defaultInView:u}={},c=[])=>{const[a,p]=E.useState({inView:u||!1,entry:null,observer:null}),l=E.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=yt(l,{root:t,rootMargin:e,threshold:n},[o,...c]);return E.useEffect(()=>{i!=null&&i.current&&m(i.current)},[i,m]),[m,a.inView,a.entry,a.observer]},It={overflow:"hidden"},xt=({aspectRatio:t,children:e})=>x.jsx("div",{style:{aspectRatio:t,...It},children:e});var j=(t=>(t.AUTO="auto",t.AVIF="avif",t.JPEG="jpeg",t.WEBP="webp",t))(j||{}),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||{}),O=(t=>(t.DEBUG="debug",t.DOWNLOAD="download",t))(O||{});const Et="https://link.visionary.cloud";j.AUTO,w.lg;const M={[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(M).reduce((t,e)=>{const n=e,o=M[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,Tt=(t,e,n)=>Rt(t,typeof e!="symbol"?e+"":e,n),W={},V={};Object.defineProperty(V,"__esModule",{value:!0});function Ut(t){return String.fromCharCode(parseInt(t.slice(1),16))}function Ct(t){return btoa(encodeURIComponent(t).replace(/%[0-9A-F]{2}/g,Ut))}V.encode=Ct;function Nt(t){return`%${`00${t.charCodeAt(0).toString(16)}`.slice(-2)}`}function Ot(t){return decodeURIComponent(Array.from(atob(t),Nt).join(""))}V.decode=Ot,Object.defineProperty(W,"__esModule",{value:!0});const tt=V;function St(t){return tt.decode(t.replace(/\-/g,"+").replace(/_/g,"/"))}var Dt=W.decode=St;function Pt(t){return tt.encode(t).replace(/\//g,"_").replace(/\+/g,"-").replace(/=+$/,"")}var _t=W.encode=Pt;const jt=t=>t.filter(Boolean),et=t=>{try{return new URL(t)}catch{return null}},L=(t="")=>/^[A-Za-z0-9_-]*$/.test(t),Vt=t=>{const{altText:e,bcc:n,blurhash:o,blurhashX:i,blurhashY:r,sourceHeight:s,sourceWidth:u,url:c}=t;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),e&&e.length&&a.push(e)),Lt(a)},Lt=t=>_t(t.join(Q)),nt=t=>{if(typeof t!="string")return null;const e=t.trim();if(!e.length||!L(e))return null;const n=Dt(e);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 v=Number(a)??0,b=Number(p)??0;return v<1||b<1?(console.error("Cannot parse Visionary Code: invalid blurhash x, y component dimensions",v,b),null):{altText:l,bcc:u,blurhash:c,blurhashX:v,blurhashY:b,sourceHeight:f,sourceWidth:h,url:m}};class $t extends Error{constructor(){super(...arguments),Tt(this,"message","invalid endpoint URL (does it contain http/https?)")}}const kt=t=>t===O.DEBUG,zt=t=>t===O.DOWNLOAD,Bt=t=>Object.values(j).includes(t),rt=t=>Object.values(w).includes(t),Mt=(t=[])=>{const e={};for(const n of t)rt(n)?e.size=w[n]:kt(n)?e.debug=!0:zt(n)?e.download=!0:Bt(n)&&(e.format=n);return e},Wt=t=>{if(!t||typeof t!="object")return null;const e=[];return t.debug&&e.push(O.DEBUG),t.download&&e.push(O.DOWNLOAD),t.format&&t.format!==j.AUTO&&e.push(t.format),t.size&&rt(t.size)&&e.push(t.size),e.length?e.sort().join(","):null},Gt=t=>{if(L(t)){const e=nt(t);if(e)return{fields:e,options:{}}}return Ft(t)},Ft=t=>{if(!t)return null;const e=t.trim();if(!e)return null;try{const n=Xt(e);if(!n)return null;const{code:o,optionTokens:i}=n,r=nt(o);if(!r)return null;const s=Mt(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},Ht=(t,e)=>{const n=Vt(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(Et));const i=[o.origin,"image",n],r=e?Wt(e):null;return r&&i.push(r),e!=null&&e.filename?i.push(e.filename):i.push("image.jpg"),i.join("/")},Xt=t=>{try{const e=new URL(t),n=jt(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||!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},ot=.7,st=1,N=24,Yt=w.lg,ct=process.env.NODE_ENV,qt=ct==="development",it=typeof document>"u",Zt=ct==="test",Jt=it?()=>{}:E.useLayoutEffect,Kt="<visionary>",T=(t,...e)=>{!console||typeof console.log!="function"||console.log(`${Kt} ${t}`,...e)},at=new Uint8Array(128);for(let t=0;t<83;t++)at["0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz#$%*+,-.:;=?@[]^_{|}~".charCodeAt(t)]=t;const $=(t,e,n)=>{let o=0;for(;e<n;)o*=83,o+=at[t.charCodeAt(e++)];return o},lt=Math.pow,S=Math.PI,Qt=S*2,ut=3294.6,ft=269.025,te=t=>t>10.31475?lt(t/ft+.052132,2.4):t/ut,G=t=>~~(t>1227e-8?ft*lt(t,.416666)-13.025:t*ut+1),D=t=>(t<0?-1:1)*t*t,dt=t=>{for(t+=S/2;t>S;)t-=Qt;const e=1.27323954*t-.405284735*D(t);return .225*(D(e)-e)+e};function ee(t){const e=$(t,2,6);return[e>>16,e>>8&255,e&255]}function ne(t,e,n,o){const i=$(t,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,v=0,b=0,g=0,y=0,A=0;const d=($(t,1,2)+1)/13446*(o|1),I=new Float64Array(u*3),Y=ee(t);for(c=0;c<3;c++)I[c]=te(Y[c]);for(c=1;c<u;c++)A=$(t,4+c*2,6+c*2),I[c*3]=D(~~(A/361)-9)*d,I[c*3+1]=D(~~(A/19)%19-9)*d,I[c*3+2]=D(A%19-9)*d;const z=new Float64Array(s*n),B=new Float64Array(r*e);for(a=0;a<s;a++)for(l=0;l<n;l++)z[a*n+l]=dt(S*l*a/n);for(c=0;c<r;c++)for(p=0;p<e;p++)B[c*e+p]=dt(S*p*c/e);const P=e*4,C=new Uint8ClampedArray(P*n);for(l=0;l<n;l++)for(p=0;p<e;p++){for(m=h=f=0,a=0;a<s;a++)for(b=z[a*n+l],c=0;c<r;c++)v=B[c*e+p]*b,g=(c+a*r)*3,m+=I[g]*v,h+=I[g+1]*v,f+=I[g+2]*v;y=4*p+l*P,C[y]=G(m),C[y+1]=G(h),C[y+2]=G(f),C[y+3]=255}return C}const k=t=>{try{return new URL(t)}catch{return null}},re=(t,e)=>`rgba(${t.r},${t.g},${t.b},${e})`,F=t=>qt||Zt?{"data-testid":t}:{},oe=(t,e)=>e?{"data-fileid":t}:{},pt=(t,e)=>Math.min(t,e),se=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}},U=(t,e=0)=>{const n=Math.pow(10,e);return Math.round(t*n)/n},ce=(t,e)=>{const n=k(t),o=k(e);return!n||!o?t:(o.pathname=n.pathname,o.search=n.search,o.toString())},ie=(t,e={},n=ot,o=st)=>{if(!t)return null;try{e.debug&&T("input imageSrc:",t);const i=Gt(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 u=r.sourceWidth/r.sourceHeight,c=(e==null?void 0:e.size)??s.size??Yt,a=M[c];let p=0,l=0,m=0;if(u>=1){l=p=pt(a,r.sourceWidth);const g=U(l/u);m=U(l/g,6)}else p=pt(a,r.sourceHeight),l=U(p*u),m=U(l/p,6);const h=U(100/m,6),f={...r,arPaddingTop:`${h}%`,aspectRatio:m,maxWidth:l,src:t},v=k(r.url);if(v)f.src=v.toString();else if(!k(t)&&L(r.url)){const g=Ht(r,{endpoint:e.endpoint,size:c});g&&(f.src=g)}e.endpoint&&(f.src=ce(f.src,e.endpoint));const b=r.bcc?se(r.bcc):null;if(b&&(f.backgroundColor=re(b,n)),!it&&r.blurhash&&!e.disableBlurLayer){const g=performance.now(),y=ne(r.blurhash,N,N,o),A=performance.now()-g;e.debug&&T(`Blurhash decode time: ${U(A,1)} ms`),y&&(f.pixels=y)}return e.debug&&T("Visionary Image state: ",f),f}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},H={CANVAS:"canvas",CONTAINER:"container",IMAGE:"image"},X={container:"v7y_7587",preventDrag:"v7y_b8c0",preventSelection:"v7y_e0dd"},fe=({alt:t,bgColorAlpha:e=ot,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:v=st,size:b,src:g,style:y,width:A})=>{const d=E.useMemo(()=>ie(g,{debug:o,disableBlurLayer:i,endpoint:s,size:b},e,v),[e,o,i,s,v,b,g]),I=E.useRef(null),[Y,z]=wt();Jt(function(){if(!I.current||!(d!=null&&d.blurhash))return;if(!d.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(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 me=performance.now()-he;T(`Canvas render time: ${U(me,1)} ms`)}},[d==null?void 0:d.blurhash,d==null?void 0:d.pixels,o]);const B=E.useCallback(_=>{o&&T("Image load error ",_),l&&l()},[o,l]),P={alt:t,loading:!a||z?"eager":"lazy",onLoad:m};if(!d){o&&T("Not a Visionary URL, rendering fallback <img />");const _={...P,className:n,height:u,onClick:p,onError:l,src:g,style:y,width:A};return x.jsx("img",{..._})}const C=vt(X.container,n,{[X.preventDrag]:!!h,[X.preventSelection]:!!f}),q={...{"--v-ar":d.arPaddingTop},...y,aspectRatio:d.aspectRatio,backgroundColor:(d==null?void 0:d.backgroundColor)??void 0,maxWidth:d.maxWidth,position:"relative",width:"100%"};A&&(q.width=A),u&&(q.height=u);const de={onClick:p},pe=ue(c),mt=x.jsxs("div",{className:C,ref:Y,style:q,...oe(d.url,o),...F(H.CONTAINER),...de,children:[!i&&x.jsx("canvas",{height:N,ref:I,style:le,width:N,...F(H.CANVAS)}),!r&&x.jsx("img",{...P,...F(H.IMAGE),onError:B,src:d.src,style:pe})]});return y!=null&&y.aspectRatio?x.jsx(xt,{aspectRatio:y.aspectRatio,children:mt}):mt};R.Image=fe,Object.defineProperty(R,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.3",
|
|
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",
|
|
@@ -17,14 +18,14 @@
|
|
|
17
18
|
"license": "ISC",
|
|
18
19
|
"scripts": {
|
|
19
20
|
"build": "tsc && npm run clean && vite build",
|
|
21
|
+
"build-storybook": "storybook build -o storybook-static",
|
|
20
22
|
"clean": "rimraf dist/",
|
|
21
23
|
"dev": "vite",
|
|
22
24
|
"lint": "tsc --noEmit; eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
|
|
23
25
|
"preview": "vite preview",
|
|
24
|
-
"test": "vitest",
|
|
25
|
-
"test:coverage": "vitest run --coverage",
|
|
26
26
|
"storybook": "storybook dev -p 6006 --no-open",
|
|
27
|
-
"
|
|
27
|
+
"test": "vitest",
|
|
28
|
+
"test:coverage": "vitest run --coverage"
|
|
28
29
|
},
|
|
29
30
|
"files": [
|
|
30
31
|
"dist/",
|
|
@@ -37,7 +38,7 @@
|
|
|
37
38
|
},
|
|
38
39
|
"dependencies": {
|
|
39
40
|
"classnames": "2.5.1",
|
|
40
|
-
"fast-blurhash": "1.1.
|
|
41
|
+
"fast-blurhash": "1.1.4",
|
|
41
42
|
"react-hook-inview": "4.5.1",
|
|
42
43
|
"visionary-url": "1.3.1"
|
|
43
44
|
},
|