@orion-studios/payload-studio 0.6.0-beta.4 → 0.6.0-beta.41

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 (46) hide show
  1. package/dist/admin/client.d.mts +1 -0
  2. package/dist/admin/client.d.ts +1 -0
  3. package/dist/admin/client.js +3924 -1355
  4. package/dist/admin/client.mjs +4090 -1533
  5. package/dist/admin/index.d.mts +2 -3
  6. package/dist/admin/index.d.ts +2 -3
  7. package/dist/admin/index.js +141 -1522
  8. package/dist/admin/index.mjs +2 -4
  9. package/dist/admin-app/client.js +11 -4
  10. package/dist/admin-app/client.mjs +1 -1
  11. package/dist/admin-app/index.d.mts +2 -2
  12. package/dist/admin-app/index.d.ts +2 -2
  13. package/dist/admin-app/index.mjs +4 -4
  14. package/dist/admin-app/styles.css +343 -41
  15. package/dist/admin.css +18 -2
  16. package/dist/{chunk-KPIX7OSV.mjs → chunk-2XH7X34N.mjs} +11 -4
  17. package/dist/{chunk-PF3EBZXF.mjs → chunk-7ZMXZRBP.mjs} +39 -3
  18. package/dist/chunk-JC3UV74N.mjs +1033 -0
  19. package/dist/{chunk-XKUTZ7IU.mjs → chunk-OL53KHTB.mjs} +46 -2
  20. package/dist/{chunk-EHUE4LCT.mjs → chunk-RKTIFEUY.mjs} +33 -3
  21. package/dist/chunk-W2UOCJDX.mjs +32 -0
  22. package/dist/{chunk-OTHERBGX.mjs → chunk-ZADL33R6.mjs} +1 -1
  23. package/dist/{index-bbA3HSxa.d.ts → index-BV0vEGl6.d.ts} +6 -9
  24. package/dist/{index-Cv-6qnrw.d.mts → index-D5zrOdyv.d.mts} +3 -1
  25. package/dist/{index-52HdVLQq.d.ts → index-DAdN56fM.d.ts} +1 -1
  26. package/dist/{index-DEkV-sMs.d.mts → index-DLfPOqYA.d.mts} +6 -9
  27. package/dist/{index-Crx_MtPw.d.ts → index-Dv-Alx4h.d.ts} +3 -1
  28. package/dist/{index-DEQC3Dwj.d.mts → index-G_uTNffQ.d.mts} +1 -1
  29. package/dist/index.d.mts +5 -5
  30. package/dist/index.d.ts +5 -5
  31. package/dist/index.js +287 -1542
  32. package/dist/index.mjs +6 -6
  33. package/dist/nextjs/index.js +39 -3
  34. package/dist/nextjs/index.mjs +2 -2
  35. package/dist/{sitePreviewTypes-BkHCWxNW.d.mts → sitePreviewTypes-BrJwGzJj.d.mts} +1 -1
  36. package/dist/{sitePreviewTypes-BkHCWxNW.d.ts → sitePreviewTypes-BrJwGzJj.d.ts} +1 -1
  37. package/dist/studio-pages/builder.css +24 -5
  38. package/dist/studio-pages/client.js +529 -63
  39. package/dist/studio-pages/client.mjs +529 -63
  40. package/dist/studio-pages/index.d.mts +1 -1
  41. package/dist/studio-pages/index.d.ts +1 -1
  42. package/dist/studio-pages/index.js +84 -4
  43. package/dist/studio-pages/index.mjs +2 -2
  44. package/package.json +1 -1
  45. package/dist/chunk-DYXSAVUQ.mjs +0 -2372
  46. package/dist/chunk-Z6L5K5MH.mjs +0 -64
@@ -97,7 +97,9 @@ var defaultBuilderBlockSettingsV2 = {
97
97
  },
