@orion-studios/payload-studio 0.6.0-beta.3 → 0.6.0-beta.31

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 (36) hide show
  1. package/dist/admin/client.d.mts +1 -1
  2. package/dist/admin/client.d.ts +1 -1
  3. package/dist/admin/client.js +4160 -1732
  4. package/dist/admin/client.mjs +4240 -1818
  5. package/dist/admin/index.d.mts +2 -2
  6. package/dist/admin/index.d.ts +2 -2
  7. package/dist/admin/index.js +140 -17
  8. package/dist/admin/index.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 +705 -41
  12. package/dist/admin.css +18 -2
  13. package/dist/{chunk-PF3EBZXF.mjs → chunk-4LSIUED5.mjs} +7 -2
  14. package/dist/{chunk-XKUTZ7IU.mjs → chunk-EDW7DPXW.mjs} +1 -1
  15. package/dist/{chunk-OTHERBGX.mjs → chunk-H4GTEY24.mjs} +1 -1
  16. package/dist/{chunk-QJAWO6K3.mjs → chunk-JC3UV74N.mjs} +140 -17
  17. package/dist/index-BV0vEGl6.d.ts +188 -0
  18. package/dist/{index-52HdVLQq.d.ts → index-DAdN56fM.d.ts} +1 -1
  19. package/dist/index-DLfPOqYA.d.mts +188 -0
  20. package/dist/{index-DEQC3Dwj.d.mts → index-G_uTNffQ.d.mts} +1 -1
  21. package/dist/index.d.mts +3 -3
  22. package/dist/index.d.ts +3 -3
  23. package/dist/index.js +147 -19
  24. package/dist/index.mjs +4 -4
  25. package/dist/nextjs/index.js +7 -2
  26. package/dist/nextjs/index.mjs +2 -2
  27. package/dist/{sitePreviewTypes-BkHCWxNW.d.mts → sitePreviewTypes-BrJwGzJj.d.mts} +1 -1
  28. package/dist/{sitePreviewTypes-BkHCWxNW.d.ts → sitePreviewTypes-BrJwGzJj.d.ts} +1 -1
  29. package/dist/studio-pages/builder.css +24 -5
  30. package/dist/studio-pages/client.js +374 -54
  31. package/dist/studio-pages/client.mjs +374 -54
  32. package/dist/studio-pages/index.js +7 -2
  33. package/dist/studio-pages/index.mjs +2 -2
  34. package/package.json +1 -1
  35. package/dist/index-B6_D4Hm4.d.ts +0 -439
  36. package/dist/index-CYaWadBl.d.mts +0 -439
