@orion-studios/payload-studio 0.5.0-beta.98 → 0.6.0-beta.1

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 (63) hide show
  1. package/README.md +58 -68
  2. package/dist/admin/client.d.mts +5 -0
  3. package/dist/admin/client.d.ts +5 -0
  4. package/dist/admin/client.js +4491 -736
  5. package/dist/admin/client.mjs +3367 -752
  6. package/dist/admin/index.d.mts +2 -1
  7. package/dist/admin/index.d.ts +2 -1
  8. package/dist/admin/index.js +498 -53
  9. package/dist/admin/index.mjs +2 -1
  10. package/dist/admin-app/client.d.mts +1 -0
  11. package/dist/admin-app/client.d.ts +1 -0
  12. package/dist/admin-app/client.js +285 -109
  13. package/dist/admin-app/client.mjs +59 -871
  14. package/dist/admin-app/index.d.mts +2 -1
  15. package/dist/admin-app/index.d.ts +2 -1
  16. package/dist/admin-app/index.mjs +5 -3
  17. package/dist/admin-app/styles.css +1708 -56
  18. package/dist/admin.css +158 -35
  19. package/dist/blocks/index.js +415 -200
  20. package/dist/blocks/index.mjs +2 -2
  21. package/dist/{chunk-XK3K5GRP.mjs → chunk-JQAHXYAM.mjs} +271 -67
  22. package/dist/chunk-KPIX7OSV.mjs +1051 -0
  23. package/dist/chunk-OQSEJXC4.mjs +166 -0
  24. package/dist/{chunk-XHWQJUX5.mjs → chunk-OTHERBGX.mjs} +3 -3
  25. package/dist/chunk-PF3EBZXF.mjs +326 -0
  26. package/dist/chunk-Q2HGC67S.mjs +904 -0
  27. package/dist/{chunk-XVH5SCBD.mjs → chunk-RKTIFEUY.mjs} +4 -19
  28. package/dist/chunk-W2UOCJDX.mjs +32 -0
  29. package/dist/{chunk-C4J35SPJ.mjs → chunk-XKUTZ7IU.mjs} +257 -452
  30. package/dist/{index-ZbOx4OCF.d.ts → index-52HdVLQq.d.ts} +12 -22
  31. package/dist/index-BMitiKK8.d.ts +435 -0
  32. package/dist/index-Crx_MtPw.d.ts +223 -0
  33. package/dist/index-Cv-6qnrw.d.mts +223 -0
  34. package/dist/{index-ZbOx4OCF.d.mts → index-DEQC3Dwj.d.mts} +12 -22
  35. package/dist/{index-BIwu3qIH.d.mts → index-DWmudwDm.d.mts} +2 -1
  36. package/dist/{index-BIwu3qIH.d.ts → index-DWmudwDm.d.ts} +2 -1
  37. package/dist/index-D_b24Gef.d.mts +435 -0
  38. package/dist/index.d.mts +5 -4
  39. package/dist/index.d.ts +5 -4
  40. package/dist/index.js +1968 -1198
  41. package/dist/index.mjs +10 -8
  42. package/dist/nextjs/index.js +5 -684
  43. package/dist/nextjs/index.mjs +2 -3
  44. package/dist/sitePreviewTypes-BkHCWxNW.d.mts +58 -0
  45. package/dist/sitePreviewTypes-BkHCWxNW.d.ts +58 -0
  46. package/dist/studio/index.d.mts +1 -1
  47. package/dist/studio/index.d.ts +1 -1
  48. package/dist/studio-pages/builder.css +125 -83
  49. package/dist/studio-pages/client.d.mts +58 -1
  50. package/dist/studio-pages/client.d.ts +58 -1
  51. package/dist/studio-pages/client.js +450 -241
  52. package/dist/studio-pages/client.mjs +455 -247
  53. package/dist/studio-pages/index.d.mts +3 -2
  54. package/dist/studio-pages/index.d.ts +3 -2
  55. package/dist/studio-pages/index.js +418 -183
  56. package/dist/studio-pages/index.mjs +15 -6
  57. package/package.json +19 -5
  58. package/dist/chunk-2FO2ROW4.mjs +0 -468
  59. package/dist/chunk-SIL2J5MF.mjs +0 -155
  60. package/dist/index-BFXZue5i.d.ts +0 -178
  61. package/dist/index-CoYRBbf6.d.mts +0 -178
  62. package/dist/index-R7hA134j.d.mts +0 -140
  63. package/dist/index-vjrjy0P4.d.ts +0 -140