98
98
  typography: {
99
99
  bodyAlign: "left",
100
+ bodySizePt: null,
100
101
  headingAlign: "left",
102
+ headingSizePt: null,
101
103
  letterSpacingPreset: "normal",
102
104
  lineHeightPreset: "normal",
103
105
  maxTextWidth: "auto"
@@ -126,7 +128,9 @@ var defaultBuilderItemSettingsV2 = {
126
128
  },
127
129
  typography: {
128
130
  bodyAlign: "left",
131
+ bodySizePt: null,
129
132
  headingAlign: "left",
133
+ headingSizePt: null,
130
134
  letterSpacingPreset: "normal",
131
135
  lineHeightPreset: "normal",
132
136
  maxTextWidth: "auto"
@@ -156,6 +160,7 @@ var defaultBuilderThemeTokens = {
156
160
 
157
161
  // src/studio-pages/builder/adapters/settingsV2.ts
158
162
  var isRecord = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
163
+ var isTextAlign = (value) => value === "left" || value === "center" || value === "right" || value === "justify";
159
164
  var parsePercent = (value) => {
160
165
  if (typeof value === "number" && Number.isFinite(value)) {
161
166
  return Math.max(0, Math.min(100, value));
@@ -180,6 +185,18 @@ var parsePixel = (value) => {
180
185
  }
181
186
  return null;
182
187
  };
188
+ var parsePoint = (value) => {
189
+ if (typeof value === "number" && Number.isFinite(value)) {
190
+ return Math.max(6, Math.min(120, Math.round(value)));
191
+ }
192
+ if (typeof value === "string" && value.trim().length > 0) {
193
+ const parsed = Number(value);
194
+ if (Number.isFinite(parsed)) {
195
+ return Math.max(6, Math.min(120, Math.round(parsed)));
196
+ }
197
+ }
198
+ return null;
199
+ };
183
200
  var mergeSettings = (defaults, input) => {
184
201
  if (!isRecord(input)) {
185
202
  return structuredClone(defaults);
@@ -198,6 +215,10 @@ var mergeSettings = (defaults, input) => {
198
215
  };
199
216
  var legacyBlockToV2Settings = (block) => {
200
217
  const current = structuredClone(defaultBuilderBlockSettingsV2);
218
+ if (block.blockType === "hero" && block.variant === "centered") {
219
+ current.typography.headingAlign = "center";
220
+ current.typography.bodyAlign = "center";
221
+ }
201
222
  current.layout.contentWidth = block.contentWidth === "narrow" || block.contentWidth === "content" || block.contentWidth === "wide" || block.contentWidth === "full" || block.contentWidth === "inherit" ? block.contentWidth : current.layout.contentWidth;
202
223
  current.layout.sectionPaddingX = block.sectionPaddingX === "none" || block.sectionPaddingX === "sm" || block.sectionPaddingX === "md" || block.sectionPaddingX === "lg" || block.sectionPaddingX === "inherit" ? block.sectionPaddingX : current.layout.sectionPaddingX;
203
224
  current.layout.sectionPaddingY = block.sectionPaddingY === "none" || block.sectionPaddingY === "sm" || block.sectionPaddingY === "lg" ? block.sectionPaddingY : current.layout.sectionPaddingY;
@@ -234,15 +255,28 @@ var legacyBlockToV2Settings = (block) => {
234
255
  current.media.positionX = parsePercent(block.imagePositionX ?? block.backgroundImagePositionX);
235
256
  current.media.positionY = parsePercent(block.imagePositionY ?? block.backgroundImagePositionY);
236
257
  current.media.height = parsePixel(block.imageHeight);
237
- current.typography.headingAlign = block.textHeadingAlign === "left" || block.textHeadingAlign === "center" || block.textHeadingAlign === "right" || block.textHeadingAlign === "justify" ? block.textHeadingAlign : current.typography.headingAlign;
238
- current.typography.bodyAlign = block.textBodyAlign === "left" || block.textBodyAlign === "center" || block.textBodyAlign === "right" || block.textBodyAlign === "justify" ? block.textBodyAlign : current.typography.bodyAlign;
258
+ current.typography.headingAlign = isTextAlign(block.textHeadingAlign) ? block.textHeadingAlign : current.typography.headingAlign;
259
+ current.typography.bodyAlign = isTextAlign(block.textBodyAlign) ? block.textBodyAlign : current.typography.bodyAlign;
260
+ current.typography.headingSizePt = parsePoint(block.textHeadingSizePt);
261
+ current.typography.bodySizePt = parsePoint(block.textBodySizePt);
239
262
  current.typography.maxTextWidth = block.textMaxWidth === "auto" || block.textMaxWidth === "sm" || block.textMaxWidth === "md" || block.textMaxWidth === "lg" || block.textMaxWidth === "full" ? block.textMaxWidth : current.typography.maxTextWidth;
240
263
  current.typography.lineHeightPreset = block.textLineHeightPreset === "tight" || block.textLineHeightPreset === "normal" || block.textLineHeightPreset === "relaxed" ? block.textLineHeightPreset : current.typography.lineHeightPreset;
241
264
  current.typography.letterSpacingPreset = block.textLetterSpacingPreset === "tight" || block.textLetterSpacingPreset === "normal" || block.textLetterSpacingPreset === "relaxed" ? block.textLetterSpacingPreset : current.typography.letterSpacingPreset;
242
265
  current.advanced.editCopyInPanel = Boolean(block.editCopyInPanel ?? current.advanced.editCopyInPanel);
243
266
  current.advanced.customClassName = typeof block.customClassName === "string" ? block.customClassName : current.advanced.customClassName;
244
267
  current.advanced.hideOnMobile = Boolean(block.hideOnMobile ?? current.advanced.hideOnMobile);
245
- return mergeSettings(current, block.settings);
268
+ const settings = mergeSettings(current, block.settings);
269
+ if (block.blockType === "hero") {
270
+ const top = settings.layout.paddingTopPt;
271
+ const bottom = settings.layout.paddingBottomPt;
272
+ const hasLegacyLinkedHeroPadding = settings.layout.linkVerticalPadding !== false && (top === null || typeof top === "undefined" || top === 30) && (bottom === null || typeof bottom === "undefined" || bottom === 30 || bottom === 20);
273
+ if (hasLegacyLinkedHeroPadding) {
274
+ settings.layout.linkVerticalPadding = false;
275
+ settings.layout.paddingTopPt = 30;
276
+ settings.layout.paddingBottomPt = 20;
277
+ }
278
+ }
279
+ return settings;
246
280
  };
247
281
  var v2SettingsToLegacyBlock = (blockWithSettings) => {
248
282
  const settings = legacyBlockToV2Settings(blockWithSettings);
@@ -268,6 +302,8 @@ var v2SettingsToLegacyBlock = (blockWithSettings) => {
268
302
  next.contentGradientAngle = settings.appearance.contentGradientAngle;
269
303
  next.textHeadingAlign = settings.typography.headingAlign;
270
304
  next.textBodyAlign = settings.typography.bodyAlign;
305
+ next.textHeadingSizePt = settings.typography.headingSizePt;
306
+ next.textBodySizePt = settings.typography.bodySizePt;
271
307
  next.textMaxWidth = settings.typography.maxTextWidth;
272
308
  next.textLineHeightPreset = settings.typography.lineHeightPreset;
273
309
  next.textLetterSpacingPreset = settings.typography.letterSpacingPreset;
@@ -362,6 +398,7 @@ var resolveTypographyStyleFromSettings = (settings) => {
362
398
  const letterSpacing = settings.letterSpacingPreset === "tight" ? "-0.01em" : settings.letterSpacingPreset === "relaxed" ? "0.02em" : "0.01em";
363
399
  const maxWidth = settings.maxTextWidth === "sm" ? "36ch" : settings.maxTextWidth === "md" ? "52ch" : settings.maxTextWidth === "lg" ? "72ch" : settings.maxTextWidth === "full" ? "100%" : void 0;
364
400
  return {
401
+ ...typeof settings.bodySizePt === "number" && Number.isFinite(settings.bodySizePt) ? { fontSize: `${settings.bodySizePt}pt` } : {},
365
402
  letterSpacing,
366
403
  lineHeight,
367
404
  maxWidth,
@@ -531,8 +568,52 @@ var alignOptions = [
531
568
  { label: "Right", value: "right" },
532
569
  { label: "Justify", value: "justify" }
533
570
  ];
534
- var layoutFieldSet = [];
571
+ var layoutFieldSet = [
572
+ {
573
+ group: "layout",
574
+ key: "settings.layout.linkVerticalPadding",
575
+ label: "Link Top/Bottom Padding",
576
+ tags: ["spacing", "padding", "vertical"],
577
+ type: "checkbox"
578
+ },
579
+ {
580
+ group: "layout",
581
+ key: "settings.layout.paddingTopPt",
582
+ label: "Top Padding (pt)",
583
+ max: 240,
584
+ min: 0,
585
+ tags: ["spacing", "padding", "top"],
586
+ type: "number"
587
+ },
588
+ {
589
+ group: "layout",
590
+ key: "settings.layout.paddingBottomPt",
591
+ label: "Bottom Padding (pt)",
592
+ max: 240,
593
+ min: 0,
594
+ tags: ["spacing", "padding", "bottom"],
595
+ type: "number"
596
+ }
597
+ ];
535
598
  var typographyFieldSet = [
599
+ {
600
+ group: "typography",
601
+ key: "settings.typography.headingSizePt",
602
+ label: "Heading Text Size (pt)",
603
+ max: 120,
604
+ min: 6,
605
+ tags: ["text", "size", "heading", "font"],
606
+ type: "number"
607
+ },
608
+ {
609
+ group: "typography",
610
+ key: "settings.typography.bodySizePt",
611
+ label: "Body Text Size (pt)",
612
+ max: 72,
613
+ min: 6,
614
+ tags: ["text", "size", "body", "paragraph", "font"],
615
+ type: "number"
616
+ },
536
617
  {
537
618
  group: "typography",
538
619
  key: "settings.typography.headingAlign",
@@ -639,6 +720,7 @@ var mediaFieldSet = [
639
720
  ];
640
721
  var commonInspectorGroups = [
641
722
  { key: "basics", label: "Basics" },
723
+ { key: "layout", label: "Layout" },
642
724
  { key: "typography", label: "Typography" },
643
725
  { key: "media", label: "Media" },
644
726
  { key: "advanced", label: "Advanced" }
@@ -924,6 +1006,69 @@ var normalizeNumber = (value, fallback) => {
924
1006
  }
925
1007
  return fallback;
926
1008
  };
1009
+ var sectionPaddingPointMap = {
1010
+ none: 0,
1011
+ sm: 17,
1012
+ md: 31,
1013
+ lg: 41
1014
+ };
1015
+ var heroDefaultPaddingTopPt = 30;
1016
+ var heroDefaultPaddingBottomPt = 20;
1017
+ var defaultTextSizePointMap = {
1018
+ cta: { body: 14, heading: 36 },
1019
+ faq: { body: 12, heading: 18 },
1020
+ featureGrid: { body: 12, heading: 36 },
1021
+ formEmbed: { body: 12, heading: 36 },
1022
+ hero: { body: 14, heading: 48 },
1023
+ media: { body: 12, heading: 36 },
1024
+ richText: { body: 12, heading: 39 },
1025
+ stats: { body: 11, heading: 30 },
1026
+ testimonials: { body: 12, heading: 36 }
1027
+ };
1028
+ var normalizeSectionPaddingY = (value) => value === "none" || value === "sm" || value === "lg" ? value : "md";
1029
+ var normalizePaddingPointValue = (value) => {
1030
+ if (typeof value === "number" && Number.isFinite(value)) {
1031
+ return Math.max(0, Math.min(240, Math.round(value)));
1032
+ }
1033
+ if (typeof value === "string" && value.trim().length > 0) {
1034
+ const parsed = Number(value);
1035
+ if (Number.isFinite(parsed)) {
1036
+ return Math.max(0, Math.min(240, Math.round(parsed)));
1037
+ }
1038
+ }
1039
+ return null;
1040
+ };
1041
+ var normalizeTextSizePointValue = (value) => {
1042
+ if (typeof value === "number" && Number.isFinite(value)) {
1043
+ return Math.max(6, Math.min(120, Math.round(value)));
1044
+ }
1045
+ if (typeof value === "string" && value.trim().length > 0) {
1046
+ const parsed = Number(value);
1047
+ if (Number.isFinite(parsed)) {
1048
+ return Math.max(6, Math.min(120, Math.round(parsed)));
1049
+ }
1050
+ }
1051
+ return null;
1052
+ };
1053
+ var getEffectiveVerticalPaddingValue = (block, key) => {
1054
+ const explicit = normalizePaddingPointValue(getByPath(block, key));
1055
+ if (explicit !== null) {
1056
+ return explicit;
1057
+ }
1058
+ const layoutSectionPaddingY = getByPath(block, "settings.layout.sectionPaddingY");
1059
+ const legacySectionPaddingY = block.sectionPaddingY;
1060
+ const inherited = block.blockType === "hero" ? key === "settings.layout.paddingBottomPt" ? heroDefaultPaddingBottomPt : heroDefaultPaddingTopPt : sectionPaddingPointMap[normalizeSectionPaddingY(layoutSectionPaddingY || legacySectionPaddingY)];
1061
+ return inherited;
1062
+ };
1063
+ var getEffectiveTextSizeValue = (block, key) => {
1064
+ const explicit = normalizeTextSizePointValue(getByPath(block, key));
1065
+ if (explicit !== null) {
1066
+ return explicit;
1067
+ }
1068
+ const blockType = typeof block.blockType === "string" ? block.blockType : "";
1069
+ const defaults = defaultTextSizePointMap[blockType] || { body: 12, heading: 36 };
1070
+ return key === "settings.typography.headingSizePt" ? defaults.heading : defaults.body;
1071
+ };
927
1072
  var getRelationID = (value) => {
928
1073
  if (typeof value === "number" || typeof value === "string") {
929
1074
  return value;
@@ -952,6 +1097,12 @@ var toMediaLibraryItem = (value) => {
952
1097
  };
953
1098
  };
954
1099
  var mediaLabel = (item) => item.filename || item.alt || `Media #${item.id}`;
1100
+ var findMediaLibraryItem = (library, id) => {
1101
+ if (id === null) {
1102
+ return null;
1103
+ }
1104
+ return library.find((item) => String(item.id) === String(id)) || null;
1105
+ };
955
1106
  var groupLabel = (key) => commonInspectorGroups.find((group) => group.key === key)?.label || key;
956
1107
  function BlockInspectorRenderer({
957
1108
  block,
@@ -1075,8 +1226,9 @@ function BlockInspectorRenderer({
1075
1226
  title: group.label,
1076
1227
  children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "orion-builder-settings-field-list", children: [
1077
1228
  group.key === "media" ? effectiveMediaSources.map((source) => {
1078
- const selectedSourceMedia = toMediaLibraryItem(source.value);
1079
1229
  const selectedSourceMediaID = getRelationID(source.value);
1230
+ const selectedRelationMedia = toMediaLibraryItem(source.value);
1231
+ const selectedSourceMedia = selectedRelationMedia ?? findMediaLibraryItem(source.library, selectedSourceMediaID);
1080
1232
  const sourceOptions = selectedSourceMedia && !source.library.some((item) => String(item.id) === String(selectedSourceMedia.id)) ? [selectedSourceMedia, ...source.library] : source.library;
1081
1233
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1082
1234
  "div",
@@ -1101,6 +1253,10 @@ function BlockInspectorRenderer({
1101
1253
  }
1102
1254
  )
1103
1255
  ] }),
1256
+ selectedSourceMedia?.alt ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "orion-builder-settings-label", children: [
1257
+ "Media Description",
1258
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { className: "orion-builder-settings-input", readOnly: true, type: "text", value: selectedSourceMedia.alt })
1259
+ ] }) : selectedSourceMediaID !== null ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "orion-builder-settings-note", children: "This media item does not have a description yet." }) : null,
1104
1260
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1105
1261
  "button",
1106
1262
  {
@@ -1157,19 +1313,20 @@ function BlockInspectorRenderer({
1157
1313
  }
1158
1314
  ) : null,
1159
1315
  (hasMediaGroupContent ? group.fields.filter((field) => !(group.key === "media" && field.key.startsWith("settings.media."))) : group.fields).map((field) => {
1160
- if (field.key === "settings.layout.paddingBottomPt" && Boolean(getByPath(block, "settings.layout.linkVerticalPadding"))) {
1316
+ if (field.key === "settings.layout.paddingBottomPt" && getByPath(block, "settings.layout.linkVerticalPadding") !== false && block.blockType !== "hero") {
1161
1317
  return null;
1162
1318
  }
1163
- if (field.key === "settings.layout.paddingRightPt" && Boolean(getByPath(block, "settings.layout.linkHorizontalPadding"))) {
1319
+ if (field.key === "settings.layout.paddingRightPt" && getByPath(block, "settings.layout.linkHorizontalPadding") !== false) {
1164
1320
  return null;
1165
1321
  }
1166
1322
  const fieldValue = getByPath(block, field.key);
1167
1323
  if (field.type === "checkbox") {
1324
+ const checked = field.key === "settings.layout.linkVerticalPadding" || field.key === "settings.layout.linkHorizontalPadding" ? typeof fieldValue === "boolean" ? fieldValue : block.blockType === "hero" ? false : true : Boolean(fieldValue);
1168
1325
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "orion-builder-settings-label is-checkbox", children: [
1169
1326
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1170
1327
  "input",
1171
1328
  {
1172
- checked: Boolean(fieldValue),
1329
+ checked,
1173
1330
  onChange: (event) => updateForKey(field.key, event.target.checked),
1174
1331
  type: "checkbox"
1175
1332
  }
@@ -1192,8 +1349,10 @@ function BlockInspectorRenderer({
1192
1349
  ] }, field.key);
1193
1350
  }
1194
1351
  if (field.type === "number") {
1195
- const numberValue = typeof fieldValue === "number" ? fieldValue : typeof fieldValue === "string" && fieldValue.trim().length > 0 ? Number(fieldValue) : null;
1196
- const resolvedValue = typeof numberValue === "number" && Number.isFinite(numberValue) ? numberValue : "";
1352
+ const isPaddingPointField = field.key === "settings.layout.paddingTopPt" || field.key === "settings.layout.paddingBottomPt";
1353
+ const isTextSizePointField = field.key === "settings.typography.headingSizePt" || field.key === "settings.typography.bodySizePt";
1354
+ const numberValue = isTextSizePointField ? normalizeTextSizePointValue(fieldValue) : normalizePaddingPointValue(fieldValue);
1355
+ const resolvedValue = numberValue !== null ? numberValue : isPaddingPointField ? getEffectiveVerticalPaddingValue(block, field.key) : isTextSizePointField ? getEffectiveTextSizeValue(block, field.key) : "";
1197
1356
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "orion-builder-settings-label", children: [
1198
1357
  field.label,
1199
1358
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
@@ -2249,8 +2408,8 @@ function renderSimpleBlockPreview(args) {
2249
2408
  getImagePresentationStyle: getImagePresentationStyle2,
2250
2409
  index,
2251
2410
  isBlockUploadTarget,
2252
- normalizeImageCornerStyle: normalizeImageCornerStyle2,
2253
- normalizeImageFit: normalizeImageFit2,
2411
+ normalizeImageCornerStyle: normalizeImageCornerStyle3,
2412
+ normalizeImageFit: normalizeImageFit3,
2254
2413
  normalizeText: normalizeText3,
2255
2414
  onDropAt,
2256
2415
  renderWithSectionShell,
@@ -2434,8 +2593,8 @@ function renderSimpleBlockPreview(args) {
2434
2593
  const imagePositionX = parseOptionalPercentNumber(mediaSettings.positionX ?? block?.imagePositionX);
2435
2594
  const imagePositionY = parseOptionalPercentNumber(mediaSettings.positionY ?? block?.imagePositionY);
2436
2595
  const imageStyle = getImagePresentationStyle2({
2437
- cornerStyle: normalizeImageCornerStyle2(mediaSettings.cornerStyle ?? block?.imageCornerStyle),
2438
- fit: normalizeImageFit2(mediaSettings.fit ?? block?.imageFit),
2596
+ cornerStyle: normalizeImageCornerStyle3(mediaSettings.cornerStyle ?? block?.imageCornerStyle),
2597
+ fit: normalizeImageFit3(mediaSettings.fit ?? block?.imageFit),
2439
2598
  positionX: imagePositionX,
2440
2599
  positionY: imagePositionY
2441
2600
  });
@@ -2965,6 +3124,63 @@ var normalizeNumber2 = (value, fallback) => {
2965
3124
  return fallback;
2966
3125
  };
2967
3126
  var clamp = (value, min, max) => Math.max(min, Math.min(max, value));
3127
+ var getRelationID2 = (value) => {
3128
+ if (typeof value === "number" || typeof value === "string") {
3129
+ return value;
3130
+ }
3131
+ if (!isRecord5(value)) {
3132
+ return null;
3133
+ }
3134
+ const id = value.id;
3135
+ return typeof id === "number" || typeof id === "string" ? id : null;
3136
+ };
3137
+ var toMediaLibraryItem2 = (value) => {
3138
+ if (!isRecord5(value)) {
3139
+ return null;
3140
+ }
3141
+ const id = getRelationID2(value);
3142
+ if (id === null) {
3143
+ return null;
3144
+ }
3145
+ const filename = typeof value.filename === "string" ? value.filename : "";
3146
+ const url = typeof value.url === "string" && value.url.length > 0 ? value.url : filename ? `/api/media/file/${encodeURIComponent(filename)}` : "";
3147
+ return {
3148
+ alt: typeof value.alt === "string" ? value.alt : "",
3149
+ filename,
3150
+ id,
3151
+ url
3152
+ };
3153
+ };
3154
+ var mediaLabel2 = (item) => item.filename || item.alt || `Media #${item.id}`;
3155
+ var findMediaLibraryItem2 = (library, id) => {
3156
+ if (id === null) {
3157
+ return null;
3158
+ }
3159
+ return library.find((item) => String(item.id) === String(id)) || null;
3160
+ };
3161
+ var normalizeImageFit = (value) => value === "contain" ? "contain" : "cover";
3162
+ var normalizeImageCornerStyle = (value) => value === "square" ? "square" : "rounded";
3163
+ var getItemMediaSettings = (item) => {
3164
+ const settings = isRecord5(item.settings) ? item.settings : {};
3165
+ const media = isRecord5(settings.media) ? settings.media : {};
3166
+ return {
3167
+ cornerStyle: normalizeImageCornerStyle(media.cornerStyle ?? item.imageCornerStyle),
3168
+ fit: normalizeImageFit(media.fit ?? item.imageFit),
3169
+ height: (() => {
3170
+ const value = media.height ?? item.imageHeight;
3171
+ if (typeof value === "number" && Number.isFinite(value)) {
3172
+ return value;
3173
+ }
3174
+ if (typeof value === "string" && value.trim().length > 0) {
3175
+ const parsed = Number(value);
3176
+ return Number.isFinite(parsed) ? parsed : null;
3177
+ }
3178
+ return null;
3179
+ })(),
3180
+ positionX: clamp(normalizeNumber2(media.positionX ?? item.imagePositionX, 50), 0, 100),
3181
+ positionY: clamp(normalizeNumber2(media.positionY ?? item.imagePositionY, 50), 0, 100)
3182
+ };
3183
+ };
2968
3184
  var hasQueryMatch = (query, ...values) => {
2969
3185
  const normalized = query.trim().toLowerCase();
2970
3186
  if (!normalized) {
@@ -3011,18 +3227,157 @@ var bulletsToTextareaValue = (value) => {
3011
3227
  return value.map((item) => isRecord5(item) && typeof item.label === "string" ? item.label.trim() : "").filter(Boolean).join("\n");
3012
3228
  };
3013
3229
  var textareaValueToBullets = (value) => value.split("\n").map((line) => line.trim()).filter(Boolean).map((label) => ({ label }));
3230
+ function ItemMediaControl({
3231
+ fieldName,
3232
+ imageURLFieldName,
3233
+ item,
3234
+ itemIndex,
3235
+ label,
3236
+ mediaLibrary,
3237
+ mediaLibraryError,
3238
+ mediaLibraryLoading,
3239
+ maxHeight,
3240
+ minHeight,
3241
+ onRemoveItemMedia,
3242
+ onSelectItemMedia,
3243
+ onUpdateItemField,
3244
+ onUpdateItemMediaPresentation,
3245
+ onUploadItemMedia,
3246
+ searchQuery,
3247
+ uploadDisabled,
3248
+ uploadLabel,
3249
+ uploading
3250
+ }) {
3251
+ const selectedMediaID = getRelationID2(item[fieldName]);
3252
+ const selectedRelationMedia = toMediaLibraryItem2(item[fieldName]);
3253
+ const selectedMedia = selectedRelationMedia ?? findMediaLibraryItem2(mediaLibrary, selectedMediaID);
3254
+ const directImageURL = normalizeText(item[imageURLFieldName]);
3255
+ const previewURL = selectedMedia?.url || directImageURL;
3256
+ const mediaSettings = getItemMediaSettings(item);
3257
+ const sourceOptions = selectedMedia && !mediaLibrary.some((libraryItem) => String(libraryItem.id) === String(selectedMedia.id)) ? [selectedMedia, ...mediaLibrary] : mediaLibrary;
3258
+ if (!hasQueryMatch(searchQuery, label, "image", "media", "photo", "picture", "url", "fit", "crop", "height")) {
3259
+ return null;
3260
+ }
3261
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "orion-builder-settings-item-card", style: { padding: "0.56rem" }, children: [
3262
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "orion-builder-settings-label", children: label }),
3263
+ previewURL ? (
3264
+ // eslint-disable-next-line @next/next/no-img-element
3265
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3266
+ "img",
3267
+ {
3268
+ alt: selectedMedia?.alt || label,
3269
+ src: previewURL,
3270
+ style: {
3271
+ aspectRatio: "16 / 9",
3272
+ border: "1px solid rgba(35, 51, 82, 0.14)",
3273
+ borderRadius: mediaSettings.cornerStyle === "square" ? 4 : 10,
3274
+ display: "block",
3275
+ objectFit: mediaSettings.fit,
3276
+ objectPosition: `${mediaSettings.positionX}% ${mediaSettings.positionY}%`,
3277
+ width: "100%"
3278
+ }
3279
+ }
3280
+ )
3281
+ ) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "orion-builder-settings-empty", children: "No image selected." }),
3282
+ mediaLibraryLoading ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "orion-builder-settings-note", children: "Loading media library..." }) : null,
3283
+ mediaLibraryError ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "orion-builder-settings-error", children: mediaLibraryError }) : null,
3284
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("label", { className: "orion-builder-settings-label", children: [
3285
+ "Media Library Image",
3286
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
3287
+ "select",
3288
+ {
3289
+ className: "orion-builder-settings-input",
3290
+ onChange: (event) => onSelectItemMedia?.(itemIndex, fieldName, event.target.value),
3291
+ value: selectedMediaID !== null ? String(selectedMediaID) : "",
3292
+ children: [
3293
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("option", { value: "", children: "No library image" }),
3294
+ sourceOptions.map((libraryItem) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("option", { value: String(libraryItem.id), children: mediaLabel2(libraryItem) }, String(libraryItem.id)))
3295
+ ]
3296
+ }
3297
+ )
3298
+ ] }),
3299
+ selectedMedia?.alt ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("label", { className: "orion-builder-settings-label", children: [
3300
+ "Media Description",
3301
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("input", { className: "orion-builder-settings-input", readOnly: true, type: "text", value: selectedMedia.alt })
3302
+ ] }) : selectedMediaID !== null ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "orion-builder-settings-note", children: "This media item does not have a description yet." }) : null,
3303
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3304
+ "button",
3305
+ {
3306
+ className: "orion-builder-settings-inline-btn",
3307
+ disabled: selectedMediaID === null,
3308
+ onClick: () => onRemoveItemMedia?.(itemIndex, fieldName),
3309
+ type: "button",
3310
+ children: "Remove Library Image"
3311
+ }
3312
+ ),
3313
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("label", { className: "orion-builder-settings-label", children: [
3314
+ "Direct Image URL",
3315
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3316
+ "input",
3317
+ {
3318
+ className: "orion-builder-settings-input",
3319
+ onChange: (event) => onUpdateItemField(itemIndex, imageURLFieldName, event.target.value),
3320
+ type: "text",
3321
+ value: directImageURL
3322
+ }
3323
+ )
3324
+ ] }),
3325
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("label", { className: "orion-builder-settings-label", children: [
3326
+ uploadLabel,
3327
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3328
+ "input",
3329
+ {
3330
+ accept: "image/*",
3331
+ className: "orion-builder-settings-input",
3332
+ disabled: uploadDisabled,
3333
+ onChange: (event) => {
3334
+ const file = event.currentTarget.files?.[0];
3335
+ if (file) {
3336
+ onUploadItemMedia?.(itemIndex, fieldName, file);
3337
+ }
3338
+ event.currentTarget.value = "";
3339
+ },
3340
+ type: "file"
3341
+ }
3342
+ )
3343
+ ] }),
3344
+ uploading ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "orion-builder-settings-note", children: "Uploading image..." }) : null,
3345
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3346
+ ImageControls,
3347
+ {
3348
+ cornerStyle: mediaSettings.cornerStyle,
3349
+ fit: mediaSettings.fit,
3350
+ height: mediaSettings.height,
3351
+ maxHeight,
3352
+ minHeight,
3353
+ onChange: (field, value) => onUpdateItemMediaPresentation?.(itemIndex, field, value),
3354
+ positionX: mediaSettings.positionX,
3355
+ positionY: mediaSettings.positionY
3356
+ }
3357
+ )
3358
+ ] });
3359
+ }
3014
3360
  function ArrayItemsEditor({
3015
3361
  blockType,
3016
3362
  expandedItemIndex,
3017
3363
  items,
3364
+ mediaLibrary = [],
3365
+ mediaLibraryError = "",
3366
+ mediaLibraryLoading = false,
3018
3367
  mode,
3019
3368
  onAddItem,
3369
+ onRemoveItemMedia,
3020
3370
  onRemoveItem,
3371
+ onSelectItemMedia,
3021
3372
  onToggleItem,
3022
3373
  onUpdateItemField,
3374
+ onUpdateItemMediaPresentation,
3023
3375
  onUpdateItemSetting,
3376
+ onUploadItemMedia,
3024
3377
  searchQuery,
3025
- showInlineCopyFields
3378
+ showInlineCopyFields,
3379
+ uploadDisabled = false,
3380
+ isItemMediaUploading
3026
3381
  }) {
3027
3382
  const config = blockConfig[blockType];
3028
3383
  const normalizedQuery = searchQuery.trim().toLowerCase();
@@ -3172,11 +3527,30 @@ function ArrayItemsEditor({
3172
3527
  }
3173
3528
  )
3174
3529
  ] }) : null,
3175
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "orion-builder-settings-note", children: [
3176
- "Select this item and use the ",
3177
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("strong", { children: "Media" }),
3178
- " group above for image source and presentation."
3179
- ] })
3530
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3531
+ ItemMediaControl,
3532
+ {
3533
+ fieldName: "media",
3534
+ imageURLFieldName: "imageURL",
3535
+ item,
3536
+ itemIndex,
3537
+ label: "Feature Image",
3538
+ maxHeight: 600,
3539
+ mediaLibrary,
3540
+ mediaLibraryError,
3541
+ mediaLibraryLoading,
3542
+ minHeight: 40,
3543
+ onRemoveItemMedia,
3544
+ onSelectItemMedia,
3545
+ onUpdateItemField,
3546
+ onUpdateItemMediaPresentation,
3547
+ onUploadItemMedia,
3548
+ searchQuery: normalizedQuery,
3549
+ uploadDisabled,
3550
+ uploadLabel: "Upload Feature Image",
3551
+ uploading: Boolean(isItemMediaUploading?.(itemIndex, "media"))
3552
+ }
3553
+ )
3180
3554
  ] }) : null,
