@riverbankcms/sdk 0.4.2 → 0.5.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.
Files changed (180) hide show
  1. package/README.md +84 -0
  2. package/dist/cli/index.js +3104 -120
  3. package/dist/cli/index.js.map +1 -1
  4. package/dist/client/analytics.js +1 -1
  5. package/dist/client/analytics.js.map +1 -1
  6. package/dist/client/analytics.mjs +1 -1
  7. package/dist/client/analytics.mjs.map +1 -1
  8. package/dist/client/bookings.js +6 -6
  9. package/dist/client/bookings.js.map +1 -1
  10. package/dist/client/bookings.mjs +6 -6
  11. package/dist/client/bookings.mjs.map +1 -1
  12. package/dist/client/client.d.mts +2 -2
  13. package/dist/client/client.d.ts +2 -2
  14. package/dist/client/client.js +1368 -520
  15. package/dist/client/client.js.map +1 -1
  16. package/dist/client/client.mjs +1368 -520
  17. package/dist/client/client.mjs.map +1 -1
  18. package/dist/client/hooks.d.mts +2 -2
  19. package/dist/client/hooks.d.ts +2 -2
  20. package/dist/client/hooks.js +26 -11
  21. package/dist/client/hooks.js.map +1 -1
  22. package/dist/client/hooks.mjs +26 -11
  23. package/dist/client/hooks.mjs.map +1 -1
  24. package/dist/client/rendering/client.js +24 -14
  25. package/dist/client/rendering/client.js.map +1 -1
  26. package/dist/client/rendering/client.mjs +24 -14
  27. package/dist/client/rendering/client.mjs.map +1 -1
  28. package/dist/client/usePage--fGlyrgj.d.mts +6439 -0
  29. package/dist/client/usePage-BTPnCuWC.d.mts +6511 -0
  30. package/dist/client/usePage-BafOS9UT.d.mts +6512 -0
  31. package/dist/client/usePage-Bnx-kA6x.d.mts +6670 -0
  32. package/dist/client/usePage-CE7X5NcN.d.ts +6439 -0
  33. package/dist/client/usePage-DoPI6b8V.d.ts +6511 -0
  34. package/dist/client/usePage-QNWArrVO.d.ts +6670 -0
  35. package/dist/client/usePage-fBgPB6Oq.d.ts +6512 -0
  36. package/dist/server/{Layout-kRv5sU81.d.ts → Layout-B-q2Py4v.d.ts} +4 -4
  37. package/dist/server/{Layout-ByUnm35V.d.mts → Layout-Cc5HUXAH.d.mts} +4 -4
  38. package/dist/server/{chunk-6JBKKV3G.js → chunk-2KCF2DNK.js} +30 -10
  39. package/dist/server/chunk-2KCF2DNK.js.map +1 -0
  40. package/dist/server/{chunk-N3PX76AP.mjs → chunk-4HIRA33Z.mjs} +247 -135
  41. package/dist/server/chunk-4HIRA33Z.mjs.map +1 -0
  42. package/dist/server/chunk-5STV4MWD.js +189 -0
  43. package/dist/server/chunk-5STV4MWD.js.map +1 -0
  44. package/dist/server/{chunk-R5B6IOFQ.js → chunk-6OSNCH4F.js} +247 -135
  45. package/dist/server/chunk-6OSNCH4F.js.map +1 -0
  46. package/dist/server/{chunk-TKMA6D6U.js → chunk-7UPVCT3K.js} +1215 -497
  47. package/dist/server/chunk-7UPVCT3K.js.map +1 -0
  48. package/dist/server/{chunk-7DS4Q3GA.mjs → chunk-AEFWG657.mjs} +3 -3
  49. package/dist/server/chunk-AEFWG657.mjs.map +1 -0
  50. package/dist/server/{chunk-USQF2XTU.mjs → chunk-BYBJA6SP.mjs} +26 -11
  51. package/dist/server/chunk-BYBJA6SP.mjs.map +1 -0
  52. package/dist/server/{chunk-ZEAJW6T3.mjs → chunk-C6FIJC7T.mjs} +4 -3
  53. package/dist/server/chunk-C6FIJC7T.mjs.map +1 -0
  54. package/dist/server/{chunk-TO7FD6TQ.js → chunk-I2D7KOEA.js} +4 -4
  55. package/dist/server/{chunk-TO7FD6TQ.js.map → chunk-I2D7KOEA.js.map} +1 -1
  56. package/dist/server/chunk-KFLZGNPO.mjs +189 -0
  57. package/dist/server/chunk-KFLZGNPO.mjs.map +1 -0
  58. package/dist/server/chunk-L5EA4FXU.mjs +134 -0
  59. package/dist/server/chunk-L5EA4FXU.mjs.map +1 -0
  60. package/dist/server/{chunk-TNRADRPH.mjs → chunk-LNOUXALA.mjs} +1137 -419
  61. package/dist/server/chunk-LNOUXALA.mjs.map +1 -0
  62. package/dist/server/{chunk-SPXMMX3C.mjs → chunk-OSF34JTQ.mjs} +4 -4
  63. package/dist/server/{chunk-SWPHIUVE.js → chunk-P3NNN73G.js} +5 -4
  64. package/dist/server/chunk-P3NNN73G.js.map +1 -0
  65. package/dist/server/{chunk-I6K5REFT.mjs → chunk-P4K63SBZ.mjs} +24 -4
  66. package/dist/server/chunk-P4K63SBZ.mjs.map +1 -0
  67. package/dist/server/{chunk-HOY77YBF.js → chunk-RVDS7VSP.js} +5 -5
  68. package/dist/server/chunk-RVDS7VSP.js.map +1 -0
  69. package/dist/server/{chunk-NW5KHH4A.js → chunk-TT5JWA4X.js} +9 -9
  70. package/dist/server/{chunk-NW5KHH4A.js.map → chunk-TT5JWA4X.js.map} +1 -1
  71. package/dist/server/chunk-VSFQRHYZ.js +134 -0
  72. package/dist/server/chunk-VSFQRHYZ.js.map +1 -0
  73. package/dist/server/{chunk-EGTDJ4PL.js → chunk-YYO3RIFO.js} +26 -11
  74. package/dist/server/chunk-YYO3RIFO.js.map +1 -0
  75. package/dist/server/{chunk-OP2GHK27.mjs → chunk-Z5ZA6Q4D.mjs} +2 -2
  76. package/dist/server/{components-D1Z2mSDr.d.ts → components-CU46ZkAv.d.mts} +20 -75
  77. package/dist/server/{components-CY8jDQjv.d.mts → components-DvozDwRN.d.ts} +20 -75
  78. package/dist/server/components.d.mts +11 -8
  79. package/dist/server/components.d.ts +11 -8
  80. package/dist/server/components.js +5 -4
  81. package/dist/server/components.js.map +1 -1
  82. package/dist/server/components.mjs +4 -3
  83. package/dist/server/config-validation.d.mts +3 -3
  84. package/dist/server/config-validation.d.ts +3 -3
  85. package/dist/server/config-validation.js +9 -5
  86. package/dist/server/config-validation.js.map +1 -1
  87. package/dist/server/config-validation.mjs +8 -4
  88. package/dist/server/config.d.mts +243 -5
  89. package/dist/server/config.d.ts +243 -5
  90. package/dist/server/config.js +72 -5
  91. package/dist/server/config.js.map +1 -1
  92. package/dist/server/config.mjs +72 -5
  93. package/dist/server/config.mjs.map +1 -1
  94. package/dist/server/core-DsNWrl3o.d.mts +44 -0
  95. package/dist/server/core-DsNWrl3o.d.ts +44 -0
  96. package/dist/server/data.d.mts +4 -3
  97. package/dist/server/data.d.ts +4 -3
  98. package/dist/server/data.js +3 -3
  99. package/dist/server/data.mjs +2 -2
  100. package/dist/server/{index-DCIz9Ptv.d.ts → index-CJfMXZQr.d.ts} +2 -1
  101. package/dist/server/{index-DFQwtj3J.d.mts → index-Q7RLMAQ6.d.mts} +2 -1
  102. package/dist/server/index.d.mts +63 -6
  103. package/dist/server/index.d.ts +63 -6
  104. package/dist/server/index.js +91 -2
  105. package/dist/server/index.js.map +1 -1
  106. package/dist/server/index.mjs +90 -1
  107. package/dist/server/index.mjs.map +1 -1
  108. package/dist/server/link-DjxLyC82.d.mts +23 -0
  109. package/dist/server/link-DjxLyC82.d.ts +23 -0
  110. package/dist/server/{loadContent-CWuE8FCx.d.mts → loadContent-DgpSKWqY.d.mts} +4 -4
  111. package/dist/server/{loadContent-DynBuR5f.d.ts → loadContent-GPvUI1bN.d.ts} +4 -4
  112. package/dist/server/{loadPage-B8RmlYgV.d.mts → loadPage-DGnIK7s4.d.mts} +17 -47
  113. package/dist/server/loadPage-DNQTTRHL.mjs +11 -0
  114. package/dist/server/{loadPage-BTkKpizX.d.ts → loadPage-DW9WB-u9.d.ts} +17 -47
  115. package/dist/server/loadPage-IDGVDFBB.js +11 -0
  116. package/dist/server/{loadPage-DUHBXDEW.js.map → loadPage-IDGVDFBB.js.map} +1 -1
  117. package/dist/server/metadata.d.mts +6 -4
  118. package/dist/server/metadata.d.ts +6 -4
  119. package/dist/server/navigation.d.mts +199 -29
  120. package/dist/server/navigation.d.ts +199 -29
  121. package/dist/server/navigation.js +27 -43
  122. package/dist/server/navigation.js.map +1 -1
  123. package/dist/server/navigation.mjs +20 -36
  124. package/dist/server/navigation.mjs.map +1 -1
  125. package/dist/server/rendering/server.d.mts +8 -6
  126. package/dist/server/rendering/server.d.ts +8 -6
  127. package/dist/server/rendering/server.js +7 -6
  128. package/dist/server/rendering/server.js.map +1 -1
  129. package/dist/server/rendering/server.mjs +6 -5
  130. package/dist/server/rendering.d.mts +14 -10
  131. package/dist/server/rendering.d.ts +14 -10
  132. package/dist/server/rendering.js +9 -8
  133. package/dist/server/rendering.js.map +1 -1
  134. package/dist/server/rendering.mjs +8 -7
  135. package/dist/server/richTextSchema-DURiozvD.d.mts +62 -0
  136. package/dist/server/richTextSchema-DURiozvD.d.ts +62 -0
  137. package/dist/server/routing.d.mts +178 -11
  138. package/dist/server/routing.d.ts +178 -11
  139. package/dist/server/routing.js +95 -2
  140. package/dist/server/routing.js.map +1 -1
  141. package/dist/server/routing.mjs +94 -1
  142. package/dist/server/routing.mjs.map +1 -1
  143. package/dist/server/{schema-Bpy9N5ZI.d.ts → schema-Z6-afHJG.d.mts} +1 -1
  144. package/dist/server/{schema-Bpy9N5ZI.d.mts → schema-Z6-afHJG.d.ts} +1 -1
  145. package/dist/server/server.d.mts +9 -7
  146. package/dist/server/server.d.ts +9 -7
  147. package/dist/server/server.js +6 -6
  148. package/dist/server/server.mjs +5 -5
  149. package/dist/server/theme-bridge.js +8 -8
  150. package/dist/server/theme-bridge.mjs +2 -2
  151. package/dist/server/{types-oCM-fw4O.d.ts → types-0f4PIlgx.d.mts} +55 -2
  152. package/dist/server/{types-txWsSxN7.d.mts → types-BjgZt8xJ.d.mts} +63 -2
  153. package/dist/server/{types-BiRZnxDx.d.ts → types-C28kMfa1.d.ts} +256 -82
  154. package/dist/server/{types-CL916r6x.d.ts → types-DLBhEPSt.d.ts} +63 -2
  155. package/dist/server/{types-CdrJqlKx.d.mts → types-DuzJZKJI.d.mts} +256 -82
  156. package/dist/server/{types-DkKEctWn.d.mts → types-kOQyCFXO.d.ts} +55 -2
  157. package/dist/server/{validation-DzvDwwRo.d.mts → validation-BGuRo8P1.d.mts} +18 -5
  158. package/dist/server/{validation-CoU8uAiu.d.ts → validation-DU2YE7u5.d.ts} +18 -5
  159. package/package.json +5 -3
  160. package/dist/server/chunk-6JBKKV3G.js.map +0 -1
  161. package/dist/server/chunk-7BOIO2S7.mjs +0 -833
  162. package/dist/server/chunk-7BOIO2S7.mjs.map +0 -1
  163. package/dist/server/chunk-7DS4Q3GA.mjs.map +0 -1
  164. package/dist/server/chunk-BLKVTULP.js +0 -833
  165. package/dist/server/chunk-BLKVTULP.js.map +0 -1
  166. package/dist/server/chunk-EGTDJ4PL.js.map +0 -1
  167. package/dist/server/chunk-HOY77YBF.js.map +0 -1
  168. package/dist/server/chunk-I6K5REFT.mjs.map +0 -1
  169. package/dist/server/chunk-N3PX76AP.mjs.map +0 -1
  170. package/dist/server/chunk-R5B6IOFQ.js.map +0 -1
  171. package/dist/server/chunk-SWPHIUVE.js.map +0 -1
  172. package/dist/server/chunk-TKMA6D6U.js.map +0 -1
  173. package/dist/server/chunk-TNRADRPH.mjs.map +0 -1
  174. package/dist/server/chunk-USQF2XTU.mjs.map +0 -1
  175. package/dist/server/chunk-ZEAJW6T3.mjs.map +0 -1
  176. package/dist/server/loadPage-DUHBXDEW.js +0 -11
  177. package/dist/server/loadPage-LYVKY3WZ.mjs +0 -11
  178. /package/dist/server/{chunk-SPXMMX3C.mjs.map → chunk-OSF34JTQ.mjs.map} +0 -0
  179. /package/dist/server/{chunk-OP2GHK27.mjs.map → chunk-Z5ZA6Q4D.mjs.map} +0 -0
  180. /package/dist/server/{loadPage-LYVKY3WZ.mjs.map → loadPage-DNQTTRHL.mjs.map} +0 -0
