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
|
@@ -15,40 +15,55 @@ export type ByBreakpoint<
|
|
|
15
15
|
B extends BreakpointMap = typeof BASEMENT_BREAKPOINTS,
|
|
16
16
|
> = { base: T } & Partial<Record<Extract<keyof B, string>, T>>
|
|
17
17
|
|
|
18
|
+
export type ImageSizesOptions<
|
|
19
|
+
B extends BreakpointMap = typeof BASEMENT_BREAKPOINTS,
|
|
20
|
+
> = { breakpoints?: B }
|
|
21
|
+
|
|
22
|
+
export type GridImageSizesOptions<
|
|
23
|
+
B extends BreakpointMap = typeof BASEMENT_BREAKPOINTS,
|
|
24
|
+
> = ImageSizesOptions<B> & {
|
|
25
|
+
/** The grid container's `max-width` in px, past which columns stop growing. */
|
|
26
|
+
maxWidth?: number
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
type Condition<T> = { min: number; value: T }
|
|
30
|
+
|
|
18
31
|
function columnWidth(columns: number): string {
|
|
19
32
|
return `${Math.round(100 / columns)}vw`
|
|
20
33
|
}
|
|
21
34
|
|
|
35
|
+
function toConditions<T>(
|
|
36
|
+
overrides: Readonly<Record<string, T | undefined>>,
|
|
37
|
+
scale: BreakpointMap
|
|
38
|
+
): Condition<T>[] {
|
|
39
|
+
return Object.entries(overrides).flatMap(([name, value]) => {
|
|
40
|
+
const min = scale[name]
|
|
41
|
+
return value !== undefined && min !== undefined ? [{ min, value }] : []
|
|
42
|
+
})
|
|
43
|
+
}
|
|
44
|
+
|
|
22
45
|
/**
|
|
23
46
|
* Widest first, since `sizes` takes the first matching condition and the last
|
|
24
47
|
* entry must be bare. `min-width` matches the Tailwind variant's boundary; a
|
|
25
48
|
* `max-width: <next> - 1` one would leave a fractional-pixel gap.
|
|
26
49
|
*/
|
|
27
|
-
function
|
|
28
|
-
|
|
29
|
-
overrides: Readonly<Record<string, string | undefined>>,
|
|
30
|
-
scale: BreakpointMap
|
|
31
|
-
): string {
|
|
32
|
-
const conditions: string[] = []
|
|
33
|
-
|
|
34
|
-
for (const [name, min] of Object.entries(scale).sort(
|
|
35
|
-
([, a], [, b]) => b - a
|
|
36
|
-
)) {
|
|
37
|
-
const value = overrides[name]
|
|
38
|
-
if (value !== undefined) {
|
|
39
|
-
conditions.push(`(min-width: ${min}px) ${value}`)
|
|
40
|
-
}
|
|
41
|
-
}
|
|
50
|
+
function joinSizes(base: string, conditions: Condition<string>[]): string {
|
|
51
|
+
const sorted = [...conditions].sort((a, b) => b.min - a.min)
|
|
42
52
|
|
|
43
|
-
return [
|
|
53
|
+
return [
|
|
54
|
+
...sorted.map(({ min, value }) => `(min-width: ${min}px) ${value}`),
|
|
55
|
+
base,
|
|
56
|
+
].join(", ")
|
|
44
57
|
}
|
|
45
58
|
|
|
46
59
|
/** Builds `sizes` from the CSS length the image renders at per breakpoint. */
|
|
47
60
|
export function buildImageSizes<
|
|
48
61
|
B extends BreakpointMap = typeof BASEMENT_BREAKPOINTS,
|
|
49
|
-
>(widths: ByBreakpoint<string, B>,
|
|
62
|
+
>(widths: ByBreakpoint<string, B>, options: ImageSizesOptions<B> = {}): string {
|
|
50
63
|
const { base, ...overrides } = widths
|
|
51
|
-
|
|
64
|
+
const scale = options.breakpoints ?? BASEMENT_BREAKPOINTS
|
|
65
|
+
|
|
66
|
+
return joinSizes(base, toConditions<string>(overrides, scale))
|
|
52
67
|
}
|
|
53
68
|
|
|
54
69
|
/**
|
|
@@ -58,15 +73,39 @@ export function buildImageSizes<
|
|
|
58
73
|
*/
|
|
59
74
|
export function buildGridImageSizes<
|
|
60
75
|
B extends BreakpointMap = typeof BASEMENT_BREAKPOINTS,
|
|
61
|
-
>(
|
|
76
|
+
>(
|
|
77
|
+
columns: ByBreakpoint<number, B>,
|
|
78
|
+
options: GridImageSizesOptions<B> = {}
|
|
79
|
+
): string {
|
|
80
|
+
const { maxWidth, breakpoints } = options
|
|
62
81
|
const { base, ...overrides } = columns
|
|
63
|
-
const
|
|
82
|
+
const steps = toConditions<number>(
|
|
83
|
+
overrides,
|
|
84
|
+
breakpoints ?? BASEMENT_BREAKPOINTS
|
|
85
|
+
)
|
|
86
|
+
const cap =
|
|
87
|
+
maxWidth !== undefined && Number.isFinite(maxWidth) && maxWidth > 0
|
|
88
|
+
? maxWidth
|
|
89
|
+
: undefined
|
|
90
|
+
|
|
91
|
+
// The cap rarely lands on a breakpoint, so it needs its own condition.
|
|
92
|
+
if (cap !== undefined && !steps.some(({ min }) => min === cap)) {
|
|
93
|
+
const below = steps
|
|
94
|
+
.filter(({ min }) => min < cap)
|
|
95
|
+
.sort((a, b) => a.min - b.min)
|
|
96
|
+
.at(-1)
|
|
64
97
|
|
|
65
|
-
|
|
66
|
-
if (count !== undefined) {
|
|
67
|
-
widths[name] = columnWidth(count)
|
|
68
|
-
}
|
|
98
|
+
steps.push({ min: cap, value: below?.value ?? base })
|
|
69
99
|
}
|
|
70
100
|
|
|
71
|
-
return
|
|
101
|
+
return joinSizes(
|
|
102
|
+
columnWidth(base),
|
|
103
|
+
steps.map(({ min, value }) => ({
|
|
104
|
+
min,
|
|
105
|
+
value:
|
|
106
|
+
cap !== undefined && min >= cap
|
|
107
|
+
? `${Math.round(cap / value)}px`
|
|
108
|
+
: columnWidth(value),
|
|
109
|
+
}))
|
|
110
|
+
)
|
|
72
111
|
}
|
|
@@ -45,6 +45,7 @@ export const metadata = generatePageMetadata({ title: 'About' })
|
|
|
45
45
|
// next/image sizes — keys mirror the element's Tailwind variants
|
|
46
46
|
buildImageSizes({ base: '100vw', desktop: '796px' })
|
|
47
47
|
buildGridImageSizes({ base: 1, tablet: 2, desktop: 3 })
|
|
48
|
+
buildGridImageSizes({ base: 1, tablet: 2, desktop: 3 }, { maxWidth: 1440 })
|
|
48
49
|
|
|
49
50
|
// Refs — in a component, use the hook: an inline mergeRefs([...]) is a new
|
|
50
51
|
// callback each render, so React detaches and reattaches every ref.
|
|
@@ -15,40 +15,55 @@ export type ByBreakpoint<
|
|
|
15
15
|
B extends BreakpointMap = typeof BASEMENT_BREAKPOINTS,
|
|
16
16
|
> = { base: T } & Partial<Record<Extract<keyof B, string>, T>>
|
|
17
17
|
|
|
18
|
+
export type ImageSizesOptions<
|
|
19
|
+
B extends BreakpointMap = typeof BASEMENT_BREAKPOINTS,
|
|
20
|
+
> = { breakpoints?: B }
|
|
21
|
+
|
|
22
|
+
export type GridImageSizesOptions<
|
|
23
|
+
B extends BreakpointMap = typeof BASEMENT_BREAKPOINTS,
|
|
24
|
+
> = ImageSizesOptions<B> & {
|
|
25
|
+
/** The grid container's `max-width` in px, past which columns stop growing. */
|
|
26
|
+
maxWidth?: number
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
type Condition<T> = { min: number; value: T }
|
|
30
|
+
|
|
18
31
|
function columnWidth(columns: number): string {
|
|
19
32
|
return `${Math.round(100 / columns)}vw`
|
|
20
33
|
}
|
|
21
34
|
|
|
35
|
+
function toConditions<T>(
|
|
36
|
+
overrides: Readonly<Record<string, T | undefined>>,
|
|
37
|
+
scale: BreakpointMap
|
|
38
|
+
): Condition<T>[] {
|
|
39
|
+
return Object.entries(overrides).flatMap(([name, value]) => {
|
|
40
|
+
const min = scale[name]
|
|
41
|
+
return value !== undefined && min !== undefined ? [{ min, value }] : []
|
|
42
|
+
})
|
|
43
|
+
}
|
|
44
|
+
|
|
22
45
|
/**
|
|
23
46
|
* Widest first, since `sizes` takes the first matching condition and the last
|
|
24
47
|
* entry must be bare. `min-width` matches the Tailwind variant's boundary; a
|
|
25
48
|
* `max-width: <next> - 1` one would leave a fractional-pixel gap.
|
|
26
49
|
*/
|
|
27
|
-
function
|
|
28
|
-
|
|
29
|
-
overrides: Readonly<Record<string, string | undefined>>,
|
|
30
|
-
scale: BreakpointMap
|
|
31
|
-
): string {
|
|
32
|
-
const conditions: string[] = []
|
|
33
|
-
|
|
34
|
-
for (const [name, min] of Object.entries(scale).sort(
|
|
35
|
-
([, a], [, b]) => b - a
|
|
36
|
-
)) {
|
|
37
|
-
const value = overrides[name]
|
|
38
|
-
if (value !== undefined) {
|
|
39
|
-
conditions.push(`(min-width: ${min}px) ${value}`)
|
|
40
|
-
}
|
|
41
|
-
}
|
|
50
|
+
function joinSizes(base: string, conditions: Condition<string>[]): string {
|
|
51
|
+
const sorted = [...conditions].sort((a, b) => b.min - a.min)
|
|
42
52
|
|
|
43
|
-
return [
|
|
53
|
+
return [
|
|
54
|
+
...sorted.map(({ min, value }) => `(min-width: ${min}px) ${value}`),
|
|
55
|
+
base,
|
|
56
|
+
].join(", ")
|
|
44
57
|
}
|
|
45
58
|
|
|
46
59
|
/** Builds `sizes` from the CSS length the image renders at per breakpoint. */
|
|
47
60
|
export function buildImageSizes<
|
|
48
61
|
B extends BreakpointMap = typeof BASEMENT_BREAKPOINTS,
|
|
49
|
-
>(widths: ByBreakpoint<string, B>,
|
|
62
|
+
>(widths: ByBreakpoint<string, B>, options: ImageSizesOptions<B> = {}): string {
|
|
50
63
|
const { base, ...overrides } = widths
|
|
51
|
-
|
|
64
|
+
const scale = options.breakpoints ?? BASEMENT_BREAKPOINTS
|
|
65
|
+
|
|
66
|
+
return joinSizes(base, toConditions<string>(overrides, scale))
|
|
52
67
|
}
|
|
53
68
|
|
|
54
69
|
/**
|
|
@@ -58,15 +73,39 @@ export function buildImageSizes<
|
|
|
58
73
|
*/
|
|
59
74
|
export function buildGridImageSizes<
|
|
60
75
|
B extends BreakpointMap = typeof BASEMENT_BREAKPOINTS,
|
|
61
|
-
>(
|
|
76
|
+
>(
|
|
77
|
+
columns: ByBreakpoint<number, B>,
|
|
78
|
+
options: GridImageSizesOptions<B> = {}
|
|
79
|
+
): string {
|
|
80
|
+
const { maxWidth, breakpoints } = options
|
|
62
81
|
const { base, ...overrides } = columns
|
|
63
|
-
const
|
|
82
|
+
const steps = toConditions<number>(
|
|
83
|
+
overrides,
|
|
84
|
+
breakpoints ?? BASEMENT_BREAKPOINTS
|
|
85
|
+
)
|
|
86
|
+
const cap =
|
|
87
|
+
maxWidth !== undefined && Number.isFinite(maxWidth) && maxWidth > 0
|
|
88
|
+
? maxWidth
|
|
89
|
+
: undefined
|
|
90
|
+
|
|
91
|
+
// The cap rarely lands on a breakpoint, so it needs its own condition.
|
|
92
|
+
if (cap !== undefined && !steps.some(({ min }) => min === cap)) {
|
|
93
|
+
const below = steps
|
|
94
|
+
.filter(({ min }) => min < cap)
|
|
95
|
+
.sort((a, b) => a.min - b.min)
|
|
96
|
+
.at(-1)
|
|
64
97
|
|
|
65
|
-
|
|
66
|
-
if (count !== undefined) {
|
|
67
|
-
widths[name] = columnWidth(count)
|
|
68
|
-
}
|
|
98
|
+
steps.push({ min: cap, value: below?.value ?? base })
|
|
69
99
|
}
|
|
70
100
|
|
|
71
|
-
return
|
|
101
|
+
return joinSizes(
|
|
102
|
+
columnWidth(base),
|
|
103
|
+
steps.map(({ min, value }) => ({
|
|
104
|
+
min,
|
|
105
|
+
value:
|
|
106
|
+
cap !== undefined && min >= cap
|
|
107
|
+
? `${Math.round(cap / value)}px`
|
|
108
|
+
: columnWidth(value),
|
|
109
|
+
}))
|
|
110
|
+
)
|
|
72
111
|
}
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { useEffect, useState } from "react";
|
|
2
|
-
import { useClient } from "sanity";
|
|
3
|
-
import { apiVersion } from "@/lib/integrations/sanity/env";
|
|
4
|
-
|
|
5
|
-
const PREVIEW_ASSETS_QUERY = `*[
|
|
6
|
-
_type == "studioPreview" &&
|
|
7
|
-
key in $keys &&
|
|
8
|
-
defined(preview.asset._ref)
|
|
9
|
-
] | order(_updatedAt desc) {
|
|
10
|
-
key,
|
|
11
|
-
"url": preview.asset->url
|
|
12
|
-
}`;
|
|
13
|
-
|
|
14
|
-
type PreviewDocument = {
|
|
15
|
-
key: string | null;
|
|
16
|
-
url: string | null;
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
export type StudioPreviewUrls = Record<string, string>;
|
|
20
|
-
|
|
21
|
-
const SEPARATOR = " ";
|
|
22
|
-
|
|
23
|
-
/** `undefined` while in flight, so callers can tell loading from "no preview". */
|
|
24
|
-
export function useStudioPreviewUrls(keys: readonly string[]) {
|
|
25
|
-
const client = useClient({ apiVersion });
|
|
26
|
-
const [urls, setUrls] = useState<StudioPreviewUrls>();
|
|
27
|
-
// Keys off contents, not array identity — callers pass a freshly mapped array.
|
|
28
|
-
const keyList = keys.join(SEPARATOR);
|
|
29
|
-
|
|
30
|
-
useEffect(() => {
|
|
31
|
-
if (!keyList) {
|
|
32
|
-
setUrls({});
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
let cancelled = false;
|
|
37
|
-
|
|
38
|
-
client
|
|
39
|
-
.fetch<PreviewDocument[]>(PREVIEW_ASSETS_QUERY, {
|
|
40
|
-
keys: keyList.split(SEPARATOR),
|
|
41
|
-
})
|
|
42
|
-
.then((documents) => {
|
|
43
|
-
if (cancelled) return;
|
|
44
|
-
const next: StudioPreviewUrls = {};
|
|
45
|
-
for (const document of documents) {
|
|
46
|
-
if (document.key && document.url && !next[document.key]) {
|
|
47
|
-
next[document.key] = document.url;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
setUrls(next);
|
|
51
|
-
})
|
|
52
|
-
.catch(() => {
|
|
53
|
-
if (!cancelled) setUrls({});
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
return () => {
|
|
57
|
-
cancelled = true;
|
|
58
|
-
};
|
|
59
|
-
}, [client, keyList]);
|
|
60
|
-
|
|
61
|
-
return urls;
|
|
62
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { defineField, defineType } from "sanity";
|
|
2
|
-
import { pageBuilderCardIcon } from "@/lib/integrations/sanity/icons";
|
|
3
|
-
import { pageBuilderBlockPreviewOptions } from "@/lib/integrations/sanity/page-builder-config";
|
|
4
|
-
|
|
5
|
-
export const studioPreview = defineType({
|
|
6
|
-
name: "studioPreview",
|
|
7
|
-
title: "Component Preview",
|
|
8
|
-
type: "document",
|
|
9
|
-
icon: pageBuilderCardIcon,
|
|
10
|
-
fields: [
|
|
11
|
-
defineField({
|
|
12
|
-
name: "key",
|
|
13
|
-
title: "Component",
|
|
14
|
-
type: "string",
|
|
15
|
-
options: { list: pageBuilderBlockPreviewOptions },
|
|
16
|
-
validation: (Rule) => Rule.required(),
|
|
17
|
-
}),
|
|
18
|
-
defineField({
|
|
19
|
-
name: "preview",
|
|
20
|
-
title: "Preview image",
|
|
21
|
-
type: "image",
|
|
22
|
-
options: { hotspot: true },
|
|
23
|
-
validation: (Rule) => Rule.required(),
|
|
24
|
-
}),
|
|
25
|
-
],
|
|
26
|
-
preview: {
|
|
27
|
-
select: { key: "key", media: "preview" },
|
|
28
|
-
prepare({ key, media }) {
|
|
29
|
-
return {
|
|
30
|
-
title:
|
|
31
|
-
pageBuilderBlockPreviewOptions.find((option) => option.value === key)
|
|
32
|
-
?.title ?? "Component Preview",
|
|
33
|
-
media,
|
|
34
|
-
};
|
|
35
|
-
},
|
|
36
|
-
},
|
|
37
|
-
});
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { useEffect, useState } from "react";
|
|
2
|
-
import { useClient } from "sanity";
|
|
3
|
-
import { apiVersion } from "@/lib/integrations/sanity/env";
|
|
4
|
-
|
|
5
|
-
const PREVIEW_ASSETS_QUERY = `*[
|
|
6
|
-
_type == "studioPreview" &&
|
|
7
|
-
key in $keys &&
|
|
8
|
-
defined(preview.asset._ref)
|
|
9
|
-
] | order(_updatedAt desc) {
|
|
10
|
-
key,
|
|
11
|
-
"url": preview.asset->url
|
|
12
|
-
}`;
|
|
13
|
-
|
|
14
|
-
type PreviewDocument = {
|
|
15
|
-
key: string | null;
|
|
16
|
-
url: string | null;
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
export type StudioPreviewUrls = Record<string, string>;
|
|
20
|
-
|
|
21
|
-
const SEPARATOR = " ";
|
|
22
|
-
|
|
23
|
-
/** `undefined` while in flight, so callers can tell loading from "no preview". */
|
|
24
|
-
export function useStudioPreviewUrls(keys: readonly string[]) {
|
|
25
|
-
const client = useClient({ apiVersion });
|
|
26
|
-
const [urls, setUrls] = useState<StudioPreviewUrls>();
|
|
27
|
-
// Keys off contents, not array identity — callers pass a freshly mapped array.
|
|
28
|
-
const keyList = keys.join(SEPARATOR);
|
|
29
|
-
|
|
30
|
-
useEffect(() => {
|
|
31
|
-
if (!keyList) {
|
|
32
|
-
setUrls({});
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
let cancelled = false;
|
|
37
|
-
|
|
38
|
-
client
|
|
39
|
-
.fetch<PreviewDocument[]>(PREVIEW_ASSETS_QUERY, {
|
|
40
|
-
keys: keyList.split(SEPARATOR),
|
|
41
|
-
})
|
|
42
|
-
.then((documents) => {
|
|
43
|
-
if (cancelled) return;
|
|
44
|
-
const next: StudioPreviewUrls = {};
|
|
45
|
-
for (const document of documents) {
|
|
46
|
-
if (document.key && document.url && !next[document.key]) {
|
|
47
|
-
next[document.key] = document.url;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
setUrls(next);
|
|
51
|
-
})
|
|
52
|
-
.catch(() => {
|
|
53
|
-
if (!cancelled) setUrls({});
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
return () => {
|
|
57
|
-
cancelled = true;
|
|
58
|
-
};
|
|
59
|
-
}, [client, keyList]);
|
|
60
|
-
|
|
61
|
-
return urls;
|
|
62
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { defineField, defineType } from "sanity";
|
|
2
|
-
import { pageBuilderCardIcon } from "@/lib/integrations/sanity/icons";
|
|
3
|
-
import { pageBuilderBlockPreviewOptions } from "@/lib/integrations/sanity/page-builder-config";
|
|
4
|
-
|
|
5
|
-
export const studioPreview = defineType({
|
|
6
|
-
name: "studioPreview",
|
|
7
|
-
title: "Component Preview",
|
|
8
|
-
type: "document",
|
|
9
|
-
icon: pageBuilderCardIcon,
|
|
10
|
-
fields: [
|
|
11
|
-
defineField({
|
|
12
|
-
name: "key",
|
|
13
|
-
title: "Component",
|
|
14
|
-
type: "string",
|
|
15
|
-
options: { list: pageBuilderBlockPreviewOptions },
|
|
16
|
-
validation: (Rule) => Rule.required(),
|
|
17
|
-
}),
|
|
18
|
-
defineField({
|
|
19
|
-
name: "preview",
|
|
20
|
-
title: "Preview image",
|
|
21
|
-
type: "image",
|
|
22
|
-
options: { hotspot: true },
|
|
23
|
-
validation: (Rule) => Rule.required(),
|
|
24
|
-
}),
|
|
25
|
-
],
|
|
26
|
-
preview: {
|
|
27
|
-
select: { key: "key", media: "preview" },
|
|
28
|
-
prepare({ key, media }) {
|
|
29
|
-
return {
|
|
30
|
-
title:
|
|
31
|
-
pageBuilderBlockPreviewOptions.find((option) => option.value === key)
|
|
32
|
-
?.title ?? "Component Preview",
|
|
33
|
-
media,
|
|
34
|
-
};
|
|
35
|
-
},
|
|
36
|
-
},
|
|
37
|
-
});
|