@riverbankcms/sdk 0.5.3 → 0.6.1
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 +239 -0
- package/dist/cli/index.js +22 -5
- package/dist/cli/index.js.map +1 -1
- package/dist/client/client.js +1 -1
- package/dist/client/client.js.map +1 -1
- package/dist/client/client.mjs +1 -1
- package/dist/client/client.mjs.map +1 -1
- package/dist/server/{Layout-BClXUTsd.d.mts → Layout-B7cvis7r.d.mts} +3 -3
- package/dist/server/{Layout-UXGjXv8M.d.ts → Layout-wBtJLTVX.d.ts} +3 -3
- package/dist/server/{chunk-VSFQRHYZ.js → chunk-3B364WO2.js} +4 -4
- package/dist/server/chunk-3B364WO2.js.map +1 -0
- package/dist/server/{chunk-5STV4MWD.js → chunk-EIVISR62.js} +112 -27
- package/dist/server/chunk-EIVISR62.js.map +1 -0
- package/dist/server/{chunk-X4STRF2V.mjs → chunk-I7ZR2WO3.mjs} +2 -2
- package/dist/server/{chunk-X4STRF2V.mjs.map → chunk-I7ZR2WO3.mjs.map} +1 -1
- package/dist/server/{chunk-ZSKOHNE7.js → chunk-IVHIQFJH.js} +2 -2
- package/dist/server/{chunk-ZSKOHNE7.js.map → chunk-IVHIQFJH.js.map} +1 -1
- package/dist/server/{chunk-L5EA4FXU.mjs → chunk-XXFF4RVR.mjs} +6 -6
- package/dist/server/chunk-XXFF4RVR.mjs.map +1 -0
- package/dist/server/{chunk-KFLZGNPO.mjs → chunk-YXA4GAAQ.mjs} +113 -28
- package/dist/server/chunk-YXA4GAAQ.mjs.map +1 -0
- package/dist/server/{components-DppHY5oD.d.ts → components-CICSJyp_.d.ts} +1 -1
- package/dist/server/{components-BmaJxgCV.d.mts → components-CMMwDXTW.d.mts} +1 -1
- package/dist/server/components.d.mts +2 -2
- package/dist/server/components.d.ts +2 -2
- package/dist/server/components.js +3 -3
- package/dist/server/components.mjs +2 -2
- package/dist/server/index.js +2 -2
- package/dist/server/index.mjs +1 -1
- package/dist/server/navigation.d.mts +138 -57
- package/dist/server/navigation.d.ts +138 -57
- package/dist/server/navigation.js +6 -2
- package/dist/server/navigation.js.map +1 -1
- package/dist/server/navigation.mjs +9 -5
- package/dist/server/rendering/server.d.mts +1 -1
- package/dist/server/rendering/server.d.ts +1 -1
- package/dist/server/rendering/server.js +3 -3
- package/dist/server/rendering/server.mjs +2 -2
- package/dist/server/rendering.d.mts +3 -3
- package/dist/server/rendering.d.ts +3 -3
- package/dist/server/rendering.js +3 -3
- package/dist/server/rendering.mjs +2 -2
- package/dist/server/server.js +2 -2
- package/dist/server/server.mjs +1 -1
- package/package.json +1 -1
- package/dist/server/chunk-5STV4MWD.js.map +0 -1
- package/dist/server/chunk-KFLZGNPO.mjs.map +0 -1
- package/dist/server/chunk-L5EA4FXU.mjs.map +0 -1
- package/dist/server/chunk-VSFQRHYZ.js.map +0 -1
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import {
|
|
2
|
+
import { buildMenu, buildLogo } from './navigation.mjs';
|
|
3
3
|
import { S as SiteResponse, R as RiverbankClient } from './types-1cLz0vnq.mjs';
|
|
4
4
|
|
|
5
5
|
type HeaderData = {
|
|
6
|
-
menu: ReturnType<typeof
|
|
7
|
-
logo: ReturnType<typeof
|
|
6
|
+
menu: ReturnType<typeof buildMenu>;
|
|
7
|
+
logo: ReturnType<typeof buildLogo>;
|
|
8
8
|
site: SiteResponse['site'];
|
|
9
9
|
theme: SiteResponse['theme'];
|
|
10
10
|
routes: SiteResponse['routes'];
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import {
|
|
2
|
+
import { buildMenu, buildLogo } from './navigation.js';
|
|
3
3
|
import { S as SiteResponse, R as RiverbankClient } from './types-BvcJU7zk.js';
|
|
4
4
|
|
|
5
5
|
type HeaderData = {
|
|
6
|
-
menu: ReturnType<typeof
|
|
7
|
-
logo: ReturnType<typeof
|
|
6
|
+
menu: ReturnType<typeof buildMenu>;
|
|
7
|
+
logo: ReturnType<typeof buildLogo>;
|
|
8
8
|
site: SiteResponse['site'];
|
|
9
9
|
theme: SiteResponse['theme'];
|
|
10
10
|
routes: SiteResponse['routes'];
|
|
@@ -1,7 +1,7 @@
|
|
|
1
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; }
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
var
|
|
4
|
+
var _chunkEIVISR62js = require('./chunk-EIVISR62.js');
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
|
|
@@ -80,8 +80,8 @@ async function Layout({
|
|
|
80
80
|
}
|
|
81
81
|
const { site, theme, navigation, layout, routes } = siteData;
|
|
82
82
|
const themeRuntime = _chunk7UPVCT3Kjs.buildThemeRuntime.call(void 0, theme);
|
|
83
|
-
const menuViewModel =
|
|
84
|
-
const logoViewModel =
|
|
83
|
+
const menuViewModel = _chunkEIVISR62js.buildMenu.call(void 0, navigation, routes);
|
|
84
|
+
const logoViewModel = _chunkEIVISR62js.buildLogo.call(void 0, _nullishCoalesce(layout.logo, () => ( null)), site.title);
|
|
85
85
|
const headerData = {
|
|
86
86
|
menu: menuViewModel,
|
|
87
87
|
logo: logoViewModel,
|
|
@@ -131,4 +131,4 @@ async function Layout({
|
|
|
131
131
|
|
|
132
132
|
|
|
133
133
|
exports.Page = Page; exports.Layout = Layout;
|
|
134
|
-
//# sourceMappingURL=chunk-
|
|
134
|
+
//# sourceMappingURL=chunk-3B364WO2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/will/Projects/Business/cms/builder/packages/sdk/dist/server/chunk-3B364WO2.js","../../src/rendering/components/Page.tsx","../../src/rendering/components/Layout.tsx"],"names":[],"mappings":"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","file":"/Users/will/Projects/Business/cms/builder/packages/sdk/dist/server/chunk-3B364WO2.js","sourcesContent":[null,"/**\n * Pure Page renderer component for Riverbank CMS.\n *\n * This component expects all data to be provided via props.\n * For data fetching, use:\n * - Server-side: `await loadPage({ client, siteId, path })`\n * - Client-side: `usePage({ client, siteId, path })`\n */\n\nimport { PageRenderer, buildThemeRuntime } from '@riverbankcms/blocks';\nimport type { PageOutline, RouteMap, Theme, ThemeTokens, BlockOverrides, OccurrenceContextData } from '@riverbankcms/blocks';\nimport type { ResolvedBlockData } from '../../data';\nimport type { RuntimeSdkConfig } from '../helpers/loadPage';\n\n// Re-export OccurrenceContextData for SDK consumers\nexport type { OccurrenceContextData };\n\nexport type PageProps = {\n // Required data (must be provided by caller)\n page: PageOutline;\n theme: Theme;\n siteId: string;\n\n // Optional data\n themeTokens?: ThemeTokens; // If not provided, will be built from theme\n resolvedData?: ResolvedBlockData; // Pre-fetched block data\n routeMap?: RouteMap;\n /**\n * SDK site configuration containing theme palette overrides.\n * When provided, the SDK palette tokens are merged into the theme tokens,\n * allowing blocks to use SDK-defined color tokens for section backgrounds.\n */\n sdkConfig?: RuntimeSdkConfig | null;\n /**\n * Supabase storage URL for direct image access.\n * SDK sites receive this from the API instead of requiring NEXT_PUBLIC_SUPABASE_URL env var.\n */\n supabaseUrl?: string;\n\n /**\n * Additional context data for content entry pages.\n * Used to pass occurrence context and content entry data to blocks.\n */\n dataContext?: {\n /** Occurrence context for event pages (from URL like /events/yoga/2025-01-15) */\n occurrenceContext?: OccurrenceContextData | null;\n /** Content entry data for template pages */\n contentEntry?: Record<string, unknown> | null;\n };\n\n // Customization\n wrapBlock?: (blockId: string, rendered: React.ReactNode) => React.ReactNode;\n registry?: Parameters<typeof PageRenderer>[0]['registry'];\n usePlaceholders?: boolean;\n /**\n * Custom components to override default block rendering.\n * Keys can be full block kind (\"block.hero\") or short form (\"hero\").\n *\n * This is SSR-safe - no context or hooks required.\n *\n * @example\n * ```tsx\n * <Page\n * {...pageData}\n * blockOverrides={{\n * 'hero': MyCustomHero,\n * 'block.testimonials': MyCustomTestimonials,\n * }}\n * />\n * ```\n */\n blockOverrides?: BlockOverrides;\n};\n\n/**\n * Pure renderer for Riverbank CMS pages.\n *\n * This component expects all data to be provided via props.\n * For data fetching, use:\n * - Server-side: `await loadPage({ client, siteId, path })`\n * - Client-side: `usePage({ client, siteId, path })`\n *\n * @example Server-side (Next.js App Router)\n * ```tsx\n * import { createRiverbankClient } from '@riverbankcms/sdk';\n * import { loadPage, Page } from '@riverbankcms/sdk/rendering';\n *\n * const client = createRiverbankClient({ apiKey, baseUrl });\n *\n * export default async function PageRoute({ params }) {\n * const pageData = await loadPage({\n * client,\n * siteId: 'site-id',\n * path: `/${params.slug}`,\n * });\n *\n * return <Page {...pageData} />;\n * }\n * ```\n *\n * @example Client-side\n * ```tsx\n * import { createRiverbankClient } from '@riverbankcms/sdk';\n * import { usePage, Page } from '@riverbankcms/sdk/rendering';\n *\n * const client = createRiverbankClient({ apiKey, baseUrl });\n *\n * function MyPage({ path }) {\n * const pageData = usePage({ client, siteId: 'site-id', path });\n *\n * if (pageData.loading) return <LoadingState />;\n * if (pageData.error) return <ErrorState error={pageData.error} />;\n * if (!pageData.page) return <NotFound />;\n *\n * return <Page {...pageData} />;\n * }\n * ```\n */\nexport function Page({\n page,\n theme,\n themeTokens: providedTokens,\n siteId,\n resolvedData,\n routeMap,\n wrapBlock,\n registry,\n usePlaceholders = false,\n blockOverrides,\n sdkConfig,\n supabaseUrl,\n dataContext,\n}: PageProps) {\n // Build theme tokens if not provided\n const baseTokens = providedTokens ?? buildThemeRuntime(theme).tokens;\n\n // Merge SDK palette tokens into theme tokens\n // This allows blocks to resolve SDK-defined color tokens (e.g., 'primary' -> '#6d28d9')\n const themeTokens = sdkConfig?.theme?.palette\n ? { ...baseTokens, palette: { ...baseTokens.palette, ...sdkConfig.theme.palette } }\n : baseTokens;\n\n return (\n <PageRenderer\n theme={theme}\n page={page}\n themeTokens={themeTokens}\n usePlaceholders={usePlaceholders}\n dataContext={{\n siteId,\n resolvedData,\n routes: routeMap,\n occurrenceContext: dataContext?.occurrenceContext ?? null,\n contentEntry: dataContext?.contentEntry ?? null,\n supabaseUrl,\n }}\n routeMap={routeMap}\n wrapBlock={wrapBlock}\n registry={registry}\n blockOverrides={blockOverrides}\n sdkConfig={sdkConfig}\n />\n );\n}\n","/**\n * Layout component with header and footer\n *\n * Renders site header and footer around content. Fetches site data if not provided.\n */\n\nimport { renderBlock, siteFooterManifest, siteHeaderManifest, buildThemeRuntime } from '@riverbankcms/blocks';\nimport { buildMenu, buildLogo } from '../../navigation';\nimport type { RiverbankClient, SiteResponse } from '../../client/types';\n\nexport type HeaderData = {\n menu: ReturnType<typeof buildMenu>;\n logo: ReturnType<typeof buildLogo>;\n site: SiteResponse['site'];\n theme: SiteResponse['theme'];\n routes: SiteResponse['routes'];\n};\n\nexport type LayoutProps = {\n // Option 1: Pass pre-fetched site data\n siteData?: SiteResponse;\n\n // Option 2: Fetch site data (provide client + identifier)\n client?: RiverbankClient;\n siteId?: string;\n slug?: string;\n domain?: string;\n\n // Content\n children: React.ReactNode;\n\n // Control rendering\n header?: boolean | ((data: HeaderData) => React.ReactNode);\n footer?: boolean;\n\n // Header variant override (if using default header)\n headerVariant?: 'classic' | 'centered' | 'transparent' | 'floating' | 'editorial';\n};\n\n/**\n * Layout component that wraps content with site header and footer.\n *\n * @example With pre-fetched site data (recommended)\n * ```tsx\n * const site = await client.getSite({ slug: 'my-site' });\n *\n * <Layout siteData={site}>\n * <Page {...pageData} />\n * </Layout>\n * ```\n *\n * @example With automatic fetching\n * ```tsx\n * <Layout client={client} slug=\"my-site\">\n * <Page {...pageData} />\n * </Layout>\n * ```\n */\nexport async function Layout({\n siteData: providedSiteData,\n client,\n siteId,\n slug,\n domain,\n children,\n header = true,\n footer = true,\n headerVariant,\n}: LayoutProps) {\n // Fetch site data if not provided\n let siteData = providedSiteData;\n if (!siteData) {\n if (!client) {\n throw new Error('Layout: must provide either siteData or client');\n }\n if (!siteId && !slug && !domain) {\n throw new Error('Layout: must provide siteId, slug, or domain when using client');\n }\n\n siteData = await client.getSite({ id: siteId, slug, domain });\n }\n\n const { site, theme, navigation, layout, routes } = siteData;\n const themeRuntime = buildThemeRuntime(theme);\n\n // Build view models for header/footer\n const menuViewModel = buildMenu(navigation, routes);\n const logoViewModel = buildLogo(layout.logo ?? null, site.title);\n\n // Prepare header data for custom headers\n const headerData: HeaderData = {\n menu: menuViewModel,\n logo: logoViewModel,\n site,\n theme,\n routes,\n };\n\n // Override header variant if specified\n const headerContent = headerVariant\n ? { ...layout.header, variant: headerVariant }\n : layout.header;\n\n // Override theme header variant if specified\n const themeWithVariant = headerVariant\n ? {\n ...theme,\n header: { ...theme.header, variant: headerVariant },\n }\n : theme;\n\n const viewModelOverrides = {\n $root: {\n siteId: site.id,\n routes,\n theme: themeWithVariant,\n },\n site,\n menu: menuViewModel,\n content: {\n logo: logoViewModel,\n },\n };\n\n // Render header based on type\n let headerElement: React.ReactNode = null;\n if (header === true) {\n // Default header rendering\n headerElement = renderBlock(siteHeaderManifest, headerContent, {\n theme: themeRuntime.tokens,\n themeConfig: themeWithVariant,\n viewModelOverrides,\n });\n } else if (typeof header === 'function') {\n // Custom header rendering\n headerElement = header(headerData);\n }\n\n return (\n <>\n {headerElement}\n\n {children}\n\n {footer && renderBlock(siteFooterManifest, layout.footer, {\n theme: themeRuntime.tokens,\n themeConfig: theme,\n viewModelOverrides,\n })}\n </>\n );\n}\n"]}
|
|
@@ -1,4 +1,10 @@
|
|
|
1
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; }// src/navigation/index.ts
|
|
2
|
+
function isNavLink(item) {
|
|
3
|
+
return item.kind === "link";
|
|
4
|
+
}
|
|
5
|
+
function isNavDropdown(item) {
|
|
6
|
+
return item.kind === "dropdown";
|
|
7
|
+
}
|
|
2
8
|
function getPrimaryNavigation(navigation) {
|
|
3
9
|
if (!navigation || navigation.length === 0) return null;
|
|
4
10
|
return _nullishCoalesce(_nullishCoalesce(navigation.find((menu) => menu.isPrimary), () => ( navigation[0])), () => ( null));
|
|
@@ -15,11 +21,31 @@ function getNavItemsBySlug(navigation, slug) {
|
|
|
15
21
|
}
|
|
16
22
|
function transformToNavItems(menu) {
|
|
17
23
|
if (!_optionalChain([menu, 'optionalAccess', _ => _.items]) || menu.items.length === 0) return [];
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
24
|
+
const toNavLink = (item) => {
|
|
25
|
+
const href = extractHref(item);
|
|
26
|
+
if (!href) return null;
|
|
27
|
+
return {
|
|
28
|
+
kind: "link",
|
|
29
|
+
id: item.id,
|
|
30
|
+
label: item.label,
|
|
31
|
+
href,
|
|
32
|
+
isExternal: isExternalLink(item)
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
const { items } = buildNestedStructure(
|
|
36
|
+
menu.items,
|
|
37
|
+
{
|
|
38
|
+
toLink: toNavLink,
|
|
39
|
+
createDropdown: (id, label, children) => ({
|
|
40
|
+
kind: "dropdown",
|
|
41
|
+
id,
|
|
42
|
+
label,
|
|
43
|
+
children
|
|
44
|
+
}),
|
|
45
|
+
extractCta: false
|
|
46
|
+
}
|
|
47
|
+
);
|
|
48
|
+
return items;
|
|
23
49
|
}
|
|
24
50
|
function buildMenuViewModel(navigation) {
|
|
25
51
|
const menu = getPrimaryNavigation(navigation);
|
|
@@ -53,12 +79,11 @@ function buildLogoViewModel(logo, fallbackTitle) {
|
|
|
53
79
|
if (!logo.url && !logo.storagePath) {
|
|
54
80
|
return null;
|
|
55
81
|
}
|
|
56
|
-
const alt = logo.alt && logo.alt.trim().length > 0 ? logo.alt : _nullishCoalesce(fallbackTitle, () => ( "Site logo"));
|
|
57
82
|
return {
|
|
58
83
|
type: "image",
|
|
59
84
|
src: _nullishCoalesce(logo.url, () => ( "")),
|
|
60
85
|
// Empty when using storagePath - MediaNode builds direct URL
|
|
61
|
-
alt,
|
|
86
|
+
alt: resolveAltText(logo.alt, fallbackTitle),
|
|
62
87
|
assetId: _nullishCoalesce(logo.assetId, () => ( void 0)),
|
|
63
88
|
width: _nullishCoalesce(logo.width, () => ( void 0)),
|
|
64
89
|
height: _nullishCoalesce(logo.height, () => ( void 0)),
|
|
@@ -66,6 +91,9 @@ function buildLogoViewModel(logo, fallbackTitle) {
|
|
|
66
91
|
storageBucket: _nullishCoalesce(logo.storageBucket, () => ( void 0))
|
|
67
92
|
};
|
|
68
93
|
}
|
|
94
|
+
function resolveAltText(alt, fallback) {
|
|
95
|
+
return alt && alt.trim().length > 0 ? alt : _nullishCoalesce(fallback, () => ( "Site logo"));
|
|
96
|
+
}
|
|
69
97
|
function extractHref(item) {
|
|
70
98
|
const link = item.url;
|
|
71
99
|
if (!link || typeof link !== "object" || !("href" in link)) return "";
|
|
@@ -76,6 +104,56 @@ function isExternalLink(item) {
|
|
|
76
104
|
if (!link || typeof link !== "object" || !("kind" in link)) return false;
|
|
77
105
|
return link.kind === "external";
|
|
78
106
|
}
|
|
107
|
+
function buildChildrenByParentId(items) {
|
|
108
|
+
const childrenByParentId = /* @__PURE__ */ new Map();
|
|
109
|
+
const itemsById = /* @__PURE__ */ new Map();
|
|
110
|
+
for (const item of items) {
|
|
111
|
+
itemsById.set(item.id, item);
|
|
112
|
+
}
|
|
113
|
+
for (const item of items) {
|
|
114
|
+
if (item.parentId) {
|
|
115
|
+
const parent = itemsById.get(item.parentId);
|
|
116
|
+
if (_optionalChain([parent, 'optionalAccess', _2 => _2.parentId]) && typeof process !== "undefined" && process.env.NODE_ENV !== "production") {
|
|
117
|
+
console.warn(
|
|
118
|
+
`[SDK Navigation] Deeply nested item detected: "${item.label}" (id: ${item.id}). Only 1 level of nesting is supported. This item will be ignored.`
|
|
119
|
+
);
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
const siblings = _nullishCoalesce(childrenByParentId.get(item.parentId), () => ( []));
|
|
123
|
+
siblings.push(item);
|
|
124
|
+
childrenByParentId.set(item.parentId, siblings);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return childrenByParentId;
|
|
128
|
+
}
|
|
129
|
+
function buildNestedStructure(items, options) {
|
|
130
|
+
const childrenByParentId = buildChildrenByParentId(items);
|
|
131
|
+
const rootItems = items.filter((item) => !item.parentId).sort((a, b) => (_nullishCoalesce(a.orderIndex, () => ( 0))) - (_nullishCoalesce(b.orderIndex, () => ( 0))));
|
|
132
|
+
const result = [];
|
|
133
|
+
let ctaItem = null;
|
|
134
|
+
for (const item of rootItems) {
|
|
135
|
+
if (options.extractCta && !ctaItem && Boolean(item.isCta) && item.urlType !== "dropdown") {
|
|
136
|
+
const link = options.toLink(item);
|
|
137
|
+
if (link) {
|
|
138
|
+
ctaItem = link;
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
if (item.urlType === "dropdown") {
|
|
143
|
+
const childRecords = _nullishCoalesce(childrenByParentId.get(item.id), () => ( []));
|
|
144
|
+
const children = childRecords.sort((a, b) => (_nullishCoalesce(a.orderIndex, () => ( 0))) - (_nullishCoalesce(b.orderIndex, () => ( 0)))).map(options.toLink).filter((child) => child !== null);
|
|
145
|
+
if (children.length > 0) {
|
|
146
|
+
result.push(options.createDropdown(item.id, item.label, children));
|
|
147
|
+
}
|
|
148
|
+
} else {
|
|
149
|
+
const link = options.toLink(item);
|
|
150
|
+
if (link) {
|
|
151
|
+
result.push(link);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return { items: result, ctaItem };
|
|
156
|
+
}
|
|
79
157
|
function convertToLinkValue(item) {
|
|
80
158
|
const payload = item.url;
|
|
81
159
|
if (!payload) return null;
|
|
@@ -109,32 +187,38 @@ function convertToLinkValue(item) {
|
|
|
109
187
|
}
|
|
110
188
|
return null;
|
|
111
189
|
}
|
|
112
|
-
function
|
|
190
|
+
function buildMenu(navigation, routes) {
|
|
113
191
|
const menu = getPrimaryNavigation(navigation);
|
|
114
192
|
if (!menu) {
|
|
115
193
|
return { items: [], ctaItem: null };
|
|
116
194
|
}
|
|
117
|
-
const
|
|
118
|
-
const items = [];
|
|
119
|
-
let ctaItem = null;
|
|
120
|
-
for (const item of flatItems) {
|
|
195
|
+
const toNavLink = (item) => {
|
|
121
196
|
const link = item.url;
|
|
122
197
|
const href = resolveHref(link, routes);
|
|
123
|
-
if (!href)
|
|
124
|
-
|
|
198
|
+
if (!href) return null;
|
|
199
|
+
return {
|
|
200
|
+
kind: "link",
|
|
125
201
|
id: item.id,
|
|
126
202
|
label: item.label,
|
|
127
203
|
href,
|
|
128
|
-
isExternal: _optionalChain([link, 'optionalAccess',
|
|
204
|
+
isExternal: _optionalChain([link, 'optionalAccess', _3 => _3.kind]) === "external"
|
|
129
205
|
};
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
206
|
+
};
|
|
207
|
+
return buildNestedStructure(
|
|
208
|
+
menu.items,
|
|
209
|
+
{
|
|
210
|
+
toLink: toNavLink,
|
|
211
|
+
createDropdown: (id, label, children) => ({
|
|
212
|
+
kind: "dropdown",
|
|
213
|
+
id,
|
|
214
|
+
label,
|
|
215
|
+
children
|
|
216
|
+
}),
|
|
217
|
+
extractCta: true
|
|
133
218
|
}
|
|
134
|
-
|
|
135
|
-
}
|
|
136
|
-
return { items, ctaItem };
|
|
219
|
+
);
|
|
137
220
|
}
|
|
221
|
+
var buildSimpleMenu = buildMenu;
|
|
138
222
|
function resolveHref(link, routes) {
|
|
139
223
|
if (!link) return null;
|
|
140
224
|
if (link.kind === "external" || link.kind === "url") {
|
|
@@ -152,11 +236,11 @@ function resolveHref(link, routes) {
|
|
|
152
236
|
}
|
|
153
237
|
return null;
|
|
154
238
|
}
|
|
155
|
-
function
|
|
239
|
+
function buildLogo(logo, fallbackAlt) {
|
|
156
240
|
if (!logo || !logo.url) {
|
|
157
241
|
return null;
|
|
158
242
|
}
|
|
159
|
-
const alt =
|
|
243
|
+
const alt = resolveAltText(logo.alt, fallbackAlt);
|
|
160
244
|
const result = {
|
|
161
245
|
type: "image",
|
|
162
246
|
src: logo.url,
|
|
@@ -170,8 +254,9 @@ function buildSimpleLogo(logo, fallbackAlt) {
|
|
|
170
254
|
}
|
|
171
255
|
return result;
|
|
172
256
|
}
|
|
173
|
-
var
|
|
174
|
-
|
|
257
|
+
var buildSimpleLogo = buildLogo;
|
|
258
|
+
|
|
259
|
+
|
|
175
260
|
|
|
176
261
|
|
|
177
262
|
|
|
@@ -185,5 +270,5 @@ var selectPrimaryMenu = getPrimaryNavigation;
|
|
|
185
270
|
|
|
186
271
|
|
|
187
272
|
|
|
188
|
-
exports.getPrimaryNavigation = getPrimaryNavigation; exports.getNavigationBySlug = getNavigationBySlug; exports.getPrimaryNavItems = getPrimaryNavItems; exports.getNavItemsBySlug = getNavItemsBySlug; exports.transformToNavItems = transformToNavItems; exports.buildMenuViewModel = buildMenuViewModel; exports.buildLogoViewModel = buildLogoViewModel; exports.
|
|
189
|
-
//# sourceMappingURL=chunk-
|
|
273
|
+
exports.isNavLink = isNavLink; exports.isNavDropdown = isNavDropdown; exports.getPrimaryNavigation = getPrimaryNavigation; exports.getNavigationBySlug = getNavigationBySlug; exports.getPrimaryNavItems = getPrimaryNavItems; exports.getNavItemsBySlug = getNavItemsBySlug; exports.transformToNavItems = transformToNavItems; exports.buildMenuViewModel = buildMenuViewModel; exports.buildLogoViewModel = buildLogoViewModel; exports.buildMenu = buildMenu; exports.buildSimpleMenu = buildSimpleMenu; exports.buildLogo = buildLogo; exports.buildSimpleLogo = buildSimpleLogo;
|
|
274
|
+
//# sourceMappingURL=chunk-EIVISR62.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/will/Projects/Business/cms/builder/packages/sdk/dist/server/chunk-EIVISR62.js","../../src/navigation/index.ts"],"names":[],"mappings":"AAAA;ACyLO,SAAS,SAAA,CAAU,IAAA,EAAgC;AACxD,EAAA,OAAO,IAAA,CAAK,KAAA,IAAS,MAAA;AACvB;AAKO,SAAS,aAAA,CAAc,IAAA,EAAoC;AAChE,EAAA,OAAO,IAAA,CAAK,KAAA,IAAS,UAAA;AACvB;AAwEO,SAAS,oBAAA,CACd,UAAA,EACgC;AAChC,EAAA,GAAA,CAAI,CAAC,WAAA,GAAc,UAAA,CAAW,OAAA,IAAW,CAAA,EAAG,OAAO,IAAA;AACnD,EAAA,yCAAO,UAAA,CAAW,IAAA,CAAK,CAAC,IAAA,EAAA,GAAS,IAAA,CAAK,SAAS,CAAA,UAAK,UAAA,CAAW,CAAC,GAAA,UAAK,MAAA;AACvE;AAUO,SAAS,mBAAA,CACd,UAAA,EACA,IAAA,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,KAAA,IAAS,IAAI,CAAA,UAAK,MAAA;AAC1D;AAoBO,SAAS,kBAAA,CAAmB,UAAA,EAAkD;AACnF,EAAA,OAAO,mBAAA,CAAoB,oBAAA,CAAqB,UAAU,CAAC,CAAA;AAC7D;AAWO,SAAS,iBAAA,CAAkB,UAAA,EAAuC,IAAA,EAAyB;AAChG,EAAA,OAAO,mBAAA,CAAoB,mBAAA,CAAoB,UAAA,EAAY,IAAI,CAAC,CAAA;AAClE;AAeO,SAAS,mBAAA,CAAoB,IAAA,EAAiD;AACnF,EAAA,GAAA,CAAI,iBAAC,IAAA,2BAAM,QAAA,GAAS,IAAA,CAAK,KAAA,CAAM,OAAA,IAAW,CAAA,EAAG,OAAO,CAAC,CAAA;AAErD,EAAA,MAAM,UAAA,EAAY,CAAC,IAAA,EAAA,GAA+C;AAChE,IAAA,MAAM,KAAA,EAAO,WAAA,CAAY,IAAI,CAAA;AAC7B,IAAA,GAAA,CAAI,CAAC,IAAA,EAAM,OAAO,IAAA;AAClB,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,MAAA;AAAA,MACN,EAAA,EAAI,IAAA,CAAK,EAAA;AAAA,MACT,KAAA,EAAO,IAAA,CAAK,KAAA;AAAA,MACZ,IAAA;AAAA,MACA,UAAA,EAAY,cAAA,CAAe,IAAI;AAAA,IACjC,CAAA;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,EAAE,MAAM,EAAA,EAAI,oBAAA;AAAA,IAChB,IAAA,CAAK,KAAA;AAAA,IACL;AAAA,MACE,MAAA,EAAQ,SAAA;AAAA,MACR,cAAA,EAAgB,CAAC,EAAA,EAAI,KAAA,EAAO,QAAA,EAAA,GAAA,CAAc;AAAA,QACxC,IAAA,EAAM,UAAA;AAAA,QACN,EAAA;AAAA,QACA,KAAA;AAAA,QACA;AAAA,MACF,CAAA,CAAA;AAAA,MACA,UAAA,EAAY;AAAA,IACd;AAAA,EACF,CAAA;AAEA,EAAA,OAAO,KAAA;AACT;AAmBO,SAAS,kBAAA,CAAmB,UAAA,EAAsD;AACvF,EAAA,MAAM,KAAA,EAAO,oBAAA,CAAqB,UAAU,CAAA;AAE5C,EAAA,GAAA,CAAI,CAAC,IAAA,EAAM;AACT,IAAA,OAAO,EAAE,KAAA,EAAO,CAAC,CAAA,EAAG,OAAA,EAAS,KAAK,CAAA;AAAA,EACpC;AAEA,EAAA,MAAM,UAAA,EAAY,IAAA,CAAK,KAAA,CACpB,MAAA,CAAO,CAAC,IAAA,EAAA,GAAS,CAAC,IAAA,CAAK,SAAA,GAAY,IAAA,CAAK,QAAA,IAAY,UAAU,CAAA,CAC9D,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,EAAA,GAAA,kBAAO,CAAA,CAAE,UAAA,UAAc,GAAA,EAAA,EAAA,kBAAM,CAAA,CAAE,UAAA,UAAc,GAAA,CAAE,CAAA;AAE3D,EAAA,MAAM,MAAA,EAA6B,CAAC,CAAA;AACpC,EAAA,IAAI,QAAA,EAAmC,IAAA;AAEvC,EAAA,IAAA,CAAA,MAAW,KAAA,GAAQ,SAAA,EAAW;AAC5B,IAAA,MAAM,SAAA,EAA8B;AAAA,MAClC,EAAA,EAAI,IAAA,CAAK,EAAA;AAAA,MACT,KAAA,EAAO,IAAA,CAAK,KAAA;AAAA,MACZ,IAAA,EAAM,kBAAA,CAAmB,IAAI,CAAA;AAAA,MAC7B,MAAA,EAAQ,IAAA;AAAA,MACR,GAAA,EAAK,IAAA;AAAA,MACL,MAAA,EAAQ;AAAA,IACV,CAAA;AAGA,IAAA,GAAA,CAAI,CAAC,QAAA,GAAW,OAAA,CAAQ,IAAA,CAAK,KAAK,CAAA,EAAG;AACnC,MAAA,QAAA,EAAU,EAAE,GAAG,QAAA,EAAU,OAAA,EAAS,UAAU,CAAA;AAC5C,MAAA,QAAA;AAAA,IACF;AAEA,IAAA,KAAA,CAAM,IAAA,CAAK,QAAQ,CAAA;AAAA,EACrB;AAEA,EAAA,OAAO,EAAE,KAAA,EAAO,QAAQ,CAAA;AAC1B;AAqBO,SAAS,kBAAA,CACd,IAAA,EACA,aAAA,EACe;AACf,EAAA,GAAA,CAAI,CAAC,IAAA,EAAM;AACT,IAAA,OAAO,IAAA;AAAA,EACT;AAGA,EAAA,GAAA,CAAI,CAAC,IAAA,CAAK,IAAA,GAAO,CAAC,IAAA,CAAK,WAAA,EAAa;AAClC,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,OAAA;AAAA,IACN,GAAA,mBAAK,IAAA,CAAK,GAAA,UAAO,IAAA;AAAA;AAAA,IACjB,GAAA,EAAK,cAAA,CAAe,IAAA,CAAK,GAAA,EAAK,aAAa,CAAA;AAAA,IAC3C,OAAA,mBAAS,IAAA,CAAK,OAAA,UAAW,KAAA,GAAA;AAAA,IACzB,KAAA,mBAAO,IAAA,CAAK,KAAA,UAAS,KAAA,GAAA;AAAA,IACrB,MAAA,mBAAQ,IAAA,CAAK,MAAA,UAAU,KAAA,GAAA;AAAA,IACvB,WAAA,mBAAa,IAAA,CAAK,WAAA,UAAe,KAAA,GAAA;AAAA,IACjC,aAAA,mBAAe,IAAA,CAAK,aAAA,UAAiB,KAAA;AAAA,EACvC,CAAA;AACF;AAWA,SAAS,cAAA,CAAe,GAAA,EAAgC,QAAA,EAA6C;AACnG,EAAA,OAAQ,IAAA,GAAO,GAAA,CAAI,IAAA,CAAK,CAAA,CAAE,OAAA,EAAS,EAAA,EAAK,IAAA,mBAAO,QAAA,UAAY,aAAA;AAC7D;AAKA,SAAS,WAAA,CAAY,IAAA,EAAoC;AACvD,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;AAKA,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;AAOA,SAAS,uBAAA,CACP,KAAA,EACqC;AACrC,EAAA,MAAM,mBAAA,kBAAqB,IAAI,GAAA,CAAoC,CAAA;AACnE,EAAA,MAAM,UAAA,kBAAY,IAAI,GAAA,CAAkC,CAAA;AAGxD,EAAA,IAAA,CAAA,MAAW,KAAA,GAAQ,KAAA,EAAO;AACxB,IAAA,SAAA,CAAU,GAAA,CAAI,IAAA,CAAK,EAAA,EAAI,IAAI,CAAA;AAAA,EAC7B;AAGA,EAAA,IAAA,CAAA,MAAW,KAAA,GAAQ,KAAA,EAAO;AACxB,IAAA,GAAA,CAAI,IAAA,CAAK,QAAA,EAAU;AAEjB,MAAA,MAAM,OAAA,EAAS,SAAA,CAAU,GAAA,CAAI,IAAA,CAAK,QAAQ,CAAA;AAC1C,MAAA,GAAA,iBAAI,MAAA,6BAAQ,WAAA,GAAY,OAAO,QAAA,IAAY,YAAA,GAAe,OAAA,CAAQ,GAAA,CAAI,SAAA,IAAa,YAAA,EAAc;AAC/F,QAAA,OAAA,CAAQ,IAAA;AAAA,UACN,CAAA,+CAAA,EAAkD,IAAA,CAAK,KAAK,CAAA,OAAA,EAAU,IAAA,CAAK,EAAE,CAAA,mEAAA;AAAA,QAE/E,CAAA;AACA,QAAA,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,SAAA,mBAAW,kBAAA,CAAmB,GAAA,CAAI,IAAA,CAAK,QAAQ,CAAA,UAAK,CAAC,GAAA;AAC3D,MAAA,QAAA,CAAS,IAAA,CAAK,IAAI,CAAA;AAClB,MAAA,kBAAA,CAAmB,GAAA,CAAI,IAAA,CAAK,QAAA,EAAU,QAAQ,CAAA;AAAA,IAChD;AAAA,EACF;AAEA,EAAA,OAAO,kBAAA;AACT;AAMA,SAAS,oBAAA,CACP,KAAA,EACA,OAAA,EAQwD;AACxD,EAAA,MAAM,mBAAA,EAAqB,uBAAA,CAAwB,KAAK,CAAA;AAGxD,EAAA,MAAM,UAAA,EAAY,KAAA,CACf,MAAA,CAAO,CAAC,IAAA,EAAA,GAAS,CAAC,IAAA,CAAK,QAAQ,CAAA,CAC/B,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,EAAA,GAAA,kBAAO,CAAA,CAAE,UAAA,UAAc,GAAA,EAAA,EAAA,kBAAM,CAAA,CAAE,UAAA,UAAc,GAAA,CAAE,CAAA;AAE3D,EAAA,MAAM,OAAA,EAAgC,CAAC,CAAA;AACvC,EAAA,IAAI,QAAA,EAAuB,IAAA;AAE3B,EAAA,IAAA,CAAA,MAAW,KAAA,GAAQ,SAAA,EAAW;AAE5B,IAAA,GAAA,CAAI,OAAA,CAAQ,WAAA,GAAc,CAAC,QAAA,GAAW,OAAA,CAAQ,IAAA,CAAK,KAAK,EAAA,GAAK,IAAA,CAAK,QAAA,IAAY,UAAA,EAAY;AACxF,MAAA,MAAM,KAAA,EAAO,OAAA,CAAQ,MAAA,CAAO,IAAI,CAAA;AAChC,MAAA,GAAA,CAAI,IAAA,EAAM;AACR,QAAA,QAAA,EAAU,IAAA;AACV,QAAA,QAAA;AAAA,MACF;AAAA,IACF;AAEA,IAAA,GAAA,CAAI,IAAA,CAAK,QAAA,IAAY,UAAA,EAAY;AAE/B,MAAA,MAAM,aAAA,mBAAe,kBAAA,CAAmB,GAAA,CAAI,IAAA,CAAK,EAAE,CAAA,UAAK,CAAC,GAAA;AACzD,MAAA,MAAM,SAAA,EAAW,YAAA,CACd,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,EAAA,GAAA,kBAAO,CAAA,CAAE,UAAA,UAAc,GAAA,EAAA,EAAA,kBAAM,CAAA,CAAE,UAAA,UAAc,GAAA,CAAE,CAAA,CACxD,GAAA,CAAI,OAAA,CAAQ,MAAM,CAAA,CAClB,MAAA,CAAO,CAAC,KAAA,EAAA,GAA0B,MAAA,IAAU,IAAI,CAAA;AAGnD,MAAA,GAAA,CAAI,QAAA,CAAS,OAAA,EAAS,CAAA,EAAG;AACvB,QAAA,MAAA,CAAO,IAAA,CAAK,OAAA,CAAQ,cAAA,CAAe,IAAA,CAAK,EAAA,EAAI,IAAA,CAAK,KAAA,EAAO,QAAQ,CAAC,CAAA;AAAA,MACnE;AAAA,IACF,EAAA,KAAO;AAEL,MAAA,MAAM,KAAA,EAAO,OAAA,CAAQ,MAAA,CAAO,IAAI,CAAA;AAChC,MAAA,GAAA,CAAI,IAAA,EAAM;AACR,QAAA,MAAA,CAAO,IAAA,CAAK,IAAI,CAAA;AAAA,MAClB;AAAA,IACF;AAAA,EACF;AAEA,EAAA,OAAO,EAAE,KAAA,EAAO,MAAA,EAAQ,QAAQ,CAAA;AAClC;AAKA,SAAS,kBAAA,CAAmB,IAAA,EAA8C;AACxE,EAAA,MAAM,QAAA,EAAU,IAAA,CAAK,GAAA;AACrB,EAAA,GAAA,CAAI,CAAC,OAAA,EAAS,OAAO,IAAA;AAErB,EAAA,MAAM,KAAA,EAAO,OAAO,OAAA,CAAQ,KAAA,IAAS,SAAA,EAAW,OAAA,CAAQ,KAAA,EAAO,IAAA;AAE/D,EAAA,GAAA,CAAI,KAAA,IAAS,WAAA,GAAc,KAAA,IAAS,KAAA,EAAO;AACzC,IAAA,MAAM,KAAA,EAAO,OAAO,OAAA,CAAQ,KAAA,IAAS,SAAA,EAAW,OAAA,CAAQ,KAAA,EAAO,IAAA;AAC/D,IAAA,OAAO,KAAA,EAAO,EAAE,IAAA,EAAM,KAAK,EAAA,EAA2C,IAAA;AAAA,EACxE;AAEA,EAAA,GAAA,CAAI,KAAA,IAAS,UAAA,EAAY;AACvB,IAAA,MAAM,QAAA,EAAU,OAAO,OAAA,CAAQ,QAAA,IAAY,SAAA,EAAW,OAAA,CAAQ,QAAA,EAAU,IAAA;AACxE,IAAA,MAAM,SAAA,EAAW,OAAO,OAAA,CAAQ,SAAA,IAAa,SAAA,EAAW,OAAA,CAAQ,SAAA,EAAW,IAAA;AAC3E,IAAA,MAAM,WAAA,EAAa,OAAA,CAAQ,WAAA,IAAe,OAAA,GAAU,OAAA,CAAQ,WAAA,IAAe,UAAA,EACvE,OAAA,CAAQ,WAAA,EACR,IAAA;AACJ,IAAA,MAAM,KAAA,EAAO,OAAO,OAAA,CAAQ,KAAA,IAAS,SAAA,EAAW,OAAA,CAAQ,KAAA,EAAO,IAAA;AAC/D,IAAA,MAAM,MAAA,EAAQ,OAAO,OAAA,CAAQ,MAAA,IAAU,SAAA,EAAW,OAAA,CAAQ,MAAA,EAAQ,IAAA;AAClE,IAAA,MAAM,UAAA,EAAY,OAAO,OAAA,CAAQ,UAAA,IAAc,SAAA,EAAW,OAAA,CAAQ,UAAA,EAAY,IAAA;AAE9E,IAAA,GAAA,CAAI,CAAC,QAAA,GAAW,CAAC,SAAA,GAAY,CAAC,WAAA,GAAc,CAAC,KAAA,GAAQ,CAAC,MAAA,GAAS,CAAC,SAAA,EAAW;AACzE,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,UAAA;AAAA,MACN,OAAA;AAAA,MACA,QAAA;AAAA,MACA,UAAA;AAAA,MACA,IAAA;AAAA,MACA,KAAA;AAAA,MACA,SAAA;AAAA,MACA,cAAA,EAAgB,OAAO,OAAA,CAAQ,eAAA,IAAmB,SAAA,EAAW,OAAA,CAAQ,eAAA,EAAiB,IAAA;AAAA,MACtF,eAAA,EAAiB,OAAO,OAAA,CAAQ,gBAAA,IAAoB,SAAA,EAAW,OAAA,CAAQ,gBAAA,EAAkB,IAAA;AAAA,MACzF,SAAA,EAAW,OAAO,OAAA,CAAQ,UAAA,IAAc,SAAA,EAAW,OAAA,CAAQ,UAAA,EAAY;AAAA,IACzE,CAAA;AAAA,EACF;AAEA,EAAA,OAAO,IAAA;AACT;AAuBO,SAAS,SAAA,CACd,UAAA,EACA,MAAA,EACM;AACN,EAAA,MAAM,KAAA,EAAO,oBAAA,CAAqB,UAAU,CAAA;AAE5C,EAAA,GAAA,CAAI,CAAC,IAAA,EAAM;AACT,IAAA,OAAO,EAAE,KAAA,EAAO,CAAC,CAAA,EAAG,OAAA,EAAS,KAAK,CAAA;AAAA,EACpC;AAEA,EAAA,MAAM,UAAA,EAAY,CAAC,IAAA,EAAA,GAA+C;AAChE,IAAA,MAAM,KAAA,EAAO,IAAA,CAAK,GAAA;AAClB,IAAA,MAAM,KAAA,EAAO,WAAA,CAAY,IAAA,EAAM,MAAM,CAAA;AACrC,IAAA,GAAA,CAAI,CAAC,IAAA,EAAM,OAAO,IAAA;AAElB,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,MAAA;AAAA,MACN,EAAA,EAAI,IAAA,CAAK,EAAA;AAAA,MACT,KAAA,EAAO,IAAA,CAAK,KAAA;AAAA,MACZ,IAAA;AAAA,MACA,UAAA,kBAAY,IAAA,6BAAM,OAAA,IAAS;AAAA,IAC7B,CAAA;AAAA,EACF,CAAA;AAEA,EAAA,OAAO,oBAAA;AAAA,IACL,IAAA,CAAK,KAAA;AAAA,IACL;AAAA,MACE,MAAA,EAAQ,SAAA;AAAA,MACR,cAAA,EAAgB,CAAC,EAAA,EAAI,KAAA,EAAO,QAAA,EAAA,GAAA,CAAc;AAAA,QACxC,IAAA,EAAM,UAAA;AAAA,QACN,EAAA;AAAA,QACA,KAAA;AAAA,QACA;AAAA,MACF,CAAA,CAAA;AAAA,MACA,UAAA,EAAY;AAAA,IACd;AAAA,EACF,CAAA;AACF;AAGO,IAAM,gBAAA,EAAkB,SAAA;AAM/B,SAAS,WAAA,CAAY,IAAA,EAA0B,MAAA,EAAiC;AAC9E,EAAA,GAAA,CAAI,CAAC,IAAA,EAAM,OAAO,IAAA;AAGlB,EAAA,GAAA,CAAI,IAAA,CAAK,KAAA,IAAS,WAAA,GAAc,IAAA,CAAK,KAAA,IAAS,KAAA,EAAO;AACnD,IAAA,OAAO,IAAA,CAAK,KAAA,GAAQ,IAAA;AAAA,EACtB;AAGA,EAAA,GAAA,CAAI,IAAA,CAAK,KAAA,IAAS,WAAA,GAAc,IAAA,CAAK,OAAA,EAAS;AAC5C,IAAA,MAAM,MAAA,EAAQ,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA;AACjC,IAAA,GAAA,CAAI,KAAA,EAAO;AACT,MAAA,GAAA,CAAI,OAAO,MAAA,IAAU,QAAA,EAAU;AAC7B,QAAA,OAAO,KAAA;AAAA,MACT;AAEA,MAAA,2EAAO,KAAA,CAAM,IAAA,UAAQ,KAAA,CAAM,MAAA,UAAQ,KAAA,CAAM,WAAA,UAAa,IAAA,CAAK,MAAA,UAAQ,MAAA;AAAA,IACrE;AAEA,IAAA,wBAAO,IAAA,CAAK,IAAA,UAAQ,MAAA;AAAA,EACtB;AAEA,EAAA,OAAO,IAAA;AACT;AAcO,SAAS,SAAA,CACd,IAAA,EACA,WAAA,EACM;AACN,EAAA,GAAA,CAAI,CAAC,KAAA,GAAQ,CAAC,IAAA,CAAK,GAAA,EAAK;AACtB,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,MAAM,IAAA,EAAM,cAAA,CAAe,IAAA,CAAK,GAAA,EAAK,WAAW,CAAA;AAEhD,EAAA,MAAM,OAAA,EAA4B;AAAA,IAChC,IAAA,EAAM,OAAA;AAAA,IACN,GAAA,EAAK,IAAA,CAAK,GAAA;AAAA,IACV;AAAA,EACF,CAAA;AAEA,EAAA,GAAA,CAAI,IAAA,CAAK,MAAA,GAAS,IAAA,EAAM;AACtB,IAAA,MAAA,CAAO,MAAA,EAAQ,IAAA,CAAK,KAAA;AAAA,EACtB;AACA,EAAA,GAAA,CAAI,IAAA,CAAK,OAAA,GAAU,IAAA,EAAM;AACvB,IAAA,MAAA,CAAO,OAAA,EAAS,IAAA,CAAK,MAAA;AAAA,EACvB;AAEA,EAAA,OAAO,MAAA;AACT;AAGO,IAAM,gBAAA,EAAkB,SAAA;ADjgB/B;AACA;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,sjBAAC","file":"/Users/will/Projects/Business/cms/builder/packages/sdk/dist/server/chunk-EIVISR62.js","sourcesContent":[null,"/**\n * Navigation helper utilities for SDK sites.\n *\n * Provides helpers to transform CMS navigation data into render-ready structures.\n * All navigation functions return nested structures supporting dropdowns.\n *\n * @example Getting nav items\n * ```ts\n * import { getPrimaryNavItems, isNavLink, isNavDropdown } from '@riverbankcms/sdk/navigation';\n *\n * const headerNav = getPrimaryNavItems(siteData.navigation);\n * headerNav.forEach(item => {\n * if (isNavLink(item)) {\n * console.log(item.href);\n * } else {\n * console.log(`${item.label} has ${item.children.length} children`);\n * }\n * });\n * ```\n *\n * @example Building menu and logo\n * ```ts\n * import { buildMenu, buildLogo } from '@riverbankcms/sdk/navigation';\n *\n * const menu = buildMenu(siteData.navigation, siteData.routes);\n * const logo = buildLogo(siteData.layout.logo, siteData.site.title);\n * ```\n *\n * @packageDocumentation\n */\n\nimport type { NavigationMenuWithItems, NavigationItemRecord, LinkPayload } from '@riverbankcms/api';\nimport type { RouteMap } from '@riverbankcms/blocks';\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Types for block rendering (full LinkValue data)\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Link value types matching @riverbankcms/blocks\n */\nexport type InternalLinkValue = {\n kind: 'internal';\n routeId: string;\n entityId: string;\n entityType: 'page' | 'content';\n href: string;\n title: string;\n typeLabel: string;\n contentTypeKey?: string | null;\n contentTypeName?: string | null;\n updatedAt?: string | null;\n};\n\nexport type ExternalLinkValue = {\n kind: 'external';\n href: string;\n};\n\nexport type CustomLinkValue = {\n kind: 'url';\n href: string;\n};\n\nexport type LinkValue = InternalLinkValue | ExternalLinkValue | CustomLinkValue;\n\n/**\n * Menu link view model for block rendering\n */\nexport type MenuLinkViewModel = {\n id: string;\n label: string;\n link: LinkValue | null;\n target: string | null;\n rel: string | null;\n active?: boolean;\n};\n\n/**\n * CTA link view model (extends MenuLinkViewModel with variant)\n */\nexport type MenuCtaViewModel = MenuLinkViewModel & {\n variant: string;\n};\n\n/**\n * Complete menu view model for header/footer blocks\n */\nexport type MenuViewModel = {\n items: MenuLinkViewModel[];\n ctaItem: MenuCtaViewModel | null;\n};\n\n/**\n * Logo source data from site layout\n */\nexport type LogoSource = {\n url: string | null;\n alt: string | null;\n assetId?: string | null;\n width?: number | null;\n height?: number | null;\n storagePath?: string | null;\n storageBucket?: string | null;\n} | null;\n\n/**\n * Logo view model for block rendering\n */\nexport type LogoViewModel = {\n type: 'image';\n src: string;\n alt: string;\n assetId?: string;\n width?: number | null;\n height?: number | null;\n storagePath?: string;\n storageBucket?: string;\n} | null;\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Navigation Item Types (always nested)\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * A navigation link item with a direct URL.\n * Use `kind` discriminator for type-safe narrowing.\n *\n * @example\n * ```ts\n * if (item.kind === 'link') {\n * console.log(item.href); // TypeScript knows href exists\n * }\n * ```\n */\nexport type NavLink = {\n /** Discriminator for type narrowing */\n kind: 'link';\n /** Unique identifier from CMS */\n id: string;\n /** Display text for the navigation link */\n label: string;\n /** The URL to navigate to */\n href: string;\n /** Whether link should open in new tab (external links) */\n isExternal: boolean;\n};\n\n/**\n * A dropdown container holding child navigation items.\n * Clicking reveals children instead of navigating.\n * Max 1 level of nesting (children are always NavLink, not NavDropdown).\n */\nexport type NavDropdown = {\n /** Discriminator for type narrowing */\n kind: 'dropdown';\n /** Unique identifier from CMS */\n id: string;\n /** Display text for the dropdown trigger */\n label: string;\n /** Child navigation links */\n children: NavLink[];\n};\n\n/**\n * Navigation item - either a link or a dropdown container.\n * Use `kind` property for type-safe discrimination.\n *\n * @example\n * ```ts\n * const items = getPrimaryNavItems(navigation);\n * items.forEach(item => {\n * if (item.kind === 'link') {\n * console.log(item.href);\n * } else {\n * console.log(item.children.length);\n * }\n * });\n * ```\n */\nexport type NavItem = NavLink | NavDropdown;\n\n/**\n * Type guard to check if a navigation item is a link.\n */\nexport function isNavLink(item: NavItem): item is NavLink {\n return item.kind === 'link';\n}\n\n/**\n * Type guard to check if a navigation item is a dropdown.\n */\nexport function isNavDropdown(item: NavItem): item is NavDropdown {\n return item.kind === 'dropdown';\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Menu and Logo types for SDK sites\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Navigation menu with items and optional CTA.\n * Built from CMS navigation data with pre-resolved hrefs.\n *\n * @example\n * ```ts\n * const menu = buildMenu(siteData.navigation, siteData.routes);\n * menu.items.forEach(item => {\n * if (item.kind === 'link') {\n * console.log(item.href);\n * } else {\n * console.log(item.children);\n * }\n * });\n * ```\n */\nexport type Menu = {\n items: NavItem[];\n ctaItem: NavLink | null;\n};\n\n/**\n * Logo data for site rendering.\n *\n * @example\n * ```ts\n * const logo = buildLogo(siteData.layout.logo, siteData.site.title);\n * if (logo) {\n * <img src={logo.src} alt={logo.alt} />\n * }\n * ```\n */\nexport type Logo = {\n type: 'image';\n src: string;\n alt: string;\n width?: number;\n height?: number;\n} | null;\n\n// Legacy type aliases for backwards compatibility\n/** @deprecated Use `NavLink` instead */\nexport type SimpleNavLink = NavLink;\n/** @deprecated Use `NavDropdown` instead */\nexport type SimpleNavDropdown = NavDropdown;\n/** @deprecated Use `NavItem` instead */\nexport type SimpleNavItem = NavItem;\n/** @deprecated Use `Menu` instead */\nexport type SimpleMenuViewModel = Menu;\n/** @deprecated Use `Logo` instead */\nexport type SimpleLogo = Logo;\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Menu selection helpers\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?.name); // \"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] ?? null;\n}\n\n/**\n * Get a navigation menu by name/slug.\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 return navigation.find((menu) => menu.name === slug) ?? null;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// NavItem transformations\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Get nav items from the primary menu (marked isPrimary, or first menu).\n * Returns nested structure supporting both links and dropdowns.\n *\n * @example\n * ```ts\n * const headerNav = getPrimaryNavItems(siteData.navigation);\n * headerNav.forEach(item => {\n * if (item.kind === 'dropdown') {\n * console.log(`${item.label} has ${item.children.length} children`);\n * }\n * });\n * ```\n */\nexport function getPrimaryNavItems(navigation: NavigationMenuWithItems[]): NavItem[] {\n return transformToNavItems(getPrimaryNavigation(navigation));\n}\n\n/**\n * Get nav items from a specific menu by slug.\n * Returns nested structure supporting both links and dropdowns.\n *\n * @example\n * ```ts\n * const footerNav = getNavItemsBySlug(siteData.navigation, 'footer');\n * ```\n */\nexport function getNavItemsBySlug(navigation: NavigationMenuWithItems[], slug: string): NavItem[] {\n return transformToNavItems(getNavigationBySlug(navigation, slug));\n}\n\n/**\n * Transform a menu into NavItem array.\n * Builds nested structure from flat items, supporting dropdowns with children.\n *\n * @example\n * ```ts\n * const nav = transformToNavItems(menu);\n * // [\n * // { kind: 'link', href: '/', label: 'Home', ... },\n * // { kind: 'dropdown', label: 'Services', children: [...] },\n * // ]\n * ```\n */\nexport function transformToNavItems(menu: NavigationMenuWithItems | null): NavItem[] {\n if (!menu?.items || menu.items.length === 0) return [];\n\n const toNavLink = (item: NavigationItemRecord): NavLink | null => {\n const href = extractHref(item);\n if (!href) return null;\n return {\n kind: 'link',\n id: item.id,\n label: item.label,\n href,\n isExternal: isExternalLink(item),\n };\n };\n\n const { items } = buildNestedStructure<NavLink, NavDropdown, NavLink>(\n menu.items,\n {\n toLink: toNavLink,\n createDropdown: (id, label, children) => ({\n kind: 'dropdown',\n id,\n label,\n children,\n }),\n extractCta: false,\n }\n );\n\n return items;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Full MenuViewModel for block rendering\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Build a MenuViewModel from navigation data for block rendering.\n * Extracts CTA item separately and preserves full link data.\n *\n * @example\n * ```ts\n * const menuViewModel = buildMenuViewModel(siteData.navigation);\n *\n * renderBlock(siteHeaderManifest, layout.header, {\n * viewModelOverrides: { menu: menuViewModel },\n * });\n * ```\n */\nexport function buildMenuViewModel(navigation: NavigationMenuWithItems[]): MenuViewModel {\n const menu = getPrimaryNavigation(navigation);\n\n if (!menu) {\n return { items: [], ctaItem: null };\n }\n\n const flatItems = menu.items\n .filter((item) => !item.parentId && item.urlType !== 'dropdown')\n .sort((a, b) => (a.orderIndex ?? 0) - (b.orderIndex ?? 0));\n\n const items: MenuLinkViewModel[] = [];\n let ctaItem: MenuCtaViewModel | null = null;\n\n for (const item of flatItems) {\n const viewItem: MenuLinkViewModel = {\n id: item.id,\n label: item.label,\n link: convertToLinkValue(item),\n target: null,\n rel: null,\n active: false,\n };\n\n // Extract first CTA item separately\n if (!ctaItem && Boolean(item.isCta)) {\n ctaItem = { ...viewItem, variant: 'primary' };\n continue;\n }\n\n items.push(viewItem);\n }\n\n return { items, ctaItem };\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Logo view model helper\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Build a LogoViewModel from site layout data.\n *\n * @param logo - Logo source from siteData.layout.logo\n * @param fallbackTitle - Site title to use as alt text fallback\n *\n * @example\n * ```ts\n * const logoViewModel = buildLogoViewModel(siteData.layout.logo, siteData.site.title);\n *\n * renderBlock(siteHeaderManifest, layout.header, {\n * viewModelOverrides: { content: { logo: logoViewModel } },\n * });\n * ```\n */\nexport function buildLogoViewModel(\n logo: LogoSource,\n fallbackTitle: string | null | undefined,\n): LogoViewModel {\n if (!logo) {\n return null;\n }\n\n // Logo must have storagePath (for direct Supabase URL) or explicit url\n if (!logo.url && !logo.storagePath) {\n return null;\n }\n\n return {\n type: 'image',\n src: logo.url ?? '', // Empty when using storagePath - MediaNode builds direct URL\n alt: resolveAltText(logo.alt, fallbackTitle),\n assetId: logo.assetId ?? undefined,\n width: logo.width ?? undefined,\n height: logo.height ?? undefined,\n storagePath: logo.storagePath ?? undefined,\n storageBucket: logo.storageBucket ?? undefined,\n };\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Internal helpers\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Resolve alt text with fallback.\n * Returns the provided alt if non-empty, otherwise falls back to the provided fallback or 'Site logo'.\n * @internal\n */\nfunction resolveAltText(alt: string | null | undefined, fallback: string | null | undefined): string {\n return (alt && alt.trim().length > 0) ? alt : (fallback ?? 'Site logo');\n}\n\n/**\n * Extracts the href from a navigation item's url field.\n */\nfunction extractHref(item: NavigationItemRecord): string {\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 */\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/**\n * Build a map of children items by parent ID.\n * Also warns about deeply nested items (grandchildren) which CMS shouldn't allow.\n * @internal\n */\nfunction buildChildrenByParentId(\n items: NavigationItemRecord[]\n): Map<string, NavigationItemRecord[]> {\n const childrenByParentId = new Map<string, NavigationItemRecord[]>();\n const itemsById = new Map<string, NavigationItemRecord>();\n\n // First pass: index items by ID\n for (const item of items) {\n itemsById.set(item.id, item);\n }\n\n // Second pass: build children map and warn about deep nesting\n for (const item of items) {\n if (item.parentId) {\n // Check if parent is itself a child (deep nesting)\n const parent = itemsById.get(item.parentId);\n if (parent?.parentId && typeof process !== 'undefined' && process.env.NODE_ENV !== 'production') {\n console.warn(\n `[SDK Navigation] Deeply nested item detected: \"${item.label}\" (id: ${item.id}). ` +\n `Only 1 level of nesting is supported. This item will be ignored.`\n );\n continue; // Skip deeply nested items\n }\n\n const siblings = childrenByParentId.get(item.parentId) ?? [];\n siblings.push(item);\n childrenByParentId.set(item.parentId, siblings);\n }\n }\n\n return childrenByParentId;\n}\n\n/**\n * Generic nested structure builder.\n * @internal\n */\nfunction buildNestedStructure<TLink, TDropdown, TCta extends TLink>(\n items: NavigationItemRecord[],\n options: {\n /** Convert a navigation item record to a link type */\n toLink: (item: NavigationItemRecord) => TLink | null;\n /** Create a dropdown from id, label, and children */\n createDropdown: (id: string, label: string, children: TLink[]) => TDropdown;\n /** Extract CTA from items (return null to skip CTA extraction) */\n extractCta?: boolean;\n }\n): { items: (TLink | TDropdown)[]; ctaItem: TCta | null } {\n const childrenByParentId = buildChildrenByParentId(items);\n\n // Process root items (no parentId) sorted by orderIndex\n const rootItems = items\n .filter((item) => !item.parentId)\n .sort((a, b) => (a.orderIndex ?? 0) - (b.orderIndex ?? 0));\n\n const result: (TLink | TDropdown)[] = [];\n let ctaItem: TCta | null = null;\n\n for (const item of rootItems) {\n // Handle CTA extraction (CTAs are always links, not dropdowns)\n if (options.extractCta && !ctaItem && Boolean(item.isCta) && item.urlType !== 'dropdown') {\n const link = options.toLink(item);\n if (link) {\n ctaItem = link as TCta;\n continue;\n }\n }\n\n if (item.urlType === 'dropdown') {\n // It's a dropdown - gather its children\n const childRecords = childrenByParentId.get(item.id) ?? [];\n const children = childRecords\n .sort((a, b) => (a.orderIndex ?? 0) - (b.orderIndex ?? 0))\n .map(options.toLink)\n .filter((child): child is TLink => child !== null);\n\n // Only include dropdown if it has children\n if (children.length > 0) {\n result.push(options.createDropdown(item.id, item.label, children));\n }\n } else {\n // It's a regular link\n const link = options.toLink(item);\n if (link) {\n result.push(link);\n }\n }\n }\n\n return { items: result, ctaItem };\n}\n\n/**\n * Convert navigation item to LinkValue for block rendering.\n */\nfunction convertToLinkValue(item: NavigationItemRecord): LinkValue | null {\n const payload = item.url as Record<string, unknown> | null;\n if (!payload) return null;\n\n const kind = typeof payload.kind === 'string' ? payload.kind : null;\n\n if (kind === 'external' || kind === 'url') {\n const href = typeof payload.href === 'string' ? payload.href : null;\n return href ? { kind, href } as ExternalLinkValue | CustomLinkValue : null;\n }\n\n if (kind === 'internal') {\n const routeId = typeof payload.routeId === 'string' ? payload.routeId : null;\n const entityId = typeof payload.entityId === 'string' ? payload.entityId : null;\n const entityType = payload.entityType === 'page' || payload.entityType === 'content'\n ? payload.entityType\n : null;\n const href = typeof payload.href === 'string' ? payload.href : null;\n const title = typeof payload.title === 'string' ? payload.title : null;\n const typeLabel = typeof payload.typeLabel === 'string' ? payload.typeLabel : null;\n\n if (!routeId || !entityId || !entityType || !href || !title || !typeLabel) {\n return null;\n }\n\n return {\n kind: 'internal',\n routeId,\n entityId,\n entityType,\n href,\n title,\n typeLabel,\n contentTypeKey: typeof payload.contentTypeKey === 'string' ? payload.contentTypeKey : null,\n contentTypeName: typeof payload.contentTypeName === 'string' ? payload.contentTypeName : null,\n updatedAt: typeof payload.updatedAt === 'string' ? payload.updatedAt : null,\n };\n }\n\n return null;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Menu and Logo builders\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Build a Menu from navigation data with pre-resolved hrefs.\n * Supports dropdown containers with nested children.\n *\n * @param navigation - Navigation menus from site data\n * @param routes - Route map for resolving internal links\n *\n * @example\n * ```ts\n * const menu = buildMenu(siteData.navigation, siteData.routes);\n * menu.items.forEach(item => {\n * if (item.kind === 'dropdown') {\n * console.log(item.children);\n * }\n * });\n * ```\n */\nexport function buildMenu(\n navigation: NavigationMenuWithItems[],\n routes: RouteMap,\n): Menu {\n const menu = getPrimaryNavigation(navigation);\n\n if (!menu) {\n return { items: [], ctaItem: null };\n }\n\n const toNavLink = (item: NavigationItemRecord): NavLink | null => {\n const link = item.url as LinkPayload | null;\n const href = resolveHref(link, routes);\n if (!href) return null;\n\n return {\n kind: 'link',\n id: item.id,\n label: item.label,\n href,\n isExternal: link?.kind === 'external',\n };\n };\n\n return buildNestedStructure<NavLink, NavDropdown, NavLink>(\n menu.items,\n {\n toLink: toNavLink,\n createDropdown: (id, label, children) => ({\n kind: 'dropdown',\n id,\n label,\n children,\n }),\n extractCta: true,\n }\n );\n}\n\n/** @deprecated Use `buildMenu` instead */\nexport const buildSimpleMenu = buildMenu;\n\n/**\n * Resolve href from a link payload using route map.\n * @internal\n */\nfunction resolveHref(link: LinkPayload | null, routes: RouteMap): string | null {\n if (!link) return null;\n\n // External or custom URL links - use href directly\n if (link.kind === 'external' || link.kind === 'url') {\n return link.href || null;\n }\n\n // Internal link - resolve from route map\n if (link.kind === 'internal' && link.routeId) {\n const route = routes[link.routeId];\n if (route) {\n if (typeof route === 'string') {\n return route;\n }\n // Try path first, then href, then draftPath\n return route.path ?? route.href ?? route.draftPath ?? link.href ?? null;\n }\n // Fall back to link.href if route not found\n return link.href ?? null;\n }\n\n return null;\n}\n\n/**\n * Build a Logo from site layout data.\n *\n * @param logo - Logo data from site layout\n * @param fallbackAlt - Fallback alt text (usually site title)\n *\n * @example\n * ```ts\n * const logo = buildLogo(siteData.layout.logo, siteData.site.title);\n * // { src: 'https://...', alt: 'Site Name', width: 200, height: 50 }\n * ```\n */\nexport function buildLogo(\n logo: Partial<LogoSource> | null,\n fallbackAlt: string | null | undefined,\n): Logo {\n if (!logo || !logo.url) {\n return null;\n }\n\n const alt = resolveAltText(logo.alt, fallbackAlt);\n\n const result: NonNullable<Logo> = {\n type: 'image',\n src: logo.url,\n alt,\n };\n\n if (logo.width != null) {\n result.width = logo.width;\n }\n if (logo.height != null) {\n result.height = logo.height;\n }\n\n return result;\n}\n\n/** @deprecated Use `buildLogo` instead */\nexport const buildSimpleLogo = buildLogo;\n\n// Re-export types for convenience\nexport type { NavigationMenuWithItems, NavigationItemRecord, LinkPayload } from '@riverbankcms/api';\n"]}
|
|
@@ -1996,7 +1996,7 @@ var SimpleCache = class {
|
|
|
1996
1996
|
};
|
|
1997
1997
|
|
|
1998
1998
|
// src/version.ts
|
|
1999
|
-
var SDK_VERSION = "0.
|
|
1999
|
+
var SDK_VERSION = "0.6.1";
|
|
2000
2000
|
|
|
2001
2001
|
// src/client/error.ts
|
|
2002
2002
|
var RiverbankApiError = class _RiverbankApiError extends Error {
|
|
@@ -2267,4 +2267,4 @@ export {
|
|
|
2267
2267
|
buildEndpointURL,
|
|
2268
2268
|
createRiverbankClient
|
|
2269
2269
|
};
|
|
2270
|
-
//# sourceMappingURL=chunk-
|
|
2270
|
+
//# sourceMappingURL=chunk-I7ZR2WO3.mjs.map
|