3181
3555
  blockType === "logoWall" ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
3182
3556
  showInlineCopyFields ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("label", { className: "orion-builder-settings-label", children: [
@@ -3203,11 +3577,30 @@ function ArrayItemsEditor({
3203
3577
  }
3204
3578
  )
3205
3579
  ] }) : null,
3206
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "orion-builder-settings-note", children: [
3207
- "Select this item and use the ",
3208
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("strong", { children: "Media" }),
3209
- " group above for image source and presentation."
3210
- ] })
3580
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3581
+ ItemMediaControl,
3582
+ {
3583
+ fieldName: "media",
3584
+ imageURLFieldName: "imageURL",
3585
+ item,
3586
+ itemIndex,
3587
+ label: "Logo Image",
3588
+ maxHeight: 200,
3589
+ mediaLibrary,
3590
+ mediaLibraryError,
3591
+ mediaLibraryLoading,
3592
+ minHeight: 24,
3593
+ onRemoveItemMedia,
3594
+ onSelectItemMedia,
3595
+ onUpdateItemField,
3596
+ onUpdateItemMediaPresentation,
3597
+ onUploadItemMedia,
3598
+ searchQuery: normalizedQuery,
3599
+ uploadDisabled,
3600
+ uploadLabel: "Upload Logo Image",
3601
+ uploading: Boolean(isItemMediaUploading?.(itemIndex, "media"))
3602
+ }
3603
+ )
3211
3604
  ] }) : null,
