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.
- package/dist/modules/features/cms/sanity-pagebuilder/config.d.ts.map +1 -1
- package/dist/modules/features/cms/sanity-pagebuilder/config.js +1 -0
- package/dist/modules/features/cms/sanity-pagebuilder/config.js.map +1 -1
- package/dist/modules/features/cms/sanity-pagebuilder-cache/config.d.ts.map +1 -1
- package/dist/modules/features/cms/sanity-pagebuilder-cache/config.js +1 -0
- package/dist/modules/features/cms/sanity-pagebuilder-cache/config.js.map +1 -1
- package/package.json +1 -1
- package/src/agent-skills/ashby-pagebuilder-block/SKILL.md +29 -11
- package/src/agent-skills/hubspot-pagebuilder-block/SKILL.md +31 -12
- package/src/agent-skills/page-builder-block/SKILL.md +26 -13
- package/src/modules/features/cms/sanity-pagebuilder/files/app/api/revalidate/route.ts +2 -2
- package/src/modules/features/cms/sanity-pagebuilder/files/components/sanity/rich-text.tsx +1 -1
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/components/block-actions-item.tsx +2 -2
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/components/component-preview-frame.tsx +124 -0
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/components/component-preview-pane.tsx +25 -0
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/components/page-builder-input.tsx +3 -26
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/components/page-builder-insert-menu.tsx +121 -93
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/icons.ts +2 -2
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/page-builder-config.ts +22 -50
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/presentation.ts +1 -18
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/queries.ts +56 -64
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/sanity.config.ts +4 -8
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/components/index.ts +0 -1
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/components/reusable/blog-content.ts +2 -2
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/index.ts +1 -4
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/shared/block.ts +4 -4
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/shared/page-builder.ts +4 -18
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/shared/page.ts +11 -37
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/singletons.ts +0 -16
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/structure.ts +35 -33
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/utils/studio-embed.ts +22 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/app/api/revalidate/route.ts +2 -2
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/components/sanity/rich-text.tsx +1 -1
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/components/block-actions-item.tsx +2 -2
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/components/component-preview-frame.tsx +124 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/components/component-preview-pane.tsx +25 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/components/page-builder-input.tsx +3 -26
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/components/page-builder-insert-menu.tsx +121 -93
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/icons.ts +2 -2
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/page-builder-config.ts +22 -50
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/presentation.ts +1 -18
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/queries.ts +56 -64
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/sanity.config.ts +4 -8
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/components/index.ts +0 -1
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/components/reusable/blog-content.ts +2 -2
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/index.ts +1 -4
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/shared/block.ts +4 -4
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/shared/page-builder.ts +4 -18
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/shared/page.ts +11 -37
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/singletons.ts +0 -16
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/structure.ts +35 -33
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/utils/studio-embed.ts +22 -0
- package/src/modules/features/forms/hubspot/files/_sanity-adapter/form-block.ts +4 -10
- package/src/modules/features/forms/hubspot/files/lib/integrations/hubspot/README.md +10 -5
- package/src/modules/features/jobs/ashby/files/_sanity-adapter/job-board-block.ts +0 -7
- package/src/modules/features/jobs/ashby/files/lib/integrations/ashby/README.md +11 -5
- package/src/templates/next-default/lib/utils/README.md +1 -0
- package/src/templates/next-default/lib/utils/image-sizes.ts +64 -25
- package/src/templates/next-experiments/lib/utils/README.md +1 -0
- package/src/templates/next-experiments/lib/utils/image-sizes.ts +64 -25
- package/src/templates/next-pagebuilder/AGENTS.md +19 -7
- package/src/templates/next-pagebuilder/README.md +15 -3
- package/src/templates/next-pagebuilder/app/actions/unlock-gated-content.ts +5 -4
- package/src/templates/next-pagebuilder/app/components/page.tsx +81 -0
- package/src/templates/next-pagebuilder/components/page-builder/components/gated-content/index.tsx +8 -3
- package/src/templates/next-pagebuilder/components/page-builder/library.ts +183 -0
- package/src/templates/next-pagebuilder/components/page-builder/registry.tsx +4 -1
- package/src/templates/next-pagebuilder/components/page-builder/renderer.tsx +3 -1
- package/src/templates/next-pagebuilder/components/page-builder/stage.tsx +10 -0
- package/src/templates/next-pagebuilder/components/page-document/index.tsx +2 -1
- package/src/templates/next-pagebuilder/lib/integrations/sanity/sanity.types.ts +139 -271
- package/src/templates/next-pagebuilder/lib/utils/image-sizes.ts +64 -25
- package/src/templates/next-pagebuilder-cache/AGENTS.md +19 -7
- package/src/templates/next-pagebuilder-cache/README.md +15 -3
- package/src/templates/next-pagebuilder-cache/app/actions/unlock-gated-content.ts +5 -4
- package/src/templates/next-pagebuilder-cache/app/components/page.tsx +91 -0
- package/src/templates/next-pagebuilder-cache/components/page-builder/components/gated-content/index.tsx +8 -3
- package/src/templates/next-pagebuilder-cache/components/page-builder/library.ts +183 -0
- package/src/templates/next-pagebuilder-cache/components/page-builder/registry.tsx +4 -1
- package/src/templates/next-pagebuilder-cache/components/page-builder/renderer.tsx +3 -1
- package/src/templates/next-pagebuilder-cache/components/page-builder/stage.tsx +10 -0
- package/src/templates/next-pagebuilder-cache/components/page-document/index.tsx +2 -1
- package/src/templates/next-pagebuilder-cache/lib/integrations/sanity/sanity.types.ts +139 -271
- package/src/templates/next-pagebuilder-cache/lib/utils/image-sizes.ts +64 -25
- package/src/templates/next-webgl/lib/utils/README.md +1 -0
- package/src/templates/next-webgl/lib/utils/image-sizes.ts +64 -25
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/components/use-studio-preview-urls.ts +0 -62
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/components/studio-preview.ts +0 -37
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/components/use-studio-preview-urls.ts +0 -62
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/components/studio-preview.ts +0 -37
|
@@ -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
|
-
|
|
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: {
|
package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/queries.ts
CHANGED
|
@@ -88,58 +88,53 @@ const richTextLinkProjection = `
|
|
|
88
88
|
const pageBuilderProjection = `
|
|
89
89
|
pageBuilder[!(_key in coalesce(^.hiddenPageBuilderKeys, []))]{
|
|
90
90
|
_key,
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
_type
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
91
|
+
// Gated content withholds its payload from the page query — only the
|
|
92
|
+
// teaser and gate config ship to the client. GROQ has no field exclusion,
|
|
93
|
+
// so this branch lists safe fields explicitly rather than spreading every
|
|
94
|
+
// field. The payload is fetched separately via GATED_CONTENT_QUERY.
|
|
95
|
+
_type == "gatedContent" => {
|
|
96
|
+
_type,
|
|
97
|
+
anchorId,
|
|
98
|
+
presentation,
|
|
99
|
+
internalTitle,
|
|
100
|
+
teaserHeading,
|
|
101
|
+
teaserBody[]{
|
|
102
|
+
${richTextLinkProjection}
|
|
103
|
+
},
|
|
104
|
+
gateType,
|
|
105
|
+
gateHeadline,
|
|
106
|
+
gateDescription,
|
|
107
|
+
submitLabel,
|
|
108
|
+
successMessage,
|
|
109
|
+
kind
|
|
110
|
+
},
|
|
111
|
+
_type != "gatedContent" => {
|
|
112
|
+
...,
|
|
113
|
+
_type == "richTextBlock" => {
|
|
114
|
+
content[]{
|
|
104
115
|
${richTextLinkProjection}
|
|
105
|
-
}
|
|
106
|
-
gateType,
|
|
107
|
-
gateHeadline,
|
|
108
|
-
gateDescription,
|
|
109
|
-
submitLabel,
|
|
110
|
-
successMessage,
|
|
111
|
-
kind
|
|
116
|
+
}
|
|
112
117
|
},
|
|
113
|
-
_type
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
${richTextLinkProjection}
|
|
119
|
-
}
|
|
118
|
+
_type == "blogContent" => {
|
|
119
|
+
categories[]->{
|
|
120
|
+
_id,
|
|
121
|
+
title,
|
|
122
|
+
slug
|
|
120
123
|
},
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
},
|
|
134
|
-
|
|
135
|
-
${richTextLinkProjection}
|
|
136
|
-
},
|
|
137
|
-
relatedPosts[]->{
|
|
138
|
-
_id,
|
|
139
|
-
title,
|
|
140
|
-
"resolvedSlug": ${pageResolvedSlugExpression},
|
|
141
|
-
metadata
|
|
142
|
-
}
|
|
124
|
+
author->{
|
|
125
|
+
_id,
|
|
126
|
+
name,
|
|
127
|
+
avatar,
|
|
128
|
+
role
|
|
129
|
+
},
|
|
130
|
+
body[]{
|
|
131
|
+
${richTextLinkProjection}
|
|
132
|
+
},
|
|
133
|
+
relatedPosts[]->{
|
|
134
|
+
_id,
|
|
135
|
+
title,
|
|
136
|
+
"resolvedSlug": ${pageResolvedSlugExpression},
|
|
137
|
+
metadata
|
|
143
138
|
}
|
|
144
139
|
}
|
|
145
140
|
}
|
|
@@ -147,10 +142,13 @@ const pageBuilderProjection = `
|
|
|
147
142
|
`;
|
|
148
143
|
|
|
149
144
|
// Gated content payload — fetched on demand by the unlock server action, keyed
|
|
150
|
-
// by the block's
|
|
151
|
-
// the client until the visitor completes the gate.
|
|
145
|
+
// by the hosting page plus the block's `_key`. Kept out of the page query so it
|
|
146
|
+
// never ships to the client until the visitor completes the gate.
|
|
152
147
|
export const GATED_CONTENT_QUERY = defineQuery(`
|
|
153
|
-
*[
|
|
148
|
+
*[
|
|
149
|
+
_type == "page" &&
|
|
150
|
+
(_id == $pageId || _id == "drafts." + $pageId)
|
|
151
|
+
][0].pageBuilder[_key == $blockKey && _type == "gatedContent"][0]{
|
|
154
152
|
kind,
|
|
155
153
|
content[]{
|
|
156
154
|
${richTextLinkProjection}
|
|
@@ -231,16 +229,10 @@ export const P_REV_SLUGS_QUERY = defineQuery(`
|
|
|
231
229
|
}
|
|
232
230
|
`);
|
|
233
231
|
|
|
234
|
-
// Pages depending on `$documentIds`, one or two hops out: one covers
|
|
235
|
-
// `collectionCategory->`, two covers anything reached through a page-builder
|
|
236
|
-
// block. All inline the referenced title or slug, so a change there goes stale.
|
|
237
232
|
export const P_REF_DOC_PAGES_QUERY = defineQuery(`
|
|
238
233
|
*[
|
|
239
234
|
_type == "page" &&
|
|
240
|
-
(
|
|
241
|
-
references($documentIds) ||
|
|
242
|
-
count(pageBuilder[_ref in *[references($documentIds)]._id]) > 0
|
|
243
|
-
)
|
|
235
|
+
references($documentIds)
|
|
244
236
|
] | order(title asc) {
|
|
245
237
|
_id,
|
|
246
238
|
title,
|
|
@@ -319,7 +311,7 @@ export const ALL_BLOG_ARTICLES_QUERY = defineQuery(`
|
|
|
319
311
|
title,
|
|
320
312
|
"slug": slug,
|
|
321
313
|
"resolvedSlug": ${pageResolvedSlugExpression},
|
|
322
|
-
"blogContent": pageBuilder[
|
|
314
|
+
"blogContent": pageBuilder[_type == "blogContent"][0]{
|
|
323
315
|
thumbnail{
|
|
324
316
|
...,
|
|
325
317
|
alt
|
|
@@ -356,14 +348,14 @@ export const BLOG_ARTICLES_PAGINATED_QUERY = defineQuery(`
|
|
|
356
348
|
(
|
|
357
349
|
!defined($category) ||
|
|
358
350
|
$category == "" ||
|
|
359
|
-
$category in pageBuilder[
|
|
351
|
+
$category in pageBuilder[_type == "blogContent"][0].categories[]->slug.current
|
|
360
352
|
)
|
|
361
353
|
] | order(_updatedAt desc)[$offset...$end] {
|
|
362
354
|
_id,
|
|
363
355
|
title,
|
|
364
356
|
"slug": slug,
|
|
365
357
|
"resolvedSlug": ${pageResolvedSlugExpression},
|
|
366
|
-
"blogContent": pageBuilder[
|
|
358
|
+
"blogContent": pageBuilder[_type == "blogContent"][0]{
|
|
367
359
|
thumbnail{
|
|
368
360
|
...,
|
|
369
361
|
alt
|
|
@@ -395,7 +387,7 @@ export const BLOG_ARTICLES_COUNT_QUERY = defineQuery(`
|
|
|
395
387
|
(
|
|
396
388
|
!defined($category) ||
|
|
397
389
|
$category == "" ||
|
|
398
|
-
$category in pageBuilder[
|
|
390
|
+
$category in pageBuilder[_type == "blogContent"][0].categories[]->slug.current
|
|
399
391
|
)
|
|
400
392
|
])
|
|
401
393
|
`);
|
|
@@ -415,7 +407,7 @@ export const ALL_BLOG_CATEGORIES_QUERY = defineQuery(`
|
|
|
415
407
|
export const COLLECTION_PAGES_QUERY = defineQuery(`
|
|
416
408
|
*[
|
|
417
409
|
_type == "page" &&
|
|
418
|
-
count(pageBuilder[!(_key in coalesce(^.hiddenPageBuilderKeys, [])) &&
|
|
410
|
+
count(pageBuilder[!(_key in coalesce(^.hiddenPageBuilderKeys, [])) && _type == "blogCollection"]) > 0
|
|
419
411
|
] {
|
|
420
412
|
"path": ${pageResolvedSlugExpression},
|
|
421
413
|
"category": collectionCategory->slug.current
|
|
@@ -7,7 +7,6 @@ import { dataset, projectId } from "./env";
|
|
|
7
7
|
import { PINNED_PAGE_ENTRIES, PINNED_PAGE_IDS } from "./pinned-pages";
|
|
8
8
|
import { presentation } from "./presentation";
|
|
9
9
|
import { schema } from "./schemas";
|
|
10
|
-
import { singletonComponentTypes } from "./singletons";
|
|
11
10
|
import { structure } from "./structure";
|
|
12
11
|
|
|
13
12
|
const isProd = process.env.NODE_ENV === "production";
|
|
@@ -19,10 +18,9 @@ const singletonDocumentActions = new Set([
|
|
|
19
18
|
]);
|
|
20
19
|
|
|
21
20
|
const isSingletonDocument = (schemaType: string, documentId?: string) =>
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
PINNED_PAGE_IDS.has(documentId));
|
|
21
|
+
schemaType === "page" &&
|
|
22
|
+
documentId !== undefined &&
|
|
23
|
+
PINNED_PAGE_IDS.has(documentId);
|
|
26
24
|
|
|
27
25
|
export default defineConfig({
|
|
28
26
|
basePath: "/studio",
|
|
@@ -107,9 +105,7 @@ export default defineConfig({
|
|
|
107
105
|
},
|
|
108
106
|
newDocumentOptions: (previousOptions) =>
|
|
109
107
|
previousOptions.filter(
|
|
110
|
-
(option) =>
|
|
111
|
-
!singletonComponentTypes.has(option.templateId) &&
|
|
112
|
-
!PINNED_PAGE_IDS.has(option.templateId),
|
|
108
|
+
(option) => !PINNED_PAGE_IDS.has(option.templateId),
|
|
113
109
|
),
|
|
114
110
|
},
|
|
115
111
|
plugins: [structureTool({ structure }), presentation, media(), table()],
|
|
@@ -4,4 +4,3 @@ export { gatedContent } from "./reusable/gated-content";
|
|
|
4
4
|
export { hero } from "./reusable/hero";
|
|
5
5
|
export { richTextBlock } from "./reusable/rich-text-block";
|
|
6
6
|
export { blogCollection } from "./singleton/content-collection";
|
|
7
|
-
export { studioPreview } from "./studio-preview";
|
|
@@ -4,7 +4,7 @@ import { defineBlock } from "@/lib/integrations/sanity/schemas/shared/block";
|
|
|
4
4
|
|
|
5
5
|
export const blogContent = defineBlock({
|
|
6
6
|
name: "blogContent",
|
|
7
|
-
title: "Blog
|
|
7
|
+
title: "Blog Posts",
|
|
8
8
|
icon: contentIcon,
|
|
9
9
|
fields: [
|
|
10
10
|
defineField({
|
|
@@ -80,7 +80,7 @@ export const blogContent = defineBlock({
|
|
|
80
80
|
},
|
|
81
81
|
prepare({ title, date, media }) {
|
|
82
82
|
return {
|
|
83
|
-
title: title || "Blog
|
|
83
|
+
title: title || "Blog Posts",
|
|
84
84
|
subtitle: date || "No date set",
|
|
85
85
|
media,
|
|
86
86
|
};
|
|
@@ -15,7 +15,6 @@ import {
|
|
|
15
15
|
gatedContent,
|
|
16
16
|
hero,
|
|
17
17
|
richTextBlock,
|
|
18
|
-
studioPreview,
|
|
19
18
|
} from "./components";
|
|
20
19
|
import { author } from "./content/author";
|
|
21
20
|
import { blogCategory } from "./content/blog-category";
|
|
@@ -83,7 +82,6 @@ export {
|
|
|
83
82
|
spacingSettings,
|
|
84
83
|
spacingStep,
|
|
85
84
|
structuredData,
|
|
86
|
-
studioPreview,
|
|
87
85
|
videoJsonLd,
|
|
88
86
|
};
|
|
89
87
|
|
|
@@ -121,8 +119,7 @@ export const schema: { types: SchemaTypeDefinition[] } = {
|
|
|
121
119
|
description,
|
|
122
120
|
richTextBlock,
|
|
123
121
|
gatedContent,
|
|
124
|
-
|
|
125
|
-
|
|
122
|
+
|
|
126
123
|
// Layout types (singletons for site-wide layout)
|
|
127
124
|
companyData,
|
|
128
125
|
navbar,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
|
-
type DocumentDefinition,
|
|
3
2
|
defineType,
|
|
4
3
|
type FieldDefinition,
|
|
5
4
|
type FieldGroupDefinition,
|
|
5
|
+
type ObjectDefinition,
|
|
6
6
|
} from "sanity";
|
|
7
7
|
import { presentationFields } from "./presentation";
|
|
8
8
|
|
|
@@ -11,7 +11,7 @@ const presentationGroup: FieldGroupDefinition = {
|
|
|
11
11
|
title: "Presentation",
|
|
12
12
|
};
|
|
13
13
|
|
|
14
|
-
type BlockDefinition = Omit<
|
|
14
|
+
type BlockDefinition = Omit<ObjectDefinition, "type" | "fields" | "groups"> & {
|
|
15
15
|
fields: FieldDefinition[];
|
|
16
16
|
groups?: FieldGroupDefinition[];
|
|
17
17
|
};
|
|
@@ -26,7 +26,7 @@ const withPresentationGroup = (groups: FieldGroupDefinition[] | undefined) => {
|
|
|
26
26
|
};
|
|
27
27
|
|
|
28
28
|
/**
|
|
29
|
-
* Defines a page-builder block — `type: "
|
|
29
|
+
* Defines a page-builder block — an inline `type: "object"` plus Anchor ID and
|
|
30
30
|
* Presentation Mode. Use instead of `defineType`.
|
|
31
31
|
*/
|
|
32
32
|
export const defineBlock = ({ fields, groups, ...rest }: BlockDefinition) => {
|
|
@@ -34,7 +34,7 @@ export const defineBlock = ({ fields, groups, ...rest }: BlockDefinition) => {
|
|
|
34
34
|
|
|
35
35
|
return defineType({
|
|
36
36
|
...rest,
|
|
37
|
-
type: "
|
|
37
|
+
type: "object",
|
|
38
38
|
...(blockGroups ? { groups: blockGroups } : {}),
|
|
39
39
|
fields: [
|
|
40
40
|
...fields,
|
|
@@ -2,8 +2,8 @@ import { defineArrayMember, defineType } from "sanity";
|
|
|
2
2
|
import { BlockActionsItem } from "@/lib/integrations/sanity/components/block-actions-item";
|
|
3
3
|
import { PageBuilderInput } from "@/lib/integrations/sanity/components/page-builder-input";
|
|
4
4
|
import {
|
|
5
|
+
pageBuilderBlockMembers,
|
|
5
6
|
pageBuilderInsertMenuGroups,
|
|
6
|
-
pageBuilderReferenceMembers,
|
|
7
7
|
} from "@/lib/integrations/sanity/page-builder-config";
|
|
8
8
|
|
|
9
9
|
export const pageBuilder = defineType({
|
|
@@ -17,27 +17,13 @@ export const pageBuilder = defineType({
|
|
|
17
17
|
groups: pageBuilderInsertMenuGroups,
|
|
18
18
|
},
|
|
19
19
|
},
|
|
20
|
-
of:
|
|
20
|
+
of: pageBuilderBlockMembers.map((member) =>
|
|
21
21
|
defineArrayMember({
|
|
22
|
-
|
|
22
|
+
type: member.documentType,
|
|
23
23
|
title: member.title,
|
|
24
|
-
type: "reference",
|
|
25
|
-
to: [{ type: member.documentType }],
|
|
26
24
|
// Per-placement Hide/Show action; hidden state lives in the owning
|
|
27
|
-
// document's `hiddenPageBuilderKeys`, not on the
|
|
25
|
+
// document's `hiddenPageBuilderKeys`, not on the block itself.
|
|
28
26
|
components: { item: BlockActionsItem },
|
|
29
|
-
...(member.documentId
|
|
30
|
-
? {
|
|
31
|
-
options: {
|
|
32
|
-
disableNew: true,
|
|
33
|
-
filter: "_id in [$documentId, $draftDocumentId]",
|
|
34
|
-
filterParams: {
|
|
35
|
-
documentId: member.documentId,
|
|
36
|
-
draftDocumentId: `drafts.${member.documentId}`,
|
|
37
|
-
},
|
|
38
|
-
},
|
|
39
|
-
}
|
|
40
|
-
: {}),
|
|
41
27
|
}),
|
|
42
28
|
),
|
|
43
29
|
});
|
|
@@ -5,7 +5,7 @@ import { apiVersion } from "@/lib/integrations/sanity/env";
|
|
|
5
5
|
import { pageIcon } from "@/lib/integrations/sanity/icons";
|
|
6
6
|
import {
|
|
7
7
|
getInvalidPageBuilderDocumentTypes,
|
|
8
|
-
|
|
8
|
+
getPageBuilderBlockMember,
|
|
9
9
|
getPageCategoryIcon,
|
|
10
10
|
type PageBuilderDocumentType,
|
|
11
11
|
type PageBuilderGroupName,
|
|
@@ -24,7 +24,6 @@ type PageValidationDocument = {
|
|
|
24
24
|
pageBuilder?: Array<{
|
|
25
25
|
_key?: string;
|
|
26
26
|
_type?: string;
|
|
27
|
-
_ref?: string;
|
|
28
27
|
}>;
|
|
29
28
|
};
|
|
30
29
|
|
|
@@ -35,11 +34,6 @@ type PageSlugValidationContext = {
|
|
|
35
34
|
};
|
|
36
35
|
};
|
|
37
36
|
|
|
38
|
-
type ReferencedPageBuilderDocument = {
|
|
39
|
-
_id: string;
|
|
40
|
-
_type: PageBuilderDocumentType;
|
|
41
|
-
};
|
|
42
|
-
|
|
43
37
|
const PAGE_FOLDER_QUERY = `*[_type == "pageFolder" && _id in [$publishedId, $draftId]][0].slug.current`;
|
|
44
38
|
|
|
45
39
|
async function getGeneratedPageCategoryForDocument(
|
|
@@ -164,41 +158,25 @@ export const page = defineType({
|
|
|
164
158
|
document,
|
|
165
159
|
context.getClient,
|
|
166
160
|
);
|
|
167
|
-
const
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
.filter((item): item is string => typeof item === "string");
|
|
173
|
-
|
|
174
|
-
if (referenceIds.length === 0) return true;
|
|
175
|
-
|
|
176
|
-
const referencedDocuments = await context
|
|
177
|
-
.getClient({ apiVersion })
|
|
178
|
-
.fetch<ReferencedPageBuilderDocument[]>(
|
|
179
|
-
`*[
|
|
180
|
-
_id in $publishedIds || _id in $draftIds
|
|
181
|
-
]{
|
|
182
|
-
_id,
|
|
183
|
-
_type
|
|
184
|
-
}`,
|
|
185
|
-
{
|
|
186
|
-
publishedIds: referenceIds,
|
|
187
|
-
draftIds: referenceIds.map((id) => `drafts.${id}`),
|
|
188
|
-
},
|
|
161
|
+
const documentTypes = (Array.isArray(value) ? value : [])
|
|
162
|
+
.map((item) => (item as { _type?: string })?._type)
|
|
163
|
+
.filter(
|
|
164
|
+
(type): type is PageBuilderDocumentType =>
|
|
165
|
+
typeof type === "string",
|
|
189
166
|
);
|
|
190
167
|
|
|
168
|
+
if (documentTypes.length === 0) return true;
|
|
169
|
+
|
|
191
170
|
const invalidDocumentTypes = getInvalidPageBuilderDocumentTypes(
|
|
192
171
|
pageType,
|
|
193
|
-
|
|
172
|
+
documentTypes,
|
|
194
173
|
);
|
|
195
174
|
|
|
196
175
|
if (invalidDocumentTypes.length === 0) return true;
|
|
197
176
|
|
|
198
|
-
const invalidMemberTitles = invalidDocumentTypes.map(
|
|
177
|
+
const invalidMemberTitles = [...new Set(invalidDocumentTypes)].map(
|
|
199
178
|
(documentType) =>
|
|
200
|
-
|
|
201
|
-
?.title ?? documentType,
|
|
179
|
+
getPageBuilderBlockMember(documentType)?.title ?? documentType,
|
|
202
180
|
);
|
|
203
181
|
|
|
204
182
|
return `These page builder components do not belong to the "${pageType ?? "generic"}" category: ${invalidMemberTitles.join(", ")}`;
|
|
@@ -209,10 +187,6 @@ export const page = defineType({
|
|
|
209
187
|
title: "Pinned Collection Category",
|
|
210
188
|
type: "reference",
|
|
211
189
|
to: [{ type: "blogCategory" }],
|
|
212
|
-
// Lives on the page because the collection block is deliberately a
|
|
213
|
-
// singleton (see `singletonComponents`) — editors reuse one block rather
|
|
214
|
-
// than creating them, so a category set there would apply site-wide. Move
|
|
215
|
-
// the block to the reusable list if you'd rather scope it per instance.
|
|
216
190
|
description:
|
|
217
191
|
"Turns this page into a category page: the content collection shows only this category. Leave empty to show everything.",
|
|
218
192
|
}),
|
|
@@ -2,22 +2,10 @@ import {
|
|
|
2
2
|
companyDataIcon,
|
|
3
3
|
footerIcon,
|
|
4
4
|
navbarIcon,
|
|
5
|
-
pageListIcon,
|
|
6
5
|
spacingSettingsIcon,
|
|
7
6
|
structuredDataIcon,
|
|
8
7
|
} from "./icons";
|
|
9
8
|
|
|
10
|
-
// `category` must be one of `componentCategories` in page-builder-config.ts.
|
|
11
|
-
export const singletonComponents = [
|
|
12
|
-
{
|
|
13
|
-
schemaType: "blogCollection",
|
|
14
|
-
documentId: "blogCollection",
|
|
15
|
-
title: "Blog Collection",
|
|
16
|
-
icon: pageListIcon,
|
|
17
|
-
category: "list",
|
|
18
|
-
},
|
|
19
|
-
] as const;
|
|
20
|
-
|
|
21
9
|
export const singletonLayout = [
|
|
22
10
|
{
|
|
23
11
|
schemaType: "companyData",
|
|
@@ -51,10 +39,6 @@ export const singletonLayout = [
|
|
|
51
39
|
},
|
|
52
40
|
] as const;
|
|
53
41
|
|
|
54
|
-
export const singletonComponentTypes: Set<string> = new Set(
|
|
55
|
-
singletonComponents.map((item) => item.schemaType),
|
|
56
|
-
);
|
|
57
|
-
|
|
58
42
|
export const singletonLayoutTypes: Set<string> = new Set(
|
|
59
43
|
singletonLayout.map((item) => item.schemaType),
|
|
60
44
|
);
|
package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/structure.ts
CHANGED
|
@@ -6,18 +6,20 @@ import type {
|
|
|
6
6
|
StructureResolver,
|
|
7
7
|
StructureResolverContext,
|
|
8
8
|
} from "sanity/structure";
|
|
9
|
+
import {
|
|
10
|
+
COMPONENT_LIBRARY,
|
|
11
|
+
getComponentPreviewPath,
|
|
12
|
+
} from "@/components/page-builder/library";
|
|
13
|
+
import { pageBuilderInsertMenuGroups } from "@/lib/integrations/sanity/page-builder-config";
|
|
14
|
+
import { ComponentPreviewPane } from "./components/component-preview-pane";
|
|
9
15
|
import { apiVersion } from "./env";
|
|
10
16
|
import {
|
|
11
17
|
authorIcon,
|
|
12
18
|
blogCategoryIcon,
|
|
19
|
+
componentIcon,
|
|
13
20
|
componentsFolderIcon,
|
|
14
21
|
contentFolderIcon,
|
|
15
|
-
contentIcon,
|
|
16
|
-
descriptionIcon,
|
|
17
|
-
gatedContentIcon,
|
|
18
|
-
heroIcon,
|
|
19
22
|
layoutFolderIcon,
|
|
20
|
-
pageBuilderCardIcon,
|
|
21
23
|
pageFolderIcon,
|
|
22
24
|
pageIcon,
|
|
23
25
|
pagesFolderIcon,
|
|
@@ -25,7 +27,7 @@ import {
|
|
|
25
27
|
} from "./icons";
|
|
26
28
|
import { PageTreePane } from "./page-tree-pane";
|
|
27
29
|
import { PINNED_PAGE_ENTRIES } from "./pinned-pages";
|
|
28
|
-
import {
|
|
30
|
+
import { singletonLayout } from "./singletons";
|
|
29
31
|
|
|
30
32
|
const PAGE_TREE_ITEM_ID_PREFIX = {
|
|
31
33
|
page: "page-tree-",
|
|
@@ -271,7 +273,7 @@ export const structure: StructureResolver = (S, context) =>
|
|
|
271
273
|
|
|
272
274
|
S.divider(),
|
|
273
275
|
|
|
274
|
-
// GROUP 3: Components --
|
|
276
|
+
// GROUP 3: Components -- live block previews, grouped like the insert menu
|
|
275
277
|
S.listItem()
|
|
276
278
|
.title("Components")
|
|
277
279
|
.icon(componentsFolderIcon)
|
|
@@ -279,33 +281,33 @@ export const structure: StructureResolver = (S, context) =>
|
|
|
279
281
|
S.list()
|
|
280
282
|
.title("Components")
|
|
281
283
|
.items([
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
284
|
+
...pageBuilderInsertMenuGroups.flatMap((group) => {
|
|
285
|
+
const entries = COMPONENT_LIBRARY.filter((entry) =>
|
|
286
|
+
group.of.includes(entry.documentType),
|
|
287
|
+
);
|
|
288
|
+
|
|
289
|
+
if (entries.length === 0) return [];
|
|
290
|
+
|
|
291
|
+
return [
|
|
292
|
+
S.divider().title(group.title),
|
|
293
|
+
...entries.map((entry) =>
|
|
294
|
+
S.listItem()
|
|
295
|
+
.title(entry.title)
|
|
296
|
+
.id(entry.documentType)
|
|
297
|
+
.icon(componentIcon)
|
|
298
|
+
.child(
|
|
299
|
+
S.component()
|
|
300
|
+
.id(`component-${entry.documentType}`)
|
|
301
|
+
.title(entry.title)
|
|
302
|
+
.component(ComponentPreviewPane)
|
|
303
|
+
.options({
|
|
304
|
+
notes: entry.notes,
|
|
305
|
+
path: getComponentPreviewPath(entry.documentType),
|
|
306
|
+
}),
|
|
307
|
+
),
|
|
292
308
|
),
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
S.documentTypeListItem("hero").title("Headings").icon(heroIcon),
|
|
296
|
-
S.documentTypeListItem("description")
|
|
297
|
-
.title("Descriptions")
|
|
298
|
-
.icon(descriptionIcon),
|
|
299
|
-
S.documentTypeListItem("gatedContent")
|
|
300
|
-
.title("Gated Content")
|
|
301
|
-
.icon(gatedContentIcon),
|
|
302
|
-
S.documentTypeListItem("blogContent")
|
|
303
|
-
.title("Blog Content")
|
|
304
|
-
.icon(contentIcon),
|
|
305
|
-
S.divider(),
|
|
306
|
-
S.documentTypeListItem("studioPreview")
|
|
307
|
-
.title("Component Previews")
|
|
308
|
-
.icon(pageBuilderCardIcon),
|
|
309
|
+
];
|
|
310
|
+
}),
|
|
309
311
|
]),
|
|
310
312
|
),
|
|
311
313
|
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { headers } from "next/headers";
|
|
2
|
+
|
|
3
|
+
const STUDIO_PATH = "/studio";
|
|
4
|
+
|
|
5
|
+
const isStudioReferer = (referer: string | null) => {
|
|
6
|
+
if (!referer) return false;
|
|
7
|
+
|
|
8
|
+
try {
|
|
9
|
+
return new URL(referer).pathname.startsWith(STUDIO_PATH);
|
|
10
|
+
} catch {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const isStudioEmbed = async () => {
|
|
16
|
+
const headerList = await headers();
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
headerList.get("sec-fetch-dest") === "iframe" ||
|
|
20
|
+
isStudioReferer(headerList.get("referer"))
|
|
21
|
+
);
|
|
22
|
+
};
|
|
@@ -7,9 +7,10 @@ import {
|
|
|
7
7
|
import { hubspotFormField } from "./form-field"
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
* Sample
|
|
11
|
-
*
|
|
12
|
-
*
|
|
10
|
+
* Sample HubSpot form block. Register it in your schema's type list, then render
|
|
11
|
+
* its `form` with <HubSpotForm /> from the integration core. In a page-builder
|
|
12
|
+
* project re-declare it through `defineBlock` so it becomes an inline block —
|
|
13
|
+
* the `hubspot-pagebuilder-block` skill walks through it:
|
|
13
14
|
*
|
|
14
15
|
* @example
|
|
15
16
|
* import { HubSpotForm } from "@/lib/integrations/hubspot/form"
|
|
@@ -51,10 +52,3 @@ export const hubspotFormBlock = defineType({
|
|
|
51
52
|
},
|
|
52
53
|
},
|
|
53
54
|
})
|
|
54
|
-
|
|
55
|
-
export const hubspotFormBlockReference = defineType({
|
|
56
|
-
name: "hubspotFormBlockReference",
|
|
57
|
-
title: "HubSpot Form Block",
|
|
58
|
-
type: "reference",
|
|
59
|
-
to: [{ type: "hubspotFormBlock" }],
|
|
60
|
-
})
|