@@ -1,33 +1,115 @@
1
- import { N as NavigationMenuWithItems } from './types-CdrJqlKx.mjs';
2
- export { L as LinkPayload, a as NavigationItemRecord } from './types-CdrJqlKx.mjs';
1
+ import { N as NavigationMenuWithItems } from './types-DuzJZKJI.mjs';
2
+ export { L as LinkPayload, a as NavigationItemRecord } from './types-DuzJZKJI.mjs';
3
+ import { R as RouteMap } from './core-DsNWrl3o.mjs';
4
+ import './schema-Z6-afHJG.mjs';
3
5
  import '@riverbankcms/ai';
4
- import './schema-Bpy9N5ZI.mjs';
5
6
  import 'zod';
7
+ import './link-DjxLyC82.mjs';
6
8
  import '@riverbankcms/media-storage-supabase';
7
9
  import '@riverbankcms/db';
8
10
 
9
11
  /**
10
12
  * Navigation helper utilities for SDK sites.
11
13
  *
12
- * Provides simple helpers to transform CMS navigation data into
13
- * render-ready NavItem arrays.
14
+ * Provides helpers to transform CMS navigation data into render-ready structures.
15
+ * Supports both simple NavItem arrays and full MenuViewModels for block rendering.
14
16
  *
15
- * @example
17
+ * @example Simple usage
16
18
  * ```ts
17
- * import { getPrimaryNavItems, getNavItemsBySlug } from '@riverbankcms/sdk/navigation';
19
+ * import { getPrimaryNavItems } from '@riverbankcms/sdk/navigation';
18
20
  *
19
- * // Get header navigation (primary menu)
20
21
  * const headerNav = getPrimaryNavItems(siteData.navigation);
22
+ * // [{ href: '/', label: 'Home', isExternal: false }, ...]
23
+ * ```
21
24
  *
22
- * // Get footer navigation by slug
23
- * const footerNav = getNavItemsBySlug(siteData.navigation, 'footer');
25
+ * @example Block rendering usage
26
+ * ```ts
27
+ * import { buildMenuViewModel, buildLogoViewModel } from '@riverbankcms/sdk/navigation';
28
+ *
29
+ * const menu = buildMenuViewModel(siteData.navigation);
30
+ * const logo = buildLogoViewModel(siteData.layout.logo, siteData.site.title);
24
31
  *
25
- * // Result: [{ href: '/', label: 'Home', isExternal: false }, ...]
32
+ * renderBlock(siteHeaderManifest, layout.header, {
33
+ * viewModelOverrides: { menu, content: { logo } },
34
+ * });
26
35
  * ```
27
36
  *
28
37
  * @packageDocumentation
29
38
  */
