@orion-studios/payload-studio 0.5.0-beta.63 → 0.5.0-beta.64
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/dist/admin-app/client.js
CHANGED
|
@@ -691,6 +691,64 @@ function MediaListItem({
|
|
|
691
691
|
// src/admin-app/components/MediaUploadForm.tsx
|
|
692
692
|
var import_react5 = require("react");
|
|
693
693
|
var import_navigation = require("next/navigation");
|
|
694
|
+
|
|
695
|
+
// src/shared/clientImageUploadOptimization.ts
|
|
696
|
+
var MAX_DIRECT_UPLOAD_BYTES = 4e6;
|
|
697
|
+
async function optimizeImageForUpload(file) {
|
|
698
|
+
if (!file.type.startsWith("image/")) {
|
|
699
|
+
return file;
|
|
700
|
+
}
|
|
701
|
+
if (file.size <= MAX_DIRECT_UPLOAD_BYTES) {
|
|
702
|
+
return file;
|
|
703
|
+
}
|
|
704
|
+
const objectURL = URL.createObjectURL(file);
|
|
705
|
+
try {
|
|
706
|
+
const image = await new Promise((resolve, reject) => {
|
|
707
|
+
const nextImage = new Image();
|
|
708
|
+
nextImage.onload = () => resolve(nextImage);
|
|
709
|
+
nextImage.onerror = () => reject(new Error("Could not read image for upload optimization."));
|
|
710
|
+
nextImage.src = objectURL;
|
|
711
|
+
});
|
|
712
|
+
const canvas = document.createElement("canvas");
|
|
713
|
+
canvas.width = Math.max(1, image.width);
|
|
714
|
+
canvas.height = Math.max(1, image.height);
|
|
715
|
+
const context = canvas.getContext("2d");
|
|
716
|
+
if (!context) {
|
|
717
|
+
return file;
|
|
718
|
+
}
|
|
719
|
+
context.drawImage(image, 0, 0, canvas.width, canvas.height);
|
|
720
|
+
const outputMime = file.type === "image/webp" ? "image/webp" : "image/jpeg";
|
|
721
|
+
const qualityPasses = [0.82, 0.74, 0.66, 0.58, 0.5, 0.42, 0.36];
|
|
722
|
+
let bestFile = null;
|
|
723
|
+
for (const quality of qualityPasses) {
|
|
724
|
+
const blob = await new Promise((resolve) => {
|
|
725
|
+
canvas.toBlob((value) => resolve(value), outputMime, quality);
|
|
726
|
+
});
|
|
727
|
+
if (!blob) {
|
|
728
|
+
continue;
|
|
729
|
+
}
|
|
730
|
+
const optimizedName = file.name.replace(/\.[^/.]+$/, outputMime === "image/webp" ? ".webp" : ".jpg");
|
|
731
|
+
const optimized = new File([blob], optimizedName, {
|
|
732
|
+
lastModified: Date.now(),
|
|
733
|
+
type: outputMime
|
|
734
|
+
});
|
|
735
|
+
if (!bestFile || optimized.size < bestFile.size) {
|
|
736
|
+
bestFile = optimized;
|
|
737
|
+
}
|
|
738
|
+
if (optimized.size <= MAX_DIRECT_UPLOAD_BYTES) {
|
|
739
|
+
break;
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
if (!bestFile) {
|
|
743
|
+
return file;
|
|
744
|
+
}
|
|
745
|
+
return bestFile.size < file.size ? bestFile : file;
|
|
746
|
+
} finally {
|
|
747
|
+
URL.revokeObjectURL(objectURL);
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
// src/admin-app/components/MediaUploadForm.tsx
|
|
694
752
|
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
695
753
|
var MEDIA_LIBRARY_SYNC_EVENT = "orion-media-library-updated";
|
|
696
754
|
var notifyMediaLibraryUpdated = () => {
|
|
@@ -773,12 +831,16 @@ function MediaUploadForm() {
|
|
|
773
831
|
setSubmitting(true);
|
|
774
832
|
setError(null);
|
|
775
833
|
try {
|
|
834
|
+
const optimizedFile = await optimizeImageForUpload(file);
|
|
835
|
+
if (optimizedFile.size > MAX_DIRECT_UPLOAD_BYTES) {
|
|
836
|
+
throw new Error("Image is too large. Use an image under 4MB or lower-resolution export.");
|
|
837
|
+
}
|
|
776
838
|
const formData = new FormData();
|
|
777
839
|
const fallbackAlt = file.name.replace(/\.[^/.]+$/, "").trim();
|
|
778
840
|
const resolvedAlt = alt.trim() || fallbackAlt || "Uploaded image";
|
|
779
841
|
formData.set("_payload", JSON.stringify({ alt: resolvedAlt }));
|
|
780
842
|
formData.set("alt", resolvedAlt);
|
|
781
|
-
formData.set("file",
|
|
843
|
+
formData.set("file", optimizedFile);
|
|
782
844
|
const response = await fetch("/api/media", {
|
|
783
845
|
method: "POST",
|
|
784
846
|
credentials: "include",
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
'use client';
|
|
2
|
+
import {
|
|
3
|
+
MAX_DIRECT_UPLOAD_BYTES,
|
|
4
|
+
optimizeImageForUpload
|
|
5
|
+
} from "../chunk-I522K6BZ.mjs";
|
|
2
6
|
|
|
3
7
|
// src/admin-app/components/AdminShellClient.tsx
|
|
4
8
|
import { useEffect, useState } from "react";
|
|
@@ -742,12 +746,16 @@ function MediaUploadForm() {
|
|
|
742
746
|
setSubmitting(true);
|
|
743
747
|
setError(null);
|
|
744
748
|
try {
|
|
749
|
+
const optimizedFile = await optimizeImageForUpload(file);
|
|
750
|
+
if (optimizedFile.size > MAX_DIRECT_UPLOAD_BYTES) {
|
|
751
|
+
throw new Error("Image is too large. Use an image under 4MB or lower-resolution export.");
|
|
752
|
+
}
|
|
745
753
|
const formData = new FormData();
|
|
746
754
|
const fallbackAlt = file.name.replace(/\.[^/.]+$/, "").trim();
|
|
747
755
|
const resolvedAlt = alt.trim() || fallbackAlt || "Uploaded image";
|
|
748
756
|
formData.set("_payload", JSON.stringify({ alt: resolvedAlt }));
|
|
749
757
|
formData.set("alt", resolvedAlt);
|
|
750
|
-
formData.set("file",
|
|
758
|
+
formData.set("file", optimizedFile);
|
|
751
759
|
const response = await fetch("/api/media", {
|
|
752
760
|
method: "POST",
|
|
753
761
|
credentials: "include",
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
// src/shared/clientImageUploadOptimization.ts
|
|
4
|
+
var MAX_DIRECT_UPLOAD_BYTES = 4e6;
|
|
5
|
+
async function optimizeImageForUpload(file) {
|
|
6
|
+
if (!file.type.startsWith("image/")) {
|
|
7
|
+
return file;
|
|
8
|
+
}
|
|
9
|
+
if (file.size <= MAX_DIRECT_UPLOAD_BYTES) {
|
|
10
|
+
return file;
|
|
11
|
+
}
|
|
12
|
+
const objectURL = URL.createObjectURL(file);
|
|
13
|
+
try {
|
|
14
|
+
const image = await new Promise((resolve, reject) => {
|
|
15
|
+
const nextImage = new Image();
|
|
16
|
+
nextImage.onload = () => resolve(nextImage);
|
|
17
|
+
nextImage.onerror = () => reject(new Error("Could not read image for upload optimization."));
|
|
18
|
+
nextImage.src = objectURL;
|
|
19
|
+
});
|
|
20
|
+
const canvas = document.createElement("canvas");
|
|
21
|
+
canvas.width = Math.max(1, image.width);
|
|
22
|
+
canvas.height = Math.max(1, image.height);
|
|
23
|
+
const context = canvas.getContext("2d");
|
|
24
|
+
if (!context) {
|
|
25
|
+
return file;
|
|
26
|
+
}
|
|
27
|
+
context.drawImage(image, 0, 0, canvas.width, canvas.height);
|
|
28
|
+
const outputMime = file.type === "image/webp" ? "image/webp" : "image/jpeg";
|
|
29
|
+
const qualityPasses = [0.82, 0.74, 0.66, 0.58, 0.5, 0.42, 0.36];
|
|
30
|
+
let bestFile = null;
|
|
31
|
+
for (const quality of qualityPasses) {
|
|
32
|
+
const blob = await new Promise((resolve) => {
|
|
33
|
+
canvas.toBlob((value) => resolve(value), outputMime, quality);
|
|
34
|
+
});
|
|
35
|
+
if (!blob) {
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
const optimizedName = file.name.replace(/\.[^/.]+$/, outputMime === "image/webp" ? ".webp" : ".jpg");
|
|
39
|
+
const optimized = new File([blob], optimizedName, {
|
|
40
|
+
lastModified: Date.now(),
|
|
41
|
+
type: outputMime
|
|
42
|
+
});
|
|
43
|
+
if (!bestFile || optimized.size < bestFile.size) {
|
|
44
|
+
bestFile = optimized;
|
|
45
|
+
}
|
|
46
|
+
if (optimized.size <= MAX_DIRECT_UPLOAD_BYTES) {
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (!bestFile) {
|
|
51
|
+
return file;
|
|
52
|
+
}
|
|
53
|
+
return bestFile.size < file.size ? bestFile : file;
|
|
54
|
+
} finally {
|
|
55
|
+
URL.revokeObjectURL(objectURL);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export {
|
|
60
|
+
MAX_DIRECT_UPLOAD_BYTES,
|
|
61
|
+
optimizeImageForUpload
|
|
62
|
+
};
|
|
@@ -263,6 +263,62 @@ var layoutToStudioDocument = (layout, title, metadata) => {
|
|
|
263
263
|
};
|
|
264
264
|
};
|
|
265
265
|
|
|
266
|
+
// src/shared/clientImageUploadOptimization.ts
|
|
267
|
+
var MAX_DIRECT_UPLOAD_BYTES = 4e6;
|
|
268
|
+
async function optimizeImageForUpload(file) {
|
|
269
|
+
if (!file.type.startsWith("image/")) {
|
|
270
|
+
return file;
|
|
271
|
+
}
|
|
272
|
+
if (file.size <= MAX_DIRECT_UPLOAD_BYTES) {
|
|
273
|
+
return file;
|
|
274
|
+
}
|
|
275
|
+
const objectURL = URL.createObjectURL(file);
|
|
276
|
+
try {
|
|
277
|
+
const image = await new Promise((resolve, reject) => {
|
|
278
|
+
const nextImage = new Image();
|
|
279
|
+
nextImage.onload = () => resolve(nextImage);
|
|
280
|
+
nextImage.onerror = () => reject(new Error("Could not read image for upload optimization."));
|
|
281
|
+
nextImage.src = objectURL;
|
|
282
|
+
});
|
|
283
|
+
const canvas = document.createElement("canvas");
|
|
284
|
+
canvas.width = Math.max(1, image.width);
|
|
285
|
+
canvas.height = Math.max(1, image.height);
|
|
286
|
+
const context = canvas.getContext("2d");
|
|
287
|
+
if (!context) {
|
|
288
|
+
return file;
|
|
289
|
+
}
|
|
290
|
+
context.drawImage(image, 0, 0, canvas.width, canvas.height);
|
|
291
|
+
const outputMime = file.type === "image/webp" ? "image/webp" : "image/jpeg";
|
|
292
|
+
const qualityPasses = [0.82, 0.74, 0.66, 0.58, 0.5, 0.42, 0.36];
|
|
293
|
+
let bestFile = null;
|
|
294
|
+
for (const quality of qualityPasses) {
|
|
295
|
+
const blob = await new Promise((resolve) => {
|
|
296
|
+
canvas.toBlob((value) => resolve(value), outputMime, quality);
|
|
297
|
+
});
|
|
298
|
+
if (!blob) {
|
|
299
|
+
continue;
|
|
300
|
+
}
|
|
301
|
+
const optimizedName = file.name.replace(/\.[^/.]+$/, outputMime === "image/webp" ? ".webp" : ".jpg");
|
|
302
|
+
const optimized = new File([blob], optimizedName, {
|
|
303
|
+
lastModified: Date.now(),
|
|
304
|
+
type: outputMime
|
|
305
|
+
});
|
|
306
|
+
if (!bestFile || optimized.size < bestFile.size) {
|
|
307
|
+
bestFile = optimized;
|
|
308
|
+
}
|
|
309
|
+
if (optimized.size <= MAX_DIRECT_UPLOAD_BYTES) {
|
|
310
|
+
break;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
if (!bestFile) {
|
|
314
|
+
return file;
|
|
315
|
+
}
|
|
316
|
+
return bestFile.size < file.size ? bestFile : file;
|
|
317
|
+
} finally {
|
|
318
|
+
URL.revokeObjectURL(objectURL);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
266
322
|
// src/studio-pages/builder/presets.ts
|
|
267
323
|
var sectionPresets = [
|
|
268
324
|
{
|
|
@@ -1030,7 +1086,6 @@ async function parsePayloadErrorMessage(response, fallbackMessage) {
|
|
|
1030
1086
|
}
|
|
1031
1087
|
return fallbackMessage;
|
|
1032
1088
|
}
|
|
1033
|
-
var MAX_DIRECT_UPLOAD_BYTES = 4e6;
|
|
1034
1089
|
var MEDIA_LIBRARY_SYNC_EVENT = "orion-media-library-updated";
|
|
1035
1090
|
var notifyMediaLibraryUpdated = () => {
|
|
1036
1091
|
if (typeof window === "undefined") {
|
|
@@ -1049,59 +1104,6 @@ var notifyMediaLibraryUpdated = () => {
|
|
|
1049
1104
|
} catch {
|
|
1050
1105
|
}
|
|
1051
1106
|
};
|
|
1052
|
-
async function optimizeImageForUpload(file) {
|
|
1053
|
-
if (!file.type.startsWith("image/")) {
|
|
1054
|
-
return file;
|
|
1055
|
-
}
|
|
1056
|
-
if (file.size <= MAX_DIRECT_UPLOAD_BYTES) {
|
|
1057
|
-
return file;
|
|
1058
|
-
}
|
|
1059
|
-
const objectURL = URL.createObjectURL(file);
|
|
1060
|
-
try {
|
|
1061
|
-
const image = await new Promise((resolve, reject) => {
|
|
1062
|
-
const nextImage = new Image();
|
|
1063
|
-
nextImage.onload = () => resolve(nextImage);
|
|
1064
|
-
nextImage.onerror = () => reject(new Error("Could not read image for upload optimization."));
|
|
1065
|
-
nextImage.src = objectURL;
|
|
1066
|
-
});
|
|
1067
|
-
const canvas = document.createElement("canvas");
|
|
1068
|
-
canvas.width = Math.max(1, image.width);
|
|
1069
|
-
canvas.height = Math.max(1, image.height);
|
|
1070
|
-
const context = canvas.getContext("2d");
|
|
1071
|
-
if (!context) {
|
|
1072
|
-
return file;
|
|
1073
|
-
}
|
|
1074
|
-
context.drawImage(image, 0, 0, canvas.width, canvas.height);
|
|
1075
|
-
const outputMime = file.type === "image/webp" ? "image/webp" : "image/jpeg";
|
|
1076
|
-
const qualityPasses = [0.82, 0.74, 0.66, 0.58, 0.5, 0.42, 0.36];
|
|
1077
|
-
let bestFile = null;
|
|
1078
|
-
for (const quality of qualityPasses) {
|
|
1079
|
-
const blob = await new Promise((resolve) => {
|
|
1080
|
-
canvas.toBlob((value) => resolve(value), outputMime, quality);
|
|
1081
|
-
});
|
|
1082
|
-
if (!blob) {
|
|
1083
|
-
continue;
|
|
1084
|
-
}
|
|
1085
|
-
const optimizedName = file.name.replace(/\.[^/.]+$/, outputMime === "image/webp" ? ".webp" : ".jpg");
|
|
1086
|
-
const optimized = new File([blob], optimizedName, {
|
|
1087
|
-
lastModified: Date.now(),
|
|
1088
|
-
type: outputMime
|
|
1089
|
-
});
|
|
1090
|
-
if (!bestFile || optimized.size < bestFile.size) {
|
|
1091
|
-
bestFile = optimized;
|
|
1092
|
-
}
|
|
1093
|
-
if (optimized.size <= MAX_DIRECT_UPLOAD_BYTES) {
|
|
1094
|
-
break;
|
|
1095
|
-
}
|
|
1096
|
-
}
|
|
1097
|
-
if (!bestFile) {
|
|
1098
|
-
return file;
|
|
1099
|
-
}
|
|
1100
|
-
return bestFile.size < file.size ? bestFile : file;
|
|
1101
|
-
} finally {
|
|
1102
|
-
URL.revokeObjectURL(objectURL);
|
|
1103
|
-
}
|
|
1104
|
-
}
|
|
1105
1107
|
function InlineText({
|
|
1106
1108
|
as = "p",
|
|
1107
1109
|
className,
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
"use client";
|
|
3
|
+
import {
|
|
4
|
+
MAX_DIRECT_UPLOAD_BYTES,
|
|
5
|
+
optimizeImageForUpload
|
|
6
|
+
} from "../chunk-I522K6BZ.mjs";
|
|
3
7
|
|
|
4
8
|
// src/studio-pages/builder/BuilderPageEditor.tsx
|
|
5
9
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
@@ -1002,7 +1006,6 @@ async function parsePayloadErrorMessage(response, fallbackMessage) {
|
|
|
1002
1006
|
}
|
|
1003
1007
|
return fallbackMessage;
|
|
1004
1008
|
}
|
|
1005
|
-
var MAX_DIRECT_UPLOAD_BYTES = 4e6;
|
|
1006
1009
|
var MEDIA_LIBRARY_SYNC_EVENT = "orion-media-library-updated";
|
|
1007
1010
|
var notifyMediaLibraryUpdated = () => {
|
|
1008
1011
|
if (typeof window === "undefined") {
|
|
@@ -1021,59 +1024,6 @@ var notifyMediaLibraryUpdated = () => {
|
|
|
1021
1024
|
} catch {
|
|
1022
1025
|
}
|
|
1023
1026
|
};
|
|
1024
|
-
async function optimizeImageForUpload(file) {
|
|
1025
|
-
if (!file.type.startsWith("image/")) {
|
|
1026
|
-
return file;
|
|
1027
|
-
}
|
|
1028
|
-
if (file.size <= MAX_DIRECT_UPLOAD_BYTES) {
|
|
1029
|
-
return file;
|
|
1030
|
-
}
|
|
1031
|
-
const objectURL = URL.createObjectURL(file);
|
|
1032
|
-
try {
|
|
1033
|
-
const image = await new Promise((resolve, reject) => {
|
|
1034
|
-
const nextImage = new Image();
|
|
1035
|
-
nextImage.onload = () => resolve(nextImage);
|
|
1036
|
-
nextImage.onerror = () => reject(new Error("Could not read image for upload optimization."));
|
|
1037
|
-
nextImage.src = objectURL;
|
|
1038
|
-
});
|
|
1039
|
-
const canvas = document.createElement("canvas");
|
|
1040
|
-
canvas.width = Math.max(1, image.width);
|
|
1041
|
-
canvas.height = Math.max(1, image.height);
|
|
1042
|
-
const context = canvas.getContext("2d");
|
|
1043
|
-
if (!context) {
|
|
1044
|
-
return file;
|
|
1045
|
-
}
|
|
1046
|
-
context.drawImage(image, 0, 0, canvas.width, canvas.height);
|
|
1047
|
-
const outputMime = file.type === "image/webp" ? "image/webp" : "image/jpeg";
|
|
1048
|
-
const qualityPasses = [0.82, 0.74, 0.66, 0.58, 0.5, 0.42, 0.36];
|
|
1049
|
-
let bestFile = null;
|
|
1050
|
-
for (const quality of qualityPasses) {
|
|
1051
|
-
const blob = await new Promise((resolve) => {
|
|
1052
|
-
canvas.toBlob((value) => resolve(value), outputMime, quality);
|
|
1053
|
-
});
|
|
1054
|
-
if (!blob) {
|
|
1055
|
-
continue;
|
|
1056
|
-
}
|
|
1057
|
-
const optimizedName = file.name.replace(/\.[^/.]+$/, outputMime === "image/webp" ? ".webp" : ".jpg");
|
|
1058
|
-
const optimized = new File([blob], optimizedName, {
|
|
1059
|
-
lastModified: Date.now(),
|
|
1060
|
-
type: outputMime
|
|
1061
|
-
});
|
|
1062
|
-
if (!bestFile || optimized.size < bestFile.size) {
|
|
1063
|
-
bestFile = optimized;
|
|
1064
|
-
}
|
|
1065
|
-
if (optimized.size <= MAX_DIRECT_UPLOAD_BYTES) {
|
|
1066
|
-
break;
|
|
1067
|
-
}
|
|
1068
|
-
}
|
|
1069
|
-
if (!bestFile) {
|
|
1070
|
-
return file;
|
|
1071
|
-
}
|
|
1072
|
-
return bestFile.size < file.size ? bestFile : file;
|
|
1073
|
-
} finally {
|
|
1074
|
-
URL.revokeObjectURL(objectURL);
|
|
1075
|
-
}
|
|
1076
|
-
}
|
|
1077
1027
|
function InlineText({
|
|
1078
1028
|
as = "p",
|
|
1079
1029
|
className,
|