bsmnt 0.12.0 → 0.13.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/application/add-integration/index.d.ts.map +1 -1
- package/dist/application/add-integration/index.js +23 -0
- package/dist/application/add-integration/index.js.map +1 -1
- package/dist/domain/consent.d.ts +17 -0
- package/dist/domain/consent.d.ts.map +1 -0
- package/dist/domain/consent.js +13 -0
- package/dist/domain/consent.js.map +1 -0
- package/dist/domain/integration.d.ts +19 -2
- package/dist/domain/integration.d.ts.map +1 -1
- package/dist/domain/integration.js +10 -1
- package/dist/domain/integration.js.map +1 -1
- package/dist/domain/jobs.d.ts +17 -0
- package/dist/domain/jobs.d.ts.map +1 -0
- package/dist/domain/jobs.js +13 -0
- package/dist/domain/jobs.js.map +1 -0
- package/dist/domain/skills.d.ts +23 -2
- package/dist/domain/skills.d.ts.map +1 -1
- package/dist/domain/skills.js +23 -2
- package/dist/domain/skills.js.map +1 -1
- package/dist/domain/templates.d.ts +7 -1
- package/dist/domain/templates.d.ts.map +1 -1
- package/dist/domain/templates.js +2 -0
- package/dist/domain/templates.js.map +1 -1
- package/dist/index.js +34 -9
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/create/setup-agent.d.ts.map +1 -1
- package/dist/infrastructure/create/setup-agent.js +11 -4
- package/dist/infrastructure/create/setup-agent.js.map +1 -1
- package/dist/infrastructure/integrations/inject-integration.d.ts.map +1 -1
- package/dist/infrastructure/integrations/inject-integration.js +36 -2
- package/dist/infrastructure/integrations/inject-integration.js.map +1 -1
- package/dist/modules/features/consent/ketch/config.d.ts +18 -0
- package/dist/modules/features/consent/ketch/config.d.ts.map +1 -0
- package/dist/modules/features/consent/ketch/config.js +24 -0
- package/dist/modules/features/consent/ketch/config.js.map +1 -0
- package/dist/modules/features/consent/ketch/mergers/biome.d.ts +16 -0
- package/dist/modules/features/consent/ketch/mergers/biome.d.ts.map +1 -0
- package/dist/modules/features/consent/ketch/mergers/biome.js +31 -0
- package/dist/modules/features/consent/ketch/mergers/biome.js.map +1 -0
- package/dist/modules/features/consent/ketch/mergers/check-integration.d.ts +13 -0
- package/dist/modules/features/consent/ketch/mergers/check-integration.d.ts.map +1 -0
- package/dist/modules/features/consent/ketch/mergers/check-integration.js +64 -0
- package/dist/modules/features/consent/ketch/mergers/check-integration.js.map +1 -0
- package/dist/modules/features/consent/ketch/mergers/env-example.d.ts +12 -0
- package/dist/modules/features/consent/ketch/mergers/env-example.d.ts.map +1 -0
- package/dist/modules/features/consent/ketch/mergers/env-example.js +28 -0
- package/dist/modules/features/consent/ketch/mergers/env-example.js.map +1 -0
- package/dist/modules/features/consent/ketch/mergers/footer.d.ts +17 -0
- package/dist/modules/features/consent/ketch/mergers/footer.d.ts.map +1 -0
- package/dist/modules/features/consent/ketch/mergers/footer.js +40 -0
- package/dist/modules/features/consent/ketch/mergers/footer.js.map +1 -0
- package/dist/modules/features/consent/ketch/mergers/knip.d.ts +18 -0
- package/dist/modules/features/consent/ketch/mergers/knip.d.ts.map +1 -0
- package/dist/modules/features/consent/ketch/mergers/knip.js +37 -0
- package/dist/modules/features/consent/ketch/mergers/knip.js.map +1 -0
- package/dist/modules/features/consent/ketch/mergers/layout.d.ts +25 -0
- package/dist/modules/features/consent/ketch/mergers/layout.d.ts.map +1 -0
- package/dist/modules/features/consent/ketch/mergers/layout.js +55 -0
- package/dist/modules/features/consent/ketch/mergers/layout.js.map +1 -0
- package/dist/modules/features/jobs/ashby/config.d.ts +19 -0
- package/dist/modules/features/jobs/ashby/config.d.ts.map +1 -0
- package/dist/modules/features/jobs/ashby/config.js +29 -0
- package/dist/modules/features/jobs/ashby/config.js.map +1 -0
- package/dist/modules/features/jobs/ashby/mergers/check-integration.d.ts +14 -0
- package/dist/modules/features/jobs/ashby/mergers/check-integration.d.ts.map +1 -0
- package/dist/modules/features/jobs/ashby/mergers/check-integration.js +78 -0
- package/dist/modules/features/jobs/ashby/mergers/check-integration.js.map +1 -0
- package/dist/modules/features/jobs/ashby/mergers/env-example.d.ts +12 -0
- package/dist/modules/features/jobs/ashby/mergers/env-example.d.ts.map +1 -0
- package/dist/modules/features/jobs/ashby/mergers/env-example.js +27 -0
- package/dist/modules/features/jobs/ashby/mergers/env-example.js.map +1 -0
- package/dist/modules/features/jobs/ashby/mergers/knip.d.ts +18 -0
- package/dist/modules/features/jobs/ashby/mergers/knip.d.ts.map +1 -0
- package/dist/modules/features/jobs/ashby/mergers/knip.js +41 -0
- package/dist/modules/features/jobs/ashby/mergers/knip.js.map +1 -0
- package/dist/paths.d.ts +12 -0
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +12 -0
- package/dist/paths.js.map +1 -1
- package/package.json +3 -1
- package/src/agent-skills/ashby-pagebuilder-block/SKILL.md +277 -0
- package/src/agent-skills/hubspot-pagebuilder-block/SKILL.md +58 -25
- package/src/agent-skills/ketch-consent-check/SKILL.md +197 -0
- package/src/agent-skills/ketch-consent-setup/SKILL.md +326 -0
- package/src/agent-skills/ketch-consent-setup/references/ui-customization.md +329 -0
- package/src/agent-skills/page-builder-block/SKILL.md +150 -0
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/components/anchor-id-input.tsx +17 -0
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/components/presentation-input.tsx +146 -0
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/components/spacing-steps-input.tsx +84 -0
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/fetchers/layout.ts +6 -3
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/icons.ts +8 -0
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/queries.ts +12 -0
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/components/reusable/blog-content.ts +3 -3
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/components/reusable/description.ts +3 -3
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/components/reusable/gated-content.ts +3 -3
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/components/reusable/hero.ts +3 -3
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/components/reusable/rich-text-block.ts +3 -3
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/components/singleton/content-collection.ts +3 -3
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/index.ts +8 -0
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/layout/spacing-settings.ts +120 -0
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/shared/anchor.ts +75 -0
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/shared/block.ts +46 -0
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/shared/presentation.ts +44 -0
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/shared/spacing.ts +164 -0
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/singletons.ts +7 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/components/anchor-id-input.tsx +17 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/components/presentation-input.tsx +146 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/components/spacing-steps-input.tsx +84 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/fetchers/layout.ts +4 -2
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/icons.ts +8 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/queries.ts +12 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/components/reusable/blog-content.ts +3 -3
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/components/reusable/description.ts +3 -3
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/components/reusable/gated-content.ts +3 -3
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/components/reusable/hero.ts +3 -3
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/components/reusable/rich-text-block.ts +3 -3
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/components/singleton/content-collection.ts +3 -3
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/index.ts +8 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/layout/spacing-settings.ts +120 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/shared/anchor.ts +75 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/shared/block.ts +46 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/shared/presentation.ts +44 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/shared/spacing.ts +164 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/singletons.ts +7 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/tags.ts +2 -0
- package/src/modules/features/consent/ketch/files/lib/integrations/check-integration.ts +25 -0
- package/src/modules/features/consent/ketch/files/lib/integrations/ketch/README.md +70 -0
- package/src/modules/features/consent/ketch/files/lib/integrations/ketch/categories.ts +20 -0
- package/src/modules/features/consent/ketch/files/lib/integrations/ketch/consent-store.ts +107 -0
- package/src/modules/features/consent/ketch/files/lib/integrations/ketch/env.ts +20 -0
- package/src/modules/features/consent/ketch/files/lib/integrations/ketch/ketch-experience.css +136 -0
- package/src/modules/features/consent/ketch/files/lib/integrations/ketch/preferences-button.tsx +51 -0
- package/src/modules/features/consent/ketch/files/lib/integrations/ketch/script.tsx +8 -0
- package/src/modules/features/consent/ketch/files/lib/integrations/ketch/types.ts +15 -0
- package/src/modules/features/consent/ketch/files/lib/integrations/ketch/use-consent.ts +26 -0
- package/src/modules/features/jobs/ashby/files/_sanity-adapter/job-board-block.ts +53 -0
- package/src/modules/features/jobs/ashby/files/lib/integrations/ashby/README.md +134 -0
- package/src/modules/features/jobs/ashby/files/lib/integrations/ashby/env.ts +3 -0
- package/src/modules/features/jobs/ashby/files/lib/integrations/ashby/index.ts +40 -0
- package/src/modules/features/jobs/ashby/files/lib/integrations/ashby/normalize.ts +124 -0
- package/src/modules/features/jobs/ashby/files/lib/integrations/ashby/types.ts +20 -0
- package/src/modules/features/jobs/ashby/files/lib/integrations/check-integration.ts +25 -0
- package/src/templates/next-pagebuilder/AGENTS.md +129 -0
- package/src/templates/next-pagebuilder/CLAUDE.md +3 -0
- package/src/templates/next-pagebuilder/README.md +70 -0
- package/src/templates/next-pagebuilder/app/(content)/layout.tsx +2 -0
- package/src/templates/next-pagebuilder/components/layout/spacing-scale/index.tsx +18 -0
- package/src/templates/next-pagebuilder/components/page-builder/components/article-content/index.tsx +1 -1
- package/src/templates/next-pagebuilder/components/page-builder/components/content-collection/index.tsx +2 -2
- package/src/templates/next-pagebuilder/components/page-builder/components/description.tsx +3 -7
- package/src/templates/next-pagebuilder/components/page-builder/components/gated-content/index.tsx +2 -2
- package/src/templates/next-pagebuilder/components/page-builder/components/hero.tsx +3 -7
- package/src/templates/next-pagebuilder/components/page-builder/components/rich-text-block.tsx +3 -5
- package/src/templates/next-pagebuilder/components/page-builder/registry.tsx +70 -0
- package/src/templates/next-pagebuilder/components/page-builder/renderer.tsx +33 -49
- package/src/templates/next-pagebuilder/components/page-builder/section.tsx +35 -0
- package/src/templates/next-pagebuilder/components/page-document/index.tsx +1 -1
- package/src/templates/next-pagebuilder/lib/integrations/sanity/sanity.types.ts +92 -4
- package/src/templates/next-pagebuilder-cache/AGENTS.md +136 -0
- package/src/templates/next-pagebuilder-cache/CLAUDE.md +3 -0
- package/src/templates/next-pagebuilder-cache/README.md +75 -0
- package/src/templates/next-pagebuilder-cache/app/(content)/layout.tsx +2 -0
- package/src/templates/next-pagebuilder-cache/components/layout/spacing-scale/index.tsx +46 -0
- package/src/templates/next-pagebuilder-cache/components/page-builder/components/article-content/index.tsx +1 -1
- package/src/templates/next-pagebuilder-cache/components/page-builder/components/content-collection/index.tsx +2 -2
- package/src/templates/next-pagebuilder-cache/components/page-builder/components/description.tsx +3 -7
- package/src/templates/next-pagebuilder-cache/components/page-builder/components/gated-content/index.tsx +2 -2
- package/src/templates/next-pagebuilder-cache/components/page-builder/components/hero.tsx +3 -7
- package/src/templates/next-pagebuilder-cache/components/page-builder/components/rich-text-block.tsx +3 -5
- package/src/templates/next-pagebuilder-cache/components/page-builder/registry.tsx +70 -0
- package/src/templates/next-pagebuilder-cache/components/page-builder/renderer.tsx +33 -49
- package/src/templates/next-pagebuilder-cache/components/page-builder/section.tsx +35 -0
- package/src/templates/next-pagebuilder-cache/components/page-document/index.tsx +1 -1
- package/src/templates/next-pagebuilder-cache/lib/integrations/sanity/sanity.types.ts +92 -4
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: page-builder-block
|
|
3
|
+
description: >-
|
|
4
|
+
Create or modify a Sanity page-builder block in a basement page-builder
|
|
5
|
+
project so it follows the repo conventions: defined with `defineBlock`, drawn
|
|
6
|
+
through the renderer's block registry, Anchor ID (generated from the title
|
|
7
|
+
when empty), Presentation Mode, and spacing owned by the frame that instances
|
|
8
|
+
the block rather than the block itself. Use when asked to "add a block to the
|
|
9
|
+
page builder", "create a new section/component for Sanity", "add anchor links
|
|
10
|
+
to a block", "control the spacing of a block from Sanity", or when reviewing
|
|
11
|
+
an existing block for these rules.
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# Page-builder block conventions
|
|
15
|
+
|
|
16
|
+
Blocks are **documents** referenced from the `pageBuilder` array, drawn by
|
|
17
|
+
`components/page-builder/renderer.tsx` through the registry in
|
|
18
|
+
`components/page-builder/registry.tsx`. Read one existing block end to end
|
|
19
|
+
before writing a new one — `hero` is the smallest complete example:
|
|
20
|
+
|
|
21
|
+
- schema: `lib/integrations/sanity/schemas/components/reusable/hero.ts`
|
|
22
|
+
- component: `components/page-builder/components/hero.tsx`
|
|
23
|
+
- registration: `lib/integrations/sanity/schemas/components/index.ts`,
|
|
24
|
+
`lib/integrations/sanity/schemas/index.ts`,
|
|
25
|
+
`lib/integrations/sanity/page-builder-config.ts`,
|
|
26
|
+
`lib/integrations/sanity/structure.ts`,
|
|
27
|
+
`components/page-builder/registry.tsx`
|
|
28
|
+
|
|
29
|
+
A block exists in two halves — a schema and a component — and each half has one
|
|
30
|
+
place that makes it a block rather than an ordinary document or a loose React
|
|
31
|
+
component. Use them and the conventions below come for free; skip them and a
|
|
32
|
+
typecheck fails.
|
|
33
|
+
|
|
34
|
+
## Non-negotiables
|
|
35
|
+
|
|
36
|
+
1. **Define the schema with `defineBlock`, never `defineType`.**
|
|
37
|
+
`lib/integrations/sanity/schemas/shared/block.ts` implies
|
|
38
|
+
`type: "document"` and appends Anchor ID + Presentation Mode as the last two
|
|
39
|
+
fields:
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
import { defineField } from "sanity"
|
|
43
|
+
import { defineBlock } from "@/lib/integrations/sanity/schemas/shared/block"
|
|
44
|
+
|
|
45
|
+
export const featureGrid = defineBlock({
|
|
46
|
+
name: "featureGrid",
|
|
47
|
+
title: "Feature Grid",
|
|
48
|
+
icon: featureGridIcon,
|
|
49
|
+
fields: [
|
|
50
|
+
// ...content fields...
|
|
51
|
+
],
|
|
52
|
+
preview: { /* ... */ },
|
|
53
|
+
})
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
What it adds:
|
|
57
|
+
- `anchorId` — optional. Left empty, the anchor is **generated from the
|
|
58
|
+
block's title** at render time (`resolveAnchorId` in
|
|
59
|
+
`lib/integrations/sanity/schemas/shared/anchor.ts` walks `headline`,
|
|
60
|
+
`heading`, `teaserHeading`, `title`, `label` — never `internalTitle`, which
|
|
61
|
+
is Studio-only) and de-duplicated per page. A value typed by hand always
|
|
62
|
+
wins. Name your block's headline field one of those and it works for free.
|
|
63
|
+
- `presentation` — object with `paddingTop` / `paddingBottom`, each storing
|
|
64
|
+
the `_key` of a step from the shared scale. No manual px, ever. A block
|
|
65
|
+
that never touches it follows whichever step is marked as the default.
|
|
66
|
+
|
|
67
|
+
Blocks that declare `groups` get a **Presentation** tab for the two fields,
|
|
68
|
+
added automatically — don't list it in `groups` yourself. A block with no
|
|
69
|
+
groups shows them inline, at the bottom of the form.
|
|
70
|
+
|
|
71
|
+
2. **Register the component in the block registry.** One entry per block, keyed
|
|
72
|
+
by schema type; the renderer has no switch to extend:
|
|
73
|
+
|
|
74
|
+
```tsx
|
|
75
|
+
featureGrid: {
|
|
76
|
+
render: (block) => <FeatureGrid block={block} />,
|
|
77
|
+
isEmpty: (block) => !block.items?.length,
|
|
78
|
+
},
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
- `render` receives the block narrowed to its own `_type`, plus a
|
|
82
|
+
`BlockContext` for page-level values a block doesn't own (`searchParams`,
|
|
83
|
+
`pinnedCategory`). Take the second argument only if you need it.
|
|
84
|
+
- `isEmpty` is optional and declares when the block has nothing to show. The
|
|
85
|
+
renderer then skips the block **and** its `<Section>`, so an unfilled block
|
|
86
|
+
leaves no padded gap behind and doesn't claim an anchor id. Don't
|
|
87
|
+
early-return `null` from the component instead — the renderer has to know
|
|
88
|
+
before it wraps anything.
|
|
89
|
+
|
|
90
|
+
The registry's key set is typed as exactly `PageBuilderDocumentType`, so a
|
|
91
|
+
block registered in `page-builder-config.ts` without an entry here — or an
|
|
92
|
+
entry here for a block that was never registered there — is a typecheck
|
|
93
|
+
error.
|
|
94
|
+
|
|
95
|
+
3. **Never hardcode vertical padding inside a block component.** The renderer
|
|
96
|
+
wraps every block in `<Section>` (`components/page-builder/section.tsx`),
|
|
97
|
+
which renders the `<section>` element, applies the anchor `id` and the
|
|
98
|
+
padding. A block component returns its content only — no outer `<section>`,
|
|
99
|
+
no `py-*` / `pt-*` / `pb-*` on its root. Internal gaps between a block's own
|
|
100
|
+
parts are fine (`gap-*`, `space-y-*`, `mt-*` on children).
|
|
101
|
+
|
|
102
|
+
4. **The spacing scale is content, not code.** Editors own it at **Layout →
|
|
103
|
+
Spacing Scale** (`spacingSettings`): a list of steps, each with a name, px
|
|
104
|
+
per breakpoint (mobile / tablet / desktop, empty reuses Desktop) and one
|
|
105
|
+
marked as the default — ticking a second one unticks the previous, so there
|
|
106
|
+
is always exactly one. They add, rename or remove steps without touching
|
|
107
|
+
code; when the list is empty the field offers an "Add the built-in steps"
|
|
108
|
+
button that seeds it.
|
|
109
|
+
`lib/integrations/sanity/schemas/shared/spacing.ts` holds the five built-in
|
|
110
|
+
steps (XS · SM · MD · LG · XL, MD default) used to seed the document and as
|
|
111
|
+
the fallback when it is empty, plus the resolver and the CSS builder.
|
|
112
|
+
|
|
113
|
+
Resolved values ship as CSS custom properties from
|
|
114
|
+
`components/layout/spacing-scale/index.tsx` (rendered by
|
|
115
|
+
`app/(content)/layout.tsx`), one `--section-space-<step key>` per step plus
|
|
116
|
+
`--section-space-default`, re-declared inside `min-width: 768px` and
|
|
117
|
+
`1440px` media queries. `Section` only references
|
|
118
|
+
`var(--section-space-<key>, var(--section-space-default, 2.5rem))`, so a
|
|
119
|
+
deleted or unknown step degrades to the default instead of breaking, and
|
|
120
|
+
**changing a value never requires a deploy**.
|
|
121
|
+
|
|
122
|
+
Publishing `spacingSettings` busts the layout cache: it is in
|
|
123
|
+
`SANITY_LAYOUT_TAGS` (`fetchers/layout.ts`, or `tags.ts` on the Cache
|
|
124
|
+
Components variant), same as navbar and footer.
|
|
125
|
+
|
|
126
|
+
5. **Regenerate types after a schema change:** `bun run sanity:typegen`. The
|
|
127
|
+
page query spreads `...` for non-gated blocks, so new fields flow through
|
|
128
|
+
automatically — except `gatedContent`, whose GROQ branch lists fields
|
|
129
|
+
explicitly (`lib/integrations/sanity/queries.ts`). Add new fields there by
|
|
130
|
+
hand if the block is gated.
|
|
131
|
+
|
|
132
|
+
## Checklist for a new block
|
|
133
|
+
|
|
134
|
+
- [ ] Schema in `schemas/components/reusable/<block>.ts` (or `singleton/` for a
|
|
135
|
+
one-instance block), built with `defineBlock` and carrying a `preview`.
|
|
136
|
+
- [ ] Icon in `lib/integrations/sanity/icons.ts` (phosphor duotone).
|
|
137
|
+
- [ ] Exported from `schemas/components/index.ts` and registered in
|
|
138
|
+
`schemas/index.ts` (`schema.types`).
|
|
139
|
+
- [ ] Member added to `page-builder-config.ts`: the `PageBuilderDocumentType`
|
|
140
|
+
union plus an entry in `reusablePageBuilderReferenceMembers` carrying
|
|
141
|
+
**both** axes — `pageTypes` (which page documents may host it) and
|
|
142
|
+
`category` (what the block is, one of `componentCategories`; `misc` only
|
|
143
|
+
when nothing fits).
|
|
144
|
+
- [ ] Listed in `structure.ts` under the right folder.
|
|
145
|
+
- [ ] Component in `components/page-builder/components/<block>.tsx`, typed with
|
|
146
|
+
`Extract<PageBuilderBlock, { _type: "<block>" }>`, no outer section, no
|
|
147
|
+
vertical padding. Variants via `cva`/`cn` when the block has variants.
|
|
148
|
+
- [ ] Entry in `components/page-builder/registry.tsx`, with `isEmpty` when the
|
|
149
|
+
block can be left unfilled.
|
|
150
|
+
- [ ] `bun run sanity:typegen && bun run typecheck && bun run lint && bun run build && bun run knip`.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type StringInputProps, useFormValue } from "sanity";
|
|
2
|
+
import { deriveAnchorId } from "@/lib/integrations/sanity/schemas/shared/anchor";
|
|
3
|
+
|
|
4
|
+
export function AnchorIdInput(props: StringInputProps) {
|
|
5
|
+
const document = useFormValue([]) as Record<string, unknown> | undefined;
|
|
6
|
+
const derived = deriveAnchorId(document ?? {});
|
|
7
|
+
|
|
8
|
+
return props.renderDefault({
|
|
9
|
+
...props,
|
|
10
|
+
elementProps: {
|
|
11
|
+
...props.elementProps,
|
|
12
|
+
placeholder: derived
|
|
13
|
+
? `${derived} — generated from the title`
|
|
14
|
+
: "generated from the title",
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { Box, Card, Flex, Select, Stack, Text } from "@sanity/ui";
|
|
2
|
+
import { useEffect, useState } from "react";
|
|
3
|
+
import { type ObjectInputProps, set, setIfMissing, useClient } from "sanity";
|
|
4
|
+
import { apiVersion } from "@/lib/integrations/sanity/env";
|
|
5
|
+
import {
|
|
6
|
+
paddingBottomIcon,
|
|
7
|
+
paddingTopIcon,
|
|
8
|
+
type SanityStudioIcon,
|
|
9
|
+
} from "@/lib/integrations/sanity/icons";
|
|
10
|
+
import {
|
|
11
|
+
getDefaultSpacingStep,
|
|
12
|
+
resolveSpacingSteps,
|
|
13
|
+
type SpacingStep,
|
|
14
|
+
type SpacingStepSource,
|
|
15
|
+
spacingStepOptions,
|
|
16
|
+
} from "@/lib/integrations/sanity/schemas/shared/spacing";
|
|
17
|
+
|
|
18
|
+
const SPACING_STEPS_QUERY = `coalesce(
|
|
19
|
+
*[_id == "drafts.spacingSettings"][0],
|
|
20
|
+
*[_id == "spacingSettings"][0]
|
|
21
|
+
).steps[]{ _key, name, mobile, tablet, desktop, isDefault }`;
|
|
22
|
+
|
|
23
|
+
type PaddingField = "paddingTop" | "paddingBottom";
|
|
24
|
+
|
|
25
|
+
type PresentationValue = Partial<Record<PaddingField, string>>;
|
|
26
|
+
|
|
27
|
+
function useSpacingSteps() {
|
|
28
|
+
const client = useClient({ apiVersion });
|
|
29
|
+
const [steps, setSteps] = useState<SpacingStep[]>(() =>
|
|
30
|
+
resolveSpacingSteps(null),
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
let active = true;
|
|
35
|
+
client
|
|
36
|
+
.fetch<SpacingStepSource[] | null>(SPACING_STEPS_QUERY)
|
|
37
|
+
.then((rows) => {
|
|
38
|
+
if (active) setSteps(resolveSpacingSteps(rows));
|
|
39
|
+
})
|
|
40
|
+
.catch(() => setSteps(resolveSpacingSteps(null)));
|
|
41
|
+
return () => {
|
|
42
|
+
active = false;
|
|
43
|
+
};
|
|
44
|
+
}, [client]);
|
|
45
|
+
|
|
46
|
+
return steps;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
type SpacingRowProps = {
|
|
50
|
+
name: PaddingField;
|
|
51
|
+
label: string;
|
|
52
|
+
icon: SanityStudioIcon;
|
|
53
|
+
options: Array<{ value: string; title: string }>;
|
|
54
|
+
value: string;
|
|
55
|
+
onSelect: (name: PaddingField, next: string) => void;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
function SpacingRow({
|
|
59
|
+
name,
|
|
60
|
+
label,
|
|
61
|
+
icon,
|
|
62
|
+
options,
|
|
63
|
+
value,
|
|
64
|
+
onSelect,
|
|
65
|
+
}: SpacingRowProps) {
|
|
66
|
+
const Icon = icon;
|
|
67
|
+
|
|
68
|
+
return (
|
|
69
|
+
<Flex align="center" gap={2}>
|
|
70
|
+
<Card
|
|
71
|
+
padding={2}
|
|
72
|
+
radius={2}
|
|
73
|
+
tone="transparent"
|
|
74
|
+
border
|
|
75
|
+
title={label}
|
|
76
|
+
aria-hidden
|
|
77
|
+
>
|
|
78
|
+
<Text size={2}>
|
|
79
|
+
<Icon />
|
|
80
|
+
</Text>
|
|
81
|
+
</Card>
|
|
82
|
+
<Box flex={1}>
|
|
83
|
+
<Select
|
|
84
|
+
aria-label={label}
|
|
85
|
+
fontSize={1}
|
|
86
|
+
padding={3}
|
|
87
|
+
radius={2}
|
|
88
|
+
value={value}
|
|
89
|
+
onChange={(event) => onSelect(name, event.currentTarget.value)}
|
|
90
|
+
>
|
|
91
|
+
{options.map((option) => (
|
|
92
|
+
<option key={option.value} value={option.value}>
|
|
93
|
+
{option.title}
|
|
94
|
+
</option>
|
|
95
|
+
))}
|
|
96
|
+
</Select>
|
|
97
|
+
</Box>
|
|
98
|
+
</Flex>
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export function PresentationInput(props: ObjectInputProps) {
|
|
103
|
+
const value = props.value as PresentationValue | undefined;
|
|
104
|
+
const steps = useSpacingSteps();
|
|
105
|
+
const options = spacingStepOptions(steps);
|
|
106
|
+
const fallback = getDefaultSpacingStep(steps).key;
|
|
107
|
+
|
|
108
|
+
const resolve = (key: string | undefined) =>
|
|
109
|
+
steps.some((step) => step.key === key) ? (key as string) : fallback;
|
|
110
|
+
|
|
111
|
+
const handleSelect = (name: PaddingField, next: string) => {
|
|
112
|
+
props.onChange([setIfMissing({}), set(next, [name])]);
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
return (
|
|
116
|
+
<Stack space={3}>
|
|
117
|
+
<Flex gap={3} wrap="wrap">
|
|
118
|
+
<Box flex={1} style={{ minWidth: 200 }}>
|
|
119
|
+
<SpacingRow
|
|
120
|
+
name="paddingTop"
|
|
121
|
+
label="Padding top"
|
|
122
|
+
icon={paddingTopIcon}
|
|
123
|
+
options={options}
|
|
124
|
+
value={resolve(value?.paddingTop)}
|
|
125
|
+
onSelect={handleSelect}
|
|
126
|
+
/>
|
|
127
|
+
</Box>
|
|
128
|
+
<Box flex={1} style={{ minWidth: 200 }}>
|
|
129
|
+
<SpacingRow
|
|
130
|
+
name="paddingBottom"
|
|
131
|
+
label="Padding bottom"
|
|
132
|
+
icon={paddingBottomIcon}
|
|
133
|
+
options={options}
|
|
134
|
+
value={resolve(value?.paddingBottom)}
|
|
135
|
+
onSelect={handleSelect}
|
|
136
|
+
/>
|
|
137
|
+
</Box>
|
|
138
|
+
</Flex>
|
|
139
|
+
<Text size={1} muted>
|
|
140
|
+
Spacing above and below this block, from the shared scale (edit the steps
|
|
141
|
+
in Layout → Spacing Scale). Untouched blocks follow whichever step is
|
|
142
|
+
marked as the default.
|
|
143
|
+
</Text>
|
|
144
|
+
</Stack>
|
|
145
|
+
);
|
|
146
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { Button, Card, Stack, Text } from "@sanity/ui";
|
|
2
|
+
import { useEffect, useRef } from "react";
|
|
3
|
+
import { type ArrayOfObjectsInputProps, set } from "sanity";
|
|
4
|
+
import { defaultSpacingSteps } from "@/lib/integrations/sanity/schemas/shared/spacing";
|
|
5
|
+
|
|
6
|
+
type StepValue = { _key?: string; isDefault?: boolean };
|
|
7
|
+
|
|
8
|
+
const defaultKeysOf = (value: StepValue[] | undefined) =>
|
|
9
|
+
(value ?? [])
|
|
10
|
+
.filter((step) => step?.isDefault === true)
|
|
11
|
+
.flatMap((step) => (step._key ? [step._key] : []));
|
|
12
|
+
|
|
13
|
+
export function SpacingStepsInput(props: ArrayOfObjectsInputProps) {
|
|
14
|
+
const value = props.value as StepValue[] | undefined;
|
|
15
|
+
const { onChange } = props;
|
|
16
|
+
|
|
17
|
+
const defaultKeys = defaultKeysOf(value);
|
|
18
|
+
const defaultKeysId = defaultKeys.join(",");
|
|
19
|
+
const lastSingleDefault = useRef<string | undefined>(defaultKeys[0]);
|
|
20
|
+
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
const keys = defaultKeysId ? defaultKeysId.split(",") : [];
|
|
23
|
+
|
|
24
|
+
if (keys.length < 2) {
|
|
25
|
+
lastSingleDefault.current = keys[0];
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const keep = keys.find((key) => key !== lastSingleDefault.current) ?? keys[0];
|
|
30
|
+
lastSingleDefault.current = keep;
|
|
31
|
+
|
|
32
|
+
onChange(
|
|
33
|
+
keys
|
|
34
|
+
.filter((key) => key !== keep)
|
|
35
|
+
.map((key) => set(false, [{ _key: key }, "isDefault"])),
|
|
36
|
+
);
|
|
37
|
+
}, [defaultKeysId, onChange]);
|
|
38
|
+
|
|
39
|
+
const seed = () => {
|
|
40
|
+
onChange(
|
|
41
|
+
set(
|
|
42
|
+
defaultSpacingSteps.map((step) => ({
|
|
43
|
+
_key: step.key,
|
|
44
|
+
_type: "spacingStep",
|
|
45
|
+
name: step.name,
|
|
46
|
+
mobile: step.mobile,
|
|
47
|
+
tablet: step.tablet,
|
|
48
|
+
desktop: step.desktop,
|
|
49
|
+
isDefault: step.isDefault,
|
|
50
|
+
})),
|
|
51
|
+
),
|
|
52
|
+
);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
<Stack space={3}>
|
|
57
|
+
{props.renderDefault(props)}
|
|
58
|
+
{value?.length ? null : (
|
|
59
|
+
<Card padding={3} radius={2} border tone="primary">
|
|
60
|
+
<Stack space={3}>
|
|
61
|
+
<Text size={1}>
|
|
62
|
+
No steps yet, so blocks fall back to the built-in scale:{" "}
|
|
63
|
+
{defaultSpacingSteps
|
|
64
|
+
.map(
|
|
65
|
+
(step) =>
|
|
66
|
+
`${step.name} ${step.desktop}px${
|
|
67
|
+
step.isDefault ? " (default)" : ""
|
|
68
|
+
}`,
|
|
69
|
+
)
|
|
70
|
+
.join(" · ")}
|
|
71
|
+
.
|
|
72
|
+
</Text>
|
|
73
|
+
<Button
|
|
74
|
+
text="Add the built-in steps"
|
|
75
|
+
tone="primary"
|
|
76
|
+
mode="ghost"
|
|
77
|
+
onClick={seed}
|
|
78
|
+
/>
|
|
79
|
+
</Stack>
|
|
80
|
+
</Card>
|
|
81
|
+
)}
|
|
82
|
+
</Stack>
|
|
83
|
+
);
|
|
84
|
+
}
|
package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/fetchers/layout.ts
CHANGED
|
@@ -8,6 +8,7 @@ export type NavbarData = NonNullable<LayoutData["navbar"]>;
|
|
|
8
8
|
export type FooterData = NonNullable<LayoutData["footer"]>;
|
|
9
9
|
export type CompanyData = NonNullable<LayoutData["companyData"]>;
|
|
10
10
|
export type StructuredData = NonNullable<LayoutData["structuredData"]>;
|
|
11
|
+
export type SpacingSettings = NonNullable<LayoutData["spacingSettings"]>;
|
|
11
12
|
|
|
12
13
|
// Singleton document types that, when published, should bust the layout cache.
|
|
13
14
|
export const SANITY_LAYOUT_TAGS = [
|
|
@@ -15,6 +16,7 @@ export const SANITY_LAYOUT_TAGS = [
|
|
|
15
16
|
"footer",
|
|
16
17
|
"companyData",
|
|
17
18
|
"structuredData",
|
|
19
|
+
"spacingSettings",
|
|
18
20
|
];
|
|
19
21
|
|
|
20
22
|
const EMPTY_LAYOUT: LayoutData = {
|
|
@@ -22,11 +24,12 @@ const EMPTY_LAYOUT: LayoutData = {
|
|
|
22
24
|
footer: null,
|
|
23
25
|
companyData: null,
|
|
24
26
|
structuredData: null,
|
|
27
|
+
spacingSettings: null,
|
|
25
28
|
};
|
|
26
29
|
|
|
27
|
-
// One query for
|
|
28
|
-
// footer
|
|
29
|
-
// because it reads all
|
|
30
|
+
// One query for every layout singleton, wrapped in React cache so the header,
|
|
31
|
+
// footer, json-ld and spacing scale share a single round trip. Tagged with each
|
|
32
|
+
// `_type` because it reads all of those documents.
|
|
30
33
|
export const getLayoutData = cache(async (): Promise<LayoutData> => {
|
|
31
34
|
const { data } = await fetchSanity<LayoutData>({
|
|
32
35
|
query: LAYOUT_QUERY,
|
|
@@ -2,6 +2,9 @@ import type { Icon, IconProps } from "@phosphor-icons/react";
|
|
|
2
2
|
import {
|
|
3
3
|
AppWindowIcon,
|
|
4
4
|
ArrowBendUpRightIcon,
|
|
5
|
+
ArrowLineDownIcon,
|
|
6
|
+
ArrowLineUpIcon,
|
|
7
|
+
ArrowsOutLineVerticalIcon,
|
|
5
8
|
ArticleNyTimesIcon,
|
|
6
9
|
BracketsCurlyIcon,
|
|
7
10
|
BriefcaseIcon,
|
|
@@ -75,6 +78,11 @@ export const richTextIcon = asDuotoneIcon(TextTIcon);
|
|
|
75
78
|
export const contentIcon = asDuotoneIcon(ArticleNyTimesIcon);
|
|
76
79
|
export const gatedContentIcon = asDuotoneIcon(LockKeyIcon);
|
|
77
80
|
|
|
81
|
+
export const spacingSettingsIcon = asDuotoneIcon(ArrowsOutLineVerticalIcon);
|
|
82
|
+
|
|
83
|
+
export const paddingTopIcon = asDuotoneIcon(ArrowLineUpIcon);
|
|
84
|
+
export const paddingBottomIcon = asDuotoneIcon(ArrowLineDownIcon);
|
|
85
|
+
|
|
78
86
|
export const pageIcon = asDuotoneIcon(FileTextIcon);
|
|
79
87
|
export const pagesFolderIcon = asDuotoneIcon(BrowsersIcon);
|
|
80
88
|
export const pageFolderIcon = asDuotoneIcon(FolderOpenIcon);
|
package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/queries.ts
CHANGED
|
@@ -96,6 +96,8 @@ const pageBuilderProjection = `
|
|
|
96
96
|
_type == "gatedContent" => {
|
|
97
97
|
_id,
|
|
98
98
|
_type,
|
|
99
|
+
anchorId,
|
|
100
|
+
presentation,
|
|
99
101
|
internalTitle,
|
|
100
102
|
teaserHeading,
|
|
101
103
|
teaserBody[]{
|
|
@@ -533,6 +535,16 @@ export const LAYOUT_QUERY = defineQuery(`
|
|
|
533
535
|
},
|
|
534
536
|
"structuredData": *[_type == "structuredData"][0]{
|
|
535
537
|
${structuredDataProjection}
|
|
538
|
+
},
|
|
539
|
+
"spacingSettings": *[_type == "spacingSettings"][0]{
|
|
540
|
+
steps[]{
|
|
541
|
+
_key,
|
|
542
|
+
name,
|
|
543
|
+
mobile,
|
|
544
|
+
tablet,
|
|
545
|
+
desktop,
|
|
546
|
+
isDefault
|
|
547
|
+
}
|
|
536
548
|
}
|
|
537
549
|
}
|
|
538
550
|
`);
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { defineField
|
|
1
|
+
import { defineField } from "sanity";
|
|
2
2
|
import { contentIcon } from "@/lib/integrations/sanity/icons";
|
|
3
|
+
import { defineBlock } from "@/lib/integrations/sanity/schemas/shared/block";
|
|
3
4
|
|
|
4
|
-
export const blogContent =
|
|
5
|
+
export const blogContent = defineBlock({
|
|
5
6
|
name: "blogContent",
|
|
6
7
|
title: "Blog Content",
|
|
7
|
-
type: "document",
|
|
8
8
|
icon: contentIcon,
|
|
9
9
|
fields: [
|
|
10
10
|
defineField({
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { defineField
|
|
1
|
+
import { defineField } from "sanity";
|
|
2
2
|
import { descriptionIcon } from "@/lib/integrations/sanity/icons";
|
|
3
|
+
import { defineBlock } from "@/lib/integrations/sanity/schemas/shared/block";
|
|
3
4
|
|
|
4
|
-
export const description =
|
|
5
|
+
export const description = defineBlock({
|
|
5
6
|
name: "description",
|
|
6
7
|
title: "Description",
|
|
7
|
-
type: "document",
|
|
8
8
|
icon: descriptionIcon,
|
|
9
9
|
fields: [
|
|
10
10
|
defineField({
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { defineField
|
|
1
|
+
import { defineField } from "sanity";
|
|
2
2
|
import { gatedContentIcon } from "@/lib/integrations/sanity/icons";
|
|
3
|
+
import { defineBlock } from "@/lib/integrations/sanity/schemas/shared/block";
|
|
3
4
|
|
|
4
5
|
type GatedContentParent = { kind?: string };
|
|
5
6
|
|
|
@@ -19,10 +20,9 @@ const requiredForKind =
|
|
|
19
20
|
return isEmpty ? message : true;
|
|
20
21
|
};
|
|
21
22
|
|
|
22
|
-
export const gatedContent =
|
|
23
|
+
export const gatedContent = defineBlock({
|
|
23
24
|
name: "gatedContent",
|
|
24
25
|
title: "Gated Content",
|
|
25
|
-
type: "document",
|
|
26
26
|
icon: gatedContentIcon,
|
|
27
27
|
description:
|
|
28
28
|
"Content hidden behind a lead-capture gate. Everyone sees the teaser; the payload is withheld from the page until the visitor submits the form.",
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { defineField
|
|
1
|
+
import { defineField } from "sanity";
|
|
2
2
|
import { heroIcon } from "@/lib/integrations/sanity/icons";
|
|
3
|
+
import { defineBlock } from "@/lib/integrations/sanity/schemas/shared/block";
|
|
3
4
|
|
|
4
|
-
export const hero =
|
|
5
|
+
export const hero = defineBlock({
|
|
5
6
|
name: "hero",
|
|
6
7
|
title: "Heading",
|
|
7
|
-
type: "document",
|
|
8
8
|
icon: heroIcon,
|
|
9
9
|
fields: [
|
|
10
10
|
defineField({
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { defineField
|
|
1
|
+
import { defineField } from "sanity";
|
|
2
2
|
import { richTextIcon } from "@/lib/integrations/sanity/icons";
|
|
3
|
+
import { defineBlock } from "@/lib/integrations/sanity/schemas/shared/block";
|
|
3
4
|
|
|
4
|
-
export const richTextBlock =
|
|
5
|
+
export const richTextBlock = defineBlock({
|
|
5
6
|
name: "richTextBlock",
|
|
6
7
|
title: "Rich Text",
|
|
7
|
-
type: "document",
|
|
8
8
|
icon: richTextIcon,
|
|
9
9
|
fields: [
|
|
10
10
|
defineField({
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { defineField
|
|
1
|
+
import { defineField } from "sanity";
|
|
2
2
|
import type { SanityStudioIcon } from "@/lib/integrations/sanity/icons";
|
|
3
3
|
import { pageListIcon } from "@/lib/integrations/sanity/icons";
|
|
4
|
+
import { defineBlock } from "@/lib/integrations/sanity/schemas/shared/block";
|
|
4
5
|
|
|
5
6
|
function createContentCollection(config: {
|
|
6
7
|
name: string;
|
|
@@ -8,10 +9,9 @@ function createContentCollection(config: {
|
|
|
8
9
|
icon: SanityStudioIcon;
|
|
9
10
|
label: string;
|
|
10
11
|
}) {
|
|
11
|
-
return
|
|
12
|
+
return defineBlock({
|
|
12
13
|
name: config.name,
|
|
13
14
|
title: config.title,
|
|
14
|
-
type: "document",
|
|
15
15
|
icon: config.icon,
|
|
16
16
|
description: `This component contains all the ${config.label}`,
|
|
17
17
|
fields: [
|
package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/index.ts
CHANGED
|
@@ -23,6 +23,7 @@ import { companyData } from "./layout/company-data";
|
|
|
23
23
|
import { footer } from "./layout/footer";
|
|
24
24
|
import { navbar } from "./layout/navbar";
|
|
25
25
|
import { redirect } from "./layout/redirect";
|
|
26
|
+
import { spacingSettings, spacingStep } from "./layout/spacing-settings";
|
|
26
27
|
import { structuredData } from "./layout/structured-data";
|
|
27
28
|
import { externalLink, link, pageReference } from "./shared/link";
|
|
28
29
|
import { metadata } from "./shared/metadata";
|
|
@@ -35,6 +36,7 @@ import {
|
|
|
35
36
|
import { page } from "./shared/page";
|
|
36
37
|
import { pageBuilder } from "./shared/page-builder";
|
|
37
38
|
import { pageFolder } from "./shared/page-folder";
|
|
39
|
+
import { presentation } from "./shared/presentation";
|
|
38
40
|
import { richText } from "./shared/richText";
|
|
39
41
|
import {
|
|
40
42
|
customJsonLd,
|
|
@@ -74,9 +76,12 @@ export {
|
|
|
74
76
|
pageBuilder,
|
|
75
77
|
pageFolder,
|
|
76
78
|
pageReference,
|
|
79
|
+
presentation,
|
|
77
80
|
redirect,
|
|
78
81
|
richText,
|
|
79
82
|
softwareApplicationJsonLd,
|
|
83
|
+
spacingSettings,
|
|
84
|
+
spacingStep,
|
|
80
85
|
structuredData,
|
|
81
86
|
studioPreview,
|
|
82
87
|
videoJsonLd,
|
|
@@ -91,6 +96,7 @@ export const schema: { types: SchemaTypeDefinition[] } = {
|
|
|
91
96
|
link,
|
|
92
97
|
metadata,
|
|
93
98
|
pageBuilder,
|
|
99
|
+
presentation,
|
|
94
100
|
richText,
|
|
95
101
|
|
|
96
102
|
// Page-level JSON-LD blocks (selectable in metadata)
|
|
@@ -122,6 +128,8 @@ export const schema: { types: SchemaTypeDefinition[] } = {
|
|
|
122
128
|
navbar,
|
|
123
129
|
footer,
|
|
124
130
|
structuredData,
|
|
131
|
+
spacingStep,
|
|
132
|
+
spacingSettings,
|
|
125
133
|
|
|
126
134
|
// Layout collections (managed lists, not singletons)
|
|
127
135
|
redirect,
|