@sonordev/site-kit 1.2.7 → 1.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (247) hide show
  1. package/README.md +5 -3
  2. package/dist/analytics/index.js +6 -6
  3. package/dist/analytics/index.mjs +2 -2
  4. package/dist/{api-CWtoFJCO.d.mts → api-DTKSHh_w.d.mts} +1 -1
  5. package/dist/{api-CWtoFJCO.d.ts → api-DTKSHh_w.d.ts} +1 -1
  6. package/dist/blog/index.js +10 -10
  7. package/dist/blog/index.js.map +1 -1
  8. package/dist/blog/index.mjs +10 -10
  9. package/dist/blog/index.mjs.map +1 -1
  10. package/dist/blog/server.js +2 -2
  11. package/dist/blog/server.js.map +1 -1
  12. package/dist/blog/server.mjs +2 -2
  13. package/dist/blog/server.mjs.map +1 -1
  14. package/dist/{chunk-7RYCHO6D.mjs → chunk-2RHO4KSK.mjs} +9 -9
  15. package/dist/{chunk-7RYCHO6D.mjs.map → chunk-2RHO4KSK.mjs.map} +1 -1
  16. package/dist/{chunk-EEZCR6E6.js → chunk-2XOW276O.js} +5 -5
  17. package/dist/{chunk-EEZCR6E6.js.map → chunk-2XOW276O.js.map} +1 -1
  18. package/dist/{chunk-JTLOJLWQ.mjs → chunk-36Y7OWES.mjs} +4 -4
  19. package/dist/chunk-36Y7OWES.mjs.map +1 -0
  20. package/dist/{chunk-DQYMKR27.mjs → chunk-47Y3YSES.mjs} +10 -10
  21. package/dist/chunk-47Y3YSES.mjs.map +1 -0
  22. package/dist/{chunk-MV3QN7PW.mjs → chunk-5F7FFUPJ.mjs} +3 -3
  23. package/dist/{chunk-MV3QN7PW.mjs.map → chunk-5F7FFUPJ.mjs.map} +1 -1
  24. package/dist/{chunk-AFAO3TGS.mjs → chunk-5YDPPOUU.mjs} +10 -10
  25. package/dist/chunk-5YDPPOUU.mjs.map +1 -0
  26. package/dist/{chunk-D63MUKZ6.mjs → chunk-6YXRLC6W.mjs} +5 -5
  27. package/dist/chunk-6YXRLC6W.mjs.map +1 -0
  28. package/dist/{chunk-7RF6PVHA.mjs → chunk-7FKPJQVS.mjs} +33 -68
  29. package/dist/chunk-7FKPJQVS.mjs.map +1 -0
  30. package/dist/{chunk-BYLIU6XG.js → chunk-7ROZJDXE.js} +10 -10
  31. package/dist/chunk-7ROZJDXE.js.map +1 -0
  32. package/dist/{chunk-UWE5PCYJ.mjs → chunk-APZMXRI3.mjs} +3 -3
  33. package/dist/chunk-APZMXRI3.mjs.map +1 -0
  34. package/dist/{chunk-622GAQP5.js → chunk-BBITDUZQ.js} +6 -6
  35. package/dist/chunk-BBITDUZQ.js.map +1 -0
  36. package/dist/{chunk-DDKW2FNA.js → chunk-BFJDUTXK.js} +8 -8
  37. package/dist/chunk-BFJDUTXK.js.map +1 -0
  38. package/dist/chunk-C3A5HXHX.mjs +78 -0
  39. package/dist/chunk-C3A5HXHX.mjs.map +1 -0
  40. package/dist/{chunk-XZJOZJB6.js → chunk-CFEOOJUT.js} +12 -12
  41. package/dist/{chunk-XZJOZJB6.js.map → chunk-CFEOOJUT.js.map} +1 -1
  42. package/dist/{chunk-M2T6R7BA.mjs → chunk-DOSSLBNW.mjs} +4 -4
  43. package/dist/chunk-DOSSLBNW.mjs.map +1 -0
  44. package/dist/{chunk-OB7E654K.js → chunk-DY4K6X3A.js} +6 -6
  45. package/dist/chunk-DY4K6X3A.js.map +1 -0
  46. package/dist/{chunk-7UKPRW25.mjs → chunk-EISQ7LJG.mjs} +6 -6
  47. package/dist/chunk-EISQ7LJG.mjs.map +1 -0
  48. package/dist/{chunk-7557OTHW.js → chunk-EUNL6GAL.js} +5 -5
  49. package/dist/chunk-EUNL6GAL.js.map +1 -0
  50. package/dist/{chunk-KUGMH4ZF.js → chunk-G6VGUAK2.js} +4 -4
  51. package/dist/chunk-G6VGUAK2.js.map +1 -0
  52. package/dist/{chunk-XQQWI6WB.js → chunk-GVXZWXQ7.js} +10 -10
  53. package/dist/chunk-GVXZWXQ7.js.map +1 -0
  54. package/dist/{chunk-24277A3Q.mjs → chunk-HF2FWDBJ.mjs} +9 -9
  55. package/dist/chunk-HF2FWDBJ.mjs.map +1 -0
  56. package/dist/{chunk-72MQFHYJ.js → chunk-IFAW7JFO.js} +16 -16
  57. package/dist/chunk-IFAW7JFO.js.map +1 -0
  58. package/dist/{chunk-P3UWIUJS.mjs → chunk-IKIJEKU3.mjs} +16 -16
  59. package/dist/chunk-IKIJEKU3.mjs.map +1 -0
  60. package/dist/{chunk-PKN27UMH.mjs → chunk-JIDOXTX2.mjs} +3 -3
  61. package/dist/{chunk-PKN27UMH.mjs.map → chunk-JIDOXTX2.mjs.map} +1 -1
  62. package/dist/{chunk-7FUV73JZ.js → chunk-JM3ZR6LB.js} +9 -9
  63. package/dist/chunk-JM3ZR6LB.js.map +1 -0
  64. package/dist/{chunk-OIIKTGRL.mjs → chunk-JMNSED4O.mjs} +8 -8
  65. package/dist/chunk-JMNSED4O.mjs.map +1 -0
  66. package/dist/chunk-MG23BS36.js +82 -0
  67. package/dist/chunk-MG23BS36.js.map +1 -0
  68. package/dist/{chunk-TFLQX7K7.mjs → chunk-N24BPFF6.mjs} +6 -6
  69. package/dist/chunk-N24BPFF6.mjs.map +1 -0
  70. package/dist/{chunk-LIVWLY2P.js → chunk-PPRAW576.js} +3 -3
  71. package/dist/{chunk-LIVWLY2P.js.map → chunk-PPRAW576.js.map} +1 -1
  72. package/dist/{chunk-W4PALSGM.js → chunk-REMHGWXT.js} +3 -3
  73. package/dist/chunk-REMHGWXT.js.map +1 -0
  74. package/dist/{chunk-DW5UJKHH.js → chunk-RMOL4TZ6.js} +8 -8
  75. package/dist/chunk-RMOL4TZ6.js.map +1 -0
  76. package/dist/{chunk-KKU3K7RG.js → chunk-SLB5V4RT.js} +33 -67
  77. package/dist/chunk-SLB5V4RT.js.map +1 -0
  78. package/dist/{chunk-K23A4G76.mjs → chunk-SQSBAPWA.mjs} +8 -8
  79. package/dist/chunk-SQSBAPWA.mjs.map +1 -0
  80. package/dist/{chunk-WECQ6KOB.js → chunk-TG46LJFB.js} +4 -4
  81. package/dist/chunk-TG46LJFB.js.map +1 -0
  82. package/dist/{chunk-43GBM4SX.js → chunk-TKQLH33E.js} +3 -3
  83. package/dist/chunk-TKQLH33E.js.map +1 -0
  84. package/dist/{chunk-UYFDNX2F.js → chunk-TLHRV3LZ.js} +5 -5
  85. package/dist/chunk-TLHRV3LZ.js.map +1 -0
  86. package/dist/{chunk-6ZCISNAB.mjs → chunk-UPR5FEIO.mjs} +3 -3
  87. package/dist/chunk-UPR5FEIO.mjs.map +1 -0
  88. package/dist/{chunk-GCJXQ4AG.mjs → chunk-VZMDH3R4.mjs} +5 -5
  89. package/dist/chunk-VZMDH3R4.mjs.map +1 -0
  90. package/dist/{chunk-LBVWVP72.js → chunk-X4J33XQD.js} +7 -7
  91. package/dist/chunk-X4J33XQD.js.map +1 -0
  92. package/dist/{chunk-QXV4667R.mjs → chunk-XFOL6JDF.mjs} +5 -5
  93. package/dist/chunk-XFOL6JDF.mjs.map +1 -0
  94. package/dist/cli/index.js +80 -91
  95. package/dist/cli/index.js.map +1 -1
  96. package/dist/cli/index.mjs +76 -87
  97. package/dist/cli/index.mjs.map +1 -1
  98. package/dist/cms/index.d.mts +139 -0
  99. package/dist/cms/index.d.ts +139 -0
  100. package/dist/cms/index.js +409 -0
  101. package/dist/cms/index.js.map +1 -0
  102. package/dist/cms/index.mjs +388 -0
  103. package/dist/cms/index.mjs.map +1 -0
  104. package/dist/cms/server.d.mts +47 -0
  105. package/dist/cms/server.d.ts +47 -0
  106. package/dist/cms/server.js +21 -0
  107. package/dist/{server-api-GJPNRYUP.js.map → cms/server.js.map} +1 -1
  108. package/dist/cms/server.mjs +4 -0
  109. package/dist/{server-api-EWXKOQZA.mjs.map → cms/server.mjs.map} +1 -1
  110. package/dist/commerce/index.js +42 -42
  111. package/dist/commerce/index.mjs +1 -1
  112. package/dist/commerce/server.d.mts +1 -1
  113. package/dist/commerce/server.d.ts +1 -1
  114. package/dist/commerce/server.js.map +1 -1
  115. package/dist/commerce/server.mjs.map +1 -1
  116. package/dist/config/index.js +1 -1
  117. package/dist/config/index.js.map +1 -1
  118. package/dist/config/index.mjs +1 -1
  119. package/dist/config/index.mjs.map +1 -1
  120. package/dist/engage/index.js +4 -4
  121. package/dist/engage/index.mjs +1 -1
  122. package/dist/forms/index.js +5 -5
  123. package/dist/forms/index.js.map +1 -1
  124. package/dist/forms/index.mjs +5 -5
  125. package/dist/forms/index.mjs.map +1 -1
  126. package/dist/generators-DOFWGRXS.js +37 -0
  127. package/dist/{generators-DTMO36DV.js.map → generators-DOFWGRXS.js.map} +1 -1
  128. package/dist/generators-R62APO62.mjs +4 -0
  129. package/dist/{generators-2XKQMPKH.mjs.map → generators-R62APO62.mjs.map} +1 -1
  130. package/dist/images/index.d.mts +1 -1
  131. package/dist/images/index.d.ts +1 -1
  132. package/dist/images/index.js +11 -11
  133. package/dist/images/index.mjs +2 -2
  134. package/dist/images/server.d.mts +3 -3
  135. package/dist/images/server.d.ts +3 -3
  136. package/dist/images/server.js +4 -4
  137. package/dist/images/server.mjs +1 -1
  138. package/dist/index.d.mts +5 -5
  139. package/dist/index.d.ts +5 -5
  140. package/dist/index.js +81 -81
  141. package/dist/index.js.map +1 -1
  142. package/dist/index.mjs +28 -28
  143. package/dist/index.mjs.map +1 -1
  144. package/dist/layout/index.d.mts +2 -2
  145. package/dist/layout/index.d.ts +2 -2
  146. package/dist/layout/index.js +17 -17
  147. package/dist/layout/index.js.map +1 -1
  148. package/dist/layout/index.mjs +10 -10
  149. package/dist/layout/index.mjs.map +1 -1
  150. package/dist/llms/index.js +12 -12
  151. package/dist/llms/index.mjs +2 -2
  152. package/dist/manifest/index.js +4 -4
  153. package/dist/manifest/index.js.map +1 -1
  154. package/dist/manifest/index.mjs +3 -3
  155. package/dist/manifest/index.mjs.map +1 -1
  156. package/dist/middleware/index.js +3 -3
  157. package/dist/middleware/index.mjs +2 -2
  158. package/dist/{migrator-2MQHOFDQ.mjs → migrator-3WQB3KQ2.mjs} +3 -3
  159. package/dist/{migrator-2MQHOFDQ.mjs.map → migrator-3WQB3KQ2.mjs.map} +1 -1
  160. package/dist/migrator-HFVQYK5R.js +37 -0
  161. package/dist/{migrator-THJCF6MZ.js.map → migrator-HFVQYK5R.js.map} +1 -1
  162. package/dist/redirects/index.d.mts +2 -2
  163. package/dist/redirects/index.d.ts +2 -2
  164. package/dist/redirects/index.js +6 -6
  165. package/dist/redirects/index.mjs +2 -2
  166. package/dist/reputation/index.js +4 -4
  167. package/dist/reputation/index.mjs +1 -1
  168. package/dist/robots/index.d.mts +1 -1
  169. package/dist/robots/index.d.ts +1 -1
  170. package/dist/robots/index.js +3 -3
  171. package/dist/robots/index.js.map +1 -1
  172. package/dist/robots/index.mjs +2 -2
  173. package/dist/robots/index.mjs.map +1 -1
  174. package/dist/seo/index.d.mts +1 -1
  175. package/dist/seo/index.d.ts +1 -1
  176. package/dist/seo/index.js +43 -43
  177. package/dist/seo/index.js.map +1 -1
  178. package/dist/seo/index.mjs +6 -6
  179. package/dist/seo/index.mjs.map +1 -1
  180. package/dist/seo/register-sitemap-cli.js +18 -18
  181. package/dist/seo/register-sitemap-cli.js.map +1 -1
  182. package/dist/seo/register-sitemap-cli.mjs +18 -18
  183. package/dist/seo/register-sitemap-cli.mjs.map +1 -1
  184. package/dist/seo/server.d.mts +1 -1
  185. package/dist/seo/server.d.ts +1 -1
  186. package/dist/seo/server.js +10 -10
  187. package/dist/seo/server.js.map +1 -1
  188. package/dist/seo/server.mjs +8 -8
  189. package/dist/seo/server.mjs.map +1 -1
  190. package/dist/{server-api-GJPNRYUP.js → server-api-C5JXIROA.js} +21 -21
  191. package/dist/server-api-C5JXIROA.js.map +1 -0
  192. package/dist/{server-api-EWXKOQZA.mjs → server-api-HTSLBT6F.mjs} +3 -3
  193. package/dist/server-api-HTSLBT6F.mjs.map +1 -0
  194. package/dist/setup/client.js +7 -7
  195. package/dist/setup/client.mjs +2 -2
  196. package/dist/setup/index.js +9 -9
  197. package/dist/setup/index.mjs +3 -3
  198. package/dist/setup/server.js +2 -2
  199. package/dist/setup/server.mjs +1 -1
  200. package/dist/site-config/index.d.mts +1 -1
  201. package/dist/site-config/index.d.ts +1 -1
  202. package/dist/site-config/index.js +3 -3
  203. package/dist/site-config/index.mjs +1 -1
  204. package/dist/sitemap/index.d.mts +2 -2
  205. package/dist/sitemap/index.d.ts +2 -2
  206. package/dist/sitemap/index.js +10 -10
  207. package/dist/sitemap/index.js.map +1 -1
  208. package/dist/sitemap/index.mjs +8 -8
  209. package/dist/sitemap/index.mjs.map +1 -1
  210. package/dist/types-BG-x8yhh.d.mts +106 -0
  211. package/dist/types-BG-x8yhh.d.ts +106 -0
  212. package/package.json +13 -1
  213. package/dist/chunk-24277A3Q.mjs.map +0 -1
  214. package/dist/chunk-43GBM4SX.js.map +0 -1
  215. package/dist/chunk-622GAQP5.js.map +0 -1
  216. package/dist/chunk-6ZCISNAB.mjs.map +0 -1
  217. package/dist/chunk-72MQFHYJ.js.map +0 -1
  218. package/dist/chunk-7557OTHW.js.map +0 -1
  219. package/dist/chunk-7FUV73JZ.js.map +0 -1
  220. package/dist/chunk-7RF6PVHA.mjs.map +0 -1
  221. package/dist/chunk-7UKPRW25.mjs.map +0 -1
  222. package/dist/chunk-AFAO3TGS.mjs.map +0 -1
  223. package/dist/chunk-BYLIU6XG.js.map +0 -1
  224. package/dist/chunk-D63MUKZ6.mjs.map +0 -1
  225. package/dist/chunk-DDKW2FNA.js.map +0 -1
  226. package/dist/chunk-DQYMKR27.mjs.map +0 -1
  227. package/dist/chunk-DW5UJKHH.js.map +0 -1
  228. package/dist/chunk-GCJXQ4AG.mjs.map +0 -1
  229. package/dist/chunk-JTLOJLWQ.mjs.map +0 -1
  230. package/dist/chunk-K23A4G76.mjs.map +0 -1
  231. package/dist/chunk-KKU3K7RG.js.map +0 -1
  232. package/dist/chunk-KUGMH4ZF.js.map +0 -1
  233. package/dist/chunk-LBVWVP72.js.map +0 -1
  234. package/dist/chunk-M2T6R7BA.mjs.map +0 -1
  235. package/dist/chunk-OB7E654K.js.map +0 -1
  236. package/dist/chunk-OIIKTGRL.mjs.map +0 -1
  237. package/dist/chunk-P3UWIUJS.mjs.map +0 -1
  238. package/dist/chunk-QXV4667R.mjs.map +0 -1
  239. package/dist/chunk-TFLQX7K7.mjs.map +0 -1
  240. package/dist/chunk-UWE5PCYJ.mjs.map +0 -1
  241. package/dist/chunk-UYFDNX2F.js.map +0 -1
  242. package/dist/chunk-W4PALSGM.js.map +0 -1
  243. package/dist/chunk-WECQ6KOB.js.map +0 -1
  244. package/dist/chunk-XQQWI6WB.js.map +0 -1
  245. package/dist/generators-2XKQMPKH.mjs +0 -4
  246. package/dist/generators-DTMO36DV.js +0 -33
  247. 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