3212
3605
  blockType === "beforeAfter" ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
3213
3606
  showInlineCopyFields ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
@@ -3235,11 +3628,54 @@ function ArrayItemsEditor({
3235
3628
  )
3236
3629
  ] })
3237
3630
  ] }) : null,
3238
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "orion-builder-settings-note", children: [
3239
- "Select this item and use the ",
3240
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("strong", { children: "Media" }),
3241
- " group above for before/after image source and presentation."
3242
- ] })
3631
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3632
+ ItemMediaControl,
3633
+ {
3634
+ fieldName: "beforeMedia",
3635
+ imageURLFieldName: "beforeImageURL",
3636
+ item,
3637
+ itemIndex,
3638
+ label: "Before Image",
3639
+ maxHeight: 600,
3640
+ mediaLibrary,
3641
+ mediaLibraryError,
3642
+ mediaLibraryLoading,
3643
+ minHeight: 60,
3644
+ onRemoveItemMedia,
3645
+ onSelectItemMedia,
3646
+ onUpdateItemField,
3647
+ onUpdateItemMediaPresentation,
3648
+ onUploadItemMedia,
3649
+ searchQuery: normalizedQuery,
3650
+ uploadDisabled,
3651
+ uploadLabel: "Upload Before Image",
3652
+ uploading: Boolean(isItemMediaUploading?.(itemIndex, "beforeMedia"))
3653
+ }
3654
+ ),
3655
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3656
+ ItemMediaControl,
3657
+ {
3658
+ fieldName: "afterMedia",
3659
+ imageURLFieldName: "afterImageURL",
3660
+ item,
3661
+ itemIndex,
3662
+ label: "After Image",
3663
+ maxHeight: 600,
3664
+ mediaLibrary,
3665
+ mediaLibraryError,
3666
+ mediaLibraryLoading,
3667
+ minHeight: 60,
3668
+ onRemoveItemMedia,
3669
+ onSelectItemMedia,
3670
+ onUpdateItemField,
3671
+ onUpdateItemMediaPresentation,
3672
+ onUploadItemMedia,
3673
+ searchQuery: normalizedQuery,
3674
+ uploadDisabled,
3675
+ uploadLabel: "Upload After Image",
3676
+ uploading: Boolean(isItemMediaUploading?.(itemIndex, "afterMedia"))
3677
+ }
3678
+ )
3243
3679
  ] }) : null,