@@ -1,3 +1,4 @@
1
- export { A as AdminConfig, C as CreateSocialMediaConnectionsFieldOptions, a as CreateSocialMediaGlobalOptions, c as configureAdmin, b as createHeaderNavItemsField, d as createSocialMediaConnectionsField, e as createSocialMediaGlobal, f as createThemePreferenceField, s as socialMediaConnectionsField, t as themePreferenceField, w as withTooltips } from '../index-CoYRBbf6.mjs';
1
+ export { A as AdminConfig, a as AdminStudioConfig, b as AdminStudioFooterPreviewConfig, c as AdminStudioHeaderPreviewConfig, d as AdminStudioSitePreviewConfig, C as CreateSocialMediaConnectionsFieldOptions, e as CreateSocialMediaGlobalOptions, R as ResolvedStudioSection, S as StudioGlobalLink, f as StudioSection, g as StudioSectionCard, h as StudioSectionComponent, j as StudioSectionRole, k as StudioSectionView, l as configureAdmin, m as createHeaderNavItemsField, n as createSocialMediaConnectionsField, o as createSocialMediaGlobal, p as createThemePreferenceField, s as socialMediaConnectionsField, t as themePreferenceField, w as withTooltips } from '../index-D_b24Gef.mjs';
2
2
  export { b as SOCIAL_MEDIA_DEFAULT_ICON_BY_PLATFORM, c as SOCIAL_MEDIA_ICON_OPTIONS, d as SOCIAL_MEDIA_PLATFORMS, e as SOCIAL_MEDIA_PLATFORM_LABELS, S as SocialMediaGlobalData, f as SocialMediaIconLibrary, g as SocialMediaIconOption, a as SocialMediaPlatform, h as SocialMediaProfileData, i as SocialMediaProfilesData } from '../socialMedia-C05Iy-SV.mjs';
3
3
  import 'payload';
4
+ import '../sitePreviewTypes-BkHCWxNW.mjs';
@@ -1,3 +1,4 @@
1
- export { A as AdminConfig, C as CreateSocialMediaConnectionsFieldOptions, a as CreateSocialMediaGlobalOptions, c as configureAdmin, b as createHeaderNavItemsField, d as createSocialMediaConnectionsField, e as createSocialMediaGlobal, f as createThemePreferenceField, s as socialMediaConnectionsField, t as themePreferenceField, w as withTooltips } from '../index-BFXZue5i.js';
1
+ export { A as AdminConfig, a as AdminStudioConfig, b as AdminStudioFooterPreviewConfig, c as AdminStudioHeaderPreviewConfig, d as AdminStudioSitePreviewConfig, C as CreateSocialMediaConnectionsFieldOptions, e as CreateSocialMediaGlobalOptions, R as ResolvedStudioSection, S as StudioGlobalLink, f as StudioSection, g as StudioSectionCard, h as StudioSectionComponent, j as StudioSectionRole, k as StudioSectionView, l as configureAdmin, m as createHeaderNavItemsField, n as createSocialMediaConnectionsField, o as createSocialMediaGlobal, p as createThemePreferenceField, s as socialMediaConnectionsField, t as themePreferenceField, w as withTooltips } from '../index-BMitiKK8.js';
2
2
  export { b as SOCIAL_MEDIA_DEFAULT_ICON_BY_PLATFORM, c as SOCIAL_MEDIA_ICON_OPTIONS, d as SOCIAL_MEDIA_PLATFORMS, e as SOCIAL_MEDIA_PLATFORM_LABELS, S as SocialMediaGlobalData, f as SocialMediaIconLibrary, g as SocialMediaIconOption, a as SocialMediaPlatform, h as SocialMediaProfileData, i as SocialMediaProfilesData } from '../socialMedia-C05Iy-SV.js';
3
3
  import 'payload';
4
+ import '../sitePreviewTypes-BkHCWxNW.js';
@@ -68,6 +68,128 @@ var createThemePreferenceField = (defaultTheme = "brand-light") => ({
68
68
  });
69
69
  var themePreferenceField = createThemePreferenceField("brand-light");
70
70
 
