@orion-studios/payload-studio 0.5.0-beta.63 → 0.5.0-beta.65
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,61 @@ 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
|
+
const objectURL = URL.createObjectURL(file);
|
|
702
|
+
try {
|
|
703
|
+
const image = await new Promise((resolve, reject) => {
|
|
704
|
+
const nextImage = new Image();
|
|
705
|
+
nextImage.onload = () => resolve(nextImage);
|
|
706
|
+
nextImage.onerror = () => reject(new Error("Could not read image for upload optimization."));
|
|
707
|
+
nextImage.src = objectURL;
|
|
708
|
+
});
|
|
709
|
+
const canvas = document.createElement("canvas");
|
|
710
|
+
canvas.width = Math.max(1, image.width);
|
|
711
|
+
canvas.height = Math.max(1, image.height);
|
|
712
|
+
const context = canvas.getContext("2d");
|
|
713
|
+
if (!context) {
|
|
714
|
+
return file;
|
|
715
|
+
}
|
|
716
|
+
context.drawImage(image, 0, 0, canvas.width, canvas.height);
|
|
717
|
+
const outputMime = file.type === "image/webp" ? "image/webp" : "image/jpeg";
|
|
718
|
+
const qualityPasses = [0.82, 0.74, 0.66, 0.58, 0.5, 0.42, 0.36, 0.3, 0.26];
|
|
719
|
+
let bestFile = null;
|
|
720
|
+
for (const quality of qualityPasses) {
|
|
721
|
+
const blob = await new Promise((resolve) => {
|
|
722
|
+
canvas.toBlob((value) => resolve(value), outputMime, quality);
|
|
723
|
+
});
|
|
724
|
+
if (!blob) {
|
|
725
|
+
continue;
|
|
726
|
+
}
|
|
727
|
+
const optimizedName = file.name.replace(/\.[^/.]+$/, outputMime === "image/webp" ? ".webp" : ".jpg");
|
|
728
|
+
const optimized = new File([blob], optimizedName, {
|
|
729
|
+
lastModified: Date.now(),
|
|
730
|
+
type: outputMime
|
|
731
|
+
});
|
|
732
|
+
if (!bestFile || optimized.size < bestFile.size) {
|
|
733
|
+
bestFile = optimized;
|
|
734
|
+
}
|
|
735
|
+
if (optimized.size <= MAX_DIRECT_UPLOAD_BYTES) {
|
|
736
|
+
break;
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
if (!bestFile) {
|
|
740
|
+
return file;
|
|
741
|
+
}
|
|
742
|
+
return bestFile.size < file.size ? bestFile : file;
|
|
743
|
+
} finally {
|
|
744
|
+
URL.revokeObjectURL(objectURL);
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
// src/admin-app/components/MediaUploadForm.tsx
|
|
694
749
|
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
695
750
|
var MEDIA_LIBRARY_SYNC_EVENT = "orion-media-library-updated";
|
|
696
751
|
var notifyMediaLibraryUpdated = () => {
|
|
@@ -773,12 +828,16 @@ function MediaUploadForm() {
|
|
|
773
828
|
setSubmitting(true);
|
|
774
829
|
setError(null);
|
|
775
830
|
try {
|
|
831
|
+
const optimizedFile = await optimizeImageForUpload(file);
|
|
832
|
+
if (optimizedFile.size > MAX_DIRECT_UPLOAD_BYTES) {
|
|
833
|
+
throw new Error("Image is too large. Use an image under 4MB or lower-resolution export.");
|
|
834
|
+
}
|
|
776
835
|
const formData = new FormData();
|
|
777
836
|
const fallbackAlt = file.name.replace(/\.[^/.]+$/, "").trim();
|
|
778
837
|
const resolvedAlt = alt.trim() || fallbackAlt || "Uploaded image";
|
|
779
838
|
formData.set("_payload", JSON.stringify({ alt: resolvedAlt }));
|
|
780
839
|
formData.set("alt", resolvedAlt);
|
|
781
|
-
formData.set("file",
|
|
840
|
+
formData.set("file", optimizedFile);
|
|
782
841
|
const response = await fetch("/api/media", {
|
|
783
842
|
method: "POST",
|
|
784
843
|
credentials: "include",
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
'use client';
|
|
2
|
+
import {
|
|
3
|
+
MAX_DIRECT_UPLOAD_BYTES,
|
|
4
|
+
optimizeImageForUpload
|
|
5
|
+
} from "../chunk-I3HYCS77.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,59 @@
|
|
|
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
|
+
const objectURL = URL.createObjectURL(file);
|
|
10
|
+
try {
|
|
11
|
+
const image = await new Promise((resolve, reject) => {
|
|
12
|
+
const nextImage = new Image();
|
|
13
|
+
nextImage.onload = () => resolve(nextImage);
|
|
14
|
+
nextImage.onerror = () => reject(new Error("Could not read image for upload optimization."));
|
|
15
|
+
nextImage.src = objectURL;
|
|
16
|
+
});
|
|
17
|
+
const canvas = document.createElement("canvas");
|
|
18
|
+
canvas.width = Math.max(1, image.width);
|
|
19
|
+
canvas.height = Math.max(1, image.height);
|
|
20
|
+
const context = canvas.getContext("2d");
|
|
21
|
+
if (!context) {
|
|
22
|
+
return file;
|
|
23
|
+
}
|
|
24
|
+
context.drawImage(image, 0, 0, canvas.width, canvas.height);
|
|
25
|
+
const outputMime = file.type === "image/webp" ? "image/webp" : "image/jpeg";
|
|
26
|
+
const qualityPasses = [0.82, 0.74, 0.66, 0.58, 0.5, 0.42, 0.36, 0.3, 0.26];
|
|
27
|
+
let bestFile = null;
|
|
28
|
+
for (const quality of qualityPasses) {
|
|
29
|
+
const blob = await new Promise((resolve) => {
|
|
30
|
+
canvas.toBlob((value) => resolve(value), outputMime, quality);
|
|
31
|
+
});
|
|
32
|
+
if (!blob) {
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
const optimizedName = file.name.replace(/\.[^/.]+$/, outputMime === "image/webp" ? ".webp" : ".jpg");
|
|
36
|
+
const optimized = new File([blob], optimizedName, {
|
|
37
|
+
lastModified: Date.now(),
|
|
38
|
+
type: outputMime
|
|
39
|
+
});
|
|
40
|
+
if (!bestFile || optimized.size < bestFile.size) {
|
|
41
|
+
bestFile = optimized;
|
|
42
|
+
}
|
|
43
|
+
if (optimized.size <= MAX_DIRECT_UPLOAD_BYTES) {
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (!bestFile) {
|
|
48
|
+
return file;
|
|
49
|
+
}
|
|
50
|
+
return bestFile.size < file.size ? bestFile : file;
|
|
51
|
+
} finally {
|
|
52
|
+
URL.revokeObjectURL(objectURL);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export {
|
|
57
|
+
MAX_DIRECT_UPLOAD_BYTES,
|
|
58
|
+
optimizeImageForUpload
|
|
59
|
+
};
|
|
@@ -263,6 +263,59 @@ 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
|
+
const objectURL = URL.createObjectURL(file);
|
|
273
|
+
try {
|
|
274
|
+
const image = await new Promise((resolve, reject) => {
|
|
275
|
+
const nextImage = new Image();
|
|
276
|
+
nextImage.onload = () => resolve(nextImage);
|
|
277
|
+
nextImage.onerror = () => reject(new Error("Could not read image for upload optimization."));
|
|
278
|
+
nextImage.src = objectURL;
|
|
279
|
+
});
|
|
280
|
+
const canvas = document.createElement("canvas");
|
|
281
|
+
canvas.width = Math.max(1, image.width);
|
|
282
|
+
canvas.height = Math.max(1, image.height);
|
|
283
|
+
const context = canvas.getContext("2d");
|
|
284
|
+
if (!context) {
|
|
285
|
+
return file;
|
|
286
|
+
}
|
|
287
|
+
context.drawImage(image, 0, 0, canvas.width, canvas.height);
|
|
288
|
+
const outputMime = file.type === "image/webp" ? "image/webp" : "image/jpeg";
|
|
289
|
+
const qualityPasses = [0.82, 0.74, 0.66, 0.58, 0.5, 0.42, 0.36, 0.3, 0.26];
|
|
290
|
+
let bestFile = null;
|
|
291
|
+
for (const quality of qualityPasses) {
|
|
292
|
+
const blob = await new Promise((resolve) => {
|
|
293
|
+
canvas.toBlob((value) => resolve(value), outputMime, quality);
|
|
294
|
+
});
|
|
295
|
+
if (!blob) {
|
|
296
|
+
continue;
|
|
297
|
+
}
|
|
298
|
+
const optimizedName = file.name.replace(/\.[^/.]+$/, outputMime === "image/webp" ? ".webp" : ".jpg");
|
|
299
|
+
const optimized = new File([blob], optimizedName, {
|
|
300
|
+
lastModified: Date.now(),
|
|
301
|
+
type: outputMime
|
|
302
|
+
});
|
|
303
|
+
if (!bestFile || optimized.size < bestFile.size) {
|
|
304
|
+
bestFile = optimized;
|
|
305
|
+
}
|
|
306
|
+
if (optimized.size <= MAX_DIRECT_UPLOAD_BYTES) {
|
|
307
|
+
break;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
if (!bestFile) {
|
|
311
|
+
return file;
|
|
312
|
+
}
|
|
313
|
+
return bestFile.size < file.size ? bestFile : file;
|
|
314
|
+
} finally {
|
|
315
|
+
URL.revokeObjectURL(objectURL);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
266
319
|
// src/studio-pages/builder/presets.ts
|
|
267
320
|
var sectionPresets = [
|
|
268
321
|
{
|
|
@@ -1030,7 +1083,6 @@ async function parsePayloadErrorMessage(response, fallbackMessage) {
|
|
|
1030
1083
|
}
|
|
1031
1084
|
return fallbackMessage;
|
|
1032
1085
|
}
|
|
1033
|
-
var MAX_DIRECT_UPLOAD_BYTES = 4e6;
|
|
1034
1086
|
var MEDIA_LIBRARY_SYNC_EVENT = "orion-media-library-updated";
|
|
1035
1087
|
var notifyMediaLibraryUpdated = () => {
|
|
1036
1088
|
if (typeof window === "undefined") {
|
|
@@ -1049,59 +1101,6 @@ var notifyMediaLibraryUpdated = () => {
|
|
|
1049
1101
|
} catch {
|
|
1050
1102
|
}
|
|
1051
1103
|
};
|
|
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
1104
|
function InlineText({
|
|
1106
1105
|
as = "p",
|
|
1107
1106
|
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-I3HYCS77.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,
|