@orion-studios/payload-studio 0.5.0-beta.113 → 0.5.0-beta.115

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 (42) hide show
  1. package/dist/admin/client.js +1880 -502
  2. package/dist/admin/client.mjs +1164 -329
  3. package/dist/admin/index.d.mts +2 -1
  4. package/dist/admin/index.d.ts +2 -1
  5. package/dist/admin/index.js +267 -59
  6. package/dist/admin/index.mjs +1 -1
  7. package/dist/admin-app/client.d.mts +1 -0
  8. package/dist/admin-app/client.d.ts +1 -0
  9. package/dist/admin-app/client.js +266 -105
  10. package/dist/admin-app/client.mjs +105 -456
  11. package/dist/admin-app/index.d.mts +2 -1
  12. package/dist/admin-app/index.d.ts +2 -1
  13. package/dist/admin-app/styles.css +351 -0
  14. package/dist/admin.css +9 -0
  15. package/dist/chunk-6NE7GIVT.mjs +555 -0
  16. package/dist/{chunk-DAIZDGHL.mjs → chunk-T5PBXPES.mjs} +267 -59
  17. package/dist/{chunk-3T2P6SDM.mjs → chunk-XKUTZ7IU.mjs} +215 -6
  18. package/dist/index-3jBpt6ZT.d.ts +385 -0
  19. package/dist/index-C3FgxbEL.d.mts +385 -0
  20. package/dist/{index-DUi_XND6.d.ts → index-Crx_MtPw.d.ts} +33 -3
  21. package/dist/{index-gLl_358v.d.mts → index-Cv-6qnrw.d.mts} +33 -3
  22. package/dist/{index-BzKOThsI.d.mts → index-DWmudwDm.d.mts} +1 -1
  23. package/dist/{index-BzKOThsI.d.ts → index-DWmudwDm.d.ts} +1 -1
  24. package/dist/{index-7lxTrxSG.d.mts → index-c5-qTRbH.d.mts} +7 -1
  25. package/dist/{index-7lxTrxSG.d.ts → index-yfpxsgUu.d.ts} +7 -1
  26. package/dist/index.d.mts +5 -4
  27. package/dist/index.d.ts +5 -4
  28. package/dist/index.js +473 -65
  29. package/dist/index.mjs +6 -6
  30. package/dist/nextjs/index.mjs +2 -2
  31. package/dist/sitePreviewTypes-BECnq9xI.d.mts +41 -0
  32. package/dist/sitePreviewTypes-BECnq9xI.d.ts +41 -0
  33. package/dist/studio/index.d.mts +1 -1
  34. package/dist/studio/index.d.ts +1 -1
  35. package/dist/studio-pages/index.d.mts +3 -3
  36. package/dist/studio-pages/index.d.ts +3 -3
  37. package/dist/studio-pages/index.js +330 -7
  38. package/dist/studio-pages/index.mjs +10 -3
  39. package/package.json +1 -1
  40. package/dist/index-B7QvY3yF.d.mts +0 -245
  41. package/dist/index-BK03FiEM.d.ts +0 -245
  42. package/dist/{chunk-BET2YLAS.mjs → chunk-OTHERBGX.mjs} +3 -3
package/dist/index.js CHANGED
@@ -211,7 +211,8 @@ function configureAdmin(config) {
211
211
  brandPrimary = "#3b82f6",
212
212
  brandSecondary = "#8b5cf6",
213
213
  defaultTheme = "brand-light",
214
- logoUrl
214
+ logoUrl,
215
+ allowThemePreference = false
215
216
  } = config;
216
217
  const studioEnabled = config.studio?.enabled ?? true;
217
218
  const formsEnabled = config.studio?.forms?.enabled ?? false;