30
39
 
40
+ /**
41
+ * Link value types matching @riverbankcms/blocks
42
+ */
43
+ type InternalLinkValue = {
44
+ kind: 'internal';
45
+ routeId: string;
46
+ entityId: string;
47
+ entityType: 'page' | 'content';
48
+ href: string;
49
+ title: string;
50
+ typeLabel: string;
51
+ contentTypeKey?: string | null;
52
+ contentTypeName?: string | null;
53
+ updatedAt?: string | null;
54
+ };
55
+ type ExternalLinkValue = {
56
+ kind: 'external';
57
+ href: string;
58
+ };
59
+ type CustomLinkValue = {
60
+ kind: 'url';
61
+ href: string;
62
+ };
63
+ type LinkValue = InternalLinkValue | ExternalLinkValue | CustomLinkValue;
64
+ /**
65
+ * Menu link view model for block rendering
66
+ */
67
+ type MenuLinkViewModel = {
68
+ id: string;
69
+ label: string;
70
+ link: LinkValue | null;
71
+ target: string | null;
72
+ rel: string | null;
73
+ active?: boolean;
74
+ };
75
+ /**
76
+ * CTA link view model (extends MenuLinkViewModel with variant)
77
+ */
78
+ type MenuCtaViewModel = MenuLinkViewModel & {
79
+ variant: string;
80
+ };
81
+ /**
82
+ * Complete menu view model for header/footer blocks
83
+ */
84
+ type MenuViewModel = {
85
+ items: MenuLinkViewModel[];
86
+ ctaItem: MenuCtaViewModel | null;
87
+ };
88
+ /**
89
+ * Logo source data from site layout
90
+ */
91
+ type LogoSource = {
92
+ url: string | null;
93
+ alt: string | null;
94
+ assetId?: string | null;
95
+ width?: number | null;
96
+ height?: number | null;
97
+ storagePath?: string | null;
98
+ storageBucket?: string | null;
99
+ } | null;
100
+ /**
101
+ * Logo view model for block rendering
102
+ */
103
+ type LogoViewModel = {
104
+ type: 'image';
105
+ src: string;
106
+ alt: string;
107
+ assetId?: string;
108
+ width?: number | null;
109
+ height?: number | null;
110
+ storagePath?: string;
111
+ storageBucket?: string;
112
+ } | null;
31
113
  /**
32
114
  * A simplified navigation item structure for component rendering.
33
115
  */
@@ -39,6 +121,53 @@ type NavItem = {
39
121
  /** Whether link should open in new tab (external links) */
40
122
  isExternal: boolean;
41
123
  };