@@ -156,6 +156,7 @@ var defaultBuilderThemeTokens = {
156
156
 
157
157
  // src/studio-pages/builder/adapters/settingsV2.ts
158
158
  var isRecord = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
159
+ var isTextAlign = (value) => value === "left" || value === "center" || value === "right" || value === "justify";
159
160
  var parsePercent = (value) => {
160
161
  if (typeof value === "number" && Number.isFinite(value)) {
161
162
  return Math.max(0, Math.min(100, value));
@@ -198,6 +199,10 @@ var mergeSettings = (defaults, input) => {
198
199
  };
199
200
  var legacyBlockToV2Settings = (block) => {
200
201
  const current = structuredClone(defaultBuilderBlockSettingsV2);
202
+ if (block.blockType === "hero" && block.variant === "centered") {
203
+ current.typography.headingAlign = "center";
204
+ current.typography.bodyAlign = "center";
205
+ }
201
206
  current.layout.contentWidth = block.contentWidth === "narrow" || block.contentWidth === "content" || block.contentWidth === "wide" || block.contentWidth === "full" || block.contentWidth === "inherit" ? block.contentWidth : current.layout.contentWidth;
202
207
  current.layout.sectionPaddingX = block.sectionPaddingX === "none" || block.sectionPaddingX === "sm" || block.sectionPaddingX === "md" || block.sectionPaddingX === "lg" || block.sectionPaddingX === "inherit" ? block.sectionPaddingX : current.layout.sectionPaddingX;
203
208
  current.layout.sectionPaddingY = block.sectionPaddingY === "none" || block.sectionPaddingY === "sm" || block.sectionPaddingY === "lg" ? block.sectionPaddingY : current.layout.sectionPaddingY;
@@ -234,8 +239,8 @@ var legacyBlockToV2Settings = (block) => {
234
239
  current.media.positionX = parsePercent(block.imagePositionX ?? block.backgroundImagePositionX);
235
240
  current.media.positionY = parsePercent(block.imagePositionY ?? block.backgroundImagePositionY);
236
241
  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;
242
+ current.typography.headingAlign = isTextAlign(block.textHeadingAlign) ? block.textHeadingAlign : current.typography.headingAlign;
243
+ current.typography.bodyAlign = isTextAlign(block.textBodyAlign) ? block.textBodyAlign : current.typography.bodyAlign;
239
244
  current.typography.maxTextWidth = block.textMaxWidth === "auto" || block.textMaxWidth === "sm" || block.textMaxWidth === "md" || block.textMaxWidth === "lg" || block.textMaxWidth === "full" ? block.textMaxWidth : current.typography.maxTextWidth;
240
245
  current.typography.lineHeightPreset = block.textLineHeightPreset === "tight" || block.textLineHeightPreset === "normal" || block.textLineHeightPreset === "relaxed" ? block.textLineHeightPreset : current.typography.lineHeightPreset;
241
246
  current.typography.letterSpacingPreset = block.textLetterSpacingPreset === "tight" || block.textLetterSpacingPreset === "normal" || block.textLetterSpacingPreset === "relaxed" ? block.textLetterSpacingPreset : current.typography.letterSpacingPreset;
@@ -952,6 +957,12 @@ var toMediaLibraryItem = (value) => {
952
957
  };
953
958
  };
954
959
  var mediaLabel = (item) => item.filename || item.alt || `Media #${item.id}`;
960
+ var findMediaLibraryItem = (library, id) => {
961
+ if (id === null) {
962
+ return null;
963
+ }
964
+ return library.find((item) => String(item.id) === String(id)) || null;
965
+ };
955
966
  var groupLabel = (key) => commonInspectorGroups.find((group) => group.key === key)?.label || key;
956
967
  function BlockInspectorRenderer({
957
968
  block,
@@ -1075,8 +1086,9 @@ function BlockInspectorRenderer({
1075
1086
  title: group.label,
1076
1087
  children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "orion-builder-settings-field-list", children: [
1077
1088
  group.key === "media" ? effectiveMediaSources.map((source) => {
1078
- const selectedSourceMedia = toMediaLibraryItem(source.value);
1079
1089
  const selectedSourceMediaID = getRelationID(source.value);
1090
+ const selectedRelationMedia = toMediaLibraryItem(source.value);
1091
+ const selectedSourceMedia = selectedRelationMedia ?? findMediaLibraryItem(source.library, selectedSourceMediaID);
1080
1092
  const sourceOptions = selectedSourceMedia && !source.library.some((item) => String(item.id) === String(selectedSourceMedia.id)) ? [selectedSourceMedia, ...source.library] : source.library;
1081
1093
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1082
1094
  "div",
@@ -1101,6 +1113,10 @@ function BlockInspectorRenderer({
1101
1113
  }
1102
1114
  )
1103
1115
  ] }),
1116
+ selectedSourceMedia?.alt ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "orion-builder-settings-label", children: [
1117
+ "Media Description",
1118
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { className: "orion-builder-settings-input", readOnly: true, type: "text", value: selectedSourceMedia.alt })
1119
+ ] }) : 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
1120
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1105
1121
  "button",
1106
1122
  {
@@ -2249,8 +2265,8 @@ function renderSimpleBlockPreview(args) {
2249
2265
  getImagePresentationStyle: getImagePresentationStyle2,
2250
2266
  index,
2251
2267
  isBlockUploadTarget,
2252
- normalizeImageCornerStyle: normalizeImageCornerStyle2,
2253
- normalizeImageFit: normalizeImageFit2,
2268
+ normalizeImageCornerStyle: normalizeImageCornerStyle3,
2269
+ normalizeImageFit: normalizeImageFit3,
2254
2270
  normalizeText: normalizeText3,
2255
2271
  onDropAt,
2256
2272
  renderWithSectionShell,
@@ -2434,8 +2450,8 @@ function renderSimpleBlockPreview(args) {
2434
2450
  const imagePositionX = parseOptionalPercentNumber(mediaSettings.positionX ?? block?.imagePositionX);
2435
2451
  const imagePositionY = parseOptionalPercentNumber(mediaSettings.positionY ?? block?.imagePositionY);
2436
2452
  const imageStyle = getImagePresentationStyle2({
2437
- cornerStyle: normalizeImageCornerStyle2(mediaSettings.cornerStyle ?? block?.imageCornerStyle),
2438
- fit: normalizeImageFit2(mediaSettings.fit ?? block?.imageFit),
2453
+ cornerStyle: normalizeImageCornerStyle3(mediaSettings.cornerStyle ?? block?.imageCornerStyle),
2454
+ fit: normalizeImageFit3(mediaSettings.fit ?? block?.imageFit),
2439
2455
  positionX: imagePositionX,
2440
2456
  positionY: imagePositionY
2441
2457
  });
@@ -2965,6 +2981,63 @@ var normalizeNumber2 = (value, fallback) => {
2965
2981
  return fallback;
2966
2982
  };
2967
2983
  var clamp = (value, min, max) => Math.max(min, Math.min(max, value));
2984
+ var getRelationID2 = (value) => {
2985
+ if (typeof value === "number" || typeof value === "string") {
2986
+ return value;
2987
+ }
2988
+ if (!isRecord5(value)) {
2989
+ return null;
2990
+ }
2991
+ const id = value.id;
2992
+ return typeof id === "number" || typeof id === "string" ? id : null;
2993
+ };
2994
+ var toMediaLibraryItem2 = (value) => {
2995
+ if (!isRecord5(value)) {
2996
+ return null;
2997
+ }
2998
+ const id = getRelationID2(value);
2999
+ if (id === null) {
3000
+ return null;
3001
+ }
3002
+ const filename = typeof value.filename === "string" ? value.filename : "";
3003
+ const url = typeof value.url === "string" && value.url.length > 0 ? value.url : filename ? `/api/media/file/${encodeURIComponent(filename)}` : "";
3004
+ return {
3005
+ alt: typeof value.alt === "string" ? value.alt : "",
3006
+ filename,
3007
+ id,
3008
+ url
3009
+ };
3010
+ };
3011
+ var mediaLabel2 = (item) => item.filename || item.alt || `Media #${item.id}`;
3012
+ var findMediaLibraryItem2 = (library, id) => {
3013
+ if (id === null) {
3014
+ return null;
3015
+ }
3016
+ return library.find((item) => String(item.id) === String(id)) || null;
3017
+ };
3018
+ var normalizeImageFit = (value) => value === "contain" ? "contain" : "cover";
3019
+ var normalizeImageCornerStyle = (value) => value === "square" ? "square" : "rounded";
3020
+ var getItemMediaSettings = (item) => {
3021
+ const settings = isRecord5(item.settings) ? item.settings : {};
3022
+ const media = isRecord5(settings.media) ? settings.media : {};
3023
+ return {
3024
+ cornerStyle: normalizeImageCornerStyle(media.cornerStyle ?? item.imageCornerStyle),
3025
+ fit: normalizeImageFit(media.fit ?? item.imageFit),
3026
+ height: (() => {
3027
+ const value = media.height ?? item.imageHeight;
3028
+ if (typeof value === "number" && Number.isFinite(value)) {
3029
+ return value;
3030
+ }
3031
+ if (typeof value === "string" && value.trim().length > 0) {
3032
+ const parsed = Number(value);
3033
+ return Number.isFinite(parsed) ? parsed : null;
3034
+ }
3035
+ return null;
3036
+ })(),
3037
+ positionX: clamp(normalizeNumber2(media.positionX ?? item.imagePositionX, 50), 0, 100),
3038
+ positionY: clamp(normalizeNumber2(media.positionY ?? item.imagePositionY, 50), 0, 100)
3039
+ };
3040
+ };
2968
3041
  var hasQueryMatch = (query, ...values) => {
2969
3042
  const normalized = query.trim().toLowerCase();
2970
3043
  if (!normalized) {
@@ -3011,18 +3084,157 @@ var bulletsToTextareaValue = (value) => {
3011
3084
  return value.map((item) => isRecord5(item) && typeof item.label === "string" ? item.label.trim() : "").filter(Boolean).join("\n");
3012
3085
  };
3013
3086
  var textareaValueToBullets = (value) => value.split("\n").map((line) => line.trim()).filter(Boolean).map((label) => ({ label }));
3087
+ function ItemMediaControl({
3088
+ fieldName,
3089
+ imageURLFieldName,
3090
+ item,
3091
+ itemIndex,
3092
+ label,
3093
+ mediaLibrary,
3094
+ mediaLibraryError,
3095
+ mediaLibraryLoading,
3096
+ maxHeight,
3097
+ minHeight,
3098
+ onRemoveItemMedia,
3099
+ onSelectItemMedia,
3100
+ onUpdateItemField,
3101
+ onUpdateItemMediaPresentation,
3102
+ onUploadItemMedia,
3103
+ searchQuery,
3104
+ uploadDisabled,
3105
+ uploadLabel,
3106
+ uploading
3107
+ }) {
3108
+ const selectedMediaID = getRelationID2(item[fieldName]);
3109
+ const selectedRelationMedia = toMediaLibraryItem2(item[fieldName]);
3110
+ const selectedMedia = selectedRelationMedia ?? findMediaLibraryItem2(mediaLibrary, selectedMediaID);
3111
+ const directImageURL = normalizeText(item[imageURLFieldName]);
3112
+ const previewURL = selectedMedia?.url || directImageURL;
3113
+ const mediaSettings = getItemMediaSettings(item);
3114
+ const sourceOptions = selectedMedia && !mediaLibrary.some((libraryItem) => String(libraryItem.id) === String(selectedMedia.id)) ? [selectedMedia, ...mediaLibrary] : mediaLibrary;
3115
+ if (!hasQueryMatch(searchQuery, label, "image", "media", "photo", "picture", "url", "fit", "crop", "height")) {
3116
+ return null;
3117
+ }
3118
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "orion-builder-settings-item-card", style: { padding: "0.56rem" }, children: [
3119
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "orion-builder-settings-label", children: label }),
3120
+ previewURL ? (
3121
+ // eslint-disable-next-line @next/next/no-img-element
3122
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3123
+ "img",
3124
+ {
3125
+ alt: selectedMedia?.alt || label,
3126
+ src: previewURL,
3127
+ style: {
3128
+ aspectRatio: "16 / 9",
3129
+ border: "1px solid rgba(35, 51, 82, 0.14)",
3130
+ borderRadius: mediaSettings.cornerStyle === "square" ? 4 : 10,
3131
+ display: "block",
3132
+ objectFit: mediaSettings.fit,
3133
+ objectPosition: `${mediaSettings.positionX}% ${mediaSettings.positionY}%`,
3134
+ width: "100%"
3135
+ }
3136
+ }
3137
+ )
3138
+ ) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "orion-builder-settings-empty", children: "No image selected." }),
3139
+ mediaLibraryLoading ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "orion-builder-settings-note", children: "Loading media library..." }) : null,
3140
+ mediaLibraryError ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "orion-builder-settings-error", children: mediaLibraryError }) : null,
3141
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("label", { className: "orion-builder-settings-label", children: [
3142
+ "Media Library Image",
3143
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
3144
+ "select",
3145
+ {
3146
+ className: "orion-builder-settings-input",
3147
+ onChange: (event) => onSelectItemMedia?.(itemIndex, fieldName, event.target.value),
3148
+ value: selectedMediaID !== null ? String(selectedMediaID) : "",
3149
+ children: [
3150
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("option", { value: "", children: "No library image" }),
3151
+ sourceOptions.map((libraryItem) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("option", { value: String(libraryItem.id), children: mediaLabel2(libraryItem) }, String(libraryItem.id)))
3152
+ ]
3153
+ }
3154
+ )
3155
+ ] }),
3156
+ selectedMedia?.alt ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("label", { className: "orion-builder-settings-label", children: [
3157
+ "Media Description",
3158
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("input", { className: "orion-builder-settings-input", readOnly: true, type: "text", value: selectedMedia.alt })
3159
+ ] }) : 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,
3160
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3161
+ "button",
3162
+ {
3163
+ className: "orion-builder-settings-inline-btn",
3164
+ disabled: selectedMediaID === null,
3165
+ onClick: () => onRemoveItemMedia?.(itemIndex, fieldName),
3166
+ type: "button",
3167
+ children: "Remove Library Image"
3168
+ }
3169
+ ),
3170
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("label", { className: "orion-builder-settings-label", children: [
3171
+ "Direct Image URL",
3172
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3173
+ "input",
3174
+ {
3175
+ className: "orion-builder-settings-input",
3176
+ onChange: (event) => onUpdateItemField(itemIndex, imageURLFieldName, event.target.value),
3177
+ type: "text",
3178
+ value: directImageURL
3179
+ }
3180
+ )
3181
+ ] }),
3182
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("label", { className: "orion-builder-settings-label", children: [
3183
+ uploadLabel,
3184
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3185
+ "input",
3186
+ {
3187
+ accept: "image/*",
3188
+ className: "orion-builder-settings-input",
3189
+ disabled: uploadDisabled,
3190
+ onChange: (event) => {
3191
+ const file = event.currentTarget.files?.[0];
3192
+ if (file) {
3193
+ onUploadItemMedia?.(itemIndex, fieldName, file);
3194
+ }
3195
+ event.currentTarget.value = "";
3196
+ },
3197
+ type: "file"
3198
+ }
3199
+ )
3200
+ ] }),
3201
+ uploading ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "orion-builder-settings-note", children: "Uploading image..." }) : null,
3202
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3203
+ ImageControls,
3204
+ {
3205
+ cornerStyle: mediaSettings.cornerStyle,
3206
+ fit: mediaSettings.fit,
3207
+ height: mediaSettings.height,
3208
+ maxHeight,
3209
+ minHeight,
3210
+ onChange: (field, value) => onUpdateItemMediaPresentation?.(itemIndex, field, value),
3211
+ positionX: mediaSettings.positionX,
3212
+ positionY: mediaSettings.positionY
3213
+ }
3214
+ )
3215
+ ] });
3216
+ }
3014
3217
  function ArrayItemsEditor({
3015
3218
  blockType,
3016
3219
  expandedItemIndex,
3017
3220
  items,
3221
+ mediaLibrary = [],
3222
+ mediaLibraryError = "",
3223
+ mediaLibraryLoading = false,
3018
3224
  mode,
3019
3225
  onAddItem,
3226
+ onRemoveItemMedia,
3020
3227
  onRemoveItem,
3228
+ onSelectItemMedia,
3021
3229
  onToggleItem,
3022
3230
  onUpdateItemField,
3231
+ onUpdateItemMediaPresentation,
3023
3232
  onUpdateItemSetting,
3233
+ onUploadItemMedia,
3024
3234
  searchQuery,
3025
- showInlineCopyFields
3235
+ showInlineCopyFields,
3236
+ uploadDisabled = false,
3237
+ isItemMediaUploading
3026
3238
  }) {
3027
3239
  const config = blockConfig[blockType];
3028
3240
  const normalizedQuery = searchQuery.trim().toLowerCase();
@@ -3172,11 +3384,30 @@ function ArrayItemsEditor({
3172
3384
  }
3173
3385
  )
3174
3386
  ] }) : 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
