@orion-studios/payload-studio 0.5.0-beta.8 → 0.5.0-beta.80

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.
Files changed (67) hide show
  1. package/README.md +20 -0
  2. package/dist/admin/client.d.mts +2 -0
  3. package/dist/admin/client.d.ts +2 -0
  4. package/dist/admin/client.js +779 -137
  5. package/dist/admin/client.mjs +769 -129
  6. package/dist/admin/index.d.mts +1 -1
  7. package/dist/admin/index.d.ts +1 -1
  8. package/dist/admin/index.js +100 -8
  9. package/dist/admin/index.mjs +3 -1
  10. package/dist/admin-app/client.d.mts +7 -0
  11. package/dist/admin-app/client.d.ts +7 -0
  12. package/dist/admin-app/client.js +1262 -3
  13. package/dist/admin-app/client.mjs +1164 -2
  14. package/dist/admin-app/index.d.mts +1 -1
  15. package/dist/admin-app/index.d.ts +1 -1
  16. package/dist/admin-app/index.js +167 -0
  17. package/dist/admin-app/index.mjs +13 -1
  18. package/dist/admin-app/styles.css +229 -0
  19. package/dist/blocks/index.js +633 -8
  20. package/dist/blocks/index.mjs +2 -2
  21. package/dist/chunk-ADIIWIYL.mjs +322 -0
  22. package/dist/{chunk-ZLLNO5FM.mjs → chunk-AFLEATYB.mjs} +44 -13
  23. package/dist/chunk-FWVVRZ32.mjs +1143 -0
  24. package/dist/{chunk-J7W5EE3B.mjs → chunk-HCEPGEAI.mjs} +100 -8
  25. package/dist/chunk-ROTPP5CU.mjs +99 -0
  26. package/dist/{chunk-ETRRXURT.mjs → chunk-SIL2J5MF.mjs} +14 -0
  27. package/dist/{chunk-PC5622T7.mjs → chunk-XK3K5GRP.mjs} +620 -9
  28. package/dist/chunk-XVH5SCBD.mjs +234 -0
  29. package/dist/index-BBp-3l6M.d.ts +134 -0
  30. package/dist/{index-CmR6NInu.d.ts → index-BIwu3qIH.d.mts} +29 -3
  31. package/dist/{index-CmR6NInu.d.mts → index-BIwu3qIH.d.ts} +29 -3
  32. package/dist/{index-DbH0Ljwp.d.ts → index-CpG3UHcS.d.mts} +1 -0
  33. package/dist/{index-DbH0Ljwp.d.mts → index-CpG3UHcS.d.ts} +1 -0
  34. package/dist/index-DT_Vorvh.d.mts +134 -0
  35. package/dist/index-ZbOx4OCF.d.mts +128 -0
  36. package/dist/index-ZbOx4OCF.d.ts +128 -0
  37. package/dist/{index-DJFhANvJ.d.mts → index-cDYkEj29.d.mts} +20 -2
  38. package/dist/{index-DJFhANvJ.d.ts → index-cDYkEj29.d.ts} +20 -2
  39. package/dist/index.d.mts +5 -5
  40. package/dist/index.d.ts +5 -5
  41. package/dist/index.js +2232 -324
  42. package/dist/index.mjs +7 -7
  43. package/dist/nextjs/index.d.mts +1 -1
  44. package/dist/nextjs/index.d.ts +1 -1
  45. package/dist/nextjs/index.js +1002 -13
  46. package/dist/nextjs/index.mjs +4 -1
  47. package/dist/studio/index.d.mts +2 -1
  48. package/dist/studio/index.d.ts +2 -1
  49. package/dist/studio/index.js +171 -5
  50. package/dist/studio/index.mjs +7 -3
  51. package/dist/studio-pages/builder.css +472 -8
  52. package/dist/studio-pages/client.d.mts +17 -0
  53. package/dist/studio-pages/client.d.ts +17 -0
  54. package/dist/studio-pages/client.js +5057 -2546
  55. package/dist/studio-pages/client.mjs +4972 -2552
  56. package/dist/studio-pages/index.d.mts +3 -2
  57. package/dist/studio-pages/index.d.ts +3 -2
  58. package/dist/studio-pages/index.js +873 -32
  59. package/dist/studio-pages/index.mjs +6 -2
  60. package/package.json +26 -12
  61. package/dist/chunk-AAOHJDNS.mjs +0 -67
  62. package/dist/chunk-N67KVM2S.mjs +0 -156
  63. package/dist/chunk-TVDMZNKU.mjs +0 -301
  64. package/dist/index-B9N5MyjF.d.mts +0 -39
  65. package/dist/index-BallJs-K.d.mts +0 -43
  66. package/dist/index-BallJs-K.d.ts +0 -43
  67. package/dist/index-g8tBHLKD.d.ts +0 -39