124
+ /**
125
+ * Simple nav link with pre-resolved href for block rendering.
126
+ */
127
+ type SimpleNavLink = {
128
+ id: string;
129
+ label: string;
130
+ href: string;
131
+ isExternal: boolean;
132
+ };
133
+ /**
134
+ * Simple menu view model with pre-resolved hrefs.
135
+ * Use this instead of MenuViewModel for cleaner data flow.
136
+ */
137
+ type SimpleMenuViewModel = {
138
+ items: SimpleNavLink[];
139
+ ctaItem: SimpleNavLink | null;
140
+ };
141
+ /**
142
+ * Simple logo data for block rendering.
143
+ */
144
+ type SimpleLogo = {
145
+ type: 'image';
146
+ src: string;
147
+ alt: string;
148
+ width?: number;
149
+ height?: number;
150
+ } | null;
151
+ /**
152
+ * Get the primary navigation menu object.
153
+ * Returns menu marked as isPrimary, or first menu if none marked.
154
+ *
155
+ * @example
156
+ * ```ts
157
+ * const menu = getPrimaryNavigation(siteData.navigation);
158
+ * console.log(menu?.title); // "Main Navigation"
159
+ * ```
160
+ */
161
+ declare function getPrimaryNavigation(navigation: NavigationMenuWithItems[]): NavigationMenuWithItems | null;
162
+ /**
163
+ * Get a navigation menu by name/slug.
164
+ *
165
+ * @example
166
+ * ```ts
167
+ * const footerMenu = getNavigationBySlug(siteData.navigation, 'footer');
168
+ * ```
169
+ */
170
+ declare function getNavigationBySlug(navigation: NavigationMenuWithItems[], slug: string): NavigationMenuWithItems | null;
42
171
  /**
43
172
  * Get nav items from the primary menu (marked isPrimary, or first menu).
44
173
  * Returns empty array if no navigation configured.
@@ -62,39 +191,80 @@ declare function getPrimaryNavItems(navigation: NavigationMenuWithItems[]): NavI
62
191
  */
63
192
  declare function getNavItemsBySlug(navigation: NavigationMenuWithItems[], slug: string): NavItem[];
64
193
  /**
65
- * Get the primary navigation menu object.
66
- * Returns menu marked as isPrimary, or first menu if none marked.
194
+ * Transform a menu into simple NavItem array.
195
+ */
196
+ declare function transformToNavItems(menu: NavigationMenuWithItems | null): NavItem[];
197
+ /**
198
+ * Build a MenuViewModel from navigation data for block rendering.
199
+ * Extracts CTA item separately and preserves full link data.
67
200
  *
68
201
  * @example
69
202
  * ```ts
70
- * const menu = getPrimaryNavigation(siteData.navigation);
71
- * console.log(menu?.title); // "Main Navigation"
72
- * console.log(menu?.slug); // "main"
203
+ * const menuViewModel = buildMenuViewModel(siteData.navigation);
204
+ *
205
+ * renderBlock(siteHeaderManifest, layout.header, {
206
+ * viewModelOverrides: { menu: menuViewModel },
207
+ * });
73
208
  * ```
74
209
  */
75
- declare function getPrimaryNavigation(navigation: NavigationMenuWithItems[]): NavigationMenuWithItems | null;
210
+ declare function buildMenuViewModel(navigation: NavigationMenuWithItems[]): MenuViewModel;
76
211
  /**
77
- * Get a navigation menu by name.
212
+ * Build a LogoViewModel from site layout data.
213
+ *
214
+ * @param logo - Logo source from siteData.layout.logo
215
+ * @param fallbackTitle - Site title to use as alt text fallback
78
216
  *
79
217
  * @example
80
218
  * ```ts
81
- * const footerMenu = getNavigationBySlug(siteData.navigation, 'footer');
219
+ * const logoViewModel = buildLogoViewModel(siteData.layout.logo, siteData.site.title);
220
+ *
221
+ * renderBlock(siteHeaderManifest, layout.header, {
222
+ * viewModelOverrides: { content: { logo: logoViewModel } },
223
+ * });
82
224
  * ```
83
225
  */
84
- declare function getNavigationBySlug(navigation: NavigationMenuWithItems[], slug: string): NavigationMenuWithItems | null;
226
+ declare function buildLogoViewModel(logo: LogoSource, fallbackTitle: string | null | undefined): LogoViewModel;
227
+ /**
228
+ * Build a SimpleMenuViewModel from navigation data with pre-resolved hrefs.
229
+ * Use this instead of buildMenuViewModel for cleaner data flow.
230
+ *
231
+ * @param navigation - Navigation menus from site data
232
+ * @param routes - Route map for resolving internal links
233
+ *
234
+ * @example
235
+ * ```ts
236
+ * const menu = buildSimpleMenu(siteData.navigation, siteData.routes);
237
+ * // { items: [{ id, label, href: '/', isExternal: false }], cta: null }
238
+ * ```
239
+ */
240
+ declare function buildSimpleMenu(navigation: NavigationMenuWithItems[], routes: RouteMap): SimpleMenuViewModel;
85
241
  /**
86
- * Transform a menu into NavItem array.
87
- * - Sorts by orderIndex
88
- * - Resolves link hrefs
89
- * - Identifies external links
90
- * - Filters out items without valid hrefs
242
+ * Build a SimpleLogo from site layout data.
243
+ *
244
+ * @param logo - Logo data from site layout
245
+ * @param fallbackAlt - Fallback alt text (usually site title)
91
246
  *
92
247
  * @example
93
248
  * ```ts
94
- * const menu = getNavigationBySlug(siteData.navigation, 'main');
95
- * const items = transformNavItems(menu);
249
+ * const logo = buildSimpleLogo(siteData.layout.logo, siteData.site.title);
250
+ * // { src: 'https://...', alt: 'Site Name', width: 200, height: 50 }
96
251
  * ```
97
252
  */
98
- declare function transformNavItems(menu: NavigationMenuWithItems | null): NavItem[];
253
+ declare function buildSimpleLogo(logo: {
254
+ url?: string | null;
255
+ alt?: string | null;
256
+ width?: number | null;
257
+ height?: number | null;
258
+ } | null, fallbackAlt: string | null | undefined): SimpleLogo;
259
+ /**
260
+ * @deprecated Use `transformToNavItems` instead.
261
+ * This alias is maintained for backwards compatibility only.
262
+ */
263
+ declare const transformNavItems: typeof transformToNavItems;
264
+ /**
265
+ * @deprecated Use `getPrimaryNavigation` instead.
266
+ * This alias is maintained for backwards compatibility only.
267
+ */
268
+ declare const selectPrimaryMenu: typeof getPrimaryNavigation;
99
269
 