- ] })
3387
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3388
+ ItemMediaControl,
3389
+ {
3390
+ fieldName: "media",
3391
+ imageURLFieldName: "imageURL",
3392
+ item,
3393
+ itemIndex,
3394
+ label: "Feature Image",
3395
+ maxHeight: 600,
3396
+ mediaLibrary,
3397
+ mediaLibraryError,
3398
+ mediaLibraryLoading,
3399
+ minHeight: 40,
3400
+ onRemoveItemMedia,
3401
+ onSelectItemMedia,
3402
+ onUpdateItemField,
3403
+ onUpdateItemMediaPresentation,
3404
+ onUploadItemMedia,
3405
+ searchQuery: normalizedQuery,
3406
+ uploadDisabled,
3407
+ uploadLabel: "Upload Feature Image",
3408
+ uploading: Boolean(isItemMediaUploading?.(itemIndex, "media"))
3409
+ }
3410
+ )
3180
3411
  ] }) : null,
3181
3412
  blockType === "logoWall" ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
3182
3413
  showInlineCopyFields ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("label", { className: "orion-builder-settings-label", children: [
@@ -3203,11 +3434,30 @@ function ArrayItemsEditor({
3203
3434
  }
3204
3435
  )
3205
3436
  ] }) : 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
- ] })
3437
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3438
+ ItemMediaControl,
3439
+ {
3440
+ fieldName: "media",
3441
+ imageURLFieldName: "imageURL",
3442
+ item,
3443
+ itemIndex,
3444
+ label: "Logo Image",
3445
+ maxHeight: 200,
3446
+ mediaLibrary,
3447
+ mediaLibraryError,
3448
+ mediaLibraryLoading,
3449
+ minHeight: 24,
3450
+ onRemoveItemMedia,
3451
+ onSelectItemMedia,
3452
+ onUpdateItemField,
3453
+ onUpdateItemMediaPresentation,
3454
+ onUploadItemMedia,
3455
+ searchQuery: normalizedQuery,
3456
+ uploadDisabled,
3457
+ uploadLabel: "Upload Logo Image",
3458
+ uploading: Boolean(isItemMediaUploading?.(itemIndex, "media"))
3459
+ }
3460
+ )
3211
3461
  ] }) : null,
