@orion-studios/payload-studio 0.6.0-beta.7 → 0.6.0-beta.70

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 (48) hide show
  1. package/dist/admin/client.js +2076 -618
  2. package/dist/admin/client.mjs +2037 -590
  3. package/dist/admin/index.d.mts +2 -2
  4. package/dist/admin/index.d.ts +2 -2
  5. package/dist/admin/index.js +140 -17
  6. package/dist/admin/index.mjs +1 -1
  7. package/dist/admin-app/client.js +11 -4
  8. package/dist/admin-app/client.mjs +1 -1
  9. package/dist/admin-app/index.d.mts +2 -2
  10. package/dist/admin-app/index.d.ts +2 -2
  11. package/dist/admin-app/styles.css +343 -41
  12. package/dist/admin.css +18 -2
  13. package/dist/builder-v2/client.d.mts +18 -0
  14. package/dist/builder-v2/client.d.ts +18 -0
  15. package/dist/builder-v2/client.js +1662 -0
  16. package/dist/builder-v2/client.mjs +1537 -0
  17. package/dist/builder-v2/index.d.mts +237 -0
  18. package/dist/builder-v2/index.d.ts +237 -0
  19. package/dist/builder-v2/index.js +735 -0
  20. package/dist/builder-v2/index.mjs +685 -0
  21. package/dist/builder-v2/styles.css +1524 -0
  22. package/dist/{chunk-KPIX7OSV.mjs → chunk-2XH7X34N.mjs} +11 -4
  23. package/dist/{chunk-PF3EBZXF.mjs → chunk-7ZMXZRBP.mjs} +39 -3
  24. package/dist/{chunk-5FNTVRCR.mjs → chunk-JC3UV74N.mjs} +140 -17
  25. package/dist/{chunk-XKUTZ7IU.mjs → chunk-NGLIA2OE.mjs} +53 -2
  26. package/dist/{chunk-OTHERBGX.mjs → chunk-ZADL33R6.mjs} +1 -1
  27. package/dist/{index-QPDAedIX.d.ts → index-BV0vEGl6.d.ts} +4 -2
  28. package/dist/{index-Cv-6qnrw.d.mts → index-D5zrOdyv.d.mts} +3 -1
  29. package/dist/{index-52HdVLQq.d.ts → index-DAdN56fM.d.ts} +1 -1
  30. package/dist/{index-DyMmaRfI.d.mts → index-DLfPOqYA.d.mts} +4 -2
  31. package/dist/{index-Crx_MtPw.d.ts → index-Dv-Alx4h.d.ts} +3 -1
  32. package/dist/{index-DEQC3Dwj.d.mts → index-G_uTNffQ.d.mts} +1 -1
  33. package/dist/index.d.mts +4 -4
  34. package/dist/index.d.ts +4 -4
  35. package/dist/index.js +231 -21
  36. package/dist/index.mjs +4 -4
  37. package/dist/nextjs/index.js +39 -3
  38. package/dist/nextjs/index.mjs +2 -2
  39. package/dist/{sitePreviewTypes-BkHCWxNW.d.mts → sitePreviewTypes-BrJwGzJj.d.mts} +1 -1
  40. package/dist/{sitePreviewTypes-BkHCWxNW.d.ts → sitePreviewTypes-BrJwGzJj.d.ts} +1 -1
  41. package/dist/studio-pages/builder.css +24 -5
  42. package/dist/studio-pages/client.js +574 -64
  43. package/dist/studio-pages/client.mjs +574 -64
  44. package/dist/studio-pages/index.d.mts +1 -1
  45. package/dist/studio-pages/index.d.ts +1 -1
  46. package/dist/studio-pages/index.js +91 -4
  47. package/dist/studio-pages/index.mjs +2 -2
  48. package/package.json +22 -3
@@ -70,7 +70,9 @@ var defaultBuilderBlockSettingsV2 = {
70
70
  },
