bsmnt 0.13.0 → 0.14.0

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 (90) hide show
  1. package/dist/modules/features/cms/sanity-pagebuilder/config.d.ts.map +1 -1
  2. package/dist/modules/features/cms/sanity-pagebuilder/config.js +1 -0
  3. package/dist/modules/features/cms/sanity-pagebuilder/config.js.map +1 -1
  4. package/dist/modules/features/cms/sanity-pagebuilder-cache/config.d.ts.map +1 -1
  5. package/dist/modules/features/cms/sanity-pagebuilder-cache/config.js +1 -0
  6. package/dist/modules/features/cms/sanity-pagebuilder-cache/config.js.map +1 -1
  7. package/package.json +1 -1
  8. package/src/agent-skills/ashby-pagebuilder-block/SKILL.md +29 -11
  9. package/src/agent-skills/hubspot-pagebuilder-block/SKILL.md +31 -12
  10. package/src/agent-skills/page-builder-block/SKILL.md +26 -13
  11. package/src/modules/features/cms/sanity-pagebuilder/files/app/api/revalidate/route.ts +2 -2
  12. package/src/modules/features/cms/sanity-pagebuilder/files/components/sanity/rich-text.tsx +1 -1
  13. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/components/block-actions-item.tsx +2 -2
  14. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/components/component-preview-frame.tsx +124 -0
  15. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/components/component-preview-pane.tsx +25 -0
  16. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/components/page-builder-input.tsx +3 -26
  17. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/components/page-builder-insert-menu.tsx +121 -93
  18. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/icons.ts +2 -2
  19. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/page-builder-config.ts +22 -50
  20. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/presentation.ts +1 -18
  21. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/queries.ts +56 -64
  22. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/sanity.config.ts +4 -8
  23. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/components/index.ts +0 -1
  24. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/components/reusable/blog-content.ts +2 -2
  25. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/index.ts +1 -4
  26. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/shared/block.ts +4 -4
  27. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/shared/page-builder.ts +4 -18
  28. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/shared/page.ts +11 -37
  29. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/singletons.ts +0 -16
  30. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/structure.ts +35 -33
  31. package/src/modules/features/cms/sanity-pagebuilder/files/lib/utils/studio-embed.ts +22 -0
  32. package/src/modules/features/cms/sanity-pagebuilder-cache/files/app/api/revalidate/route.ts +2 -2
  33. package/src/modules/features/cms/sanity-pagebuilder-cache/files/components/sanity/rich-text.tsx +1 -1
  34. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/components/block-actions-item.tsx +2 -2
  35. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/components/component-preview-frame.tsx +124 -0
  36. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/components/component-preview-pane.tsx +25 -0
  37. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/components/page-builder-input.tsx +3 -26
  38. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/components/page-builder-insert-menu.tsx +121 -93
  39. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/icons.ts +2 -2
  40. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/page-builder-config.ts +22 -50
  41. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/presentation.ts +1 -18
  42. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/queries.ts +56 -64
  43. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/sanity.config.ts +4 -8
  44. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/components/index.ts +0 -1
  45. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/components/reusable/blog-content.ts +2 -2
  46. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/index.ts +1 -4
  47. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/shared/block.ts +4 -4
  48. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/shared/page-builder.ts +4 -18
  49. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/shared/page.ts +11 -37
  50. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/singletons.ts +0 -16
  51. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/structure.ts +35 -33
  52. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/utils/studio-embed.ts +22 -0
  53. package/src/modules/features/forms/hubspot/files/_sanity-adapter/form-block.ts +4 -10
  54. package/src/modules/features/forms/hubspot/files/lib/integrations/hubspot/README.md +10 -5
  55. package/src/modules/features/jobs/ashby/files/_sanity-adapter/job-board-block.ts +0 -7
  56. package/src/modules/features/jobs/ashby/files/lib/integrations/ashby/README.md +11 -5
  57. package/src/templates/next-default/lib/utils/README.md +1 -0
  58. package/src/templates/next-default/lib/utils/image-sizes.ts +64 -25
  59. package/src/templates/next-experiments/lib/utils/README.md +1 -0
  60. package/src/templates/next-experiments/lib/utils/image-sizes.ts +64 -25
  61. package/src/templates/next-pagebuilder/AGENTS.md +19 -7
  62. package/src/templates/next-pagebuilder/README.md +15 -3
  63. package/src/templates/next-pagebuilder/app/actions/unlock-gated-content.ts +5 -4
  64. package/src/templates/next-pagebuilder/app/components/page.tsx +81 -0
  65. package/src/templates/next-pagebuilder/components/page-builder/components/gated-content/index.tsx +8 -3
  66. package/src/templates/next-pagebuilder/components/page-builder/library.ts +183 -0
  67. package/src/templates/next-pagebuilder/components/page-builder/registry.tsx +4 -1
  68. package/src/templates/next-pagebuilder/components/page-builder/renderer.tsx +3 -1
  69. package/src/templates/next-pagebuilder/components/page-builder/stage.tsx +10 -0
  70. package/src/templates/next-pagebuilder/components/page-document/index.tsx +2 -1
  71. package/src/templates/next-pagebuilder/lib/integrations/sanity/sanity.types.ts +139 -271
  72. package/src/templates/next-pagebuilder/lib/utils/image-sizes.ts +64 -25
  73. package/src/templates/next-pagebuilder-cache/AGENTS.md +19 -7
  74. package/src/templates/next-pagebuilder-cache/README.md +15 -3
  75. package/src/templates/next-pagebuilder-cache/app/actions/unlock-gated-content.ts +5 -4
  76. package/src/templates/next-pagebuilder-cache/app/components/page.tsx +91 -0
  77. package/src/templates/next-pagebuilder-cache/components/page-builder/components/gated-content/index.tsx +8 -3
  78. package/src/templates/next-pagebuilder-cache/components/page-builder/library.ts +183 -0
  79. package/src/templates/next-pagebuilder-cache/components/page-builder/registry.tsx +4 -1
  80. package/src/templates/next-pagebuilder-cache/components/page-builder/renderer.tsx +3 -1
  81. package/src/templates/next-pagebuilder-cache/components/page-builder/stage.tsx +10 -0
  82. package/src/templates/next-pagebuilder-cache/components/page-document/index.tsx +2 -1
  83. package/src/templates/next-pagebuilder-cache/lib/integrations/sanity/sanity.types.ts +139 -271
  84. package/src/templates/next-pagebuilder-cache/lib/utils/image-sizes.ts +64 -25
  85. package/src/templates/next-webgl/lib/utils/README.md +1 -0
  86. package/src/templates/next-webgl/lib/utils/image-sizes.ts +64 -25
  87. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/components/use-studio-preview-urls.ts +0 -62
  88. package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/components/studio-preview.ts +0 -37
  89. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/components/use-studio-preview-urls.ts +0 -62
  90. package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/components/studio-preview.ts +0 -37
