cms-renderer 0.6.7 → 0.6.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -146,6 +146,37 @@ type BlockData = {
146
146
  type: string;
147
147
  content: Record<string, unknown>;
148
148
  };
149
+ /**
150
+ * Document metadata fields returned by the CMS API.
151
+ * These are added to all documents beyond their schema-defined fields.
152
+ *
153
+ * Use with generated Zod schemas:
154
+ * @example
155
+ * ```ts
156
+ * import type { DocumentMetadata } from 'cms-renderer/lib/types';
157
+ * import type { Post as GeneratedPost } from './generated/cms-schemas';
158
+ *
159
+ * export interface Post extends DocumentMetadata, GeneratedPost {}
160
+ * ```
161
+ */
162
+ interface DocumentMetadata {
163
+ _id: string;
164
+ _title?: string;
165
+ }
166
+ /**
167
+ * Reference to another document.
168
+ * Used in reference fields and arrays of references.
169
+ *
170
+ * @example
171
+ * ```ts
172
+ * interface Category extends DocumentMetadata {
173
+ * post_list?: Reference[];
174
+ * }
175
+ * ```
176
+ */
177
+ interface Reference {
178
+ _ref: string;
179
+ }
149
180
  /**
150
181
  * Resolved route parameter info exposed to block components.
151
182
  * Contains the parameter value, its schema name, and the resolved document.
@@ -197,4 +228,4 @@ interface BlockComponentRegistry {
197
228
  [schemaName: string]: BlockComponent<any>;
198
229
  }
199
230
 
200
- export { type ArticleContent, type BlockComponent, type BlockComponentProps, type BlockComponentRegistry, type BlockData, type BlockType, type CTABlockContent, type FeaturesBlockContent, type HeaderContent, type HeroBlockContent, type Level1Link, type Level2Link, type Level3Link, type LogoTrustBlockContent, type NavigationButton, type NavigationContent, type NavigationLink, type ResolvedRouteParams, type RouteParamInfo, __cmsRendererTypesModule };
231
+ export { type ArticleContent, type BlockComponent, type BlockComponentProps, type BlockComponentRegistry, type BlockData, type BlockType, type CTABlockContent, type DocumentMetadata, type FeaturesBlockContent, type HeaderContent, type HeroBlockContent, type Level1Link, type Level2Link, type Level3Link, type LogoTrustBlockContent, type NavigationButton, type NavigationContent, type NavigationLink, type Reference, type ResolvedRouteParams, type RouteParamInfo, __cmsRendererTypesModule };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../lib/types.ts"],"sourcesContent":["/**\n * Block Rendering Types\n *\n * Type definitions for the ComponentMap pattern.\n * Block types map to React components via the blockComponents registry.\n */\n\nimport type { ComponentType } from 'react';\n\n// Ensures the emitted JS stays a module for consumers that import this entry for types.\nexport const __cmsRendererTypesModule = true;\n\n// -----------------------------------------------------------------------------\n// Block Type Discriminant\n// -----------------------------------------------------------------------------\n\n/**\n * Valid block type strings.\n * Must match the schema_name field in block data from the tRPC API.\n */\nexport type BlockType =\n | 'navigation'\n | 'header'\n | 'article'\n | 'hero-block'\n | 'features-block'\n | 'cta-block'\n | 'logo-trust-block';\n\n// -----------------------------------------------------------------------------\n// Content Types (inferred from seed data)\n// -----------------------------------------------------------------------------\n\n/**\n * Navigation link button structure.\n */\nexport interface NavigationButton {\n label: string;\n href: string;\n ariaLabel: string;\n}\n\n/**\n * Navigation link with type and button.\n */\nexport interface NavigationLink {\n button: NavigationButton;\n type: 'Default' | 'Flyout';\n}\n\n/**\n * Level 3 navigation item (leaf node).\n */\nexport interface Level3Link {\n link: NavigationLink;\n}\n\n/**\n * Level 2 navigation item with optional Level 3 children.\n */\nexport interface Level2Link {\n link: NavigationLink;\n children?: Level3Link[];\n}\n\n/**\n * Level 1 navigation item with optional Level 2 children.\n */\nexport interface Level1Link {\n link: NavigationLink;\n children?: Level2Link[];\n}\n\n/**\n * Navigation block content.\n */\nexport interface NavigationContent {\n logo?: {\n url: string;\n alt: string;\n };\n ariaLabel: string;\n links: Level1Link[];\n}\n\n/**\n * Header block content.\n */\nexport interface HeaderContent {\n headline: string;\n subheadline?: string;\n backgroundImage?: {\n url: string;\n alt: string;\n };\n ctaButton?: {\n label: string;\n href: string;\n };\n alignment: 'left' | 'center' | 'right';\n}\n\n/**\n * Article block content.\n */\nexport interface ArticleContent {\n headline: string;\n author?: string;\n publishedAt?: string;\n body: string;\n tags?: readonly string[] | string[];\n status?: string;\n}\n\n/**\n * Hero block content (from CMS schema).\n */\nexport type HeroBlockContent = import('@repo/cms-schema/blocks').HeroBlockContent;\n\n/**\n * Features block content (from CMS schema).\n */\nexport type FeaturesBlockContent = import('@repo/cms-schema/blocks').FeaturesBlockContent;\n\n/**\n * CTA block content (from CMS schema).\n */\nexport type CTABlockContent = import('@repo/cms-schema/blocks').CTABlockContent;\n\n/**\n * Logo Trust block content (from CMS schema).\n */\nexport type LogoTrustBlockContent = import('@repo/cms-schema/blocks').LogoTrustBlockContent;\n\n// -----------------------------------------------------------------------------\n// Block Data Union\n// -----------------------------------------------------------------------------\n\n/**\n * Discriminated union of all block types.\n * Use the `type` field to narrow to specific content types.\n *\n * Each block also carries its stable CMS `id`, which should be used as the\n * React `key` when rendering lists of blocks.\n *\n * @example\n * ```tsx\n * function renderBlock(block: BlockData) {\n * if (block.type === 'header') {\n * // TypeScript knows block.content is HeaderContent\n * return <h1>{block.content.headline}</h1>;\n * }\n * }\n * ```\n */\nexport type BlockData =\n | { id: string; type: 'navigation'; content: NavigationContent }\n | { id: string; type: 'header'; content: HeaderContent }\n | { id: string; type: 'article'; content: ArticleContent }\n | { id: string; type: 'hero-block'; content: HeroBlockContent }\n | { id: string; type: 'features-block'; content: FeaturesBlockContent }\n | { id: string; type: 'cta-block'; content: CTABlockContent }\n | { id: string; type: 'logo-trust-block'; content: LogoTrustBlockContent }\n | { id: string; type: string; content: Record<string, unknown> };\n\n// -----------------------------------------------------------------------------\n// Route Parameter Types\n// -----------------------------------------------------------------------------\n\n/**\n * Resolved route parameter info exposed to block components.\n * Contains the parameter value, its schema name, and the resolved document.\n */\nexport interface RouteParamInfo {\n value: string;\n schemaName: string;\n document: {\n id: string;\n title: string;\n content: Record<string, unknown>;\n schema_name: string;\n };\n}\n\n/**\n * Map of route parameter names to their resolved info.\n * E.g., `{ country: { value: \"us\", schemaName: \"country\", document: {...} } }`\n */\nexport type ResolvedRouteParams = Record<string, RouteParamInfo>;\n\n// -----------------------------------------------------------------------------\n// Component Types\n// -----------------------------------------------------------------------------\n\n/**\n * Props for a block component.\n * Each block component receives its typed content.\n */\nexport interface BlockComponentProps<T> {\n content: T;\n routeParams?: ResolvedRouteParams;\n /** ISO 639-1 language code extracted from the route's language param, if present. */\n language?: string;\n}\n\n/**\n * A React component that renders a specific block type.\n */\nexport type BlockComponent<T> = ComponentType<BlockComponentProps<T>>;\n\n/**\n * Registry of block type to component mappings.\n * This is the core of the ComponentMap pattern.\n *\n * Predefined block types have strongly-typed content.\n * Custom blocks (keyed by their schema_name) receive `Record<string, unknown>`.\n */\nexport interface BlockComponentRegistry {\n navigation: BlockComponent<NavigationContent>;\n header: BlockComponent<HeaderContent>;\n article: BlockComponent<ArticleContent>;\n 'hero-block': BlockComponent<HeroBlockContent>;\n 'features-block': BlockComponent<FeaturesBlockContent>;\n 'cta-block': BlockComponent<CTABlockContent>;\n 'logo-trust-block': BlockComponent<LogoTrustBlockContent>;\n // Custom blocks: register by schema_name\n // biome-ignore lint/suspicious/noExplicitAny: Custom block content is dynamic\n [schemaName: string]: BlockComponent<any>;\n}\n"],"mappings":";AAUO,IAAM,2BAA2B;","names":[]}
1
+ {"version":3,"sources":["../../lib/types.ts"],"sourcesContent":["/**\n * Block Rendering Types\n *\n * Type definitions for the ComponentMap pattern.\n * Block types map to React components via the blockComponents registry.\n */\n\nimport type { ComponentType } from 'react';\n\n// Ensures the emitted JS stays a module for consumers that import this entry for types.\nexport const __cmsRendererTypesModule = true;\n\n// -----------------------------------------------------------------------------\n// Block Type Discriminant\n// -----------------------------------------------------------------------------\n\n/**\n * Valid block type strings.\n * Must match the schema_name field in block data from the tRPC API.\n */\nexport type BlockType =\n | 'navigation'\n | 'header'\n | 'article'\n | 'hero-block'\n | 'features-block'\n | 'cta-block'\n | 'logo-trust-block';\n\n// -----------------------------------------------------------------------------\n// Content Types (inferred from seed data)\n// -----------------------------------------------------------------------------\n\n/**\n * Navigation link button structure.\n */\ninterface NavigationButton {\n label: string;\n href: string;\n ariaLabel: string;\n}\n\n/**\n * Navigation link with type and button.\n */\ninterface NavigationLink {\n button: NavigationButton;\n type: 'Default' | 'Flyout';\n}\n\n/**\n * Level 3 navigation item (leaf node).\n */\ninterface Level3Link {\n link: NavigationLink;\n}\n\n/**\n * Level 2 navigation item with optional Level 3 children.\n */\ninterface Level2Link {\n link: NavigationLink;\n children?: Level3Link[];\n}\n\n/**\n * Level 1 navigation item with optional Level 2 children.\n */\ninterface Level1Link {\n link: NavigationLink;\n children?: Level2Link[];\n}\n\n/**\n * Navigation block content.\n */\ninterface NavigationContent {\n logo?: {\n url: string;\n alt: string;\n };\n ariaLabel: string;\n links: Level1Link[];\n}\n\n/**\n * Header block content.\n */\ninterface HeaderContent {\n headline: string;\n subheadline?: string;\n backgroundImage?: {\n url: string;\n alt: string;\n };\n ctaButton?: {\n label: string;\n href: string;\n };\n alignment: 'left' | 'center' | 'right';\n}\n\n/**\n * Article block content.\n */\ninterface ArticleContent {\n headline: string;\n author?: string;\n publishedAt?: string;\n body: string;\n tags?: readonly string[] | string[];\n status?: string;\n}\n\n/**\n * Hero block content (from CMS schema).\n */\nexport type HeroBlockContent = import('@repo/cms-schema/blocks').HeroBlockContent;\n\n/**\n * Features block content (from CMS schema).\n */\nexport type FeaturesBlockContent = import('@repo/cms-schema/blocks').FeaturesBlockContent;\n\n/**\n * CTA block content (from CMS schema).\n */\nexport type CTABlockContent = import('@repo/cms-schema/blocks').CTABlockContent;\n\n/**\n * Logo Trust block content (from CMS schema).\n */\nexport type LogoTrustBlockContent = import('@repo/cms-schema/blocks').LogoTrustBlockContent;\n\n// -----------------------------------------------------------------------------\n// Block Data Union\n// -----------------------------------------------------------------------------\n\n/**\n * Discriminated union of all block types.\n * Use the `type` field to narrow to specific content types.\n *\n * Each block also carries its stable CMS `id`, which should be used as the\n * React `key` when rendering lists of blocks.\n *\n * @example\n * ```tsx\n * function renderBlock(block: BlockData) {\n * if (block.type === 'header') {\n * // TypeScript knows block.content is HeaderContent\n * return <h1>{block.content.headline}</h1>;\n * }\n * }\n * ```\n */\nexport type BlockData =\n | { id: string; type: 'navigation'; content: NavigationContent }\n | { id: string; type: 'header'; content: HeaderContent }\n | { id: string; type: 'article'; content: ArticleContent }\n | { id: string; type: 'hero-block'; content: HeroBlockContent }\n | { id: string; type: 'features-block'; content: FeaturesBlockContent }\n | { id: string; type: 'cta-block'; content: CTABlockContent }\n | { id: string; type: 'logo-trust-block'; content: LogoTrustBlockContent }\n | { id: string; type: string; content: Record<string, unknown> };\n\n// -----------------------------------------------------------------------------\n// Document Types (for custom schema data fetching)\n// -----------------------------------------------------------------------------\n\n/**\n * Document metadata fields returned by the CMS API.\n * These are added to all documents beyond their schema-defined fields.\n *\n * Use with generated Zod schemas:\n * @example\n * ```ts\n * import type { DocumentMetadata } from 'cms-renderer/lib/types';\n * import type { Post as GeneratedPost } from './generated/cms-schemas';\n *\n * export interface Post extends DocumentMetadata, GeneratedPost {}\n * ```\n */\ninterface DocumentMetadata {\n _id: string;\n _title?: string;\n}\n\n/**\n * Reference to another document.\n * Used in reference fields and arrays of references.\n *\n * @example\n * ```ts\n * interface Category extends DocumentMetadata {\n * post_list?: Reference[];\n * }\n * ```\n */\ninterface Reference {\n _ref: string;\n}\n\n// -----------------------------------------------------------------------------\n// Route Parameter Types\n// -----------------------------------------------------------------------------\n\n/**\n * Resolved route parameter info exposed to block components.\n * Contains the parameter value, its schema name, and the resolved document.\n */\ninterface RouteParamInfo {\n value: string;\n schemaName: string;\n document: {\n id: string;\n title: string;\n content: Record<string, unknown>;\n schema_name: string;\n };\n}\n\n/**\n * Map of route parameter names to their resolved info.\n * E.g., `{ country: { value: \"us\", schemaName: \"country\", document: {...} } }`\n */\nexport type ResolvedRouteParams = Record<string, RouteParamInfo>;\n\n// -----------------------------------------------------------------------------\n// Component Types\n// -----------------------------------------------------------------------------\n\n/**\n * Props for a block component.\n * Each block component receives its typed content.\n */\ninterface BlockComponentProps<T> {\n content: T;\n routeParams?: ResolvedRouteParams;\n /** ISO 639-1 language code extracted from the route's language param, if present. */\n language?: string;\n}\n\n/**\n * A React component that renders a specific block type.\n */\nexport type BlockComponent<T> = ComponentType<BlockComponentProps<T>>;\n\n/**\n * Registry of block type to component mappings.\n * This is the core of the ComponentMap pattern.\n *\n * Predefined block types have strongly-typed content.\n * Custom blocks (keyed by their schema_name) receive `Record<string, unknown>`.\n */\ninterface BlockComponentRegistry {\n navigation: BlockComponent<NavigationContent>;\n header: BlockComponent<HeaderContent>;\n article: BlockComponent<ArticleContent>;\n 'hero-block': BlockComponent<HeroBlockContent>;\n 'features-block': BlockComponent<FeaturesBlockContent>;\n 'cta-block': BlockComponent<CTABlockContent>;\n 'logo-trust-block': BlockComponent<LogoTrustBlockContent>;\n // Custom blocks: register by schema_name\n // biome-ignore lint/suspicious/noExplicitAny: Custom block content is dynamic\n [schemaName: string]: BlockComponent<any>;\n}\n\nexport type {\n ArticleContent,\n BlockComponentProps,\n BlockComponentRegistry,\n DocumentMetadata,\n HeaderContent,\n Level1Link,\n Level2Link,\n Level3Link,\n NavigationButton,\n NavigationContent,\n NavigationLink,\n Reference,\n RouteParamInfo,\n};\n"],"mappings":";AAUO,IAAM,2BAA2B;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cms-renderer",
3
- "version": "0.6.7",
3
+ "version": "0.6.9",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "exports": {
@@ -113,7 +113,7 @@
113
113
  "@trpc/server": "^11.8.1",
114
114
  "escape-string-regexp": "^5.0.0",
115
115
  "md4w": "^0.2.7",
116
- "next": "^16.1.1",
116
+ "next": "16.2.6",
117
117
  "object-hash": "^3.0.0",
118
118
  "shiki": "^4.0.2",
119
119
  "react": "^19.1.0",
@@ -4,7 +4,7 @@
4
4
  overflow-x: hidden;
5
5
  overflow-wrap: anywhere;
6
6
  word-break: break-word;
7
- color: #d1d5db;
7
+ color: var(--text);
8
8
  font-size: 15px;
9
9
  line-height: 1.75;
10
10
  }
@@ -13,7 +13,7 @@
13
13
  .cms-docs-markdown h2,
14
14
  .cms-docs-markdown h3,
15
15
  .cms-docs-markdown h4 {
16
- color: #ffffff;
16
+ color: var(--text);
17
17
  font-weight: 600;
18
18
  }
19
19
 
@@ -57,13 +57,13 @@
57
57
  }