3244
3680
  blockType === "stats" ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_jsx_runtime12.Fragment, { children: showInlineCopyFields ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
3245
3681
  /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("label", { className: "orion-builder-settings-label", children: [
@@ -3445,8 +3881,8 @@ var resolveBuilderMediumHeroHeight = (topViewportHeight) => {
3445
3881
  }
3446
3882
  return "50svh";
3447
3883
  };
3448
- var normalizeImageFit = (value) => normalizeHeroImageFit(value);
3449
- var normalizeImageCornerStyle = (value, legacyFitValue) => normalizeHeroImageCornerStyle(value, legacyFitValue);
3884
+ var normalizeImageFit2 = (value) => normalizeHeroImageFit(value);
3885
+ var normalizeImageCornerStyle2 = (value, legacyFitValue) => normalizeHeroImageCornerStyle(value, legacyFitValue);
3450
3886
  var positionPercent = (value, fit) => {
3451
3887
  const resolved = fit === "cover" && (value === "left" || value === "right") ? "center" : value;
3452
3888
  switch (resolved) {
@@ -3615,6 +4051,8 @@ var sectionPaddingMap = {
3615
4051
  md: "2.6rem",
3616
4052
  lg: "3.4rem"
3617
4053
  };
4054
+ var heroDefaultPaddingTop = "30pt";
4055
+ var heroDefaultPaddingBottom = "20pt";
3618
4056
  var quickAddBlockTypes = [
3619
4057
  "hero",
3620
4058
  "featureGrid",
@@ -3878,6 +4316,12 @@ function getThemeColorOverride(tokens, colorKey) {
3878
4316
  const normalized = value.trim();
3879
4317
  return normalized.length > 0 ? normalized : null;
3880
4318
  }
4319
+ function normalizeCustomClassName(value) {
4320
+ if (typeof value !== "string") {
4321
+ return "";
4322
+ }
4323
+ return value.split(/\s+/).map((className) => className.trim()).filter(Boolean).join(" ");
4324
+ }
3881
4325
  var sectionStyleFromBlock = (block, pageDefaults) => {
3882
4326
  const settings = isRecord6(block.settings) ? block.settings : {};
3883
4327
  const layoutSettings = isRecord6(settings.layout) ? settings.layout : {};
@@ -3963,15 +4407,15 @@ var sectionStyleFromBlock = (block, pageDefaults) => {
3963
4407
  } : {},
3964
4408
  sectionClass: `orion-builder-shell is-${pageDefaults.pageWidthDefault} padx-${resolvedSectionPaddingX}`,
3965
4409
  sectionInnerStyle: {
3966
- paddingBottom: customPaddingBottom === null ? sectionPaddingMap[sectionPaddingY] : `${customPaddingBottom}pt`,
4410
+ paddingBottom: customPaddingBottom === null ? block.blockType === "hero" ? heroDefaultPaddingBottom : sectionPaddingMap[sectionPaddingY] : `${customPaddingBottom}pt`,
3967
4411
  paddingLeft: customPaddingLeft === null ? void 0 : `${customPaddingLeft}pt`,
3968
4412
  paddingRight: customPaddingRight === null ? void 0 : `${customPaddingRight}pt`,
3969
- paddingTop: customPaddingTop === null ? sectionPaddingMap[sectionPaddingY] : `${customPaddingTop}pt`
4413
+ paddingTop: customPaddingTop === null ? block.blockType === "hero" ? heroDefaultPaddingTop : sectionPaddingMap[sectionPaddingY] : `${customPaddingTop}pt`
3970
4414
  },
3971
4415
  sectionStyle: sectionMode === "color" ? { background: sectionColor } : sectionMode === "gradient" ? { background: sectionGradient } : block.blockType === "hero" ? { background: "transparent" } : {}
3972
4416
  };
3973
4417
  };
3974
- function getRelationID2(value) {
4418
+ function getRelationID3(value) {
3975
4419
  if (typeof value === "number" || typeof value === "string") {
3976
4420
  return value;
3977
4421
  }
@@ -4004,7 +4448,7 @@ function extractUploadedMedia(value) {
4004
4448
  if (!candidate || typeof candidate !== "object") {
4005
4449
  return null;
4006
4450
  }
4007
- const id = getRelationID2(candidate);
4451
+ const id = getRelationID3(candidate);
4008
4452
  if (id === null) {
4009
4453
  return null;
4010
4454
  }
@@ -4015,11 +4459,11 @@ function extractUploadedMedia(value) {
4015
4459
  url: typeof candidate.url === "string" ? candidate.url : ""
4016
4460
  };
4017
4461
  }
4018
- function toMediaLibraryItem2(value) {
4462
+ function toMediaLibraryItem3(value) {
4019
4463
  if (!value || typeof value !== "object") {
4020
4464
  return null;
4021
4465
  }
4022
- const id = getRelationID2(value);
4466
+ const id = getRelationID3(value);
4023
4467
  if (id === null) {
4024
4468
  return null;
4025
4469
  }
@@ -4197,7 +4641,7 @@ function BuilderPageEditor({
4197
4641
  }
4198
4642
  const json = await response.json();
4199
4643
  const docs = Array.isArray(json.docs) ? json.docs : [];
4200
- const items = docs.map((doc2) => toMediaLibraryItem2(doc2)).filter((item) => item !== null);
4644
+ const items = docs.map((doc2) => toMediaLibraryItem3(doc2)).filter((item) => item !== null);
4201
4645
  setMediaLibrary(items);
4202
4646
  } catch (error) {
4203
4647
  setMediaLibraryError(error instanceof Error ? error.message : "Could not load media library.");
@@ -4551,7 +4995,7 @@ function BuilderPageEditor({
4551
4995
  const nextLayout = cloneBlockLayout(layout);
4552
4996
  const block = nextLayout[selectedIndex];
4553
4997
  if (target.kind === "hero") {
4554
- const uploadedItem = toMediaLibraryItem2(uploaded);
4998
+ const uploadedItem = toMediaLibraryItem3(uploaded);
4555
4999
  nextLayout[selectedIndex] = {
4556
5000
  ...block,
4557
5001
  backgroundImageURL: uploadedItem?.url || normalizeText2(uploaded.url),
@@ -4615,13 +5059,13 @@ function BuilderPageEditor({
4615
5059
  const nextBlock = { ...migrateBlockToSettingsV2(block) };
4616
5060
  const blockType = normalizeText2(nextBlock.blockType);
4617
5061
  if (blockType === "hero") {
4618
- const mediaID = getRelationID2(nextBlock.media);
5062
+ const mediaID = getRelationID3(nextBlock.media);
4619
5063
  if (mediaID !== null) {
4620
5064
  nextBlock.media = mediaID;
4621
5065
  }
4622
5066
  }
4623
5067
  if (blockType === "media") {
4624
- const imageID = getRelationID2(nextBlock.image);
5068
+ const imageID = getRelationID3(nextBlock.image);
4625
5069
  if (imageID !== null) {
4626
5070
  nextBlock.image = imageID;
4627
5071
  }
@@ -4633,15 +5077,15 @@ function BuilderPageEditor({
4633
5077
  return rawItem;
4634
5078
  }
4635
5079
  const nextItem = { ...rawItem };
4636
- const mediaID = getRelationID2(nextItem.media);
5080
+ const mediaID = getRelationID3(nextItem.media);
4637
5081
  if (mediaID !== null) {
4638
5082
  nextItem.media = mediaID;
4639
5083
  }
4640
- const beforeMediaID = getRelationID2(nextItem.beforeMedia);
5084
+ const beforeMediaID = getRelationID3(nextItem.beforeMedia);
4641
5085
  if (beforeMediaID !== null) {
4642
5086
  nextItem.beforeMedia = beforeMediaID;
4643
5087
  }
4644
- const afterMediaID = getRelationID2(nextItem.afterMedia);
5088
+ const afterMediaID = getRelationID3(nextItem.afterMedia);
4645
5089
  if (afterMediaID !== null) {
4646
5090
  nextItem.afterMedia = afterMediaID;
4647
5091
  }
@@ -4697,6 +5141,7 @@ function BuilderPageEditor({
4697
5141
  const inheritProjectStyles = options?.inheritProjectStyles === true;
4698
5142
  const shell = sectionStyleFromBlock(block, pageDefaults);
4699
5143
  const blockSettings = isRecord6(block.settings) ? block.settings : {};
5144
+ const blockAdvanced = isRecord6(blockSettings.advanced) ? blockSettings.advanced : {};
4700
5145
  const blockTypography = isRecord6(blockSettings.typography) ? blockSettings.typography : {};
4701
5146
  const blockTheme = isRecord6(blockSettings.theme) ? blockSettings.theme : {};
4702
5147
  const heroBackgroundColor = normalizeText2(block.backgroundColor).trim();
@@ -4704,23 +5149,35 @@ function BuilderPageEditor({
4704
5149
  const heroMedia = block.blockType === "hero" ? resolveMedia(block.media) : null;
4705
5150
  const heroHasImage = block.blockType === "hero" && Boolean(heroBackgroundImageURL || heroMedia?.url);
4706
5151
  const heroTextColor = block.blockType === "hero" ? heroHasImage ? "#ffffff" : heroBackgroundColor ? getReadableTextColor(heroBackgroundColor, resolvedThemeTokens.colors.headingText, "#ffffff") : resolvedThemeTokens.colors.headingText : null;
5152
+ const bodyAlign = blockTypography.bodyAlign === "center" || blockTypography.bodyAlign === "justify" || blockTypography.bodyAlign === "right" ? blockTypography.bodyAlign : "left";
4707
5153
  const typographyStyle = resolveTypographyStyleFromSettings({
4708
- bodyAlign: blockTypography.bodyAlign === "center" || blockTypography.bodyAlign === "justify" || blockTypography.bodyAlign === "right" ? blockTypography.bodyAlign : "left",
5154
+ bodyAlign,
4709
5155
  letterSpacingPreset: blockTypography.letterSpacingPreset === "tight" || blockTypography.letterSpacingPreset === "relaxed" ? blockTypography.letterSpacingPreset : "normal",
4710
5156
  lineHeightPreset: blockTypography.lineHeightPreset === "tight" || blockTypography.lineHeightPreset === "relaxed" ? blockTypography.lineHeightPreset : "normal",
5157
+ bodySizePt: typeof blockTypography.bodySizePt === "number" && Number.isFinite(blockTypography.bodySizePt) ? blockTypography.bodySizePt : null,
4711
5158
  maxTextWidth: blockTypography.maxTextWidth === "sm" || blockTypography.maxTextWidth === "md" || blockTypography.maxTextWidth === "lg" || blockTypography.maxTextWidth === "full" ? blockTypography.maxTextWidth : "auto"
4712
5159
  });
4713
5160
  const headingAlign = blockTypography.headingAlign === "center" || blockTypography.headingAlign === "justify" || blockTypography.headingAlign === "right" ? blockTypography.headingAlign : "left";
4714
5161
  const headingColor = getThemeColorOverride(blockTheme, "headingText") || getThemeColorOverride(pageDefaults.themePage, "headingText") || getThemeColorOverride(siteThemeTokens, "headingText") || heroTextColor || resolvedThemeTokens.colors.headingText;
4715
5162
  const bodyColor = getThemeColorOverride(blockTheme, "bodyText") || getThemeColorOverride(pageDefaults.themePage, "bodyText") || getThemeColorOverride(siteThemeTokens, "bodyText") || heroTextColor || resolvedThemeTokens.colors.bodyText;
4716
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("section", { className: `${className} ${shell.sectionClass}`, style: shell.sectionStyle, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: shell.sectionInnerStyle, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5163
+ const customClassName = normalizeCustomClassName(blockAdvanced.customClassName ?? block.customClassName);
5164
+ const hideOnMobile = Boolean(blockAdvanced.hideOnMobile ?? block.hideOnMobile);
5165
+ const sectionClassName = [
5166
+ className,
5167
+ shell.sectionClass,
5168
+ customClassName,
5169
+ hideOnMobile ? "orion-builder-hide-mobile" : ""
5170
+ ].filter(Boolean).join(" ");
5171
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("section", { className: sectionClassName, style: shell.sectionStyle, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: shell.sectionInnerStyle, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4717
5172
  "div",
4718
5173
  {
4719
5174
  className: shell.contentClass,
4720
5175
  style: {
4721
5176
  ...shell.contentStyle,
5177
+ "--orion-builder-heading-align": headingAlign,
5178
+ "--orion-builder-body-align": bodyAlign,
5179
+ "--orion-builder-actions-align": bodyAlign === "center" ? "center" : bodyAlign === "right" ? "flex-end" : "flex-start",
4722
5180
  ...inheritProjectStyles ? {} : {
4723
- "--orion-builder-heading-align": headingAlign,
4724
5181
  "--orion-builder-heading-color": headingColor,
4725
5182
  color: bodyColor,
4726
5183
  ...typographyStyle
@@ -5207,8 +5664,8 @@ function BuilderPageEditor({
5207
5664
  }
5208
5665
  ] : [];
5209
5666
  const selectedMediaImageControls = selectedItemRecord && typeof selectedItemIndex === "number" && (selectedType === "featureGrid" || selectedType === "logoWall" || selectedType === "beforeAfter") ? {
5210
- cornerStyle: normalizeImageCornerStyle(selectedItemRecord.imageCornerStyle),
5211
- fit: normalizeImageFit(selectedItemRecord.imageFit),
5667
+ cornerStyle: normalizeImageCornerStyle2(selectedItemRecord.imageCornerStyle),
5668
+ fit: normalizeImageFit2(selectedItemRecord.imageFit),
5212
5669
  height: (() => {
5213
5670
  if (typeof selectedItemRecord.imageHeight === "number" && Number.isFinite(selectedItemRecord.imageHeight)) {
5214
5671
  return selectedItemRecord.imageHeight;
@@ -5683,8 +6140,8 @@ function BuilderPageEditor({
5683
6140
  const itemPositionX = parseOptionalPercentNumber2(itemRecord?.imagePositionX);
5684
6141
  const itemPositionY = parseOptionalPercentNumber2(itemRecord?.imagePositionY);
5685
6142
  const itemImageStyle = getImagePresentationStyle({
5686
- cornerStyle: normalizeImageCornerStyle(itemRecord?.imageCornerStyle),
5687
- fit: normalizeImageFit(itemRecord?.imageFit),
6143
+ cornerStyle: normalizeImageCornerStyle2(itemRecord?.imageCornerStyle),
6144
+ fit: normalizeImageFit2(itemRecord?.imageFit),
5688
6145
  positionX: itemPositionX,
5689
6146
  positionY: itemPositionY
5690
6147
  });
@@ -5801,8 +6258,8 @@ function BuilderPageEditor({
5801
6258
  const itemPositionX = parseOptionalPercentNumber2(itemRecord?.imagePositionX);
5802
6259
  const itemPositionY = parseOptionalPercentNumber2(itemRecord?.imagePositionY);
5803
6260
  const itemImageStyle = getImagePresentationStyle({
5804
- cornerStyle: normalizeImageCornerStyle(itemRecord?.imageCornerStyle),
5805
- fit: normalizeImageFit(itemRecord?.imageFit),
6261
+ cornerStyle: normalizeImageCornerStyle2(itemRecord?.imageCornerStyle),
6262
+ fit: normalizeImageFit2(itemRecord?.imageFit),
5806
6263
  positionX: itemPositionX,
5807
6264
  positionY: itemPositionY
5808
6265
  });
@@ -6008,8 +6465,8 @@ function BuilderPageEditor({
6008
6465
  const itemPositionX = parseOptionalPercentNumber2(itemRecord?.imagePositionX);
6009
6466
  const itemPositionY = parseOptionalPercentNumber2(itemRecord?.imagePositionY);
6010
6467
  const imageStyle = getImagePresentationStyle({
6011
- cornerStyle: normalizeImageCornerStyle(itemRecord?.imageCornerStyle),
6012
- fit: normalizeImageFit(itemRecord?.imageFit),
6468
+ cornerStyle: normalizeImageCornerStyle2(itemRecord?.imageCornerStyle),
6469
+ fit: normalizeImageFit2(itemRecord?.imageFit),
6013
6470
  positionX: itemPositionX,
6014
6471
  positionY: itemPositionY,
6015
6472
  roundedRadius: 10
@@ -6122,8 +6579,8 @@ function BuilderPageEditor({
6122
6579
  const itemPositionX = parseOptionalPercentNumber2(itemRecord?.imagePositionX);
6123
6580
  const itemPositionY = parseOptionalPercentNumber2(itemRecord?.imagePositionY);
6124
6581
  const imageStyle = getImagePresentationStyle({
6125
- cornerStyle: normalizeImageCornerStyle(itemRecord?.imageCornerStyle),
6126
- fit: normalizeImageFit(itemRecord?.imageFit),
6582
+ cornerStyle: normalizeImageCornerStyle2(itemRecord?.imageCornerStyle),
6583
+ fit: normalizeImageFit2(itemRecord?.imageFit),
6127
6584
  positionX: itemPositionX,
6128
6585
  positionY: itemPositionY
6129
6586
  });
@@ -6429,8 +6886,8 @@ function BuilderPageEditor({
6429
6886
  getImagePresentationStyle,
6430
6887
  index,
6431
6888
  isBlockUploadTarget,
6432
- normalizeImageCornerStyle,
6433
- normalizeImageFit,
6889
+ normalizeImageCornerStyle: normalizeImageCornerStyle2,
6890
+ normalizeImageFit: normalizeImageFit2,
6434
6891
  normalizeText: normalizeText2,
6435
6892
  onDropAt,
6436
6893
  renderWithSectionShell,
@@ -6659,23 +7116,32 @@ function BuilderPageEditor({
6659
7116
  blockType: selectedType,
6660
7117
  expandedItemIndex,
6661
7118
  items: selectedItems,
7119
+ isItemMediaUploading: isSelectedItemMediaUploading,
7120
+ mediaLibrary,
7121
+ mediaLibraryError,
7122
+ mediaLibraryLoading,
6662
7123
  mode: settingsPanelMode,
6663
7124
  onAddItem: appendDefaultItemToSelected,
6664
7125
  onRemoveItem: (itemIndex) => removeItemFromSelected("items", itemIndex),
7126
+ onRemoveItemMedia: (itemIndex, fieldName) => setSelectedItemMediaFieldFromLibrary(itemIndex, fieldName, ""),
7127
+ onSelectItemMedia: (itemIndex, fieldName, mediaID) => setSelectedItemMediaFieldFromLibrary(itemIndex, fieldName, mediaID),
6665
7128
  onToggleItem: toggleSelectedItem,
6666
7129
  onUpdateItemField: (itemIndex, fieldName, value) => updateArrayItemField(selectedIndex ?? 0, "items", itemIndex, fieldName, value),
7130
+ onUpdateItemMediaPresentation: (itemIndex, fieldName, value) => updateArrayItemSettingField(selectedIndex ?? 0, "items", itemIndex, `media.${fieldName}`, value),
6667
7131
  onUpdateItemSetting: (itemIndex, path, value) => updateArrayItemSettingField(selectedIndex ?? 0, "items", itemIndex, path, value),
7132
+ onUploadItemMedia: uploadItemMediaFromV2,
6668
7133
  searchQuery: settingsSearchQuery,
6669
- showInlineCopyFields: editCopyInPanelEnabled
7134
+ showInlineCopyFields: editCopyInPanelEnabled,
7135
+ uploadDisabled: uploadingTarget !== null
6670
7136
  }
6671
7137
  ) : null,
6672
7138
  /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { style: sidebarLabelStyle, children: [
6673
- "Upload Alt Text",
7139
+ "New Upload Alt Text",
6674
7140
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6675
7141
  "input",
6676
7142
  {
6677
7143
  onChange: (event) => setUploadAltText(event.target.value),
6678
- placeholder: "Describe the image",
7144
+ placeholder: "Used only when uploading a new image",
6679
7145
  style: sidebarInputStyle,
6680
7146
  type: "text",
6681
7147
  value: uploadAltText