@@ -7,6 +7,7 @@ import {
7
7
  var admin_exports = {};
8
8
  __export(admin_exports, {
9
9
  configureAdmin: () => configureAdmin,
10
+ createHeaderNavItemsField: () => createHeaderNavItemsField,
10
11
  createThemePreferenceField: () => createThemePreferenceField,
11
12
  themePreferenceField: () => themePreferenceField,
12
13
  withTooltips: () => withTooltips
@@ -61,14 +62,25 @@ function configureAdmin(config) {
61
62
  defaultTheme = "brand-light",
62
63
  logoUrl
63
64
  } = config;
64
- const studioEnabled = Boolean(config.studio?.enabled);
65
+ const studioEnabled = config.studio?.enabled ?? true;
65
66
  const pagesCollectionSlug = config.studio?.pages?.collectionSlug || "pages";
66
67
  const mediaCollectionSlug = config.studio?.media?.collectionSlug || "media";
67
- const globals = config.studio?.globals || [
68
+ const contactFormStudioPath = "/studio-contact-form";
69
+ const configuredGlobals = config.studio?.globals || [
68
70
  { slug: "site-settings", label: "Website Settings" },
69
71
  { slug: "header", label: "Header & Navigation" },
70
- { slug: "footer", label: "Footer" }
72
+ { slug: "footer", label: "Footer" },
73
+ { slug: "contact-form", label: "Contact Form" }
71
74
  ];
75
+ const globals = configuredGlobals.map((global) => {
76
+ if (global.slug !== "contact-form" || global.href) {
77
+ return global;
78
+ }
79
+ return {
80
+ ...global,
81
+ href: contactFormStudioPath
82
+ };
83
+ });
72
84
  let cssPath;
73
85
  const pkgDist = getPkgDistDir();
74
86
  const sourceCssPath = path.resolve(pkgDist, "admin.css");
@@ -98,7 +110,8 @@ function configureAdmin(config) {
98
110
  clientProps: {
99
111
  brandName,
100
112
  logoUrl,
101
- globalsBasePath: "/admin/studio-globals",
113
+ globalsBasePath: "/studio-globals",
114
+ globalsExtraMatchPrefixes: [contactFormStudioPath],
102
115
  mediaCollectionSlug,
103
116
  pagesCollectionSlug
104
117
  }
@@ -130,7 +143,8 @@ function configureAdmin(config) {
130
143
  clientProps: {
131
144
  brandName,
132
145
  logoUrl,
133
- globalsBasePath: "/admin/studio-globals",
146
+ globalsBasePath: "/studio-globals",
147
+ globalsExtraMatchPrefixes: [contactFormStudioPath],
134
148
  mediaCollectionSlug,
135
149
  pagesCollectionSlug
136
150
  }
@@ -144,7 +158,18 @@ function configureAdmin(config) {
144
158
  path: clientPath,
145
159
  clientProps: {
146
160
  globals,
147
- globalsBasePath: "/admin/studio-globals"
161
+ globalsBasePath: "/studio-globals"
162
+ }
163
+ }
164
+ },
165
+ studioContactForm: {
166
+ path: "/studio-contact-form",
167
+ Component: {
168
+ exportName: "AdminStudioContactFormView",
169
+ path: clientPath,
170
+ clientProps: {
171
+ globalSlug: "contact-form",
172
+ globalsBasePath: "/studio-globals"
148
173
  }
149
174
  }
150
175
  }
@@ -191,16 +216,47 @@ function configureAdmin(config) {
191
216
  const labelMap = {
192
217
  header: { group: "Site Design", label: "Header & Navigation" },
193
218
  footer: { group: "Site Design", label: "Footer" },
194
- "site-settings": { group: "Site Design", label: "Website Settings" }
219
+ "site-settings": { group: "Site Design", label: "Website Settings" },
220
+ "contact-form": { group: "Lead Forms", label: "Contact Form" }
195
221
  };
196
222
  return globals2.map((global) => {
197
223
  const mapping = labelMap[global.slug];
198
224
  if (!mapping) return global;
225
+ const shouldAttachContactFormRedirect = studioEnabled && global.slug === "contact-form";
226
+ const existingViews = global.admin?.components?.views;
227
+ const existingEditViews = existingViews?.edit;
228
+ const hasCustomContactFormEditView = Boolean(
229
+ existingEditViews?.root || existingEditViews?.default && typeof existingEditViews.default === "object" && existingEditViews.default.Component
230
+ );
231
+ const contactFormEditViews = shouldAttachContactFormRedirect && !hasCustomContactFormEditView ? {
232
+ ...existingEditViews,
233
+ default: {
234
+ ...typeof existingEditViews?.default === "object" ? existingEditViews.default : {},
235
+ Component: {
236
+ exportName: "StudioContactFormRedirect",
237
+ path: clientPath,
238
+ clientProps: {
239
+ studioContactFormPath: contactFormStudioPath
240
+ }
241
+ }
242
+ }
243
+ } : existingEditViews;
199
244
  return {
200
245
  ...global,
201
246
  admin: {
202
247
  ...global.admin,
203
- group: mapping.group
248
+ group: mapping.group,
249
+ components: {
250
+ ...global.admin?.components,
251
+ ...shouldAttachContactFormRedirect ? {
252
+ views: {
253
+ ...existingViews,
254
+ ...contactFormEditViews ? {
255
+ edit: contactFormEditViews
256
+ } : {}
257
+ }
258
+ } : {}
259
+ }
204
260
  },
205
261
  label: mapping.label
206
262
  };
@@ -269,10 +325,46 @@ function addTooltipToField(field, tooltips) {
269
325
  return field;
270
326
  }
271
327
 
328
+ // src/admin/fields/headerNav.ts
329
+ var createHeaderNavItemsField = () => ({
330
+ name: "navItems",
331
+ type: "array",
332
+ labels: { singular: "Navigation Link", plural: "Navigation Links" },
333
+ admin: {
334
+ description: "The links displayed in your website's main navigation menu."
335
+ },
336
+ fields: [
337
+ {
338
+ name: "label",
339
+ type: "text",
340
+ required: true,
341
+ admin: {
342
+ description: "The text shown for this navigation link."
343
+ }
344
+ },
345
+ {
346
+ name: "href",
347
+ type: "text",
348
+ required: true,
349
+ admin: {
350
+ description: 'The URL this link points to (e.g., "/about" or "https://example.com").'
351
+ }
352
+ },
353
+ {
354
+ name: "parentHref",
355
+ type: "text",
356
+ admin: {
357
+ description: "Optional parent link URL. If set to another nav item href, this item appears in that dropdown."
358
+ }
359
+ }
360
+ ]
361
+ });
362
+
272
363
  export {
273
364
  createThemePreferenceField,
274
365
  themePreferenceField,
275
366
  configureAdmin,
276
367
  withTooltips,
368
+ createHeaderNavItemsField,
277
369
  admin_exports
278
370
  };
@@ -0,0 +1,99 @@
1
+ 'use client';
2
+
3
+ // src/shared/clientImageUploadOptimization.ts
4
+ var MAX_DIRECT_UPLOAD_BYTES = 4e6;
5
+ var extensionForMimeType = (mimeType) => {
6
+ switch (mimeType) {
7
+ case "image/webp":
8
+ return ".webp";
9
+ case "image/png":
10
+ return ".png";
11
+ default:
12
+ return ".jpg";
13
+ }
14
+ };
15
+ var detectCanvasTransparency = (context, width, height) => {
16
+ try {
17
+ const { data } = context.getImageData(0, 0, width, height);
18
+ for (let index = 3; index < data.length; index += 4) {
19
+ if (data[index] < 255) {
20
+ return true;
21
+ }
22
+ }
23
+ } catch {
24
+ }
25
+ return false;
26
+ };
27
+ var resolveOutputMimeTypes = (sourceMime, hasTransparency) => {
28
+ const candidates = [];
29
+ if (hasTransparency) {
30
+ candidates.push("image/webp", "image/png");
31
+ } else if (sourceMime === "image/webp") {
32
+ candidates.push("image/webp", "image/jpeg");
33
+ } else if (sourceMime === "image/png") {
34
+ candidates.push("image/webp", "image/jpeg", "image/png");
35
+ } else {
36
+ candidates.push("image/jpeg", "image/webp");
37
+ }
38
+ return [...new Set(candidates)];
39
+ };
40
+ async function optimizeImageForUpload(file) {
41
+ if (!file.type.startsWith("image/")) {
42
+ return file;
43
+ }
44
+ const objectURL = URL.createObjectURL(file);
45
+ try {
46
+ const image = await new Promise((resolve, reject) => {
47
+ const nextImage = new Image();
48
+ nextImage.onload = () => resolve(nextImage);
49
+ nextImage.onerror = () => reject(new Error("Could not read image for upload optimization."));
50
+ nextImage.src = objectURL;
51
+ });
52
+ const canvas = document.createElement("canvas");
53
+ canvas.width = Math.max(1, image.width);
54
+ canvas.height = Math.max(1, image.height);
55
+ const context = canvas.getContext("2d");
56
+ if (!context) {
57
+ return file;
58
+ }
59
+ context.drawImage(image, 0, 0, canvas.width, canvas.height);
60
+ const sourceMime = file.type.toLowerCase();
61
+ const hasTransparency = detectCanvasTransparency(context, canvas.width, canvas.height);
62
+ const outputMimes = resolveOutputMimeTypes(sourceMime, hasTransparency);
63
+ const qualityPasses = [0.82, 0.74, 0.66, 0.58, 0.5, 0.42, 0.36, 0.3, 0.26];
64
+ let bestFile = null;
65
+ for (const outputMime of outputMimes) {
66
+ const passes = outputMime === "image/png" ? [void 0] : qualityPasses;
67
+ for (const quality of passes) {
68
+ const blob = await new Promise((resolve) => {
69
+ canvas.toBlob((value) => resolve(value), outputMime, quality);
70
+ });
71
+ if (!blob) {
72
+ continue;
73
+ }
74
+ const optimizedName = file.name.replace(/\.[^/.]+$/, extensionForMimeType(outputMime));
75
+ const optimized = new File([blob], optimizedName, {
76
+ lastModified: Date.now(),
77
+ type: outputMime
78
+ });
79
+ if (!bestFile || optimized.size < bestFile.size) {
80
+ bestFile = optimized;
81
+ }
82
+ if (optimized.size <= MAX_DIRECT_UPLOAD_BYTES) {
83
+ break;
84
+ }
85
+ }
86
+ }
87
+ if (!bestFile) {
88
+ return file;
89
+ }
90
+ return bestFile.size < file.size ? bestFile : file;
91
+ } finally {
92
+ URL.revokeObjectURL(objectURL);
93
+ }
94
+ }
95
+
96
+ export {
97
+ MAX_DIRECT_UPLOAD_BYTES,
98
+ optimizeImageForUpload
99
+ };
@@ -7,6 +7,7 @@ var sectionStyleDefaults = {
7
7
  contentGradientPreset: "none",
8
8
  contentGradientTo: "#f4f6f2",
9
9
  contentWidth: "inherit",
10
+ sectionPaddingX: "inherit",
10
11
  sectionBackgroundColor: "#ffffff",
11
12
  sectionBackgroundMode: "none",
12
13
  sectionGradientAngle: "135",
@@ -44,6 +45,19 @@ var sectionStyleFields = () => [
44
45
  type: "select",
45
46
  defaultValue: sectionStyleDefaults.sectionPaddingY,
46
47
  options: [
48
+ { label: "None", value: "none" },
49
+ { label: "Small", value: "sm" },
50
+ { label: "Medium", value: "md" },
51
+ { label: "Large", value: "lg" }
52
+ ]
53
+ },
54
+ {
55
+ name: "sectionPaddingX",
56
+ type: "select",
57
+ defaultValue: sectionStyleDefaults.sectionPaddingX,
58
+ options: [
59
+ { label: "Inherit", value: "inherit" },
60
+ { label: "None", value: "none" },
47
61
  { label: "Small", value: "sm" },
48
62
  { label: "Medium", value: "md" },
49
63
  { label: "Large", value: "lg" }