@nexpress/theme-docs 0.1.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.
- package/LICENSE +21 -0
- package/dist/components/error.d.ts +25 -0
- package/dist/components/error.js +115 -0
- package/dist/components/error.js.map +1 -0
- package/dist/components/members-error.d.ts +27 -0
- package/dist/components/members-error.js +118 -0
- package/dist/components/members-error.js.map +1 -0
- package/dist/index.d.ts +156 -0
- package/dist/index.js +813 -0
- package/dist/index.js.map +1 -0
- package/package.json +73 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/header.tsx","../src/settings-helpers.ts","../src/settings.ts","../src/members-not-found.tsx","../src/members-shell.tsx","../src/not-found.tsx","../src/routes/doc-detail.tsx","../src/templates/doc-page.tsx","../src/search.tsx","../src/shell.tsx","../src/sidebar.tsx","../src/styles.ts"],"sourcesContent":["import { defineTheme } from \"@nexpress/theme\";\n\nimport { DocsHeader } from \"./header.js\";\nimport { DocsMembersNotFound } from \"./members-not-found.js\";\nimport { DocsMembersShell } from \"./members-shell.js\";\nimport { DocsNotFound } from \"./not-found.js\";\nimport { DocsDetailRoute } from \"./routes/doc-detail.js\";\nimport { DocsSearch } from \"./search.js\";\nimport { DocsShell } from \"./shell.js\";\nimport { DocsSidebar } from \"./sidebar.js\";\nimport { docsCss } from \"./styles.js\";\nimport { docsSettingsSchema } from \"./settings.js\";\nimport { DocPageTemplate } from \"./templates/doc-page.js\";\n\n/**\n * `@nexpress/theme-docs` — documentation theme for NexPress.\n *\n * Stresses F.2 (search route + sidebar slot consuming\n * hierarchy) and F.3 (settings: version, githubRepo,\n * sidebarHeading, TOC toggle). Different contract axis from\n * F.9-A's magazine — sidebar-driven layout, hierarchical doc\n * collection, prev/next navigation.\n */\nexport const docsTheme = defineTheme({\n manifest: {\n id: \"docs\",\n name: \"Docs\",\n version: \"0.1.0\",\n description:\n \"Documentation theme — hierarchical sidebar, prev/next nav, search masthead. Pairs with a `docs` collection that has parent/order fields.\",\n author: { name: \"NexPress\" },\n nexpress: { minVersion: \"0.1.0\" },\n requires: {\n collections: {\n docs: {\n createIfAbsent: true,\n fields: {\n title: { type: \"text\", required: true },\n body: { type: \"richText\" },\n parent: {\n type: \"relationship\",\n relationTo: \"docs\",\n hard: false,\n },\n order: { type: \"number\" },\n },\n },\n },\n },\n settingsSchema: docsSettingsSchema,\n },\n impl: {\n shell: DocsShell,\n slots: {\n header: DocsHeader,\n sidebar: DocsSidebar,\n },\n css: docsCss,\n tokens: {\n // Docs lean cool/neutral with a sharp accent — distinct\n // from magazine's warm cream so a side-by-side preview\n // makes the swap obvious.\n colors: {\n primary: \"oklch(0.55 0.18 260)\",\n primaryForeground: \"oklch(0.985 0.005 260)\",\n background: \"oklch(0.99 0.005 260)\",\n foreground: \"oklch(0.18 0.025 260)\",\n muted: \"oklch(0.95 0.012 260)\",\n mutedForeground: \"oklch(0.5 0.025 260)\",\n border: \"oklch(0.9 0.012 260)\",\n card: \"oklch(0.985 0.008 260)\",\n cardForeground: \"oklch(0.18 0.025 260)\",\n accent: \"oklch(0.92 0.05 260)\",\n accentForeground: \"oklch(0.18 0.025 260)\",\n },\n },\n templates: {\n docs: {\n default: {\n label: \"Doc page\",\n description:\n \"Hierarchical sidebar + body + prev/next nav. Optional 'Edit on GitHub' link when settings.githubRepo is set.\",\n component: DocPageTemplate,\n },\n },\n },\n routes: [\n // F.2 — docs theme's scoped search route. Lives at\n // `/docs/search` rather than `/search` (#609): the host's\n // reference app has an app-explicit `/search` page route\n // that takes precedence over theme routes per the locked\n // dispatch order (app file > page > theme > plugin). The\n // theme can't override the universal search page, so it\n // scopes its own search to a `/docs/*` namespace and the\n // operator gets both routes: framework `/search` + docs\n // theme `/docs/search`.\n //\n // Order matters: search comes first so `/docs/search` is\n // matched as a literal rather than `{ slug: \"search\" }`\n // by the parametric detail route below (dispatcher is\n // first-match-wins).\n { pattern: \"/docs/search\", component: DocsSearch },\n // Doc detail dispatch (#614). The sidebar + template emit\n // `/docs/<slug>` links; without this route those 404 in\n // the reference app — the catch-all only resolves `pages`\n // rows, not arbitrary `docs` collection rows. The\n // component looks up the docs row by slug and renders\n // through `templates.docs.default` (DocPageTemplate).\n { pattern: \"/docs/:slug\", component: DocsDetailRoute },\n ],\n navLocations: {\n primary: {\n label: \"Primary header nav\",\n description: \"Inline links beside the masthead search box.\",\n maxItems: 5,\n },\n },\n notFound: DocsNotFound,\n // M.* adoption (2026-05-11). Docs gains purpose-built member\n // chrome: drops the docs sidebar (hierarchical doc nav is\n // useless on auth forms), keeps the masthead, narrows the\n // content column. Without this, the fallback chain would\n // walk back to `impl.shell` (the 3-column grid) and the\n // sidebar slot would surface alongside an auth form.\n // - `shell`: DocsMembersShell (header + narrow column, no\n // sidebar).\n // - `notFound`: DocsMembersNotFound (stale-auth-link framing\n // with /members/login CTA, monospace accent matching the\n // theme).\n // - `error`: forward-compat type marker; the actual render\n // goes through `./components/members-error`'s client\n // subpath, lazy-imported by\n // `apps/web/src/app/(member)/error.tsx`'s registry\n // (F.7.1 delegation — Next mandates `error.tsx` is \"use\n // client\").\n members: {\n shell: DocsMembersShell,\n notFound: DocsMembersNotFound,\n },\n },\n});\n\nexport {\n DocsHeader,\n DocsShell,\n DocsSidebar,\n DocsNotFound,\n DocsMembersShell,\n DocsMembersNotFound,\n DocsSearch,\n DocPageTemplate,\n};\nexport { docsCss };\nexport { docsSettingsSchema, type DocsSettings } from \"./settings.js\";\n","import * as React from \"react\";\nimport { NavMenu } from \"@nexpress/next\";\n\nimport { resolveDocsSettings } from \"./settings-helpers.js\";\n\n/**\n * Phase F.9-B — docs theme masthead.\n *\n * Brand strap: site title (left), search input (center), nav\n * + version label (right). Reads settings via\n * `resolveDocsSettings()` so the version label and search\n * placeholder match the operator's admin choices.\n *\n * The search input is a plain GET form to `/docs/search` —\n * F.2's theme route handles the query (#609: the universal\n * `/search` is the framework's own page, so the docs theme\n * scopes its search to `/docs/search` to avoid being shadowed\n * by the host's `app/(site)/search/page.tsx`). No client-side\n * JS for the input itself; works without hydration.\n */\nexport async function DocsHeader(): Promise<React.ReactElement> {\n const settings = await resolveDocsSettings();\n return (\n <header className=\"np-docs-header\">\n <div className=\"np-docs-header-inner\">\n <a href=\"/\" className=\"np-docs-brand\">\n <span className=\"np-docs-brand-name\">Docs</span>\n <span className=\"np-docs-brand-version\">{settings.version}</span>\n </a>\n <form\n action=\"/docs/search\"\n method=\"get\"\n className=\"np-docs-search-form\"\n role=\"search\"\n >\n <input\n type=\"search\"\n name=\"q\"\n placeholder={settings.searchPlaceholder}\n className=\"np-docs-search-input\"\n aria-label=\"Search the docs\"\n />\n </form>\n <nav className=\"np-docs-nav\" aria-label=\"Primary\">\n <NavMenu location=\"primary\" className=\"np-docs-primary-nav\" />\n {settings.githubRepo ? (\n <a\n href={settings.githubRepo}\n className=\"np-docs-github-link\"\n target=\"_blank\"\n rel=\"noreferrer\"\n >\n GitHub\n </a>\n ) : null}\n </nav>\n </div>\n </header>\n );\n}\n","import { getCachedThemeSettings } from \"@nexpress/next\";\n\nimport { docsSettingsSchema, type DocsSettings } from \"./settings.js\";\n\n/**\n * Phase F.9-B / F.9.1-B — typed accessor over the cached theme\n * settings read.\n *\n * Uses `getCachedThemeSettings` so multiple resolveSettings()\n * calls in the same request (header + sidebar + page template +\n * search) share one DB hit via Next's `unstable_cache`. The\n * `nx:theme:<siteId>` tag handles invalidation.\n *\n * On parse failure (theme upgrade changed the shape, etc.)\n * falls back to the schema defaults. The admin's\n * `getThemeSettingsWithStatus` surfaces a banner when this\n * happens; the runtime keeps rendering with safe values.\n */\nexport async function resolveDocsSettings(): Promise<DocsSettings> {\n const raw = await getCachedThemeSettings(\"docs\");\n const parsed = docsSettingsSchema.safeParse(raw);\n if (parsed.success) return parsed.data;\n return docsSettingsSchema.parse({});\n}\n","import { z } from \"zod\";\n\n/**\n * Phase F.9-B — operator-tunable docs settings.\n *\n * Stresses F.3's settings auto-form on a different axis from\n * magazine: more URL inputs, a select/enum for sidebar\n * orientation, and a documentation-flavored field set.\n */\nexport const docsSettingsSchema = z.object({\n version: z\n .string()\n .default(\"v1\")\n .describe(\n \"Currently-displayed version label, shown in the masthead. Update on each release.\",\n ),\n githubRepo: z\n .string()\n .url()\n .optional()\n .describe(\n \"Optional repository URL — when set, page templates render an 'Edit on GitHub' link in the prev/next bar.\",\n ),\n sidebarHeading: z\n .string()\n .default(\"Documentation\")\n .describe(\"Heading shown above the hierarchical sidebar nav.\"),\n showTableOfContents: z\n .boolean()\n .default(true)\n .describe(\"Render the in-page TOC sidebar on doc pages.\"),\n searchPlaceholder: z\n .string()\n .default(\"Search the docs…\")\n .describe(\"Placeholder text for the search input in the masthead.\"),\n});\n\nexport type DocsSettings = z.infer<typeof docsSettingsSchema>;\n","import * as React from \"react\";\n\n/**\n * Docs theme's member-tree 404.\n *\n * Mirrors `DocsNotFound`'s technical voice but tuned for the\n * member context — CTA points at `/members/login` rather than\n * the docs index, and the copy acknowledges stale auth links\n * (the dominant cause of 404s inside `/members/*`).\n *\n * Server component; rendered by `(member)/not-found.tsx` when\n * the active theme is docs and `impl.members.notFound` is\n * declared.\n *\n * Renders a `<div>`, not `<main>`, because the framework's\n * `<ShellWrap surface=\"member\">` already emits the page's\n * `<main className=\"np-member-main\">` landmark.\n */\nexport function DocsMembersNotFound(): React.ReactElement {\n return (\n <div\n className=\"np-docs-members-not-found\"\n style={{\n maxWidth: 520,\n margin: \"5rem auto\",\n padding: \"0 1.5rem\",\n }}\n >\n <p\n style={{\n margin: 0,\n fontSize: \"0.75rem\",\n textTransform: \"uppercase\",\n letterSpacing: \"0.12em\",\n color: \"var(--np-color-muted-foreground)\",\n fontFamily: \"var(--np-font-mono, ui-monospace, monospace)\",\n }}\n >\n 404 · account\n </p>\n <h1\n style={{\n margin: \"0.75rem 0 0\",\n fontSize: \"1.875rem\",\n fontFamily: \"var(--np-font-heading)\",\n fontWeight: 600,\n lineHeight: 1.2,\n }}\n >\n That account link is no longer valid.\n </h1>\n <p\n style={{\n margin: \"1.25rem 0 0\",\n color: \"var(--np-color-muted-foreground)\",\n fontSize: \"0.9375rem\",\n lineHeight: 1.6,\n }}\n >\n Verification and password-reset links are single-use and expire after a\n short window. Open the sign-in page and request a fresh one.\n </p>\n <p style={{ margin: \"1.75rem 0 0\" }}>\n <a\n href=\"/members/login\"\n style={{\n display: \"inline-block\",\n padding: \"0.5rem 1.25rem\",\n borderRadius: \"0.375rem\",\n background: \"var(--np-color-primary)\",\n color: \"var(--np-color-primary-foreground)\",\n textDecoration: \"none\",\n fontSize: \"0.875rem\",\n fontWeight: 500,\n }}\n >\n Go to sign in\n </a>\n </p>\n </div>\n );\n}\n","import type { ReactNode } from \"react\";\n\nimport { DocsHeader } from \"./header.js\";\n\n/**\n * Docs theme's member-tree shell.\n *\n * Drops the docs sidebar (which is hierarchical-doc navigation —\n * useless on auth forms) and renders a narrow column under the\n * masthead. Reuses `DocsHeader` directly so a masthead bump\n * cascades to member pages — single source of truth for chrome.\n *\n * Skips the public `DocsShell`'s 3-column grid because the\n * `<ShellWrap surface=\"member\">` fallback chain only invokes\n * `impl.members.shell` (this component); the public shell never\n * wraps the member tree.\n */\nexport function DocsMembersShell({ children }: { children: ReactNode }) {\n return (\n <div className=\"np-docs np-docs-shell\">\n <DocsHeader />\n <div className=\"np-docs-members\">\n <div className=\"np-docs-members-column\">{children}</div>\n </div>\n </div>\n );\n}\n","import * as React from \"react\";\n\n/**\n * Phase F.9-B — docs 404.\n *\n * Tighter / less editorial than magazine's; suggests search +\n * homepage as next steps.\n */\nexport function DocsNotFound(): React.ReactElement {\n // `<div>` — (site)/layout.tsx already emits the page's `<main>`.\n return (\n <div\n className=\"np-docs-not-found\"\n style={{\n maxWidth: 560,\n margin: \"5rem auto\",\n padding: \"0 1.5rem\",\n }}\n >\n <p\n style={{\n margin: 0,\n fontSize: \"0.75rem\",\n textTransform: \"uppercase\",\n letterSpacing: \"0.08em\",\n color: \"var(--np-color-muted-foreground)\",\n }}\n >\n 404 — Not found\n </p>\n <h1 style={{ margin: \"0.75rem 0 0.5rem\", fontSize: \"1.75rem\" }}>\n That page isn't in the docs.\n </h1>\n <p\n style={{\n margin: \"0.75rem 0 1.5rem\",\n color: \"var(--np-color-muted-foreground)\",\n }}\n >\n It may have been renamed or merged into another section. Try the\n search bar in the header, or head to the homepage.\n </p>\n <a\n href=\"/\"\n style={{\n display: \"inline-block\",\n padding: \"0.4rem 1rem\",\n borderRadius: \"0.375rem\",\n background: \"var(--np-color-primary)\",\n color: \"var(--np-color-primary-foreground)\",\n textDecoration: \"none\",\n fontWeight: 500,\n }}\n >\n Homepage\n </a>\n </div>\n );\n}\n","import { findDocuments } from \"@nexpress/core\";\nimport type { NpRouteRenderProps, NpTemplateRenderProps } from \"@nexpress/theme\";\nimport { notFound } from \"next/navigation\";\nimport * as React from \"react\";\n\nimport { DocPageTemplate } from \"../templates/doc-page.js\";\n\n/**\n * Theme route for `/docs/:slug` — looks up a docs collection row\n * and renders it through `DocPageTemplate` (#614).\n *\n * Without this route, the sidebar's `/docs/<slug>` links and the\n * doc template's prev/next links 404 in the reference app — the\n * catch-all only resolves `pages` rows + theme archive routes;\n * arbitrary `docs` collection rows weren't reachable by URL.\n *\n * The lookup is a defensive untyped `findDocuments<DocsRow>`\n * call: the docs collection schema lives in the user's project,\n * not the theme, so we re-declare the minimal shape the template\n * needs (title + body + parent + order) and trust runtime row\n * data to match. Operators who run `theme:install\n * @nexpress/theme-docs` get those fields generated for them.\n *\n * Membership / access: same path the catch-all uses for `pages`\n * — `findDocuments` already enforces `access.read` and\n * `community.visibility` so we don't need to gate here.\n */\n\ninterface DocsRow {\n id: string;\n slug: string;\n title: string;\n body?: unknown;\n parent?: string | null;\n order?: number;\n status?: string;\n excerpt?: string;\n}\n\nexport async function DocsDetailRoute({\n params,\n blockCtx,\n}: NpRouteRenderProps): Promise<React.ReactElement> {\n const slug = typeof params.slug === \"string\" ? params.slug : \"\";\n if (!slug) notFound();\n\n const result = await findDocuments<DocsRow>(\"docs\", {\n where: { slug, status: \"published\" },\n limit: 1,\n });\n const doc = result.docs[0];\n if (!doc) notFound();\n\n // `DocPageTemplate`'s prop generic defaults to\n // `Record<string, unknown>` — cast through `unknown` so our\n // narrower `DocsRow` shape (which doesn't carry an index\n // signature) matches the template's contract.\n const templateProps: NpTemplateRenderProps = {\n doc: doc as unknown as Record<string, unknown>,\n blockCtx,\n };\n return <DocPageTemplate {...templateProps} />;\n}\n","import * as React from \"react\";\nimport type { NpTemplateRenderProps } from \"@nexpress/theme\";\nimport { findDocuments } from \"@nexpress/core\";\n\nimport { resolveDocsSettings } from \"../settings-helpers.js\";\n\ninterface DocDoc {\n id: string;\n slug: string;\n title: string;\n body?: unknown;\n parent?: string | null;\n order?: number;\n}\n\n/**\n * Phase F.9-B — doc page template.\n *\n * Renders the doc's title + body, plus a prev/next bar at the\n * bottom that walks the same parent-ordered hierarchy the\n * sidebar uses. Optional \"Edit on GitHub\" link is added when\n * the operator set `settings.githubRepo`.\n *\n * Body rendering: this template assumes `doc.body` is a\n * Lexical / blocks payload. For a real F.9-B we'd thread\n * through `renderBlocks(doc.body, { ctx: blockCtx })` for the\n * actual content; the placeholder JSON keeps the contract\n * shape-correct without binding to a specific body shape that\n * may differ across operator setups.\n */\nexport async function DocPageTemplate({\n doc: rawDoc,\n}: NpTemplateRenderProps): Promise<React.ReactElement> {\n const doc = rawDoc as unknown as DocDoc;\n const settings = await resolveDocsSettings();\n\n const navInfo = await loadPrevNext(doc);\n\n return (\n <article className=\"np-docs-page\">\n <header>\n <h1>{doc.title}</h1>\n </header>\n <div className=\"np-docs-body\">\n {/* Operators that customize body rendering swap this\n placeholder for `renderBlocks(doc.body, { ctx })`\n or their own renderer. */}\n <pre style={{ whiteSpace: \"pre-wrap\", fontFamily: \"inherit\" }}>\n {typeof doc.body === \"string\" ? doc.body : \"Doc body unavailable.\"}\n </pre>\n </div>\n\n {settings.githubRepo ? (\n <p style={{ marginTop: \"2rem\" }}>\n <a\n href={`${settings.githubRepo}/edit/main/docs/${doc.slug}.md`}\n target=\"_blank\"\n rel=\"noreferrer\"\n style={{\n fontSize: \"0.875rem\",\n color: \"var(--np-color-muted-foreground)\",\n }}\n >\n ✏️ Edit on GitHub\n </a>\n </p>\n ) : null}\n\n <nav className=\"np-docs-prev-next\" aria-label=\"Pagination\">\n {navInfo.prev ? (\n <a href={`/docs/${navInfo.prev.slug}`}>\n <span className=\"np-docs-prev-next-label\">← Previous</span>\n {navInfo.prev.title}\n </a>\n ) : (\n <span />\n )}\n {navInfo.next ? (\n <a\n href={`/docs/${navInfo.next.slug}`}\n style={{ textAlign: \"right\" }}\n >\n <span className=\"np-docs-prev-next-label\">Next →</span>\n {navInfo.next.title}\n </a>\n ) : (\n <span />\n )}\n </nav>\n </article>\n );\n}\n\nasync function loadPrevNext(\n current: DocDoc,\n): Promise<{ prev: DocDoc | null; next: DocDoc | null }> {\n // For F.9-B we walk the same ordered list the sidebar uses\n // and pick the doc immediately before/after `current`. Cap\n // matches the sidebar (500); same query is cached at the\n // docs read path.\n const result = await findDocuments<Record<string, unknown>>(\"docs\", {\n where: { status: \"published\" },\n sort: \"order\",\n limit: 500,\n });\n const docs = result.docs as unknown as DocDoc[];\n const idx = docs.findIndex((d) => d.id === current.id);\n if (idx < 0) return { prev: null, next: null };\n return {\n prev: idx > 0 ? docs[idx - 1] ?? null : null,\n next: idx < docs.length - 1 ? docs[idx + 1] ?? null : null,\n };\n}\n","import * as React from \"react\";\nimport type { NpRouteRenderProps } from \"@nexpress/theme\";\nimport { getCollectionConfig, searchCollections } from \"@nexpress/core\";\n\n/**\n * Resolves a search-result URL via the collection's\n * `seo.urlPath` config when available, falling back to\n * `/<collection>/<slug>` convention. Without this, posts (which\n * typically live under `/blog/`) would 404 from search hits.\n * Wrapped in try/catch because `getCollectionConfig` throws for\n * unknown collections — a search adapter that returns rows from\n * a no-longer-registered collection shouldn't crash the page.\n */\nfunction resolveResultUrl(\n collection: string,\n doc: Record<string, unknown>,\n): string {\n try {\n const config = getCollectionConfig(collection);\n const urlPath = config.seo?.urlPath;\n if (typeof urlPath === \"function\") {\n const result = urlPath(doc);\n if (typeof result === \"string\" && result.length > 0) return result;\n }\n } catch {\n // Unknown collection or missing seo config — fall through.\n }\n const slug = typeof doc.slug === \"string\" ? doc.slug : \"\";\n return slug ? `/${collection}/${slug}` : \"#\";\n}\n\n/**\n * Phase F.9-B — `/search` route component.\n *\n * Reads `?q=` from searchParams, runs `searchCollections` (the\n * full-text search API), and renders the hits. Empty query →\n * empty results pane with hint copy. Stresses F.2's route\n * dispatch with a non-collection-walk shape (search is\n * cross-collection by design).\n */\n\nexport async function DocsSearch({\n searchParams,\n}: NpRouteRenderProps): Promise<React.ReactElement> {\n const raw = searchParams.q;\n const query = typeof raw === \"string\" ? raw.trim() : \"\";\n\n if (query.length === 0) {\n return (\n <div className=\"np-docs-search\">\n <h1>Search</h1>\n <p style={{ color: \"var(--np-color-muted-foreground)\" }}>\n Enter a query in the masthead search box to find pages.\n </p>\n </div>\n );\n }\n\n const result = await searchCollections({ q: query, limit: 20 });\n return (\n <div className=\"np-docs-search\">\n <h1>Search results for “{query}”</h1>\n {result.results.length === 0 ? (\n <p style={{ color: \"var(--np-color-muted-foreground)\" }}>No matches.</p>\n ) : (\n <ul style={{ listStyle: \"none\", padding: 0, margin: \"1.5rem 0 0\" }}>\n {result.results.map((item, i) => {\n const doc = item.doc;\n const slug = typeof doc.slug === \"string\" ? doc.slug : null;\n const title =\n typeof doc.title === \"string\" ? doc.title : (slug ?? \"Untitled\");\n const url = resolveResultUrl(item.collection, doc);\n return (\n <li\n key={`${item.collection}:${(doc.id as string | undefined) ?? i}`}\n style={{\n padding: \"1rem 0\",\n borderBottom: \"1px solid var(--np-color-border)\",\n }}\n >\n <p\n style={{\n margin: 0,\n fontSize: \"0.75rem\",\n textTransform: \"uppercase\",\n letterSpacing: \"0.08em\",\n color: \"var(--np-color-muted-foreground)\",\n }}\n >\n {item.collection}\n </p>\n <h2 style={{ margin: \"0.25rem 0 0.5rem\", fontSize: \"1.125rem\" }}>\n <a\n href={url}\n style={{ color: \"inherit\", textDecoration: \"none\" }}\n >\n {title}\n </a>\n </h2>\n {typeof doc.excerpt === \"string\" ? (\n <p\n style={{\n margin: 0,\n color: \"var(--np-color-muted-foreground)\",\n }}\n >\n {doc.excerpt}\n </p>\n ) : null}\n </li>\n );\n })}\n </ul>\n )}\n </div>\n );\n}\n","import * as React from \"react\";\nimport type { NpThemeShellProps } from \"@nexpress/theme\";\n\n/**\n * Phase F.9-B — docs theme shell.\n *\n * Body grid: header on top, then a 3-column row of sidebar +\n * main + (optional) TOC. The sidebar slot reads the docs\n * collection hierarchy; main is the page render; TOC is left\n * to the page template (it knows which headings the doc has).\n */\nexport function DocsShell({ children }: NpThemeShellProps): React.ReactElement {\n return (\n <div className=\"np-docs-shell\">\n <div className=\"np-docs-grid\">{children}</div>\n </div>\n );\n}\n","import * as React from \"react\";\nimport { findDocuments } from \"@nexpress/core\";\n\nimport { resolveDocsSettings } from \"./settings-helpers.js\";\n\ninterface DocNode {\n id: string;\n slug: string;\n title: string;\n parent: string | null;\n order: number;\n children: DocNode[];\n}\n\n/**\n * Phase F.9-B — hierarchical sidebar.\n *\n * Walks the `docs` collection (declared as required in the\n * manifest), builds a parent/order tree, renders nested nav.\n * The current doc is highlighted via `data-current=\"true\"`.\n *\n * The function reads `currentSlug` from a query param (when\n * called as a route component) or from doc context. For F.9-B\n * we keep it simple: the slot component fetches the request's\n * URL via `headers()` and matches on `pathname.startsWith`.\n */\nexport async function DocsSidebar(): Promise<React.ReactElement> {\n const settings = await resolveDocsSettings();\n\n // Pull every doc and assemble the hierarchy. Capped at 500 to\n // keep the query bounded — typical doc sites stay well under.\n const result = await findDocuments<Record<string, unknown>>(\"docs\", {\n where: { status: \"published\" },\n sort: \"order\",\n limit: 500,\n });\n\n const tree = buildTree(result.docs);\n // Active-link detection happens client-side via the URL; here\n // we just emit the static tree. The CSS uses `aria-current`\n // (set by Next's link-active conventions) plus the\n // `data-current` we'd set if we threaded the current path\n // through; F.9-B leaves this as a polish item — links work,\n // the highlight is missing.\n return (\n <aside className=\"np-docs-sidebar\" aria-label=\"Docs navigation\">\n <h2>{settings.sidebarHeading}</h2>\n <NavTree nodes={tree} />\n </aside>\n );\n}\n\ninterface DocRow {\n id: unknown;\n slug: unknown;\n title: unknown;\n parent: unknown;\n order: unknown;\n}\n\nfunction buildTree(rawDocs: Record<string, unknown>[]): DocNode[] {\n const docs = rawDocs as unknown as DocRow[];\n const byId = new Map<string, DocNode>();\n // First pass: every doc as a flat node with empty children.\n for (const d of docs) {\n if (typeof d.id !== \"string\") continue;\n if (typeof d.slug !== \"string\") continue;\n byId.set(d.id, {\n id: d.id,\n slug: d.slug,\n title: typeof d.title === \"string\" ? d.title : d.slug,\n parent: typeof d.parent === \"string\" ? d.parent : null,\n order: typeof d.order === \"number\" ? d.order : 0,\n children: [],\n });\n }\n // Second pass: hang each non-root under its parent.\n const roots: DocNode[] = [];\n for (const node of byId.values()) {\n if (node.parent && byId.has(node.parent)) {\n byId.get(node.parent)!.children.push(node);\n } else {\n roots.push(node);\n }\n }\n // Sort by order at every level.\n const sortRec = (list: DocNode[]) => {\n list.sort((a, b) => a.order - b.order);\n for (const n of list) sortRec(n.children);\n };\n sortRec(roots);\n return roots;\n}\n\nfunction NavTree({ nodes }: { nodes: DocNode[] }): React.ReactElement {\n return (\n <ul>\n {nodes.map((n) => (\n <li key={n.id}>\n <a href={`/docs/${n.slug}`}>{n.title}</a>\n {n.children.length > 0 ? <NavTree nodes={n.children} /> : null}\n </li>\n ))}\n </ul>\n );\n}\n","/**\n * Phase F.9-B — docs theme CSS.\n *\n * Scoped under `.np-docs-*` so theme swaps don't leave\n * residue. Uses `var(--np-color-*)` tokens so admin\n * settings → tokens still apply on top.\n */\nexport const docsCss = `\n.np-docs-shell {\n display: flex;\n flex-direction: column;\n min-height: 100vh;\n background: var(--np-color-background);\n color: var(--np-color-foreground);\n font-family: var(--np-font-body, system-ui, sans-serif);\n}\n\n.np-docs-header {\n position: sticky;\n top: 0;\n z-index: 50;\n background: var(--np-color-background);\n border-bottom: 1px solid var(--np-color-border);\n backdrop-filter: blur(8px);\n}\n\n.np-docs-header-inner {\n max-width: 1200px;\n margin: 0 auto;\n padding: 0.75rem 1.5rem;\n display: grid;\n grid-template-columns: auto 1fr auto;\n gap: 1.5rem;\n align-items: center;\n}\n\n.np-docs-brand {\n display: flex;\n align-items: baseline;\n gap: 0.5rem;\n font-weight: 600;\n text-decoration: none;\n color: var(--np-color-foreground);\n}\n\n.np-docs-brand-version {\n font-size: 0.75rem;\n font-family: ui-monospace, \"SF Mono\", Menlo, monospace;\n color: var(--np-color-muted-foreground);\n background: var(--np-color-muted);\n padding: 0.125rem 0.375rem;\n border-radius: 0.25rem;\n}\n\n.np-docs-search-form {\n flex: 1;\n}\n\n.np-docs-search-input {\n width: 100%;\n padding: 0.4rem 0.75rem;\n border: 1px solid var(--np-color-border);\n border-radius: 0.375rem;\n background: var(--np-color-card);\n color: var(--np-color-foreground);\n font-size: 0.875rem;\n}\n\n.np-docs-search-input:focus {\n outline: 2px solid var(--np-color-primary);\n outline-offset: -2px;\n border-color: transparent;\n}\n\n.np-docs-nav {\n display: flex;\n align-items: center;\n gap: 1rem;\n}\n\n.np-docs-primary-nav {\n display: flex;\n list-style: none;\n margin: 0;\n padding: 0;\n gap: 1rem;\n}\n\n.np-docs-primary-nav a {\n color: var(--np-color-muted-foreground);\n text-decoration: none;\n font-size: 0.875rem;\n}\n\n.np-docs-primary-nav a:hover {\n color: var(--np-color-foreground);\n}\n\n.np-docs-github-link {\n font-size: 0.875rem;\n color: var(--np-color-muted-foreground);\n text-decoration: none;\n}\n\n.np-docs-grid {\n flex: 1;\n display: grid;\n grid-template-columns: 240px minmax(0, 1fr);\n max-width: 1200px;\n margin: 0 auto;\n width: 100%;\n gap: 2.5rem;\n padding: 2rem 1.5rem;\n}\n\n@media (max-width: 768px) {\n .np-docs-grid {\n grid-template-columns: 1fr;\n }\n .np-docs-sidebar {\n display: none;\n }\n}\n\n.np-docs-sidebar {\n position: sticky;\n top: 4rem;\n align-self: start;\n max-height: calc(100vh - 5rem);\n overflow-y: auto;\n}\n\n.np-docs-sidebar h2 {\n font-size: 0.75rem;\n text-transform: uppercase;\n letter-spacing: 0.08em;\n color: var(--np-color-muted-foreground);\n margin: 0 0 0.75rem;\n}\n\n.np-docs-sidebar ul {\n list-style: none;\n padding: 0;\n margin: 0;\n}\n\n.np-docs-sidebar li {\n margin: 0.125rem 0;\n}\n\n.np-docs-sidebar a {\n display: block;\n padding: 0.25rem 0.5rem;\n border-radius: 0.25rem;\n color: var(--np-color-muted-foreground);\n text-decoration: none;\n font-size: 0.875rem;\n}\n\n.np-docs-sidebar a:hover {\n background: var(--np-color-muted);\n color: var(--np-color-foreground);\n}\n\n.np-docs-sidebar a[data-current=\"true\"] {\n background: color-mix(in oklch, var(--np-color-primary) 12%, transparent);\n color: var(--np-color-primary);\n font-weight: 500;\n}\n\n.np-docs-sidebar ul ul {\n margin-left: 0.75rem;\n border-left: 1px solid var(--np-color-border);\n padding-left: 0.5rem;\n}\n\n.np-docs-page {\n max-width: 720px;\n}\n\n.np-docs-page h1 {\n font-size: 2rem;\n margin: 0 0 0.5rem;\n}\n\n.np-docs-prev-next {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 1rem;\n margin-top: 3rem;\n padding-top: 1.5rem;\n border-top: 1px solid var(--np-color-border);\n}\n\n.np-docs-prev-next a {\n display: block;\n padding: 0.75rem 1rem;\n border: 1px solid var(--np-color-border);\n border-radius: 0.5rem;\n color: var(--np-color-foreground);\n text-decoration: none;\n}\n\n.np-docs-prev-next a:hover {\n border-color: var(--np-color-primary);\n}\n\n.np-docs-prev-next-label {\n display: block;\n font-size: 0.75rem;\n color: var(--np-color-muted-foreground);\n margin-bottom: 0.25rem;\n}\n\n/* M.* member surface — narrow auth-form column under the\n masthead, no sidebar (the docs sidebar is hierarchical\n doc nav, useless on auth forms). */\n.np-docs-members {\n display: flex;\n justify-content: center;\n min-height: 60vh;\n padding: 3rem 1.5rem;\n}\n.np-docs-members-column {\n width: 100%;\n max-width: 440px;\n}\n\n/* Member form token overrides — docs aesthetic: slightly\n rounded corners, neutral palette, monospace label accent. */\n.np-docs .np-members-form {\n --np-member-form-input-bg: var(--np-color-background);\n --np-member-form-input-border: var(--np-color-border);\n --np-member-form-input-border-focus: var(--np-color-primary);\n --np-member-form-input-radius: 0.375rem;\n --np-member-form-button-radius: 0.375rem;\n}\n.np-docs .np-members-form .np-form-label {\n font-family: var(--np-font-mono, ui-monospace, monospace);\n font-size: 0.8125rem;\n}\n`;\n"],"mappings":"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","names":["jsx","jsxs","jsx","jsxs","jsx","jsxs","findDocuments","jsx","jsxs","jsx","findDocuments","jsx","jsxs","jsx","findDocuments","jsx","jsxs","findDocuments"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nexpress/theme-docs",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Documentation theme for NexPress — hierarchical sidebar, prev/next nav, in-page TOC.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Nexpress",
|
|
7
|
+
"homepage": "https://github.com/nexpress-cms/nexpress#readme",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/nexpress-cms/nexpress.git",
|
|
11
|
+
"directory": "packages/themes/docs"
|
|
12
|
+
},
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/nexpress-cms/nexpress/issues"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"nexpress",
|
|
18
|
+
"theme",
|
|
19
|
+
"docs"
|
|
20
|
+
],
|
|
21
|
+
"type": "module",
|
|
22
|
+
"main": "./dist/index.js",
|
|
23
|
+
"types": "./dist/index.d.ts",
|
|
24
|
+
"exports": {
|
|
25
|
+
".": {
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"import": "./dist/index.js"
|
|
28
|
+
},
|
|
29
|
+
"./components/error": {
|
|
30
|
+
"types": "./dist/components/error.d.ts",
|
|
31
|
+
"import": "./dist/components/error.js"
|
|
32
|
+
},
|
|
33
|
+
"./components/members-error": {
|
|
34
|
+
"types": "./dist/components/members-error.d.ts",
|
|
35
|
+
"import": "./dist/components/members-error.js"
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"files": [
|
|
39
|
+
"dist"
|
|
40
|
+
],
|
|
41
|
+
"engines": {
|
|
42
|
+
"node": ">=20"
|
|
43
|
+
},
|
|
44
|
+
"peerDependencies": {
|
|
45
|
+
"next": "^15.0.0 || ^16.0.0",
|
|
46
|
+
"react": "^19.0.0",
|
|
47
|
+
"react-dom": "^19.0.0"
|
|
48
|
+
},
|
|
49
|
+
"dependencies": {
|
|
50
|
+
"zod": "^4.3.6",
|
|
51
|
+
"@nexpress/core": "0.1.0",
|
|
52
|
+
"@nexpress/editor": "0.1.0",
|
|
53
|
+
"@nexpress/next": "0.1.0",
|
|
54
|
+
"@nexpress/blocks": "0.1.0",
|
|
55
|
+
"@nexpress/theme": "0.1.0"
|
|
56
|
+
},
|
|
57
|
+
"devDependencies": {
|
|
58
|
+
"@types/react": "^19.0.0",
|
|
59
|
+
"@types/react-dom": "^19.0.0",
|
|
60
|
+
"next": "^16.2.4",
|
|
61
|
+
"react": "^19.0.0",
|
|
62
|
+
"react-dom": "^19.0.0",
|
|
63
|
+
"tsup": "^8.5.0",
|
|
64
|
+
"typescript": "^5.8.0"
|
|
65
|
+
},
|
|
66
|
+
"scripts": {
|
|
67
|
+
"build": "tsup",
|
|
68
|
+
"dev": "tsup --watch --no-clean",
|
|
69
|
+
"clean": "rm -rf dist",
|
|
70
|
+
"typecheck": "tsc --noEmit",
|
|
71
|
+
"lint": "eslint . --cache --cache-location node_modules/.cache/eslint"
|
|
72
|
+
}
|
|
73
|
+
}
|