100
- export { type NavItem, NavigationMenuWithItems, getNavItemsBySlug, getNavigationBySlug, getPrimaryNavItems, getPrimaryNavigation, transformNavItems };
270
+ export { type CustomLinkValue, type ExternalLinkValue, type InternalLinkValue, type LinkValue, type LogoSource, type LogoViewModel, type MenuCtaViewModel, type MenuLinkViewModel, type MenuViewModel, type NavItem, NavigationMenuWithItems, type SimpleLogo, type SimpleMenuViewModel, type SimpleNavLink, buildLogoViewModel, buildMenuViewModel, buildSimpleLogo, buildSimpleMenu, getNavItemsBySlug, getNavigationBySlug, getPrimaryNavItems, getPrimaryNavigation, selectPrimaryMenu, transformNavItems, transformToNavItems };
@@ -1,33 +1,115 @@
1
- import { N as NavigationMenuWithItems } from './types-BiRZnxDx.js';
2
- export { L as LinkPayload, a as NavigationItemRecord } from './types-BiRZnxDx.js';
1
+ import { N as NavigationMenuWithItems } from './types-C28kMfa1.js';
2
+ export { L as LinkPayload, a as NavigationItemRecord } from './types-C28kMfa1.js';
3
+ import { R as RouteMap } from './core-DsNWrl3o.js';
4
+ import './schema-Z6-afHJG.js';
3
5
  import '@riverbankcms/ai';
4
- import './schema-Bpy9N5ZI.js';
5
6
  import 'zod';
7
+ import './link-DjxLyC82.js';
6
8
  import '@riverbankcms/media-storage-supabase';
7
9
  import '@riverbankcms/db';
8
10
 
9
11
  /**
10
12
  * Navigation helper utilities for SDK sites.
11
13
  *
12
- * Provides simple helpers to transform CMS navigation data into
13
- * render-ready NavItem arrays.
14
+ * Provides helpers to transform CMS navigation data into render-ready structures.
15
+ * Supports both simple NavItem arrays and full MenuViewModels for block rendering.
14
16
  *
15
- * @example
17
+ * @example Simple usage
16
18
  * ```ts
17
- * import { getPrimaryNavItems, getNavItemsBySlug } from '@riverbankcms/sdk/navigation';
19
+ * import { getPrimaryNavItems } from '@riverbankcms/sdk/navigation';
18
20
  *
19
- * // Get header navigation (primary menu)
20
21
  * const headerNav = getPrimaryNavItems(siteData.navigation);
22
+ * // [{ href: '/', label: 'Home', isExternal: false }, ...]
23
+ * ```
21
24
  *
22
- * // Get footer navigation by slug
23
- * const footerNav = getNavItemsBySlug(siteData.navigation, 'footer');
25
+ * @example Block rendering usage
26
+ * ```ts
27
+ * import { buildMenuViewModel, buildLogoViewModel } from '@riverbankcms/sdk/navigation';
28
+ *
29
+ * const menu = buildMenuViewModel(siteData.navigation);
30
+ * const logo = buildLogoViewModel(siteData.layout.logo, siteData.site.title);
24
31
  *
25
- * // Result: [{ href: '/', label: 'Home', isExternal: false }, ...]
32
+ * renderBlock(siteHeaderManifest, layout.header, {
33
+ * viewModelOverrides: { menu, content: { logo } },
34
+ * });
26
35
  * ```
27
36
  *
28
37
  * @packageDocumentation
29
38
  */
30
39
 
40
+ /**
41
+ * Link value types matching @riverbankcms/blocks
42
+ */
43
+ type InternalLinkValue = {
44
+ kind: 'internal';
45
+ routeId: string;
46
+ entityId: string;
47
+ entityType: 'page' | 'content';
48
+ href: string;
49
+ title: string;
50
+ typeLabel: string;
51
+ contentTypeKey?: string | null;
52
+ contentTypeName?: string | null;
53
+ updatedAt?: string | null;
54
+ };
55
+ type ExternalLinkValue = {
56
+ kind: 'external';
57
+ href: string;
58
+ };
59
+ type CustomLinkValue = {
60
+ kind: 'url';
61
+ href: string;
62
+ };
63
+ type LinkValue = InternalLinkValue | ExternalLinkValue | CustomLinkValue;
64
+ /**
65
+ * Menu link view model for block rendering
66
+ */
67
+ type MenuLinkViewModel = {
68
+ id: string;
69
+ label: string;
70
+ link: LinkValue | null;
71
+ target: string | null;
72
+ rel: string | null;
73
+ active?: boolean;
74
+ };
75
+ /**
76
+ * CTA link view model (extends MenuLinkViewModel with variant)
77
+ */
78
+ type MenuCtaViewModel = MenuLinkViewModel & {
79
+ variant: string;
80
+ };
81
+ /**
82
+ * Complete menu view model for header/footer blocks
83
+ */
84
+ type MenuViewModel = {
85
+ items: MenuLinkViewModel[];
86
+ ctaItem: MenuCtaViewModel | null;
87
+ };
88
+ /**
89
+ * Logo source data from site layout
90
+ */
91
+ type LogoSource = {
92
+ url: string | null;
93
+ alt: string | null;
94
+ assetId?: string | null;
95
+ width?: number | null;
96
+ height?: number | null;
97
+ storagePath?: string | null;
98
+ storageBucket?: string | null;
99
+ } | null;
100
+ /**
101
+ * Logo view model for block rendering
102
+ */
103
+ type LogoViewModel = {
104
+ type: 'image';
105
+ src: string;
106
+ alt: string;
107
+ assetId?: string;
108
+ width?: number | null;
109
+ height?: number | null;
110
+ storagePath?: string;
111
+ storageBucket?: string;
112
+ } | null;
31
113
  /**
32
114
  * A simplified navigation item structure for component rendering.
33
115
  */
@@ -39,6 +121,53 @@ type NavItem = {
39
121
  /** Whether link should open in new tab (external links) */
40
122
  isExternal: boolean;
41
123
  };
124
+ /**
125
+ * Simple nav link with pre-resolved href for block rendering.
126
+ */
127
+ type SimpleNavLink = {
128
+ id: string;
129
+ label: string;
130
+ href: string;
131
+ isExternal: boolean;
132
+ };
133
+ /**
134
+ * Simple menu view model with pre-resolved hrefs.
135
+ * Use this instead of MenuViewModel for cleaner data flow.
136
+ */
137
+ type SimpleMenuViewModel = {
138
+ items: SimpleNavLink[];
139
+ ctaItem: SimpleNavLink | null;
140
+ };
141
+ /**
142
+ * Simple logo data for block rendering.
143
+ */
144
+ type SimpleLogo = {
145
+ type: 'image';
146
+ src: string;
147
+ alt: string;
148
+ width?: number;
149
+ height?: number;
150
+ } | null;
151
+ /**
152
+ * Get the primary navigation menu object.
153
+ * Returns menu marked as isPrimary, or first menu if none marked.
154
+ *
155
+ * @example
156
+ * ```ts
157
+ * const menu = getPrimaryNavigation(siteData.navigation);
158
+ * console.log(menu?.title); // "Main Navigation"
159
+ * ```
160
+ */
161
+ declare function getPrimaryNavigation(navigation: NavigationMenuWithItems[]): NavigationMenuWithItems | null;
162
+ /**
163
+ * Get a navigation menu by name/slug.
164
+ *
165
+ * @example
166
+ * ```ts
167
+ * const footerMenu = getNavigationBySlug(siteData.navigation, 'footer');
168
+ * ```
169
+ */
170
+ declare function getNavigationBySlug(navigation: NavigationMenuWithItems[], slug: string): NavigationMenuWithItems | null;
42
171
  /**
43
172
  * Get nav items from the primary menu (marked isPrimary, or first menu).
44
173
  * Returns empty array if no navigation configured.
@@ -62,39 +191,80 @@ declare function getPrimaryNavItems(navigation: NavigationMenuWithItems[]): NavI
62
191
  */