58
58
 
59
59
  .cms-docs-markdown a {
60
- color: #93c5fd;
60
+ color: var(--accent);
61
61
  text-decoration: underline;
62
62
  text-underline-offset: 4px;
63
63
  }
64
64
 
65
65
  .cms-docs-markdown strong {
66
- color: #ffffff;
66
+ color: var(--text);
67
67
  font-weight: 600;
68
68
  }
69
69
 
@@ -90,26 +90,26 @@
90
90
  }
91
91
 
92
92
  .cms-docs-markdown blockquote {
93
- border-left: 2px solid #374151;
93
+ border-left: 2px solid var(--border-strong);
94
94
  padding-left: 1rem;
95
- color: #9ca3af;
95
+ color: var(--text-muted);
96
96
  font-style: italic;
97
97
  }
98
98
 
99
99
  .cms-docs-markdown :not(pre) > code {
100
100
  border-radius: 0.25rem;
101
- background: #1f2937;
101
+ background: var(--code-bg);
102
102
  padding: 0.125rem 0.375rem;
103
- color: #f9fafb;
103
+ color: var(--code-fg);
104
104
  font-size: 0.9em;
105
105
  }
106
106
 
107
107
  .cms-docs-markdown pre,
108
108
  .cms-docs-markdown .shiki {
109
109
  overflow-x: auto;
110
- border: 1px solid #1f2937;
110
+ border: 1px solid var(--code-border);
111
111
  border-radius: 0.75rem;
112
- background: #0b0f19;
112
+ background: var(--surface-muted);
113
113
  padding: 1rem;
114
114
  }
115
115
 
@@ -117,13 +117,13 @@
117
117
  .cms-docs-markdown .shiki code {
118
118
  background: transparent;
119
119
  padding: 0;
120
- color: #e5e7eb;
120
+ color: var(--text);
121
121
  }
122
122
 
123
123
  .cms-docs-markdown hr {
124
124
  margin: 2rem 0;
125
125
  border: 0;
126
- border-top: 1px solid #1f2937;
126
+ border-top: 1px solid var(--border);
127
127
  }
128
128
 
129
129
  .cms-docs-markdown table {
@@ -135,13 +135,13 @@
135
135
 
136
136
  .cms-docs-markdown th,
137
137
  .cms-docs-markdown td {
138
- border: 1px solid #374151;
138
+ border: 1px solid var(--border-strong);
139
139
  padding: 0.5rem 0.75rem;
140
140
  }
141
141
 
142
142
  .cms-docs-markdown th {
143
- background: #111827;
144
- color: #ffffff;
143
+ background: var(--table-header);
144
+ color: var(--text);
145
145
  text-align: left;
146
146
  }
147
147