@cedros/data-react 0.1.1 → 0.1.2

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.
@@ -1,13 +1,13 @@
1
- export type { AdminPlugin, AdminSectionConfig, AdminGroupConfig, AdminSectionProps, HostContext, PluginContext, PluginRegistry, PluginId, SectionId, QualifiedSectionId, PluginPermission } from "./types.js";
1
+ export type { AdminPlugin, AdminSectionConfig, AdminGroupConfig, AdminSectionProps, HostContext, PluginContext, PluginRegistry, PluginId, SectionId, QualifiedSectionId, PluginPermission, ResolvedSection } from "./types.js";
2
2
  export { cedrosDataPlugin, dataPlugin } from "./plugin.js";
3
3
  export { default as defaultDataPlugin } from "./plugin.js";
4
4
  export { CEDROS_DATA_SECTIONS, CEDROS_DATA_SECTION_IDS, CEDROS_DATA_GROUPS } from "./sectionIds.js";
5
5
  export { AdminButton, Card, TextInput, SelectInput, JsonEditor, StatusNotice } from "./components.js";
6
6
  export { DataTable, type DataTableProps, type DataTableColumn } from "./primitives/DataTable.js";
7
- export { Toolbar, SearchInput, FilterChips, type FilterChipItem } from "./primitives/Toolbar.js";
8
- export { Pagination } from "./primitives/Pagination.js";
9
- export { JsonCodeEditor } from "./primitives/JsonCodeEditor.js";
7
+ export { Toolbar, SearchInput, FilterChips, type ToolbarProps, type SearchInputProps, type FilterChipsProps, type FilterChipItem } from "./primitives/Toolbar.js";
8
+ export { Pagination, type AdminPaginationProps } from "./primitives/Pagination.js";
9
+ export { JsonCodeEditor, type JsonCodeEditorProps } from "./primitives/JsonCodeEditor.js";
10
10
  export { DiffViewer, type DiffBlock } from "./primitives/DiffViewer.js";
11
11
  export { FormFieldRow, FieldTypeSelect, type FormFieldRowValue, type FieldTypeOption } from "./primitives/FormFieldRow.js";
12
- export { ConfirmDialog } from "./primitives/ConfirmDialog.js";
12
+ export { ConfirmDialog, type ConfirmDialogProps } from "./primitives/ConfirmDialog.js";
13
13
  export { ToastProvider, useToast, InlineAlert, type AlertTone } from "./primitives/alerts.js";
@@ -1,5 +1,5 @@
1
1
  import type { ReactNode } from "react";