71
+ // src/admin-app/routeRegistry.ts
72
+ var adminNavIcons = [
73
+ "dashboard",
74
+ "pages",
75
+ "forms",
76
+ "globals",
77
+ "media",
78
+ "tools",
79
+ "account",
80
+ "analytics"
81
+ ];
82
+
83
+ // src/shared/studioSections.ts
84
+ var studioRoles = /* @__PURE__ */ new Set(["admin", "editor", "client"]);
85
+ var studioIcons = new Set(adminNavIcons);
86
+ var isRecord = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
87
+ var isAbsoluteExternalURL = (value) => /^[a-zA-Z][a-zA-Z\d+\-.]*:/.test(value) || value.startsWith("//");
88
+ var normalizePathLikeValue = (value) => {
89
+ const trimmed = value.trim();
90
+ if (!trimmed) {
91
+ return "";
92
+ }
93
+ if (isAbsoluteExternalURL(trimmed)) {
94
+ return trimmed;
95
+ }
96
+ const withLeadingSlash = trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
97
+ const normalized = withLeadingSlash.replace(/\/+$/, "");
98
+ return normalized || "/";
99
+ };
100
+ var normalizeStringArray = (value) => {
101
+ if (!Array.isArray(value)) {
102
+ return [];
103
+ }
104
+ return value.filter((entry) => typeof entry === "string").map((entry) => normalizePathLikeValue(entry)).filter((entry) => entry.length > 0);
105
+ };
106
+ var normalizeRoles = (value) => {
107
+ if (!Array.isArray(value)) {
108
+ return void 0;
109
+ }
110
+ const roles = value.filter((entry) => typeof entry === "string" && studioRoles.has(entry));
111
+ return roles.length > 0 ? roles : void 0;
112
+ };
113
+ var normalizeCard = (value) => {
114
+ if (!isRecord(value) || typeof value.title !== "string") {
115
+ return void 0;
116
+ }
117
+ const title = value.title.trim();
118
+ if (!title) {
119
+ return void 0;
120
+ }
121
+ return {
122
+ title,
123
+ ...typeof value.description === "string" && value.description.trim().length > 0 ? { description: value.description.trim() } : {}
124
+ };
125
+ };
126
+ var normalizeIcon = (value) => typeof value === "string" && studioIcons.has(value) ? value : void 0;
127
+ var resolveStudioSections = (value) => {
128
+ if (!Array.isArray(value)) {
129
+ return [];
130
+ }
131
+ const sections = [];
132
+ const seen = /* @__PURE__ */ new Set();
133
+ for (const entry of value) {
134
+ if (!isRecord(entry) || typeof entry.id !== "string" || typeof entry.label !== "string") {
135
+ continue;
136
+ }
137
+ const id = entry.id.trim();
138
+ const label = entry.label.trim();
139
+ if (!id || !label || seen.has(id)) {
140
+ continue;
141
+ }
142
+ const href = typeof entry.href === "string" && entry.href.trim().length > 0 ? normalizePathLikeValue(entry.href) : isRecord(entry.view) && typeof entry.view.path === "string" ? normalizePathLikeValue(entry.view.path) : "";
143
+ if (!href) {
144
+ continue;
145
+ }
146
+ const matchPrefixes = Array.from(/* @__PURE__ */ new Set([href, ...normalizeStringArray(entry.matchPrefixes)]));
147
+ sections.push({
148
+ id,
149
+ label,
150
+ href,
151
+ matchPrefixes,
152
+ ...normalizeIcon(entry.icon) ? { icon: normalizeIcon(entry.icon) } : {},
153
+ ...normalizeRoles(entry.roles) ? { roles: normalizeRoles(entry.roles) } : {},
154
+ ...normalizeCard(entry.card) ? { card: normalizeCard(entry.card) } : {}
155
+ });
156
+ seen.add(id);
157
+ }
158
+ return sections;
159
+ };
160
+ var resolveStudioSectionViews = (value) => {
161
+ if (!Array.isArray(value)) {
162
+ return {};
163
+ }
164
+ const views = {};
165
+ for (const entry of value) {
166
+ if (!isRecord(entry) || typeof entry.id !== "string" || !isRecord(entry.view)) {
167
+ continue;
168
+ }
169
+ const id = entry.id.trim();
170
+ const view = entry.view;
171
+ const component = isRecord(view.Component) ? view.Component : null;
172
+ if (!id || typeof view.path !== "string" || !component || typeof component.exportName !== "string" || typeof component.path !== "string") {
173
+ continue;
174
+ }
175
+ const path2 = normalizePathLikeValue(view.path);
176
+ const componentPath = component.path.trim();
177
+ const exportName = component.exportName.trim();
178
+ if (!path2 || !componentPath || !exportName) {
179
+ continue;
180
+ }
181
+ views[id] = {
182
+ path: path2,
183
+ Component: {
184
+ exportName,
185
+ path: componentPath,
186
+ ...isRecord(component.clientProps) ? { clientProps: component.clientProps } : {}
187
+ }
188
+ };
189
+ }
190
+ return views;
191
+ };
192
+
71
193
  // src/admin/helpers/configureAdmin.ts
