img-upload-kit 1.1.1 → 2.0.0
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/CHANGELOG.md +56 -41
- package/MIGRATION.md +192 -0
- package/README.md +138 -154
- package/dist/bin.js +1186 -0
- package/dist/bin.js.map +1 -0
- package/dist/blur.cjs +40 -412
- package/dist/blur.cjs.map +1 -1
- package/dist/blur.d.cts +5 -5
- package/dist/blur.d.ts +5 -5
- package/dist/blur.js +39 -393
- package/dist/blur.js.map +1 -1
- package/dist/blurDataUtils-DveBRtqE.d.cts +43 -0
- package/dist/blurDataUtils-yx9Q6HlU.d.ts +43 -0
- package/dist/blurService-D5TpMNji.d.ts +83 -0
- package/dist/blurService-DacwylJx.d.cts +83 -0
- package/dist/chunk-2OVNXHTN.cjs +514 -0
- package/dist/chunk-2OVNXHTN.cjs.map +1 -0
- package/dist/chunk-3ICG2SLL.cjs +135 -0
- package/dist/chunk-3ICG2SLL.cjs.map +1 -0
- package/dist/chunk-4ASFG3KB.js +514 -0
- package/dist/chunk-4ASFG3KB.js.map +1 -0
- package/dist/chunk-AI3JJLSA.js +2370 -0
- package/dist/chunk-AI3JJLSA.js.map +1 -0
- package/dist/chunk-CV23O4YU.js +145 -0
- package/dist/chunk-CV23O4YU.js.map +1 -0
- package/dist/chunk-G7LLSKBV.js +158 -0
- package/dist/chunk-G7LLSKBV.js.map +1 -0
- package/dist/chunk-IB3TEDLR.js +294 -0
- package/dist/chunk-IB3TEDLR.js.map +1 -0
- package/dist/chunk-KJVYWKIG.cjs +158 -0
- package/dist/chunk-KJVYWKIG.cjs.map +1 -0
- package/dist/chunk-NEDBIIE3.cjs +226 -0
- package/dist/chunk-NEDBIIE3.cjs.map +1 -0
- package/dist/chunk-QHU7FUO4.cjs +37 -0
- package/dist/chunk-QHU7FUO4.cjs.map +1 -0
- package/dist/chunk-QQHZJKNA.js +135 -0
- package/dist/chunk-QQHZJKNA.js.map +1 -0
- package/dist/chunk-S2IFAWJK.js +37 -0
- package/dist/chunk-S2IFAWJK.js.map +1 -0
- package/dist/chunk-TT5C7K3Q.js +226 -0
- package/dist/chunk-TT5C7K3Q.js.map +1 -0
- package/dist/chunk-U2TWTEBY.cjs +2370 -0
- package/dist/chunk-U2TWTEBY.cjs.map +1 -0
- package/dist/chunk-WISG74VL.cjs +294 -0
- package/dist/chunk-WISG74VL.cjs.map +1 -0
- package/dist/chunk-YRXXQUDE.cjs +145 -0
- package/dist/chunk-YRXXQUDE.cjs.map +1 -0
- package/dist/cli.cjs +273 -76
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +269 -73
- package/dist/cli.js.map +1 -1
- package/dist/headless.cjs +8 -1880
- package/dist/headless.cjs.map +1 -1
- package/dist/headless.d.cts +3 -1
- package/dist/headless.d.ts +3 -1
- package/dist/headless.js +25 -1886
- package/dist/headless.js.map +1 -1
- package/dist/index-BIdnqtW8.d.ts +234 -0
- package/dist/index-Brk_uHs6.d.cts +234 -0
- package/dist/{index-FVXXKf2v.d.ts → index-CPMlaQsC.d.ts} +76 -153
- package/dist/{index-FVXXKf2v.d.cts → index-DHINe-rA.d.cts} +76 -153
- package/dist/index.cjs +64 -532
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -4
- package/dist/index.d.ts +7 -4
- package/dist/index.js +63 -504
- package/dist/index.js.map +1 -1
- package/dist/{memoryAdapter-CBu7_3Pp.d.ts → memoryAdapter-Ck0ccZbF.d.cts} +3 -2
- package/dist/{memoryAdapter-BJjyLR-1.d.cts → memoryAdapter-DxEKaG0b.d.ts} +3 -2
- package/dist/placeholders-C4ftwaII.d.ts +5 -0
- package/dist/placeholders-x_3rt65M.d.cts +5 -0
- package/dist/react.cjs +1952 -3257
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +188 -50
- package/dist/react.d.ts +188 -50
- package/dist/react.js +1763 -3013
- package/dist/react.js.map +1 -1
- package/dist/server-handler.cjs +14 -0
- package/dist/server-handler.cjs.map +1 -0
- package/dist/server-handler.d.cts +3 -0
- package/dist/server-handler.d.ts +3 -0
- package/dist/server-handler.js +14 -0
- package/dist/server-handler.js.map +1 -0
- package/dist/server.cjs +1096 -532
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +77 -154
- package/dist/server.d.ts +77 -154
- package/dist/server.js +1050 -448
- package/dist/server.js.map +1 -1
- package/dist/storage.cjs +239 -232
- package/dist/storage.cjs.map +1 -1
- package/dist/storage.d.cts +21 -5
- package/dist/storage.d.ts +21 -5
- package/dist/storage.js +227 -207
- package/dist/storage.js.map +1 -1
- package/dist/styles/animated-image.css +112 -0
- package/dist/styles/dropzone-and-tiles.css +247 -0
- package/dist/styles/modals-and-dock.css +248 -0
- package/dist/styles/primitives.css +197 -0
- package/dist/styles/quality-and-inputs.css +184 -0
- package/dist/styles/tokens.css +123 -0
- package/dist/styles.css +39 -24
- package/dist/types-BrP-o9nd.d.cts +85 -0
- package/dist/types-sZ3KoFQY.d.ts +85 -0
- package/dist/types-yShGNQnW.d.cts +61 -0
- package/dist/types-yShGNQnW.d.ts +61 -0
- package/dist/{types-CiLY0DwB.d.cts → upload-C5Trd6Dh.d.cts} +27 -53
- package/dist/{types-CiLY0DwB.d.ts → upload-C5Trd6Dh.d.ts} +27 -53
- package/package.json +92 -32
- package/dist/blurService-DqsnfPTd.d.cts +0 -172
- package/dist/blurService-DqsnfPTd.d.ts +0 -172
package/dist/blur.cjs
CHANGED
|
@@ -1,413 +1,41 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
const blurData = getBlurData(image);
|
|
44
|
-
return {
|
|
45
|
-
backgroundColor: blurData.blurColor,
|
|
46
|
-
backgroundImage: `url(${image.url})`,
|
|
47
|
-
backgroundSize: "cover",
|
|
48
|
-
backgroundPosition: "center",
|
|
49
|
-
backgroundRepeat: "no-repeat"
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
function getBlurPlaceholderStyle(image) {
|
|
53
|
-
const blurData = getBlurData(image);
|
|
54
|
-
if (!blurData.blurDataUrl) {
|
|
55
|
-
return {
|
|
56
|
-
backgroundColor: blurData.blurColor
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
return {
|
|
60
|
-
backgroundColor: blurData.blurColor,
|
|
61
|
-
backgroundImage: `url(${blurData.blurDataUrl})`,
|
|
62
|
-
backgroundSize: "cover",
|
|
63
|
-
backgroundPosition: "center",
|
|
64
|
-
filter: "blur(20px)",
|
|
65
|
-
transform: "scale(1.1)"
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
function hasBlurData(image) {
|
|
69
|
-
return Boolean(image?.blurDataUrl || image?.blurColor || image?.blurHash);
|
|
70
|
-
}
|
|
71
|
-
function getBulkBlurData(images) {
|
|
72
|
-
return images.map(getBlurData);
|
|
73
|
-
}
|
|
74
|
-
function createSrcSetWithBlur(image) {
|
|
75
|
-
if (!image?.url) return "";
|
|
76
|
-
const blurData = getBlurData(image);
|
|
77
|
-
if (!blurData.blurDataUrl) {
|
|
78
|
-
return image.url;
|
|
79
|
-
}
|
|
80
|
-
return `${blurData.blurDataUrl} 40w, ${image.url} ${image.width || 1920}w`;
|
|
81
|
-
}
|
|
82
|
-
function preloadImageWithBlur(image) {
|
|
83
|
-
if (!image?.url || typeof document === "undefined") return;
|
|
84
|
-
const link = document.createElement("link");
|
|
85
|
-
link.rel = "preload";
|
|
86
|
-
link.as = "image";
|
|
87
|
-
link.href = image.url;
|
|
88
|
-
const blurData = getBlurData(image);
|
|
89
|
-
if (blurData.blurDataUrl) {
|
|
90
|
-
link.setAttribute("imagesrcset", blurData.blurDataUrl);
|
|
91
|
-
}
|
|
92
|
-
document.head.appendChild(link);
|
|
93
|
-
}
|
|
94
|
-
function extractImageUrls(image) {
|
|
95
|
-
if (!image?.url) return [];
|
|
96
|
-
return [image.url];
|
|
97
|
-
}
|
|
98
|
-
function decodeBlurHashToDataURL(hash, width = 32, height = 32, punch = 1) {
|
|
99
|
-
if (!hash || typeof document === "undefined") return null;
|
|
100
|
-
const validation = blurhash.isBlurhashValid(hash);
|
|
101
|
-
if (!validation.result) return null;
|
|
102
|
-
try {
|
|
103
|
-
const pixels = blurhash.decode(hash, width, height, punch);
|
|
104
|
-
const canvas = document.createElement("canvas");
|
|
105
|
-
canvas.width = width;
|
|
106
|
-
canvas.height = height;
|
|
107
|
-
const ctx = canvas.getContext("2d");
|
|
108
|
-
if (!ctx) return null;
|
|
109
|
-
const imageData = ctx.createImageData(width, height);
|
|
110
|
-
imageData.data.set(pixels);
|
|
111
|
-
ctx.putImageData(imageData, 0, 0);
|
|
112
|
-
return canvas.toDataURL("image/png");
|
|
113
|
-
} catch {
|
|
114
|
-
return null;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// src/blur/lruCache.ts
|
|
119
|
-
var LRUCache = class {
|
|
120
|
-
maxSize;
|
|
121
|
-
cache;
|
|
122
|
-
constructor(maxSize = 500) {
|
|
123
|
-
this.maxSize = Math.max(1, maxSize);
|
|
124
|
-
this.cache = /* @__PURE__ */ new Map();
|
|
125
|
-
}
|
|
126
|
-
get(key) {
|
|
127
|
-
if (!this.cache.has(key)) return void 0;
|
|
128
|
-
const value = this.cache.get(key);
|
|
129
|
-
this.cache.delete(key);
|
|
130
|
-
this.cache.set(key, value);
|
|
131
|
-
return value;
|
|
132
|
-
}
|
|
133
|
-
set(key, value) {
|
|
134
|
-
if (this.cache.has(key)) {
|
|
135
|
-
this.cache.delete(key);
|
|
136
|
-
}
|
|
137
|
-
if (this.cache.size >= this.maxSize) {
|
|
138
|
-
const firstKey = this.cache.keys().next().value;
|
|
139
|
-
if (firstKey !== void 0) {
|
|
140
|
-
this.cache.delete(firstKey);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
this.cache.set(key, value);
|
|
144
|
-
}
|
|
145
|
-
has(key) {
|
|
146
|
-
return this.cache.has(key);
|
|
147
|
-
}
|
|
148
|
-
clear() {
|
|
149
|
-
this.cache.clear();
|
|
150
|
-
}
|
|
151
|
-
get size() {
|
|
152
|
-
return this.cache.size;
|
|
153
|
-
}
|
|
154
|
-
};
|
|
155
|
-
|
|
156
|
-
// src/blur/pathMapper.ts
|
|
157
|
-
var DEFAULT_CDN_PATTERNS = [
|
|
158
|
-
/^https?:\/\/[^/]+\.supabase\.co\/storage\/v1\/object\/public\/([^/]+)\/(.+)$/,
|
|
159
|
-
/^https?:\/\/[^/]+\.r2\.dev\/(.+)$/,
|
|
160
|
-
/^https?:\/\/[^/]+\.amazonaws\.com\/(.+)$/,
|
|
161
|
-
/^https?:\/\/[^/]+\.cloudflare\.com\/(.+)$/,
|
|
162
|
-
/^https?:\/\/cdn\.[^/]+\/(.+)$/
|
|
163
|
-
];
|
|
164
|
-
function normalizeImagePath(imageSrc, options = {}) {
|
|
165
|
-
const originalPath = imageSrc;
|
|
166
|
-
let normalizedPath = imageSrc;
|
|
167
|
-
let isExternal = false;
|
|
168
|
-
try {
|
|
169
|
-
if (imageSrc.startsWith("data:") || imageSrc.startsWith("blob:")) {
|
|
170
|
-
return {
|
|
171
|
-
normalizedPath: imageSrc,
|
|
172
|
-
isExternal: false,
|
|
173
|
-
originalPath
|
|
174
|
-
};
|
|
175
|
-
}
|
|
176
|
-
const patterns = options.cdnPatterns || DEFAULT_CDN_PATTERNS;
|
|
177
|
-
if (imageSrc.startsWith("http://") || imageSrc.startsWith("https://")) {
|
|
178
|
-
const url = new URL(imageSrc);
|
|
179
|
-
isExternal = true;
|
|
180
|
-
const cleanUrlNoQuery = `${url.origin}${url.pathname}`;
|
|
181
|
-
for (const pattern of patterns) {
|
|
182
|
-
const match = cleanUrlNoQuery.match(pattern);
|
|
183
|
-
if (match) {
|
|
184
|
-
const pathPart = match[match.length - 1];
|
|
185
|
-
normalizedPath = "/" + pathPart.replace(/^\/+/, "");
|
|
186
|
-
break;
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
if (normalizedPath === imageSrc) {
|
|
190
|
-
normalizedPath = url.pathname;
|
|
191
|
-
}
|
|
192
|
-
} else {
|
|
193
|
-
normalizedPath = normalizedPath.split("?")[0].split("#")[0];
|
|
194
|
-
}
|
|
195
|
-
normalizedPath = normalizedPath.replace(/\\/g, "/").replace(/^\.\.?\//g, "");
|
|
196
|
-
if (!normalizedPath.startsWith("/")) {
|
|
197
|
-
normalizedPath = "/" + normalizedPath;
|
|
198
|
-
}
|
|
199
|
-
const prefixesToStrip = options.stripPrefixes || ["/public/"];
|
|
200
|
-
for (const prefix of prefixesToStrip) {
|
|
201
|
-
if (normalizedPath.startsWith(prefix)) {
|
|
202
|
-
normalizedPath = "/" + normalizedPath.slice(prefix.length).replace(/^\/+/, "");
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
const segments = normalizedPath.split("/").filter(Boolean);
|
|
206
|
-
const filename = segments[segments.length - 1];
|
|
207
|
-
const folder = segments.length > 1 ? segments.slice(0, -1).join("/") : void 0;
|
|
208
|
-
const dotIdx = filename ? filename.lastIndexOf(".") : -1;
|
|
209
|
-
const extension = filename && dotIdx > 0 ? filename.slice(dotIdx + 1).toLowerCase() : void 0;
|
|
210
|
-
return {
|
|
211
|
-
normalizedPath,
|
|
212
|
-
folder,
|
|
213
|
-
filename,
|
|
214
|
-
extension,
|
|
215
|
-
isExternal,
|
|
216
|
-
originalPath
|
|
217
|
-
};
|
|
218
|
-
} catch {
|
|
219
|
-
return {
|
|
220
|
-
normalizedPath: imageSrc,
|
|
221
|
-
isExternal: false,
|
|
222
|
-
originalPath
|
|
223
|
-
};
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
// src/blur/placeholders.ts
|
|
228
|
-
var DEFAULT_PLACEHOLDERS = {
|
|
229
|
-
default: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTUwIiBoZWlnaHQ9IjE1MCIgdmlld0JveD0iMCAwIDE1MCAxNTAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkaWVudCIgeDE9IjAlIiB5MT0iMCUiIHgyPSIxMDAlIiB5Mj0iMTAwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3R5bGU9InN0b3AtY29sb3I6IzJhMzIzZDtzdG9wLW9wYWNpdHk6MSIvPjxzdG9wIG9mZnNldD0iNTAlIiBzdHlsZT0ic3RvcC1jb2xvcjojMjEyNzMwO3N0b3Atb3BhY2l0eToxIi8+PHN0b3Agb2Zmc2V0PSIxMDAlIiBzdHlsZT0ic3RvcC1jb2xvcjojMTgxZDI0O3N0b3Atb3BhY2l0eToxIi8+PC9saW5lYXJHcmFkaWVudD48L2RlZnM+PHJlY3Qgd2lkdGg9IjE1MCIgaGVpZ2h0PSIxNTAiIGZpbGw9InVybCgjZ3JhZGllbnQpIi8+PC9zdmc+",
|
|
230
|
-
hero: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTkyMCIgaGVpZ2h0PSIxMDgwIiB2aWV3Qm94PSIwIDAgMTkyMCAxMDgwIiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxkZWZzPjxsaW5lYXJHcmFkaWVudCBpZD0iaGVyb0dyYWRpZW50IiB4MT0iMCUiIHkxPSIwJSIgeDI9IjEwMCUiIHkyPSIxMDAlIj48c3RvcCBvZmZzZXQ9IjAlIiBzdHlsZT0ic3RvcC1jb2xvcjojMmQzNzQ4O3N0b3Atb3BhY2l0eToxIi8+PHN0b3Agb2Zmc2V0PSIzMCUiIHN0eWxlPSJzdG9wLWNvbG9yOiMyMzJiMzg7c3RvcC1vcGFjaXR5OjEiLz48c3RvcCBvZmZzZXQ9IjcwJSIgc3R5bGU9InN0b3AtY29sb3I6IzFlMjUzMDtzdG9wLW9wYWNpdHk6MSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3R5bGU9InN0b3AtY29sb3I6IzE3MWQyNztzdG9wLW9wYWNpdHk6MSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHdpZHRoPSIxOTIwIiBoZWlnaHQ9IjEwODAiIGZpbGw9InVybCgjaGVyb0dyYWRpZW50KSIvPjwvc3ZnPg==",
|
|
231
|
-
card: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAwIiBoZWlnaHQ9IjMwMCIgdmlld0JveD0iMCAwIDQwMCAzMDAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJjYXJkR3JhZGllbnQiIHgxPSIwJSIgeTE9IjAlIiB4Mj0iMTAwJSIgeTI9IjEwMCUiPjxzdG9wIG9mZnNldD0iMCUiIHN0eWxlPSJzdG9wLWNvbG9yOiMyYTMyM2Q7c3RvcC1vcGFjaXR5OjEiLz48c3RvcCBvZmZzZXQ9IjEwMCUiIHN0eWxlPSJzdG9wLWNvbG9yOiMxYzIyMmI7c3RvcC1vcGFjaXR5OjEiLz48L2xpbmVhckdyYWRpZW50PjwvZGVmcz48cmVjdCB3aWR0aD0iNDAwIiBoZWlnaHQ9IjMwMCIgZmlsbD0idXJsKCNjYXJkR3JhZGllbnQpIi8+PC9zdmc+",
|
|
232
|
-
thumbnail: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgdmlld0JveD0iMCAwIDEwMCAxMDAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHJlY3Qgd2lkdGg9IjEwMCIgaGVpZ2h0PSIxMDAiIGZpbGw9IiMyNDJiMzUiLz48L3N2Zz4="
|
|
233
|
-
};
|
|
234
|
-
|
|
235
|
-
// src/blur/blurService.ts
|
|
236
|
-
var BlurService = class {
|
|
237
|
-
blurData;
|
|
238
|
-
cache;
|
|
239
|
-
pathOptions;
|
|
240
|
-
metadata;
|
|
241
|
-
metrics;
|
|
242
|
-
constructor(options = {}) {
|
|
243
|
-
this.blurData = {};
|
|
244
|
-
this.pathOptions = options.pathOptions;
|
|
245
|
-
this.metadata = {
|
|
246
|
-
version: "2.0",
|
|
247
|
-
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
248
|
-
totalImages: 0
|
|
249
|
-
};
|
|
250
|
-
this.cache = new LRUCache(options.cacheSize ?? 500);
|
|
251
|
-
this.metrics = {
|
|
252
|
-
totalRequests: 0,
|
|
253
|
-
cacheHits: 0,
|
|
254
|
-
cacheMisses: 0,
|
|
255
|
-
errors: 0
|
|
256
|
-
};
|
|
257
|
-
if (options.manifest) {
|
|
258
|
-
this.loadManifest(options.manifest);
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
/**
|
|
262
|
-
* Hydrate the service with a generated `blur-hashes.json` manifest or hash map.
|
|
263
|
-
*/
|
|
264
|
-
loadManifest(manifest) {
|
|
265
|
-
this.cache.clear();
|
|
266
|
-
if ("hashes" in manifest && typeof manifest.hashes === "object" && manifest.hashes !== null) {
|
|
267
|
-
const typed = manifest;
|
|
268
|
-
this.blurData = { ...typed.hashes };
|
|
269
|
-
this.metadata = {
|
|
270
|
-
version: typed.version || "2.0",
|
|
271
|
-
generatedAt: typed.generatedAt || (/* @__PURE__ */ new Date()).toISOString(),
|
|
272
|
-
totalImages: Object.keys(this.blurData).length
|
|
273
|
-
};
|
|
274
|
-
} else {
|
|
275
|
-
this.blurData = { ...manifest };
|
|
276
|
-
this.metadata = {
|
|
277
|
-
version: "2.0",
|
|
278
|
-
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
279
|
-
totalImages: Object.keys(this.blurData).length
|
|
280
|
-
};
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
/**
|
|
284
|
-
* Register or update a single image's blur data at runtime.
|
|
285
|
-
*/
|
|
286
|
-
registerEntry(imagePath, entry) {
|
|
287
|
-
this.blurData[imagePath] = entry;
|
|
288
|
-
this.metadata.totalImages = Object.keys(this.blurData).length;
|
|
289
|
-
this.cache.clear();
|
|
290
|
-
}
|
|
291
|
-
getDefaultPlaceholder(type = "default") {
|
|
292
|
-
return DEFAULT_PLACEHOLDERS[type];
|
|
293
|
-
}
|
|
294
|
-
findBlurDataByPath(imageSrc) {
|
|
295
|
-
let data = this.blurData[imageSrc];
|
|
296
|
-
if (data) return data;
|
|
297
|
-
const pathInfo = normalizeImagePath(imageSrc, this.pathOptions);
|
|
298
|
-
data = this.blurData[pathInfo.normalizedPath];
|
|
299
|
-
if (data) return data;
|
|
300
|
-
const withSlash = pathInfo.normalizedPath.startsWith("/") ? pathInfo.normalizedPath : "/" + pathInfo.normalizedPath;
|
|
301
|
-
const withoutSlash = pathInfo.normalizedPath.replace(/^\/+/, "");
|
|
302
|
-
data = this.blurData[withSlash] || this.blurData[withoutSlash];
|
|
303
|
-
if (data) return data;
|
|
304
|
-
if (pathInfo.isExternal && pathInfo.originalPath !== imageSrc) {
|
|
305
|
-
data = this.blurData[pathInfo.originalPath];
|
|
306
|
-
if (data) return data;
|
|
307
|
-
}
|
|
308
|
-
return null;
|
|
309
|
-
}
|
|
310
|
-
getDominantColor(imageSrc) {
|
|
311
|
-
const data = this.findBlurDataByPath(imageSrc);
|
|
312
|
-
return data?.color || "#E5E7EB";
|
|
313
|
-
}
|
|
314
|
-
getBlurDataURL(imageSrc, options = {}) {
|
|
315
|
-
const { type = "default", size = "small" } = options;
|
|
316
|
-
this.metrics.totalRequests++;
|
|
317
|
-
const cacheKey = `${imageSrc}-${size}`;
|
|
318
|
-
if (this.cache.has(cacheKey)) {
|
|
319
|
-
this.metrics.cacheHits++;
|
|
320
|
-
return this.cache.get(cacheKey).dataUrl;
|
|
321
|
-
}
|
|
322
|
-
this.metrics.cacheMisses++;
|
|
323
|
-
if (Object.keys(this.blurData).length === 0) {
|
|
324
|
-
return this.getDefaultPlaceholder(type);
|
|
325
|
-
}
|
|
326
|
-
const data = this.findBlurDataByPath(imageSrc);
|
|
327
|
-
if (!data) {
|
|
328
|
-
return this.getDefaultPlaceholder(type);
|
|
329
|
-
}
|
|
330
|
-
const blurDataURL = data.variants?.[size] || data.variants?.small || this.getDefaultPlaceholder(type);
|
|
331
|
-
this.cache.set(cacheKey, {
|
|
332
|
-
dataUrl: blurDataURL,
|
|
333
|
-
timestamp: Date.now()
|
|
334
|
-
});
|
|
335
|
-
return blurDataURL;
|
|
336
|
-
}
|
|
337
|
-
getBulkBlurData(imageSrcs, options = {}) {
|
|
338
|
-
const result = {};
|
|
339
|
-
for (const imageSrc of imageSrcs) {
|
|
340
|
-
result[imageSrc] = this.getBlurDataURL(imageSrc, options);
|
|
341
|
-
}
|
|
342
|
-
return result;
|
|
343
|
-
}
|
|
344
|
-
getProgressiveData(imageSrc, size = "small") {
|
|
345
|
-
return {
|
|
346
|
-
color: this.getDominantColor(imageSrc),
|
|
347
|
-
blur: this.getBlurDataURL(imageSrc, { size }),
|
|
348
|
-
hasBlur: this.hasBlurHash(imageSrc)
|
|
349
|
-
};
|
|
350
|
-
}
|
|
351
|
-
hasBlurHash(imageSrc) {
|
|
352
|
-
return Boolean(this.findBlurDataByPath(imageSrc));
|
|
353
|
-
}
|
|
354
|
-
getMetadata() {
|
|
355
|
-
const cacheHitRate = this.metrics.totalRequests > 0 ? (this.metrics.cacheHits / this.metrics.totalRequests * 100).toFixed(2) : "0.00";
|
|
356
|
-
return {
|
|
357
|
-
...this.metadata,
|
|
358
|
-
cacheSize: this.cache.size,
|
|
359
|
-
metrics: {
|
|
360
|
-
...this.metrics,
|
|
361
|
-
cacheHitRate: `${cacheHitRate}%`
|
|
362
|
-
}
|
|
363
|
-
};
|
|
364
|
-
}
|
|
365
|
-
clearCache() {
|
|
366
|
-
this.cache.clear();
|
|
367
|
-
}
|
|
368
|
-
getBlurHash(imageSrc) {
|
|
369
|
-
const data = this.findBlurDataByPath(imageSrc);
|
|
370
|
-
return data?.hash || null;
|
|
371
|
-
}
|
|
372
|
-
preloadBlurData(imageSrcs, size = "small") {
|
|
373
|
-
for (const imageSrc of imageSrcs) {
|
|
374
|
-
this.getBlurDataURL(imageSrc, { size });
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
async fetchBlurDataForImage(imageSrc, type = "default") {
|
|
378
|
-
return Promise.resolve(this.getBlurDataURL(imageSrc, { type }));
|
|
379
|
-
}
|
|
380
|
-
getAvailableKeys() {
|
|
381
|
-
return Object.keys(this.blurData);
|
|
382
|
-
}
|
|
383
|
-
findMatchingKeys(searchTerm) {
|
|
384
|
-
const lower = searchTerm.toLowerCase();
|
|
385
|
-
return Object.keys(this.blurData).filter(
|
|
386
|
-
(key) => key.toLowerCase().includes(lower)
|
|
387
|
-
);
|
|
388
|
-
}
|
|
389
|
-
};
|
|
390
|
-
function createBlurService(options) {
|
|
391
|
-
return new BlurService(options);
|
|
392
|
-
}
|
|
393
|
-
var blurService = new BlurService();
|
|
394
|
-
|
|
395
|
-
exports.BlurService = BlurService;
|
|
396
|
-
exports.DEFAULT_CDN_PATTERNS = DEFAULT_CDN_PATTERNS;
|
|
397
|
-
exports.DEFAULT_PLACEHOLDERS = DEFAULT_PLACEHOLDERS;
|
|
398
|
-
exports.LRUCache = LRUCache;
|
|
399
|
-
exports.blurService = blurService;
|
|
400
|
-
exports.createBlurService = createBlurService;
|
|
401
|
-
exports.createSrcSetWithBlur = createSrcSetWithBlur;
|
|
402
|
-
exports.decodeBlurHashToDataURL = decodeBlurHashToDataURL;
|
|
403
|
-
exports.extractImageUrls = extractImageUrls;
|
|
404
|
-
exports.getBackgroundPropsWithBlur = getBackgroundPropsWithBlur;
|
|
405
|
-
exports.getBlurData = getBlurData;
|
|
406
|
-
exports.getBlurPlaceholderStyle = getBlurPlaceholderStyle;
|
|
407
|
-
exports.getBulkBlurData = getBulkBlurData;
|
|
408
|
-
exports.getImagePropsWithBlur = getImagePropsWithBlur;
|
|
409
|
-
exports.hasBlurData = hasBlurData;
|
|
410
|
-
exports.normalizeImagePath = normalizeImagePath;
|
|
411
|
-
exports.preloadImageWithBlur = preloadImageWithBlur;
|
|
412
|
-
//# sourceMappingURL=blur.cjs.map
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
var _chunkWISG74VLcjs = require('./chunk-WISG74VL.cjs');
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
var _chunk3ICG2SLLcjs = require('./chunk-3ICG2SLL.cjs');
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
exports.BlurService = _chunkWISG74VLcjs.BlurService; exports.DEFAULT_CDN_PATTERNS = _chunkWISG74VLcjs.DEFAULT_CDN_PATTERNS; exports.DEFAULT_PLACEHOLDERS = _chunkWISG74VLcjs.DEFAULT_PLACEHOLDERS; exports.LRUCache = _chunkWISG74VLcjs.LRUCache; exports.blurService = _chunkWISG74VLcjs.blurService; exports.createBlurService = _chunkWISG74VLcjs.createBlurService; exports.createSrcSetWithBlur = _chunk3ICG2SLLcjs.createSrcSetWithBlur; exports.decodeBlurHashToDataURL = _chunk3ICG2SLLcjs.decodeBlurHashToDataURL; exports.extractImageUrls = _chunk3ICG2SLLcjs.extractImageUrls; exports.getBackgroundPropsWithBlur = _chunk3ICG2SLLcjs.getBackgroundPropsWithBlur; exports.getBlurData = _chunk3ICG2SLLcjs.getBlurData; exports.getBlurPlaceholderStyle = _chunk3ICG2SLLcjs.getBlurPlaceholderStyle; exports.getBulkBlurData = _chunk3ICG2SLLcjs.getBulkBlurData; exports.getImagePropsWithBlur = _chunk3ICG2SLLcjs.getImagePropsWithBlur; exports.hasBlurData = _chunk3ICG2SLLcjs.hasBlurData; exports.normalizeImagePath = _chunkWISG74VLcjs.normalizeImagePath; exports.preloadImageWithBlur = _chunk3ICG2SLLcjs.preloadImageWithBlur;
|
|
413
41
|
//# sourceMappingURL=blur.cjs.map
|
package/dist/blur.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/blur/blurDataUtils.ts","../src/blur/lruCache.ts","../src/blur/pathMapper.ts","../src/blur/placeholders.ts","../src/blur/blurService.ts"],"names":["isBlurhashValid","decodeBlurHash"],"mappings":";;;;;AAaO,SAAS,YACd,KAAA,EACU;AACV,EAAA,IAAI,CAAC,KAAA,EAAO;AACV,IAAA,OAAO;AAAA,MACL,WAAA,EAAa,EAAA;AAAA,MACb,SAAA,EAAW,SAAA;AAAA,MACX,OAAA,EAAS;AAAA,KACX;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,WAAA,EAAa,MAAM,WAAA,IAAe,EAAA;AAAA,IAClC,SAAA,EAAW,MAAM,SAAA,IAAa,SAAA;AAAA,IAC9B,GAAI,MAAM,QAAA,GAAW,EAAE,UAAU,KAAA,CAAM,QAAA,KAAa,EAAC;AAAA,IACrD,OAAA,EAAS,OAAA,CAAQ,KAAA,CAAM,WAAA,IAAe,MAAM,QAAQ;AAAA,GACtD;AACF;AAEO,SAAS,sBACd,KAAA,EACA;AACA,EAAA,IAAI,CAAC,OAAO,GAAA,EAAK;AACf,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,MAAM,QAAA,GAAW,YAAY,KAAK,CAAA;AAElC,EAAA,OAAO;AAAA,IACL,KAAK,KAAA,CAAM,GAAA;AAAA,IACX,GAAA,EAAK,MAAM,OAAA,IAAW,EAAA;AAAA,IACtB,KAAA,EAAO,MAAM,KAAA,IAAS,IAAA;AAAA,IACtB,MAAA,EAAQ,MAAM,MAAA,IAAU,IAAA;AAAA,IACxB,GAAI,SAAS,WAAA,IAAe;AAAA,MAC1B,WAAA,EAAa,MAAA;AAAA,MACb,aAAa,QAAA,CAAS;AAAA;AACxB,GACF;AACF;AAEO,SAAS,2BACd,KAAA,EACsB;AACtB,EAAA,IAAI,CAAC,OAAO,GAAA,EAAK;AACf,IAAA,OAAO;AAAA,MACL,eAAA,EAAiB;AAAA,KACnB;AAAA,EACF;AAEA,EAAA,MAAM,QAAA,GAAW,YAAY,KAAK,CAAA;AAElC,EAAA,OAAO;AAAA,IACL,iBAAiB,QAAA,CAAS,SAAA;AAAA,IAC1B,eAAA,EAAiB,CAAA,IAAA,EAAO,KAAA,CAAM,GAAG,CAAA,CAAA,CAAA;AAAA,IACjC,cAAA,EAAgB,OAAA;AAAA,IAChB,kBAAA,EAAoB,QAAA;AAAA,IACpB,gBAAA,EAAkB;AAAA,GACpB;AACF;AAEO,SAAS,wBACd,KAAA,EACsB;AACtB,EAAA,MAAM,QAAA,GAAW,YAAY,KAAK,CAAA;AAElC,EAAA,IAAI,CAAC,SAAS,WAAA,EAAa;AACzB,IAAA,OAAO;AAAA,MACL,iBAAiB,QAAA,CAAS;AAAA,KAC5B;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,iBAAiB,QAAA,CAAS,SAAA;AAAA,IAC1B,eAAA,EAAiB,CAAA,IAAA,EAAO,QAAA,CAAS,WAAW,CAAA,CAAA,CAAA;AAAA,IAC5C,cAAA,EAAgB,OAAA;AAAA,IAChB,kBAAA,EAAoB,QAAA;AAAA,IACpB,MAAA,EAAQ,YAAA;AAAA,IACR,SAAA,EAAW;AAAA,GACb;AACF;AAEO,SAAS,YACd,KAAA,EACS;AACT,EAAA,OAAO,QAAQ,KAAA,EAAO,WAAA,IAAe,KAAA,EAAO,SAAA,IAAa,OAAO,QAAQ,CAAA;AAC1E;AAEO,SAAS,gBACd,MAAA,EACY;AACZ,EAAA,OAAO,MAAA,CAAO,IAAI,WAAW,CAAA;AAC/B;AAEO,SAAS,qBACd,KAAA,EACQ;AACR,EAAA,IAAI,CAAC,KAAA,EAAO,GAAA,EAAK,OAAO,EAAA;AAExB,EAAA,MAAM,QAAA,GAAW,YAAY,KAAK,CAAA;AAClC,EAAA,IAAI,CAAC,SAAS,WAAA,EAAa;AACzB,IAAA,OAAO,KAAA,CAAM,GAAA;AAAA,EACf;AAEA,EAAA,OAAO,CAAA,EAAG,SAAS,WAAW,CAAA,MAAA,EAAS,MAAM,GAAG,CAAA,CAAA,EAAI,KAAA,CAAM,KAAA,IAAS,IAAI,CAAA,CAAA,CAAA;AACzE;AAEO,SAAS,qBACd,KAAA,EACM;AACN,EAAA,IAAI,CAAC,KAAA,EAAO,GAAA,IAAO,OAAO,aAAa,WAAA,EAAa;AAEpD,EAAA,MAAM,IAAA,GAAO,QAAA,CAAS,aAAA,CAAc,MAAM,CAAA;AAC1C,EAAA,IAAA,CAAK,GAAA,GAAM,SAAA;AACX,EAAA,IAAA,CAAK,EAAA,GAAK,OAAA;AACV,EAAA,IAAA,CAAK,OAAO,KAAA,CAAM,GAAA;AAElB,EAAA,MAAM,QAAA,GAAW,YAAY,KAAK,CAAA;AAClC,EAAA,IAAI,SAAS,WAAA,EAAa;AACxB,IAAA,IAAA,CAAK,YAAA,CAAa,aAAA,EAAe,QAAA,CAAS,WAAW,CAAA;AAAA,EACvD;AAEA,EAAA,QAAA,CAAS,IAAA,CAAK,YAAY,IAAI,CAAA;AAChC;AAEO,SAAS,iBACd,KAAA,EACU;AACV,EAAA,IAAI,CAAC,KAAA,EAAO,GAAA,EAAK,OAAO,EAAC;AACzB,EAAA,OAAO,CAAC,MAAM,GAAG,CAAA;AACnB;AAMO,SAAS,wBACd,IAAA,EACA,KAAA,GAAgB,IAChB,MAAA,GAAiB,EAAA,EACjB,QAAgB,CAAA,EACD;AACf,EAAA,IAAI,CAAC,IAAA,IAAQ,OAAO,QAAA,KAAa,aAAa,OAAO,IAAA;AACrD,EAAA,MAAM,UAAA,GAAaA,yBAAgB,IAAI,CAAA;AACvC,EAAA,IAAI,CAAC,UAAA,CAAW,MAAA,EAAQ,OAAO,IAAA;AAE/B,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAASC,eAAA,CAAe,IAAA,EAAM,KAAA,EAAO,QAAQ,KAAK,CAAA;AACxD,IAAA,MAAM,MAAA,GAAS,QAAA,CAAS,aAAA,CAAc,QAAQ,CAAA;AAC9C,IAAA,MAAA,CAAO,KAAA,GAAQ,KAAA;AACf,IAAA,MAAA,CAAO,MAAA,GAAS,MAAA;AAChB,IAAA,MAAM,GAAA,GAAM,MAAA,CAAO,UAAA,CAAW,IAAI,CAAA;AAClC,IAAA,IAAI,CAAC,KAAK,OAAO,IAAA;AACjB,IAAA,MAAM,SAAA,GAAY,GAAA,CAAI,eAAA,CAAgB,KAAA,EAAO,MAAM,CAAA;AACnD,IAAA,SAAA,CAAU,IAAA,CAAK,IAAI,MAAM,CAAA;AACzB,IAAA,GAAA,CAAI,YAAA,CAAa,SAAA,EAAW,CAAA,EAAG,CAAC,CAAA;AAChC,IAAA,OAAO,MAAA,CAAO,UAAU,WAAW,CAAA;AAAA,EACrC,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;;;AC5KO,IAAM,WAAN,MAAqB;AAAA,EACT,OAAA;AAAA,EACA,KAAA;AAAA,EAEjB,WAAA,CAAY,UAAkB,GAAA,EAAK;AACjC,IAAA,IAAA,CAAK,OAAA,GAAU,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,OAAO,CAAA;AAClC,IAAA,IAAA,CAAK,KAAA,uBAAY,GAAA,EAAI;AAAA,EACvB;AAAA,EAEA,IAAI,GAAA,EAAuB;AACzB,IAAA,IAAI,CAAC,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,GAAG,GAAG,OAAO,MAAA;AAEjC,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,GAAG,CAAA;AAChC,IAAA,IAAA,CAAK,KAAA,CAAM,OAAO,GAAG,CAAA;AACrB,IAAA,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,GAAA,EAAK,KAAK,CAAA;AACzB,IAAA,OAAO,KAAA;AAAA,EACT;AAAA,EAEA,GAAA,CAAI,KAAQ,KAAA,EAAgB;AAC1B,IAAA,IAAI,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,GAAG,CAAA,EAAG;AACvB,MAAA,IAAA,CAAK,KAAA,CAAM,OAAO,GAAG,CAAA;AAAA,IACvB;AAEA,IAAA,IAAI,IAAA,CAAK,KAAA,CAAM,IAAA,IAAQ,IAAA,CAAK,OAAA,EAAS;AACnC,MAAA,MAAM,WAAW,IAAA,CAAK,KAAA,CAAM,IAAA,EAAK,CAAE,MAAK,CAAE,KAAA;AAC1C,MAAA,IAAI,aAAa,MAAA,EAAW;AAC1B,QAAA,IAAA,CAAK,KAAA,CAAM,OAAO,QAAQ,CAAA;AAAA,MAC5B;AAAA,IACF;AAEA,IAAA,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,GAAA,EAAK,KAAK,CAAA;AAAA,EAC3B;AAAA,EAEA,IAAI,GAAA,EAAiB;AACnB,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,GAAG,CAAA;AAAA,EAC3B;AAAA,EAEA,KAAA,GAAc;AACZ,IAAA,IAAA,CAAK,MAAM,KAAA,EAAM;AAAA,EACnB;AAAA,EAEA,IAAI,IAAA,GAAe;AACjB,IAAA,OAAO,KAAK,KAAA,CAAM,IAAA;AAAA,EACpB;AACF;;;AC5CO,IAAM,oBAAA,GAAiC;AAAA,EAC5C,8EAAA;AAAA,EACA,mCAAA;AAAA,EACA,0CAAA;AAAA,EACA,2CAAA;AAAA,EACA;AACF;AAqBO,SAAS,kBAAA,CACd,QAAA,EACA,OAAA,GAAgC,EAAC,EACvB;AACV,EAAA,MAAM,YAAA,GAAe,QAAA;AACrB,EAAA,IAAI,cAAA,GAAiB,QAAA;AACrB,EAAA,IAAI,UAAA,GAAa,KAAA;AAEjB,EAAA,IAAI;AACF,IAAA,IAAI,SAAS,UAAA,CAAW,OAAO,KAAK,QAAA,CAAS,UAAA,CAAW,OAAO,CAAA,EAAG;AAChE,MAAA,OAAO;AAAA,QACL,cAAA,EAAgB,QAAA;AAAA,QAChB,UAAA,EAAY,KAAA;AAAA,QACZ;AAAA,OACF;AAAA,IACF;AAEA,IAAA,MAAM,QAAA,GAAW,QAAQ,WAAA,IAAe,oBAAA;AAExC,IAAA,IAAI,SAAS,UAAA,CAAW,SAAS,KAAK,QAAA,CAAS,UAAA,CAAW,UAAU,CAAA,EAAG;AACrE,MAAA,MAAM,GAAA,GAAM,IAAI,GAAA,CAAI,QAAQ,CAAA;AAC5B,MAAA,UAAA,GAAa,IAAA;AACb,MAAA,MAAM,kBAAkB,CAAA,EAAG,GAAA,CAAI,MAAM,CAAA,EAAG,IAAI,QAAQ,CAAA,CAAA;AAEpD,MAAA,KAAA,MAAW,WAAW,QAAA,EAAU;AAC9B,QAAA,MAAM,KAAA,GAAQ,eAAA,CAAgB,KAAA,CAAM,OAAO,CAAA;AAC3C,QAAA,IAAI,KAAA,EAAO;AACT,UAAA,MAAM,QAAA,GAAW,KAAA,CAAM,KAAA,CAAM,MAAA,GAAS,CAAC,CAAA;AACvC,UAAA,cAAA,GAAiB,GAAA,GAAM,QAAA,CAAS,OAAA,CAAQ,MAAA,EAAQ,EAAE,CAAA;AAClD,UAAA;AAAA,QACF;AAAA,MACF;AAEA,MAAA,IAAI,mBAAmB,QAAA,EAAU;AAC/B,QAAA,cAAA,GAAiB,GAAA,CAAI,QAAA;AAAA,MACvB;AAAA,IACF,CAAA,MAAO;AACL,MAAA,cAAA,GAAiB,cAAA,CAAe,MAAM,GAAG,CAAA,CAAE,CAAC,CAAA,CAAE,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,CAAA;AAAA,IAC5D;AAEA,IAAA,cAAA,GAAiB,eAAe,OAAA,CAAQ,KAAA,EAAO,GAAG,CAAA,CAAE,OAAA,CAAQ,aAAa,EAAE,CAAA;AAE3E,IAAA,IAAI,CAAC,cAAA,CAAe,UAAA,CAAW,GAAG,CAAA,EAAG;AACnC,MAAA,cAAA,GAAiB,GAAA,GAAM,cAAA;AAAA,IACzB;AAEA,IAAA,MAAM,eAAA,GAAkB,OAAA,CAAQ,aAAA,IAAiB,CAAC,UAAU,CAAA;AAC5D,IAAA,KAAA,MAAW,UAAU,eAAA,EAAiB;AACpC,MAAA,IAAI,cAAA,CAAe,UAAA,CAAW,MAAM,CAAA,EAAG;AACrC,QAAA,cAAA,GAAiB,GAAA,GAAM,eAAe,KAAA,CAAM,MAAA,CAAO,MAAM,CAAA,CAAE,OAAA,CAAQ,QAAQ,EAAE,CAAA;AAAA,MAC/E;AAAA,IACF;AAEA,IAAA,MAAM,WAAW,cAAA,CAAe,KAAA,CAAM,GAAG,CAAA,CAAE,OAAO,OAAO,CAAA;AACzD,IAAA,MAAM,QAAA,GAAW,QAAA,CAAS,QAAA,CAAS,MAAA,GAAS,CAAC,CAAA;AAC7C,IAAA,MAAM,MAAA,GACJ,QAAA,CAAS,MAAA,GAAS,CAAA,GAAI,QAAA,CAAS,KAAA,CAAM,CAAA,EAAG,CAAA,CAAE,CAAA,CAAE,IAAA,CAAK,GAAG,CAAA,GAAI,KAAA,CAAA;AAC1D,IAAA,MAAM,MAAA,GAAS,QAAA,GAAW,QAAA,CAAS,WAAA,CAAY,GAAG,CAAA,GAAI,CAAA,CAAA;AACtD,IAAA,MAAM,SAAA,GACJ,QAAA,IAAY,MAAA,GAAS,CAAA,GAAI,QAAA,CAAS,MAAM,MAAA,GAAS,CAAC,CAAA,CAAE,WAAA,EAAY,GAAI,KAAA,CAAA;AAEtE,IAAA,OAAO;AAAA,MACL,cAAA;AAAA,MACA,MAAA;AAAA,MACA,QAAA;AAAA,MACA,SAAA;AAAA,MACA,UAAA;AAAA,MACA;AAAA,KACF;AAAA,EACF,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO;AAAA,MACL,cAAA,EAAgB,QAAA;AAAA,MAChB,UAAA,EAAY,KAAA;AAAA,MACZ;AAAA,KACF;AAAA,EACF;AACF;;;ACrGO,IAAM,oBAAA,GAA4D;AAAA,EACvE,OAAA,EACE,wmBAAA;AAAA,EACF,IAAA,EACE,gtBAAA;AAAA,EACF,IAAA,EACE,giBAAA;AAAA,EACF,SAAA,EACE;AACJ;;;ACOO,IAAM,cAAN,MAAkB;AAAA,EACf,QAAA;AAAA,EACS,KAAA;AAAA,EACA,WAAA;AAAA,EACT,QAAA;AAAA,EAKA,OAAA;AAAA,EAER,WAAA,CAAY,OAAA,GAA8B,EAAC,EAAG;AAC5C,IAAA,IAAA,CAAK,WAAW,EAAC;AACjB,IAAA,IAAA,CAAK,cAAc,OAAA,CAAQ,WAAA;AAC3B,IAAA,IAAA,CAAK,QAAA,GAAW;AAAA,MACd,OAAA,EAAS,KAAA;AAAA,MACT,WAAA,EAAA,iBAAa,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,MACpC,WAAA,EAAa;AAAA,KACf;AACA,IAAA,IAAA,CAAK,KAAA,GAAQ,IAAI,QAAA,CAAS,OAAA,CAAQ,aAAa,GAAG,CAAA;AAClD,IAAA,IAAA,CAAK,OAAA,GAAU;AAAA,MACb,aAAA,EAAe,CAAA;AAAA,MACf,SAAA,EAAW,CAAA;AAAA,MACX,WAAA,EAAa,CAAA;AAAA,MACb,MAAA,EAAQ;AAAA,KACV;AAEA,IAAA,IAAI,QAAQ,QAAA,EAAU;AACpB,MAAA,IAAA,CAAK,YAAA,CAAa,QAAQ,QAAQ,CAAA;AAAA,IACpC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,aACE,QAAA,EACM;AACN,IAAA,IAAA,CAAK,MAAM,KAAA,EAAM;AAEjB,IAAA,IAAI,QAAA,IAAY,YAAY,OAAO,QAAA,CAAS,WAAW,QAAA,IAAY,QAAA,CAAS,WAAW,IAAA,EAAM;AAC3F,MAAA,MAAM,KAAA,GAAQ,QAAA;AACd,MAAA,IAAA,CAAK,QAAA,GAAW,EAAE,GAAG,KAAA,CAAM,MAAA,EAAO;AAClC,MAAA,IAAA,CAAK,QAAA,GAAW;AAAA,QACd,OAAA,EAAS,MAAM,OAAA,IAAW,KAAA;AAAA,QAC1B,aAAa,KAAA,CAAM,WAAA,IAAA,iBAAe,IAAI,IAAA,IAAO,WAAA,EAAY;AAAA,QACzD,WAAA,EAAa,MAAA,CAAO,IAAA,CAAK,IAAA,CAAK,QAAQ,CAAA,CAAE;AAAA,OAC1C;AAAA,IACF,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,QAAA,GAAW,EAAE,GAAI,QAAA,EAA+C;AACrE,MAAA,IAAA,CAAK,QAAA,GAAW;AAAA,QACd,OAAA,EAAS,KAAA;AAAA,QACT,WAAA,EAAA,iBAAa,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,QACpC,WAAA,EAAa,MAAA,CAAO,IAAA,CAAK,IAAA,CAAK,QAAQ,CAAA,CAAE;AAAA,OAC1C;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,aAAA,CAAc,WAAmB,KAAA,EAAgC;AAC/D,IAAA,IAAA,CAAK,QAAA,CAAS,SAAS,CAAA,GAAI,KAAA;AAC3B,IAAA,IAAA,CAAK,SAAS,WAAA,GAAc,MAAA,CAAO,IAAA,CAAK,IAAA,CAAK,QAAQ,CAAA,CAAE,MAAA;AACvD,IAAA,IAAA,CAAK,MAAM,KAAA,EAAM;AAAA,EACnB;AAAA,EAEA,qBAAA,CAAsB,OAA4B,SAAA,EAAmB;AACnE,IAAA,OAAO,qBAAqB,IAAI,CAAA;AAAA,EAClC;AAAA,EAEQ,mBAAmB,QAAA,EAA4C;AACrE,IAAA,IAAI,IAAA,GAAO,IAAA,CAAK,QAAA,CAAS,QAAQ,CAAA;AACjC,IAAA,IAAI,MAAM,OAAO,IAAA;AAEjB,IAAA,MAAM,QAAA,GAAW,kBAAA,CAAmB,QAAA,EAAU,IAAA,CAAK,WAAW,CAAA;AAC9D,IAAA,IAAA,GAAO,IAAA,CAAK,QAAA,CAAS,QAAA,CAAS,cAAc,CAAA;AAC5C,IAAA,IAAI,MAAM,OAAO,IAAA;AAEjB,IAAA,MAAM,SAAA,GAAY,SAAS,cAAA,CAAe,UAAA,CAAW,GAAG,CAAA,GACpD,QAAA,CAAS,cAAA,GACT,GAAA,GAAM,QAAA,CAAS,cAAA;AACnB,IAAA,MAAM,YAAA,GAAe,QAAA,CAAS,cAAA,CAAe,OAAA,CAAQ,QAAQ,EAAE,CAAA;AAE/D,IAAA,IAAA,GAAO,KAAK,QAAA,CAAS,SAAS,CAAA,IAAK,IAAA,CAAK,SAAS,YAAY,CAAA;AAC7D,IAAA,IAAI,MAAM,OAAO,IAAA;AAEjB,IAAA,IAAI,QAAA,CAAS,UAAA,IAAc,QAAA,CAAS,YAAA,KAAiB,QAAA,EAAU;AAC7D,MAAA,IAAA,GAAO,IAAA,CAAK,QAAA,CAAS,QAAA,CAAS,YAAY,CAAA;AAC1C,MAAA,IAAI,MAAM,OAAO,IAAA;AAAA,IACnB;AAEA,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EAEA,iBAAiB,QAAA,EAA0B;AACzC,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,kBAAA,CAAmB,QAAQ,CAAA;AAC7C,IAAA,OAAO,MAAM,KAAA,IAAS,SAAA;AAAA,EACxB;AAAA,EAEA,cAAA,CACE,QAAA,EACA,OAAA,GAGI,EAAC,EACG;AACR,IAAA,MAAM,EAAE,IAAA,GAAO,SAAA,EAAW,IAAA,GAAO,SAAQ,GAAI,OAAA;AAE7C,IAAA,IAAA,CAAK,OAAA,CAAQ,aAAA,EAAA;AAEb,IAAA,MAAM,QAAA,GAAW,CAAA,EAAG,QAAQ,CAAA,CAAA,EAAI,IAAI,CAAA,CAAA;AACpC,IAAA,IAAI,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,QAAQ,CAAA,EAAG;AAC5B,MAAA,IAAA,CAAK,OAAA,CAAQ,SAAA,EAAA;AACb,MAAA,OAAO,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,QAAQ,CAAA,CAAG,OAAA;AAAA,IACnC;AAEA,IAAA,IAAA,CAAK,OAAA,CAAQ,WAAA,EAAA;AAEb,IAAA,IAAI,OAAO,IAAA,CAAK,IAAA,CAAK,QAAQ,CAAA,CAAE,WAAW,CAAA,EAAG;AAC3C,MAAA,OAAO,IAAA,CAAK,sBAAsB,IAAI,CAAA;AAAA,IACxC;AAEA,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,kBAAA,CAAmB,QAAQ,CAAA;AAC7C,IAAA,IAAI,CAAC,IAAA,EAAM;AACT,MAAA,OAAO,IAAA,CAAK,sBAAsB,IAAI,CAAA;AAAA,IACxC;AAEA,IAAA,MAAM,WAAA,GACJ,IAAA,CAAK,QAAA,GAAW,IAAI,CAAA,IACpB,KAAK,QAAA,EAAU,KAAA,IACf,IAAA,CAAK,qBAAA,CAAsB,IAAI,CAAA;AAEjC,IAAA,IAAA,CAAK,KAAA,CAAM,IAAI,QAAA,EAAU;AAAA,MACvB,OAAA,EAAS,WAAA;AAAA,MACT,SAAA,EAAW,KAAK,GAAA;AAAI,KACrB,CAAA;AAED,IAAA,OAAO,WAAA;AAAA,EACT;AAAA,EAEA,eAAA,CACE,SAAA,EACA,OAAA,GAGI,EAAC,EACmB;AACxB,IAAA,MAAM,SAAiC,EAAC;AACxC,IAAA,KAAA,MAAW,YAAY,SAAA,EAAW;AAChC,MAAA,MAAA,CAAO,QAAQ,CAAA,GAAI,IAAA,CAAK,cAAA,CAAe,UAAU,OAAO,CAAA;AAAA,IAC1D;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AAAA,EAEA,kBAAA,CAAmB,QAAA,EAAkB,IAAA,GAAiB,OAAA,EAAS;AAC7D,IAAA,OAAO;AAAA,MACL,KAAA,EAAO,IAAA,CAAK,gBAAA,CAAiB,QAAQ,CAAA;AAAA,MACrC,MAAM,IAAA,CAAK,cAAA,CAAe,QAAA,EAAU,EAAE,MAAM,CAAA;AAAA,MAC5C,OAAA,EAAS,IAAA,CAAK,WAAA,CAAY,QAAQ;AAAA,KACpC;AAAA,EACF;AAAA,EAEA,YAAY,QAAA,EAA2B;AACrC,IAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,kBAAA,CAAmB,QAAQ,CAAC,CAAA;AAAA,EAClD;AAAA,EAEA,WAAA,GAAc;AACZ,IAAA,MAAM,YAAA,GACJ,IAAA,CAAK,OAAA,CAAQ,aAAA,GAAgB,KAEtB,IAAA,CAAK,OAAA,CAAQ,SAAA,GAAY,IAAA,CAAK,OAAA,CAAQ,aAAA,GACvC,GAAA,EACA,OAAA,CAAQ,CAAC,CAAA,GACX,MAAA;AAEN,IAAA,OAAO;AAAA,MACL,GAAG,IAAA,CAAK,QAAA;AAAA,MACR,SAAA,EAAW,KAAK,KAAA,CAAM,IAAA;AAAA,MACtB,OAAA,EAAS;AAAA,QACP,GAAG,IAAA,CAAK,OAAA;AAAA,QACR,YAAA,EAAc,GAAG,YAAY,CAAA,CAAA;AAAA;AAC/B,KACF;AAAA,EACF;AAAA,EAEA,UAAA,GAAmB;AACjB,IAAA,IAAA,CAAK,MAAM,KAAA,EAAM;AAAA,EACnB;AAAA,EAEA,YAAY,QAAA,EAAiC;AAC3C,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,kBAAA,CAAmB,QAAQ,CAAA;AAC7C,IAAA,OAAO,MAAM,IAAA,IAAQ,IAAA;AAAA,EACvB;AAAA,EAEA,eAAA,CAAgB,SAAA,EAAqB,IAAA,GAAiB,OAAA,EAAe;AACnE,IAAA,KAAA,MAAW,YAAY,SAAA,EAAW;AAChC,MAAA,IAAA,CAAK,cAAA,CAAe,QAAA,EAAU,EAAE,IAAA,EAAM,CAAA;AAAA,IACxC;AAAA,EACF;AAAA,EAEA,MAAM,qBAAA,CACJ,QAAA,EACA,IAAA,GAA4B,SAAA,EACX;AACjB,IAAA,OAAO,OAAA,CAAQ,QAAQ,IAAA,CAAK,cAAA,CAAe,UAAU,EAAE,IAAA,EAAM,CAAC,CAAA;AAAA,EAChE;AAAA,EAEA,gBAAA,GAA6B;AAC3B,IAAA,OAAO,MAAA,CAAO,IAAA,CAAK,IAAA,CAAK,QAAQ,CAAA;AAAA,EAClC;AAAA,EAEA,iBAAiB,UAAA,EAA8B;AAC7C,IAAA,MAAM,KAAA,GAAQ,WAAW,WAAA,EAAY;AACrC,IAAA,OAAO,MAAA,CAAO,IAAA,CAAK,IAAA,CAAK,QAAQ,CAAA,CAAE,MAAA;AAAA,MAAO,CAAC,GAAA,KACxC,GAAA,CAAI,WAAA,EAAY,CAAE,SAAS,KAAK;AAAA,KAClC;AAAA,EACF;AACF;AAEO,SAAS,kBAAkB,OAAA,EAA2C;AAC3E,EAAA,OAAO,IAAI,YAAY,OAAO,CAAA;AAChC;AAEO,IAAM,WAAA,GAAc,IAAI,WAAA","file":"blur.cjs","sourcesContent":["import { decode as decodeBlurHash, isBlurhashValid } from 'blurhash';\nimport type { BlurData, BlurImageSource } from './types';\n\nexport interface BlurPlaceholderStyle {\n backgroundColor: string;\n backgroundImage?: string;\n backgroundSize?: string;\n backgroundPosition?: string;\n backgroundRepeat?: string;\n filter?: string;\n transform?: string;\n}\n\nexport function getBlurData(\n image: BlurImageSource | null | undefined,\n): BlurData {\n if (!image) {\n return {\n blurDataUrl: '',\n blurColor: '#E5E7EB',\n hasBlur: false,\n };\n }\n\n return {\n blurDataUrl: image.blurDataUrl || '',\n blurColor: image.blurColor || '#E5E7EB',\n ...(image.blurHash ? { blurHash: image.blurHash } : {}),\n hasBlur: Boolean(image.blurDataUrl || image.blurHash),\n };\n}\n\nexport function getImagePropsWithBlur(\n image: BlurImageSource | null | undefined,\n) {\n if (!image?.url) {\n return null;\n }\n\n const blurData = getBlurData(image);\n\n return {\n src: image.url,\n alt: image.altText || '',\n width: image.width || 1920,\n height: image.height || 1080,\n ...(blurData.blurDataUrl && {\n placeholder: 'blur' as const,\n blurDataURL: blurData.blurDataUrl,\n }),\n };\n}\n\nexport function getBackgroundPropsWithBlur(\n image: BlurImageSource | null | undefined,\n): BlurPlaceholderStyle {\n if (!image?.url) {\n return {\n backgroundColor: '#E5E7EB',\n };\n }\n\n const blurData = getBlurData(image);\n\n return {\n backgroundColor: blurData.blurColor,\n backgroundImage: `url(${image.url})`,\n backgroundSize: 'cover',\n backgroundPosition: 'center',\n backgroundRepeat: 'no-repeat',\n };\n}\n\nexport function getBlurPlaceholderStyle(\n image: BlurImageSource | null | undefined,\n): BlurPlaceholderStyle {\n const blurData = getBlurData(image);\n\n if (!blurData.blurDataUrl) {\n return {\n backgroundColor: blurData.blurColor,\n };\n }\n\n return {\n backgroundColor: blurData.blurColor,\n backgroundImage: `url(${blurData.blurDataUrl})`,\n backgroundSize: 'cover',\n backgroundPosition: 'center',\n filter: 'blur(20px)',\n transform: 'scale(1.1)',\n };\n}\n\nexport function hasBlurData(\n image: BlurImageSource | null | undefined,\n): boolean {\n return Boolean(image?.blurDataUrl || image?.blurColor || image?.blurHash);\n}\n\nexport function getBulkBlurData(\n images: Array<BlurImageSource | null | undefined>,\n): BlurData[] {\n return images.map(getBlurData);\n}\n\nexport function createSrcSetWithBlur(\n image: BlurImageSource | null | undefined,\n): string {\n if (!image?.url) return '';\n\n const blurData = getBlurData(image);\n if (!blurData.blurDataUrl) {\n return image.url;\n }\n\n return `${blurData.blurDataUrl} 40w, ${image.url} ${image.width || 1920}w`;\n}\n\nexport function preloadImageWithBlur(\n image: BlurImageSource | null | undefined,\n): void {\n if (!image?.url || typeof document === 'undefined') return;\n\n const link = document.createElement('link');\n link.rel = 'preload';\n link.as = 'image';\n link.href = image.url;\n\n const blurData = getBlurData(image);\n if (blurData.blurDataUrl) {\n link.setAttribute('imagesrcset', blurData.blurDataUrl);\n }\n\n document.head.appendChild(link);\n}\n\nexport function extractImageUrls(\n image: BlurImageSource | null | undefined,\n): string[] {\n if (!image?.url) return [];\n return [image.url];\n}\n\n/**\n * Browser helper: Decodes a compact BlurHash string (e.g. \"LEHV6nWB2yk8pyo0adR*.7kCMdnj\")\n * into a `data:image/png;base64,...` URL using an offscreen `<canvas>`.\n */\nexport function decodeBlurHashToDataURL(\n hash: string,\n width: number = 32,\n height: number = 32,\n punch: number = 1,\n): string | null {\n if (!hash || typeof document === 'undefined') return null;\n const validation = isBlurhashValid(hash);\n if (!validation.result) return null;\n\n try {\n const pixels = decodeBlurHash(hash, width, height, punch);\n const canvas = document.createElement('canvas');\n canvas.width = width;\n canvas.height = height;\n const ctx = canvas.getContext('2d');\n if (!ctx) return null;\n const imageData = ctx.createImageData(width, height);\n imageData.data.set(pixels);\n ctx.putImageData(imageData, 0, 0);\n return canvas.toDataURL('image/png');\n } catch {\n return null;\n }\n}\n","export class LRUCache<K, V> {\n private readonly maxSize: number;\n private readonly cache: Map<K, V>;\n\n constructor(maxSize: number = 500) {\n this.maxSize = Math.max(1, maxSize);\n this.cache = new Map();\n }\n\n get(key: K): V | undefined {\n if (!this.cache.has(key)) return undefined;\n\n const value = this.cache.get(key)!;\n this.cache.delete(key);\n this.cache.set(key, value);\n return value;\n }\n\n set(key: K, value: V): void {\n if (this.cache.has(key)) {\n this.cache.delete(key);\n }\n\n if (this.cache.size >= this.maxSize) {\n const firstKey = this.cache.keys().next().value;\n if (firstKey !== undefined) {\n this.cache.delete(firstKey);\n }\n }\n\n this.cache.set(key, value);\n }\n\n has(key: K): boolean {\n return this.cache.has(key);\n }\n\n clear(): void {\n this.cache.clear();\n }\n\n get size(): number {\n return this.cache.size;\n }\n}\n","export const DEFAULT_CDN_PATTERNS: RegExp[] = [\n /^https?:\\/\\/[^/]+\\.supabase\\.co\\/storage\\/v1\\/object\\/public\\/([^/]+)\\/(.+)$/,\n /^https?:\\/\\/[^/]+\\.r2\\.dev\\/(.+)$/,\n /^https?:\\/\\/[^/]+\\.amazonaws\\.com\\/(.+)$/,\n /^https?:\\/\\/[^/]+\\.cloudflare\\.com\\/(.+)$/,\n /^https?:\\/\\/cdn\\.[^/]+\\/(.+)$/,\n];\n\nexport interface NormalizePathOptions {\n cdnPatterns?: RegExp[];\n stripPrefixes?: string[];\n}\n\nexport interface PathInfo {\n normalizedPath: string;\n folder?: string;\n filename?: string;\n extension?: string;\n isExternal: boolean;\n originalPath: string;\n}\n\n/**\n * Project-agnostic image URL / path normalizer.\n * Strips query parameters, leading `/public/`, relative `./`, and common CDN prefixes\n * so manifest keys match consistently across local and CDN environments.\n */\nexport function normalizeImagePath(\n imageSrc: string,\n options: NormalizePathOptions = {},\n): PathInfo {\n const originalPath = imageSrc;\n let normalizedPath = imageSrc;\n let isExternal = false;\n\n try {\n if (imageSrc.startsWith('data:') || imageSrc.startsWith('blob:')) {\n return {\n normalizedPath: imageSrc,\n isExternal: false,\n originalPath,\n };\n }\n\n const patterns = options.cdnPatterns || DEFAULT_CDN_PATTERNS;\n\n if (imageSrc.startsWith('http://') || imageSrc.startsWith('https://')) {\n const url = new URL(imageSrc);\n isExternal = true;\n const cleanUrlNoQuery = `${url.origin}${url.pathname}`;\n\n for (const pattern of patterns) {\n const match = cleanUrlNoQuery.match(pattern);\n if (match) {\n const pathPart = match[match.length - 1];\n normalizedPath = '/' + pathPart.replace(/^\\/+/, '');\n break;\n }\n }\n\n if (normalizedPath === imageSrc) {\n normalizedPath = url.pathname;\n }\n } else {\n normalizedPath = normalizedPath.split('?')[0].split('#')[0];\n }\n\n normalizedPath = normalizedPath.replace(/\\\\/g, '/').replace(/^\\.\\.?\\//g, '');\n\n if (!normalizedPath.startsWith('/')) {\n normalizedPath = '/' + normalizedPath;\n }\n\n const prefixesToStrip = options.stripPrefixes || ['/public/'];\n for (const prefix of prefixesToStrip) {\n if (normalizedPath.startsWith(prefix)) {\n normalizedPath = '/' + normalizedPath.slice(prefix.length).replace(/^\\/+/, '');\n }\n }\n\n const segments = normalizedPath.split('/').filter(Boolean);\n const filename = segments[segments.length - 1];\n const folder =\n segments.length > 1 ? segments.slice(0, -1).join('/') : undefined;\n const dotIdx = filename ? filename.lastIndexOf('.') : -1;\n const extension =\n filename && dotIdx > 0 ? filename.slice(dotIdx + 1).toLowerCase() : undefined;\n\n return {\n normalizedPath,\n folder,\n filename,\n extension,\n isExternal,\n originalPath,\n };\n } catch {\n return {\n normalizedPath: imageSrc,\n isExternal: false,\n originalPath,\n };\n }\n}\n","import type { BlurPlaceholderType } from './types';\n\nexport const DEFAULT_PLACEHOLDERS: Record<BlurPlaceholderType, string> = {\n default:\n 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTUwIiBoZWlnaHQ9IjE1MCIgdmlld0JveD0iMCAwIDE1MCAxNTAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkaWVudCIgeDE9IjAlIiB5MT0iMCUiIHgyPSIxMDAlIiB5Mj0iMTAwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3R5bGU9InN0b3AtY29sb3I6IzJhMzIzZDtzdG9wLW9wYWNpdHk6MSIvPjxzdG9wIG9mZnNldD0iNTAlIiBzdHlsZT0ic3RvcC1jb2xvcjojMjEyNzMwO3N0b3Atb3BhY2l0eToxIi8+PHN0b3Agb2Zmc2V0PSIxMDAlIiBzdHlsZT0ic3RvcC1jb2xvcjojMTgxZDI0O3N0b3Atb3BhY2l0eToxIi8+PC9saW5lYXJHcmFkaWVudD48L2RlZnM+PHJlY3Qgd2lkdGg9IjE1MCIgaGVpZ2h0PSIxNTAiIGZpbGw9InVybCgjZ3JhZGllbnQpIi8+PC9zdmc+',\n hero:\n 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTkyMCIgaGVpZ2h0PSIxMDgwIiB2aWV3Qm94PSIwIDAgMTkyMCAxMDgwIiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxkZWZzPjxsaW5lYXJHcmFkaWVudCBpZD0iaGVyb0dyYWRpZW50IiB4MT0iMCUiIHkxPSIwJSIgeDI9IjEwMCUiIHkyPSIxMDAlIj48c3RvcCBvZmZzZXQ9IjAlIiBzdHlsZT0ic3RvcC1jb2xvcjojMmQzNzQ4O3N0b3Atb3BhY2l0eToxIi8+PHN0b3Agb2Zmc2V0PSIzMCUiIHN0eWxlPSJzdG9wLWNvbG9yOiMyMzJiMzg7c3RvcC1vcGFjaXR5OjEiLz48c3RvcCBvZmZzZXQ9IjcwJSIgc3R5bGU9InN0b3AtY29sb3I6IzFlMjUzMDtzdG9wLW9wYWNpdHk6MSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3R5bGU9InN0b3AtY29sb3I6IzE3MWQyNztzdG9wLW9wYWNpdHk6MSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHdpZHRoPSIxOTIwIiBoZWlnaHQ9IjEwODAiIGZpbGw9InVybCgjaGVyb0dyYWRpZW50KSIvPjwvc3ZnPg==',\n card:\n 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAwIiBoZWlnaHQ9IjMwMCIgdmlld0JveD0iMCAwIDQwMCAzMDAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJjYXJkR3JhZGllbnQiIHgxPSIwJSIgeTE9IjAlIiB4Mj0iMTAwJSIgeTI9IjEwMCUiPjxzdG9wIG9mZnNldD0iMCUiIHN0eWxlPSJzdG9wLWNvbG9yOiMyYTMyM2Q7c3RvcC1vcGFjaXR5OjEiLz48c3RvcCBvZmZzZXQ9IjEwMCUiIHN0eWxlPSJzdG9wLWNvbG9yOiMxYzIyMmI7c3RvcC1vcGFjaXR5OjEiLz48L2xpbmVhckdyYWRpZW50PjwvZGVmcz48cmVjdCB3aWR0aD0iNDAwIiBoZWlnaHQ9IjMwMCIgZmlsbD0idXJsKCNjYXJkR3JhZGllbnQpIi8+PC9zdmc+',\n thumbnail:\n 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgdmlld0JveD0iMCAwIDEwMCAxMDAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHJlY3Qgd2lkdGg9IjEwMCIgaGVpZ2h0PSIxMDAiIGZpbGw9IiMyNDJiMzUiLz48L3N2Zz4=',\n};\n","import { LRUCache } from './lruCache';\nimport { normalizeImagePath, type NormalizePathOptions } from './pathMapper';\nimport { DEFAULT_PLACEHOLDERS } from './placeholders';\nimport type {\n BlurCacheEntry,\n BlurManifestData,\n BlurManifestEntry,\n BlurPlaceholderType,\n BlurServiceMetrics,\n BlurSize,\n} from './types';\n\nexport interface BlurServiceOptions {\n cacheSize?: number;\n manifest?: BlurManifestData | Record<string, BlurManifestEntry>;\n pathOptions?: NormalizePathOptions;\n}\n\nexport class BlurService {\n private blurData: Record<string, BlurManifestEntry>;\n private readonly cache: LRUCache<string, BlurCacheEntry>;\n private readonly pathOptions?: NormalizePathOptions;\n private metadata: {\n version: string;\n generatedAt: string;\n totalImages: number;\n };\n private metrics: BlurServiceMetrics;\n\n constructor(options: BlurServiceOptions = {}) {\n this.blurData = {};\n this.pathOptions = options.pathOptions;\n this.metadata = {\n version: '2.0',\n generatedAt: new Date().toISOString(),\n totalImages: 0,\n };\n this.cache = new LRUCache(options.cacheSize ?? 500);\n this.metrics = {\n totalRequests: 0,\n cacheHits: 0,\n cacheMisses: 0,\n errors: 0,\n };\n\n if (options.manifest) {\n this.loadManifest(options.manifest);\n }\n }\n\n /**\n * Hydrate the service with a generated `blur-hashes.json` manifest or hash map.\n */\n loadManifest(\n manifest: BlurManifestData | Record<string, BlurManifestEntry>,\n ): void {\n this.cache.clear();\n\n if ('hashes' in manifest && typeof manifest.hashes === 'object' && manifest.hashes !== null) {\n const typed = manifest as BlurManifestData;\n this.blurData = { ...typed.hashes };\n this.metadata = {\n version: typed.version || '2.0',\n generatedAt: typed.generatedAt || new Date().toISOString(),\n totalImages: Object.keys(this.blurData).length,\n };\n } else {\n this.blurData = { ...(manifest as Record<string, BlurManifestEntry>) };\n this.metadata = {\n version: '2.0',\n generatedAt: new Date().toISOString(),\n totalImages: Object.keys(this.blurData).length,\n };\n }\n }\n\n /**\n * Register or update a single image's blur data at runtime.\n */\n registerEntry(imagePath: string, entry: BlurManifestEntry): void {\n this.blurData[imagePath] = entry;\n this.metadata.totalImages = Object.keys(this.blurData).length;\n this.cache.clear();\n }\n\n getDefaultPlaceholder(type: BlurPlaceholderType = 'default'): string {\n return DEFAULT_PLACEHOLDERS[type];\n }\n\n private findBlurDataByPath(imageSrc: string): BlurManifestEntry | null {\n let data = this.blurData[imageSrc];\n if (data) return data;\n\n const pathInfo = normalizeImagePath(imageSrc, this.pathOptions);\n data = this.blurData[pathInfo.normalizedPath];\n if (data) return data;\n\n const withSlash = pathInfo.normalizedPath.startsWith('/')\n ? pathInfo.normalizedPath\n : '/' + pathInfo.normalizedPath;\n const withoutSlash = pathInfo.normalizedPath.replace(/^\\/+/, '');\n\n data = this.blurData[withSlash] || this.blurData[withoutSlash];\n if (data) return data;\n\n if (pathInfo.isExternal && pathInfo.originalPath !== imageSrc) {\n data = this.blurData[pathInfo.originalPath];\n if (data) return data;\n }\n\n return null;\n }\n\n getDominantColor(imageSrc: string): string {\n const data = this.findBlurDataByPath(imageSrc);\n return data?.color || '#E5E7EB';\n }\n\n getBlurDataURL(\n imageSrc: string,\n options: {\n type?: BlurPlaceholderType;\n size?: BlurSize;\n } = {},\n ): string {\n const { type = 'default', size = 'small' } = options;\n\n this.metrics.totalRequests++;\n\n const cacheKey = `${imageSrc}-${size}`;\n if (this.cache.has(cacheKey)) {\n this.metrics.cacheHits++;\n return this.cache.get(cacheKey)!.dataUrl;\n }\n\n this.metrics.cacheMisses++;\n\n if (Object.keys(this.blurData).length === 0) {\n return this.getDefaultPlaceholder(type);\n }\n\n const data = this.findBlurDataByPath(imageSrc);\n if (!data) {\n return this.getDefaultPlaceholder(type);\n }\n\n const blurDataURL =\n data.variants?.[size] ||\n data.variants?.small ||\n this.getDefaultPlaceholder(type);\n\n this.cache.set(cacheKey, {\n dataUrl: blurDataURL,\n timestamp: Date.now(),\n });\n\n return blurDataURL;\n }\n\n getBulkBlurData(\n imageSrcs: string[],\n options: {\n type?: BlurPlaceholderType;\n size?: BlurSize;\n } = {},\n ): Record<string, string> {\n const result: Record<string, string> = {};\n for (const imageSrc of imageSrcs) {\n result[imageSrc] = this.getBlurDataURL(imageSrc, options);\n }\n return result;\n }\n\n getProgressiveData(imageSrc: string, size: BlurSize = 'small') {\n return {\n color: this.getDominantColor(imageSrc),\n blur: this.getBlurDataURL(imageSrc, { size }),\n hasBlur: this.hasBlurHash(imageSrc),\n };\n }\n\n hasBlurHash(imageSrc: string): boolean {\n return Boolean(this.findBlurDataByPath(imageSrc));\n }\n\n getMetadata() {\n const cacheHitRate =\n this.metrics.totalRequests > 0\n ? (\n (this.metrics.cacheHits / this.metrics.totalRequests) *\n 100\n ).toFixed(2)\n : '0.00';\n\n return {\n ...this.metadata,\n cacheSize: this.cache.size,\n metrics: {\n ...this.metrics,\n cacheHitRate: `${cacheHitRate}%`,\n },\n };\n }\n\n clearCache(): void {\n this.cache.clear();\n }\n\n getBlurHash(imageSrc: string): string | null {\n const data = this.findBlurDataByPath(imageSrc);\n return data?.hash || null;\n }\n\n preloadBlurData(imageSrcs: string[], size: BlurSize = 'small'): void {\n for (const imageSrc of imageSrcs) {\n this.getBlurDataURL(imageSrc, { size });\n }\n }\n\n async fetchBlurDataForImage(\n imageSrc: string,\n type: BlurPlaceholderType = 'default',\n ): Promise<string> {\n return Promise.resolve(this.getBlurDataURL(imageSrc, { type }));\n }\n\n getAvailableKeys(): string[] {\n return Object.keys(this.blurData);\n }\n\n findMatchingKeys(searchTerm: string): string[] {\n const lower = searchTerm.toLowerCase();\n return Object.keys(this.blurData).filter((key) =>\n key.toLowerCase().includes(lower),\n );\n }\n}\n\nexport function createBlurService(options?: BlurServiceOptions): BlurService {\n return new BlurService(options);\n}\n\nexport const blurService = new BlurService();\n"]}
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/image-upload-kit/image-upload-kit/dist/blur.cjs"],"names":[],"mappings":"AAAA;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACF,wDAA6B;AAC7B;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,wDAA6B;AAC7B;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,olCAAC","file":"/home/runner/work/image-upload-kit/image-upload-kit/dist/blur.cjs"}
|
package/dist/blur.d.cts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
export {
|
|
1
|
+
export { B as BlurPlaceholderStyle, c as createSrcSetWithBlur, d as decodeBlurHashToDataURL, e as extractImageUrls, g as getBackgroundPropsWithBlur, a as getBlurData, b as getBlurPlaceholderStyle, f as getBulkBlurData, h as getImagePropsWithBlur, i as hasBlurData, p as preloadImageWithBlur } from './blurDataUtils-DveBRtqE.cjs';
|
|
2
|
+
export { B as BlurService, a as BlurServiceOptions, D as DEFAULT_CDN_PATTERNS, N as NormalizePathOptions, P as PathInfo, b as blurService, c as createBlurService, n as normalizeImagePath } from './blurService-DacwylJx.cjs';
|
|
3
|
+
export { D as DEFAULT_PLACEHOLDERS } from './placeholders-x_3rt65M.cjs';
|
|
4
|
+
export { B as BlurCacheEntry, a as BlurData, b as BlurDataOptions, c as BlurImageSource, d as BlurManifestData, e as BlurManifestEntry, f as BlurPlaceholderType, g as BlurServiceConfig, h as BlurServiceMetrics, i as BlurSize } from './types-yShGNQnW.cjs';
|
|
3
5
|
|
|
4
6
|
declare class LRUCache<K, V> {
|
|
5
7
|
private readonly maxSize;
|
|
@@ -12,6 +14,4 @@ declare class LRUCache<K, V> {
|
|
|
12
14
|
get size(): number;
|
|
13
15
|
}
|
|
14
16
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
export { BlurPlaceholderType, DEFAULT_PLACEHOLDERS, LRUCache };
|
|
17
|
+
export { LRUCache };
|
package/dist/blur.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
export {
|
|
1
|
+
export { B as BlurPlaceholderStyle, c as createSrcSetWithBlur, d as decodeBlurHashToDataURL, e as extractImageUrls, g as getBackgroundPropsWithBlur, a as getBlurData, b as getBlurPlaceholderStyle, f as getBulkBlurData, h as getImagePropsWithBlur, i as hasBlurData, p as preloadImageWithBlur } from './blurDataUtils-yx9Q6HlU.js';
|
|
2
|
+
export { B as BlurService, a as BlurServiceOptions, D as DEFAULT_CDN_PATTERNS, N as NormalizePathOptions, P as PathInfo, b as blurService, c as createBlurService, n as normalizeImagePath } from './blurService-D5TpMNji.js';
|
|
3
|
+
export { D as DEFAULT_PLACEHOLDERS } from './placeholders-C4ftwaII.js';
|
|
4
|
+
export { B as BlurCacheEntry, a as BlurData, b as BlurDataOptions, c as BlurImageSource, d as BlurManifestData, e as BlurManifestEntry, f as BlurPlaceholderType, g as BlurServiceConfig, h as BlurServiceMetrics, i as BlurSize } from './types-yShGNQnW.js';
|
|
3
5
|
|
|
4
6
|
declare class LRUCache<K, V> {
|
|
5
7
|
private readonly maxSize;
|
|
@@ -12,6 +14,4 @@ declare class LRUCache<K, V> {
|
|
|
12
14
|
get size(): number;
|
|
13
15
|
}
|
|
14
16
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
export { BlurPlaceholderType, DEFAULT_PLACEHOLDERS, LRUCache };
|
|
17
|
+
export { LRUCache };
|