2
- interface ConfirmDialogProps {
2
+ export interface ConfirmDialogProps {
3
3
  open: boolean;
4
4
  title: string;
5
5
  description?: string;
@@ -11,4 +11,3 @@ interface ConfirmDialogProps {
11
11
  children?: ReactNode;
12
12
  }
13
13
  export declare function ConfirmDialog({ open, title, description, confirmLabel, cancelLabel, tone, onConfirm, onCancel, children }: ConfirmDialogProps): React.JSX.Element | null;
14
- export {};
@@ -1,4 +1,4 @@
1
- interface JsonCodeEditorProps {
1
+ export interface JsonCodeEditorProps {
2
2
  value: string;
3
3
  onChange: (value: string) => void;
4
4
  label?: string;
@@ -7,4 +7,3 @@ interface JsonCodeEditorProps {
7
7
  onValidJson?: (value: unknown) => void;
8
8
  }
9
9
  export declare function JsonCodeEditor({ value, onChange, label, placeholder, readOnly, onValidJson }: JsonCodeEditorProps): React.JSX.Element;
10
- export {};
@@ -1,8 +1,7 @@
1
- interface PaginationProps {
1
+ export interface AdminPaginationProps {
2
2
  page: number;
3
3
  pageSize: number;
4
4
  total: number;
5
5
  onPageChange: (page: number) => void;
6
6
  }
7
- export declare function Pagination({ page, pageSize, total, onPageChange }: PaginationProps): React.JSX.Element;
8
- export {};
7
+ export declare function Pagination({ page, pageSize, total, onPageChange }: AdminPaginationProps): React.JSX.Element;
@@ -1,10 +1,10 @@
1
1
  import type { ReactNode } from "react";
2
- interface ToolbarProps {
2
+ export interface ToolbarProps {
3
3
  left?: ReactNode;
4
4
  right?: ReactNode;
5
5
  }
6
6
  export declare function Toolbar({ left, right }: ToolbarProps): React.JSX.Element;
7
- interface SearchInputProps {
7
+ export interface SearchInputProps {
8
8
  value: string;
9
9
  onChange: (value: string) => void;
10
10
  placeholder?: string;
@@ -15,9 +15,8 @@ export interface FilterChipItem {
15
15
  label: string;
16
16
  active: boolean;
17
17
  }
18
- interface FilterChipsProps {
18
+ export interface FilterChipsProps {
19
19
  items: FilterChipItem[];
20
20
  onToggle: (key: string) => void;
21
21
  }
22
22
  export declare function FilterChips({ items, onToggle }: FilterChipsProps): React.JSX.Element;
23
- export {};
@@ -7,4 +7,4 @@
7
7
  export { CmsContent, type CmsContentProps } from "./CmsContent.js";
8
8
  export { getOrCreateVisitorId } from "./visitor.js";
9
9
  export { sanitizeCmsHtml, renderCmsMarkdown } from "./sanitize.js";
10
- export type { CmsPageRecord, SiteDataRecord, SanitizeOptions, ContentType, } from "./types.js";
10
+ export type { CmsPageRecord, PageMetadataInput, SiteDataRecord, SanitizeOptions, ContentType, MeteredReadsInfo, } from "./types.js";
@@ -1,4 +1,4 @@
1
- import type { BuildPageMetadataOptions, CmsPageRecord, ServerFetchOptions } from "./types.js";
1
+ import type { BuildPageMetadataOptions, CmsPageRecord, PageMetadataInput, ServerFetchOptions } from "./types.js";
2
2
  /**
3
3
  * Metadata object compatible with Next.js `generateMetadata` return type.
4
4
  * Kept as a plain object so this module doesn't import `next` as a dependency.
@@ -26,13 +26,15 @@ export interface PageMetadata {
26
26
  other?: Record<string, string>;
27
27
  }
28
28
  /**
29
- * Builds a Next.js-compatible Metadata object from a CMS page record.
29
+ * Builds a Next.js-compatible Metadata object from a page record.
30
30
  *
31
- * @param page - CMS page record from the entries API
31
+ * Accepts both wrapped CmsPageRecord shapes and flat page records.
32
+ *
33
+ * @param page - Page record (wrapped or flat)
32
34
  * @param options - Optional site data, origin, path, and mode
33
35
  * @returns Metadata object suitable for Next.js `generateMetadata`
34
36
  */
35
- export declare function buildPageMetadata(page: CmsPageRecord, options?: BuildPageMetadataOptions): PageMetadata;
37
+ export declare function buildPageMetadata(page: CmsPageRecord | PageMetadataInput, options?: BuildPageMetadataOptions): PageMetadata;
36
38
  /**
37
39
  * Convenience wrapper that fetches a page by slug, then builds metadata.
38
40
  *
@@ -1,28 +1,35 @@
1
1
  import { fetchJson, resolveServerUrl } from "./fetch.js";
2
+ /** Resolves a field from the wrapped payload or flat top-level. */
3
+ function field(page, key) {
4
+ const rec = page;
5
+ const payload = rec.payload;
6
+ return payload?.[key] ?? rec[key];
7
+ }
2
8
  /**
3
- * Builds a Next.js-compatible Metadata object from a CMS page record.
9
+ * Builds a Next.js-compatible Metadata object from a page record.
10
+ *
11
+ * Accepts both wrapped CmsPageRecord shapes and flat page records.
4
12
  *
5
- * @param page - CMS page record from the entries API
13
+ * @param page - Page record (wrapped or flat)
6
14
  * @param options - Optional site data, origin, path, and mode
7
15
  * @returns Metadata object suitable for Next.js `generateMetadata`
8
16
  */
9
17
  export function buildPageMetadata(page, options) {
10
- const p = page.payload;
11
18
  const site = options?.siteData;
12
19
  const origin = options?.origin?.replace(/\/+$/, "") ?? "";
13
- const path = options?.path ?? p.route ?? "";
20
+ const path = options?.path ?? field(page, "route") ?? "";
14
21
  const mode = options?.mode ?? "page";
15
22
  const siteName = site?.siteName ?? site?.siteTitle ?? "";
16
- const title = p.title ?? siteName ?? undefined;
17
- const description = p.description ?? site?.defaultDescription ?? undefined;
18
- const ogTitle = p.ogTitle ?? p.title ?? undefined;
19
- const ogDescription = p.ogDescription ?? p.description ?? undefined;
20
- const ogImages = buildOgImages(p.ogImage, site?.defaultOgImage);
23
+ const title = field(page, "title") ?? siteName ?? undefined;
24
+ const description = field(page, "description") ?? site?.defaultDescription ?? undefined;
25
+ const ogTitle = field(page, "ogTitle") ?? field(page, "title") ?? undefined;
26
+ const ogDescription = field(page, "ogDescription") ?? field(page, "description") ?? undefined;
27
+ const ogImages = buildOgImages(field(page, "ogImage"), site?.defaultOgImage);
21
28
  const pageUrl = origin ? `${origin}${path}` : undefined;
22
29
  const ogType = mode === "blog" ? "article" : "website";
23
- const twitterTitle = p.twitterTitle ?? p.ogTitle ?? p.title ?? undefined;
24
- const twitterDescription = p.twitterDescription ?? p.ogDescription ?? p.description ?? undefined;
25
- const canonical = resolveCanonical(origin, path, mode, p.slug);
30
+ const twitterTitle = field(page, "twitterTitle") ?? field(page, "ogTitle") ?? field(page, "title") ?? undefined;
31
+ const twitterDescription = field(page, "twitterDescription") ?? field(page, "ogDescription") ?? field(page, "description") ?? undefined;
32
+ const canonical = resolveCanonical(origin, path, mode, field(page, "slug"));
26
33
  const metadata = {
27
34
  title,
28
35
  description,
@@ -112,31 +119,34 @@ function resolveCanonical(origin, path, mode, slug) {
112
119
  if (!origin)
113
120
  return undefined;
114
121
  if (mode === "docs" && slug) {
115
- return `${origin}/blog/${slug}`;
122
+ return `${origin}/docs/${slug}`;
116
123
  }
117
124
  return `${origin}${path}`;
118
125
  }
119
126
  function buildBlogJsonLd(page, origin, path) {
120
- const p = page.payload;
127
+ const updatedAt = field(page, "updatedAt");
121
128
  const jsonLd = {
122
129
  "@context": "https://schema.org",
123
130
  "@type": "BlogPosting",
124
- headline: p.title,
125
- description: p.description,
126
- datePublished: p.publishedAt,
127
- dateModified: p.updatedAt ?? page.updated_at,
131
+ headline: field(page, "title"),
132
+ description: field(page, "description"),
133
+ datePublished: field(page, "publishedAt"),
134
+ dateModified: updatedAt ?? page.updated_at,
128
135
  };
129
136
  if (origin) {
130
137
  jsonLd.url = `${origin}${path}`;
131
138
  }
132
- if (p.author) {
133
- jsonLd.author = { "@type": "Person", name: p.author };
139
+ const author = field(page, "author");
140
+ if (author) {
141
+ jsonLd.author = { "@type": "Person", name: author };
134
142
  }
135
- if (p.ogImage) {
136
- jsonLd.image = p.ogImage;
143
+ const ogImage = field(page, "ogImage");
144
+ if (ogImage) {
145
+ jsonLd.image = ogImage;
137
146
  }
138
- if (p.wordCount) {
139
- jsonLd.wordCount = p.wordCount;
147
+ const wordCount = field(page, "wordCount");
148
+ if (wordCount) {
149
+ jsonLd.wordCount = wordCount;
140
150
  }
141
151
  return JSON.stringify(jsonLd);
142
152
  }
@@ -11,4 +11,4 @@ export { buildPageMetadata, generatePageMetadata, type PageMetadata, } from "./m
11
11
  export { loadSitemapEntries } from "./sitemap.js";
12
12
  export { fetchBlogPost } from "./entries.js";
13
13
  export { listBlogSlugs, listContentSlugs, listLearnPathIds, } from "./slugs.js";
14
- export type { BuildPageMetadataOptions, CmsPageRecord, MeteredReadsInfo, SiteDataRecord, SitemapEntry, ServerFetchOptions, ContentType, } from "./types.js";
14
+ export type { BuildPageMetadataOptions, CmsPageRecord, MeteredReadsInfo, PageMetadataInput, SiteDataRecord, SitemapEntry, ServerFetchOptions, ContentType, } from "./types.js";
@@ -63,6 +63,18 @@ export interface SanitizeOptions {
63
63
  /** Allowed URL protocols for href/src attributes. */
64
64
  allowedProtocols?: string[];
65
65
  }
66
+ /**
67
+ * Flexible input for `buildPageMetadata`.
68
+ *
69
+ * Accepts both the wrapped CmsPageRecord shape (`{ entry_key, payload, updated_at }`)
70
+ * and flat page records where fields live at the top level (`{ title, ogImage, ... }`).
71
+ */
72
+ export interface PageMetadataInput {
73
+ entry_key?: string;
74
+ payload?: Record<string, unknown>;
75
+ updated_at?: string;
76
+ [key: string]: unknown;
77
+ }
66
78
  /** Options for building page metadata. */
67
79
  export interface BuildPageMetadataOptions {
68
80
  siteData?: SiteDataRecord;
@@ -195,6 +195,10 @@
195
195
  background: color-mix(in srgb, var(--cds-link) 9%, var(--cds-muted-bg) 91%);
196
196
  }
197
197
 
198
+ .cedros-site__docs-item--depth-0 {
199
+ padding-left: 0;
200
+ }
201
+
198
202
  .cedros-site__docs-item--depth-1 {
199
203
  padding-left: 0.9rem;
200
204
  }
@@ -312,6 +316,10 @@
312
316
  font-size: 0.8rem;
313
317
  }
314
318
 
319
+ .cedros-site__toc-link--depth-2 {
320
+ padding-left: 0;
321
+ }
322
+
315
323
  .cedros-site__toc-link--depth-3 {
316
324
  padding-left: 0.65rem;
317
325
  }
@@ -240,6 +240,12 @@
240
240
  }
241
241
  }
242
242
 
243
+ /* ─── Docs article modifier ──── */
244
+
245
+ .cedros-site__docs-article {
246
+ overflow: hidden;
247
+ }
248
+
243
249
  /* ─── TOC scroll-spy active link ──── */
244
250
 
245
251
  .cedros-site__toc-link--active {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cedros/data-react",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "React components, page templates, and Next.js integration for cedros-data",
5
5
  "type": "module",
6
6
  "main": "./dist/react/index.js",