63
192
  declare function getNavItemsBySlug(navigation: NavigationMenuWithItems[], slug: string): NavItem[];
64
193
  /**
65
- * Get the primary navigation menu object.
66
- * Returns menu marked as isPrimary, or first menu if none marked.
194
+ * Transform a menu into simple NavItem array.
195
+ */
196
+ declare function transformToNavItems(menu: NavigationMenuWithItems | null): NavItem[];
197
+ /**
198
+ * Build a MenuViewModel from navigation data for block rendering.
199
+ * Extracts CTA item separately and preserves full link data.
67
200
  *
68
201
  * @example
69
202
  * ```ts
70
- * const menu = getPrimaryNavigation(siteData.navigation);
71
- * console.log(menu?.title); // "Main Navigation"
72
- * console.log(menu?.slug); // "main"
203
+ * const menuViewModel = buildMenuViewModel(siteData.navigation);
204
+ *
205
+ * renderBlock(siteHeaderManifest, layout.header, {
206
+ * viewModelOverrides: { menu: menuViewModel },
207
+ * });
73
208
  * ```
74
209
  */
75
- declare function getPrimaryNavigation(navigation: NavigationMenuWithItems[]): NavigationMenuWithItems | null;
210
+ declare function buildMenuViewModel(navigation: NavigationMenuWithItems[]): MenuViewModel;
76
211
  /**
77
- * Get a navigation menu by name.
212
+ * Build a LogoViewModel from site layout data.
213
+ *
214
+ * @param logo - Logo source from siteData.layout.logo
215
+ * @param fallbackTitle - Site title to use as alt text fallback
78
216
  *
79
217
  * @example
80
218
  * ```ts
81
- * const footerMenu = getNavigationBySlug(siteData.navigation, 'footer');
219
+ * const logoViewModel = buildLogoViewModel(siteData.layout.logo, siteData.site.title);
220
+ *
221
+ * renderBlock(siteHeaderManifest, layout.header, {
222
+ * viewModelOverrides: { content: { logo: logoViewModel } },
223
+ * });
82
224
  * ```
83
225
  */
84
- declare function getNavigationBySlug(navigation: NavigationMenuWithItems[], slug: string): NavigationMenuWithItems | null;
226
+ declare function buildLogoViewModel(logo: LogoSource, fallbackTitle: string | null | undefined): LogoViewModel;
227
+ /**
228
+ * Build a SimpleMenuViewModel from navigation data with pre-resolved hrefs.
229
+ * Use this instead of buildMenuViewModel for cleaner data flow.
230
+ *
231
+ * @param navigation - Navigation menus from site data
232
+ * @param routes - Route map for resolving internal links
233
+ *
234
+ * @example
235
+ * ```ts
236
+ * const menu = buildSimpleMenu(siteData.navigation, siteData.routes);
237
+ * // { items: [{ id, label, href: '/', isExternal: false }], cta: null }
238
+ * ```
239
+ */
240
+ declare function buildSimpleMenu(navigation: NavigationMenuWithItems[], routes: RouteMap): SimpleMenuViewModel;
85
241
  /**
86
- * Transform a menu into NavItem array.
87
- * - Sorts by orderIndex
88
- * - Resolves link hrefs
89
- * - Identifies external links
90
- * - Filters out items without valid hrefs
242
+ * Build a SimpleLogo from site layout data.
243
+ *
244
+ * @param logo - Logo data from site layout
245
+ * @param fallbackAlt - Fallback alt text (usually site title)
91
246
  *
92
247
  * @example
93
248
  * ```ts
94
- * const menu = getNavigationBySlug(siteData.navigation, 'main');
95
- * const items = transformNavItems(menu);
249
+ * const logo = buildSimpleLogo(siteData.layout.logo, siteData.site.title);
250
+ * // { src: 'https://...', alt: 'Site Name', width: 200, height: 50 }
96
251
  * ```
97
252
  */
98
- declare function transformNavItems(menu: NavigationMenuWithItems | null): NavItem[];
253
+ declare function buildSimpleLogo(logo: {
254
+ url?: string | null;
255
+ alt?: string | null;
256
+ width?: number | null;
257
+ height?: number | null;
258
+ } | null, fallbackAlt: string | null | undefined): SimpleLogo;
259
+ /**
260
+ * @deprecated Use `transformToNavItems` instead.
261
+ * This alias is maintained for backwards compatibility only.
262
+ */
263
+ declare const transformNavItems: typeof transformToNavItems;
264
+ /**
265
+ * @deprecated Use `getPrimaryNavigation` instead.
266
+ * This alias is maintained for backwards compatibility only.
267
+ */
268
+ declare const selectPrimaryMenu: typeof getPrimaryNavigation;
99
269
 