71
71
  typography: {
72
72
  bodyAlign: "left",
73
+ bodySizePt: null,
73
74
  headingAlign: "left",
75
+ headingSizePt: null,
74
76
  letterSpacingPreset: "normal",
75
77
  lineHeightPreset: "normal",
76
78
  maxTextWidth: "auto"
@@ -99,7 +101,9 @@ var defaultBuilderItemSettingsV2 = {
99
101
  },
100
102
  typography: {
101
103
  bodyAlign: "left",
104
+ bodySizePt: null,
102
105
  headingAlign: "left",
106
+ headingSizePt: null,
103
107
  letterSpacingPreset: "normal",
104
108
  lineHeightPreset: "normal",
105
109
  maxTextWidth: "auto"
@@ -129,6 +133,7 @@ var defaultBuilderThemeTokens = {
129
133
 
130
134
  // src/studio-pages/builder/adapters/settingsV2.ts
131
135
  var isRecord = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
136
+ var isTextAlign = (value) => value === "left" || value === "center" || value === "right" || value === "justify";
132
137
  var parsePercent = (value) => {
133
138
  if (typeof value === "number" && Number.isFinite(value)) {
134
139
  return Math.max(0, Math.min(100, value));
@@ -153,6 +158,18 @@ var parsePixel = (value) => {
153
158
  }
154
159
  return null;
155
160
  };
161
+ var parsePoint = (value) => {
162
+ if (typeof value === "number" && Number.isFinite(value)) {
163
+ return Math.max(6, Math.min(120, Math.round(value)));
164
+ }
165
+ if (typeof value === "string" && value.trim().length > 0) {
166
+ const parsed = Number(value);
167
+ if (Number.isFinite(parsed)) {
168
+ return Math.max(6, Math.min(120, Math.round(parsed)));
169
+ }
170
+ }
171
+ return null;
172
+ };
156
173
  var mergeSettings = (defaults, input) => {
157
174
  if (!isRecord(input)) {
158
175
  return structuredClone(defaults);
@@ -171,6 +188,10 @@ var mergeSettings = (defaults, input) => {
171
188
  };
172
189
  var legacyBlockToV2Settings = (block) => {
173
190
  const current = structuredClone(defaultBuilderBlockSettingsV2);
191
+ if (block.blockType === "hero" && block.variant === "centered") {
192
+ current.typography.headingAlign = "center";
193
+ current.typography.bodyAlign = "center";
194
+ }
174
195
  current.layout.contentWidth = block.contentWidth === "narrow" || block.contentWidth === "content" || block.contentWidth === "wide" || block.contentWidth === "full" || block.contentWidth === "inherit" ? block.contentWidth : current.layout.contentWidth;
175
196
  current.layout.sectionPaddingX = block.sectionPaddingX === "none" || block.sectionPaddingX === "sm" || block.sectionPaddingX === "md" || block.sectionPaddingX === "lg" || block.sectionPaddingX === "inherit" ? block.sectionPaddingX : current.layout.sectionPaddingX;
176
197
  current.layout.sectionPaddingY = block.sectionPaddingY === "none" || block.sectionPaddingY === "sm" || block.sectionPaddingY === "lg" ? block.sectionPaddingY : current.layout.sectionPaddingY;
@@ -207,15 +228,28 @@ var legacyBlockToV2Settings = (block) => {
207
228
  current.media.positionX = parsePercent(block.imagePositionX ?? block.backgroundImagePositionX);
208
229
  current.media.positionY = parsePercent(block.imagePositionY ?? block.backgroundImagePositionY);
209
230
  current.media.height = parsePixel(block.imageHeight);
210
- current.typography.headingAlign = block.textHeadingAlign === "left" || block.textHeadingAlign === "center" || block.textHeadingAlign === "right" || block.textHeadingAlign === "justify" ? block.textHeadingAlign : current.typography.headingAlign;
211
- current.typography.bodyAlign = block.textBodyAlign === "left" || block.textBodyAlign === "center" || block.textBodyAlign === "right" || block.textBodyAlign === "justify" ? block.textBodyAlign : current.typography.bodyAlign;
231
+ current.typography.headingAlign = isTextAlign(block.textHeadingAlign) ? block.textHeadingAlign : current.typography.headingAlign;
232
+ current.typography.bodyAlign = isTextAlign(block.textBodyAlign) ? block.textBodyAlign : current.typography.bodyAlign;
233
+ current.typography.headingSizePt = parsePoint(block.textHeadingSizePt);
234
+ current.typography.bodySizePt = parsePoint(block.textBodySizePt);
212
235
  current.typography.maxTextWidth = block.textMaxWidth === "auto" || block.textMaxWidth === "sm" || block.textMaxWidth === "md" || block.textMaxWidth === "lg" || block.textMaxWidth === "full" ? block.textMaxWidth : current.typography.maxTextWidth;
213
236
  current.typography.lineHeightPreset = block.textLineHeightPreset === "tight" || block.textLineHeightPreset === "normal" || block.textLineHeightPreset === "relaxed" ? block.textLineHeightPreset : current.typography.lineHeightPreset;
214
237
  current.typography.letterSpacingPreset = block.textLetterSpacingPreset === "tight" || block.textLetterSpacingPreset === "normal" || block.textLetterSpacingPreset === "relaxed" ? block.textLetterSpacingPreset : current.typography.letterSpacingPreset;
215
238
  current.advanced.editCopyInPanel = Boolean(block.editCopyInPanel ?? current.advanced.editCopyInPanel);
216
239
  current.advanced.customClassName = typeof block.customClassName === "string" ? block.customClassName : current.advanced.customClassName;
217
240
  current.advanced.hideOnMobile = Boolean(block.hideOnMobile ?? current.advanced.hideOnMobile);
218
- return mergeSettings(current, block.settings);
241
+ const settings = mergeSettings(current, block.settings);
242
+ if (block.blockType === "hero") {
243
+ const top = settings.layout.paddingTopPt;
244
+ const bottom = settings.layout.paddingBottomPt;
245
+ const hasLegacyLinkedHeroPadding = settings.layout.linkVerticalPadding !== false && (top === null || typeof top === "undefined" || top === 30) && (bottom === null || typeof bottom === "undefined" || bottom === 30 || bottom === 20);
246
+ if (hasLegacyLinkedHeroPadding) {
247
+ settings.layout.linkVerticalPadding = false;
248
+ settings.layout.paddingTopPt = 30;
249
+ settings.layout.paddingBottomPt = 20;
250
+ }
251
+ }
252
+ return settings;
219
253
  };
220
254
  var v2SettingsToLegacyBlock = (blockWithSettings) => {
221
255
  const settings = legacyBlockToV2Settings(blockWithSettings);
@@ -241,6 +275,8 @@ var v2SettingsToLegacyBlock = (blockWithSettings) => {
241
275
  next.contentGradientAngle = settings.appearance.contentGradientAngle;
242
276
  next.textHeadingAlign = settings.typography.headingAlign;
243
277
  next.textBodyAlign = settings.typography.bodyAlign;
278
+ next.textHeadingSizePt = settings.typography.headingSizePt;
279
+ next.textBodySizePt = settings.typography.bodySizePt;
244
280
  next.textMaxWidth = settings.typography.maxTextWidth;
245
281
  next.textLineHeightPreset = settings.typography.lineHeightPreset;
246
282
  next.textLetterSpacingPreset = settings.typography.letterSpacingPreset;
@@ -335,6 +371,7 @@ var resolveTypographyStyleFromSettings = (settings) => {
335
371
  const letterSpacing = settings.letterSpacingPreset === "tight" ? "-0.01em" : settings.letterSpacingPreset === "relaxed" ? "0.02em" : "0.01em";
336
372
  const maxWidth = settings.maxTextWidth === "sm" ? "36ch" : settings.maxTextWidth === "md" ? "52ch" : settings.maxTextWidth === "lg" ? "72ch" : settings.maxTextWidth === "full" ? "100%" : void 0;
337
373
  return {
374
+ ...typeof settings.bodySizePt === "number" && Number.isFinite(settings.bodySizePt) ? { fontSize: `${settings.bodySizePt}pt` } : {},
338
375
  letterSpacing,
339
376
  lineHeight,
340
377
  maxWidth,
@@ -504,8 +541,52 @@ var alignOptions = [
504
541
  { label: "Right", value: "right" },
505
542
  { label: "Justify", value: "justify" }
506
543
  ];
507
- var layoutFieldSet = [];
544
+ var layoutFieldSet = [
545
+ {
546
+ group: "layout",
547
+ key: "settings.layout.linkVerticalPadding",
548
+ label: "Link Top/Bottom Padding",
549
+ tags: ["spacing", "padding", "vertical"],
550
+ type: "checkbox"
551
+ },
552
+ {
553
+ group: "layout",
554
+ key: "settings.layout.paddingTopPt",
555
+ label: "Top Padding (pt)",
556
+ max: 240,
557
+ min: 0,
558
+ tags: ["spacing", "padding", "top"],
559
+ type: "number"
560
+ },
561
+ {
562
+ group: "layout",
563
+ key: "settings.layout.paddingBottomPt",
564
+ label: "Bottom Padding (pt)",
565
+ max: 240,
566
+ min: 0,
567
+ tags: ["spacing", "padding", "bottom"],
568
+ type: "number"
569
+ }
570
+ ];
508
571
  var typographyFieldSet = [
572
+ {
573
+ group: "typography",
574
+ key: "settings.typography.headingSizePt",
575
+ label: "Heading Text Size (pt)",
576
+ max: 120,
577
+ min: 6,
578
+ tags: ["text", "size", "heading", "font"],
579
+ type: "number"
580
+ },
581
+ {
582
+ group: "typography",
583
+ key: "settings.typography.bodySizePt",
584
+ label: "Body Text Size (pt)",
585
+ max: 72,
586
+ min: 6,
587
+ tags: ["text", "size", "body", "paragraph", "font"],
588
+ type: "number"
589
+ },
509
590
  {
510
591
  group: "typography",
511
592
  key: "settings.typography.headingAlign",
@@ -612,6 +693,7 @@ var mediaFieldSet = [
612
693
  ];
613
694
  var commonInspectorGroups = [
614
695
  { key: "basics", label: "Basics" },
696
+ { key: "layout", label: "Layout" },
615
697
  { key: "typography", label: "Typography" },
616
698
  { key: "media", label: "Media" },
617
699
  { key: "advanced", label: "Advanced" }
@@ -728,6 +810,13 @@ var inspectorDefinitionByBlockType = {
728
810
  { group: "basics", inlineEditable: true, key: "kicker", label: "Kicker", type: "text" },
729
811
  { group: "basics", inlineEditable: true, key: "headline", label: "Headline", type: "text" },
730
812
  { group: "basics", inlineEditable: true, key: "subheadline", label: "Subheadline", type: "textarea" },
813
+ {
814
+ group: "basics",
815
+ key: "settings.marquee.itemsText",
816
+ label: "Scrolling Bar Options",
817
+ tags: ["marquee", "scrolling", "bar", "categories"],
818
+ type: "textarea"
819
+ },
731
820
  {
732
821
  group: "basics",
733
822
  key: "variant",
@@ -897,6 +986,69 @@ var normalizeNumber = (value, fallback) => {
897
986
  }
898
987
  return fallback;
899
988
  };
989
+ var sectionPaddingPointMap = {
990
+ none: 0,
991
+ sm: 17,
992
+ md: 31,
993
+ lg: 41
994
+ };
995
+ var heroDefaultPaddingTopPt = 30;
996
+ var heroDefaultPaddingBottomPt = 20;
997
+ var defaultTextSizePointMap = {
998
+ cta: { body: 14, heading: 36 },
999
+ faq: { body: 12, heading: 18 },
1000
+ featureGrid: { body: 12, heading: 36 },
1001
+ formEmbed: { body: 12, heading: 36 },
1002
+ hero: { body: 14, heading: 48 },
1003
+ media: { body: 12, heading: 36 },
1004
+ richText: { body: 12, heading: 39 },
1005
+ stats: { body: 11, heading: 30 },
1006
+ testimonials: { body: 12, heading: 36 }
1007
+ };
1008
+ var normalizeSectionPaddingY = (value) => value === "none" || value === "sm" || value === "lg" ? value : "md";
1009
+ var normalizePaddingPointValue = (value) => {
1010
+ if (typeof value === "number" && Number.isFinite(value)) {
1011
+ return Math.max(0, Math.min(240, Math.round(value)));
1012
+ }
1013
+ if (typeof value === "string" && value.trim().length > 0) {
1014
+ const parsed = Number(value);
1015
+ if (Number.isFinite(parsed)) {
1016
+ return Math.max(0, Math.min(240, Math.round(parsed)));
1017
+ }
1018
+ }
1019
+ return null;
1020
+ };
1021
+ var normalizeTextSizePointValue = (value) => {
1022
+ if (typeof value === "number" && Number.isFinite(value)) {
1023
+ return Math.max(6, Math.min(120, Math.round(value)));
1024
+ }
1025
+ if (typeof value === "string" && value.trim().length > 0) {
1026
+ const parsed = Number(value);
1027
+ if (Number.isFinite(parsed)) {
1028
+ return Math.max(6, Math.min(120, Math.round(parsed)));
1029
+ }
1030
+ }
1031
+ return null;
1032
+ };
1033
+ var getEffectiveVerticalPaddingValue = (block, key) => {
1034
+ const explicit = normalizePaddingPointValue(getByPath(block, key));
1035
+ if (explicit !== null) {
1036
+ return explicit;
1037
+ }
1038
+ const layoutSectionPaddingY = getByPath(block, "settings.layout.sectionPaddingY");
1039
+ const legacySectionPaddingY = block.sectionPaddingY;
1040
+ const inherited = block.blockType === "hero" ? key === "settings.layout.paddingBottomPt" ? heroDefaultPaddingBottomPt : heroDefaultPaddingTopPt : sectionPaddingPointMap[normalizeSectionPaddingY(layoutSectionPaddingY || legacySectionPaddingY)];
1041
+ return inherited;
1042
+ };
1043
+ var getEffectiveTextSizeValue = (block, key) => {
1044
+ const explicit = normalizeTextSizePointValue(getByPath(block, key));
1045
+ if (explicit !== null) {
1046
+ return explicit;
1047
+ }
1048
+ const blockType = typeof block.blockType === "string" ? block.blockType : "";
1049
+ const defaults = defaultTextSizePointMap[blockType] || { body: 12, heading: 36 };
1050
+ return key === "settings.typography.headingSizePt" ? defaults.heading : defaults.body;
1051
+ };
900
1052
  var getRelationID = (value) => {
901
1053
  if (typeof value === "number" || typeof value === "string") {
902
1054
  return value;
@@ -925,6 +1077,12 @@ var toMediaLibraryItem = (value) => {
925
1077
  };
926
1078
  };
927
1079
  var mediaLabel = (item) => item.filename || item.alt || `Media #${item.id}`;
1080
+ var findMediaLibraryItem = (library, id) => {
1081
+ if (id === null) {
1082
+ return null;
1083
+ }
1084
+ return library.find((item) => String(item.id) === String(id)) || null;
1085
+ };
928
1086
  var groupLabel = (key) => commonInspectorGroups.find((group) => group.key === key)?.label || key;
929
1087
  function BlockInspectorRenderer({
930
1088
  block,
@@ -1048,8 +1206,9 @@ function BlockInspectorRenderer({
1048
1206
  title: group.label,
1049
1207
  children: /* @__PURE__ */ jsxs3("div", { className: "orion-builder-settings-field-list", children: [
1050
1208
  group.key === "media" ? effectiveMediaSources.map((source) => {
1051
- const selectedSourceMedia = toMediaLibraryItem(source.value);
1052
1209
  const selectedSourceMediaID = getRelationID(source.value);
1210
+ const selectedRelationMedia = toMediaLibraryItem(source.value);
1211
+ const selectedSourceMedia = selectedRelationMedia ?? findMediaLibraryItem(source.library, selectedSourceMediaID);
1053
1212
  const sourceOptions = selectedSourceMedia && !source.library.some((item) => String(item.id) === String(selectedSourceMedia.id)) ? [selectedSourceMedia, ...source.library] : source.library;
1054
1213
  return /* @__PURE__ */ jsxs3(
1055
1214
  "div",
@@ -1059,6 +1218,26 @@ function BlockInspectorRenderer({
1059
1218
  children: [
1060
1219
  source.loading ? /* @__PURE__ */ jsx3("div", { className: "orion-builder-settings-note", children: "Loading media library..." }) : null,
1061
1220
  source.error ? /* @__PURE__ */ jsx3("div", { className: "orion-builder-settings-error", children: source.error }) : null,
1221
+ selectedSourceMedia?.url ? (
1222
+ // eslint-disable-next-line @next/next/no-img-element
1223
+ /* @__PURE__ */ jsx3(
1224
+ "img",
1225
+ {
1226
+ alt: selectedSourceMedia.alt || source.label,
1227
+ src: selectedSourceMedia.url,
1228
+ style: {
1229
+ aspectRatio: "16 / 9",
1230
+ border: "1px solid rgba(35, 51, 82, 0.14)",
1231
+ borderRadius: 10,
1232
+ display: "block",
1233
+ marginBottom: "0.7rem",
1234
+ objectFit: effectiveMedia.fit,
1235
+ objectPosition: `${effectiveMedia.positionX}% ${effectiveMedia.positionY}%`,
1236
+ width: "100%"
1237
+ }
1238
+ }
1239
+ )
1240
+ ) : /* @__PURE__ */ jsx3("div", { className: "orion-builder-settings-empty", children: "No image selected." }),
1062
1241
  /* @__PURE__ */ jsxs3("label", { className: "orion-builder-settings-label", children: [
1063
1242
  source.label,
1064
1243
  /* @__PURE__ */ jsxs3(
@@ -1074,6 +1253,10 @@ function BlockInspectorRenderer({
1074
1253
  }
1075
1254
  )
1076
1255
  ] }),
1256
+ selectedSourceMedia?.alt ? /* @__PURE__ */ jsxs3("label", { className: "orion-builder-settings-label", children: [
1257
+ "Media Description",
1258
+ /* @__PURE__ */ jsx3("input", { className: "orion-builder-settings-input", readOnly: true, type: "text", value: selectedSourceMedia.alt })
1259
+ ] }) : selectedSourceMediaID !== null ? /* @__PURE__ */ jsx3("div", { className: "orion-builder-settings-note", children: "This media item does not have a description yet." }) : null,
1077
1260
  /* @__PURE__ */ jsx3(
1078
1261
  "button",
1079
1262
  {
@@ -1130,19 +1313,20 @@ function BlockInspectorRenderer({
1130
1313
  }
1131
1314
  ) : null,
1132
1315
  (hasMediaGroupContent ? group.fields.filter((field) => !(group.key === "media" && field.key.startsWith("settings.media."))) : group.fields).map((field) => {
1133
- 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") {
1134
1317
  return null;
1135
1318
  }
1136
- 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) {
1137
1320
  return null;
1138
1321
  }
1139
1322
  const fieldValue = getByPath(block, field.key);
1140
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);
1141
1325
  return /* @__PURE__ */ jsxs3("label", { className: "orion-builder-settings-label is-checkbox", children: [
1142
1326
  /* @__PURE__ */ jsx3(
1143
1327
  "input",
1144
1328
  {
1145
- checked: Boolean(fieldValue),
1329
+ checked,
1146
1330
  onChange: (event) => updateForKey(field.key, event.target.checked),
1147
1331
  type: "checkbox"
1148
1332
  }
@@ -1165,8 +1349,10 @@ function BlockInspectorRenderer({
1165
1349
  ] }, field.key);
1166
1350
  }
1167
1351
  if (field.type === "number") {
1168
- const numberValue = typeof fieldValue === "number" ? fieldValue : typeof fieldValue === "string" && fieldValue.trim().length > 0 ? Number(fieldValue) : null;
1169
- 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) : "";
1170
1356
  return /* @__PURE__ */ jsxs3("label", { className: "orion-builder-settings-label", children: [
1171
1357
  field.label,
1172
1358
  /* @__PURE__ */ jsx3(
@@ -2129,8 +2315,8 @@ function renderSimpleBlockPreview(args) {
2129
2315
  getImagePresentationStyle: getImagePresentationStyle2,
2130
2316
  index,
2131
2317
  isBlockUploadTarget,
2132
- normalizeImageCornerStyle: normalizeImageCornerStyle2,
2133
- normalizeImageFit: normalizeImageFit2,
2318
+ normalizeImageCornerStyle: normalizeImageCornerStyle3,
2319
+ normalizeImageFit: normalizeImageFit3,
2134
2320
  normalizeText: normalizeText3,
2135
2321
  onDropAt,
2136
2322
  renderWithSectionShell,
@@ -2314,8 +2500,8 @@ function renderSimpleBlockPreview(args) {
2314
2500
  const imagePositionX = parseOptionalPercentNumber(mediaSettings.positionX ?? block?.imagePositionX);
2315
2501
  const imagePositionY = parseOptionalPercentNumber(mediaSettings.positionY ?? block?.imagePositionY);
2316
2502
  const imageStyle = getImagePresentationStyle2({
2317
- cornerStyle: normalizeImageCornerStyle2(mediaSettings.cornerStyle ?? block?.imageCornerStyle),
2318
- fit: normalizeImageFit2(mediaSettings.fit ?? block?.imageFit),
2503
+ cornerStyle: normalizeImageCornerStyle3(mediaSettings.cornerStyle ?? block?.imageCornerStyle),
2504
+ fit: normalizeImageFit3(mediaSettings.fit ?? block?.imageFit),
2319
2505
  positionX: imagePositionX,
2320
2506
  positionY: imagePositionY
2321
2507
  });
@@ -2845,6 +3031,76 @@ var normalizeNumber2 = (value, fallback) => {
2845
3031
  return fallback;
2846
3032
  };
2847
3033
  var clamp = (value, min, max) => Math.max(min, Math.min(max, value));
3034
+ var getRelationID2 = (value) => {
3035
+ if (typeof value === "number" || typeof value === "string") {
3036
+ return value;
3037
+ }
3038
+ if (!isRecord5(value)) {
3039
+ return null;
3040
+ }
3041
+ const id = value.id;
3042
+ return typeof id === "number" || typeof id === "string" ? id : null;
3043
+ };
3044
+ var toMediaLibraryItem2 = (value) => {
3045
+ if (!isRecord5(value)) {
3046
+ return null;
3047
+ }
3048
+ const id = getRelationID2(value);
3049
+ if (id === null) {
3050
+ return null;
3051
+ }
3052
+ const filename = typeof value.filename === "string" ? value.filename : "";
3053
+ const url = typeof value.url === "string" && value.url.length > 0 ? value.url : filename ? `/api/media/file/${encodeURIComponent(filename)}` : "";
3054
+ return {
3055
+ alt: typeof value.alt === "string" ? value.alt : "",
3056
+ filename,
3057
+ id,
3058
+ url
3059
+ };
3060
+ };
3061
+ var mediaFromImageURL = (url, fallbackLabel) => {
3062
+ if (typeof url !== "string" || url.trim().length === 0) {
3063
+ return null;
3064
+ }
3065
+ const normalizedURL = url.trim();
3066
+ const filename = normalizedURL.split("/").filter(Boolean).pop() || fallbackLabel;
3067
+ return {
3068
+ alt: fallbackLabel,
3069
+ filename,
3070
+ id: `url:${normalizedURL}`,
3071
+ url: normalizedURL
3072
+ };
3073
+ };
3074
+ var mediaLabel2 = (item) => item.filename || item.alt || `Media #${item.id}`;
3075
+ var findMediaLibraryItem2 = (library, id) => {
3076
+ if (id === null) {
3077
+ return null;
3078
+ }
3079
+ return library.find((item) => String(item.id) === String(id)) || null;
3080
+ };
3081
+ var normalizeImageFit = (value) => value === "contain" ? "contain" : "cover";
3082
+ var normalizeImageCornerStyle = (value) => value === "square" ? "square" : "rounded";
3083
+ var getItemMediaSettings = (item) => {
3084
+ const settings = isRecord5(item.settings) ? item.settings : {};
3085
+ const media = isRecord5(settings.media) ? settings.media : {};
3086
+ return {
3087
+ cornerStyle: normalizeImageCornerStyle(media.cornerStyle ?? item.imageCornerStyle),
3088
+ fit: normalizeImageFit(media.fit ?? item.imageFit),
3089
+ height: (() => {
3090
+ const value = media.height ?? item.imageHeight;
3091
+ if (typeof value === "number" && Number.isFinite(value)) {
3092
+ return value;
3093
+ }
3094
+ if (typeof value === "string" && value.trim().length > 0) {
3095
+ const parsed = Number(value);
3096
+ return Number.isFinite(parsed) ? parsed : null;
3097
+ }
3098
+ return null;
3099
+ })(),
3100
+ positionX: clamp(normalizeNumber2(media.positionX ?? item.imagePositionX, 50), 0, 100),
3101
+ positionY: clamp(normalizeNumber2(media.positionY ?? item.imagePositionY, 50), 0, 100)
3102
+ };
3103
+ };
2848
3104
  var hasQueryMatch = (query, ...values) => {
2849
3105
  const normalized = query.trim().toLowerCase();
2850
3106
  if (!normalized) {
@@ -2891,18 +3147,148 @@ var bulletsToTextareaValue = (value) => {
2891
3147
  return value.map((item) => isRecord5(item) && typeof item.label === "string" ? item.label.trim() : "").filter(Boolean).join("\n");
2892
3148
  };
2893
3149
  var textareaValueToBullets = (value) => value.split("\n").map((line) => line.trim()).filter(Boolean).map((label) => ({ label }));
3150
+ function ItemMediaControl({
3151
+ fieldName,
3152
+ imageURLFieldName,
3153
+ item,
3154
+ itemIndex,
3155
+ label,
3156
+ mediaLibrary,
3157
+ mediaLibraryError,
3158
+ mediaLibraryLoading,
3159
+ maxHeight,
3160
+ minHeight,
3161
+ onRemoveItemMedia,
3162
+ onSelectItemMedia,
3163
+ onUpdateItemField,
3164
+ onUpdateItemMediaPresentation,
3165
+ onUploadItemMedia,
3166
+ searchQuery,
3167
+ uploadDisabled,
3168
+ uploadLabel,
3169
+ uploading
3170
+ }) {
3171
+ const directImageURL = normalizeText(item[imageURLFieldName]);
3172
+ const selectedRelationMedia = toMediaLibraryItem2(item[fieldName]) ?? mediaFromImageURL(directImageURL, label);
3173
+ const selectedMediaID = getRelationID2(item[fieldName]) ?? selectedRelationMedia?.id ?? null;
3174
+ const selectedMedia = selectedRelationMedia ?? findMediaLibraryItem2(mediaLibrary, selectedMediaID);
3175
+ const previewURL = selectedMedia?.url || directImageURL;
3176
+ const mediaSettings = getItemMediaSettings(item);
3177
+ const sourceOptions = selectedMedia && !mediaLibrary.some((libraryItem) => String(libraryItem.id) === String(selectedMedia.id)) ? [selectedMedia, ...mediaLibrary] : mediaLibrary;
3178
+ if (!hasQueryMatch(searchQuery, label, "image", "media", "photo", "picture", "url", "fit", "crop", "height")) {
3179
+ return null;
3180
+ }
3181
+ return /* @__PURE__ */ jsxs11("div", { className: "orion-builder-settings-item-card", style: { padding: "0.56rem" }, children: [
3182
+ /* @__PURE__ */ jsx12("div", { className: "orion-builder-settings-label", children: label }),
3183
+ previewURL ? (
3184
+ // eslint-disable-next-line @next/next/no-img-element
3185
+ /* @__PURE__ */ jsx12(
3186
+ "img",
3187
+ {
3188
+ alt: selectedMedia?.alt || label,
3189
+ src: previewURL,
3190
+ style: {
3191
+ aspectRatio: "16 / 9",
3192
+ border: "1px solid rgba(35, 51, 82, 0.14)",
3193
+ borderRadius: mediaSettings.cornerStyle === "square" ? 4 : 10,
3194
+ display: "block",
3195
+ objectFit: mediaSettings.fit,
3196
+ objectPosition: `${mediaSettings.positionX}% ${mediaSettings.positionY}%`,
3197
+ width: "100%"
3198
+ }
3199
+ }
3200
+ )
3201
+ ) : /* @__PURE__ */ jsx12("div", { className: "orion-builder-settings-empty", children: "No image selected." }),
3202
+ mediaLibraryLoading ? /* @__PURE__ */ jsx12("div", { className: "orion-builder-settings-note", children: "Loading media library..." }) : null,
3203
+ mediaLibraryError ? /* @__PURE__ */ jsx12("div", { className: "orion-builder-settings-error", children: mediaLibraryError }) : null,
3204
+ /* @__PURE__ */ jsxs11("label", { className: "orion-builder-settings-label", children: [
3205
+ "Media Library Image",
3206
+ /* @__PURE__ */ jsxs11(
3207
+ "select",
3208
+ {
3209
+ className: "orion-builder-settings-input",
3210
+ onChange: (event) => onSelectItemMedia?.(itemIndex, fieldName, event.target.value),
3211
+ value: selectedMediaID !== null ? String(selectedMediaID) : "",
3212
+ children: [
3213
+ /* @__PURE__ */ jsx12("option", { value: "", children: "No image" }),
3214
+ sourceOptions.map((libraryItem) => /* @__PURE__ */ jsx12("option", { value: String(libraryItem.id), children: mediaLabel2(libraryItem) }, String(libraryItem.id)))
3215
+ ]
3216
+ }
3217
+ )
3218
+ ] }),
3219
+ selectedMedia?.alt ? /* @__PURE__ */ jsxs11("label", { className: "orion-builder-settings-label", children: [
3220
+ "Media Description",
3221
+ /* @__PURE__ */ jsx12("input", { className: "orion-builder-settings-input", readOnly: true, type: "text", value: selectedMedia.alt })
3222
+ ] }) : selectedMediaID !== null ? /* @__PURE__ */ jsx12("div", { className: "orion-builder-settings-note", children: "This media item does not have a description yet." }) : null,
3223
+ /* @__PURE__ */ jsx12(
3224
+ "button",
3225
+ {
3226
+ className: "orion-builder-settings-inline-btn",
3227
+ disabled: selectedMediaID === null,
3228
+ onClick: () => {
3229
+ onRemoveItemMedia?.(itemIndex, fieldName);
3230
+ onUpdateItemField(itemIndex, imageURLFieldName, "");
3231
+ },
3232
+ type: "button",
3233
+ children: "Remove Image"
3234
+ }
3235
+ ),
3236
+ /* @__PURE__ */ jsxs11("label", { className: "orion-builder-settings-label", children: [
3237
+ uploadLabel,
3238
+ /* @__PURE__ */ jsx12(
3239
+ "input",
3240
+ {
3241
+ accept: "image/*",
3242
+ className: "orion-builder-settings-input",
3243
+ disabled: uploadDisabled,
3244
+ onChange: (event) => {
3245
+ const file = event.currentTarget.files?.[0];
3246
+ if (file) {
3247
+ onUploadItemMedia?.(itemIndex, fieldName, file);
3248
+ }
3249
+ event.currentTarget.value = "";
3250
+ },
3251
+ type: "file"
3252
+ }
3253
+ )
3254
+ ] }),
3255
+ uploading ? /* @__PURE__ */ jsx12("div", { className: "orion-builder-settings-note", children: "Uploading image..." }) : null,
3256
+ /* @__PURE__ */ jsx12(
3257
+ ImageControls,
3258
+ {
3259
+ cornerStyle: mediaSettings.cornerStyle,
3260
+ fit: mediaSettings.fit,
3261
+ height: mediaSettings.height,
3262
+ maxHeight,
3263
+ minHeight,
3264
+ onChange: (field, value) => onUpdateItemMediaPresentation?.(itemIndex, field, value),
3265
+ positionX: mediaSettings.positionX,
3266
+ positionY: mediaSettings.positionY
3267
+ }
3268
+ )
3269
+ ] });
3270
+ }
2894
3271
  function ArrayItemsEditor({
2895
3272
  blockType,
2896
3273
  expandedItemIndex,
2897
3274
  items,
3275
+ mediaLibrary = [],
3276
+ mediaLibraryError = "",
3277
+ mediaLibraryLoading = false,
2898
3278
  mode,
2899
3279
  onAddItem,
3280
+ onRemoveItemMedia,
2900
3281
  onRemoveItem,
3282
+ onSelectItemMedia,
2901
3283
  onToggleItem,
2902
3284
  onUpdateItemField,
3285
+ onUpdateItemMediaPresentation,
2903
3286
  onUpdateItemSetting,
3287
+ onUploadItemMedia,
2904
3288
  searchQuery,
2905
- showInlineCopyFields
3289
+ showInlineCopyFields,
3290
+ uploadDisabled = false,
3291
+ isItemMediaUploading
2906
3292
  }) {
2907
3293
  const config = blockConfig[blockType];
2908
3294
  const normalizedQuery = searchQuery.trim().toLowerCase();
@@ -3052,11 +3438,30 @@ function ArrayItemsEditor({
3052
3438
  }
3053
3439
  )
3054
3440
  ] }) : null,
3055
- /* @__PURE__ */ jsxs11("div", { className: "orion-builder-settings-note", children: [
3056
- "Select this item and use the ",
3057
- /* @__PURE__ */ jsx12("strong", { children: "Media" }),
3058
- " group above for image source and presentation."
3059
- ] })
3441
+ /* @__PURE__ */ jsx12(
3442
+ ItemMediaControl,
3443
+ {
3444
+ fieldName: "media",
3445
+ imageURLFieldName: "imageURL",
3446
+ item,
3447
+ itemIndex,
3448
+ label: "Feature Image",
3449
+ maxHeight: 600,
3450
+ mediaLibrary,
3451
+ mediaLibraryError,
3452
+ mediaLibraryLoading,
3453
+ minHeight: 40,
3454
+ onRemoveItemMedia,
3455
+ onSelectItemMedia,
3456
+ onUpdateItemField,
3457
+ onUpdateItemMediaPresentation,
3458
+ onUploadItemMedia,
3459
+ searchQuery: normalizedQuery,
3460
+ uploadDisabled,
3461
+ uploadLabel: "Upload Feature Image",
3462
+ uploading: Boolean(isItemMediaUploading?.(itemIndex, "media"))
3463
+ }
3464
+ )
3060
3465
  ] }) : null,
3061
3466
  blockType === "logoWall" ? /* @__PURE__ */ jsxs11(Fragment4, { children: [
3062
3467
  showInlineCopyFields ? /* @__PURE__ */ jsxs11("label", { className: "orion-builder-settings-label", children: [
@@ -3083,11 +3488,30 @@ function ArrayItemsEditor({
3083
3488
  }
3084
3489
  )
3085
3490
  ] }) : null,
3086
- /* @__PURE__ */ jsxs11("div", { className: "orion-builder-settings-note", children: [
3087
- "Select this item and use the ",
3088
- /* @__PURE__ */ jsx12("strong", { children: "Media" }),
3089
- " group above for image source and presentation."
3090
- ] })
3491
+ /* @__PURE__ */ jsx12(
3492
+ ItemMediaControl,
3493
+ {
3494
+ fieldName: "media",
3495
+ imageURLFieldName: "imageURL",
3496
+ item,
3497
+ itemIndex,
3498
+ label: "Logo Image",
3499
+ maxHeight: 200,
3500
+ mediaLibrary,
3501
+ mediaLibraryError,
3502
+ mediaLibraryLoading,
3503
+ minHeight: 24,
3504
+ onRemoveItemMedia,
3505
+ onSelectItemMedia,
3506
+ onUpdateItemField,
3507
+ onUpdateItemMediaPresentation,
3508
+ onUploadItemMedia,
3509
+ searchQuery: normalizedQuery,
3510
+ uploadDisabled,
3511
+ uploadLabel: "Upload Logo Image",
3512
+ uploading: Boolean(isItemMediaUploading?.(itemIndex, "media"))
3513
+ }
3514
+ )
3091
3515
  ] }) : null,
3092
3516
  blockType === "beforeAfter" ? /* @__PURE__ */ jsxs11(Fragment4, { children: [
3093
3517
  showInlineCopyFields ? /* @__PURE__ */ jsxs11(Fragment4, { children: [
@@ -3115,11 +3539,54 @@ function ArrayItemsEditor({
3115
3539
  )
3116
3540
  ] })
3117
3541
  ] }) : null,
3118
- /* @__PURE__ */ jsxs11("div", { className: "orion-builder-settings-note", children: [
3119
- "Select this item and use the ",
3120
- /* @__PURE__ */ jsx12("strong", { children: "Media" }),
3121
- " group above for before/after image source and presentation."
3122
- ] })
3542
+ /* @__PURE__ */ jsx12(
3543
+ ItemMediaControl,
3544
+ {
3545
+ fieldName: "beforeMedia",
3546
+ imageURLFieldName: "beforeImageURL",
3547
+ item,
3548
+ itemIndex,
3549
+ label: "Before Image",
3550
+ maxHeight: 600,
3551
+ mediaLibrary,
3552
+ mediaLibraryError,
3553
+ mediaLibraryLoading,
3554
+ minHeight: 60,
3555
+ onRemoveItemMedia,
3556
+ onSelectItemMedia,
3557
+ onUpdateItemField,
3558
+ onUpdateItemMediaPresentation,
3559
+ onUploadItemMedia,
3560
+ searchQuery: normalizedQuery,
3561
+ uploadDisabled,
3562
+ uploadLabel: "Upload Before Image",
3563
+ uploading: Boolean(isItemMediaUploading?.(itemIndex, "beforeMedia"))
3564
+ }
3565
+ ),
3566
+ /* @__PURE__ */ jsx12(
3567
+ ItemMediaControl,
3568
+ {
3569
+ fieldName: "afterMedia",
3570
+ imageURLFieldName: "afterImageURL",
3571
+ item,
3572
+ itemIndex,
3573
+ label: "After Image",
3574
+ maxHeight: 600,
3575
+ mediaLibrary,
3576
+ mediaLibraryError,
3577
+ mediaLibraryLoading,
3578
+ minHeight: 60,
3579
+ onRemoveItemMedia,
3580
+ onSelectItemMedia,
3581
+ onUpdateItemField,
3582
+ onUpdateItemMediaPresentation,
3583
+ onUploadItemMedia,
3584
+ searchQuery: normalizedQuery,
3585
+ uploadDisabled,
3586
+ uploadLabel: "Upload After Image",
3587
+ uploading: Boolean(isItemMediaUploading?.(itemIndex, "afterMedia"))
3588
+ }
3589
+ )
3123
3590
  ] }) : null,
3124
3591
  blockType === "stats" ? /* @__PURE__ */ jsx12(Fragment4, { children: showInlineCopyFields ? /* @__PURE__ */ jsxs11(Fragment4, { children: [
3125
3592
  /* @__PURE__ */ jsxs11("label", { className: "orion-builder-settings-label", children: [
@@ -3284,6 +3751,19 @@ var resolveMedia = (value) => {
3284
3751
  }
3285
3752
  return null;
3286
3753
  };
3754
+ var mediaFromImageURL2 = (url, fallbackLabel = "Current image") => {
3755
+ if (typeof url !== "string" || url.trim().length === 0) {
3756
+ return null;
3757
+ }
3758
+ const normalizedURL = url.trim();
3759
+ const filename = normalizedURL.split("/").filter(Boolean).pop() || fallbackLabel;
3760
+ return {
3761
+ alt: fallbackLabel,
3762
+ filename,
3763
+ id: `url:${normalizedURL}`,
3764
+ url: normalizedURL
3765
+ };
3766
+ };
3287
3767
  var resolveMediaWithURL = (value, imageURL, alt) => {
3288
3768
  const resolved = resolveMedia(value);
3289
3769
  if (resolved?.url) {
@@ -3325,8 +3805,8 @@ var resolveBuilderMediumHeroHeight = (topViewportHeight) => {
3325
3805
  }
3326
3806
  return "50svh";
3327
3807
  };
3328
- var normalizeImageFit = (value) => normalizeHeroImageFit(value);
3329
- var normalizeImageCornerStyle = (value, legacyFitValue) => normalizeHeroImageCornerStyle(value, legacyFitValue);
3808
+ var normalizeImageFit2 = (value) => normalizeHeroImageFit(value);
3809
+ var normalizeImageCornerStyle2 = (value, legacyFitValue) => normalizeHeroImageCornerStyle(value, legacyFitValue);
3330
3810
  var positionPercent = (value, fit) => {
3331
3811
  const resolved = fit === "cover" && (value === "left" || value === "right") ? "center" : value;
3332
3812
  switch (resolved) {
@@ -3495,6 +3975,8 @@ var sectionPaddingMap = {
3495
3975
  md: "2.6rem",
3496
3976
  lg: "3.4rem"
3497
3977
  };
3978
+ var heroDefaultPaddingTop = "30pt";
3979
+ var heroDefaultPaddingBottom = "20pt";
3498
3980
  var quickAddBlockTypes = [
3499
3981
  "hero",
3500
3982
  "featureGrid",
@@ -3758,6 +4240,12 @@ function getThemeColorOverride(tokens, colorKey) {
3758
4240
  const normalized = value.trim();
3759
4241
  return normalized.length > 0 ? normalized : null;
3760
4242
  }
4243
+ function normalizeCustomClassName(value) {
4244
+ if (typeof value !== "string") {
4245
+ return "";
4246
+ }
4247
+ return value.split(/\s+/).map((className) => className.trim()).filter(Boolean).join(" ");
4248
+ }
3761
4249
  var sectionStyleFromBlock = (block, pageDefaults) => {
3762
4250
  const settings = isRecord6(block.settings) ? block.settings : {};
3763
4251
  const layoutSettings = isRecord6(settings.layout) ? settings.layout : {};
@@ -3843,15 +4331,15 @@ var sectionStyleFromBlock = (block, pageDefaults) => {
3843
4331
  } : {},
3844
4332
  sectionClass: `orion-builder-shell is-${pageDefaults.pageWidthDefault} padx-${resolvedSectionPaddingX}`,
3845
4333
  sectionInnerStyle: {
3846
- paddingBottom: customPaddingBottom === null ? sectionPaddingMap[sectionPaddingY] : `${customPaddingBottom}pt`,
4334
+ paddingBottom: customPaddingBottom === null ? block.blockType === "hero" ? heroDefaultPaddingBottom : sectionPaddingMap[sectionPaddingY] : `${customPaddingBottom}pt`,
3847
4335
  paddingLeft: customPaddingLeft === null ? void 0 : `${customPaddingLeft}pt`,
3848
4336
  paddingRight: customPaddingRight === null ? void 0 : `${customPaddingRight}pt`,
3849
- paddingTop: customPaddingTop === null ? sectionPaddingMap[sectionPaddingY] : `${customPaddingTop}pt`
4337
+ paddingTop: customPaddingTop === null ? block.blockType === "hero" ? heroDefaultPaddingTop : sectionPaddingMap[sectionPaddingY] : `${customPaddingTop}pt`
3850
4338
  },
3851
4339
  sectionStyle: sectionMode === "color" ? { background: sectionColor } : sectionMode === "gradient" ? { background: sectionGradient } : block.blockType === "hero" ? { background: "transparent" } : {}
3852
4340
  };
3853
4341
  };
3854
- function getRelationID2(value) {
4342
+ function getRelationID3(value) {
3855
4343
  if (typeof value === "number" || typeof value === "string") {
3856
4344
  return value;
3857
4345
  }
@@ -3884,7 +4372,7 @@ function extractUploadedMedia(value) {
3884
4372
  if (!candidate || typeof candidate !== "object") {
3885
4373
  return null;
3886
4374
  }
3887
- const id = getRelationID2(candidate);
4375
+ const id = getRelationID3(candidate);
3888
4376
  if (id === null) {
3889
4377
  return null;
3890
4378
  }
@@ -3895,11 +4383,11 @@ function extractUploadedMedia(value) {
3895
4383
  url: typeof candidate.url === "string" ? candidate.url : ""
3896
4384
  };
3897
4385
  }
3898
- function toMediaLibraryItem2(value) {
4386
+ function toMediaLibraryItem3(value) {
3899
4387
  if (!value || typeof value !== "object") {
3900
4388
  return null;
3901
4389
  }
3902
- const id = getRelationID2(value);
4390
+ const id = getRelationID3(value);
3903
4391
  if (id === null) {
3904
4392
  return null;
3905
4393
  }
@@ -4032,7 +4520,7 @@ function BuilderPageEditor({
4032
4520
  const selectedBlockAdvancedSettings = isRecord6(selectedBlockSettings.advanced) ? selectedBlockSettings.advanced : {};
4033
4521
  const isArrayItemBlockSelected = selectedType === "featureGrid" || selectedType === "logoWall" || selectedType === "beforeAfter" || selectedType === "stats" || selectedType === "faq" || selectedType === "testimonials";
4034
4522
  const selectedBlockHasMediaSource = selectedType === "hero" || selectedType === "media";
4035
- const selectedBlockMediaValue = selectedType === "hero" ? selectedBlock?.media : selectedType === "media" ? selectedBlock?.image : null;
4523
+ const selectedBlockMediaValue = selectedType === "hero" ? selectedBlock?.media ?? mediaFromImageURL2(selectedBlock?.backgroundImageURL, "Hero image") : selectedType === "media" ? selectedBlock?.image ?? mediaFromImageURL2(selectedBlock?.imageURL, "Section image") : null;
4036
4524
  const selectedItemRecord = typeof selectedItemIndex === "number" && selectedItemIndex >= 0 && selectedItemIndex < selectedItems.length && isRecord6(selectedItems[selectedItemIndex]) ? selectedItems[selectedItemIndex] : null;
4037
4525
  const editCopyInPanelEnabled = Boolean(selectedBlockAdvancedSettings.editCopyInPanel);
4038
4526
  const isBlockUploadTarget = (blockIndex, kind) => selectedIndex === blockIndex && uploadingTarget?.kind === kind;
@@ -4077,7 +4565,7 @@ function BuilderPageEditor({
4077
4565
  }
4078
4566
  const json = await response.json();
4079
4567
  const docs = Array.isArray(json.docs) ? json.docs : [];
4080
- const items = docs.map((doc2) => toMediaLibraryItem2(doc2)).filter((item) => item !== null);
4568
+ const items = docs.map((doc2) => toMediaLibraryItem3(doc2)).filter((item) => item !== null);
4081
4569
  setMediaLibrary(items);
4082
4570
  } catch (error) {
4083
4571
  setMediaLibraryError(error instanceof Error ? error.message : "Could not load media library.");
@@ -4431,7 +4919,7 @@ function BuilderPageEditor({
4431
4919
  const nextLayout = cloneBlockLayout(layout);
4432
4920
  const block = nextLayout[selectedIndex];
4433
4921
  if (target.kind === "hero") {
4434
- const uploadedItem = toMediaLibraryItem2(uploaded);
4922
+ const uploadedItem = toMediaLibraryItem3(uploaded);
4435
4923
  nextLayout[selectedIndex] = {
4436
4924
  ...block,
4437
4925
  backgroundImageURL: uploadedItem?.url || normalizeText2(uploaded.url),
@@ -4495,13 +4983,13 @@ function BuilderPageEditor({
4495
4983
  const nextBlock = { ...migrateBlockToSettingsV2(block) };
4496
4984
  const blockType = normalizeText2(nextBlock.blockType);
4497
4985
  if (blockType === "hero") {
4498
- const mediaID = getRelationID2(nextBlock.media);
4986
+ const mediaID = getRelationID3(nextBlock.media);
4499
4987
  if (mediaID !== null) {
4500
4988
  nextBlock.media = mediaID;
4501
4989
  }
4502
4990
  }
4503
4991
  if (blockType === "media") {
4504
- const imageID = getRelationID2(nextBlock.image);
4992
+ const imageID = getRelationID3(nextBlock.image);
4505
4993
  if (imageID !== null) {
4506
4994
  nextBlock.image = imageID;
4507
4995
  }
@@ -4513,15 +5001,15 @@ function BuilderPageEditor({
4513
5001
  return rawItem;
4514
5002
  }
4515
5003
  const nextItem = { ...rawItem };
4516
- const mediaID = getRelationID2(nextItem.media);
5004
+ const mediaID = getRelationID3(nextItem.media);
4517
5005
  if (mediaID !== null) {
4518
5006
  nextItem.media = mediaID;
4519
5007
  }
4520
- const beforeMediaID = getRelationID2(nextItem.beforeMedia);
5008
+ const beforeMediaID = getRelationID3(nextItem.beforeMedia);
4521
5009
  if (beforeMediaID !== null) {
4522
5010
  nextItem.beforeMedia = beforeMediaID;
4523
5011
  }
4524
- const afterMediaID = getRelationID2(nextItem.afterMedia);
5012
+ const afterMediaID = getRelationID3(nextItem.afterMedia);
4525
5013
  if (afterMediaID !== null) {
4526
5014
  nextItem.afterMedia = afterMediaID;
4527
5015
  }
@@ -4577,6 +5065,7 @@ function BuilderPageEditor({
4577
5065
  const inheritProjectStyles = options?.inheritProjectStyles === true;
4578
5066
  const shell = sectionStyleFromBlock(block, pageDefaults);
4579
5067
  const blockSettings = isRecord6(block.settings) ? block.settings : {};
5068
+ const blockAdvanced = isRecord6(blockSettings.advanced) ? blockSettings.advanced : {};
4580
5069
  const blockTypography = isRecord6(blockSettings.typography) ? blockSettings.typography : {};
4581
5070
  const blockTheme = isRecord6(blockSettings.theme) ? blockSettings.theme : {};
4582
5071
  const heroBackgroundColor = normalizeText2(block.backgroundColor).trim();
@@ -4584,23 +5073,35 @@ function BuilderPageEditor({
4584
5073
  const heroMedia = block.blockType === "hero" ? resolveMedia(block.media) : null;
4585
5074
  const heroHasImage = block.blockType === "hero" && Boolean(heroBackgroundImageURL || heroMedia?.url);
4586
5075
  const heroTextColor = block.blockType === "hero" ? heroHasImage ? "#ffffff" : heroBackgroundColor ? getReadableTextColor(heroBackgroundColor, resolvedThemeTokens.colors.headingText, "#ffffff") : resolvedThemeTokens.colors.headingText : null;
5076
+ const bodyAlign = blockTypography.bodyAlign === "center" || blockTypography.bodyAlign === "justify" || blockTypography.bodyAlign === "right" ? blockTypography.bodyAlign : "left";
4587
5077
  const typographyStyle = resolveTypographyStyleFromSettings({
4588
- bodyAlign: blockTypography.bodyAlign === "center" || blockTypography.bodyAlign === "justify" || blockTypography.bodyAlign === "right" ? blockTypography.bodyAlign : "left",
5078
+ bodyAlign,
4589
5079
  letterSpacingPreset: blockTypography.letterSpacingPreset === "tight" || blockTypography.letterSpacingPreset === "relaxed" ? blockTypography.letterSpacingPreset : "normal",
4590
5080
  lineHeightPreset: blockTypography.lineHeightPreset === "tight" || blockTypography.lineHeightPreset === "relaxed" ? blockTypography.lineHeightPreset : "normal",
5081
+ bodySizePt: typeof blockTypography.bodySizePt === "number" && Number.isFinite(blockTypography.bodySizePt) ? blockTypography.bodySizePt : null,
4591
5082
  maxTextWidth: blockTypography.maxTextWidth === "sm" || blockTypography.maxTextWidth === "md" || blockTypography.maxTextWidth === "lg" || blockTypography.maxTextWidth === "full" ? blockTypography.maxTextWidth : "auto"
4592
5083
  });
4593
5084
  const headingAlign = blockTypography.headingAlign === "center" || blockTypography.headingAlign === "justify" || blockTypography.headingAlign === "right" ? blockTypography.headingAlign : "left";
4594
5085
  const headingColor = getThemeColorOverride(blockTheme, "headingText") || getThemeColorOverride(pageDefaults.themePage, "headingText") || getThemeColorOverride(siteThemeTokens, "headingText") || heroTextColor || resolvedThemeTokens.colors.headingText;
4595
5086
  const bodyColor = getThemeColorOverride(blockTheme, "bodyText") || getThemeColorOverride(pageDefaults.themePage, "bodyText") || getThemeColorOverride(siteThemeTokens, "bodyText") || heroTextColor || resolvedThemeTokens.colors.bodyText;
4596
- return /* @__PURE__ */ jsx13("section", { className: `${className} ${shell.sectionClass}`, style: shell.sectionStyle, children: /* @__PURE__ */ jsx13("div", { style: shell.sectionInnerStyle, children: /* @__PURE__ */ jsx13(
5087
+ const customClassName = normalizeCustomClassName(blockAdvanced.customClassName ?? block.customClassName);
5088
+ const hideOnMobile = Boolean(blockAdvanced.hideOnMobile ?? block.hideOnMobile);
5089
+ const sectionClassName = [
5090
+ className,
5091
+ shell.sectionClass,
5092
+ customClassName,
5093
+ hideOnMobile ? "orion-builder-hide-mobile" : ""
5094
+ ].filter(Boolean).join(" ");
5095
+ return /* @__PURE__ */ jsx13("section", { className: sectionClassName, style: shell.sectionStyle, children: /* @__PURE__ */ jsx13("div", { style: shell.sectionInnerStyle, children: /* @__PURE__ */ jsx13(
4597
5096
  "div",
4598
5097
  {
4599
5098
  className: shell.contentClass,
4600
5099
  style: {
4601
5100
  ...shell.contentStyle,
5101
+ "--orion-builder-heading-align": headingAlign,
5102
+ "--orion-builder-body-align": bodyAlign,
5103
+ "--orion-builder-actions-align": bodyAlign === "center" ? "center" : bodyAlign === "right" ? "flex-end" : "flex-start",
4602
5104
  ...inheritProjectStyles ? {} : {
4603
- "--orion-builder-heading-align": headingAlign,
4604
5105
  "--orion-builder-heading-color": headingColor,
4605
5106
  color: bodyColor,
4606
5107
  ...typographyStyle
@@ -5087,8 +5588,8 @@ function BuilderPageEditor({
5087
5588
  }
5088
5589
  ] : [];
5089
5590
  const selectedMediaImageControls = selectedItemRecord && typeof selectedItemIndex === "number" && (selectedType === "featureGrid" || selectedType === "logoWall" || selectedType === "beforeAfter") ? {
5090
- cornerStyle: normalizeImageCornerStyle(selectedItemRecord.imageCornerStyle),
5091
- fit: normalizeImageFit(selectedItemRecord.imageFit),
5591
+ cornerStyle: normalizeImageCornerStyle2(selectedItemRecord.imageCornerStyle),
5592
+ fit: normalizeImageFit2(selectedItemRecord.imageFit),
5092
5593
  height: (() => {
5093
5594
  if (typeof selectedItemRecord.imageHeight === "number" && Number.isFinite(selectedItemRecord.imageHeight)) {
5094
5595
  return selectedItemRecord.imageHeight;
@@ -5563,8 +6064,8 @@ function BuilderPageEditor({
5563
6064
  const itemPositionX = parseOptionalPercentNumber2(itemRecord?.imagePositionX);
5564
6065
  const itemPositionY = parseOptionalPercentNumber2(itemRecord?.imagePositionY);
5565
6066
  const itemImageStyle = getImagePresentationStyle({
5566
- cornerStyle: normalizeImageCornerStyle(itemRecord?.imageCornerStyle),
5567
- fit: normalizeImageFit(itemRecord?.imageFit),
6067
+ cornerStyle: normalizeImageCornerStyle2(itemRecord?.imageCornerStyle),
6068
+ fit: normalizeImageFit2(itemRecord?.imageFit),
5568
6069
  positionX: itemPositionX,
5569
6070
  positionY: itemPositionY
5570
6071
  });
@@ -5681,8 +6182,8 @@ function BuilderPageEditor({
5681
6182
  const itemPositionX = parseOptionalPercentNumber2(itemRecord?.imagePositionX);
5682
6183
  const itemPositionY = parseOptionalPercentNumber2(itemRecord?.imagePositionY);
5683
6184
  const itemImageStyle = getImagePresentationStyle({
5684
- cornerStyle: normalizeImageCornerStyle(itemRecord?.imageCornerStyle),
5685
- fit: normalizeImageFit(itemRecord?.imageFit),
6185
+ cornerStyle: normalizeImageCornerStyle2(itemRecord?.imageCornerStyle),
6186
+ fit: normalizeImageFit2(itemRecord?.imageFit),
5686
6187
  positionX: itemPositionX,
5687
6188
  positionY: itemPositionY
5688
6189
  });
@@ -5888,8 +6389,8 @@ function BuilderPageEditor({
5888
6389
  const itemPositionX = parseOptionalPercentNumber2(itemRecord?.imagePositionX);
5889
6390
  const itemPositionY = parseOptionalPercentNumber2(itemRecord?.imagePositionY);
5890
6391
  const imageStyle = getImagePresentationStyle({
5891
- cornerStyle: normalizeImageCornerStyle(itemRecord?.imageCornerStyle),
5892
- fit: normalizeImageFit(itemRecord?.imageFit),
6392
+ cornerStyle: normalizeImageCornerStyle2(itemRecord?.imageCornerStyle),
6393
+ fit: normalizeImageFit2(itemRecord?.imageFit),
5893
6394
  positionX: itemPositionX,
5894
6395
  positionY: itemPositionY,
5895
6396
  roundedRadius: 10
@@ -6002,8 +6503,8 @@ function BuilderPageEditor({
6002
6503
  const itemPositionX = parseOptionalPercentNumber2(itemRecord?.imagePositionX);
6003
6504
  const itemPositionY = parseOptionalPercentNumber2(itemRecord?.imagePositionY);
6004
6505
  const imageStyle = getImagePresentationStyle({
6005
- cornerStyle: normalizeImageCornerStyle(itemRecord?.imageCornerStyle),
6006
- fit: normalizeImageFit(itemRecord?.imageFit),
6506
+ cornerStyle: normalizeImageCornerStyle2(itemRecord?.imageCornerStyle),
6507
+ fit: normalizeImageFit2(itemRecord?.imageFit),
6007
6508
  positionX: itemPositionX,
6008
6509
  positionY: itemPositionY
6009
6510
  });
@@ -6309,8 +6810,8 @@ function BuilderPageEditor({
6309
6810
  getImagePresentationStyle,
6310
6811
  index,
6311
6812
  isBlockUploadTarget,
6312
- normalizeImageCornerStyle,
6313
- normalizeImageFit,
6813
+ normalizeImageCornerStyle: normalizeImageCornerStyle2,
6814
+ normalizeImageFit: normalizeImageFit2,
6314
6815
  normalizeText: normalizeText2,
6315
6816
  onDropAt,
6316
6817
  renderWithSectionShell,
@@ -6539,23 +7040,32 @@ function BuilderPageEditor({
6539
7040
  blockType: selectedType,
6540
7041
  expandedItemIndex,
6541
7042
  items: selectedItems,
7043
+ isItemMediaUploading: isSelectedItemMediaUploading,
7044
+ mediaLibrary,
7045
+ mediaLibraryError,
7046
+ mediaLibraryLoading,
6542
7047
  mode: settingsPanelMode,
6543
7048
  onAddItem: appendDefaultItemToSelected,
6544
7049
  onRemoveItem: (itemIndex) => removeItemFromSelected("items", itemIndex),
7050
+ onRemoveItemMedia: (itemIndex, fieldName) => setSelectedItemMediaFieldFromLibrary(itemIndex, fieldName, ""),
7051
+ onSelectItemMedia: (itemIndex, fieldName, mediaID) => setSelectedItemMediaFieldFromLibrary(itemIndex, fieldName, mediaID),
6545
7052
  onToggleItem: toggleSelectedItem,
6546
7053
  onUpdateItemField: (itemIndex, fieldName, value) => updateArrayItemField(selectedIndex ?? 0, "items", itemIndex, fieldName, value),
7054
+ onUpdateItemMediaPresentation: (itemIndex, fieldName, value) => updateArrayItemSettingField(selectedIndex ?? 0, "items", itemIndex, `media.${fieldName}`, value),
6547
7055
  onUpdateItemSetting: (itemIndex, path, value) => updateArrayItemSettingField(selectedIndex ?? 0, "items", itemIndex, path, value),
7056
+ onUploadItemMedia: uploadItemMediaFromV2,
6548
7057
  searchQuery: settingsSearchQuery,
6549
- showInlineCopyFields: editCopyInPanelEnabled
7058
+ showInlineCopyFields: editCopyInPanelEnabled,
7059
+ uploadDisabled: uploadingTarget !== null
6550
7060
  }
6551
7061
  ) : null,
6552
7062
  /* @__PURE__ */ jsxs12("label", { style: sidebarLabelStyle, children: [
6553
- "Upload Alt Text",
7063
+ "New Upload Alt Text",
6554
7064
  /* @__PURE__ */ jsx13(
6555
7065
  "input",
6556
7066
  {
6557
7067
  onChange: (event) => setUploadAltText(event.target.value),
6558
- placeholder: "Describe the image",
7068
+ placeholder: "Used only when uploading a new image",
6559
7069
  style: sidebarInputStyle,
6560
7070
  type: "text",
6561
7071
  value: uploadAltText