@@ -12,6 +12,11 @@ import {
12
12
  } from "@sanity/ui";
13
13
  import { useMemo, useState } from "react";
14
14
  import type { ArrayInputFunctionsProps, ArraySchemaType } from "sanity";
15
+ import {
16
+ getComponentPreviewPath,
17
+ getLibraryEntry,
18
+ } from "@/components/page-builder/library";
19
+ import { ComponentPreviewFrame } from "./component-preview-frame";
15
20
 
16
21
  type ArrayItem = { _key: string };
17
22
  type MemberSchemaType = ArraySchemaType["of"][number];
@@ -24,18 +29,22 @@ type InsertMenuSection = {
24
29
  members: MemberSchemaType[];
25
30
  };
26
31
 
27
- const SCROLL_HEIGHT = "min(60vh, 34rem)";
28
- const TILE_ASPECT_RATIO = "3 / 2";
32
+ const DIALOG_HEIGHT = "min(70vh, 42rem)";
33
+ const CHOICE_LIST_WIDTH = 260;
29
34
 
30
35
  const memberTitle = (member: MemberSchemaType) => member.title ?? member.name;
31
36
 
32
- function BlockTile({
37
+ function ChoiceRow({
38
+ active,
33
39
  member,
34
- previewUrl,
40
+ notes,
41
+ onAdd,
35
42
  onSelect,
36
43
  }: {
44
+ active: boolean;
37
45
  member: MemberSchemaType;
38
- previewUrl: string | undefined;
46
+ notes: string | undefined;
47
+ onAdd: () => void;
39
48
  onSelect: () => void;
40
49
  }) {
41
50
  const Icon = member.icon;
@@ -43,63 +52,42 @@ function BlockTile({
43
52
  return (
44
53
  <Card
45
54
  as="button"
46
- border
47
55
  onClick={onSelect}
48
- overflow="hidden"
49
- padding={0}
56
+ onDoubleClick={onAdd}
57
+ padding={2}
58
+ pressed={active}
50
59
  radius={2}
51
60
  style={{ cursor: "pointer", textAlign: "left", width: "100%" }}
61
+ tone={active ? "primary" : "default"}
52
62
  type="button"
53
63
  >
54
- <Stack space={0}>
55
- <Box
56
- style={{
57
- aspectRatio: TILE_ASPECT_RATIO,
58
- background: "var(--card-muted-bg-color)",
59
- position: "relative",
60
- }}
61
- >
62
- {previewUrl ? (
63
- // biome-ignore lint/performance/noImgElement: Studio-only CMS asset
64
- <img
65
- alt=""
66
- src={`${previewUrl}?w=640&fit=max&auto=format`}
67
- style={{
68
- height: "100%",
69
- inset: 0,
70
- objectFit: "contain",
71
- position: "absolute",
72
- width: "100%",
73
- }}
74
- />
75
- ) : (
76
- <Flex
77
- align="center"
78
- justify="center"
79
- style={{ inset: 0, position: "absolute" }}
80
- >
81
- {Icon ? <Icon /> : null}
82
- </Flex>
83
- )}
84
- </Box>
85
- <Box padding={2}>
86
- <Text size={1} textOverflow="ellipsis" weight="medium">
64
+ <Flex align="flex-start" gap={3}>
65
+ {Icon ? (
66
+ <Text size={2}>
67
+ <Icon />
68
+ </Text>
69
+ ) : null}
70
+ <Stack flex={1} space={2}>
71
+ <Text size={1} weight="medium">
87
72
  {memberTitle(member)}
88
73
  </Text>
89
- </Box>
90
- </Stack>
74
+ {notes ? (
75
+ <Text muted size={0} style={{ lineHeight: 1.4 }}>
76
+ {notes}
77
+ </Text>
78
+ ) : null}
79
+ </Stack>
80
+ </Flex>
91
81
  </Card>
92
82
  );
93
83
  }
94
84
 
95
85
  function InsertMenuDialog({
96
86
  sections,
97
- previewImageUrl,
98
87
  onSelect,
99
88
  onClose,
100
89
  }: {
101
90
  sections: InsertMenuSection[];
102
- previewImageUrl: ((schemaTypeName: string) => string | undefined) | undefined;
103
91
  onSelect: (member: MemberSchemaType) => void;
104
92
  onClose: () => void;
105
93
  }) {
@@ -118,60 +106,108 @@ function InsertMenuDialog({
118
106
  .filter((section) => section.members.length > 0);
119
107
  }, [search, sections]);
120
108
 
109
+ const visibleMembers = visibleSections.flatMap((section) => section.members);
110
+ const [selectedName, setSelectedName] = useState(
111
+ () => visibleMembers[0]?.name,
112
+ );
113
+
114
+ const selected =
115
+ visibleMembers.find((member) => member.name === selectedName) ??
116
+ visibleMembers[0];
117
+
118
+ const selectedEntry = selected ? getLibraryEntry(selected.name) : null;
119
+
121
120
  return (
122
121
  <Dialog
122
+ footer={
123
+ <Flex gap={2} justify="flex-end" padding={3}>
124
+ <Button mode="bleed" onClick={onClose} text="Cancel" />
125
+ <Button
126
+ disabled={!selected}
127
+ onClick={() => selected && onSelect(selected)}
128
+ text="Add component"
129
+ tone="primary"
130
+ />
131
+ </Flex>
132
+ }
123
133
  header="Components"
124
134
  id="page-builder-insert"
125
135
  onClose={onClose}
126
136
  open
127
- width={3}
137
+ width={4}
128
138
  >
129
- <Stack padding={4} space={4}>
130
- <TextInput
131
- autoFocus
132
- icon={SearchIcon}
133
- onChange={(event) => setSearch(event.currentTarget.value)}
134
- placeholder="Search components…"
135
- value={search}
136
- />
137
- <Box style={{ height: SCROLL_HEIGHT, overflowY: "auto" }}>
138
- {visibleSections.length === 0 ? (
139
- <Text muted size={1}>
140
- No components match “{search}”.
141
- </Text>
139
+ <Flex gap={3} padding={3} style={{ height: DIALOG_HEIGHT }}>
140
+ <Stack
141
+ space={3}
142
+ style={{ flex: `0 0 ${CHOICE_LIST_WIDTH}px`, minWidth: 0 }}
143
+ >
144
+ <TextInput
145
+ autoFocus
146
+ icon={SearchIcon}
147
+ onChange={(event) => setSearch(event.currentTarget.value)}
148
+ placeholder="Search components…"
149
+ value={search}
150
+ />
151
+ <Box style={{ flex: 1, overflowY: "auto" }}>
152
+ {visibleSections.length === 0 ? (
153
+ <Text muted size={1}>
154
+ No components match “{search}”.
155
+ </Text>
156
+ ) : (
157
+ <Stack space={4}>
158
+ {visibleSections.map((section) => (
159
+ <Stack key={section.name} space={2}>
160
+ <Text muted size={0} weight="semibold">
161
+ {section.title.toUpperCase()}
162
+ </Text>
163
+ <Stack space={1}>
164
+ {section.members.map((member) => (
165
+ <ChoiceRow
166
+ active={member.name === selected?.name}
167
+ key={member.name}
168
+ member={member}
169
+ notes={getLibraryEntry(member.name)?.notes}
170
+ onAdd={() => onSelect(member)}
171
+ onSelect={() => setSelectedName(member.name)}
172
+ />
173
+ ))}
174
+ </Stack>
175
+ </Stack>
176
+ ))}
177
+ </Stack>
178
+ )}
179
+ </Box>
180
+ </Stack>
181
+
182
+ <Card
183
+ border
184
+ flex={1}
185
+ radius={2}
186
+ style={{ overflow: "hidden" }}
187
+ tone="transparent"
188
+ >
189
+ {selected && selectedEntry ? (
190
+ <ComponentPreviewFrame
191
+ key={selected.name}
192
+ notes={selectedEntry.notes}
193
+ path={getComponentPreviewPath(selected.name)}
194
+ />
142
195
  ) : (
143
- <Stack space={5}>
144
- {visibleSections.map((section) => (
145
- <Stack key={section.name} space={3}>
146
- <Text muted size={1} weight="semibold">
147
- {section.title}
148
- </Text>
149
- <Grid columns={[2, 3, 4]} gap={3}>
150
- {section.members.map((member) => (
151
- <BlockTile
152
- key={member.name}
153
- member={member}
154
- onSelect={() => onSelect(member)}
155
- previewUrl={previewImageUrl?.(member.name)}
156
- />
157
- ))}
158
- </Grid>
159
- </Stack>
160
- ))}
161
- </Stack>
196
+ <Flex align="center" height="fill" justify="center" padding={4}>
197
+ <Text muted size={1}>
198
+ No preview for this component yet.
199
+ </Text>
200
+ </Flex>
162
201
  )}
163
- </Box>
164
- </Stack>
202
+ </Card>
203
+ </Flex>
165
204
  </Dialog>
166
205
  );
167
206
  }
168
207
 
169
208
  /**
170
- * Pass as `arrayFunctions`. Reads `insertMenu.groups` and `insertMenu.views`, so
171
- * a schema already configuring the built-in menu needs no extra wiring.
172
- *
173
- * Replaces the built-in popover, which is anchored to the array grid element and
174
- * so clips on page scroll and resizes when switching tabs.
209
+ * Pass as `arrayFunctions`. Replaces the built-in popover, which is anchored to
210
+ * the array grid element and so clips on page scroll.
175
211
  */
176
212
  export function PageBuilderInsertMenu(
177
213
  props: ArrayInputFunctionsProps<ArrayItem, ArraySchemaType>,
@@ -199,13 +235,6 @@ export function PageBuilderInsertMenu(
199
235
  .filter((section) => section.members.length > 0);
200
236
  }, [members, insertMenu]);
201
237
 
202
- const previewImageUrl = useMemo(() => {
203
- const gridView = insertMenu?.views?.find((view) => view.name === "grid");
204
- return gridView && "previewImageUrl" in gridView
205
- ? gridView.previewImageUrl
206
- : undefined;
207
- }, [insertMenu]);
208
-
209
238
  const insert = (member: MemberSchemaType) => {
210
239
  onItemAppend((onValueCreate as unknown as CreateItem)(member));
211
240
  setOpen(false);
@@ -233,7 +262,6 @@ export function PageBuilderInsertMenu(
233
262
  <InsertMenuDialog
234
263
  onClose={() => setOpen(false)}
235
264
  onSelect={insert}
236
- previewImageUrl={previewImageUrl}
237
265
  sections={sections}
238
266
  />
239
267
  )}
@@ -12,6 +12,7 @@ import {
12
12
  BuildingsIcon,
13
13
  CalendarBlankIcon,
14
14
  CardsIcon,
15
+ CubeIcon,
15
16
  FileTextIcon,
16
17
  FolderOpenIcon,
17
18
  FootprintsIcon,
@@ -19,7 +20,6 @@ import {
19
20
  ListBulletsIcon,
20
21
  ListIcon,
21
22
  LockKeyIcon,
22
- PackageIcon,
23
23
  QuestionIcon,
24
24
  RocketIcon,
25
25
  ShapesIcon,
@@ -45,7 +45,6 @@ const asDuotoneIcon = (IconComponent: Icon): SanityStudioIcon => {
45
45
  return DuotoneIcon;
46
46
  };
47
47
 
48
- export const pageBuilderCardIcon = asDuotoneIcon(PackageIcon);
49
48
  export const pageBuilderCardListIcon = asDuotoneIcon(ListIcon);
50
49
 
51
50
  export const authorIcon = asDuotoneIcon(UserCircleIcon);
@@ -54,6 +53,7 @@ export const pageListIcon = asDuotoneIcon(ListBulletsIcon);
54
53
 
55
54
  export const blogCategoryIcon = asDuotoneIcon(TagIcon);
56
55
 
56
+ export const componentIcon = asDuotoneIcon(CubeIcon);
57
57
  export const componentsFolderIcon = asDuotoneIcon(ShapesIcon);
58
58
 
59
59
  export const companyDataIcon = asDuotoneIcon(BuildingsIcon);
@@ -1,5 +1,4 @@
1
1
  import { contentIcon, pageIcon, type SanityStudioIcon } from "./icons";
2
- import { singletonComponents } from "./singletons";
3
2
 
4
3
  export type PageBuilderDocumentType =
5
4
  | "hero"
@@ -7,7 +6,7 @@ export type PageBuilderDocumentType =
7
6
  | "richTextBlock"
8
7
  | "gatedContent"
9
8
  | "blogContent"
10
- | (typeof singletonComponents)[number]["schemaType"];
9
+ | "blogCollection";
11
10
 
12
11
  /**
13
12
  * A block declares two orthogonal axes. `pageTypes` is which page documents may
@@ -27,18 +26,13 @@ export const componentCategories = [
27
26
 
28
27
  export type ComponentCategory = (typeof componentCategories)[number]["name"];
29
28
 
30
- type PageBuilderReferenceMember = {
29
+ type PageBuilderBlockMember = {
31
30
  documentType: PageBuilderDocumentType;
32
- name: string;
33
31
  title: string;
34
- documentId?: string;
35
32
  pageTypes: readonly PageBuilderGroupName[];
36
33
  category: ComponentCategory;
37
34
  };
38
35
 
39
- export const blockPreviewKey = (schemaTypeName: string) =>
40
- `block.${schemaTypeName}`;
41
-
42
36
  export const pageBuilderPageTypes: Array<{
43
37
  title: string;
44
38
  value: PageBuilderGroupName;
@@ -56,78 +50,61 @@ export const getPageCategoryIcon = (
56
50
  pageType: PageBuilderGroupName | undefined | null,
57
51
  ) => pageCategoryIcons[pageType ?? "generic"];
58
52
 
59
- const reusablePageBuilderReferenceMembers: PageBuilderReferenceMember[] = [
53
+ export const pageBuilderBlockMembers: PageBuilderBlockMember[] = [
60
54
  {
61
55
  documentType: "hero",
62
- name: "heroReference",
63
56
  title: "Heading",
64
57
  pageTypes: ["generic"],
65
58
  category: "hero",
66
59
  },
67
60
  {
68
61
  documentType: "description",
69
- name: "descriptionReference",
70
62
  title: "Description",
71
63
  pageTypes: ["generic"],
72
64
  category: "text",
73
65
  },
74
66
  {
75
67
  documentType: "richTextBlock",
76
- name: "richTextBlockReference",
77
68
  title: "Rich Text",
78
69
  pageTypes: ["generic"],
79
70
  category: "text",
80
71
  },
81
72
  {
82
73
  documentType: "gatedContent",
83
- name: "gatedContentReference",
84
74
  title: "Gated Content",
85
75
  pageTypes: ["generic"],
86
76
  category: "misc",
87
77
  },
78
+ {
79
+ documentType: "blogCollection",
80
+ title: "Blog Collection",
81
+ pageTypes: ["generic"],
82
+ category: "list",
83
+ },
88
84
  {
89
85
  documentType: "blogContent",
90
- name: "blogContentReference",
91
- title: "Blog Content",
86
+ title: "Blog Posts",
92
87
  pageTypes: ["blogEntry"],
93
88
  category: "content",
94
89
  },
95
90
  ];
96
91
 
97
- const singletonPageBuilderReferenceMembers: PageBuilderReferenceMember[] =
98
- singletonComponents.map((component) => ({
99
- documentType: component.schemaType,
100
- name: `${component.schemaType}Reference`,
101
- title: component.title,
102
- documentId: component.documentId,
103
- pageTypes: ["generic"],
104
- category: component.category,
105
- }));
106
-
107
- export const pageBuilderReferenceMembers: PageBuilderReferenceMember[] = [
108
- ...reusablePageBuilderReferenceMembers,
109
- ...singletonPageBuilderReferenceMembers,
110
- ];
111
-
112
- export const getPageBuilderReferenceMember = (name: string) =>
113
- pageBuilderReferenceMembers.find((member) => member.name === name);
114
-
115
- export const getPageBuilderReferenceMemberByDocumentType = (
92
+ export const getPageBuilderBlockMember = (
116
93
  documentType: PageBuilderDocumentType,
117
94
  ) =>
118
- pageBuilderReferenceMembers.find(
95
+ pageBuilderBlockMembers.find(
119
96
  (member) => member.documentType === documentType,
120
97
  );
121
98
 
122
99
  const isMemberVisibleForPageType = (
123
- member: PageBuilderReferenceMember,
100
+ member: PageBuilderBlockMember,
124
101
  pageType: PageBuilderGroupName | undefined,
125
102
  ) => member.pageTypes.includes(pageType ?? "generic");
126
103
 
127
- export const getVisiblePageBuilderReferenceMembers = (
104
+ export const getVisiblePageBuilderBlockMembers = (
128
105
  pageType: PageBuilderGroupName | undefined,
129
106
  ) =>
130
- pageBuilderReferenceMembers.filter((member) =>
107
+ pageBuilderBlockMembers.filter((member) =>
131
108
  isMemberVisibleForPageType(member, pageType),
132
109
  );
133
110
 
@@ -135,7 +112,9 @@ export const getVisiblePageBuilderMemberNames = (
135
112
  pageType: PageBuilderGroupName | undefined,
136
113
  ) =>
137
114
  new Set(
138
- getVisiblePageBuilderReferenceMembers(pageType).map((member) => member.name),
115
+ getVisiblePageBuilderBlockMembers(pageType).map(
116
+ (member) => member.documentType,
117
+ ),
139
118
  );
140
119
 
141
120
  export const getVisiblePageBuilderInsertMenuGroups = (
@@ -155,7 +134,7 @@ export const getInvalidPageBuilderDocumentTypes = (
155
134
  documentTypes: PageBuilderDocumentType[],
156
135
  ) =>
157
136
  documentTypes.filter((documentType) => {
158
- const member = getPageBuilderReferenceMemberByDocumentType(documentType);
137
+ const member = getPageBuilderBlockMember(documentType);
159
138
 
160
139
  if (!member) return false;
161
140
 
@@ -165,18 +144,11 @@ export const getInvalidPageBuilderDocumentTypes = (
165
144
  export const pageBuilderInsertMenuGroups: Array<{
166
145
  name: ComponentCategory;
167
146
  title: string;
168
- of: string[];
147
+ of: PageBuilderDocumentType[];
169
148
  }> = componentCategories.map(({ name, title }) => ({
170
149
  name,
171
150
  title,
172
- of: pageBuilderReferenceMembers
151
+ of: pageBuilderBlockMembers
173
152
  .filter((member) => member.category === name)
174
- .map((member) => member.name),
153
+ .map((member) => member.documentType),
175
154
  }));
176
-
177
- export const pageBuilderBlockPreviewOptions = pageBuilderReferenceMembers.map(
178
- (member) => ({
179
- title: `Block — ${member.title} · ${member.name}`,
180
- value: blockPreviewKey(member.name),
181
- }),
182
- );
@@ -43,10 +43,6 @@ const pageResolvedSlugExpression = buildNestedSlugExpression(
43
43
  "slug.current",
44
44
  );
45
45
 
46
- const CONTENT_TYPE_PREFIXES: Record<string, string> = {
47
- blogContent: "blog",
48
- };
49
-
50
46
  const resolveSlugLocation = <T extends { title?: string }>(
51
47
  documentStore: DocumentStore,
52
48
  id: string,
@@ -73,10 +69,6 @@ export const presentation = presentationTool({
73
69
  route: "/",
74
70
  filter: `_type == "page" && _id == "${HOMEPAGE_PINNED_PAGE.id}"`,
75
71
  },
76
- ...Object.entries(CONTENT_TYPE_PREFIXES).map(([type, prefix]) => ({
77
- route: `/${prefix}/:slug`,
78
- filter: `_type == "${type}" && slug.current == $slug`,
79
- })),
80
72
  {
81
73
  route: "/:slug+",
82
74
  filter: `_type == "page" && ${pageResolvedSlugExpression} == $slug`,
@@ -97,16 +89,7 @@ export const presentation = presentationTool({
97
89
  );
98
90
  }
99
91
 
100
- const prefix = CONTENT_TYPE_PREFIXES[params.type];
101
- if (!prefix) return null;
102
-
103
- return resolveSlugLocation<{ title?: string; slug?: string }>(
104
- documentStore,
105
- params.id,
106
- `title, "slug": slug.current`,
107
- (doc) => (doc.slug ? `/${prefix}/${doc.slug}` : null),
108
- "Untitled",
109
- );
92
+ return null;
110
93
  },
111
94
  },
112
95
  previewUrl: {