100
- export { type NavItem, NavigationMenuWithItems, getNavItemsBySlug, getNavigationBySlug, getPrimaryNavItems, getPrimaryNavigation, transformNavItems };
270
+ export { type CustomLinkValue, type ExternalLinkValue, type InternalLinkValue, type LinkValue, type LogoSource, type LogoViewModel, type MenuCtaViewModel, type MenuLinkViewModel, type MenuViewModel, type NavItem, NavigationMenuWithItems, type SimpleLogo, type SimpleMenuViewModel, type SimpleNavLink, buildLogoViewModel, buildMenuViewModel, buildSimpleLogo, buildSimpleMenu, getNavItemsBySlug, getNavigationBySlug, getPrimaryNavItems, getPrimaryNavigation, selectPrimaryMenu, transformNavItems, transformToNavItems };
@@ -1,44 +1,28 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }require('./chunk-DGUM43GV.js');
2
-
3
- // src/navigation/index.ts
4
- function getPrimaryNavItems(navigation) {
5
- return transformNavItems(getPrimaryNavigation(navigation));
6
- }
7
- function getNavItemsBySlug(navigation, slug) {
8
- return transformNavItems(getNavigationBySlug(navigation, slug));
9
- }
10
- function getPrimaryNavigation(navigation) {
11
- if (!navigation || navigation.length === 0) return null;
12
- return _nullishCoalesce(navigation.find((menu) => menu.isPrimary), () => ( navigation[0]));
13
- }
14
- function getNavigationBySlug(navigation, slug) {
15
- if (!navigation || navigation.length === 0) return null;
16
- return _nullishCoalesce(navigation.find((menu) => menu.name === slug), () => ( null));
17
- }
18
- function transformNavItems(menu) {
19
- if (!_optionalChain([menu, 'optionalAccess', _ => _.items]) || menu.items.length === 0) return [];
20
- const items = menu.items;
21
- return items.slice().sort((a, b) => (_nullishCoalesce(a.orderIndex, () => ( 0))) - (_nullishCoalesce(b.orderIndex, () => ( 0)))).map((item) => ({
22
- label: item.label,
23
- href: resolveItemHref(item),
24
- isExternal: isExternalLink(item)
25
- })).filter((item) => Boolean(item.href));
26
- }
27
- function resolveItemHref(item) {
28
- const link = item.url;
29
- if (!link || typeof link !== "object" || !("href" in link)) return "";
30
- return link.href;
31
- }
32
- function isExternalLink(item) {
33
- const link = item.url;
34
- if (!link || typeof link !== "object" || !("kind" in link)) return false;
35
- return link.kind === "external";
36
- }
37
-
38
-
39
-
40
-
41
-
42
-
43
- exports.getNavItemsBySlug = getNavItemsBySlug; exports.getNavigationBySlug = getNavigationBySlug; exports.getPrimaryNavItems = getPrimaryNavItems; exports.getPrimaryNavigation = getPrimaryNavigation; exports.transformNavItems = transformNavItems;
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
+
13
+ var _chunk5STV4MWDjs = require('./chunk-5STV4MWD.js');
14
+ require('./chunk-DGUM43GV.js');
15
+
16
+
17
+
18
+
19
+
20
+
21
+
22
+
23
+
24
+
25
+
26
+
27
+ exports.buildLogoViewModel = _chunk5STV4MWDjs.buildLogoViewModel; exports.buildMenuViewModel = _chunk5STV4MWDjs.buildMenuViewModel; exports.buildSimpleLogo = _chunk5STV4MWDjs.buildSimpleLogo; exports.buildSimpleMenu = _chunk5STV4MWDjs.buildSimpleMenu; exports.getNavItemsBySlug = _chunk5STV4MWDjs.getNavItemsBySlug; exports.getNavigationBySlug = _chunk5STV4MWDjs.getNavigationBySlug; exports.getPrimaryNavItems = _chunk5STV4MWDjs.getPrimaryNavItems; exports.getPrimaryNavigation = _chunk5STV4MWDjs.getPrimaryNavigation; exports.selectPrimaryMenu = _chunk5STV4MWDjs.selectPrimaryMenu; exports.transformNavItems = _chunk5STV4MWDjs.transformNavItems; exports.transformToNavItems = _chunk5STV4MWDjs.transformToNavItems;
44
28
  //# sourceMappingURL=navigation.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/will/Projects/Business/cms/builder/packages/sdk/dist/server/navigation.js","../../src/navigation/index.ts"],"names":[],"mappings":"AAAA,gtBAA4B;AAC5B;AACA;ACgDO,SAAS,kBAAA,CAAmB,UAAA,EAAkD;AACnF,EAAA,OAAO,iBAAA,CAAkB,oBAAA,CAAqB,UAAU,CAAC,CAAA;AAC3D;AAYO,SAAS,iBAAA,CAAkB,UAAA,EAAuC,IAAA,EAAyB;AAChG,EAAA,OAAO,iBAAA,CAAkB,mBAAA,CAAoB,UAAA,EAAY,IAAI,CAAC,CAAA;AAChE;AAiBO,SAAS,oBAAA,CACd,UAAA,EACgC;AAChC,EAAA,GAAA,CAAI,CAAC,WAAA,GAAc,UAAA,CAAW,OAAA,IAAW,CAAA,EAAG,OAAO,IAAA;AACnD,EAAA,wBAAO,UAAA,CAAW,IAAA,CAAK,CAAC,IAAA,EAAA,GAAS,IAAA,CAAK,SAAS,CAAA,UAAK,UAAA,CAAW,CAAC,GAAA;AAClE;AAUO,SAAS,mBAAA,CACd,UAAA,EACA,IAAA,EACgC;AAChC,EAAA,GAAA,CAAI,CAAC,WAAA,GAAc,UAAA,CAAW,OAAA,IAAW,CAAA,EAAG,OAAO,IAAA;AAEnD,EAAA,wBAAO,UAAA,CAAW,IAAA,CAAK,CAAC,IAAA,EAAA,GAAS,IAAA,CAAK,KAAA,IAAS,IAAI,CAAA,UAAK,MAAA;AAC1D;AAeO,SAAS,iBAAA,CAAkB,IAAA,EAAiD;AACjF,EAAA,GAAA,CAAI,iBAAC,IAAA,2BAAM,QAAA,GAAS,IAAA,CAAK,KAAA,CAAM,OAAA,IAAW,CAAA,EAAG,OAAO,CAAC,CAAA;AAErD,EAAA,MAAM,MAAA,EAAgC,IAAA,CAAK,KAAA;AAE3C,EAAA,OAAO,KAAA,CACJ,KAAA,CAAM,CAAA,CACN,IAAA,CAAK,CAAC,CAAA,EAAyB,CAAA,EAAA,GAAA,kBAA6B,CAAA,CAAE,UAAA,UAAc,GAAA,EAAA,EAAA,kBAAM,CAAA,CAAE,UAAA,UAAc,GAAA,CAAE,CAAA,CACpG,GAAA,CAAI,CAAC,IAAA,EAAA,GAAA,CAAgC;AAAA,IACpC,KAAA,EAAO,IAAA,CAAK,KAAA;AAAA,IACZ,IAAA,EAAM,eAAA,CAAgB,IAAI,CAAA;AAAA,IAC1B,UAAA,EAAY,cAAA,CAAe,IAAI;AAAA,EACjC,CAAA,CAAE,CAAA,CACD,MAAA,CAAO,CAAC,IAAA,EAAA,GAA0B,OAAA,CAAQ,IAAA,CAAK,IAAI,CAAC,CAAA;AACzD;AAWA,SAAS,eAAA,CAAgB,IAAA,EAAoC;AAE3D,EAAA,MAAM,KAAA,EAAO,IAAA,CAAK,GAAA;AAClB,EAAA,GAAA,CAAI,CAAC,KAAA,GAAQ,OAAO,KAAA,IAAS,SAAA,GAAY,CAAA,CAAE,OAAA,GAAU,IAAA,CAAA,EAAO,OAAO,EAAA;AACnE,EAAA,OAAO,IAAA,CAAK,IAAA;AACd;AAMA,SAAS,cAAA,CAAe,IAAA,EAAqC;AAC3D,EAAA,MAAM,KAAA,EAAO,IAAA,CAAK,GAAA;AAClB,EAAA,GAAA,CAAI,CAAC,KAAA,GAAQ,OAAO,KAAA,IAAS,SAAA,GAAY,CAAA,CAAE,OAAA,GAAU,IAAA,CAAA,EAAO,OAAO,KAAA;AACnE,EAAA,OAAO,IAAA,CAAK,KAAA,IAAS,UAAA;AACvB;AD5HA;AACE;AACA;AACA;AACA;AACA;AACF,sPAAC","file":"/Users/will/Projects/Business/cms/builder/packages/sdk/dist/server/navigation.js","sourcesContent":[null,"/**\n * Navigation helper utilities for SDK sites.\n *\n * Provides simple helpers to transform CMS navigation data into\n * render-ready NavItem arrays.\n *\n * @example\n * ```ts\n * import { getPrimaryNavItems, getNavItemsBySlug } from '@riverbankcms/sdk/navigation';\n *\n * // Get header navigation (primary menu)\n * const headerNav = getPrimaryNavItems(siteData.navigation);\n *\n * // Get footer navigation by slug\n * const footerNav = getNavItemsBySlug(siteData.navigation, 'footer');\n *\n * // Result: [{ href: '/', label: 'Home', isExternal: false }, ...]\n * ```\n *\n * @packageDocumentation\n */\n\nimport type { NavigationMenuWithItems, NavigationItemRecord, LinkPayload } from '@riverbankcms/api';\n\n/**\n * A simplified navigation item structure for component rendering.\n */\nexport type NavItem = {\n /** The URL to navigate to */\n href: string;\n /** Display text for the navigation link */\n label: string;\n /** Whether link should open in new tab (external links) */\n isExternal: boolean;\n};\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Primary API: Simple one-liner helpers\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Get nav items from the primary menu (marked isPrimary, or first menu).\n * Returns empty array if no navigation configured.\n *\n * @example\n * ```ts\n * const headerNav = getPrimaryNavItems(siteData.navigation);\n * // [{ href: '/', label: 'Home', isExternal: false }, ...]\n * ```\n */\nexport function getPrimaryNavItems(navigation: NavigationMenuWithItems[]): NavItem[] {\n return transformNavItems(getPrimaryNavigation(navigation));\n}\n\n/**\n * Get nav items from a specific menu by slug.\n * Useful for footer nav, secondary nav, etc.\n * Returns empty array if menu not found.\n *\n * @example\n * ```ts\n * const footerNav = getNavItemsBySlug(siteData.navigation, 'footer');\n * ```\n */\nexport function getNavItemsBySlug(navigation: NavigationMenuWithItems[], slug: string): NavItem[] {\n return transformNavItems(getNavigationBySlug(navigation, slug));\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Building blocks for advanced use cases\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Get the primary navigation menu object.\n * Returns menu marked as isPrimary, or first menu if none marked.\n *\n * @example\n * ```ts\n * const menu = getPrimaryNavigation(siteData.navigation);\n * console.log(menu?.title); // \"Main Navigation\"\n * console.log(menu?.slug); // \"main\"\n * ```\n */\nexport function getPrimaryNavigation(\n navigation: NavigationMenuWithItems[],\n): NavigationMenuWithItems | null {\n if (!navigation || navigation.length === 0) return null;\n return navigation.find((menu) => menu.isPrimary) ?? navigation[0];\n}\n\n/**\n * Get a navigation menu by name.\n *\n * @example\n * ```ts\n * const footerMenu = getNavigationBySlug(siteData.navigation, 'footer');\n * ```\n */\nexport function getNavigationBySlug(\n navigation: NavigationMenuWithItems[],\n slug: string,\n): NavigationMenuWithItems | null {\n if (!navigation || navigation.length === 0) return null;\n // Match by name (the database field) - function is named \"slug\" for API simplicity\n return navigation.find((menu) => menu.name === slug) ?? null;\n}\n\n/**\n * Transform a menu into NavItem array.\n * - Sorts by orderIndex\n * - Resolves link hrefs\n * - Identifies external links\n * - Filters out items without valid hrefs\n *\n * @example\n * ```ts\n * const menu = getNavigationBySlug(siteData.navigation, 'main');\n * const items = transformNavItems(menu);\n * ```\n */\nexport function transformNavItems(menu: NavigationMenuWithItems | null): NavItem[] {\n if (!menu?.items || menu.items.length === 0) return [];\n\n const items: NavigationItemRecord[] = menu.items;\n\n return items\n .slice()\n .sort((a: NavigationItemRecord, b: NavigationItemRecord) => (a.orderIndex ?? 0) - (b.orderIndex ?? 0))\n .map((item: NavigationItemRecord) => ({\n label: item.label,\n href: resolveItemHref(item),\n isExternal: isExternalLink(item),\n }))\n .filter((item): item is NavItem => Boolean(item.href));\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Internal helpers\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Extracts the href from a navigation item's url field.\n * The `url` field is a JSON column containing link data with { kind, href, ... } structure.\n * Gracefully returns empty string for malformed or missing link data.\n */\nfunction resolveItemHref(item: NavigationItemRecord): string {\n // The database field is `url` (JSON) which gets camelized to `url`\n const link = item.url as LinkPayload | null | undefined;\n if (!link || typeof link !== 'object' || !('href' in link)) return '';\n return link.href;\n}\n\n/**\n * Determines if a navigation item's link is external.\n * External links (kind: 'external') should typically open in a new tab.\n */\nfunction isExternalLink(item: NavigationItemRecord): boolean {\n const link = item.url as LinkPayload | null | undefined;\n if (!link || typeof link !== 'object' || !('kind' in link)) return false;\n return link.kind === 'external';\n}\n\n// Re-export types for convenience\nexport type { NavigationMenuWithItems, NavigationItemRecord, LinkPayload } from '@riverbankcms/api';\n"]}
1
+ {"version":3,"sources":["/Users/will/Projects/Business/cms/builder/packages/sdk/dist/server/navigation.js"],"names":[],"mappings":"AAAA;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,sDAA4B;AAC5B,+BAA4B;AAC5B;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,2sBAAC","file":"/Users/will/Projects/Business/cms/builder/packages/sdk/dist/server/navigation.js"}