72
194
  var import_meta = {};
73
195
  function getPkgDistDir() {
@@ -93,17 +215,28 @@ function configureAdmin(config) {
93
215
  brandPrimary = "#3b82f6",
94
216
  brandSecondary = "#8b5cf6",
95
217
  defaultTheme = "brand-light",
96
- logoUrl
218
+ logoUrl,
219
+ allowThemePreference = false
97
220
  } = config;
98
221
  const studioEnabled = config.studio?.enabled ?? true;
222
+ const formsEnabled = config.studio?.forms?.enabled ?? false;
223
+ const formsCollectionSlug = config.studio?.forms?.collectionSlug || "forms";
224
+ const formSubmissionsCollectionSlug = config.studio?.forms?.submissionsCollectionSlug || "form-submissions";
225
+ const formUploadsCollectionSlug = config.studio?.forms?.uploadsCollectionSlug || "form-uploads";
99
226
  const pagesCollectionSlug = config.studio?.pages?.collectionSlug || "pages";
227
+ const builderBasePath = config.studio?.pages?.builderBasePath || "/builder";
100
228
  const mediaCollectionSlug = config.studio?.media?.collectionSlug || "media";
101
- const contactFormStudioPath = "/studio-contact-form";
229
+ const globalsBasePath = "/site-globals";
230
+ const pagesBasePath = "/pages";
231
+ const formsBasePath = "/forms";
232
+ const mediaBasePath = "/media";
233
+ const toolsBasePath = "/tools";
234
+ const contactFormStudioPath = "/contact-form";
102
235
  const configuredGlobals = config.studio?.globals || [
103
236
  { slug: "site-settings", label: "Website Settings" },
104
237
  { slug: "header", label: "Header & Navigation" },
105
238
  { slug: "footer", label: "Footer" },
106
- { slug: "contact-form", label: "Contact Form" }
239
+ { slug: "social-media", label: "Social Media" }
107
240
  ];
108
241
  const globals = configuredGlobals.map((global) => {
109
242
  if (global.slug !== "contact-form" || global.href) {
@@ -114,24 +247,80 @@ function configureAdmin(config) {
114
247
  href: contactFormStudioPath
115
248
  };
116
249
  });
250
+ const studioSections = resolveStudioSections(config.studio?.sections || []);
251
+ const studioSectionViews = resolveStudioSectionViews(config.studio?.sections || []);
252
+ const sitePreview = config.studio?.sitePreview;
117
253
  let cssPath;
118
254
  const pkgDist = getPkgDistDir();
119
255
  const sourceCssPath = import_path.default.resolve(pkgDist, "admin.css");
120
- if (config.basePath && import_fs.default.existsSync(sourceCssPath)) {
121
- let css = import_fs.default.readFileSync(sourceCssPath, "utf-8");
122
- css = css.replace("--brand-primary: #3b82f6;", `--brand-primary: ${brandPrimary};`);
123
- css = css.replace("--brand-secondary: #8b5cf6;", `--brand-secondary: ${brandSecondary};`);
124
- const genDir = import_path.default.resolve(config.basePath, ".generated");
256
+ const adminAppCssPath = import_path.default.resolve(pkgDist, "admin-app", "styles.css");
257
+ const cssSources = [sourceCssPath, adminAppCssPath].filter((filePath) => import_fs.default.existsSync(filePath));
258
+ if (cssSources.length === 0) {
259
+ cssPath = sourceCssPath;
260
+ } else {
261
+ let css = cssSources.map((filePath) => import_fs.default.readFileSync(filePath, "utf-8")).join("\n\n");
262
+ css = css.replace(
263
+ "--orion-cms-brand-primary-fallback: #3b82f6;",
264
+ `--orion-cms-brand-primary-fallback: ${brandPrimary};`
265
+ );
266
+ css = css.replace(
267
+ "--orion-cms-brand-secondary-fallback: #8b5cf6;",
268
+ `--orion-cms-brand-secondary-fallback: ${brandSecondary};`
269
+ );
270
+ const outputBasePath = config.basePath || process.cwd();
271
+ const genDir = import_path.default.resolve(outputBasePath, ".generated");
125
272
  if (!import_fs.default.existsSync(genDir)) {
126
273
  import_fs.default.mkdirSync(genDir, { recursive: true });
127
274
  }
128
275
  const genPath = import_path.default.resolve(genDir, "admin.css");
129
276
  import_fs.default.writeFileSync(genPath, css);
130
277
  cssPath = genPath;
131
- } else {
132
- cssPath = sourceCssPath;
133
278
  }
134
279
  const clientPath = "@orion-studios/payload-studio/admin/client";
280
+ const studioNavClientProps = {
281
+ brandName,
282
+ formSubmissionsCollectionSlug,
283
+ formsCollectionSlug,
284
+ formsEnabled,
285
+ formUploadsCollectionSlug,
286
+ globalsBasePath,
287
+ globalsExtraMatchPrefixes: [contactFormStudioPath],
288
+ logoUrl,
289
+ mediaCollectionSlug,
290
+ pagesCollectionSlug,
291
+ sections: studioSections
292
+ };
293
+ const studioBackBreadcrumbComponent = {
294
+ exportName: "StudioBackBreadcrumb",
295
+ path: clientPath
296
+ };
297
+ const hasMatchingComponent = (items, exportName) => Array.isArray(items) && items.some(
298
+ (item) => item && typeof item === "object" && item.exportName === exportName && item.path === clientPath
299
+ );
300
+ const appendComponent = (items, component, exportName) => hasMatchingComponent(items, exportName) ? items || [] : [...items || [], component];
301
+ const attachStudioBackBreadcrumbToCollection = (collection) => {
302
+ if (!studioEnabled) {
303
+ return collection;
304
+ }
305
+ const existingBeforeDocumentControls = collection.admin?.components?.edit?.beforeDocumentControls;
306
+ return {
307
+ ...collection,
308
+ admin: {
309
+ ...collection.admin,
310
+ components: {
311
+ ...collection.admin?.components,
312
+ edit: {
313
+ ...collection.admin?.components?.edit,
314
+ beforeDocumentControls: appendComponent(
315
+ existingBeforeDocumentControls,
316
+ studioBackBreadcrumbComponent,
317
+ "StudioBackBreadcrumb"
318
+ )
319
+ }
320
+ }
321
+ }
322
+ };
323
+ };
135
324
  return {
136
325
  admin: {
137
326
  css: cssPath,
@@ -140,14 +329,7 @@ function configureAdmin(config) {
140
329
  Nav: {
141
330
  exportName: "AdminStudioNav",
142
331
  path: clientPath,
143
- clientProps: {
144
- brandName,
145
- logoUrl,
146
- globalsBasePath: "/studio-globals",
147
- globalsExtraMatchPrefixes: [contactFormStudioPath],
148
- mediaCollectionSlug,
149
- pagesCollectionSlug
150
- }
332
+ clientProps: studioNavClientProps
151
333
  }
152
334
  } : {},
153
335
  graphics: {
@@ -173,39 +355,131 @@ function configureAdmin(config) {
173
355
  Component: {
174
356
  exportName: studioEnabled ? "AdminStudioDashboard" : "Dashboard",
175
357
  path: clientPath,
176
- clientProps: {
177
- brandName,
178
- logoUrl,
179
- globalsBasePath: "/studio-globals",
180
- globalsExtraMatchPrefixes: [contactFormStudioPath],
181
- mediaCollectionSlug,
182
- pagesCollectionSlug
183
- }
358
+ clientProps: studioNavClientProps
184
359
  }
185
360
  },
186
361
  ...studioEnabled ? {
187
362
  studioGlobals: {
188
- path: "/studio-globals",
363
+ path: globalsBasePath,
189
364
  Component: {
190
365
  exportName: "AdminStudioGlobalsView",
191
366
  path: clientPath,
192
367
  clientProps: {
368
+ ...studioNavClientProps,
193
369
  globals,
194
- globalsBasePath: "/studio-globals"
370
+ globalsBasePath
371
+ }
372
+ }
373
+ },
374
+ studioPages: {
375
+ path: pagesBasePath,
376
+ Component: {
377
+ exportName: "AdminStudioPagesListView",
378
+ path: clientPath,
379
+ clientProps: {
380
+ ...studioNavClientProps,
381
+ pagesCollectionSlug
382
+ }
383
+ }
384
+ },
385
+ studioPageEditor: {
386
+ path: `${pagesBasePath}/:id`,
387
+ Component: {
388
+ exportName: "AdminStudioPageEditView",
389
+ path: clientPath,
390
+ clientProps: {
391
+ ...studioNavClientProps,
392
+ builderBasePath
393
+ }
394
+ }
395
+ },
396
+ studioPageNew: {
397
+ path: `${pagesBasePath}/new`,
398
+ Component: {
399
+ exportName: "AdminStudioNewPageView",
400
+ path: clientPath,
401
+ clientProps: {
402
+ ...studioNavClientProps,
403
+ pagesCollectionSlug
195
404
  }
196
405
  }
197
406
  },
198
407
  studioContactForm: {
199
- path: "/studio-contact-form",
408
+ path: contactFormStudioPath,
200
409
  Component: {
201
410
  exportName: "AdminStudioContactFormView",
202
411
  path: clientPath,
203
412
  clientProps: {
413
+ ...studioNavClientProps,
204
414
  globalSlug: "contact-form",
205
- globalsBasePath: "/studio-globals"
415
+ globalsBasePath
206
416
  }
207
417
  }
208
- }
418
+ },
419
+ ...formsEnabled ? {
420
+ studioForms: {
421
+ path: formsBasePath,
422
+ Component: {
423
+ exportName: "AdminStudioFormsView",
424
+ path: clientPath,
425
+ clientProps: {
426
+ ...studioNavClientProps,
427
+ formsCollectionSlug,
428
+ formSubmissionsCollectionSlug,
429
+ formUploadsCollectionSlug
430
+ }
431
+ }
432
+ }
433
+ } : {},
434
+ studioMedia: {
435
+ path: mediaBasePath,
436
+ Component: {
437
+ exportName: "AdminStudioMediaView",
438
+ path: clientPath,
439
+ clientProps: {
440
+ ...studioNavClientProps,
441
+ mediaCollectionSlug
442
+ }
443
+ }
444
+ },
445
+ studioMediaItem: {
446
+ path: `${mediaBasePath}/:id`,
447
+ Component: {
448
+ exportName: "AdminStudioMediaItemView",
449
+ path: clientPath,
450
+ clientProps: {
451
+ ...studioNavClientProps,
452
+ mediaCollectionSlug
453
+ }
454
+ }
455
+ },
456
+ studioTools: {
457
+ path: toolsBasePath,
458
+ Component: {
459
+ exportName: "AdminStudioToolsView",
460
+ path: clientPath,
461
+ clientProps: {
462
+ ...studioNavClientProps,
463
+ mediaCollectionSlug,
464
+ pagesCollectionSlug
465
+ }
466
+ }
467
+ },
468
+ ...Object.fromEntries(
469
+ Object.entries(studioSectionViews).map(([id, view]) => [
470
+ id,
471
+ {
472
+ path: view.path,
473
+ Component: {
474
+ ...view.Component,
475
+ clientProps: {
476
+ ...studioNavClientProps,
477
+ ...view.Component.clientProps || {}
478
+ }
479
+ }
480
+ }
481
+ ])
482
+ )
209
483
  } : {}
210
484
  },
211
485
  providers: [
@@ -213,19 +487,33 @@ function configureAdmin(config) {
213
487
  exportName: "ThemeProvider",
214
488
  path: clientPath,
215
489
  clientProps: {
490
+ allowThemePreference,
216
491
  defaultTheme
217
492
  }
218
493
  }
219
494
  ],
220
- afterNavLinks: [
495
+ beforeLogin: [
221
496
  {
222
- exportName: "ThemeSwitcher",
497
+ exportName: "AdminLoginIntro",
223
498
  path: clientPath,
224
499
  clientProps: {
225
- defaultTheme
500
+ brandName,
501
+ logoUrl
226
502
  }
227
503
  }
228
- ]
504
+ ],
505
+ ...allowThemePreference ? {
506
+ afterNavLinks: [
507
+ {
508
+ exportName: "ThemeSwitcher",
509
+ path: clientPath,
510
+ clientProps: {
511
+ allowThemePreference,
512
+ defaultTheme
513
+ }
514
+ }
515
+ ]
516
+ } : {}
229
517
  },
230
518
  meta: {
231
519
  titleSuffix: ` \u2014 ${brandName}`
@@ -240,10 +528,76 @@ function configureAdmin(config) {
240
528
  const hasThemePreference = existingFields.some(
241
529
  (field) => typeof field === "object" && field !== null && "name" in field && field.name === "themePreference"
242
530
  );
243
- return {
531
+ const nextCollection = {
244
532
  ...usersCollection,
245
- fields: hasThemePreference ? existingFields : [...existingFields, createThemePreferenceField(defaultTheme)]
533
+ fields: !allowThemePreference || hasThemePreference ? existingFields : [...existingFields, createThemePreferenceField(defaultTheme)]
246
534
  };
535
+ return attachStudioBackBreadcrumbToCollection(nextCollection);
536
+ },
537
+ wrapPagesCollection(pagesCollection) {
538
+ if (!studioEnabled) {
539
+ return pagesCollection;
540
+ }
541
+ const collectionWithBreadcrumb = attachStudioBackBreadcrumbToCollection(pagesCollection);
542
+ const existingEditMenuItems = collectionWithBreadcrumb.admin?.components?.edit?.editMenuItems;
543
+ const existingViews = collectionWithBreadcrumb.admin?.components?.views;
544
+ const existingEditViews = existingViews?.edit;
545
+ const hasCustomEditView = Boolean(
546
+ existingEditViews?.root || existingEditViews?.default && typeof existingEditViews.default === "object" && existingEditViews.default.Component
547
+ );
548
+ return {
549
+ ...collectionWithBreadcrumb,
550
+ admin: {
551
+ ...collectionWithBreadcrumb.admin,
552
+ components: {
553
+ ...collectionWithBreadcrumb.admin?.components,
554
+ edit: {
555
+ ...collectionWithBreadcrumb.admin?.components?.edit,
556
+ editMenuItems: appendComponent(
557
+ existingEditMenuItems,
558
+ {
559
+ exportName: "OpenInStudioMenuItem",
560
+ path: clientPath,
561
+ clientProps: {
562
+ pagesPathBase: pagesBasePath
563
+ }
564
+ },
565
+ "OpenInStudioMenuItem"
566
+ )
567
+ },
568
+ views: {
569
+ ...existingViews,
570
+ ...hasCustomEditView ? {} : {
571
+ edit: {
572
+ ...existingEditViews,
573
+ default: {
574
+ ...typeof existingEditViews?.default === "object" ? existingEditViews.default : {},
575
+ Component: {
576
+ exportName: "PageEditRedirectToStudio",
577
+ path: clientPath,
578
+ clientProps: {
579
+ pagesPathBase: pagesBasePath
580
+ }
581
+ }
582
+ }
583
+ }
584
+ }
585
+ }
586
+ }
587
+ }
588
+ };
589
+ },
590
+ wrapMediaCollection(mediaCollection) {
591
+ return attachStudioBackBreadcrumbToCollection(mediaCollection);
592
+ },
593
+ wrapFormsCollection(formsCollection) {
594
+ return attachStudioBackBreadcrumbToCollection(formsCollection);
595
+ },
596
+ wrapFormSubmissionsCollection(formSubmissionsCollection) {
597
+ return attachStudioBackBreadcrumbToCollection(formSubmissionsCollection);
598
+ },
599
+ wrapFormUploadsCollection(formUploadsCollection) {
600
+ return attachStudioBackBreadcrumbToCollection(formUploadsCollection);
247
601
  },
248
602
  wrapGlobals(globals2) {
249
603
  const labelMap = {
@@ -256,25 +610,110 @@ function configureAdmin(config) {
256
610
  return globals2.map((global) => {
257
611
  const mapping = labelMap[global.slug];
258
612
  if (!mapping) return global;
613
+ const shouldAttachSiteSettingsEditView = studioEnabled && global.slug === "site-settings";
614
+ const shouldAttachSocialMediaEditView = studioEnabled && global.slug === "social-media";
259
615
  const shouldAttachContactFormRedirect = studioEnabled && global.slug === "contact-form";
616
+ const shouldAttachHeaderEditView = studioEnabled && global.slug === "header";
617
+ const shouldAttachFooterEditView = studioEnabled && global.slug === "footer";
260
618
  const existingViews = global.admin?.components?.views;
261
619
  const existingEditViews = existingViews?.edit;
262
- const hasCustomContactFormEditView = Boolean(
620
+ const hasCustomEditView = Boolean(
263
621
  existingEditViews?.root || existingEditViews?.default && typeof existingEditViews.default === "object" && existingEditViews.default.Component
264
622
  );
265
- const contactFormEditViews = shouldAttachContactFormRedirect && !hasCustomContactFormEditView ? {
266
- ...existingEditViews,
267
- default: {
268
- ...typeof existingEditViews?.default === "object" ? existingEditViews.default : {},
269
- Component: {
270
- exportName: "StudioContactFormRedirect",
271
- path: clientPath,
272
- clientProps: {
273
- studioContactFormPath: contactFormStudioPath
623
+ const nextEditViews = (() => {
624
+ if (shouldAttachSiteSettingsEditView && !hasCustomEditView) {
625
+ return {
626
+ ...existingEditViews,
627
+ default: {
628
+ ...typeof existingEditViews?.default === "object" ? existingEditViews.default : {},
629
+ Component: {
630
+ exportName: "AdminStudioSiteSettingsGlobalView",
631
+ path: clientPath,
632
+ clientProps: {
633
+ ...studioNavClientProps,
634
+ globalSlug: global.slug,
635
+ mediaCollectionSlug
636
+ }
637
+ }
274
638
  }
275
- }
639
+ };
640
+ }
641
+ if (shouldAttachSocialMediaEditView && !hasCustomEditView) {
642
+ return {
643
+ ...existingEditViews,
644
+ default: {
645
+ ...typeof existingEditViews?.default === "object" ? existingEditViews.default : {},
646
+ Component: {
647
+ exportName: "AdminStudioSocialMediaGlobalView",
648
+ path: clientPath,
649
+ clientProps: {
650
+ ...studioNavClientProps,
651
+ globalSlug: global.slug
652
+ }
653
+ }
654
+ }
655
+ };
656
+ }
657
+ if (shouldAttachHeaderEditView && !hasCustomEditView) {
658
+ return {
659
+ ...existingEditViews,
660
+ default: {
661
+ ...typeof existingEditViews?.default === "object" ? existingEditViews.default : {},
662
+ Component: {
663
+ exportName: "AdminStudioHeaderGlobalView",
664
+ path: clientPath,
665
+ clientProps: {
666
+ ...studioNavClientProps,
667
+ actionHref: sitePreview?.header?.actionHref,
668
+ actionLabel: sitePreview?.header?.actionLabel,
669
+ globalSlug: global.slug,
670
+ locationSummary: sitePreview?.locationSummary,
671
+ pagesCollectionSlug
672
+ }
673
+ }
674
+ }
675
+ };
676
+ }
677
+ if (shouldAttachFooterEditView && !hasCustomEditView) {
678
+ return {
679
+ ...existingEditViews,
680
+ default: {
681
+ ...typeof existingEditViews?.default === "object" ? existingEditViews.default : {},
682
+ Component: {
683
+ exportName: "AdminStudioFooterGlobalView",
684
+ path: clientPath,
685
+ clientProps: {
686
+ ...studioNavClientProps,
687
+ builtByHref: sitePreview?.footer?.builtByHref,
688
+ builtByLabel: sitePreview?.footer?.builtByLabel,
689
+ description: sitePreview?.footer?.description,
690
+ footerCategories: sitePreview?.footer?.footerCategories,
691
+ footerLinks: sitePreview?.footer?.footerLinks,
692
+ globalSlug: global.slug,
693
+ locationSummary: sitePreview?.locationSummary
694
+ }
695
+ }
696
+ }
697
+ };
698
+ }
699
+ if (shouldAttachContactFormRedirect && !hasCustomEditView) {
700
+ return {
701
+ ...existingEditViews,
702
+ default: {
703
+ ...typeof existingEditViews?.default === "object" ? existingEditViews.default : {},
704
+ Component: {
705
+ exportName: "StudioContactFormRedirect",
706
+ path: clientPath,
707
+ clientProps: {
708
+ studioContactFormPath: contactFormStudioPath
709
+ }
710
+ }
711
+ }
712
+ };
276
713
  }
277
- } : existingEditViews;
714
+ return existingEditViews;
715
+ })();
716
+ const existingBeforeDocumentControls = global.admin?.components?.elements?.beforeDocumentControls;
278
717
  return {
279
718
  ...global,
280
719
  admin: {
@@ -282,12 +721,18 @@ function configureAdmin(config) {
282
721
  group: mapping.group,
283
722
  components: {
284
723
  ...global.admin?.components,
285
- ...shouldAttachContactFormRedirect ? {
724
+ elements: {
725
+ ...global.admin?.components?.elements,
726
+ beforeDocumentControls: studioEnabled ? appendComponent(
727
+ existingBeforeDocumentControls,
728
+ studioBackBreadcrumbComponent,
729
+ "StudioBackBreadcrumb"
730
+ ) : existingBeforeDocumentControls
731
+ },
732
+ ...nextEditViews ? {
286
733
  views: {
287
734
  ...existingViews,
288
- ...contactFormEditViews ? {
289
- edit: contactFormEditViews
290
- } : {}
735
+ edit: nextEditViews
291
736
  }
292
737
  } : {}
293
738
  }