img-upload-kit 1.1.1 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +89 -74
- package/MIGRATION.md +192 -0
- package/README.md +243 -259
- 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-25GYKQ6J.js +158 -0
- package/dist/chunk-25GYKQ6J.js.map +1 -0
- package/dist/chunk-34L4TEE3.cjs +226 -0
- package/dist/chunk-34L4TEE3.cjs.map +1 -0
- package/dist/chunk-DFCSN3X7.cjs +158 -0
- package/dist/chunk-DFCSN3X7.cjs.map +1 -0
- package/dist/chunk-EWVIL57J.js +294 -0
- package/dist/chunk-EWVIL57J.js.map +1 -0
- package/dist/chunk-FP5YIWG5.cjs +135 -0
- package/dist/chunk-FP5YIWG5.cjs.map +1 -0
- package/dist/chunk-HILELQGS.js +226 -0
- package/dist/chunk-HILELQGS.js.map +1 -0
- package/dist/chunk-IDLLCVGB.js +2370 -0
- package/dist/chunk-IDLLCVGB.js.map +1 -0
- package/dist/chunk-J6A44Y3W.js +514 -0
- package/dist/chunk-J6A44Y3W.js.map +1 -0
- package/dist/chunk-LOSVFO56.cjs +145 -0
- package/dist/chunk-LOSVFO56.cjs.map +1 -0
- package/dist/chunk-MBQJ6NVJ.cjs +294 -0
- package/dist/chunk-MBQJ6NVJ.cjs.map +1 -0
- package/dist/chunk-MHGQEBPW.js +145 -0
- package/dist/chunk-MHGQEBPW.js.map +1 -0
- package/dist/chunk-QHU7FUO4.cjs +37 -0
- package/dist/chunk-QHU7FUO4.cjs.map +1 -0
- package/dist/chunk-S2IFAWJK.js +37 -0
- package/dist/chunk-S2IFAWJK.js.map +1 -0
- package/dist/chunk-TA5Y64JM.cjs +2370 -0
- package/dist/chunk-TA5Y64JM.cjs.map +1 -0
- package/dist/chunk-VYVZVUNI.js +135 -0
- package/dist/chunk-VYVZVUNI.js.map +1 -0
- package/dist/chunk-XKQMCY5Z.cjs +514 -0
- package/dist/chunk-XKQMCY5Z.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 +235 -220
- 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/index.js
CHANGED
|
@@ -1,506 +1,65 @@
|
|
|
1
|
-
import {
|
|
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
|
-
|
|
1
|
+
import {
|
|
2
|
+
createMemoryStorageAdapter
|
|
3
|
+
} from "./chunk-MHGQEBPW.js";
|
|
4
|
+
import {
|
|
5
|
+
decodeBlurHashToDataURL,
|
|
6
|
+
getBackgroundPropsWithBlur,
|
|
7
|
+
getBlurData,
|
|
8
|
+
getImagePropsWithBlur
|
|
9
|
+
} from "./chunk-VYVZVUNI.js";
|
|
10
|
+
import {
|
|
11
|
+
QUALITY_PRESETS,
|
|
12
|
+
calculateReduction,
|
|
13
|
+
createSuccessMessage,
|
|
14
|
+
estimateOutputSize,
|
|
15
|
+
formatFileSize,
|
|
16
|
+
getFriendlyErrorMessage,
|
|
17
|
+
getStatusMessage
|
|
18
|
+
} from "./chunk-25GYKQ6J.js";
|
|
19
|
+
import {
|
|
20
|
+
DEFAULT_ALLOWED_FORMATS,
|
|
21
|
+
DEFAULT_BLUR_COLOR,
|
|
22
|
+
DEFAULT_IMAGE_DIMENSIONS,
|
|
23
|
+
RASTER_ALLOWED_FORMATS,
|
|
24
|
+
STANDARD_PRESETS,
|
|
25
|
+
SVG_MIME_TYPE,
|
|
26
|
+
defineUploadPresets,
|
|
27
|
+
generateColorSvgDataURL,
|
|
28
|
+
hexToRgb,
|
|
29
|
+
normalizeColorInput,
|
|
30
|
+
rgbToHex,
|
|
31
|
+
validateImageFile,
|
|
32
|
+
validateImageFileStrict,
|
|
33
|
+
validateImageFileWithName,
|
|
34
|
+
validateMultipleFiles
|
|
35
|
+
} from "./chunk-HILELQGS.js";
|
|
36
|
+
export {
|
|
37
|
+
DEFAULT_ALLOWED_FORMATS,
|
|
38
|
+
DEFAULT_BLUR_COLOR,
|
|
39
|
+
DEFAULT_IMAGE_DIMENSIONS,
|
|
40
|
+
QUALITY_PRESETS,
|
|
41
|
+
RASTER_ALLOWED_FORMATS,
|
|
42
|
+
STANDARD_PRESETS,
|
|
43
|
+
SVG_MIME_TYPE,
|
|
44
|
+
calculateReduction,
|
|
45
|
+
createMemoryStorageAdapter,
|
|
46
|
+
createSuccessMessage,
|
|
47
|
+
decodeBlurHashToDataURL,
|
|
48
|
+
defineUploadPresets,
|
|
49
|
+
estimateOutputSize,
|
|
50
|
+
formatFileSize,
|
|
51
|
+
generateColorSvgDataURL,
|
|
52
|
+
getBackgroundPropsWithBlur,
|
|
53
|
+
getBlurData,
|
|
54
|
+
getFriendlyErrorMessage,
|
|
55
|
+
getImagePropsWithBlur,
|
|
56
|
+
getStatusMessage,
|
|
57
|
+
hexToRgb,
|
|
58
|
+
normalizeColorInput,
|
|
59
|
+
rgbToHex,
|
|
60
|
+
validateImageFile,
|
|
61
|
+
validateImageFileStrict,
|
|
62
|
+
validateImageFileWithName,
|
|
63
|
+
validateMultipleFiles
|
|
37
64
|
};
|
|
38
|
-
|
|
39
|
-
// src/types/presets.ts
|
|
40
|
-
var DEFAULT_ALLOWED_FORMATS = [
|
|
41
|
-
"image/jpeg",
|
|
42
|
-
"image/png",
|
|
43
|
-
"image/webp",
|
|
44
|
-
"image/avif",
|
|
45
|
-
"image/svg+xml"
|
|
46
|
-
];
|
|
47
|
-
var RASTER_ALLOWED_FORMATS = [
|
|
48
|
-
"image/jpeg",
|
|
49
|
-
"image/png",
|
|
50
|
-
"image/webp",
|
|
51
|
-
"image/avif"
|
|
52
|
-
];
|
|
53
|
-
var DEFAULT_IMAGE_DIMENSIONS = {
|
|
54
|
-
width: 1920,
|
|
55
|
-
height: 1080
|
|
56
|
-
};
|
|
57
|
-
var STANDARD_PRESETS = {
|
|
58
|
-
thumbnail: {
|
|
59
|
-
folder: "thumbnails",
|
|
60
|
-
maxDimensions: { width: 600, height: 600 },
|
|
61
|
-
maxSizeMB: 5,
|
|
62
|
-
quality: 78,
|
|
63
|
-
recommendedQualityLevel: "medium",
|
|
64
|
-
allowedFormats: RASTER_ALLOWED_FORMATS,
|
|
65
|
-
recommendationNote: {
|
|
66
|
-
en: "Thumbnails display at compact sizes \u2014 Medium quality keeps pages fast",
|
|
67
|
-
ar: "\u0627\u0644\u0645\u0635\u063A\u0631\u0627\u062A \u062A\u0639\u0631\u0636 \u0628\u0623\u062D\u062C\u0627\u0645 \u0635\u063A\u064A\u0631\u0629 \u2014 \u0627\u0644\u062C\u0648\u062F\u0629 \u0627\u0644\u0645\u062A\u0648\u0633\u0637\u0629 \u062A\u062D\u0627\u0641\u0638 \u0639\u0644\u0649 \u0633\u0631\u0639\u0629 \u0627\u0644\u0635\u0641\u062D\u0629"
|
|
68
|
-
}
|
|
69
|
-
},
|
|
70
|
-
avatar: {
|
|
71
|
-
folder: "avatars",
|
|
72
|
-
maxDimensions: { width: 512, height: 512 },
|
|
73
|
-
maxSizeMB: 5,
|
|
74
|
-
quality: 80,
|
|
75
|
-
recommendedQualityLevel: "medium",
|
|
76
|
-
allowedFormats: RASTER_ALLOWED_FORMATS,
|
|
77
|
-
recommendationNote: {
|
|
78
|
-
en: "Avatars display small \u2014 Medium quality balances sharpness and speed",
|
|
79
|
-
ar: "\u0627\u0644\u0635\u0648\u0631 \u0627\u0644\u0634\u062E\u0635\u064A\u0629 \u0635\u063A\u064A\u0631\u0629 \u2014 \u0627\u0644\u062C\u0648\u062F\u0629 \u0627\u0644\u0645\u062A\u0648\u0633\u0637\u0629 \u062A\u0648\u0627\u0632\u0646 \u0628\u064A\u0646 \u0627\u0644\u0648\u0636\u0648\u062D \u0648\u0627\u0644\u0633\u0631\u0639\u0629"
|
|
80
|
-
}
|
|
81
|
-
},
|
|
82
|
-
card: {
|
|
83
|
-
folder: "cards",
|
|
84
|
-
maxDimensions: { width: 1200, height: 900 },
|
|
85
|
-
maxSizeMB: 8,
|
|
86
|
-
quality: 85,
|
|
87
|
-
recommendedQualityLevel: "high",
|
|
88
|
-
allowedFormats: DEFAULT_ALLOWED_FORMATS
|
|
89
|
-
},
|
|
90
|
-
cover: {
|
|
91
|
-
folder: "covers",
|
|
92
|
-
maxDimensions: { width: 1920, height: 1080 },
|
|
93
|
-
maxSizeMB: 10,
|
|
94
|
-
quality: 88,
|
|
95
|
-
recommendedQualityLevel: "high",
|
|
96
|
-
allowedFormats: DEFAULT_ALLOWED_FORMATS
|
|
97
|
-
},
|
|
98
|
-
hero: {
|
|
99
|
-
folder: "hero",
|
|
100
|
-
maxDimensions: { width: 2560, height: 1440 },
|
|
101
|
-
maxSizeMB: 15,
|
|
102
|
-
quality: 92,
|
|
103
|
-
recommendedQualityLevel: "maximum",
|
|
104
|
-
allowedFormats: DEFAULT_ALLOWED_FORMATS,
|
|
105
|
-
recommendationNote: {
|
|
106
|
-
en: "Full-width hero visuals benefit from Maximum quality to preserve fine detail",
|
|
107
|
-
ar: "\u0627\u0644\u0635\u0648\u0631 \u0627\u0644\u0631\u0626\u064A\u0633\u064A\u0629 \u0628\u0639\u0631\u0636 \u0643\u0627\u0645\u0644 \u062A\u0633\u062A\u0641\u064A\u062F \u0645\u0646 \u0627\u0644\u062C\u0648\u062F\u0629 \u0627\u0644\u0642\u0635\u0648\u0649 \u0644\u0644\u062D\u0641\u0627\u0638 \u0639\u0644\u0649 \u0627\u0644\u062A\u0641\u0627\u0635\u064A\u0644 \u0627\u0644\u062F\u0642\u064A\u0642\u0629"
|
|
108
|
-
}
|
|
109
|
-
},
|
|
110
|
-
logo: {
|
|
111
|
-
folder: "logos",
|
|
112
|
-
maxDimensions: { width: 800, height: 800 },
|
|
113
|
-
maxSizeMB: 5,
|
|
114
|
-
quality: 90,
|
|
115
|
-
recommendedQualityLevel: "high",
|
|
116
|
-
allowedFormats: DEFAULT_ALLOWED_FORMATS,
|
|
117
|
-
recommendationNote: {
|
|
118
|
-
en: "Prefer SVG for vector logos \u2014 High quality preserves crisp edges on raster logos",
|
|
119
|
-
ar: "\u064A\u0641\u0636\u0644 SVG \u0644\u0644\u0634\u0639\u0627\u0631\u0627\u062A \u0627\u0644\u0645\u062A\u062C\u0647\u0629 \u2014 \u0627\u0644\u062C\u0648\u062F\u0629 \u0627\u0644\u0639\u0627\u0644\u064A\u0629 \u062A\u062D\u0627\u0641\u0638 \u0639\u0644\u0649 \u062D\u0648\u0627\u0641 \u0648\u0627\u0636\u062D\u0629"
|
|
120
|
-
}
|
|
121
|
-
},
|
|
122
|
-
original: {
|
|
123
|
-
folder: "originals",
|
|
124
|
-
maxDimensions: { width: 4096, height: 4096 },
|
|
125
|
-
maxSizeMB: 25,
|
|
126
|
-
quality: 95,
|
|
127
|
-
recommendedQualityLevel: "maximum",
|
|
128
|
-
allowedFormats: DEFAULT_ALLOWED_FORMATS
|
|
129
|
-
}
|
|
130
|
-
};
|
|
131
|
-
function defineUploadPresets(presets) {
|
|
132
|
-
return presets;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// src/utils/color.ts
|
|
136
|
-
var DEFAULT_BLUR_COLOR = "#F5F5F5";
|
|
137
|
-
function normalizeColorInput(value) {
|
|
138
|
-
if (!value) return null;
|
|
139
|
-
let next = value.trim();
|
|
140
|
-
if (!next) return null;
|
|
141
|
-
if (!next.startsWith("#")) {
|
|
142
|
-
next = `#${next}`;
|
|
143
|
-
}
|
|
144
|
-
const threeHex = /^#([0-9a-fA-F]{3})$/;
|
|
145
|
-
const sixHex = /^#([0-9a-fA-F]{6})$/;
|
|
146
|
-
if (threeHex.test(next)) {
|
|
147
|
-
const [, triplet] = next.match(threeHex) ?? [];
|
|
148
|
-
if (triplet) {
|
|
149
|
-
next = `#${triplet.split("").map((char) => char + char).join("")}`;
|
|
150
|
-
}
|
|
151
|
-
} else if (!sixHex.test(next)) {
|
|
152
|
-
return null;
|
|
153
|
-
}
|
|
154
|
-
return next.toUpperCase();
|
|
155
|
-
}
|
|
156
|
-
function hexToRgb(hex) {
|
|
157
|
-
const normalized = hex.replace("#", "");
|
|
158
|
-
const expanded = normalized.length === 3 ? normalized.split("").map((char) => char + char).join("") : normalized;
|
|
159
|
-
const padded = expanded.padEnd(6, "0").slice(0, 6);
|
|
160
|
-
const value = Number.parseInt(padded, 16);
|
|
161
|
-
if (Number.isNaN(value)) {
|
|
162
|
-
return { r: 245, g: 245, b: 245 };
|
|
163
|
-
}
|
|
164
|
-
return {
|
|
165
|
-
r: value >> 16 & 255,
|
|
166
|
-
g: value >> 8 & 255,
|
|
167
|
-
b: value & 255
|
|
168
|
-
};
|
|
169
|
-
}
|
|
170
|
-
function rgbToHex(r, g, b) {
|
|
171
|
-
const clamp = (v) => Math.max(0, Math.min(255, Math.round(v)));
|
|
172
|
-
const value = clamp(r) << 16 | clamp(g) << 8 | clamp(b);
|
|
173
|
-
return `#${value.toString(16).padStart(6, "0").toUpperCase()}`;
|
|
174
|
-
}
|
|
175
|
-
function encodeBase64Ascii(str) {
|
|
176
|
-
if (typeof btoa === "function") {
|
|
177
|
-
return btoa(str);
|
|
178
|
-
}
|
|
179
|
-
return Buffer.from(str, "utf8").toString("base64");
|
|
180
|
-
}
|
|
181
|
-
function generateColorSvgDataURL(color = DEFAULT_BLUR_COLOR) {
|
|
182
|
-
const safeColor = normalizeColorInput(color) || DEFAULT_BLUR_COLOR;
|
|
183
|
-
const svg = `<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg"><rect width="100%" height="100%" fill="${safeColor}"/></svg>`;
|
|
184
|
-
return `data:image/svg+xml;base64,${encodeBase64Ascii(svg)}`;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
// src/utils/formatters.ts
|
|
188
|
-
function formatFileSize(bytes) {
|
|
189
|
-
if (bytes <= 0) return "0 Bytes";
|
|
190
|
-
const k = 1024;
|
|
191
|
-
const sizes = ["Bytes", "KB", "MB", "GB"];
|
|
192
|
-
const i = Math.min(
|
|
193
|
-
sizes.length - 1,
|
|
194
|
-
Math.floor(Math.log(bytes) / Math.log(k))
|
|
195
|
-
);
|
|
196
|
-
return `${Math.round(bytes / Math.pow(k, i) * 100) / 100} ${sizes[i]}`;
|
|
197
|
-
}
|
|
198
|
-
function calculateReduction(original, optimized) {
|
|
199
|
-
if (original <= 0) return 0;
|
|
200
|
-
return Math.round((original - optimized) / original * 100);
|
|
201
|
-
}
|
|
202
|
-
function estimateOutputSize(originalBytes, level) {
|
|
203
|
-
return Math.round(originalBytes * QUALITY_PRESETS[level].compressionRatio);
|
|
204
|
-
}
|
|
205
|
-
var creativeMessages = [
|
|
206
|
-
"Sprinkling digital magic \u2728",
|
|
207
|
-
"Painting pixels with perfection \u{1F3A8}",
|
|
208
|
-
"Launching to the cloud \u{1F680}",
|
|
209
|
-
"Creating something beautiful \u2B50",
|
|
210
|
-
"Transforming your vision \u26A1",
|
|
211
|
-
"Weaving visual excellence \u{1F4AB}",
|
|
212
|
-
"Crafting your masterpiece \u{1F3AD}",
|
|
213
|
-
"Working our magic \u{1F52E}",
|
|
214
|
-
"Making it pixel-perfect \u2728",
|
|
215
|
-
"Keep calm, creating magic \u{1F3AA}",
|
|
216
|
-
"Hitting the sweet spot \u{1F3AF}",
|
|
217
|
-
"Artist mode activated \u{1F3A8}",
|
|
218
|
-
"Shooting for the stars \u{1F320}",
|
|
219
|
-
"Compressing with love \u{1F49D}",
|
|
220
|
-
"Enhancing quality \u{1F48E}",
|
|
221
|
-
"Polishing to perfection \u2728"
|
|
222
|
-
];
|
|
223
|
-
var creativeMessagesAr = [
|
|
224
|
-
"\u0646\u0636\u064A\u0641 \u0644\u0645\u0633\u0629 \u0631\u0642\u0645\u064A\u0629 \u0633\u0627\u062D\u0631\u0629 \u2728",
|
|
225
|
-
"\u0646\u0646\u0633\u0642 \u0627\u0644\u0628\u0643\u0633\u0644\u0627\u062A \u0628\u0625\u062A\u0642\u0627\u0646 \u{1F3A8}",
|
|
226
|
-
"\u0627\u0644\u0631\u0641\u0639 \u062C\u0627\u0631\u064D \u0625\u0644\u0649 \u0627\u0644\u0633\u062D\u0627\u0628\u0629 \u{1F680}",
|
|
227
|
-
"\u0646\u0635\u0646\u0639 \u0634\u064A\u0626\u0627\u064B \u062C\u0645\u064A\u0644\u0627\u064B \u2B50",
|
|
228
|
-
"\u0646\u062D\u0648\u0651\u0644 \u0631\u0624\u064A\u062A\u0643 \u0625\u0644\u0649 \u0648\u0627\u0642\u0639 \u26A1",
|
|
229
|
-
"\u0646\u0628\u0646\u064A \u062A\u062C\u0631\u0628\u0629 \u0628\u0635\u0631\u064A\u0629 \u0645\u0645\u064A\u0632\u0629 \u{1F4AB}",
|
|
230
|
-
"\u0646\u0635\u0642\u0644 \u0639\u0645\u0644\u0643 \u0628\u0627\u062D\u062A\u0631\u0627\u0641 \u{1F3AD}",
|
|
231
|
-
"\u0627\u0644\u0633\u062D\u0631 \u062C\u0627\u0631\u064D \u0627\u0644\u0622\u0646 \u{1F52E}",
|
|
232
|
-
"\u0646\u0636\u0628\u0637 \u0643\u0644 \u0628\u0643\u0633\u0644 \u0628\u0639\u0646\u0627\u064A\u0629 \u2728",
|
|
233
|
-
"\u0627\u0647\u062F\u0623\u060C \u0646\u062D\u0646 \u0646\u0647\u062A\u0645 \u0628\u0627\u0644\u062A\u0641\u0627\u0635\u064A\u0644 \u{1F3AA}",
|
|
234
|
-
"\u0646\u0642\u062A\u0631\u0628 \u0645\u0646 \u0627\u0644\u0646\u062A\u064A\u062C\u0629 \u0627\u0644\u0645\u062B\u0627\u0644\u064A\u0629 \u{1F3AF}",
|
|
235
|
-
"\u0648\u0636\u0639 \u0627\u0644\u0625\u0628\u062F\u0627\u0639 \u0645\u0641\u0639\u0644 \u{1F3A8}",
|
|
236
|
-
"\u0646\u0633\u062A\u0647\u062F\u0641 \u0623\u0641\u0636\u0644 \u0646\u062A\u064A\u062C\u0629 \u{1F320}",
|
|
237
|
-
"\u0636\u063A\u0637 \u0630\u0643\u064A \u0645\u0639 \u0627\u0644\u062D\u0641\u0627\u0638 \u0639\u0644\u0649 \u0627\u0644\u062C\u0648\u062F\u0629 \u{1F49D}",
|
|
238
|
-
"\u062A\u062D\u0633\u064A\u0646 \u0627\u0644\u062C\u0648\u062F\u0629 \u0645\u0633\u062A\u0645\u0631 \u{1F48E}",
|
|
239
|
-
"\u0627\u0644\u0644\u0645\u0633\u0627\u062A \u0627\u0644\u0623\u062E\u064A\u0631\u0629 \u0642\u064A\u062F \u0627\u0644\u062A\u0646\u0641\u064A\u0630 \u2728"
|
|
240
|
-
];
|
|
241
|
-
var lastMessageIndex = -1;
|
|
242
|
-
function getStatusMessage(progress, locale = "en") {
|
|
243
|
-
const list = locale === "ar" ? creativeMessagesAr : creativeMessages;
|
|
244
|
-
const clampedProgress = Math.max(0, Math.min(99, progress));
|
|
245
|
-
const messageIndex = Math.floor(clampedProgress / 100 * list.length);
|
|
246
|
-
const useRandom = Math.random() > 0.7;
|
|
247
|
-
let selectedIndex = useRandom ? Math.floor(Math.random() * list.length) : messageIndex;
|
|
248
|
-
if (selectedIndex === lastMessageIndex && list.length > 1) {
|
|
249
|
-
selectedIndex = (selectedIndex + 1) % list.length;
|
|
250
|
-
}
|
|
251
|
-
lastMessageIndex = selectedIndex;
|
|
252
|
-
if (progress >= 95) {
|
|
253
|
-
return locale === "ar" ? "\u{1F389} \u0627\u0642\u062A\u0631\u0628\u0646\u0627 \u062C\u062F\u0627\u064B..." : "\u{1F389} Almost there...";
|
|
254
|
-
}
|
|
255
|
-
if (progress >= 85) {
|
|
256
|
-
return locale === "ar" ? "\u2728 \u0646\u0636\u0639 \u0627\u0644\u0644\u0645\u0633\u0627\u062A \u0627\u0644\u0623\u062E\u064A\u0631\u0629..." : "\u2728 Polishing the final details...";
|
|
257
|
-
}
|
|
258
|
-
return list[selectedIndex];
|
|
259
|
-
}
|
|
260
|
-
function createSuccessMessage(originalSize, optimizedSize, compact = false, locale = "en") {
|
|
261
|
-
const reduction = calculateReduction(originalSize, optimizedSize);
|
|
262
|
-
const original = formatFileSize(originalSize);
|
|
263
|
-
const optimized = formatFileSize(optimizedSize);
|
|
264
|
-
if (compact) {
|
|
265
|
-
if (reduction > 50) {
|
|
266
|
-
return locale === "ar" ? `\u{1F389} \u0623\u0635\u063A\u0631 \u0628\u0646\u0633\u0628\u0629 ${reduction}%! (${original} \u2192 ${optimized})` : `\u{1F389} ${reduction}% smaller! (${original} \u2192 ${optimized})`;
|
|
267
|
-
}
|
|
268
|
-
if (reduction > 0) {
|
|
269
|
-
return locale === "ar" ? `\u2713 \u0623\u0635\u063A\u0631 \u0628\u0646\u0633\u0628\u0629 ${reduction}% (${original} \u2192 ${optimized})` : `\u2713 ${reduction}% smaller (${original} \u2192 ${optimized})`;
|
|
270
|
-
}
|
|
271
|
-
return `\u2713 ${optimized}`;
|
|
272
|
-
}
|
|
273
|
-
if (reduction > 70) {
|
|
274
|
-
return locale === "ar" ? `\u{1F389} \u0631\u0627\u0626\u0639! \u062A\u0645 \u062A\u0642\u0644\u064A\u0644 \u0627\u0644\u062D\u062C\u0645 \u0628\u0646\u0633\u0628\u0629 ${reduction}% (${original} \u2192 ${optimized})` : `\u{1F389} Amazing! Reduced by ${reduction}% (${original} \u2192 ${optimized})`;
|
|
275
|
-
}
|
|
276
|
-
if (reduction > 50) {
|
|
277
|
-
return locale === "ar" ? `\u2728 \u0645\u0645\u062A\u0627\u0632! \u062A\u0645 \u062A\u0642\u0644\u064A\u0644 \u0627\u0644\u062D\u062C\u0645 \u0628\u0646\u0633\u0628\u0629 ${reduction}% (${original} \u2192 ${optimized})` : `\u2728 Great! Reduced by ${reduction}% (${original} \u2192 ${optimized})`;
|
|
278
|
-
}
|
|
279
|
-
if (reduction > 20) {
|
|
280
|
-
return locale === "ar" ? `\u2713 \u0627\u0643\u062A\u0645\u0644 \u0627\u0644\u0631\u0641\u0639! \u062A\u0645 \u062A\u0642\u0644\u064A\u0644 \u0627\u0644\u062D\u062C\u0645 \u0628\u0646\u0633\u0628\u0629 ${reduction}% (${original} \u2192 ${optimized})` : `\u2713 Upload complete! Reduced by ${reduction}% (${original} \u2192 ${optimized})`;
|
|
281
|
-
}
|
|
282
|
-
return locale === "ar" ? `\u2713 \u0627\u0643\u062A\u0645\u0644 \u0627\u0644\u0631\u0641\u0639! (${original} \u2192 ${optimized})` : `\u2713 Upload complete! (${original} \u2192 ${optimized})`;
|
|
283
|
-
}
|
|
284
|
-
function getFriendlyErrorMessage(error, locale = "en") {
|
|
285
|
-
const lower = error.toLowerCase();
|
|
286
|
-
if (lower.includes("size") || lower.includes("large") || lower.includes("exceeds")) {
|
|
287
|
-
return locale === "ar" ? "\u0627\u0644\u0645\u0644\u0641 \u0643\u0628\u064A\u0631 \u062C\u062F\u0627\u064B. \u064A\u0631\u062C\u0649 \u0627\u062E\u062A\u064A\u0627\u0631 \u0635\u0648\u0631\u0629 \u0623\u0635\u063A\u0631." : "File is too large. Please choose a smaller image.";
|
|
288
|
-
}
|
|
289
|
-
if (lower.includes("type") || lower.includes("format")) {
|
|
290
|
-
return locale === "ar" ? "\u0646\u0648\u0639 \u0627\u0644\u0645\u0644\u0641 \u063A\u064A\u0631 \u0635\u0627\u0644\u062D. \u064A\u0631\u062C\u0649 \u0631\u0641\u0639 \u0635\u0648\u0631\u0629 \u0635\u0627\u0644\u062D\u0629 (JPEG, PNG, WebP, AVIF, SVG)." : "Invalid file type. Please upload a valid image (JPEG, PNG, WebP, AVIF, SVG).";
|
|
291
|
-
}
|
|
292
|
-
if (lower.includes("network") || lower.includes("fetch")) {
|
|
293
|
-
return locale === "ar" ? "\u062D\u062F\u062B \u062E\u0637\u0623 \u0641\u064A \u0627\u0644\u0634\u0628\u0643\u0629. \u064A\u0631\u062C\u0649 \u0627\u0644\u062A\u062D\u0642\u0642 \u0645\u0646 \u0627\u0644\u0627\u062A\u0635\u0627\u0644 \u0648\u0627\u0644\u0645\u062D\u0627\u0648\u0644\u0629 \u0645\u0631\u0629 \u0623\u062E\u0631\u0649." : "Network error. Please check your connection and try again.";
|
|
294
|
-
}
|
|
295
|
-
if (lower.includes("timeout") || lower.includes("timed out")) {
|
|
296
|
-
return locale === "ar" ? "\u0627\u0646\u062A\u0647\u062A \u0645\u0647\u0644\u0629 \u0627\u0644\u0631\u0641\u0639. \u064A\u0631\u062C\u0649 \u0627\u0644\u0645\u062D\u0627\u0648\u0644\u0629 \u0645\u0631\u0629 \u0623\u062E\u0631\u0649." : "Upload timed out. Please try again.";
|
|
297
|
-
}
|
|
298
|
-
if (error) return error;
|
|
299
|
-
return locale === "ar" ? "\u0641\u0634\u0644 \u0627\u0644\u0631\u0641\u0639. \u064A\u0631\u062C\u0649 \u0627\u0644\u0645\u062D\u0627\u0648\u0644\u0629 \u0645\u0631\u0629 \u0623\u062E\u0631\u0649." : "Upload failed. Please try again.";
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
// src/utils/validators.ts
|
|
303
|
-
function validateImageFileStrict(file, maxSizeMB, allowedFormats) {
|
|
304
|
-
const maxBytes = maxSizeMB * 1024 * 1024;
|
|
305
|
-
if (file.size > maxBytes) {
|
|
306
|
-
return {
|
|
307
|
-
valid: false,
|
|
308
|
-
error: `File size (${(file.size / 1024 / 1024).toFixed(2)}MB) exceeds maximum of ${maxSizeMB}MB`
|
|
309
|
-
};
|
|
310
|
-
}
|
|
311
|
-
if (allowedFormats.length > 0 && !allowedFormats.includes(file.type)) {
|
|
312
|
-
return {
|
|
313
|
-
valid: false,
|
|
314
|
-
error: `File type ${file.type || "unknown"} is not allowed. Allowed: ${allowedFormats.join(", ")}`
|
|
315
|
-
};
|
|
316
|
-
}
|
|
317
|
-
return { valid: true };
|
|
318
|
-
}
|
|
319
|
-
function validateImageFile(file, maxSizeMB, locale = "en", allowedFormats) {
|
|
320
|
-
if (!file.type || !file.type.startsWith("image/")) {
|
|
321
|
-
return locale === "ar" ? "\u064A\u0631\u062C\u0649 \u0627\u062E\u062A\u064A\u0627\u0631 \u0645\u0644\u0641 \u0635\u0648\u0631\u0629 \u0635\u0627\u0644\u062D" : "Please select a valid image file";
|
|
322
|
-
}
|
|
323
|
-
if (allowedFormats && allowedFormats.length > 0 && !allowedFormats.includes(file.type)) {
|
|
324
|
-
return locale === "ar" ? `\u0635\u064A\u063A\u0629 \u0627\u0644\u0645\u0644\u0641 \u063A\u064A\u0631 \u0645\u062F\u0639\u0648\u0645\u0629 (${file.type})` : `Unsupported image format (${file.type})`;
|
|
325
|
-
}
|
|
326
|
-
const fileSizeMB = file.size / (1024 * 1024);
|
|
327
|
-
if (fileSizeMB > maxSizeMB) {
|
|
328
|
-
return locale === "ar" ? `\u064A\u062C\u0628 \u0623\u0644\u0627 \u064A\u062A\u062C\u0627\u0648\u0632 \u062D\u062C\u0645 \u0627\u0644\u0645\u0644\u0641 ${maxSizeMB}MB` : `File size must be less than ${maxSizeMB}MB`;
|
|
329
|
-
}
|
|
330
|
-
return null;
|
|
331
|
-
}
|
|
332
|
-
function validateImageFileWithName(file, maxSizeMB, locale = "en") {
|
|
333
|
-
if (!file.type || !file.type.startsWith("image/")) {
|
|
334
|
-
return locale === "ar" ? `${file.name}: \u0644\u064A\u0633 \u0645\u0644\u0641 \u0635\u0648\u0631\u0629 \u0635\u0627\u0644\u062D\u0627\u064B` : `${file.name}: Not a valid image file`;
|
|
335
|
-
}
|
|
336
|
-
const fileSizeMB = file.size / (1024 * 1024);
|
|
337
|
-
if (fileSizeMB > maxSizeMB) {
|
|
338
|
-
return locale === "ar" ? `${file.name}: \u064A\u062C\u0628 \u0623\u0644\u0627 \u064A\u062A\u062C\u0627\u0648\u0632 \u062D\u062C\u0645 \u0627\u0644\u0645\u0644\u0641 ${maxSizeMB}MB` : `${file.name}: File size must be less than ${maxSizeMB}MB`;
|
|
339
|
-
}
|
|
340
|
-
return null;
|
|
341
|
-
}
|
|
342
|
-
function validateMultipleFiles(files, maxSizeMB, currentCount, maxImages, locale = "en") {
|
|
343
|
-
if (currentCount + files.length > maxImages) {
|
|
344
|
-
return locale === "ar" ? `\u064A\u0645\u0643\u0646 \u0631\u0641\u0639 ${maxImages} \u0635\u0648\u0631\u0629 \u0641\u0642\u0637. \u0627\u0644\u0645\u062A\u0628\u0642\u064A: ${maxImages - currentCount}.` : `Can only upload ${maxImages} images. ${maxImages - currentCount} remaining.`;
|
|
345
|
-
}
|
|
346
|
-
const oversizedFiles = [];
|
|
347
|
-
for (const file of files) {
|
|
348
|
-
const fileSizeMB = file.size / (1024 * 1024);
|
|
349
|
-
if (fileSizeMB > maxSizeMB) {
|
|
350
|
-
oversizedFiles.push(file.name);
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
if (oversizedFiles.length > 0) {
|
|
354
|
-
if (locale === "ar") {
|
|
355
|
-
return `\u0627\u0644\u0645\u0644\u0641\u0627\u062A \u0627\u0644\u062A\u0627\u0644\u064A\u0629 \u0623\u0643\u0628\u0631 \u0645\u0646 \u0627\u0644\u062D\u062F \u0627\u0644\u0645\u0633\u0645\u0648\u062D (${maxSizeMB}MB): ${oversizedFiles.join(", ")}`;
|
|
356
|
-
}
|
|
357
|
-
return `The following file${oversizedFiles.length > 1 ? "s are" : " is"} too large (max ${maxSizeMB}MB): ${oversizedFiles.join(", ")}`;
|
|
358
|
-
}
|
|
359
|
-
return null;
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
// src/storage/memoryAdapter.ts
|
|
363
|
-
function createMemoryStorageAdapter(options = {}) {
|
|
364
|
-
const baseUrl = (options.baseUrl || "https://memory.local/uploads").replace(
|
|
365
|
-
/\/+$/,
|
|
366
|
-
""
|
|
367
|
-
);
|
|
368
|
-
const store = /* @__PURE__ */ new Map();
|
|
369
|
-
const toKey = (bucket, path) => `${bucket}::${path.replace(/^\/+/, "")}`;
|
|
370
|
-
const getPublicUrl = (bucket, path) => {
|
|
371
|
-
const cleanPath = path.replace(/^\/+/, "");
|
|
372
|
-
return `${baseUrl}/${bucket}/${cleanPath}`;
|
|
373
|
-
};
|
|
374
|
-
return {
|
|
375
|
-
async upload(params) {
|
|
376
|
-
const cleanPath = params.path.replace(/^\/+/, "");
|
|
377
|
-
const key = toKey(params.bucket, cleanPath);
|
|
378
|
-
if (params.upsert === false && store.has(key)) {
|
|
379
|
-
throw new Error(`Object already exists at ${params.bucket}/${cleanPath}`);
|
|
380
|
-
}
|
|
381
|
-
store.set(key, {
|
|
382
|
-
bucket: params.bucket,
|
|
383
|
-
path: cleanPath,
|
|
384
|
-
data: new Uint8Array(params.data),
|
|
385
|
-
contentType: params.contentType,
|
|
386
|
-
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
387
|
-
metadata: params.metadata
|
|
388
|
-
});
|
|
389
|
-
return {
|
|
390
|
-
bucket: params.bucket,
|
|
391
|
-
path: cleanPath,
|
|
392
|
-
url: getPublicUrl(params.bucket, cleanPath)
|
|
393
|
-
};
|
|
394
|
-
},
|
|
395
|
-
async delete(bucket, path) {
|
|
396
|
-
const key = toKey(bucket, path);
|
|
397
|
-
store.delete(key);
|
|
398
|
-
},
|
|
399
|
-
getPublicUrl,
|
|
400
|
-
async list(bucket, folder) {
|
|
401
|
-
const cleanFolder = folder ? folder.replace(/^\/+|\/+$/g, "") : "";
|
|
402
|
-
const entries = [];
|
|
403
|
-
for (const obj of store.values()) {
|
|
404
|
-
if (obj.bucket !== bucket) continue;
|
|
405
|
-
if (cleanFolder && !obj.path.startsWith(`${cleanFolder}/`)) continue;
|
|
406
|
-
const name = cleanFolder ? obj.path.slice(cleanFolder.length + 1) : obj.path;
|
|
407
|
-
entries.push({
|
|
408
|
-
name,
|
|
409
|
-
id: `${obj.bucket}/${obj.path}`,
|
|
410
|
-
createdAt: obj.createdAt,
|
|
411
|
-
size: obj.data.byteLength
|
|
412
|
-
});
|
|
413
|
-
}
|
|
414
|
-
return entries;
|
|
415
|
-
},
|
|
416
|
-
async deleteByUrl(url) {
|
|
417
|
-
const prefix = `${baseUrl}/`;
|
|
418
|
-
if (!url.startsWith(prefix)) return false;
|
|
419
|
-
const rest = url.slice(prefix.length);
|
|
420
|
-
const slashIdx = rest.indexOf("/");
|
|
421
|
-
if (slashIdx === -1) return false;
|
|
422
|
-
const bucket = rest.slice(0, slashIdx);
|
|
423
|
-
const filePath = rest.slice(slashIdx + 1);
|
|
424
|
-
const key = toKey(bucket, filePath);
|
|
425
|
-
return store.delete(key);
|
|
426
|
-
},
|
|
427
|
-
getObject(bucket, path) {
|
|
428
|
-
return store.get(toKey(bucket, path));
|
|
429
|
-
},
|
|
430
|
-
clear() {
|
|
431
|
-
store.clear();
|
|
432
|
-
},
|
|
433
|
-
get size() {
|
|
434
|
-
return store.size;
|
|
435
|
-
}
|
|
436
|
-
};
|
|
437
|
-
}
|
|
438
|
-
function getBlurData(image) {
|
|
439
|
-
if (!image) {
|
|
440
|
-
return {
|
|
441
|
-
blurDataUrl: "",
|
|
442
|
-
blurColor: "#E5E7EB",
|
|
443
|
-
hasBlur: false
|
|
444
|
-
};
|
|
445
|
-
}
|
|
446
|
-
return {
|
|
447
|
-
blurDataUrl: image.blurDataUrl || "",
|
|
448
|
-
blurColor: image.blurColor || "#E5E7EB",
|
|
449
|
-
...image.blurHash ? { blurHash: image.blurHash } : {},
|
|
450
|
-
hasBlur: Boolean(image.blurDataUrl || image.blurHash)
|
|
451
|
-
};
|
|
452
|
-
}
|
|
453
|
-
function getImagePropsWithBlur(image) {
|
|
454
|
-
if (!image?.url) {
|
|
455
|
-
return null;
|
|
456
|
-
}
|
|
457
|
-
const blurData = getBlurData(image);
|
|
458
|
-
return {
|
|
459
|
-
src: image.url,
|
|
460
|
-
alt: image.altText || "",
|
|
461
|
-
width: image.width || 1920,
|
|
462
|
-
height: image.height || 1080,
|
|
463
|
-
...blurData.blurDataUrl && {
|
|
464
|
-
placeholder: "blur",
|
|
465
|
-
blurDataURL: blurData.blurDataUrl
|
|
466
|
-
}
|
|
467
|
-
};
|
|
468
|
-
}
|
|
469
|
-
function getBackgroundPropsWithBlur(image) {
|
|
470
|
-
if (!image?.url) {
|
|
471
|
-
return {
|
|
472
|
-
backgroundColor: "#E5E7EB"
|
|
473
|
-
};
|
|
474
|
-
}
|
|
475
|
-
const blurData = getBlurData(image);
|
|
476
|
-
return {
|
|
477
|
-
backgroundColor: blurData.blurColor,
|
|
478
|
-
backgroundImage: `url(${image.url})`,
|
|
479
|
-
backgroundSize: "cover",
|
|
480
|
-
backgroundPosition: "center",
|
|
481
|
-
backgroundRepeat: "no-repeat"
|
|
482
|
-
};
|
|
483
|
-
}
|
|
484
|
-
function decodeBlurHashToDataURL(hash, width = 32, height = 32, punch = 1) {
|
|
485
|
-
if (!hash || typeof document === "undefined") return null;
|
|
486
|
-
const validation = isBlurhashValid(hash);
|
|
487
|
-
if (!validation.result) return null;
|
|
488
|
-
try {
|
|
489
|
-
const pixels = decode(hash, width, height, punch);
|
|
490
|
-
const canvas = document.createElement("canvas");
|
|
491
|
-
canvas.width = width;
|
|
492
|
-
canvas.height = height;
|
|
493
|
-
const ctx = canvas.getContext("2d");
|
|
494
|
-
if (!ctx) return null;
|
|
495
|
-
const imageData = ctx.createImageData(width, height);
|
|
496
|
-
imageData.data.set(pixels);
|
|
497
|
-
ctx.putImageData(imageData, 0, 0);
|
|
498
|
-
return canvas.toDataURL("image/png");
|
|
499
|
-
} catch {
|
|
500
|
-
return null;
|
|
501
|
-
}
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
export { DEFAULT_ALLOWED_FORMATS, DEFAULT_BLUR_COLOR, DEFAULT_IMAGE_DIMENSIONS, QUALITY_PRESETS, RASTER_ALLOWED_FORMATS, STANDARD_PRESETS, calculateReduction, createMemoryStorageAdapter, createSuccessMessage, decodeBlurHashToDataURL, defineUploadPresets, estimateOutputSize, formatFileSize, generateColorSvgDataURL, getBackgroundPropsWithBlur, getBlurData, getFriendlyErrorMessage, getImagePropsWithBlur, getStatusMessage, hexToRgb, normalizeColorInput, rgbToHex, validateImageFile, validateImageFileStrict, validateImageFileWithName, validateMultipleFiles };
|
|
505
|
-
//# sourceMappingURL=index.js.map
|
|
506
65
|
//# sourceMappingURL=index.js.map
|