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
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { d as BlurManifestData, e as BlurManifestEntry, f as BlurPlaceholderType, i as BlurSize } from './types-yShGNQnW.cjs';
|
|
2
|
+
|
|
3
|
+
declare const DEFAULT_CDN_PATTERNS: RegExp[];
|
|
4
|
+
interface NormalizePathOptions {
|
|
5
|
+
cdnPatterns?: RegExp[];
|
|
6
|
+
stripPrefixes?: string[];
|
|
7
|
+
}
|
|
8
|
+
interface PathInfo {
|
|
9
|
+
normalizedPath: string;
|
|
10
|
+
folder?: string;
|
|
11
|
+
filename?: string;
|
|
12
|
+
extension?: string;
|
|
13
|
+
isExternal: boolean;
|
|
14
|
+
originalPath: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Project-agnostic image URL / path normalizer.
|
|
18
|
+
* Strips query parameters, leading `/public/`, relative `./`, and common CDN prefixes
|
|
19
|
+
* so manifest keys match consistently across local and CDN environments.
|
|
20
|
+
*/
|
|
21
|
+
declare function normalizeImagePath(imageSrc: string, options?: NormalizePathOptions): PathInfo;
|
|
22
|
+
|
|
23
|
+
interface BlurServiceOptions {
|
|
24
|
+
cacheSize?: number;
|
|
25
|
+
manifest?: BlurManifestData | Record<string, BlurManifestEntry>;
|
|
26
|
+
pathOptions?: NormalizePathOptions;
|
|
27
|
+
}
|
|
28
|
+
declare class BlurService {
|
|
29
|
+
private blurData;
|
|
30
|
+
private readonly cache;
|
|
31
|
+
private readonly pathOptions?;
|
|
32
|
+
private metadata;
|
|
33
|
+
private metrics;
|
|
34
|
+
constructor(options?: BlurServiceOptions);
|
|
35
|
+
/**
|
|
36
|
+
* Hydrate the service with a generated `blur-hashes.json` manifest or hash map.
|
|
37
|
+
*/
|
|
38
|
+
loadManifest(manifest: BlurManifestData | Record<string, BlurManifestEntry>): void;
|
|
39
|
+
/**
|
|
40
|
+
* Register or update a single image's blur data at runtime.
|
|
41
|
+
*/
|
|
42
|
+
registerEntry(imagePath: string, entry: BlurManifestEntry): void;
|
|
43
|
+
getDefaultPlaceholder(type?: BlurPlaceholderType): string;
|
|
44
|
+
private findBlurDataByPath;
|
|
45
|
+
getDominantColor(imageSrc: string): string;
|
|
46
|
+
getBlurDataURL(imageSrc: string, options?: {
|
|
47
|
+
type?: BlurPlaceholderType;
|
|
48
|
+
size?: BlurSize;
|
|
49
|
+
}): string;
|
|
50
|
+
getBulkBlurData(imageSrcs: string[], options?: {
|
|
51
|
+
type?: BlurPlaceholderType;
|
|
52
|
+
size?: BlurSize;
|
|
53
|
+
}): Record<string, string>;
|
|
54
|
+
getProgressiveData(imageSrc: string, size?: BlurSize): {
|
|
55
|
+
color: string;
|
|
56
|
+
blur: string;
|
|
57
|
+
hasBlur: boolean;
|
|
58
|
+
};
|
|
59
|
+
hasBlurHash(imageSrc: string): boolean;
|
|
60
|
+
getMetadata(): {
|
|
61
|
+
cacheSize: number;
|
|
62
|
+
metrics: {
|
|
63
|
+
cacheHitRate: string;
|
|
64
|
+
totalRequests: number;
|
|
65
|
+
cacheHits: number;
|
|
66
|
+
cacheMisses: number;
|
|
67
|
+
errors: number;
|
|
68
|
+
};
|
|
69
|
+
version: string;
|
|
70
|
+
generatedAt: string;
|
|
71
|
+
totalImages: number;
|
|
72
|
+
};
|
|
73
|
+
clearCache(): void;
|
|
74
|
+
getBlurHash(imageSrc: string): string | null;
|
|
75
|
+
preloadBlurData(imageSrcs: string[], size?: BlurSize): void;
|
|
76
|
+
fetchBlurDataForImage(imageSrc: string, type?: BlurPlaceholderType): Promise<string>;
|
|
77
|
+
getAvailableKeys(): string[];
|
|
78
|
+
findMatchingKeys(searchTerm: string): string[];
|
|
79
|
+
}
|
|
80
|
+
declare function createBlurService(options?: BlurServiceOptions): BlurService;
|
|
81
|
+
declare const blurService: BlurService;
|
|
82
|
+
|
|
83
|
+
export { BlurService as B, DEFAULT_CDN_PATTERNS as D, type NormalizePathOptions as N, type PathInfo as P, type BlurServiceOptions as a, blurService as b, createBlurService as c, normalizeImagePath as n };
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
// src/types/quality.ts
|
|
2
|
+
var QUALITY_PRESETS = {
|
|
3
|
+
low: {
|
|
4
|
+
label: "Low",
|
|
5
|
+
labelAr: "\u0645\u0646\u062E\u0641\u0636\u0629",
|
|
6
|
+
value: 50,
|
|
7
|
+
description: "Smallest file \u2014 best for tiny thumbnails and icons",
|
|
8
|
+
descriptionAr: "\u0623\u0635\u063A\u0631 \u062D\u062C\u0645 \u2014 \u0645\u0646\u0627\u0633\u0628 \u0644\u0644\u0645\u0635\u063A\u0631\u0627\u062A \u0648\u0627\u0644\u0623\u064A\u0642\u0648\u0646\u0627\u062A \u0627\u0644\u0635\u063A\u064A\u0631\u0629",
|
|
9
|
+
compressionRatio: 0.12
|
|
10
|
+
},
|
|
11
|
+
medium: {
|
|
12
|
+
label: "Medium",
|
|
13
|
+
labelAr: "\u0645\u062A\u0648\u0633\u0637\u0629",
|
|
14
|
+
value: 72,
|
|
15
|
+
description: "Balanced size and quality \u2014 suitable for most web images",
|
|
16
|
+
descriptionAr: "\u062A\u0648\u0627\u0632\u0646 \u0628\u064A\u0646 \u0627\u0644\u062D\u062C\u0645 \u0648\u0627\u0644\u062C\u0648\u062F\u0629 \u2014 \u0645\u0646\u0627\u0633\u0628 \u0644\u0645\u0639\u0638\u0645 \u0635\u0648\u0631 \u0627\u0644\u0648\u064A\u0628",
|
|
17
|
+
compressionRatio: 0.22
|
|
18
|
+
},
|
|
19
|
+
high: {
|
|
20
|
+
label: "High",
|
|
21
|
+
labelAr: "\u0639\u0627\u0644\u064A\u0629",
|
|
22
|
+
value: 85,
|
|
23
|
+
description: "Recommended \u2014 sharp visuals with excellent compression",
|
|
24
|
+
descriptionAr: "\u0645\u0648\u0635\u0649 \u0628\u0647 \u2014 \u062C\u0648\u062F\u0629 \u0639\u0627\u0644\u064A\u0629 \u0648\u0636\u063A\u0637 \u0645\u0645\u062A\u0627\u0632",
|
|
25
|
+
compressionRatio: 0.3
|
|
26
|
+
},
|
|
27
|
+
maximum: {
|
|
28
|
+
label: "Maximum",
|
|
29
|
+
labelAr: "\u0623\u0642\u0635\u0649 \u062C\u0648\u062F\u0629",
|
|
30
|
+
value: 95,
|
|
31
|
+
description: "Closest to original \u2014 large file, use for hero / print",
|
|
32
|
+
descriptionAr: "\u0623\u0642\u0631\u0628 \u0644\u0644\u0623\u0635\u0644 \u2014 \u062D\u062C\u0645 \u0643\u0628\u064A\u0631\u060C \u0645\u0646\u0627\u0633\u0628 \u0644\u0644\u0635\u0648\u0631 \u0627\u0644\u0631\u0626\u064A\u0633\u064A\u0629 \u0648\u0627\u0644\u0637\u0628\u0627\u0639\u0629",
|
|
33
|
+
compressionRatio: 0.55
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// src/utils/formatters.ts
|
|
38
|
+
function formatFileSize(bytes) {
|
|
39
|
+
if (bytes <= 0) return "0 Bytes";
|
|
40
|
+
const k = 1024;
|
|
41
|
+
const sizes = ["Bytes", "KB", "MB", "GB"];
|
|
42
|
+
const i = Math.min(
|
|
43
|
+
sizes.length - 1,
|
|
44
|
+
Math.floor(Math.log(bytes) / Math.log(k))
|
|
45
|
+
);
|
|
46
|
+
return `${Math.round(bytes / Math.pow(k, i) * 100) / 100} ${sizes[i]}`;
|
|
47
|
+
}
|
|
48
|
+
function calculateReduction(original, optimized) {
|
|
49
|
+
if (original <= 0) return 0;
|
|
50
|
+
return Math.round((original - optimized) / original * 100);
|
|
51
|
+
}
|
|
52
|
+
function estimateOutputSize(originalBytes, level) {
|
|
53
|
+
return Math.round(originalBytes * QUALITY_PRESETS[level].compressionRatio);
|
|
54
|
+
}
|
|
55
|
+
var creativeMessages = [
|
|
56
|
+
"Sprinkling digital magic \u2728",
|
|
57
|
+
"Painting pixels with perfection \u{1F3A8}",
|
|
58
|
+
"Launching to the cloud \u{1F680}",
|
|
59
|
+
"Creating something beautiful \u2B50",
|
|
60
|
+
"Transforming your vision \u26A1",
|
|
61
|
+
"Weaving visual excellence \u{1F4AB}",
|
|
62
|
+
"Crafting your masterpiece \u{1F3AD}",
|
|
63
|
+
"Working our magic \u{1F52E}",
|
|
64
|
+
"Making it pixel-perfect \u2728",
|
|
65
|
+
"Keep calm, creating magic \u{1F3AA}",
|
|
66
|
+
"Hitting the sweet spot \u{1F3AF}",
|
|
67
|
+
"Artist mode activated \u{1F3A8}",
|
|
68
|
+
"Shooting for the stars \u{1F320}",
|
|
69
|
+
"Compressing with love \u{1F49D}",
|
|
70
|
+
"Enhancing quality \u{1F48E}",
|
|
71
|
+
"Polishing to perfection \u2728"
|
|
72
|
+
];
|
|
73
|
+
var creativeMessagesAr = [
|
|
74
|
+
"\u0646\u0636\u064A\u0641 \u0644\u0645\u0633\u0629 \u0631\u0642\u0645\u064A\u0629 \u0633\u0627\u062D\u0631\u0629 \u2728",
|
|
75
|
+
"\u0646\u0646\u0633\u0642 \u0627\u0644\u0628\u0643\u0633\u0644\u0627\u062A \u0628\u0625\u062A\u0642\u0627\u0646 \u{1F3A8}",
|
|
76
|
+
"\u0627\u0644\u0631\u0641\u0639 \u062C\u0627\u0631\u064D \u0625\u0644\u0649 \u0627\u0644\u0633\u062D\u0627\u0628\u0629 \u{1F680}",
|
|
77
|
+
"\u0646\u0635\u0646\u0639 \u0634\u064A\u0626\u0627\u064B \u062C\u0645\u064A\u0644\u0627\u064B \u2B50",
|
|
78
|
+
"\u0646\u062D\u0648\u0651\u0644 \u0631\u0624\u064A\u062A\u0643 \u0625\u0644\u0649 \u0648\u0627\u0642\u0639 \u26A1",
|
|
79
|
+
"\u0646\u0628\u0646\u064A \u062A\u062C\u0631\u0628\u0629 \u0628\u0635\u0631\u064A\u0629 \u0645\u0645\u064A\u0632\u0629 \u{1F4AB}",
|
|
80
|
+
"\u0646\u0635\u0642\u0644 \u0639\u0645\u0644\u0643 \u0628\u0627\u062D\u062A\u0631\u0627\u0641 \u{1F3AD}",
|
|
81
|
+
"\u0627\u0644\u0633\u062D\u0631 \u062C\u0627\u0631\u064D \u0627\u0644\u0622\u0646 \u{1F52E}",
|
|
82
|
+
"\u0646\u0636\u0628\u0637 \u0643\u0644 \u0628\u0643\u0633\u0644 \u0628\u0639\u0646\u0627\u064A\u0629 \u2728",
|
|
83
|
+
"\u0627\u0647\u062F\u0623\u060C \u0646\u062D\u0646 \u0646\u0647\u062A\u0645 \u0628\u0627\u0644\u062A\u0641\u0627\u0635\u064A\u0644 \u{1F3AA}",
|
|
84
|
+
"\u0646\u0642\u062A\u0631\u0628 \u0645\u0646 \u0627\u0644\u0646\u062A\u064A\u062C\u0629 \u0627\u0644\u0645\u062B\u0627\u0644\u064A\u0629 \u{1F3AF}",
|
|
85
|
+
"\u0648\u0636\u0639 \u0627\u0644\u0625\u0628\u062F\u0627\u0639 \u0645\u0641\u0639\u0644 \u{1F3A8}",
|
|
86
|
+
"\u0646\u0633\u062A\u0647\u062F\u0641 \u0623\u0641\u0636\u0644 \u0646\u062A\u064A\u062C\u0629 \u{1F320}",
|
|
87
|
+
"\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}",
|
|
88
|
+
"\u062A\u062D\u0633\u064A\u0646 \u0627\u0644\u062C\u0648\u062F\u0629 \u0645\u0633\u062A\u0645\u0631 \u{1F48E}",
|
|
89
|
+
"\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"
|
|
90
|
+
];
|
|
91
|
+
function getStatusMessage(progress, locale = "en") {
|
|
92
|
+
if (progress >= 95) {
|
|
93
|
+
return locale === "ar" ? "\u{1F389} \u0627\u0642\u062A\u0631\u0628\u0646\u0627 \u062C\u062F\u0627\u064B..." : "\u{1F389} Almost there...";
|
|
94
|
+
}
|
|
95
|
+
if (progress >= 85) {
|
|
96
|
+
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...";
|
|
97
|
+
}
|
|
98
|
+
const list = locale === "ar" ? creativeMessagesAr : creativeMessages;
|
|
99
|
+
const clampedProgress = Math.max(0, Math.min(99, progress));
|
|
100
|
+
const messageIndex = Math.min(
|
|
101
|
+
list.length - 1,
|
|
102
|
+
Math.floor(clampedProgress / 100 * list.length)
|
|
103
|
+
);
|
|
104
|
+
return list[messageIndex];
|
|
105
|
+
}
|
|
106
|
+
function createSuccessMessage(originalSize, optimizedSize, compact = false, locale = "en") {
|
|
107
|
+
const reduction = calculateReduction(originalSize, optimizedSize);
|
|
108
|
+
const original = formatFileSize(originalSize);
|
|
109
|
+
const optimized = formatFileSize(optimizedSize);
|
|
110
|
+
if (compact) {
|
|
111
|
+
if (reduction > 50) {
|
|
112
|
+
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})`;
|
|
113
|
+
}
|
|
114
|
+
if (reduction > 0) {
|
|
115
|
+
return locale === "ar" ? `\u2713 \u0623\u0635\u063A\u0631 \u0628\u0646\u0633\u0628\u0629 ${reduction}% (${original} \u2192 ${optimized})` : `\u2713 ${reduction}% smaller (${original} \u2192 ${optimized})`;
|
|
116
|
+
}
|
|
117
|
+
return `\u2713 ${optimized}`;
|
|
118
|
+
}
|
|
119
|
+
if (reduction > 70) {
|
|
120
|
+
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})`;
|
|
121
|
+
}
|
|
122
|
+
if (reduction > 50) {
|
|
123
|
+
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})`;
|
|
124
|
+
}
|
|
125
|
+
if (reduction > 20) {
|
|
126
|
+
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})`;
|
|
127
|
+
}
|
|
128
|
+
return locale === "ar" ? `\u2713 \u0627\u0643\u062A\u0645\u0644 \u0627\u0644\u0631\u0641\u0639! (${original} \u2192 ${optimized})` : `\u2713 Upload complete! (${original} \u2192 ${optimized})`;
|
|
129
|
+
}
|
|
130
|
+
var FILE_TYPE_ERROR_REGEX = /\b(?:file\s+type|mime\s+type|invalid\s+type|unsupported|format|mime)\b/i;
|
|
131
|
+
function getFriendlyErrorMessage(error, locale = "en") {
|
|
132
|
+
const lower = error.toLowerCase();
|
|
133
|
+
if (lower.includes("size") || lower.includes("large") || lower.includes("exceeds")) {
|
|
134
|
+
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.";
|
|
135
|
+
}
|
|
136
|
+
if (lower.includes("network") || lower.includes("fetch") || lower.includes("connection")) {
|
|
137
|
+
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.";
|
|
138
|
+
}
|
|
139
|
+
if (lower.includes("timeout") || lower.includes("timed out")) {
|
|
140
|
+
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.";
|
|
141
|
+
}
|
|
142
|
+
if (FILE_TYPE_ERROR_REGEX.test(error)) {
|
|
143
|
+
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)." : "Invalid file type. Please upload a valid image (JPEG, PNG, WebP, AVIF).";
|
|
144
|
+
}
|
|
145
|
+
if (error) return error;
|
|
146
|
+
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.";
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export {
|
|
150
|
+
QUALITY_PRESETS,
|
|
151
|
+
formatFileSize,
|
|
152
|
+
calculateReduction,
|
|
153
|
+
estimateOutputSize,
|
|
154
|
+
getStatusMessage,
|
|
155
|
+
createSuccessMessage,
|
|
156
|
+
getFriendlyErrorMessage
|
|
157
|
+
};
|
|
158
|
+
//# sourceMappingURL=chunk-25GYKQ6J.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/types/quality.ts","../src/utils/formatters.ts"],"sourcesContent":["export type UploadLocale = 'en' | 'ar';\n\nexport type ImageOutputFormat = 'avif' | 'webp' | 'jpeg' | 'png' | 'svg';\n\nexport type ExplicitOutputFormat = 'avif' | 'webp' | 'jpeg' | 'png';\n\nexport type QualityLevel = 'low' | 'medium' | 'high' | 'maximum';\n\nexport interface QualityPreset {\n label: string;\n labelAr: string;\n value: number;\n description: string;\n descriptionAr: string;\n /** Rough fraction of original bytes after modern AVIF/WebP compression */\n compressionRatio: number;\n}\n\nexport const QUALITY_PRESETS: Record<QualityLevel, QualityPreset> = {\n low: {\n label: 'Low',\n labelAr: 'منخفضة',\n value: 50,\n description: 'Smallest file — best for tiny thumbnails and icons',\n descriptionAr: 'أصغر حجم — مناسب للمصغرات والأيقونات الصغيرة',\n compressionRatio: 0.12,\n },\n medium: {\n label: 'Medium',\n labelAr: 'متوسطة',\n value: 72,\n description: 'Balanced size and quality — suitable for most web images',\n descriptionAr: 'توازن بين الحجم والجودة — مناسب لمعظم صور الويب',\n compressionRatio: 0.22,\n },\n high: {\n label: 'High',\n labelAr: 'عالية',\n value: 85,\n description: 'Recommended — sharp visuals with excellent compression',\n descriptionAr: 'موصى به — جودة عالية وضغط ممتاز',\n compressionRatio: 0.3,\n },\n maximum: {\n label: 'Maximum',\n labelAr: 'أقصى جودة',\n value: 95,\n description: 'Closest to original — large file, use for hero / print',\n descriptionAr: 'أقرب للأصل — حجم كبير، مناسب للصور الرئيسية والطباعة',\n compressionRatio: 0.55,\n },\n};\n\nexport interface ImageDimensions {\n width: number;\n height: number;\n}\n","import type { QualityLevel, UploadLocale } from '../types';\r\nimport { QUALITY_PRESETS } from '../types';\r\n\r\nexport function formatFileSize(bytes: number): string {\r\n if (bytes <= 0) return '0 Bytes';\r\n const k = 1024;\r\n const sizes = ['Bytes', 'KB', 'MB', 'GB'];\r\n const i = Math.min(\r\n sizes.length - 1,\r\n Math.floor(Math.log(bytes) / Math.log(k)),\r\n );\r\n return `${Math.round((bytes / Math.pow(k, i)) * 100) / 100} ${sizes[i]}`;\r\n}\r\n\r\nexport function calculateReduction(\r\n original: number,\r\n optimized: number,\r\n): number {\r\n if (original <= 0) return 0;\r\n return Math.round(((original - optimized) / original) * 100);\r\n}\r\n\r\nexport function estimateOutputSize(\r\n originalBytes: number,\r\n level: QualityLevel,\r\n): number {\r\n return Math.round(originalBytes * QUALITY_PRESETS[level].compressionRatio);\r\n}\r\n\r\nconst creativeMessages = [\r\n 'Sprinkling digital magic ✨',\r\n 'Painting pixels with perfection 🎨',\r\n 'Launching to the cloud 🚀',\r\n 'Creating something beautiful ⭐',\r\n 'Transforming your vision ⚡',\r\n 'Weaving visual excellence 💫',\r\n 'Crafting your masterpiece 🎭',\r\n 'Working our magic 🔮',\r\n 'Making it pixel-perfect ✨',\r\n 'Keep calm, creating magic 🎪',\r\n 'Hitting the sweet spot 🎯',\r\n 'Artist mode activated 🎨',\r\n 'Shooting for the stars 🌠',\r\n 'Compressing with love 💝',\r\n 'Enhancing quality 💎',\r\n 'Polishing to perfection ✨',\r\n];\r\n\r\nconst creativeMessagesAr = [\r\n 'نضيف لمسة رقمية ساحرة ✨',\r\n 'ننسق البكسلات بإتقان 🎨',\r\n 'الرفع جارٍ إلى السحابة 🚀',\r\n 'نصنع شيئاً جميلاً ⭐',\r\n 'نحوّل رؤيتك إلى واقع ⚡',\r\n 'نبني تجربة بصرية مميزة 💫',\r\n 'نصقل عملك باحتراف 🎭',\r\n 'السحر جارٍ الآن 🔮',\r\n 'نضبط كل بكسل بعناية ✨',\r\n 'اهدأ، نحن نهتم بالتفاصيل 🎪',\r\n 'نقترب من النتيجة المثالية 🎯',\r\n 'وضع الإبداع مفعل 🎨',\r\n 'نستهدف أفضل نتيجة 🌠',\r\n 'ضغط ذكي مع الحفاظ على الجودة 💝',\r\n 'تحسين الجودة مستمر 💎',\r\n 'اللمسات الأخيرة قيد التنفيذ ✨',\r\n];\r\n\r\nexport function getStatusMessage(\r\n progress: number,\r\n locale: UploadLocale = 'en',\r\n): string {\r\n if (progress >= 95) {\r\n return locale === 'ar' ? '🎉 اقتربنا جداً...' : '🎉 Almost there...';\r\n }\r\n if (progress >= 85) {\r\n return locale === 'ar'\r\n ? '✨ نضع اللمسات الأخيرة...'\r\n : '✨ Polishing the final details...';\r\n }\r\n\r\n const list = locale === 'ar' ? creativeMessagesAr : creativeMessages;\r\n const clampedProgress = Math.max(0, Math.min(99, progress));\r\n const messageIndex = Math.min(\r\n list.length - 1,\r\n Math.floor((clampedProgress / 100) * list.length),\r\n );\r\n\r\n return list[messageIndex];\r\n}\r\n\r\nexport function createSuccessMessage(\r\n originalSize: number,\r\n optimizedSize: number,\r\n compact: boolean = false,\r\n locale: UploadLocale = 'en',\r\n): string {\r\n const reduction = calculateReduction(originalSize, optimizedSize);\r\n const original = formatFileSize(originalSize);\r\n const optimized = formatFileSize(optimizedSize);\r\n\r\n if (compact) {\r\n if (reduction > 50) {\r\n return locale === 'ar'\r\n ? `🎉 أصغر بنسبة ${reduction}%! (${original} → ${optimized})`\r\n : `🎉 ${reduction}% smaller! (${original} → ${optimized})`;\r\n }\r\n if (reduction > 0) {\r\n return locale === 'ar'\r\n ? `✓ أصغر بنسبة ${reduction}% (${original} → ${optimized})`\r\n : `✓ ${reduction}% smaller (${original} → ${optimized})`;\r\n }\r\n return `✓ ${optimized}`;\r\n }\r\n\r\n if (reduction > 70) {\r\n return locale === 'ar'\r\n ? `🎉 رائع! تم تقليل الحجم بنسبة ${reduction}% (${original} → ${optimized})`\r\n : `🎉 Amazing! Reduced by ${reduction}% (${original} → ${optimized})`;\r\n }\r\n if (reduction > 50) {\r\n return locale === 'ar'\r\n ? `✨ ممتاز! تم تقليل الحجم بنسبة ${reduction}% (${original} → ${optimized})`\r\n : `✨ Great! Reduced by ${reduction}% (${original} → ${optimized})`;\r\n }\r\n if (reduction > 20) {\r\n return locale === 'ar'\r\n ? `✓ اكتمل الرفع! تم تقليل الحجم بنسبة ${reduction}% (${original} → ${optimized})`\r\n : `✓ Upload complete! Reduced by ${reduction}% (${original} → ${optimized})`;\r\n }\r\n return locale === 'ar'\r\n ? `✓ اكتمل الرفع! (${original} → ${optimized})`\r\n : `✓ Upload complete! (${original} → ${optimized})`;\r\n}\r\n\r\nconst FILE_TYPE_ERROR_REGEX =\r\n /\\b(?:file\\s+type|mime\\s+type|invalid\\s+type|unsupported|format|mime)\\b/i;\r\n\r\nexport function getFriendlyErrorMessage(\r\n error: string,\r\n locale: UploadLocale = 'en',\r\n): string {\r\n const lower = error.toLowerCase();\r\n if (\r\n lower.includes('size') ||\r\n lower.includes('large') ||\r\n lower.includes('exceeds')\r\n ) {\r\n return locale === 'ar'\r\n ? 'الملف كبير جداً. يرجى اختيار صورة أصغر.'\r\n : 'File is too large. Please choose a smaller image.';\r\n }\r\n if (\r\n lower.includes('network') ||\r\n lower.includes('fetch') ||\r\n lower.includes('connection')\r\n ) {\r\n return locale === 'ar'\r\n ? 'حدث خطأ في الشبكة. يرجى التحقق من الاتصال والمحاولة مرة أخرى.'\r\n : 'Network error. Please check your connection and try again.';\r\n }\r\n if (lower.includes('timeout') || lower.includes('timed out')) {\r\n return locale === 'ar'\r\n ? 'انتهت مهلة الرفع. يرجى المحاولة مرة أخرى.'\r\n : 'Upload timed out. Please try again.';\r\n }\r\n if (FILE_TYPE_ERROR_REGEX.test(error)) {\r\n return locale === 'ar'\r\n ? 'نوع الملف غير صالح. يرجى رفع صورة صالحة (JPEG, PNG, WebP, AVIF).'\r\n : 'Invalid file type. Please upload a valid image (JPEG, PNG, WebP, AVIF).';\r\n }\r\n if (error) return error;\r\n return locale === 'ar'\r\n ? 'فشل الرفع. يرجى المحاولة مرة أخرى.'\r\n : 'Upload failed. Please try again.';\r\n}\r\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }// src/types/presets.ts
|
|
2
|
+
var SVG_MIME_TYPE = "image/svg+xml";
|
|
3
|
+
var DEFAULT_ALLOWED_FORMATS = [
|
|
4
|
+
"image/jpeg",
|
|
5
|
+
"image/png",
|
|
6
|
+
"image/webp",
|
|
7
|
+
"image/avif"
|
|
8
|
+
];
|
|
9
|
+
var RASTER_ALLOWED_FORMATS = [
|
|
10
|
+
"image/jpeg",
|
|
11
|
+
"image/png",
|
|
12
|
+
"image/webp",
|
|
13
|
+
"image/avif"
|
|
14
|
+
];
|
|
15
|
+
var DEFAULT_IMAGE_DIMENSIONS = {
|
|
16
|
+
width: 1920,
|
|
17
|
+
height: 1080
|
|
18
|
+
};
|
|
19
|
+
var STANDARD_PRESETS = {
|
|
20
|
+
thumbnail: {
|
|
21
|
+
folder: "thumbnails",
|
|
22
|
+
maxDimensions: { width: 600, height: 600 },
|
|
23
|
+
maxSizeMB: 5,
|
|
24
|
+
quality: 78,
|
|
25
|
+
recommendedQualityLevel: "medium",
|
|
26
|
+
allowedFormats: RASTER_ALLOWED_FORMATS,
|
|
27
|
+
recommendationNote: {
|
|
28
|
+
en: "Thumbnails display at compact sizes \u2014 Medium quality keeps pages fast",
|
|
29
|
+
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"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
avatar: {
|
|
33
|
+
folder: "avatars",
|
|
34
|
+
maxDimensions: { width: 512, height: 512 },
|
|
35
|
+
maxSizeMB: 5,
|
|
36
|
+
quality: 80,
|
|
37
|
+
recommendedQualityLevel: "medium",
|
|
38
|
+
allowedFormats: RASTER_ALLOWED_FORMATS,
|
|
39
|
+
recommendationNote: {
|
|
40
|
+
en: "Avatars display small \u2014 Medium quality balances sharpness and speed",
|
|
41
|
+
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"
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
card: {
|
|
45
|
+
folder: "cards",
|
|
46
|
+
maxDimensions: { width: 1200, height: 900 },
|
|
47
|
+
maxSizeMB: 8,
|
|
48
|
+
quality: 85,
|
|
49
|
+
recommendedQualityLevel: "high",
|
|
50
|
+
allowedFormats: DEFAULT_ALLOWED_FORMATS
|
|
51
|
+
},
|
|
52
|
+
cover: {
|
|
53
|
+
folder: "covers",
|
|
54
|
+
maxDimensions: { width: 1920, height: 1080 },
|
|
55
|
+
maxSizeMB: 10,
|
|
56
|
+
quality: 88,
|
|
57
|
+
recommendedQualityLevel: "high",
|
|
58
|
+
allowedFormats: DEFAULT_ALLOWED_FORMATS
|
|
59
|
+
},
|
|
60
|
+
hero: {
|
|
61
|
+
folder: "hero",
|
|
62
|
+
maxDimensions: { width: 2560, height: 1440 },
|
|
63
|
+
maxSizeMB: 15,
|
|
64
|
+
quality: 92,
|
|
65
|
+
recommendedQualityLevel: "maximum",
|
|
66
|
+
allowedFormats: DEFAULT_ALLOWED_FORMATS,
|
|
67
|
+
recommendationNote: {
|
|
68
|
+
en: "Full-width hero visuals benefit from Maximum quality to preserve fine detail",
|
|
69
|
+
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"
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
logo: {
|
|
73
|
+
folder: "logos",
|
|
74
|
+
maxDimensions: { width: 800, height: 800 },
|
|
75
|
+
maxSizeMB: 5,
|
|
76
|
+
quality: 90,
|
|
77
|
+
recommendedQualityLevel: "high",
|
|
78
|
+
allowedFormats: DEFAULT_ALLOWED_FORMATS,
|
|
79
|
+
recommendationNote: {
|
|
80
|
+
en: "Prefer SVG for vector logos \u2014 High quality preserves crisp edges on raster logos",
|
|
81
|
+
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"
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
original: {
|
|
85
|
+
folder: "originals",
|
|
86
|
+
maxDimensions: { width: 4096, height: 4096 },
|
|
87
|
+
maxSizeMB: 25,
|
|
88
|
+
quality: 95,
|
|
89
|
+
recommendedQualityLevel: "maximum",
|
|
90
|
+
allowedFormats: DEFAULT_ALLOWED_FORMATS
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
function defineUploadPresets(presets) {
|
|
94
|
+
return presets;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// src/utils/color.ts
|
|
98
|
+
var DEFAULT_BLUR_COLOR = "#F5F5F5";
|
|
99
|
+
function normalizeColorInput(value) {
|
|
100
|
+
if (!value) return null;
|
|
101
|
+
let next = value.trim();
|
|
102
|
+
if (!next) return null;
|
|
103
|
+
if (!next.startsWith("#")) {
|
|
104
|
+
next = `#${next}`;
|
|
105
|
+
}
|
|
106
|
+
const threeHex = /^#([0-9a-fA-F]{3})$/;
|
|
107
|
+
const sixHex = /^#([0-9a-fA-F]{6})$/;
|
|
108
|
+
if (threeHex.test(next)) {
|
|
109
|
+
const [, triplet] = _nullishCoalesce(next.match(threeHex), () => ( []));
|
|
110
|
+
if (triplet) {
|
|
111
|
+
next = `#${triplet.split("").map((char) => char + char).join("")}`;
|
|
112
|
+
}
|
|
113
|
+
} else if (!sixHex.test(next)) {
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
return next.toUpperCase();
|
|
117
|
+
}
|
|
118
|
+
function hexToRgb(hex) {
|
|
119
|
+
const normalized = hex.replace("#", "");
|
|
120
|
+
const expanded = normalized.length === 3 ? normalized.split("").map((char) => char + char).join("") : normalized;
|
|
121
|
+
const padded = expanded.padEnd(6, "0").slice(0, 6);
|
|
122
|
+
const value = Number.parseInt(padded, 16);
|
|
123
|
+
if (Number.isNaN(value)) {
|
|
124
|
+
return { r: 245, g: 245, b: 245 };
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
r: value >> 16 & 255,
|
|
128
|
+
g: value >> 8 & 255,
|
|
129
|
+
b: value & 255
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
function rgbToHex(r, g, b) {
|
|
133
|
+
const clamp = (v) => Math.max(0, Math.min(255, Math.round(v)));
|
|
134
|
+
const value = clamp(r) << 16 | clamp(g) << 8 | clamp(b);
|
|
135
|
+
return `#${value.toString(16).padStart(6, "0").toUpperCase()}`;
|
|
136
|
+
}
|
|
137
|
+
function encodeBase64Ascii(str) {
|
|
138
|
+
if (typeof btoa === "function") {
|
|
139
|
+
return btoa(str);
|
|
140
|
+
}
|
|
141
|
+
return Buffer.from(str, "utf8").toString("base64");
|
|
142
|
+
}
|
|
143
|
+
function generateColorSvgDataURL(color = DEFAULT_BLUR_COLOR) {
|
|
144
|
+
const safeColor = normalizeColorInput(color) || DEFAULT_BLUR_COLOR;
|
|
145
|
+
const svg = `<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg"><rect width="100%" height="100%" fill="${safeColor}"/></svg>`;
|
|
146
|
+
return `data:image/svg+xml;base64,${encodeBase64Ascii(svg)}`;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// src/utils/validators.ts
|
|
150
|
+
function validateImageFileStrict(file, maxSizeMB, allowedFormats) {
|
|
151
|
+
const maxBytes = maxSizeMB * 1024 * 1024;
|
|
152
|
+
if (file.size > maxBytes) {
|
|
153
|
+
return {
|
|
154
|
+
valid: false,
|
|
155
|
+
error: `File size (${(file.size / 1024 / 1024).toFixed(2)}MB) exceeds maximum of ${maxSizeMB}MB`
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
if (allowedFormats.length > 0 && !allowedFormats.includes(file.type)) {
|
|
159
|
+
return {
|
|
160
|
+
valid: false,
|
|
161
|
+
error: `File type ${file.type || "unknown"} is not allowed. Allowed: ${allowedFormats.join(", ")}`
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
return { valid: true };
|
|
165
|
+
}
|
|
166
|
+
function validateImageFile(file, maxSizeMB, locale = "en", allowedFormats) {
|
|
167
|
+
if (!file.type || !file.type.startsWith("image/")) {
|
|
168
|
+
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";
|
|
169
|
+
}
|
|
170
|
+
if (allowedFormats && allowedFormats.length > 0 && !allowedFormats.includes(file.type)) {
|
|
171
|
+
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})`;
|
|
172
|
+
}
|
|
173
|
+
const fileSizeMB = file.size / (1024 * 1024);
|
|
174
|
+
if (fileSizeMB > maxSizeMB) {
|
|
175
|
+
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`;
|
|
176
|
+
}
|
|
177
|
+
return null;
|
|
178
|
+
}
|
|
179
|
+
function validateImageFileWithName(file, maxSizeMB, locale = "en") {
|
|
180
|
+
if (!file.type || !file.type.startsWith("image/")) {
|
|
181
|
+
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`;
|
|
182
|
+
}
|
|
183
|
+
const fileSizeMB = file.size / (1024 * 1024);
|
|
184
|
+
if (fileSizeMB > maxSizeMB) {
|
|
185
|
+
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`;
|
|
186
|
+
}
|
|
187
|
+
return null;
|
|
188
|
+
}
|
|
189
|
+
function validateMultipleFiles(files, maxSizeMB, currentCount, maxImages, locale = "en") {
|
|
190
|
+
if (currentCount + files.length > maxImages) {
|
|
191
|
+
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.`;
|
|
192
|
+
}
|
|
193
|
+
const oversizedFiles = [];
|
|
194
|
+
for (const file of files) {
|
|
195
|
+
const fileSizeMB = file.size / (1024 * 1024);
|
|
196
|
+
if (fileSizeMB > maxSizeMB) {
|
|
197
|
+
oversizedFiles.push(file.name);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
if (oversizedFiles.length > 0) {
|
|
201
|
+
if (locale === "ar") {
|
|
202
|
+
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(", ")}`;
|
|
203
|
+
}
|
|
204
|
+
return `The following file${oversizedFiles.length > 1 ? "s are" : " is"} too large (max ${maxSizeMB}MB): ${oversizedFiles.join(", ")}`;
|
|
205
|
+
}
|
|
206
|
+
return null;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
exports.SVG_MIME_TYPE = SVG_MIME_TYPE; exports.DEFAULT_ALLOWED_FORMATS = DEFAULT_ALLOWED_FORMATS; exports.RASTER_ALLOWED_FORMATS = RASTER_ALLOWED_FORMATS; exports.DEFAULT_IMAGE_DIMENSIONS = DEFAULT_IMAGE_DIMENSIONS; exports.STANDARD_PRESETS = STANDARD_PRESETS; exports.defineUploadPresets = defineUploadPresets; exports.DEFAULT_BLUR_COLOR = DEFAULT_BLUR_COLOR; exports.normalizeColorInput = normalizeColorInput; exports.hexToRgb = hexToRgb; exports.rgbToHex = rgbToHex; exports.generateColorSvgDataURL = generateColorSvgDataURL; exports.validateImageFileStrict = validateImageFileStrict; exports.validateImageFile = validateImageFile; exports.validateImageFileWithName = validateImageFileWithName; exports.validateMultipleFiles = validateMultipleFiles;
|
|
226
|
+
//# sourceMappingURL=chunk-34L4TEE3.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["e:\\Personal-Projects\\image-upload-kit\\dist\\chunk-34L4TEE3.cjs"],"names":[],"mappings":"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AAC,CAAC,KAAK,EAAE,OAAO,IAAI;AACzB,EAAE,IAAI,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;AACzB,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,OAAO,IAAI;AACxB,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE;AAC7B,IAAI,KAAK,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,CAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"E:\\Personal-Projects\\image-upload-kit\\dist\\chunk-34L4TEE3.cjs","sourcesContent":[null]}
|