3212
3462
  blockType === "beforeAfter" ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
3213
3463
  showInlineCopyFields ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
@@ -3235,11 +3485,54 @@ function ArrayItemsEditor({
3235
3485
  )
3236
3486
  ] })
3237
3487
  ] }) : 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
- ] })
3488
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3489
+ ItemMediaControl,
3490
+ {
3491
+ fieldName: "beforeMedia",
3492
+ imageURLFieldName: "beforeImageURL",
3493
+ item,
3494
+ itemIndex,
3495
+ label: "Before Image",
3496
+ maxHeight: 600,
3497
+ mediaLibrary,
3498
+ mediaLibraryError,
3499
+ mediaLibraryLoading,
3500
+ minHeight: 60,
3501
+ onRemoveItemMedia,
3502
+ onSelectItemMedia,
3503
+ onUpdateItemField,
3504
+ onUpdateItemMediaPresentation,
3505
+ onUploadItemMedia,
3506
+ searchQuery: normalizedQuery,
3507
+ uploadDisabled,
3508
+ uploadLabel: "Upload Before Image",
3509
+ uploading: Boolean(isItemMediaUploading?.(itemIndex, "beforeMedia"))
3510
+ }
3511
+ ),
3512
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3513
+ ItemMediaControl,
3514
+ {
3515
+ fieldName: "afterMedia",
3516
+ imageURLFieldName: "afterImageURL",
3517
+ item,
3518
+ itemIndex,
3519
+ label: "After Image",
3520
+ maxHeight: 600,
3521
+ mediaLibrary,
3522
+ mediaLibraryError,
3523
+ mediaLibraryLoading,
3524
+ minHeight: 60,
3525
+ onRemoveItemMedia,
3526
+ onSelectItemMedia,
3527
+ onUpdateItemField,
3528
+ onUpdateItemMediaPresentation,
3529
+ onUploadItemMedia,
3530
+ searchQuery: normalizedQuery,
3531
+ uploadDisabled,
3532
+ uploadLabel: "Upload After Image",
3533
+ uploading: Boolean(isItemMediaUploading?.(itemIndex, "afterMedia"))
3534
+ }
3535
+ )
3243
3536
  ] }) : null,
