@sonordev/site-kit 1.2.7 → 1.2.9
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/README.md +5 -3
- package/dist/analytics/index.js +6 -6
- package/dist/analytics/index.mjs +2 -2
- package/dist/{api-CWtoFJCO.d.mts → api-DTKSHh_w.d.mts} +1 -1
- package/dist/{api-CWtoFJCO.d.ts → api-DTKSHh_w.d.ts} +1 -1
- package/dist/blog/index.js +10 -10
- package/dist/blog/index.js.map +1 -1
- package/dist/blog/index.mjs +10 -10
- package/dist/blog/index.mjs.map +1 -1
- package/dist/blog/server.js +2 -2
- package/dist/blog/server.js.map +1 -1
- package/dist/blog/server.mjs +2 -2
- package/dist/blog/server.mjs.map +1 -1
- package/dist/{chunk-7RYCHO6D.mjs → chunk-2RHO4KSK.mjs} +9 -9
- package/dist/{chunk-7RYCHO6D.mjs.map → chunk-2RHO4KSK.mjs.map} +1 -1
- package/dist/{chunk-EEZCR6E6.js → chunk-2XOW276O.js} +5 -5
- package/dist/{chunk-EEZCR6E6.js.map → chunk-2XOW276O.js.map} +1 -1
- package/dist/{chunk-JTLOJLWQ.mjs → chunk-36Y7OWES.mjs} +4 -4
- package/dist/chunk-36Y7OWES.mjs.map +1 -0
- package/dist/{chunk-DQYMKR27.mjs → chunk-47Y3YSES.mjs} +10 -10
- package/dist/chunk-47Y3YSES.mjs.map +1 -0
- package/dist/{chunk-MV3QN7PW.mjs → chunk-5F7FFUPJ.mjs} +3 -3
- package/dist/{chunk-MV3QN7PW.mjs.map → chunk-5F7FFUPJ.mjs.map} +1 -1
- package/dist/{chunk-AFAO3TGS.mjs → chunk-5YDPPOUU.mjs} +10 -10
- package/dist/chunk-5YDPPOUU.mjs.map +1 -0
- package/dist/{chunk-D63MUKZ6.mjs → chunk-6YXRLC6W.mjs} +5 -5
- package/dist/chunk-6YXRLC6W.mjs.map +1 -0
- package/dist/{chunk-7RF6PVHA.mjs → chunk-7FKPJQVS.mjs} +33 -68
- package/dist/chunk-7FKPJQVS.mjs.map +1 -0
- package/dist/{chunk-BYLIU6XG.js → chunk-7ROZJDXE.js} +10 -10
- package/dist/chunk-7ROZJDXE.js.map +1 -0
- package/dist/{chunk-UWE5PCYJ.mjs → chunk-APZMXRI3.mjs} +3 -3
- package/dist/chunk-APZMXRI3.mjs.map +1 -0
- package/dist/{chunk-622GAQP5.js → chunk-BBITDUZQ.js} +6 -6
- package/dist/chunk-BBITDUZQ.js.map +1 -0
- package/dist/{chunk-DDKW2FNA.js → chunk-BFJDUTXK.js} +8 -8
- package/dist/chunk-BFJDUTXK.js.map +1 -0
- package/dist/chunk-C3A5HXHX.mjs +78 -0
- package/dist/chunk-C3A5HXHX.mjs.map +1 -0
- package/dist/{chunk-XZJOZJB6.js → chunk-CFEOOJUT.js} +12 -12
- package/dist/{chunk-XZJOZJB6.js.map → chunk-CFEOOJUT.js.map} +1 -1
- package/dist/{chunk-M2T6R7BA.mjs → chunk-DOSSLBNW.mjs} +4 -4
- package/dist/chunk-DOSSLBNW.mjs.map +1 -0
- package/dist/{chunk-OB7E654K.js → chunk-DY4K6X3A.js} +6 -6
- package/dist/chunk-DY4K6X3A.js.map +1 -0
- package/dist/{chunk-7UKPRW25.mjs → chunk-EISQ7LJG.mjs} +6 -6
- package/dist/chunk-EISQ7LJG.mjs.map +1 -0
- package/dist/{chunk-7557OTHW.js → chunk-EUNL6GAL.js} +5 -5
- package/dist/chunk-EUNL6GAL.js.map +1 -0
- package/dist/{chunk-KUGMH4ZF.js → chunk-G6VGUAK2.js} +4 -4
- package/dist/chunk-G6VGUAK2.js.map +1 -0
- package/dist/{chunk-XQQWI6WB.js → chunk-GVXZWXQ7.js} +10 -10
- package/dist/chunk-GVXZWXQ7.js.map +1 -0
- package/dist/{chunk-24277A3Q.mjs → chunk-HF2FWDBJ.mjs} +9 -9
- package/dist/chunk-HF2FWDBJ.mjs.map +1 -0
- package/dist/{chunk-72MQFHYJ.js → chunk-IFAW7JFO.js} +16 -16
- package/dist/chunk-IFAW7JFO.js.map +1 -0
- package/dist/{chunk-P3UWIUJS.mjs → chunk-IKIJEKU3.mjs} +16 -16
- package/dist/chunk-IKIJEKU3.mjs.map +1 -0
- package/dist/{chunk-PKN27UMH.mjs → chunk-JIDOXTX2.mjs} +3 -3
- package/dist/{chunk-PKN27UMH.mjs.map → chunk-JIDOXTX2.mjs.map} +1 -1
- package/dist/{chunk-7FUV73JZ.js → chunk-JM3ZR6LB.js} +9 -9
- package/dist/chunk-JM3ZR6LB.js.map +1 -0
- package/dist/{chunk-OIIKTGRL.mjs → chunk-JMNSED4O.mjs} +8 -8
- package/dist/chunk-JMNSED4O.mjs.map +1 -0
- package/dist/chunk-MG23BS36.js +82 -0
- package/dist/chunk-MG23BS36.js.map +1 -0
- package/dist/{chunk-TFLQX7K7.mjs → chunk-N24BPFF6.mjs} +6 -6
- package/dist/chunk-N24BPFF6.mjs.map +1 -0
- package/dist/{chunk-LIVWLY2P.js → chunk-PPRAW576.js} +3 -3
- package/dist/{chunk-LIVWLY2P.js.map → chunk-PPRAW576.js.map} +1 -1
- package/dist/chunk-QETK4P5G.mjs +142 -0
- package/dist/chunk-QETK4P5G.mjs.map +1 -0
- package/dist/{chunk-W4PALSGM.js → chunk-REMHGWXT.js} +3 -3
- package/dist/chunk-REMHGWXT.js.map +1 -0
- package/dist/{chunk-DW5UJKHH.js → chunk-RMOL4TZ6.js} +8 -8
- package/dist/chunk-RMOL4TZ6.js.map +1 -0
- package/dist/{chunk-KKU3K7RG.js → chunk-SLB5V4RT.js} +33 -67
- package/dist/chunk-SLB5V4RT.js.map +1 -0
- package/dist/{chunk-K23A4G76.mjs → chunk-SQSBAPWA.mjs} +8 -8
- package/dist/chunk-SQSBAPWA.mjs.map +1 -0
- package/dist/{chunk-WECQ6KOB.js → chunk-TG46LJFB.js} +4 -4
- package/dist/chunk-TG46LJFB.js.map +1 -0
- package/dist/{chunk-43GBM4SX.js → chunk-TKQLH33E.js} +3 -3
- package/dist/chunk-TKQLH33E.js.map +1 -0
- package/dist/{chunk-UYFDNX2F.js → chunk-TLHRV3LZ.js} +5 -5
- package/dist/chunk-TLHRV3LZ.js.map +1 -0
- package/dist/{chunk-6ZCISNAB.mjs → chunk-UPR5FEIO.mjs} +3 -3
- package/dist/chunk-UPR5FEIO.mjs.map +1 -0
- package/dist/chunk-VTECURKB.js +144 -0
- package/dist/chunk-VTECURKB.js.map +1 -0
- package/dist/{chunk-GCJXQ4AG.mjs → chunk-VZMDH3R4.mjs} +5 -5
- package/dist/chunk-VZMDH3R4.mjs.map +1 -0
- package/dist/{chunk-LBVWVP72.js → chunk-X4J33XQD.js} +7 -7
- package/dist/chunk-X4J33XQD.js.map +1 -0
- package/dist/{chunk-QXV4667R.mjs → chunk-XFOL6JDF.mjs} +5 -5
- package/dist/chunk-XFOL6JDF.mjs.map +1 -0
- package/dist/cli/index.js +80 -91
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/index.mjs +76 -87
- package/dist/cli/index.mjs.map +1 -1
- package/dist/cms/index.d.mts +139 -0
- package/dist/cms/index.d.ts +139 -0
- package/dist/cms/index.js +409 -0
- package/dist/cms/index.js.map +1 -0
- package/dist/cms/index.mjs +388 -0
- package/dist/cms/index.mjs.map +1 -0
- package/dist/cms/server.d.mts +47 -0
- package/dist/cms/server.d.ts +47 -0
- package/dist/cms/server.js +21 -0
- package/dist/{server-api-GJPNRYUP.js.map → cms/server.js.map} +1 -1
- package/dist/cms/server.mjs +4 -0
- package/dist/{server-api-EWXKOQZA.mjs.map → cms/server.mjs.map} +1 -1
- package/dist/commerce/index.js +42 -42
- package/dist/commerce/index.mjs +1 -1
- package/dist/commerce/server.d.mts +1 -1
- package/dist/commerce/server.d.ts +1 -1
- package/dist/commerce/server.js.map +1 -1
- package/dist/commerce/server.mjs.map +1 -1
- package/dist/config/index.js +1 -1
- package/dist/config/index.js.map +1 -1
- package/dist/config/index.mjs +1 -1
- package/dist/config/index.mjs.map +1 -1
- package/dist/engage/index.js +4 -4
- package/dist/engage/index.mjs +1 -1
- package/dist/forms/index.js +5 -5
- package/dist/forms/index.js.map +1 -1
- package/dist/forms/index.mjs +5 -5
- package/dist/forms/index.mjs.map +1 -1
- package/dist/generators-DOFWGRXS.js +37 -0
- package/dist/{generators-DTMO36DV.js.map → generators-DOFWGRXS.js.map} +1 -1
- package/dist/generators-R62APO62.mjs +4 -0
- package/dist/{generators-2XKQMPKH.mjs.map → generators-R62APO62.mjs.map} +1 -1
- package/dist/images/index.d.mts +1 -1
- package/dist/images/index.d.ts +1 -1
- package/dist/images/index.js +11 -11
- package/dist/images/index.mjs +2 -2
- package/dist/images/server.d.mts +3 -3
- package/dist/images/server.d.ts +3 -3
- package/dist/images/server.js +4 -4
- package/dist/images/server.mjs +1 -1
- package/dist/index.d.mts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.js +81 -81
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +28 -28
- package/dist/index.mjs.map +1 -1
- package/dist/layout/client.d.mts +18 -0
- package/dist/layout/client.d.ts +18 -0
- package/dist/layout/client.js +18 -0
- package/dist/layout/client.js.map +1 -0
- package/dist/layout/client.mjs +9 -0
- package/dist/layout/client.mjs.map +1 -0
- package/dist/layout/index.d.mts +4 -27
- package/dist/layout/index.d.ts +4 -27
- package/dist/layout/index.js +15 -145
- package/dist/layout/index.js.map +1 -1
- package/dist/layout/index.mjs +11 -141
- package/dist/layout/index.mjs.map +1 -1
- package/dist/llms/index.js +12 -12
- package/dist/llms/index.mjs +2 -2
- package/dist/manifest/index.js +4 -4
- package/dist/manifest/index.js.map +1 -1
- package/dist/manifest/index.mjs +3 -3
- package/dist/manifest/index.mjs.map +1 -1
- package/dist/middleware/index.js +3 -3
- package/dist/middleware/index.mjs +2 -2
- package/dist/{migrator-2MQHOFDQ.mjs → migrator-3WQB3KQ2.mjs} +3 -3
- package/dist/{migrator-2MQHOFDQ.mjs.map → migrator-3WQB3KQ2.mjs.map} +1 -1
- package/dist/migrator-HFVQYK5R.js +37 -0
- package/dist/{migrator-THJCF6MZ.js.map → migrator-HFVQYK5R.js.map} +1 -1
- package/dist/redirects/index.d.mts +2 -2
- package/dist/redirects/index.d.ts +2 -2
- package/dist/redirects/index.js +6 -6
- package/dist/redirects/index.mjs +2 -2
- package/dist/reputation/index.js +4 -4
- package/dist/reputation/index.mjs +1 -1
- package/dist/robots/index.d.mts +1 -1
- package/dist/robots/index.d.ts +1 -1
- package/dist/robots/index.js +3 -3
- package/dist/robots/index.js.map +1 -1
- package/dist/robots/index.mjs +2 -2
- package/dist/robots/index.mjs.map +1 -1
- package/dist/seo/index.d.mts +1 -1
- package/dist/seo/index.d.ts +1 -1
- package/dist/seo/index.js +43 -43
- package/dist/seo/index.js.map +1 -1
- package/dist/seo/index.mjs +6 -6
- package/dist/seo/index.mjs.map +1 -1
- package/dist/seo/register-sitemap-cli.js +18 -18
- package/dist/seo/register-sitemap-cli.js.map +1 -1
- package/dist/seo/register-sitemap-cli.mjs +18 -18
- package/dist/seo/register-sitemap-cli.mjs.map +1 -1
- package/dist/seo/server.d.mts +1 -1
- package/dist/seo/server.d.ts +1 -1
- package/dist/seo/server.js +10 -10
- package/dist/seo/server.js.map +1 -1
- package/dist/seo/server.mjs +8 -8
- package/dist/seo/server.mjs.map +1 -1
- package/dist/{server-api-GJPNRYUP.js → server-api-C5JXIROA.js} +21 -21
- package/dist/server-api-C5JXIROA.js.map +1 -0
- package/dist/{server-api-EWXKOQZA.mjs → server-api-HTSLBT6F.mjs} +3 -3
- package/dist/server-api-HTSLBT6F.mjs.map +1 -0
- package/dist/setup/client.js +7 -7
- package/dist/setup/client.mjs +2 -2
- package/dist/setup/index.js +9 -9
- package/dist/setup/index.mjs +3 -3
- package/dist/setup/server.js +2 -2
- package/dist/setup/server.mjs +1 -1
- package/dist/site-config/index.d.mts +1 -1
- package/dist/site-config/index.d.ts +1 -1
- package/dist/site-config/index.js +3 -3
- package/dist/site-config/index.mjs +1 -1
- package/dist/sitemap/index.d.mts +2 -2
- package/dist/sitemap/index.d.ts +2 -2
- package/dist/sitemap/index.js +10 -10
- package/dist/sitemap/index.js.map +1 -1
- package/dist/sitemap/index.mjs +8 -8
- package/dist/sitemap/index.mjs.map +1 -1
- package/dist/types-5RCOK10v.d.mts +25 -0
- package/dist/types-5RCOK10v.d.ts +25 -0
- package/dist/types-BG-x8yhh.d.mts +106 -0
- package/dist/types-BG-x8yhh.d.ts +106 -0
- package/package.json +13 -1
- package/dist/chunk-24277A3Q.mjs.map +0 -1
- package/dist/chunk-43GBM4SX.js.map +0 -1
- package/dist/chunk-622GAQP5.js.map +0 -1
- package/dist/chunk-6ZCISNAB.mjs.map +0 -1
- package/dist/chunk-72MQFHYJ.js.map +0 -1
- package/dist/chunk-7557OTHW.js.map +0 -1
- package/dist/chunk-7FUV73JZ.js.map +0 -1
- package/dist/chunk-7RF6PVHA.mjs.map +0 -1
- package/dist/chunk-7UKPRW25.mjs.map +0 -1
- package/dist/chunk-AFAO3TGS.mjs.map +0 -1
- package/dist/chunk-BYLIU6XG.js.map +0 -1
- package/dist/chunk-D63MUKZ6.mjs.map +0 -1
- package/dist/chunk-DDKW2FNA.js.map +0 -1
- package/dist/chunk-DQYMKR27.mjs.map +0 -1
- package/dist/chunk-DW5UJKHH.js.map +0 -1
- package/dist/chunk-GCJXQ4AG.mjs.map +0 -1
- package/dist/chunk-JTLOJLWQ.mjs.map +0 -1
- package/dist/chunk-K23A4G76.mjs.map +0 -1
- package/dist/chunk-KKU3K7RG.js.map +0 -1
- package/dist/chunk-KUGMH4ZF.js.map +0 -1
- package/dist/chunk-LBVWVP72.js.map +0 -1
- package/dist/chunk-M2T6R7BA.mjs.map +0 -1
- package/dist/chunk-OB7E654K.js.map +0 -1
- package/dist/chunk-OIIKTGRL.mjs.map +0 -1
- package/dist/chunk-P3UWIUJS.mjs.map +0 -1
- package/dist/chunk-QXV4667R.mjs.map +0 -1
- package/dist/chunk-TFLQX7K7.mjs.map +0 -1
- package/dist/chunk-UWE5PCYJ.mjs.map +0 -1
- package/dist/chunk-UYFDNX2F.js.map +0 -1
- package/dist/chunk-W4PALSGM.js.map +0 -1
- package/dist/chunk-WECQ6KOB.js.map +0 -1
- package/dist/chunk-XQQWI6WB.js.map +0 -1
- package/dist/generators-2XKQMPKH.mjs +0 -4
- package/dist/generators-DTMO36DV.js +0 -33
- package/dist/migrator-THJCF6MZ.js +0 -37
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import React__default from 'react';
|
|
2
|
+
import { b as CmsPageProps, c as CmsSectionProps, S as SectionType, d as SectionRendererProps, P as PortableTextRendererProps, e as SanityImageRef } from '../types-BG-x8yhh.mjs';
|
|
3
|
+
export { C as CmsPageData, f as CmsPageSeo, a as CmsSectionData, h as PortableTextBlock, g as PortableTextContent } from '../types-BG-x8yhh.mjs';
|
|
4
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Async React Server Component that fetches and renders a full CMS page.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```tsx
|
|
11
|
+
* // app/[...slug]/page.tsx
|
|
12
|
+
* import { CmsPage } from '@sonordev/site-kit/cms'
|
|
13
|
+
*
|
|
14
|
+
* export default function Page({ params }) {
|
|
15
|
+
* return <CmsPage path={`/${params.slug.join('/')}`} />
|
|
16
|
+
* }
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
declare function CmsPage({ path, sectionComponents, portableTextComponents, fallback, className, }: CmsPageProps): Promise<React__default.ReactElement | null>;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Renders a single CMS section using the appropriate renderer for its type.
|
|
23
|
+
* Override specific section renderers via the `sectionComponents` prop.
|
|
24
|
+
*/
|
|
25
|
+
declare function CmsSection({ section, sectionComponents, portableTextComponents }: CmsSectionProps): react_jsx_runtime.JSX.Element | null;
|
|
26
|
+
|
|
27
|
+
interface CmsPreviewProps {
|
|
28
|
+
/** Portal API base URL */
|
|
29
|
+
apiUrl?: string;
|
|
30
|
+
/** API key for fetching draft content */
|
|
31
|
+
apiKey: string;
|
|
32
|
+
/** Page path to preview */
|
|
33
|
+
path: string;
|
|
34
|
+
/** Poll interval in ms (0 = no polling) */
|
|
35
|
+
pollInterval?: number;
|
|
36
|
+
/** Override section renderers */
|
|
37
|
+
sectionComponents?: Partial<Record<SectionType, React__default.ComponentType<SectionRendererProps>>>;
|
|
38
|
+
/** Override Portable Text components */
|
|
39
|
+
portableTextComponents?: Record<string, React__default.ComponentType<any>>;
|
|
40
|
+
/** Wrapper className */
|
|
41
|
+
className?: string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Client component for previewing draft CMS content.
|
|
45
|
+
* Fetches draft content from Portal API and re-renders on changes.
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```tsx
|
|
49
|
+
* // Used in preview mode (e.g., ?preview=true)
|
|
50
|
+
* import { CmsPreview } from '@sonordev/site-kit/cms'
|
|
51
|
+
*
|
|
52
|
+
* <CmsPreview
|
|
53
|
+
* apiKey={process.env.NEXT_PUBLIC_UPTRADE_API_KEY!}
|
|
54
|
+
* path="/about"
|
|
55
|
+
* pollInterval={3000}
|
|
56
|
+
* />
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
declare function CmsPreview({ apiUrl, apiKey, path, pollInterval, sectionComponents, portableTextComponents, className, }: CmsPreviewProps): react_jsx_runtime.JSX.Element;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Renders Portable Text content with Sonor default styling.
|
|
63
|
+
* Accepts `components` prop to override or extend defaults.
|
|
64
|
+
*/
|
|
65
|
+
declare function PortableTextRenderer({ value, components: overrides, className, }: PortableTextRendererProps): react_jsx_runtime.JSX.Element | null;
|
|
66
|
+
|
|
67
|
+
interface SanityImageConfig {
|
|
68
|
+
projectId: string;
|
|
69
|
+
dataset: string;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Initialise (or re-initialise) the image builder with project config.
|
|
73
|
+
* Call once at app startup — e.g. in SiteKitProvider or layout.
|
|
74
|
+
* If never called, falls back to DEFAULT_CONFIG.
|
|
75
|
+
*/
|
|
76
|
+
declare function configureSanityImages(config: SanityImageConfig): void;
|
|
77
|
+
interface ImageUrlOptions {
|
|
78
|
+
width?: number;
|
|
79
|
+
height?: number;
|
|
80
|
+
/** Device-pixel-ratio multiplier (default 1) */
|
|
81
|
+
dpr?: number;
|
|
82
|
+
/** Quality 0-100 (default: Sanity auto) */
|
|
83
|
+
quality?: number;
|
|
84
|
+
/** Force a specific format */
|
|
85
|
+
format?: 'webp' | 'avif' | 'png' | 'jpg';
|
|
86
|
+
/** Fit mode */
|
|
87
|
+
fit?: 'clip' | 'crop' | 'fill' | 'fillmax' | 'max' | 'scale' | 'min';
|
|
88
|
+
/** Apply blur (0-2000) */
|
|
89
|
+
blur?: number;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Build an optimised image URL from a SanityImageRef.
|
|
93
|
+
* Automatically applies hotspot/crop metadata when present.
|
|
94
|
+
*
|
|
95
|
+
* ```ts
|
|
96
|
+
* const url = sanityImageUrl(heroImage, { width: 1200 })
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
declare function sanityImageUrl(image: SanityImageRef | undefined | null, options?: ImageUrlOptions): string;
|
|
100
|
+
/**
|
|
101
|
+
* Generate a srcSet string for responsive images.
|
|
102
|
+
*
|
|
103
|
+
* ```tsx
|
|
104
|
+
* <img srcSet={sanityImageSrcSet(img, [400, 800, 1200])} sizes="100vw" />
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
declare function sanityImageSrcSet(image: SanityImageRef | undefined | null, widths?: number[], options?: Omit<ImageUrlOptions, 'width'>): string;
|
|
108
|
+
/**
|
|
109
|
+
* Compute CSS `object-position` from a Sanity hotspot.
|
|
110
|
+
* Returns `undefined` if no hotspot is defined.
|
|
111
|
+
*/
|
|
112
|
+
declare function hotspotToObjectPosition(image: SanityImageRef | undefined | null): string | undefined;
|
|
113
|
+
|
|
114
|
+
declare function HeroSection({ data, portableTextComponents }: SectionRendererProps): react_jsx_runtime.JSX.Element;
|
|
115
|
+
|
|
116
|
+
declare function RichTextSection({ data, portableTextComponents }: SectionRendererProps): react_jsx_runtime.JSX.Element | null;
|
|
117
|
+
|
|
118
|
+
declare function CtaSection({ data, portableTextComponents }: SectionRendererProps): react_jsx_runtime.JSX.Element;
|
|
119
|
+
|
|
120
|
+
declare function GallerySection({ data, portableTextComponents }: SectionRendererProps): react_jsx_runtime.JSX.Element | null;
|
|
121
|
+
|
|
122
|
+
declare function TestimonialsSection({ data, portableTextComponents }: SectionRendererProps): react_jsx_runtime.JSX.Element | null;
|
|
123
|
+
|
|
124
|
+
declare function FaqSection({ data, portableTextComponents }: SectionRendererProps): react_jsx_runtime.JSX.Element | null;
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Form section — renders a heading and a placeholder for the managed form.
|
|
128
|
+
* The actual form rendering depends on ManagedForm from the forms module.
|
|
129
|
+
* Sites should override this section renderer to integrate with their form setup.
|
|
130
|
+
*/
|
|
131
|
+
declare function FormSection({ data, portableTextComponents }: SectionRendererProps): react_jsx_runtime.JSX.Element;
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Custom section — passes props to a named component.
|
|
135
|
+
* Sites must provide their own component map via sectionComponents override.
|
|
136
|
+
*/
|
|
137
|
+
declare function CustomSection({ data, displayName }: SectionRendererProps): react_jsx_runtime.JSX.Element;
|
|
138
|
+
|
|
139
|
+
export { CmsPage, CmsPageProps, CmsPreview, CmsSection, CmsSectionProps, CtaSection, CustomSection, FaqSection, FormSection, GallerySection, HeroSection, type ImageUrlOptions, PortableTextRenderer, PortableTextRendererProps, RichTextSection, type SanityImageConfig, SanityImageRef, SectionRendererProps, SectionType, TestimonialsSection, configureSanityImages, hotspotToObjectPosition, sanityImageSrcSet, sanityImageUrl };
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import React__default from 'react';
|
|
2
|
+
import { b as CmsPageProps, c as CmsSectionProps, S as SectionType, d as SectionRendererProps, P as PortableTextRendererProps, e as SanityImageRef } from '../types-BG-x8yhh.js';
|
|
3
|
+
export { C as CmsPageData, f as CmsPageSeo, a as CmsSectionData, h as PortableTextBlock, g as PortableTextContent } from '../types-BG-x8yhh.js';
|
|
4
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Async React Server Component that fetches and renders a full CMS page.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```tsx
|
|
11
|
+
* // app/[...slug]/page.tsx
|
|
12
|
+
* import { CmsPage } from '@sonordev/site-kit/cms'
|
|
13
|
+
*
|
|
14
|
+
* export default function Page({ params }) {
|
|
15
|
+
* return <CmsPage path={`/${params.slug.join('/')}`} />
|
|
16
|
+
* }
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
declare function CmsPage({ path, sectionComponents, portableTextComponents, fallback, className, }: CmsPageProps): Promise<React__default.ReactElement | null>;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Renders a single CMS section using the appropriate renderer for its type.
|
|
23
|
+
* Override specific section renderers via the `sectionComponents` prop.
|
|
24
|
+
*/
|
|
25
|
+
declare function CmsSection({ section, sectionComponents, portableTextComponents }: CmsSectionProps): react_jsx_runtime.JSX.Element | null;
|
|
26
|
+
|
|
27
|
+
interface CmsPreviewProps {
|
|
28
|
+
/** Portal API base URL */
|
|
29
|
+
apiUrl?: string;
|
|
30
|
+
/** API key for fetching draft content */
|
|
31
|
+
apiKey: string;
|
|
32
|
+
/** Page path to preview */
|
|
33
|
+
path: string;
|
|
34
|
+
/** Poll interval in ms (0 = no polling) */
|
|
35
|
+
pollInterval?: number;
|
|
36
|
+
/** Override section renderers */
|
|
37
|
+
sectionComponents?: Partial<Record<SectionType, React__default.ComponentType<SectionRendererProps>>>;
|
|
38
|
+
/** Override Portable Text components */
|
|
39
|
+
portableTextComponents?: Record<string, React__default.ComponentType<any>>;
|
|
40
|
+
/** Wrapper className */
|
|
41
|
+
className?: string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Client component for previewing draft CMS content.
|
|
45
|
+
* Fetches draft content from Portal API and re-renders on changes.
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```tsx
|
|
49
|
+
* // Used in preview mode (e.g., ?preview=true)
|
|
50
|
+
* import { CmsPreview } from '@sonordev/site-kit/cms'
|
|
51
|
+
*
|
|
52
|
+
* <CmsPreview
|
|
53
|
+
* apiKey={process.env.NEXT_PUBLIC_UPTRADE_API_KEY!}
|
|
54
|
+
* path="/about"
|
|
55
|
+
* pollInterval={3000}
|
|
56
|
+
* />
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
declare function CmsPreview({ apiUrl, apiKey, path, pollInterval, sectionComponents, portableTextComponents, className, }: CmsPreviewProps): react_jsx_runtime.JSX.Element;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Renders Portable Text content with Sonor default styling.
|
|
63
|
+
* Accepts `components` prop to override or extend defaults.
|
|
64
|
+
*/
|
|
65
|
+
declare function PortableTextRenderer({ value, components: overrides, className, }: PortableTextRendererProps): react_jsx_runtime.JSX.Element | null;
|
|
66
|
+
|
|
67
|
+
interface SanityImageConfig {
|
|
68
|
+
projectId: string;
|
|
69
|
+
dataset: string;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Initialise (or re-initialise) the image builder with project config.
|
|
73
|
+
* Call once at app startup — e.g. in SiteKitProvider or layout.
|
|
74
|
+
* If never called, falls back to DEFAULT_CONFIG.
|
|
75
|
+
*/
|
|
76
|
+
declare function configureSanityImages(config: SanityImageConfig): void;
|
|
77
|
+
interface ImageUrlOptions {
|
|
78
|
+
width?: number;
|
|
79
|
+
height?: number;
|
|
80
|
+
/** Device-pixel-ratio multiplier (default 1) */
|
|
81
|
+
dpr?: number;
|
|
82
|
+
/** Quality 0-100 (default: Sanity auto) */
|
|
83
|
+
quality?: number;
|
|
84
|
+
/** Force a specific format */
|
|
85
|
+
format?: 'webp' | 'avif' | 'png' | 'jpg';
|
|
86
|
+
/** Fit mode */
|
|
87
|
+
fit?: 'clip' | 'crop' | 'fill' | 'fillmax' | 'max' | 'scale' | 'min';
|
|
88
|
+
/** Apply blur (0-2000) */
|
|
89
|
+
blur?: number;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Build an optimised image URL from a SanityImageRef.
|
|
93
|
+
* Automatically applies hotspot/crop metadata when present.
|
|
94
|
+
*
|
|
95
|
+
* ```ts
|
|
96
|
+
* const url = sanityImageUrl(heroImage, { width: 1200 })
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
declare function sanityImageUrl(image: SanityImageRef | undefined | null, options?: ImageUrlOptions): string;
|
|
100
|
+
/**
|
|
101
|
+
* Generate a srcSet string for responsive images.
|
|
102
|
+
*
|
|
103
|
+
* ```tsx
|
|
104
|
+
* <img srcSet={sanityImageSrcSet(img, [400, 800, 1200])} sizes="100vw" />
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
declare function sanityImageSrcSet(image: SanityImageRef | undefined | null, widths?: number[], options?: Omit<ImageUrlOptions, 'width'>): string;
|
|
108
|
+
/**
|
|
109
|
+
* Compute CSS `object-position` from a Sanity hotspot.
|
|
110
|
+
* Returns `undefined` if no hotspot is defined.
|
|
111
|
+
*/
|
|
112
|
+
declare function hotspotToObjectPosition(image: SanityImageRef | undefined | null): string | undefined;
|
|
113
|
+
|
|
114
|
+
declare function HeroSection({ data, portableTextComponents }: SectionRendererProps): react_jsx_runtime.JSX.Element;
|
|
115
|
+
|
|
116
|
+
declare function RichTextSection({ data, portableTextComponents }: SectionRendererProps): react_jsx_runtime.JSX.Element | null;
|
|
117
|
+
|
|
118
|
+
declare function CtaSection({ data, portableTextComponents }: SectionRendererProps): react_jsx_runtime.JSX.Element;
|
|
119
|
+
|
|
120
|
+
declare function GallerySection({ data, portableTextComponents }: SectionRendererProps): react_jsx_runtime.JSX.Element | null;
|
|
121
|
+
|
|
122
|
+
declare function TestimonialsSection({ data, portableTextComponents }: SectionRendererProps): react_jsx_runtime.JSX.Element | null;
|
|
123
|
+
|
|
124
|
+
declare function FaqSection({ data, portableTextComponents }: SectionRendererProps): react_jsx_runtime.JSX.Element | null;
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Form section — renders a heading and a placeholder for the managed form.
|
|
128
|
+
* The actual form rendering depends on ManagedForm from the forms module.
|
|
129
|
+
* Sites should override this section renderer to integrate with their form setup.
|
|
130
|
+
*/
|
|
131
|
+
declare function FormSection({ data, portableTextComponents }: SectionRendererProps): react_jsx_runtime.JSX.Element;
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Custom section — passes props to a named component.
|
|
135
|
+
* Sites must provide their own component map via sectionComponents override.
|
|
136
|
+
*/
|
|
137
|
+
declare function CustomSection({ data, displayName }: SectionRendererProps): react_jsx_runtime.JSX.Element;
|
|
138
|
+
|
|
139
|
+
export { CmsPage, CmsPageProps, CmsPreview, CmsSection, CmsSectionProps, CtaSection, CustomSection, FaqSection, FormSection, GallerySection, HeroSection, type ImageUrlOptions, PortableTextRenderer, PortableTextRendererProps, RichTextSection, type SanityImageConfig, SanityImageRef, SectionRendererProps, SectionType, TestimonialsSection, configureSanityImages, hotspotToObjectPosition, sanityImageSrcSet, sanityImageUrl };
|
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkMG23BS36_js = require('../chunk-MG23BS36.js');
|
|
4
|
+
require('../chunk-ZSMWDLMK.js');
|
|
5
|
+
var react = require('@portabletext/react');
|
|
6
|
+
var imageUrlBuilder = require('@sanity/image-url');
|
|
7
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
8
|
+
var react$1 = require('react');
|
|
9
|
+
|
|
10
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
11
|
+
|
|
12
|
+
var imageUrlBuilder__default = /*#__PURE__*/_interopDefault(imageUrlBuilder);
|
|
13
|
+
|
|
14
|
+
var _builder = null;
|
|
15
|
+
var DEFAULT_CONFIG = {
|
|
16
|
+
projectId: "l55lyemx",
|
|
17
|
+
dataset: "production"
|
|
18
|
+
};
|
|
19
|
+
function configureSanityImages(config) {
|
|
20
|
+
_builder = imageUrlBuilder__default.default(config);
|
|
21
|
+
}
|
|
22
|
+
function getBuilder() {
|
|
23
|
+
if (!_builder) {
|
|
24
|
+
_builder = imageUrlBuilder__default.default(DEFAULT_CONFIG);
|
|
25
|
+
}
|
|
26
|
+
return _builder;
|
|
27
|
+
}
|
|
28
|
+
function sanityImageUrl(image, options = {}) {
|
|
29
|
+
if (!image?.asset?._ref) return "";
|
|
30
|
+
let builder = getBuilder().image(image).auto("format");
|
|
31
|
+
if (options.width) builder = builder.width(options.width);
|
|
32
|
+
if (options.height) builder = builder.height(options.height);
|
|
33
|
+
if (options.dpr) builder = builder.dpr(options.dpr);
|
|
34
|
+
if (options.quality) builder = builder.quality(options.quality);
|
|
35
|
+
if (options.format) builder = builder.format(options.format);
|
|
36
|
+
if (options.fit) builder = builder.fit(options.fit);
|
|
37
|
+
if (options.blur) builder = builder.blur(options.blur);
|
|
38
|
+
return builder.url();
|
|
39
|
+
}
|
|
40
|
+
function sanityImageSrcSet(image, widths = [400, 800, 1200, 1600], options = {}) {
|
|
41
|
+
if (!image?.asset?._ref) return "";
|
|
42
|
+
return widths.map((w) => `${sanityImageUrl(image, { ...options, width: w })} ${w}w`).join(", ");
|
|
43
|
+
}
|
|
44
|
+
function hotspotToObjectPosition(image) {
|
|
45
|
+
if (!image?.hotspot) return void 0;
|
|
46
|
+
return `${(image.hotspot.x * 100).toFixed(1)}% ${(image.hotspot.y * 100).toFixed(1)}%`;
|
|
47
|
+
}
|
|
48
|
+
var defaultComponents = {
|
|
49
|
+
block: {
|
|
50
|
+
h1: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "sonor-cms-h1", children }),
|
|
51
|
+
h2: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "sonor-cms-h2", children }),
|
|
52
|
+
h3: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "sonor-cms-h3", children }),
|
|
53
|
+
h4: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "sonor-cms-h4", children }),
|
|
54
|
+
normal: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("p", { className: "sonor-cms-p", children }),
|
|
55
|
+
blockquote: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("blockquote", { className: "sonor-cms-blockquote", children })
|
|
56
|
+
},
|
|
57
|
+
marks: {
|
|
58
|
+
strong: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("strong", { children }),
|
|
59
|
+
em: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("em", { children }),
|
|
60
|
+
code: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("code", { className: "sonor-cms-code", children }),
|
|
61
|
+
underline: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("u", { children }),
|
|
62
|
+
"strike-through": ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("s", { children }),
|
|
63
|
+
link: ({ children, value }) => {
|
|
64
|
+
const href = value?.href || "#";
|
|
65
|
+
const isExternal = href.startsWith("http");
|
|
66
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
67
|
+
"a",
|
|
68
|
+
{
|
|
69
|
+
href,
|
|
70
|
+
className: "sonor-cms-link",
|
|
71
|
+
...isExternal ? { target: "_blank", rel: "noopener noreferrer" } : {},
|
|
72
|
+
children
|
|
73
|
+
}
|
|
74
|
+
);
|
|
75
|
+
},
|
|
76
|
+
highlight: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("mark", { className: "sonor-cms-highlight", children })
|
|
77
|
+
},
|
|
78
|
+
list: {
|
|
79
|
+
bullet: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "sonor-cms-ul", children }),
|
|
80
|
+
number: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("ol", { className: "sonor-cms-ol", children })
|
|
81
|
+
},
|
|
82
|
+
listItem: {
|
|
83
|
+
bullet: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("li", { children }),
|
|
84
|
+
number: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("li", { children })
|
|
85
|
+
},
|
|
86
|
+
types: {
|
|
87
|
+
image: ({ value }) => {
|
|
88
|
+
if (!value?.asset?._ref && !value?.url) return null;
|
|
89
|
+
const src = value.url || sanityImageUrl(value, { width: 1200 });
|
|
90
|
+
const srcSet = !value.url ? sanityImageSrcSet(value, [400, 800, 1200, 1600]) : void 0;
|
|
91
|
+
const objectPosition = hotspotToObjectPosition(value);
|
|
92
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("figure", { className: "sonor-cms-figure", children: [
|
|
93
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
94
|
+
"img",
|
|
95
|
+
{
|
|
96
|
+
src,
|
|
97
|
+
srcSet,
|
|
98
|
+
sizes: "(max-width: 768px) 100vw, (max-width: 1200px) 80vw, 1200px",
|
|
99
|
+
alt: value.alt || "",
|
|
100
|
+
className: "sonor-cms-img",
|
|
101
|
+
loading: "lazy",
|
|
102
|
+
style: objectPosition ? { objectPosition } : void 0
|
|
103
|
+
}
|
|
104
|
+
),
|
|
105
|
+
value.caption && /* @__PURE__ */ jsxRuntime.jsx("figcaption", { className: "sonor-cms-figcaption", children: typeof value.caption === "string" ? value.caption : null })
|
|
106
|
+
] });
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
function PortableTextRenderer({
|
|
111
|
+
value,
|
|
112
|
+
components: overrides,
|
|
113
|
+
className
|
|
114
|
+
}) {
|
|
115
|
+
if (!value || !Array.isArray(value) || value.length === 0) return null;
|
|
116
|
+
const merged = overrides ? {
|
|
117
|
+
...defaultComponents,
|
|
118
|
+
block: { ...defaultComponents.block, ...overrides.block },
|
|
119
|
+
marks: { ...defaultComponents.marks, ...overrides.marks },
|
|
120
|
+
types: { ...defaultComponents.types, ...overrides.types },
|
|
121
|
+
list: { ...defaultComponents.list, ...overrides.list },
|
|
122
|
+
listItem: { ...defaultComponents.listItem, ...overrides.listItem }
|
|
123
|
+
} : defaultComponents;
|
|
124
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: className || "sonor-cms-content", children: /* @__PURE__ */ jsxRuntime.jsx(react.PortableText, { value, components: merged }) });
|
|
125
|
+
}
|
|
126
|
+
function HeroSection({ data, portableTextComponents }) {
|
|
127
|
+
const headline = data.headline;
|
|
128
|
+
const subheadline = data.subheadline;
|
|
129
|
+
const ctaText = data.ctaText;
|
|
130
|
+
const ctaLink = data.ctaLink;
|
|
131
|
+
const bgImage = data.backgroundImage;
|
|
132
|
+
const bgUrl = sanityImageUrl(bgImage, { width: 1920, quality: 80 });
|
|
133
|
+
const bgPosition = hotspotToObjectPosition(bgImage) || "50% 50%";
|
|
134
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
135
|
+
"section",
|
|
136
|
+
{
|
|
137
|
+
className: "sonor-cms-hero",
|
|
138
|
+
style: bgUrl ? { backgroundImage: `url(${bgUrl})`, backgroundPosition: bgPosition, backgroundSize: "cover" } : void 0,
|
|
139
|
+
children: [
|
|
140
|
+
headline && /* @__PURE__ */ jsxRuntime.jsx(PortableTextRenderer, { value: headline, components: portableTextComponents, className: "sonor-cms-hero-headline" }),
|
|
141
|
+
subheadline && /* @__PURE__ */ jsxRuntime.jsx(PortableTextRenderer, { value: subheadline, components: portableTextComponents, className: "sonor-cms-hero-subheadline" }),
|
|
142
|
+
ctaText && ctaLink && /* @__PURE__ */ jsxRuntime.jsx("a", { href: ctaLink, className: "sonor-cms-hero-cta", children: ctaText })
|
|
143
|
+
]
|
|
144
|
+
}
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
function RichTextSection({ data, portableTextComponents }) {
|
|
148
|
+
const content = data.content;
|
|
149
|
+
if (!content) return null;
|
|
150
|
+
return /* @__PURE__ */ jsxRuntime.jsx("section", { className: "sonor-cms-richtext", children: /* @__PURE__ */ jsxRuntime.jsx(PortableTextRenderer, { value: content, components: portableTextComponents }) });
|
|
151
|
+
}
|
|
152
|
+
function CtaSection({ data, portableTextComponents }) {
|
|
153
|
+
const headline = data.headline;
|
|
154
|
+
const description = data.description;
|
|
155
|
+
const buttonText = data.buttonText;
|
|
156
|
+
const buttonLink = data.buttonLink;
|
|
157
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "sonor-cms-cta", children: [
|
|
158
|
+
headline && /* @__PURE__ */ jsxRuntime.jsx(PortableTextRenderer, { value: headline, components: portableTextComponents, className: "sonor-cms-cta-headline" }),
|
|
159
|
+
description && /* @__PURE__ */ jsxRuntime.jsx(PortableTextRenderer, { value: description, components: portableTextComponents, className: "sonor-cms-cta-description" }),
|
|
160
|
+
buttonText && buttonLink && /* @__PURE__ */ jsxRuntime.jsx("a", { href: buttonLink, className: "sonor-cms-cta-button", children: buttonText })
|
|
161
|
+
] });
|
|
162
|
+
}
|
|
163
|
+
function GallerySection({ data, portableTextComponents }) {
|
|
164
|
+
const images = data.images || [];
|
|
165
|
+
const layout = data.layout || "grid";
|
|
166
|
+
const caption = data.caption;
|
|
167
|
+
if (images.length === 0) return null;
|
|
168
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "sonor-cms-gallery", children: [
|
|
169
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `sonor-cms-gallery-${layout}`, children: images.map((img, i) => {
|
|
170
|
+
const objectPosition = hotspotToObjectPosition(img);
|
|
171
|
+
return /* @__PURE__ */ jsxRuntime.jsx("figure", { className: "sonor-cms-gallery-item", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
172
|
+
"img",
|
|
173
|
+
{
|
|
174
|
+
src: sanityImageUrl(img, { width: 800 }),
|
|
175
|
+
srcSet: sanityImageSrcSet(img, [400, 800, 1200]),
|
|
176
|
+
sizes: "(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 33vw",
|
|
177
|
+
alt: img.alt || "",
|
|
178
|
+
loading: "lazy",
|
|
179
|
+
style: objectPosition ? { objectPosition } : void 0
|
|
180
|
+
}
|
|
181
|
+
) }, img.asset?._ref || i);
|
|
182
|
+
}) }),
|
|
183
|
+
caption && /* @__PURE__ */ jsxRuntime.jsx(PortableTextRenderer, { value: caption, components: portableTextComponents, className: "sonor-cms-gallery-caption" })
|
|
184
|
+
] });
|
|
185
|
+
}
|
|
186
|
+
function TestimonialsSection({ data, portableTextComponents }) {
|
|
187
|
+
const items = data.items || [];
|
|
188
|
+
const layout = data.layout || "grid";
|
|
189
|
+
if (items.length === 0) return null;
|
|
190
|
+
return /* @__PURE__ */ jsxRuntime.jsx("section", { className: `sonor-cms-testimonials sonor-cms-testimonials-${layout}`, children: items.map((item, i) => /* @__PURE__ */ jsxRuntime.jsxs("blockquote", { className: "sonor-cms-testimonial", children: [
|
|
191
|
+
/* @__PURE__ */ jsxRuntime.jsx(PortableTextRenderer, { value: item.quote, components: portableTextComponents, className: "sonor-cms-testimonial-quote" }),
|
|
192
|
+
/* @__PURE__ */ jsxRuntime.jsxs("footer", { className: "sonor-cms-testimonial-footer", children: [
|
|
193
|
+
item.avatar?.asset?._ref && /* @__PURE__ */ jsxRuntime.jsx(
|
|
194
|
+
"img",
|
|
195
|
+
{
|
|
196
|
+
src: sanityImageUrl(item.avatar, { width: 80, height: 80, fit: "crop" }),
|
|
197
|
+
alt: item.avatar.alt || item.author,
|
|
198
|
+
className: "sonor-cms-testimonial-avatar",
|
|
199
|
+
width: 80,
|
|
200
|
+
height: 80,
|
|
201
|
+
loading: "lazy"
|
|
202
|
+
}
|
|
203
|
+
),
|
|
204
|
+
/* @__PURE__ */ jsxRuntime.jsxs("cite", { className: "sonor-cms-testimonial-author", children: [
|
|
205
|
+
item.author,
|
|
206
|
+
item.role && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "sonor-cms-testimonial-role", children: [
|
|
207
|
+
", ",
|
|
208
|
+
item.role
|
|
209
|
+
] })
|
|
210
|
+
] })
|
|
211
|
+
] })
|
|
212
|
+
] }, i)) });
|
|
213
|
+
}
|
|
214
|
+
function FaqSection({ data, portableTextComponents }) {
|
|
215
|
+
const items = data.items || [];
|
|
216
|
+
if (items.length === 0) return null;
|
|
217
|
+
return /* @__PURE__ */ jsxRuntime.jsx("section", { className: "sonor-cms-faq", children: items.map((item, i) => /* @__PURE__ */ jsxRuntime.jsxs("details", { className: "sonor-cms-faq-item", children: [
|
|
218
|
+
/* @__PURE__ */ jsxRuntime.jsx("summary", { className: "sonor-cms-faq-question", children: item.question }),
|
|
219
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "sonor-cms-faq-answer", children: /* @__PURE__ */ jsxRuntime.jsx(PortableTextRenderer, { value: item.answer, components: portableTextComponents }) })
|
|
220
|
+
] }, i)) });
|
|
221
|
+
}
|
|
222
|
+
function FormSection({ data, portableTextComponents }) {
|
|
223
|
+
const formSlug = data.formSlug;
|
|
224
|
+
const heading = data.heading;
|
|
225
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "sonor-cms-form", children: [
|
|
226
|
+
heading && /* @__PURE__ */ jsxRuntime.jsx(PortableTextRenderer, { value: heading, components: portableTextComponents, className: "sonor-cms-form-heading" }),
|
|
227
|
+
formSlug ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
228
|
+
"div",
|
|
229
|
+
{
|
|
230
|
+
className: "sonor-cms-form-embed",
|
|
231
|
+
"data-form-slug": formSlug
|
|
232
|
+
}
|
|
233
|
+
) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "sonor-cms-form-placeholder", children: "Form not configured" })
|
|
234
|
+
] });
|
|
235
|
+
}
|
|
236
|
+
function CustomSection({ data, displayName }) {
|
|
237
|
+
const componentName = data.componentName;
|
|
238
|
+
data.props || {};
|
|
239
|
+
return /* @__PURE__ */ jsxRuntime.jsx("section", { className: "sonor-cms-custom", "data-component": componentName, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "sonor-cms-custom-placeholder", children: [
|
|
240
|
+
"Custom component: ",
|
|
241
|
+
componentName || displayName
|
|
242
|
+
] }) });
|
|
243
|
+
}
|
|
244
|
+
var defaultRenderers = {
|
|
245
|
+
hero: HeroSection,
|
|
246
|
+
richText: RichTextSection,
|
|
247
|
+
cta: CtaSection,
|
|
248
|
+
gallery: GallerySection,
|
|
249
|
+
testimonials: TestimonialsSection,
|
|
250
|
+
faq: FaqSection,
|
|
251
|
+
form: FormSection,
|
|
252
|
+
custom: CustomSection
|
|
253
|
+
};
|
|
254
|
+
function CmsSection({ section, sectionComponents, portableTextComponents }) {
|
|
255
|
+
const Renderer = sectionComponents?.[section.sectionType] || defaultRenderers[section.sectionType];
|
|
256
|
+
if (!Renderer) {
|
|
257
|
+
if (process.env.NODE_ENV === "development") {
|
|
258
|
+
console.warn(`@sonordev/cms: No renderer for section type: ${section.sectionType}`);
|
|
259
|
+
}
|
|
260
|
+
return null;
|
|
261
|
+
}
|
|
262
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
263
|
+
"div",
|
|
264
|
+
{
|
|
265
|
+
className: `sonor-cms-section sonor-cms-section-${section.sectionType}`,
|
|
266
|
+
"data-section-id": section._id,
|
|
267
|
+
"data-section-type": section.sectionType,
|
|
268
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
269
|
+
Renderer,
|
|
270
|
+
{
|
|
271
|
+
data: section.data,
|
|
272
|
+
sectionType: section.sectionType,
|
|
273
|
+
displayName: section.displayName,
|
|
274
|
+
portableTextComponents
|
|
275
|
+
}
|
|
276
|
+
)
|
|
277
|
+
}
|
|
278
|
+
);
|
|
279
|
+
}
|
|
280
|
+
async function CmsPage({
|
|
281
|
+
path,
|
|
282
|
+
sectionComponents,
|
|
283
|
+
portableTextComponents,
|
|
284
|
+
fallback,
|
|
285
|
+
className
|
|
286
|
+
}) {
|
|
287
|
+
const page = await chunkMG23BS36_js.getCmsPage(path);
|
|
288
|
+
if (!page) {
|
|
289
|
+
if (fallback) return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: fallback });
|
|
290
|
+
return null;
|
|
291
|
+
}
|
|
292
|
+
if (!page.sections || page.sections.length === 0) {
|
|
293
|
+
if (fallback) return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: fallback });
|
|
294
|
+
return null;
|
|
295
|
+
}
|
|
296
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
297
|
+
"div",
|
|
298
|
+
{
|
|
299
|
+
className: className || "sonor-cms-page",
|
|
300
|
+
"data-cms-page-id": page._id,
|
|
301
|
+
"data-cms-path": page.path,
|
|
302
|
+
children: page.sections.map((section) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
303
|
+
CmsSection,
|
|
304
|
+
{
|
|
305
|
+
section,
|
|
306
|
+
sectionComponents,
|
|
307
|
+
portableTextComponents
|
|
308
|
+
},
|
|
309
|
+
section._id
|
|
310
|
+
))
|
|
311
|
+
}
|
|
312
|
+
);
|
|
313
|
+
}
|
|
314
|
+
function CmsPreview({
|
|
315
|
+
apiUrl = process.env.SONOR_API_URL || process.env.NEXT_PUBLIC_UPTRADE_API_URL || "https://api.sonor.io",
|
|
316
|
+
apiKey,
|
|
317
|
+
path,
|
|
318
|
+
pollInterval = 3e3,
|
|
319
|
+
sectionComponents,
|
|
320
|
+
portableTextComponents,
|
|
321
|
+
className
|
|
322
|
+
}) {
|
|
323
|
+
const [page, setPage] = react$1.useState(null);
|
|
324
|
+
const [error, setError] = react$1.useState(null);
|
|
325
|
+
react$1.useEffect(() => {
|
|
326
|
+
let cancelled = false;
|
|
327
|
+
async function fetchPage() {
|
|
328
|
+
try {
|
|
329
|
+
const res = await fetch(`${apiUrl}/api/public/cms/page`, {
|
|
330
|
+
method: "POST",
|
|
331
|
+
headers: {
|
|
332
|
+
"Content-Type": "application/json",
|
|
333
|
+
"x-api-key": apiKey
|
|
334
|
+
},
|
|
335
|
+
body: JSON.stringify({ path })
|
|
336
|
+
});
|
|
337
|
+
if (!res.ok) {
|
|
338
|
+
setError(`Error ${res.status}`);
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
const data = await res.json();
|
|
342
|
+
if (!cancelled && data?.found && data.page) {
|
|
343
|
+
setPage(data.page);
|
|
344
|
+
setError(null);
|
|
345
|
+
}
|
|
346
|
+
} catch (err) {
|
|
347
|
+
if (!cancelled) {
|
|
348
|
+
setError("Failed to load preview");
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
fetchPage();
|
|
353
|
+
if (pollInterval > 0) {
|
|
354
|
+
const interval = setInterval(fetchPage, pollInterval);
|
|
355
|
+
return () => {
|
|
356
|
+
cancelled = true;
|
|
357
|
+
clearInterval(interval);
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
return () => {
|
|
361
|
+
cancelled = true;
|
|
362
|
+
};
|
|
363
|
+
}, [apiUrl, apiKey, path, pollInterval]);
|
|
364
|
+
if (error) {
|
|
365
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "sonor-cms-preview-error", children: /* @__PURE__ */ jsxRuntime.jsxs("p", { children: [
|
|
366
|
+
"Preview error: ",
|
|
367
|
+
error
|
|
368
|
+
] }) });
|
|
369
|
+
}
|
|
370
|
+
if (!page) {
|
|
371
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "sonor-cms-preview-loading", children: /* @__PURE__ */ jsxRuntime.jsx("p", { children: "Loading preview..." }) });
|
|
372
|
+
}
|
|
373
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
374
|
+
"div",
|
|
375
|
+
{
|
|
376
|
+
className: className || "sonor-cms-page sonor-cms-preview",
|
|
377
|
+
"data-cms-preview": "true",
|
|
378
|
+
"data-cms-path": page.path,
|
|
379
|
+
children: page.sections?.map((section) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
380
|
+
CmsSection,
|
|
381
|
+
{
|
|
382
|
+
section,
|
|
383
|
+
sectionComponents,
|
|
384
|
+
portableTextComponents
|
|
385
|
+
},
|
|
386
|
+
section._id
|
|
387
|
+
))
|
|
388
|
+
}
|
|
389
|
+
);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
exports.CmsPage = CmsPage;
|
|
393
|
+
exports.CmsPreview = CmsPreview;
|
|
394
|
+
exports.CmsSection = CmsSection;
|
|
395
|
+
exports.CtaSection = CtaSection;
|
|
396
|
+
exports.CustomSection = CustomSection;
|
|
397
|
+
exports.FaqSection = FaqSection;
|
|
398
|
+
exports.FormSection = FormSection;
|
|
399
|
+
exports.GallerySection = GallerySection;
|
|
400
|
+
exports.HeroSection = HeroSection;
|
|
401
|
+
exports.PortableTextRenderer = PortableTextRenderer;
|
|
402
|
+
exports.RichTextSection = RichTextSection;
|
|
403
|
+
exports.TestimonialsSection = TestimonialsSection;
|
|
404
|
+
exports.configureSanityImages = configureSanityImages;
|
|
405
|
+
exports.hotspotToObjectPosition = hotspotToObjectPosition;
|
|
406
|
+
exports.sanityImageSrcSet = sanityImageSrcSet;
|
|
407
|
+
exports.sanityImageUrl = sanityImageUrl;
|
|
408
|
+
//# sourceMappingURL=index.js.map
|
|
409
|
+
//# sourceMappingURL=index.js.map
|