@@ -219,13 +220,19 @@ function configureAdmin(config) {
219
220
  const formSubmissionsCollectionSlug = config.studio?.forms?.submissionsCollectionSlug || "form-submissions";
220
221
  const formUploadsCollectionSlug = config.studio?.forms?.uploadsCollectionSlug || "form-uploads";
221
222
  const pagesCollectionSlug = config.studio?.pages?.collectionSlug || "pages";
223
+ const builderBasePath = config.studio?.pages?.builderBasePath || "/builder";
222
224
  const mediaCollectionSlug = config.studio?.media?.collectionSlug || "media";
223
- const contactFormStudioPath = "/studio-contact-form";
225
+ const globalsBasePath = "/site-globals";
226
+ const pagesBasePath = "/pages";
227
+ const formsBasePath = "/forms";
228
+ const mediaBasePath = "/media";
229
+ const toolsBasePath = "/tools";
230
+ const contactFormStudioPath = "/contact-form";
224
231
  const configuredGlobals = config.studio?.globals || [
225
232
  { slug: "site-settings", label: "Website Settings" },
226
233
  { slug: "header", label: "Header & Navigation" },
227
234
  { slug: "footer", label: "Footer" },
228
- { slug: "contact-form", label: "Contact Form" }
235
+ { slug: "social-media", label: "Social Media" }
229
236
  ];
230
237
  const globals = configuredGlobals.map((global) => {
231
238
  if (global.slug !== "contact-form" || global.href) {
@@ -238,6 +245,7 @@ function configureAdmin(config) {
238
245
  });
239
246
  const studioSections = resolveStudioSections(config.studio?.sections || []);
240
247
  const studioSectionViews = resolveStudioSectionViews(config.studio?.sections || []);
248
+ const sitePreview = config.studio?.sitePreview;
241
249
  let cssPath;
242
250
  const pkgDist = getPkgDistDir();
243
251
  const sourceCssPath = import_path.default.resolve(pkgDist, "admin.css");
@@ -256,6 +264,50 @@ function configureAdmin(config) {
256
264
  cssPath = sourceCssPath;
257
265
  }
258
266
  const clientPath = "@orion-studios/payload-studio/admin/client";
267
+ const studioNavClientProps = {
268
+ brandName,
269
+ formSubmissionsCollectionSlug,
270
+ formsCollectionSlug,
271
+ formsEnabled,
272
+ formUploadsCollectionSlug,
273
+ globalsBasePath,
274
+ globalsExtraMatchPrefixes: [contactFormStudioPath],
275
+ logoUrl,
276
+ mediaCollectionSlug,
277
+ pagesCollectionSlug,
278
+ sections: studioSections
279
+ };
280
+ const studioBackBreadcrumbComponent = {
281
+ exportName: "StudioBackBreadcrumb",
282
+ path: clientPath
283
+ };
284
+ const hasMatchingComponent = (items, exportName) => Array.isArray(items) && items.some(
285
+ (item) => item && typeof item === "object" && item.exportName === exportName && item.path === clientPath
286
+ );
287
+ const appendComponent = (items, component, exportName) => hasMatchingComponent(items, exportName) ? items || [] : [...items || [], component];
288
+ const attachStudioBackBreadcrumbToCollection = (collection) => {
289
+ if (!studioEnabled) {
290
+ return collection;
291
+ }
292
+ const existingBeforeDocumentControls = collection.admin?.components?.edit?.beforeDocumentControls;
293
+ return {
294
+ ...collection,
295
+ admin: {
296
+ ...collection.admin,
297
+ components: {
298
+ ...collection.admin?.components,
299
+ edit: {
300
+ ...collection.admin?.components?.edit,
301
+ beforeDocumentControls: appendComponent(
302
+ existingBeforeDocumentControls,
303
+ studioBackBreadcrumbComponent,
304
+ "StudioBackBreadcrumb"
305
+ )
306
+ }
307
+ }
308
+ }
309
+ };
310
+ };
259
311
  return {
260
312
  admin: {
261
313
  css: cssPath,
@@ -264,19 +316,7 @@ function configureAdmin(config) {
264
316
  Nav: {
265
317
  exportName: "AdminStudioNav",
266
318
  path: clientPath,
267
- clientProps: {
268
- brandName,
269
- logoUrl,
270
- globalsBasePath: "/studio-globals",
271
- globalsExtraMatchPrefixes: [contactFormStudioPath],
272
- formSubmissionsCollectionSlug,
273
- formsCollectionSlug,
274
- formsEnabled,
275
- formUploadsCollectionSlug,
276
- mediaCollectionSlug,
277
- pagesCollectionSlug,
278
- sections: studioSections
279
- }
319
+ clientProps: studioNavClientProps
280
320
  }
281
321
  } : {},
282
322
  graphics: {
@@ -302,51 +342,64 @@ function configureAdmin(config) {
302
342
  Component: {
303
343
  exportName: studioEnabled ? "AdminStudioDashboard" : "Dashboard",
304
344
  path: clientPath,
305
- clientProps: {
306
- brandName,
307
- logoUrl,
308
- globalsBasePath: "/studio-globals",
309
- globalsExtraMatchPrefixes: [contactFormStudioPath],
310
- formSubmissionsCollectionSlug,
311
- formsCollectionSlug,
312
- formsEnabled,
313
- formUploadsCollectionSlug,
314
- mediaCollectionSlug,
315
- pagesCollectionSlug,
316
- sections: studioSections
317
- }
345
+ clientProps: studioNavClientProps
318
346
  }
319
347
  },
320
348
  ...studioEnabled ? {
321
349
  studioGlobals: {
322
- path: "/studio-globals",
350
+ path: globalsBasePath,
323
351
  Component: {
324
352
  exportName: "AdminStudioGlobalsView",
325
353
  path: clientPath,
326
354
  clientProps: {
355
+ ...studioNavClientProps,
327
356
  globals,
328
- globalsBasePath: "/studio-globals"
357
+ globalsBasePath
358
+ }
359
+ }
360
+ },
361
+ studioPages: {
362
+ path: pagesBasePath,
363
+ Component: {
364
+ exportName: "AdminStudioPagesListView",
365
+ path: clientPath,
366
+ clientProps: {
367
+ ...studioNavClientProps,
368
+ pagesCollectionSlug
369
+ }
370
+ }
371
+ },
372
+ studioPageEditor: {
373
+ path: `${pagesBasePath}/:id`,
374
+ Component: {
375
+ exportName: "AdminStudioPageEditView",
376
+ path: clientPath,
377
+ clientProps: {
378
+ ...studioNavClientProps,
379
+ builderBasePath
329
380
  }
330
381
  }
331
382
  },
332
383
  studioContactForm: {
333
- path: "/studio-contact-form",
384
+ path: contactFormStudioPath,
334
385
  Component: {
335
386
  exportName: "AdminStudioContactFormView",
336
387
  path: clientPath,
337
388
  clientProps: {
389
+ ...studioNavClientProps,
338
390
  globalSlug: "contact-form",
339
- globalsBasePath: "/studio-globals"
391
+ globalsBasePath
340
392
  }
341
393
  }
342
394
  },
343
395
  ...formsEnabled ? {
344
396
  studioForms: {
345
- path: "/studio-forms",
397
+ path: formsBasePath,
346
398
  Component: {
347
399
  exportName: "AdminStudioFormsView",
348
400
  path: clientPath,
349
401
  clientProps: {
402
+ ...studioNavClientProps,
350
403
  formsCollectionSlug,
351
404
  formSubmissionsCollectionSlug,
352
405
  formUploadsCollectionSlug
@@ -354,12 +407,41 @@ function configureAdmin(config) {
354
407
  }
355
408
  }
356
409
  } : {},
410
+ studioMedia: {
411
+ path: mediaBasePath,
412
+ Component: {
413
+ exportName: "AdminStudioMediaView",
414
+ path: clientPath,
415
+ clientProps: {
416
+ ...studioNavClientProps,
417
+ mediaCollectionSlug
418
+ }
419
+ }
420
+ },
421
+ studioTools: {
422
+ path: toolsBasePath,
423
+ Component: {
424
+ exportName: "AdminStudioToolsView",
425
+ path: clientPath,
426
+ clientProps: {
427
+ ...studioNavClientProps,
428
+ mediaCollectionSlug,
429
+ pagesCollectionSlug
430
+ }
431
+ }
432
+ },
357
433
  ...Object.fromEntries(
358
434
  Object.entries(studioSectionViews).map(([id, view]) => [
359
435
  id,
360
436
  {
361
437
  path: view.path,
362
- Component: view.Component
438
+ Component: {
439
+ ...view.Component,
440
+ clientProps: {
441
+ ...studioNavClientProps,
442
+ ...view.Component.clientProps || {}
443
+ }
444
+ }
363
445
  }
364
446
  ])
365
447
  )
@@ -370,19 +452,23 @@ function configureAdmin(config) {
370
452
  exportName: "ThemeProvider",
371
453
  path: clientPath,
372
454
  clientProps: {
455
+ allowThemePreference,
373
456
  defaultTheme
374
457
  }
375
458
  }
376
459
  ],
377
- afterNavLinks: [
378
- {
379
- exportName: "ThemeSwitcher",
380
- path: clientPath,
381
- clientProps: {
382
- defaultTheme
460
+ ...allowThemePreference ? {
461
+ afterNavLinks: [
462
+ {
463
+ exportName: "ThemeSwitcher",
464
+ path: clientPath,
465
+ clientProps: {
466
+ allowThemePreference,
467
+ defaultTheme
468
+ }
383
469
  }
384
- }
385
- ]
470
+ ]
471
+ } : {}
386
472
  },
387
473
  meta: {
388
474
  titleSuffix: ` \u2014 ${brandName}`
@@ -397,10 +483,76 @@ function configureAdmin(config) {
397
483
  const hasThemePreference = existingFields.some(
398
484
  (field) => typeof field === "object" && field !== null && "name" in field && field.name === "themePreference"
399
485
  );
400
- return {
486
+ const nextCollection = {
401
487
  ...usersCollection,
402
488
  fields: hasThemePreference ? existingFields : [...existingFields, createThemePreferenceField(defaultTheme)]
403
489
  };
490
+ return attachStudioBackBreadcrumbToCollection(nextCollection);
491
+ },
492
+ wrapPagesCollection(pagesCollection) {
493
+ if (!studioEnabled) {
494
+ return pagesCollection;
495
+ }
496
+ const collectionWithBreadcrumb = attachStudioBackBreadcrumbToCollection(pagesCollection);
497
+ const existingEditMenuItems = collectionWithBreadcrumb.admin?.components?.edit?.editMenuItems;
498
+ const existingViews = collectionWithBreadcrumb.admin?.components?.views;
499
+ const existingEditViews = existingViews?.edit;
500
+ const hasCustomEditView = Boolean(
501
+ existingEditViews?.root || existingEditViews?.default && typeof existingEditViews.default === "object" && existingEditViews.default.Component
502
+ );
503
+ return {
504
+ ...collectionWithBreadcrumb,
505
+ admin: {
506
+ ...collectionWithBreadcrumb.admin,
507
+ components: {
508
+ ...collectionWithBreadcrumb.admin?.components,
509
+ edit: {
510
+ ...collectionWithBreadcrumb.admin?.components?.edit,
511
+ editMenuItems: appendComponent(
512
+ existingEditMenuItems,
513
+ {
514
+ exportName: "OpenInStudioMenuItem",
515
+ path: clientPath,
516
+ clientProps: {
517
+ pagesPathBase: pagesBasePath
518
+ }
519
+ },
520
+ "OpenInStudioMenuItem"
521
+ )
522
+ },
523
+ views: {
524
+ ...existingViews,
525
+ ...hasCustomEditView ? {} : {
526
+ edit: {
527
+ ...existingEditViews,
528
+ default: {
529
+ ...typeof existingEditViews?.default === "object" ? existingEditViews.default : {},
530
+ Component: {
531
+ exportName: "PageEditRedirectToStudio",
532
+ path: clientPath,
533
+ clientProps: {
534
+ pagesPathBase: pagesBasePath
535
+ }
536
+ }
537
+ }
538
+ }
539
+ }
540
+ }
541
+ }
542
+ }
543
+ };
544
+ },
545
+ wrapMediaCollection(mediaCollection) {
546
+ return attachStudioBackBreadcrumbToCollection(mediaCollection);
547
+ },
548
+ wrapFormsCollection(formsCollection) {
549
+ return attachStudioBackBreadcrumbToCollection(formsCollection);
550
+ },
551
+ wrapFormSubmissionsCollection(formSubmissionsCollection) {
552
+ return attachStudioBackBreadcrumbToCollection(formSubmissionsCollection);
553
+ },
554
+ wrapFormUploadsCollection(formUploadsCollection) {
555
+ return attachStudioBackBreadcrumbToCollection(formUploadsCollection);
404
556
  },
405
557
  wrapGlobals(globals2) {
406
558
  const labelMap = {
@@ -414,24 +566,74 @@ function configureAdmin(config) {
414
566
  const mapping = labelMap[global.slug];
415
567
  if (!mapping) return global;
416
568
  const shouldAttachContactFormRedirect = studioEnabled && global.slug === "contact-form";
569
+ const shouldAttachHeaderEditView = studioEnabled && global.slug === "header";
570
+ const shouldAttachFooterEditView = studioEnabled && global.slug === "footer";
417
571
  const existingViews = global.admin?.components?.views;
418
572
  const existingEditViews = existingViews?.edit;
419
573
  const hasCustomContactFormEditView = Boolean(
420
574
  existingEditViews?.root || existingEditViews?.default && typeof existingEditViews.default === "object" && existingEditViews.default.Component
421
575
  );
422
- const contactFormEditViews = shouldAttachContactFormRedirect && !hasCustomContactFormEditView ? {
423
- ...existingEditViews,
424
- default: {
425
- ...typeof existingEditViews?.default === "object" ? existingEditViews.default : {},
426
- Component: {
427
- exportName: "StudioContactFormRedirect",
428
- path: clientPath,
429
- clientProps: {
430
- studioContactFormPath: contactFormStudioPath
576
+ const nextEditViews = (() => {
577
+ if (shouldAttachHeaderEditView && !hasCustomContactFormEditView) {
578
+ return {
579
+ ...existingEditViews,
580
+ default: {
581
+ ...typeof existingEditViews?.default === "object" ? existingEditViews.default : {},
582
+ Component: {
583
+ exportName: "AdminStudioHeaderGlobalView",
584
+ path: clientPath,
585
+ clientProps: {
586
+ ...studioNavClientProps,
587
+ actionHref: sitePreview?.header?.actionHref,
588
+ actionLabel: sitePreview?.header?.actionLabel,
589
+ globalSlug: global.slug,
590
+ locationSummary: sitePreview?.locationSummary,
591
+ pagesCollectionSlug
592
+ }
593
+ }
431
594
  }
432
- }
595
+ };
433
596
  }
434
- } : existingEditViews;
597
+ if (shouldAttachFooterEditView && !hasCustomContactFormEditView) {
598
+ return {
599
+ ...existingEditViews,
600
+ default: {
601
+ ...typeof existingEditViews?.default === "object" ? existingEditViews.default : {},
602
+ Component: {
603
+ exportName: "AdminStudioFooterGlobalView",
604
+ path: clientPath,
605
+ clientProps: {
606
+ ...studioNavClientProps,
607
+ builtByHref: sitePreview?.footer?.builtByHref,
608
+ builtByLabel: sitePreview?.footer?.builtByLabel,
609
+ description: sitePreview?.footer?.description,
610
+ footerCategories: sitePreview?.footer?.footerCategories,
611
+ footerLinks: sitePreview?.footer?.footerLinks,
612
+ globalSlug: global.slug,
613
+ locationSummary: sitePreview?.locationSummary
614
+ }
615
+ }
616
+ }
617
+ };
618
+ }
619
+ if (shouldAttachContactFormRedirect && !hasCustomContactFormEditView) {
620
+ return {
621
+ ...existingEditViews,
622
+ default: {
623
+ ...typeof existingEditViews?.default === "object" ? existingEditViews.default : {},
624
+ Component: {
625
+ exportName: "StudioContactFormRedirect",
626
+ path: clientPath,
627
+ clientProps: {
628
+ studioContactFormPath: contactFormStudioPath
629
+ }
630
+ }
631
+ }
632
+ };
633
+ }
634
+ return existingEditViews;
635
+ })();
636
+ const existingBeforeDocumentControls = global.admin?.components?.elements?.beforeDocumentControls;
435
637
  return {
436
638
  ...global,
437
639
  admin: {
@@ -439,12 +641,18 @@ function configureAdmin(config) {
439
641
  group: mapping.group,
440
642
  components: {
441
643
  ...global.admin?.components,
442
- ...shouldAttachContactFormRedirect ? {
644
+ elements: {
645
+ ...global.admin?.components?.elements,
646
+ beforeDocumentControls: studioEnabled ? appendComponent(
647
+ existingBeforeDocumentControls,
648
+ studioBackBreadcrumbComponent,
649
+ "StudioBackBreadcrumb"
650
+ ) : existingBeforeDocumentControls
651
+ },
652
+ ...nextEditViews ? {
443
653
  views: {
444
654
  ...existingViews,
445
- ...contactFormEditViews ? {
446
- edit: contactFormEditViews
447
- } : {}
655
+ edit: nextEditViews
448
656
  }
449
657
  } : {}
450
658
  }
@@ -3817,14 +4025,17 @@ function resolveSocialMediaLinks(data) {
3817
4025
  var studio_pages_exports = {};
3818
4026
  __export(studio_pages_exports, {
3819
4027
  createDefaultStudioDocument: () => createDefaultStudioDocument,
4028
+ createStudioPageService: () => createStudioPageService,
3820
4029
  defaultBuilderThemeTokens: () => defaultBuilderThemeTokens,
4030
+ getStudioDocumentFromPage: () => getStudioDocumentFromPage,
3821
4031
  layoutToStudioDocument: () => layoutToStudioDocument,
3822
4032
  pageInspectorPanels: () => pageInspectorPanels,
3823
4033
  pageNodeTypes: () => pageNodeTypes,
3824
4034
  pagePaletteGroups: () => pagePaletteGroups,
3825
4035
  pageStudioModuleManifest: () => pageStudioModuleManifest,
3826
4036
  resolveBuilderThemeTokens: () => resolveBuilderThemeTokens,
3827
- studioDocumentToLayout: () => studioDocumentToLayout
4037
+ studioDocumentToLayout: () => studioDocumentToLayout,
4038
+ toEditorInitialDoc: () => toEditorInitialDoc
3828
4039
  });
3829
4040
 
3830
4041
  // src/studio-pages/builder/settings-v2/themeTokens.ts
@@ -4201,10 +4412,207 @@ var inspectorDefinitionByBlockType = {
4201
4412
  }
4202
4413
  };
4203
4414
 
4204
- // src/studio-pages/migrations.ts
4415
+ // src/studio-pages/pageService.ts
4205
4416
  var isRecord5 = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
4206
- var assertPageStudioDocumentV1 = (value) => {
4417
+ var toRecordArray = (value) => Array.isArray(value) ? value.filter((item) => isRecord5(item)) : [];
4418
+ var getRelationID = (value) => {
4419
+ if (typeof value === "number" || typeof value === "string") {
4420
+ return value;
4421
+ }
4207
4422
  if (!isRecord5(value)) {
4423
+ return null;
4424
+ }
4425
+ const id = value.id;
4426
+ return typeof id === "number" || typeof id === "string" ? id : null;
4427
+ };
4428
+ var asLayoutArray = (value) => toRecordArray(value);
4429
+ var hydrateRelationship = (valueFromStudio, valueFromLayout) => {
4430
+ if (isRecord5(valueFromStudio)) {
4431
+ return valueFromStudio;
4432
+ }
4433
+ if (!isRecord5(valueFromLayout)) {
4434
+ return valueFromStudio;
4435
+ }
4436
+ const studioID = getRelationID(valueFromStudio);
4437
+ const layoutID = getRelationID(valueFromLayout);
4438
+ if (studioID === null || layoutID === null || String(studioID) !== String(layoutID)) {
4439
+ return valueFromStudio;
4440
+ }
4441
+ return valueFromLayout;
4442
+ };
4443
+ var hydrateDocumentWithLayoutRelations = (document, layout) => {
4444
+ const nextNodes = document.nodes.map((node, index) => {
4445
+ const layoutBlock = layout[index];
4446
+ if (!isRecord5(layoutBlock)) {
4447
+ return node;
4448
+ }
4449
+ if (typeof layoutBlock.blockType !== "string" || layoutBlock.blockType !== node.type) {
4450
+ return node;
4451
+ }
4452
+ const nextData = { ...node.data };
4453
+ if (node.type === "hero") {
4454
+ nextData.media = hydrateRelationship(nextData.media, layoutBlock.media);
4455
+ }
4456
+ if (node.type === "media") {
4457
+ nextData.image = hydrateRelationship(nextData.image, layoutBlock.image);
4458
+ }
4459
+ if (node.type === "featureGrid" || node.type === "logoWall" || node.type === "beforeAfter") {
4460
+ const studioItems = Array.isArray(nextData.items) ? nextData.items : [];
4461
+ const layoutItems = Array.isArray(layoutBlock.items) ? layoutBlock.items : [];
4462
+ nextData.items = studioItems.map((rawStudioItem, itemIndex) => {
4463
+ if (!isRecord5(rawStudioItem)) {
4464
+ return rawStudioItem;
4465
+ }
4466
+ const layoutItem = layoutItems[itemIndex];
4467
+ if (!isRecord5(layoutItem)) {
4468
+ return rawStudioItem;
4469
+ }
4470
+ const nextItem = { ...rawStudioItem };
4471
+ nextItem.media = hydrateRelationship(nextItem.media, layoutItem.media);
4472
+ nextItem.beforeMedia = hydrateRelationship(nextItem.beforeMedia, layoutItem.beforeMedia);
4473
+ nextItem.afterMedia = hydrateRelationship(nextItem.afterMedia, layoutItem.afterMedia);
4474
+ return nextItem;
4475
+ });
4476
+ }
4477
+ return {
4478
+ ...node,
4479
+ data: nextData
4480
+ };
4481
+ });
4482
+ return {
4483
+ ...document,
4484
+ nodes: nextNodes
4485
+ };
4486
+ };
4487
+ var normalizeDocument = (document) => ({
4488
+ ...document,
4489
+ schemaVersion: 1,
4490
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
4491
+ });
4492
+ var normalizeLegacyHeroDefaults = (document) => {
4493
+ const nodes = document.nodes.map((node) => {
4494
+ if (node.type !== "hero" || !isRecord5(node.data)) {
4495
+ return node;
4496
+ }
4497
+ const nextData = { ...node.data };
4498
+ const heroBackgroundColor = typeof nextData.backgroundColor === "string" ? nextData.backgroundColor.trim().toLowerCase() : "";
4499
+ const sectionBackgroundMode = typeof nextData.sectionBackgroundMode === "string" ? nextData.sectionBackgroundMode : "none";
4500
+ const hasBackgroundImageURL = typeof nextData.backgroundImageURL === "string" && nextData.backgroundImageURL.trim().length > 0;
4501
+ const mediaRelation = getRelationID(nextData.media);
4502
+ if (heroBackgroundColor === "#124a37" && sectionBackgroundMode === "none" && !hasBackgroundImageURL && mediaRelation === null) {
4503
+ nextData.backgroundColor = "";
4504
+ }
4505
+ return {
4506
+ ...node,
4507
+ data: nextData
4508
+ };
4509
+ });
4510
+ return {
4511
+ ...document,
4512
+ nodes
4513
+ };
4514
+ };
4515
+ var assertCanPublish = (issues) => {
4516
+ const publishErrors = issues.filter((issue) => issue.severity === "error");
4517
+ if (publishErrors.length > 0) {
4518
+ throw new Error(`Cannot publish page: ${publishErrors[0].message}`);
4519
+ }
4520
+ };
4521
+ var getStudioDocumentFromPage = (doc) => {
4522
+ const title = typeof doc.title === "string" ? doc.title : void 0;
4523
+ const layout = asLayoutArray(doc.layout);
4524
+ try {
4525
+ const studioDocument = assertStudioDocumentV1(doc.studioDocument);
4526
+ if (layout.length > 0) {
4527
+ return hydrateDocumentWithLayoutRelations(studioDocument, layout);
4528
+ }
4529
+ return studioDocument;
4530
+ } catch {
4531
+ if (layout.length > 0) {
4532
+ return layoutToStudioDocument(layout, title);
4533
+ }
4534
+ return createEmptyStudioDocument(title);
4535
+ }
4536
+ };
4537
+ var createStudioPageService = ({
4538
+ collectionSlug = "pages",
4539
+ modules,
4540
+ payload,
4541
+ user
4542
+ }) => ({
4543
+ getPageForStudio: async (pageID) => {
4544
+ const page = await payload.findByID({
4545
+ collection: collectionSlug,
4546
+ depth: 2,
4547
+ draft: true,
4548
+ id: pageID,
4549
+ overrideAccess: false,
4550
+ user
4551
+ });
4552
+ const studioDocument = getStudioDocumentFromPage(page);
4553
+ return {
4554
+ id: String(page.id),
4555
+ slug: typeof page.slug === "string" ? page.slug : "",
4556
+ studioDocument,
4557
+ title: typeof page.title === "string" ? page.title : "Untitled Page"
4558
+ };
4559
+ },
4560
+ validateStudioDocument: (document) => validateStudioDocument(document, modules),
4561
+ saveDraft: async (pageID, document, _metadata) => {
4562
+ const normalizedDocument = normalizeLegacyHeroDefaults(normalizeDocument(document));
4563
+ const compileResult = compileStudioDocument(normalizedDocument, modules);
4564
+ await payload.update({
4565
+ collection: collectionSlug,
4566
+ data: {
4567
+ _status: "draft",
4568
+ layout: compileResult.layout,
4569
+ studioDocument: normalizedDocument,
4570
+ studioValidationIssues: compileResult.issues,
4571
+ title: normalizedDocument.title
4572
+ },
4573
+ id: pageID,
4574
+ overrideAccess: false,
4575
+ user
4576
+ });
4577
+ return {
4578
+ id: pageID,
4579
+ status: "draft"
4580
+ };
4581
+ },
4582
+ publish: async (pageID, document, _metadata) => {
4583
+ const normalizedDocument = normalizeLegacyHeroDefaults(normalizeDocument(document));
4584
+ const compileResult = compileStudioDocument(normalizedDocument, modules);
4585
+ assertCanPublish(compileResult.issues);
4586
+ await payload.update({
4587
+ collection: collectionSlug,
4588
+ data: {
4589
+ _status: "published",
4590
+ layout: compileResult.layout,
4591
+ studioDocument: normalizedDocument,
4592
+ studioValidationIssues: compileResult.issues,
4593
+ title: normalizedDocument.title
4594
+ },
4595
+ id: pageID,
4596
+ overrideAccess: false,
4597
+ user
4598
+ });
4599
+ return {
4600
+ id: pageID,
4601
+ status: "published"
4602
+ };
4603
+ }
4604
+ });
4605
+ var toEditorInitialDoc = (payloadPage) => ({
4606
+ layout: studioDocumentToLayout(payloadPage.studioDocument),
4607
+ slug: typeof payloadPage.slug === "string" ? payloadPage.slug : "",
4608
+ studioDocument: payloadPage.studioDocument,
4609
+ title: payloadPage.title
4610
+ });
4611
+
4612
+ // src/studio-pages/migrations.ts
4613
+ var isRecord6 = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
4614
+ var assertPageStudioDocumentV1 = (value) => {
4615
+ if (!isRecord6(value)) {
4208
4616
  throw new Error("Studio document must be an object");
4209
4617
  }
4210
4618
  if (value.schemaVersion !== 1) {
@@ -4214,7 +4622,7 @@ var assertPageStudioDocumentV1 = (value) => {
4214
4622
  throw new Error("Studio document nodes must be an array");
4215
4623
  }
4216
4624
  const nodes = value.nodes.map((node, index) => {
4217
- if (!isRecord5(node)) {
4625
+ if (!isRecord6(node)) {
4218
4626
  throw new Error(`Node at index ${index} must be an object`);
4219
4627
  }
4220
4628
  if (typeof node.id !== "string" || node.id.length === 0) {
@@ -4223,7 +4631,7 @@ var assertPageStudioDocumentV1 = (value) => {
4223
4631
  if (typeof node.type !== "string" || node.type.length === 0) {
4224
4632
  throw new Error(`Node at index ${index} has invalid type`);
4225
4633
  }
4226
- if (!isRecord5(node.data)) {
4634
+ if (!isRecord6(node.data)) {
4227
4635
  throw new Error(`Node at index ${index} has invalid data`);
4228
4636
  }
4229
4637
  return {
@@ -4233,7 +4641,7 @@ var assertPageStudioDocumentV1 = (value) => {
4233
4641
  };
4234
4642
  });
4235
4643
  return {
4236
- metadata: isRecord5(value.metadata) ? value.metadata : void 0,
4644
+ metadata: isRecord6(value.metadata) ? value.metadata : void 0,
4237
4645
  nodes,
4238
4646
  schemaVersion: 1,
4239
4647
  title: typeof value.title === "string" ? value.title : void 0,