3244
3537
  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
3538
  /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("label", { className: "orion-builder-settings-label", children: [
@@ -3445,8 +3738,8 @@ var resolveBuilderMediumHeroHeight = (topViewportHeight) => {
3445
3738
  }
3446
3739
  return "50svh";
3447
3740
  };
3448
- var normalizeImageFit = (value) => normalizeHeroImageFit(value);
3449
- var normalizeImageCornerStyle = (value, legacyFitValue) => normalizeHeroImageCornerStyle(value, legacyFitValue);
3741
+ var normalizeImageFit2 = (value) => normalizeHeroImageFit(value);
3742
+ var normalizeImageCornerStyle2 = (value, legacyFitValue) => normalizeHeroImageCornerStyle(value, legacyFitValue);
3450
3743
  var positionPercent = (value, fit) => {
3451
3744
  const resolved = fit === "cover" && (value === "left" || value === "right") ? "center" : value;
3452
3745
  switch (resolved) {
@@ -3878,6 +4171,12 @@ function getThemeColorOverride(tokens, colorKey) {
3878
4171
  const normalized = value.trim();
3879
4172
  return normalized.length > 0 ? normalized : null;
3880
4173
  }
4174
+ function normalizeCustomClassName(value) {
4175
+ if (typeof value !== "string") {
4176
+ return "";
4177
+ }
4178
+ return value.split(/\s+/).map((className) => className.trim()).filter(Boolean).join(" ");
4179
+ }
3881
4180
  var sectionStyleFromBlock = (block, pageDefaults) => {
3882
4181
  const settings = isRecord6(block.settings) ? block.settings : {};
3883
4182
  const layoutSettings = isRecord6(settings.layout) ? settings.layout : {};
@@ -3971,7 +4270,7 @@ var sectionStyleFromBlock = (block, pageDefaults) => {
3971
4270
  sectionStyle: sectionMode === "color" ? { background: sectionColor } : sectionMode === "gradient" ? { background: sectionGradient } : block.blockType === "hero" ? { background: "transparent" } : {}
3972
4271
  };
3973
4272
  };
3974
- function getRelationID2(value) {
4273
+ function getRelationID3(value) {
3975
4274
  if (typeof value === "number" || typeof value === "string") {
3976
4275
  return value;
3977
4276
  }
@@ -4004,7 +4303,7 @@ function extractUploadedMedia(value) {
4004
4303
  if (!candidate || typeof candidate !== "object") {
4005
4304
  return null;
4006
4305
  }
4007
- const id = getRelationID2(candidate);
4306
+ const id = getRelationID3(candidate);
4008
4307
  if (id === null) {
4009
4308
  return null;
4010
4309
  }
@@ -4015,11 +4314,11 @@ function extractUploadedMedia(value) {
4015
4314
  url: typeof candidate.url === "string" ? candidate.url : ""
4016
4315
  };
4017
4316
  }
4018
- function toMediaLibraryItem2(value) {
4317
+ function toMediaLibraryItem3(value) {
4019
4318
  if (!value || typeof value !== "object") {
4020
4319
  return null;
4021
4320
  }
4022
- const id = getRelationID2(value);
4321
+ const id = getRelationID3(value);
4023
4322
  if (id === null) {
4024
4323
  return null;
4025
4324
  }
@@ -4197,7 +4496,7 @@ function BuilderPageEditor({
4197
4496
  }
4198
4497
  const json = await response.json();
4199
4498
  const docs = Array.isArray(json.docs) ? json.docs : [];
4200
- const items = docs.map((doc2) => toMediaLibraryItem2(doc2)).filter((item) => item !== null);
4499
+ const items = docs.map((doc2) => toMediaLibraryItem3(doc2)).filter((item) => item !== null);
4201
4500
  setMediaLibrary(items);
4202
4501
  } catch (error) {
4203
4502
  setMediaLibraryError(error instanceof Error ? error.message : "Could not load media library.");
@@ -4551,7 +4850,7 @@ function BuilderPageEditor({
4551
4850
  const nextLayout = cloneBlockLayout(layout);
4552
4851
  const block = nextLayout[selectedIndex];
4553
4852
  if (target.kind === "hero") {
4554
- const uploadedItem = toMediaLibraryItem2(uploaded);
4853
+ const uploadedItem = toMediaLibraryItem3(uploaded);
4555
4854
  nextLayout[selectedIndex] = {
4556
4855
  ...block,
4557
4856
  backgroundImageURL: uploadedItem?.url || normalizeText2(uploaded.url),
@@ -4615,13 +4914,13 @@ function BuilderPageEditor({
4615
4914
  const nextBlock = { ...migrateBlockToSettingsV2(block) };
4616
4915
  const blockType = normalizeText2(nextBlock.blockType);
4617
4916
  if (blockType === "hero") {
4618
- const mediaID = getRelationID2(nextBlock.media);
4917
+ const mediaID = getRelationID3(nextBlock.media);
4619
4918
  if (mediaID !== null) {
4620
4919
  nextBlock.media = mediaID;
4621
4920
  }
4622
4921
  }
4623
4922
  if (blockType === "media") {
4624
- const imageID = getRelationID2(nextBlock.image);
4923
+ const imageID = getRelationID3(nextBlock.image);
4625
4924
  if (imageID !== null) {
4626
4925
  nextBlock.image = imageID;
4627
4926
  }
@@ -4633,15 +4932,15 @@ function BuilderPageEditor({
4633
4932
  return rawItem;
4634
4933
  }
4635
4934
  const nextItem = { ...rawItem };
4636
- const mediaID = getRelationID2(nextItem.media);
4935
+ const mediaID = getRelationID3(nextItem.media);
4637
4936
  if (mediaID !== null) {
4638
4937
  nextItem.media = mediaID;
4639
4938
  }
4640
- const beforeMediaID = getRelationID2(nextItem.beforeMedia);
4939
+ const beforeMediaID = getRelationID3(nextItem.beforeMedia);
4641
4940
  if (beforeMediaID !== null) {
4642
4941
  nextItem.beforeMedia = beforeMediaID;
4643
4942
  }
4644
- const afterMediaID = getRelationID2(nextItem.afterMedia);
4943
+ const afterMediaID = getRelationID3(nextItem.afterMedia);
4645
4944
  if (afterMediaID !== null) {
4646
4945
  nextItem.afterMedia = afterMediaID;
4647
4946
  }
@@ -4697,6 +4996,7 @@ function BuilderPageEditor({
4697
4996
  const inheritProjectStyles = options?.inheritProjectStyles === true;
4698
4997
  const shell = sectionStyleFromBlock(block, pageDefaults);
4699
4998
  const blockSettings = isRecord6(block.settings) ? block.settings : {};
4999
+ const blockAdvanced = isRecord6(blockSettings.advanced) ? blockSettings.advanced : {};
4700
5000
  const blockTypography = isRecord6(blockSettings.typography) ? blockSettings.typography : {};
4701
5001
  const blockTheme = isRecord6(blockSettings.theme) ? blockSettings.theme : {};
4702
5002
  const heroBackgroundColor = normalizeText2(block.backgroundColor).trim();
@@ -4704,8 +5004,9 @@ function BuilderPageEditor({
4704
5004
  const heroMedia = block.blockType === "hero" ? resolveMedia(block.media) : null;
4705
5005
  const heroHasImage = block.blockType === "hero" && Boolean(heroBackgroundImageURL || heroMedia?.url);
4706
5006
  const heroTextColor = block.blockType === "hero" ? heroHasImage ? "#ffffff" : heroBackgroundColor ? getReadableTextColor(heroBackgroundColor, resolvedThemeTokens.colors.headingText, "#ffffff") : resolvedThemeTokens.colors.headingText : null;
5007
+ const bodyAlign = blockTypography.bodyAlign === "center" || blockTypography.bodyAlign === "justify" || blockTypography.bodyAlign === "right" ? blockTypography.bodyAlign : "left";
4707
5008
  const typographyStyle = resolveTypographyStyleFromSettings({
4708
- bodyAlign: blockTypography.bodyAlign === "center" || blockTypography.bodyAlign === "justify" || blockTypography.bodyAlign === "right" ? blockTypography.bodyAlign : "left",
5009
+ bodyAlign,
4709
5010
  letterSpacingPreset: blockTypography.letterSpacingPreset === "tight" || blockTypography.letterSpacingPreset === "relaxed" ? blockTypography.letterSpacingPreset : "normal",
4710
5011
  lineHeightPreset: blockTypography.lineHeightPreset === "tight" || blockTypography.lineHeightPreset === "relaxed" ? blockTypography.lineHeightPreset : "normal",
4711
5012
  maxTextWidth: blockTypography.maxTextWidth === "sm" || blockTypography.maxTextWidth === "md" || blockTypography.maxTextWidth === "lg" || blockTypography.maxTextWidth === "full" ? blockTypography.maxTextWidth : "auto"
@@ -4713,14 +5014,24 @@ function BuilderPageEditor({
4713
5014
  const headingAlign = blockTypography.headingAlign === "center" || blockTypography.headingAlign === "justify" || blockTypography.headingAlign === "right" ? blockTypography.headingAlign : "left";
4714
5015
  const headingColor = getThemeColorOverride(blockTheme, "headingText") || getThemeColorOverride(pageDefaults.themePage, "headingText") || getThemeColorOverride(siteThemeTokens, "headingText") || heroTextColor || resolvedThemeTokens.colors.headingText;
4715
5016
  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)(
5017
+ const customClassName = normalizeCustomClassName(blockAdvanced.customClassName ?? block.customClassName);
5018
+ const hideOnMobile = Boolean(blockAdvanced.hideOnMobile ?? block.hideOnMobile);
5019
+ const sectionClassName = [
5020
+ className,
5021
+ shell.sectionClass,
5022
+ customClassName,
5023
+ hideOnMobile ? "orion-builder-hide-mobile" : ""
5024
+ ].filter(Boolean).join(" ");
5025
+ 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
5026
  "div",
4718
5027
  {
4719
5028
  className: shell.contentClass,
4720
5029
  style: {
4721
5030
  ...shell.contentStyle,
5031
+ "--orion-builder-heading-align": headingAlign,
5032
+ "--orion-builder-body-align": bodyAlign,
5033
+ "--orion-builder-actions-align": bodyAlign === "center" ? "center" : bodyAlign === "right" ? "flex-end" : "flex-start",
4722
5034
  ...inheritProjectStyles ? {} : {
4723
- "--orion-builder-heading-align": headingAlign,
4724
5035
  "--orion-builder-heading-color": headingColor,
4725
5036
  color: bodyColor,
4726
5037
  ...typographyStyle
@@ -5207,8 +5518,8 @@ function BuilderPageEditor({
5207
5518
  }
5208
5519
  ] : [];
5209
5520
  const selectedMediaImageControls = selectedItemRecord && typeof selectedItemIndex === "number" && (selectedType === "featureGrid" || selectedType === "logoWall" || selectedType === "beforeAfter") ? {
5210
- cornerStyle: normalizeImageCornerStyle(selectedItemRecord.imageCornerStyle),
5211
- fit: normalizeImageFit(selectedItemRecord.imageFit),
5521
+ cornerStyle: normalizeImageCornerStyle2(selectedItemRecord.imageCornerStyle),
5522
+ fit: normalizeImageFit2(selectedItemRecord.imageFit),
5212
5523
  height: (() => {
5213
5524
  if (typeof selectedItemRecord.imageHeight === "number" && Number.isFinite(selectedItemRecord.imageHeight)) {
5214
5525
  return selectedItemRecord.imageHeight;
@@ -5683,8 +5994,8 @@ function BuilderPageEditor({
5683
5994
  const itemPositionX = parseOptionalPercentNumber2(itemRecord?.imagePositionX);
5684
5995
  const itemPositionY = parseOptionalPercentNumber2(itemRecord?.imagePositionY);
5685
5996
  const itemImageStyle = getImagePresentationStyle({
5686
- cornerStyle: normalizeImageCornerStyle(itemRecord?.imageCornerStyle),
5687
- fit: normalizeImageFit(itemRecord?.imageFit),
5997
+ cornerStyle: normalizeImageCornerStyle2(itemRecord?.imageCornerStyle),
5998
+ fit: normalizeImageFit2(itemRecord?.imageFit),
5688
5999
  positionX: itemPositionX,
5689
6000
  positionY: itemPositionY
5690
6001
  });
@@ -5801,8 +6112,8 @@ function BuilderPageEditor({
5801
6112
  const itemPositionX = parseOptionalPercentNumber2(itemRecord?.imagePositionX);
5802
6113
  const itemPositionY = parseOptionalPercentNumber2(itemRecord?.imagePositionY);
5803
6114
  const itemImageStyle = getImagePresentationStyle({
5804
- cornerStyle: normalizeImageCornerStyle(itemRecord?.imageCornerStyle),
5805
- fit: normalizeImageFit(itemRecord?.imageFit),
6115
+ cornerStyle: normalizeImageCornerStyle2(itemRecord?.imageCornerStyle),
6116
+ fit: normalizeImageFit2(itemRecord?.imageFit),
5806
6117
  positionX: itemPositionX,
5807
6118
  positionY: itemPositionY
5808
6119
  });
@@ -6008,8 +6319,8 @@ function BuilderPageEditor({
6008
6319
  const itemPositionX = parseOptionalPercentNumber2(itemRecord?.imagePositionX);
6009
6320
  const itemPositionY = parseOptionalPercentNumber2(itemRecord?.imagePositionY);
6010
6321
  const imageStyle = getImagePresentationStyle({
6011
- cornerStyle: normalizeImageCornerStyle(itemRecord?.imageCornerStyle),
6012
- fit: normalizeImageFit(itemRecord?.imageFit),
6322
+ cornerStyle: normalizeImageCornerStyle2(itemRecord?.imageCornerStyle),
6323
+ fit: normalizeImageFit2(itemRecord?.imageFit),
6013
6324
  positionX: itemPositionX,
6014
6325
  positionY: itemPositionY,
6015
6326
  roundedRadius: 10
@@ -6122,8 +6433,8 @@ function BuilderPageEditor({
6122
6433
  const itemPositionX = parseOptionalPercentNumber2(itemRecord?.imagePositionX);
6123
6434
  const itemPositionY = parseOptionalPercentNumber2(itemRecord?.imagePositionY);
6124
6435
  const imageStyle = getImagePresentationStyle({
6125
- cornerStyle: normalizeImageCornerStyle(itemRecord?.imageCornerStyle),
6126
- fit: normalizeImageFit(itemRecord?.imageFit),
6436
+ cornerStyle: normalizeImageCornerStyle2(itemRecord?.imageCornerStyle),
6437
+ fit: normalizeImageFit2(itemRecord?.imageFit),
6127
6438
  positionX: itemPositionX,
6128
6439
  positionY: itemPositionY
6129
6440
  });
@@ -6429,8 +6740,8 @@ function BuilderPageEditor({
6429
6740
  getImagePresentationStyle,
6430
6741
  index,
6431
6742
  isBlockUploadTarget,
6432
- normalizeImageCornerStyle,
6433
- normalizeImageFit,
6743
+ normalizeImageCornerStyle: normalizeImageCornerStyle2,
6744
+ normalizeImageFit: normalizeImageFit2,
6434
6745
  normalizeText: normalizeText2,
6435
6746
  onDropAt,
6436
6747
  renderWithSectionShell,
@@ -6659,23 +6970,32 @@ function BuilderPageEditor({
6659
6970
  blockType: selectedType,
6660
6971
  expandedItemIndex,
6661
6972
  items: selectedItems,
6973
+ isItemMediaUploading: isSelectedItemMediaUploading,
6974
+ mediaLibrary,
6975
+ mediaLibraryError,
6976
+ mediaLibraryLoading,
6662
6977
  mode: settingsPanelMode,
6663
6978
  onAddItem: appendDefaultItemToSelected,
6664
6979
  onRemoveItem: (itemIndex) => removeItemFromSelected("items", itemIndex),
6980
+ onRemoveItemMedia: (itemIndex, fieldName) => setSelectedItemMediaFieldFromLibrary(itemIndex, fieldName, ""),
6981
+ onSelectItemMedia: (itemIndex, fieldName, mediaID) => setSelectedItemMediaFieldFromLibrary(itemIndex, fieldName, mediaID),
6665
6982
  onToggleItem: toggleSelectedItem,
6666
6983
  onUpdateItemField: (itemIndex, fieldName, value) => updateArrayItemField(selectedIndex ?? 0, "items", itemIndex, fieldName, value),
6984
+ onUpdateItemMediaPresentation: (itemIndex, fieldName, value) => updateArrayItemSettingField(selectedIndex ?? 0, "items", itemIndex, `media.${fieldName}`, value),
6667
6985
  onUpdateItemSetting: (itemIndex, path, value) => updateArrayItemSettingField(selectedIndex ?? 0, "items", itemIndex, path, value),
6986
+ onUploadItemMedia: uploadItemMediaFromV2,
6668
6987
  searchQuery: settingsSearchQuery,
6669
- showInlineCopyFields: editCopyInPanelEnabled
6988
+ showInlineCopyFields: editCopyInPanelEnabled,
6989
+ uploadDisabled: uploadingTarget !== null
6670
6990
  }
6671
6991
  ) : null,
6672
6992
  /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { style: sidebarLabelStyle, children: [
6673
- "Upload Alt Text",
6993
+ "New Upload Alt Text",
6674
6994
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6675
6995
  "input",
6676
6996
  {
6677
6997
  onChange: (event) => setUploadAltText(event.target.value),
6678
- placeholder: "Describe the image",
6998
+ placeholder: "Used only when uploading a new image",
6679
6999
  style: sidebarInputStyle,
6680
7000
  type: "text",
6681
7001
  value: uploadAltText