@nexpress/theme-docs 0.2.2 → 0.3.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/dist/index.js.map CHANGED
@@ -1 +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&apos;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 add\n * @nexpress/theme-docs` get those fields auto-merged into their\n * docs collection by `defineConfig`.\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 &ldquo;{query}&rdquo;</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"]}
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/toc-scrollspy-bridge.ts","../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\nconst SEED_NAV = {\n header: [\n { id: \"nav-docs-docs\", label: \"Docs\", type: \"link\" as const, url: \"/docs\" },\n { id: \"nav-docs-reference\", label: \"Reference\", type: \"link\" as const, url: \"/docs/reference\" },\n { id: \"nav-docs-blog\", label: \"Blog\", type: \"link\" as const, url: \"/blog\" },\n ],\n footer: [\n { id: \"nav-docs-footer-docs\", label: \"Documentation\", type: \"link\" as const, url: \"/docs\" },\n { id: \"nav-docs-footer-reference\", label: \"Reference\", type: \"link\" as const, url: \"/docs/reference\" },\n { id: \"nav-docs-footer-changelog\", label: \"Changelog\", type: \"link\" as const, url: \"/changelog\" },\n { id: \"nav-docs-footer-github\", label: \"GitHub\", type: \"link\" as const, url: \"https://github.com\" },\n ],\n};\n\n/**\n * `@nexpress/theme-docs` — documentation theme for NexPress.\n *\n * Three-column reference-docs layout: sticky search-first header\n * (brand mark + version pill + ⌘K search + primary nav + GitHub\n * link), hierarchical sidebar with bullet-eyebrow groups + nested\n * links + status badges, centered article column with breadcrumbs\n * + lede + meta pills + Lexical body, on-this-page TOC on the\n * right. Sidebar collapses out at the tablet breakpoint; TOC\n * collapses out below 1100px.\n *\n * Pairs with `posts` rows of `kind: \"doc\"`\n * (universal-content-model #748 — docs are posts with a kind\n * discriminator, not a separate collection). The doc-specific\n * fields (`lede`, `stableSince`) are contributed via\n * `requires.collections.posts.fields` and merged onto the\n * built-in posts collection at config-resolution time.\n *\n * `seedContent.navigation` ships the primary header / footer\n * links. Doc rows are operator-authored; themes that want to\n * seed kind=\"doc\" content use `seedContent.posts` with the\n * `kind` field set on each entry (see U.1 #749).\n */\nexport const docsTheme = defineTheme({\n manifest: {\n id: \"docs\",\n name: \"Docs\",\n version: \"0.2.0\",\n description:\n \"Documentation theme — three-column layout with hierarchical sidebar, breadcrumbs + lede + meta pills on the article column, on-this-page TOC on the right rail. Blue accent on a near-white surface; pairs with a `docs` collection.\",\n author: { name: \"NexPress\" },\n nexpress: { minVersion: \"0.1.0\" },\n requires: {\n collections: {\n posts: {\n // Universal-content-model #748 — docs are posts with\n // `kind: \"doc\"`. The framework's built-in `posts`\n // collection already supplies `title` / `body` /\n // `parent` (rel→posts) / `order`. Docs theme adds the\n // doc-specific meta pills and contributes the kind\n // option + kinds metadata block for admin / URL\n // routing.\n fields: {\n kind: {\n type: \"select\",\n options: [{ label: \"Doc\", value: \"doc\" }],\n },\n // Short opening paragraph rendered as a lede under\n // the h1. Optional — the article still renders\n // without it. Lives in a \"Docs\" sidebar group with\n // `stableSince`; the group + fields hide entirely\n // when the active kind isn't `\"doc\"`.\n lede: {\n type: \"textarea\",\n hard: false,\n admin: {\n position: \"sidebar\",\n group: \"Docs\",\n condition: { when: \"kind\", equals: \"doc\" },\n },\n },\n // Meta-pill slot — advisory hint the doc-page\n // template surfaces in the strap row. Note: portfolio\n // theme also contributes a `badge: text` field on\n // posts; the merge-requirements union picks the first\n // declarer. Docs reads `doc.badge` regardless of which\n // theme declared the column.\n stableSince: {\n type: \"text\",\n hard: false,\n admin: {\n position: \"sidebar\",\n group: \"Docs\",\n condition: { when: \"kind\", equals: \"doc\" },\n },\n },\n },\n groupMeta: {\n Docs: {\n icon: \"BookOpen\",\n description: \"Doc-specific meta — lede and API stability hint.\",\n },\n },\n kinds: {\n doc: {\n label: \"Doc\",\n labelPlural: \"Documentation\",\n icon: \"BookOpen\",\n // Public-site URL pattern. The catch-all router\n // matches `/docs/<slug>` and queries posts with\n // `where: { kind: \"doc\", slug }`.\n urlPattern: \"/docs/:slug\",\n // Hint to admin: show parent + order controls and\n // render the list as a tree, not a flat table.\n hierarchical: true,\n },\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 colors: {\n primary: \"#2563eb\",\n primaryForeground: \"#ffffff\",\n background: \"#fbfcfe\",\n foreground: \"#0c1320\",\n muted: \"#f1f4f9\",\n mutedForeground: \"#5b6478\",\n border: \"#e2e7ef\",\n card: \"#ffffff\",\n },\n typography: {\n fontHeading:\n '\"Geist\", -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif',\n fontBody:\n '\"Geist\", -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif',\n fontMono:\n '\"Geist Mono\", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace',\n },\n shape: {\n radiusSm: \"5px\",\n radiusMd: \"9px\",\n radiusLg: \"10px\",\n },\n },\n seedContent: {\n navigation: SEED_NAV,\n },\n templates: {\n // Universal-content-model #748 — docs are posts with\n // `kind: \"doc\"`. The template key matches the kind value so\n // the per-kind template lookup picks this up automatically.\n // Article-kind posts continue rendering through the\n // framework's inline article markup unless the operator\n // declares a `templates.posts.default` of their own.\n posts: {\n doc: {\n label: \"Doc page\",\n description:\n \"Three-column reference layout — breadcrumbs + lede + meta + Lexical body + feedback + prev/next, with the docs sidebar slotted on the left and the on-page TOC on the right.\",\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. The sidebar + template emit\n // `/docs/<slug>` links; the route component looks up the\n // doc-kind post by slug and renders through DocPageTemplate.\n // Universal-content-model #748 — docs are posts with\n // `kind=\"doc\"`; the lookup filters on kind, not collection.\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, getCachedSite } from \"@nexpress/next\";\n\nimport { SearchKeyboardShortcut } from \"./components/search-keyboard-shortcut.js\";\nimport { resolveDocsSettings } from \"./settings-helpers.js\";\n\nconst FALLBACK_SITE_NAME = \"NexPress\";\n\n/**\n * Docs theme masthead. Brand strap (mark + wordmark + version\n * pill) on the left, ⌘K search form centered, primary nav +\n * GitHub repo link on the right.\n *\n * Search is a plain GET form to `/docs/search` — the theme's\n * own route handles the query so the host's `(site)/search`\n * page doesn't shadow it (#609). The ⌘K affordance is purely\n * visual hint copy in a `<kbd>`; wiring it to a global hotkey\n * is a separate client island sites can add on top.\n *\n * The GitHub link reads `settings.githubRepo`. When the admin\n * setting is unset, the link is hidden.\n */\nexport async function DocsHeader(): Promise<React.ReactElement> {\n const [settings, site] = await Promise.all([\n resolveDocsSettings(),\n getCachedSite(),\n ]);\n const siteName = site?.name?.trim() || FALLBACK_SITE_NAME;\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-mark\" aria-hidden=\"true\" />\n <span className=\"np-docs-brand-name\">{siteName}</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 <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n aria-hidden=\"true\"\n >\n <circle cx=\"11\" cy=\"11\" r=\"7\" />\n <path d=\"m21 21-4.3-4.3\" />\n </svg>\n <label className=\"sr-only\" htmlFor=\"np-docs-search-input\">\n Search the docs\n </label>\n <input\n id=\"np-docs-search-input\"\n type=\"search\"\n name=\"q\"\n placeholder={settings.searchPlaceholder}\n className=\"np-docs-search-input\"\n />\n <kbd className=\"np-docs-search-kbd\">⌘K</kbd>\n </form>\n <SearchKeyboardShortcut targetId=\"np-docs-search-input\" />\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\"\n target=\"_blank\"\n rel=\"noreferrer\"\n aria-label=\"GitHub repository\"\n >\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path d=\"M12 .5a12 12 0 0 0-3.8 23.39c.6.11.82-.26.82-.58v-2c-3.34.73-4.04-1.61-4.04-1.61-.55-1.39-1.34-1.76-1.34-1.76-1.1-.75.08-.74.08-.74 1.21.09 1.85 1.24 1.85 1.24 1.07 1.84 2.81 1.31 3.5 1 .11-.78.42-1.31.76-1.61-2.66-.3-5.47-1.33-5.47-5.93 0-1.31.47-2.38 1.24-3.22-.12-.3-.54-1.52.12-3.17 0 0 1-.32 3.3 1.23a11.5 11.5 0 0 1 6 0c2.28-1.55 3.29-1.23 3.29-1.23.66 1.65.25 2.87.12 3.17.77.84 1.24 1.91 1.24 3.22 0 4.61-2.81 5.62-5.49 5.92.43.37.81 1.1.81 2.22v3.29c0 .32.22.7.83.58A12 12 0 0 0 12 .5Z\" />\n </svg>\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&apos;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 doc-kind post and\n * renders it through `DocPageTemplate`.\n *\n * Universal-content-model #748: docs are posts with `kind=\"doc\"`.\n * The framework's catch-all also matches `/docs/:slug` via the\n * theme's `kinds.doc.urlPattern` metadata; this explicit theme\n * route stays for two reasons:\n *\n * 1. It's the supported path for theme-internal navigation\n * that bypasses the kinds-metadata dispatcher (prev/next,\n * sidebar links).\n * 2. It runs ahead of the kinds dispatcher in the precedence\n * order so a future themes feature that needs to wrap\n * doc-page rendering (e.g. signing-aware drafts) can hook\n * in here without touching the framework.\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 kind?: 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>(\"posts\", {\n where: { slug, status: \"published\", kind: \"doc\" },\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, type NpRichTextContent } from \"@nexpress/core\";\nimport { extractHeadingToc, renderRichText } from \"@nexpress/editor/server\";\n\n// Routed via a sibling-depth bridge module (`../toc-scrollspy-\n// bridge.js`) rather than `../components/toc-scrollspy.js`\n// directly: tsup's `external` rule matches the import specifier\n// verbatim, and a parent-relative spec at this depth would\n// preserve `\"../components/...\"` in the bundled `dist/index.js`\n// (escapes dist at consume time). The bridge re-exports from a\n// sibling-depth path that DOES match the external rule, so the\n// final bundle carries `import \"./components/toc-scrollspy.js\"`\n// which resolves cleanly to `dist/components/toc-scrollspy.js`.\n// A package-subpath self-import was tried first but fails\n// during tsup's parallel dts step (the index dts can't see the\n// component's freshly-written .d.ts in time, TS7016).\nimport { TocScrollspy } from \"../toc-scrollspy-bridge.js\";\nimport { resolveDocsSettings } from \"../settings-helpers.js\";\n\ninterface DocDoc {\n id: string;\n slug: string;\n title: string;\n lede?: string;\n body?: NpRichTextContent;\n parent?: string | null;\n order?: number;\n updatedAt?: string | Date;\n publishedAt?: string | Date;\n stableSince?: string;\n readingTime?: number | string;\n}\n\n\n/**\n * Doc page template — three-zone article: header strap\n * (breadcrumbs + h1 + lede + meta pills), Lexical-rendered body,\n * footer (feedback widget + prev/next pair).\n *\n * Breadcrumbs walk the parent chain so a nested doc shows\n * `Docs / Plugins / Author quickstart` without the operator\n * configuring it explicitly. Falls back to a single \"Docs\" entry\n * for root-level pages.\n *\n * Meta pills render only when their data is present:\n *\n * - `stableSince` (e.g. `\"0.1\"`) → green pill `\"Stable since 0.1\"`.\n * - `readingTime` (number or string) → `\"X min read\"` pill.\n * - `updatedAt` → date string after a · separator.\n * - `settings.githubRepo` set → `\"Edit this page →\"` link to GH.\n *\n * Feedback row is static HTML (Yes / Could be better buttons)\n * without a wired endpoint — operators that want a real\n * feedback API drop in their own client island.\n *\n * Prev/next walks the same ordered list the sidebar uses; the\n * doc immediately before / after `current` in render-order wins.\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 const breadcrumbs = await loadBreadcrumbs(doc);\n const navInfo = await loadPrevNext(doc);\n const updatedLabel = formatUpdated(doc.updatedAt ?? doc.publishedAt);\n const readingLabel = readingMinutesLabel(doc.readingTime);\n const editHref = settings.githubRepo\n ? `${settings.githubRepo}/edit/main/docs/${doc.slug}.md`\n : null;\n const toc = extractHeadingToc(doc.body);\n const reportIssueHref = settings.githubRepo\n ? `${settings.githubRepo}/issues/new`\n : null;\n\n return (\n <>\n <article className=\"np-docs-page\">\n <nav className=\"np-docs-breadcrumbs\" aria-label=\"Breadcrumb\">\n {breadcrumbs.map((crumb, index) => {\n const isLast = index === breadcrumbs.length - 1;\n return (\n <React.Fragment key={`crumb-${index.toString()}-${crumb.slug ?? \"root\"}`}>\n {index > 0 ? (\n <span className=\"np-docs-breadcrumbs-sep\" aria-hidden=\"true\">\n /\n </span>\n ) : null}\n {isLast || !crumb.slug ? (\n <span>{crumb.title}</span>\n ) : (\n <a href={`/docs/${crumb.slug}`}>{crumb.title}</a>\n )}\n </React.Fragment>\n );\n })}\n </nav>\n\n <h1>{doc.title}</h1>\n {doc.lede ? <p className=\"np-docs-page-lede\">{doc.lede}</p> : null}\n\n {(doc.stableSince || readingLabel || updatedLabel || editHref) ? (\n <div className=\"np-docs-page-meta\">\n {doc.stableSince ? (\n <span className=\"np-docs-page-meta-pill status\">\n Stable since {doc.stableSince}\n </span>\n ) : null}\n {readingLabel ? (\n <span className=\"np-docs-page-meta-pill\">{readingLabel}</span>\n ) : null}\n {updatedLabel ? (\n <>\n <span className=\"np-docs-page-meta-sep\" aria-hidden=\"true\">\n ·\n </span>\n <span>Updated {updatedLabel}</span>\n </>\n ) : null}\n {editHref ? (\n <a href={editHref} target=\"_blank\" rel=\"noreferrer\">\n Edit this page →\n </a>\n ) : null}\n </div>\n ) : null}\n\n <div className=\"np-docs-page-body\">\n {doc.body ? (\n // Core types `NpRichTextContent` as the opaque\n // `Record<string, unknown>`; the editor's renderer\n // refines it to `{ root: ... }`. Structural cast at\n // the boundary — both sides go through the same\n // Lexical serializer.\n renderRichText(doc.body as unknown as Parameters<typeof renderRichText>[0])\n ) : (\n <p style={{ color: \"var(--np-color-muted-foreground)\" }}>\n No body content yet.\n </p>\n )}\n </div>\n\n <div className=\"np-docs-feedback\">\n <div>\n <div className=\"np-docs-feedback-title\">Was this page helpful?</div>\n <div className=\"np-docs-feedback-helper\">\n Operators wire the feedback endpoint via a plugin or a custom\n client island — the form is intentionally inert in v0.1.\n </div>\n </div>\n <div className=\"np-docs-feedback-buttons\">\n <button type=\"button\">Yes</button>\n <button type=\"button\">Could be better</button>\n </div>\n </div>\n\n <nav className=\"np-docs-prev-next\" aria-label=\"Pagination\">\n {navInfo.prev ? (\n <a\n href={`/docs/${navInfo.prev.slug}`}\n className=\"np-docs-prev-next-prev\"\n >\n <div className=\"np-docs-prev-next-dir\">← Previous</div>\n <div className=\"np-docs-prev-next-title\">{navInfo.prev.title}</div>\n </a>\n ) : (\n <span />\n )}\n {navInfo.next ? (\n <a\n href={`/docs/${navInfo.next.slug}`}\n className=\"np-docs-prev-next-next\"\n >\n <div className=\"np-docs-prev-next-dir\">Next →</div>\n <div className=\"np-docs-prev-next-title\">{navInfo.next.title}</div>\n </a>\n ) : (\n <span />\n )}\n </nav>\n </article>\n\n {toc.length > 0 ? (\n <aside className=\"np-docs-toc\" aria-label=\"On this page\">\n <p className=\"np-docs-toc-eyebrow\">On this page</p>\n <ul>\n {toc.map((entry) => (\n <li\n key={`toc-${entry.id}`}\n style={entry.level === 3 ? { marginLeft: \"0.85rem\" } : undefined}\n >\n <a href={`#${entry.id}`}>{entry.text}</a>\n </li>\n ))}\n </ul>\n <TocScrollspy ids={toc.map((entry) => entry.id)} />\n\n {(editHref || reportIssueHref) ? (\n <div className=\"np-docs-toc-secondary\">\n {editHref ? (\n <a href={editHref} target=\"_blank\" rel=\"noreferrer\">\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n aria-hidden=\"true\"\n >\n <path d=\"M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7\" />\n <path d=\"m18.5 2.5 3 3L12 15l-4 1 1-4 9.5-9.5z\" />\n </svg>\n Edit on GitHub\n </a>\n ) : null}\n {reportIssueHref ? (\n <a href={reportIssueHref} target=\"_blank\" rel=\"noreferrer\">\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n aria-hidden=\"true\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3\" />\n <line x1=\"12\" y1=\"17\" x2=\"12.01\" y2=\"17\" />\n </svg>\n Report an issue\n </a>\n ) : null}\n </div>\n ) : null}\n </aside>\n ) : null}\n </>\n );\n}\n\ninterface Crumb {\n slug: string | null;\n title: string;\n}\n\nasync function loadBreadcrumbs(current: DocDoc): Promise<Crumb[]> {\n const root: Crumb = { slug: null, title: \"Docs\" };\n if (!current.parent) {\n return [root, { slug: null, title: current.title }];\n }\n // Walk parents in a single bounded query — sidebar already\n // pulls the same list so the row count is small.\n const result = await findDocuments<Record<string, unknown>>(\"posts\", {\n where: { status: \"published\", kind: \"doc\" },\n sort: \"order\",\n limit: 500,\n });\n const byId = new Map<string, DocDoc>();\n for (const r of result.docs as unknown as DocDoc[]) {\n if (r.id) byId.set(r.id, r);\n }\n const chain: Crumb[] = [];\n let cursor: string | null = current.parent;\n let safety = 6;\n while (cursor && safety-- > 0) {\n const node = byId.get(cursor);\n if (!node) break;\n chain.unshift({ slug: node.slug, title: node.title });\n cursor = node.parent ?? null;\n }\n return [root, ...chain, { slug: null, title: current.title }];\n}\n\nasync function loadPrevNext(\n current: DocDoc,\n): Promise<{ prev: DocDoc | null; next: DocDoc | null }> {\n const result = await findDocuments<Record<string, unknown>>(\"posts\", {\n where: { status: \"published\", kind: \"doc\" },\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\nfunction formatUpdated(value: DocDoc[\"updatedAt\"]): string | null {\n if (!value) return null;\n try {\n const d = typeof value === \"string\" ? new Date(value) : value;\n if (Number.isNaN(d.getTime())) return null;\n return d.toLocaleDateString(undefined, {\n year: \"numeric\",\n month: \"short\",\n day: \"numeric\",\n });\n } catch {\n return null;\n }\n}\n\nfunction readingMinutesLabel(value: DocDoc[\"readingTime\"]): string | null {\n if (!value && value !== 0) return null;\n if (typeof value === \"number\") return `${value.toString()} min read`;\n return value;\n}\n","// Sibling-depth re-export of the client TocScrollspy component.\n//\n// Why this file exists: `doc-page.tsx` lives at `src/templates/`\n// and needs the client island that lives at\n// `src/components/toc-scrollspy.tsx`. Importing it directly\n// would require `../components/toc-scrollspy.js`, and tsup's\n// `external` rule matches the specifier verbatim — a parent-\n// relative spec gets baked into `dist/index.js` and escapes the\n// dist root at consume time (Turbopack reports `Module not\n// found`).\n//\n// Routing through this bridge moves the externalized import to\n// sibling-depth (`./components/toc-scrollspy.js`) which is what\n// the `dist/` layout expects.\nexport { TocScrollspy } from \"./components/toc-scrollspy.js\";\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 &ldquo;{query}&rdquo;</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 /**\n * Optional small label rendered next to the link\n * (`new` / `beta` / `api`). Renders as a pill via the\n * `.np-docs-sidebar-badge.{value}` selector in styles.ts.\n * Treated as advisory; sites without the field render no\n * badge.\n */\n badge: string | null;\n children: DocNode[];\n}\n\n/**\n * Hierarchical sidebar for the docs theme.\n *\n * Top-level docs (those without a `parent`) become **group\n * eyebrows** rendered with a bullet dot indicator; each\n * group's children are the linkable items under the eyebrow.\n * Deeper levels render as nested lists with a hairline left\n * rule.\n *\n * The current doc is highlighted via `data-current=\"true\"`\n * resolved from the request's pathname. Wired through\n * `next/headers` (`x-np-pathname`) so the highlight survives\n * server rendering with no client-side hydration.\n */\nexport async function DocsSidebar(): Promise<React.ReactElement> {\n const settings = await resolveDocsSettings();\n const currentSlug = await currentPathSlug();\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 // Universal-content-model #748: docs are posts with kind=\"doc\".\n const result = await findDocuments<Record<string, unknown>>(\"posts\", {\n where: { status: \"published\", kind: \"doc\" },\n sort: \"order\",\n limit: 500,\n });\n\n const tree = buildTree(result.docs);\n\n if (tree.length === 0) {\n return (\n <aside className=\"np-docs-sidebar\" aria-label=\"Docs navigation\">\n <div className=\"np-docs-sidebar-group\">\n <h2 className=\"np-docs-sidebar-eyebrow\">\n <span className=\"np-docs-sidebar-eyebrow-dot\" aria-hidden=\"true\" />\n {settings.sidebarHeading}\n </h2>\n <p\n style={{\n padding: \"0.34rem 0.6rem\",\n fontSize: \"0.875rem\",\n color: \"var(--np-color-muted-foreground)\",\n margin: 0,\n }}\n >\n No docs yet.\n </p>\n </div>\n </aside>\n );\n }\n\n return (\n <aside className=\"np-docs-sidebar\" aria-label=\"Docs navigation\">\n {tree.map((group) => (\n <div className=\"np-docs-sidebar-group\" key={group.id}>\n <h2 className=\"np-docs-sidebar-eyebrow\">\n <span className=\"np-docs-sidebar-eyebrow-dot\" aria-hidden=\"true\" />\n {group.title}\n </h2>\n {group.children.length > 0 ? (\n <NavTree nodes={group.children} currentSlug={currentSlug} />\n ) : (\n <ul>\n <SidebarLink node={group} currentSlug={currentSlug} />\n </ul>\n )}\n </div>\n ))}\n </aside>\n );\n}\n\ninterface DocRow {\n id: unknown;\n slug: unknown;\n title: unknown;\n parent: unknown;\n order: unknown;\n badge: unknown;\n}\n\nasync function currentPathSlug(): Promise<string | null> {\n try {\n const { headers } = await import(\"next/headers\");\n const list = await headers();\n const pathname = list.get(\"x-np-pathname\");\n if (!pathname) return null;\n const m = /^\\/docs\\/(.+?)\\/?$/.exec(pathname);\n return m ? (m[1] ?? null) : null;\n } catch {\n return null;\n }\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 badge: typeof d.badge === \"string\" ? d.badge : null,\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({\n nodes,\n currentSlug,\n}: {\n nodes: DocNode[];\n currentSlug: string | null;\n}): React.ReactElement {\n return (\n <ul>\n {nodes.map((n) => (\n <li key={n.id}>\n <SidebarLink node={n} currentSlug={currentSlug} />\n {n.children.length > 0 ? (\n <NavTree nodes={n.children} currentSlug={currentSlug} />\n ) : null}\n </li>\n ))}\n </ul>\n );\n}\n\nfunction SidebarLink({\n node,\n currentSlug,\n}: {\n node: DocNode;\n currentSlug: string | null;\n}): React.ReactElement {\n const isCurrent = currentSlug !== null && currentSlug === node.slug;\n const badgeClass = node.badge\n ? `np-docs-sidebar-badge ${node.badge.toLowerCase()}`\n : null;\n return (\n <a\n href={`/docs/${node.slug}`}\n data-current={isCurrent ? \"true\" : undefined}\n aria-current={isCurrent ? \"page\" : undefined}\n >\n {node.title}\n {badgeClass ? (\n <span className={badgeClass}>{node.badge!.toUpperCase()}</span>\n ) : null}\n </a>\n );\n}\n","/**\n * `@nexpress/theme-docs` — CSS layout.\n *\n * Three-column reference-docs layout: sticky search-first header,\n * hierarchical sidebar (groups with bullet eyebrows + nested\n * links + status badges), centered article column, on-this-page\n * TOC on the right. Sidebar + TOC collapse out below the\n * tablet / phone breakpoints respectively.\n *\n * Scoped under `.np-docs-*` so a theme swap to another v0.2\n * theme doesn't leave residue. All colors resolve through the\n * `--np-color-*` tokens so admin overrides on top still apply.\n *\n * The terminal-style shell command snippet uses `.np-docs-cmdline`\n * (not `.np-docs-shell`) because `.np-docs-shell` is already\n * claimed by the route shell's root container.\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, \"Geist\", -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif);\n line-height: 1.6;\n -webkit-font-smoothing: antialiased;\n}\n.np-docs-shell a { color: inherit; }\n.np-docs-shell code,\n.np-docs-shell pre,\n.np-docs-shell kbd {\n font-family: var(--np-font-mono, \"Geist Mono\", ui-monospace, SFMono-Regular, Menlo, monospace);\n}\n\n/* ============================================================\n * Header — sticky bar with brand + version pill, ⌘K search in\n * the center, primary nav + GitHub link on the right. Grid\n * keeps everything anchored regardless of viewport width.\n * ============================================================ */\n.np-docs-header {\n position: sticky;\n top: 0;\n z-index: 30;\n background: color-mix(in oklab, var(--np-color-background) 80%, transparent);\n backdrop-filter: saturate(140%) blur(14px);\n -webkit-backdrop-filter: saturate(140%) blur(14px);\n border-bottom: 1px solid var(--np-color-border);\n}\n.np-docs-header-inner {\n max-width: 1380px;\n margin: 0 auto;\n padding: 0.7rem 1.5rem;\n display: grid;\n grid-template-columns: minmax(220px, 1fr) minmax(0, 2fr) auto;\n gap: 1.5rem;\n align-items: center;\n}\n.np-docs-brand {\n display: inline-flex;\n align-items: center;\n gap: 0.55rem;\n font-weight: 700;\n font-size: 1.0625rem;\n letter-spacing: -0.02em;\n text-decoration: none;\n}\n.np-docs-brand-mark {\n width: 1.55rem;\n height: 1.55rem;\n border-radius: 6px;\n background: linear-gradient(135deg, var(--np-color-primary, #2563eb), #0ea5e9);\n position: relative;\n flex: none;\n}\n.np-docs-brand-mark::after {\n content: \"\";\n position: absolute;\n inset: 5px;\n border-radius: 2px;\n background: var(--np-color-background, #fff);\n opacity: 0.95;\n clip-path: polygon(0 0, 100% 0, 100% 100%, 60% 100%, 0 35%);\n}\n.np-docs-brand-name { font-weight: 700; }\n.np-docs-brand-version {\n font-family: var(--np-font-mono);\n font-size: 0.72rem;\n font-weight: 500;\n color: var(--np-color-primary);\n background: color-mix(in oklab, var(--np-color-primary) 14%, var(--np-color-card));\n padding: 0.15rem 0.45rem;\n border-radius: 5px;\n}\n\n.np-docs-search-form {\n max-width: 520px;\n width: 100%;\n position: relative;\n justify-self: center;\n}\n.np-docs-search-form svg {\n position: absolute;\n top: 50%;\n left: 0.85rem;\n transform: translateY(-50%);\n color: var(--np-color-muted-foreground);\n}\n.np-docs-search-input {\n width: 100%;\n padding: 0.55rem 0.85rem 0.55rem 2.4rem;\n font: inherit;\n font-size: 0.875rem;\n color: var(--np-color-foreground);\n background: var(--np-color-card);\n border: 1px solid var(--np-color-border);\n border-radius: 9px;\n}\n.np-docs-search-input::placeholder {\n color: var(--np-color-muted-foreground);\n}\n.np-docs-search-input:focus {\n outline: none;\n border-color: var(--np-color-primary);\n box-shadow: 0 0 0 3px color-mix(in oklab, var(--np-color-primary) 22%, transparent);\n}\n.np-docs-search-kbd {\n position: absolute;\n right: 0.6rem;\n top: 50%;\n transform: translateY(-50%);\n font-size: 0.7rem;\n padding: 0.1rem 0.4rem;\n color: var(--np-color-muted-foreground);\n border: 1px solid var(--np-color-border);\n border-radius: 4px;\n}\n\n.np-docs-nav {\n display: flex;\n align-items: center;\n gap: 1.25rem;\n}\n.np-docs-primary-nav {\n display: flex;\n list-style: none;\n gap: 1.25rem;\n margin: 0;\n padding: 0;\n}\n.np-docs-primary-nav a {\n color: var(--np-color-muted-foreground);\n font-size: 0.875rem;\n font-weight: 500;\n text-decoration: none;\n}\n.np-docs-primary-nav a:hover,\n.np-docs-primary-nav a[aria-current=\"page\"] {\n color: var(--np-color-foreground);\n}\n.np-docs-github,\n.np-docs-github-link {\n display: inline-flex;\n align-items: center;\n gap: 0.45rem;\n padding: 0.4rem 0.7rem;\n font-size: 0.8125rem;\n color: var(--np-color-muted-foreground);\n background: var(--np-color-muted);\n border: 1px solid var(--np-color-border);\n border-radius: 7px;\n text-decoration: none;\n}\n.np-docs-github:hover,\n.np-docs-github-link:hover {\n color: var(--np-color-foreground);\n}\n\n@media (max-width: 800px) {\n .np-docs-header-inner {\n grid-template-columns: auto 1fr auto;\n gap: 0.75rem;\n }\n .np-docs-search-form { display: none; }\n .np-docs-primary-nav { display: none; }\n}\n\n/* ============================================================\n * 3-column layout: sidebar + article + on-page TOC.\n * ============================================================ */\n.np-docs-grid,\n.np-docs-body {\n max-width: 1380px;\n margin: 0 auto;\n width: 100%;\n display: grid;\n grid-template-columns: 260px minmax(0, 1fr) 220px;\n gap: 3rem;\n padding: 2.25rem 1.5rem 4rem;\n}\n@media (max-width: 1100px) {\n .np-docs-grid,\n .np-docs-body {\n grid-template-columns: 240px minmax(0, 1fr);\n }\n .np-docs-toc { display: none; }\n}\n@media (max-width: 800px) {\n .np-docs-grid,\n .np-docs-body {\n grid-template-columns: 1fr;\n }\n .np-docs-sidebar { display: none; }\n}\n\n/* ============================================================\n * Sidebar — grouped link list with bullet eyebrow + badges.\n * ============================================================ */\n.np-docs-sidebar {\n position: sticky;\n top: 4.25rem;\n align-self: start;\n max-height: calc(100vh - 5rem);\n overflow-y: auto;\n padding-right: 0.5rem;\n}\n.np-docs-sidebar-group { margin-bottom: 1.5rem; }\n.np-docs-sidebar-eyebrow {\n display: flex;\n align-items: center;\n gap: 0.4rem;\n font-family: var(--np-font-mono);\n font-size: 0.7rem;\n text-transform: uppercase;\n letter-spacing: 0.08em;\n color: var(--np-color-muted-foreground);\n margin: 0 0 0.65rem;\n font-weight: 600;\n}\n.np-docs-sidebar-eyebrow-dot {\n width: 0.4rem;\n height: 0.4rem;\n border-radius: 50%;\n background: var(--np-color-primary);\n}\n.np-docs-sidebar ul {\n list-style: none;\n padding: 0;\n margin: 0;\n}\n.np-docs-sidebar li { margin: 0.05rem 0; }\n.np-docs-sidebar a {\n display: block;\n padding: 0.34rem 0.6rem;\n font-size: 0.875rem;\n color: var(--np-color-muted-foreground);\n text-decoration: none;\n border-radius: 6px;\n line-height: 1.35;\n}\n.np-docs-sidebar a:hover {\n background: var(--np-color-muted);\n color: var(--np-color-foreground);\n}\n.np-docs-sidebar a[data-current=\"true\"],\n.np-docs-sidebar a[aria-current=\"page\"] {\n color: var(--np-color-primary);\n background: color-mix(in oklab, var(--np-color-primary) 14%, var(--np-color-card));\n font-weight: 500;\n}\n.np-docs-sidebar ul ul {\n margin-left: 0.5rem;\n padding-left: 0.85rem;\n border-left: 1px solid var(--np-color-border);\n}\n.np-docs-sidebar-badge {\n display: inline-block;\n font-family: var(--np-font-mono);\n font-size: 0.62rem;\n padding: 0.02rem 0.34rem;\n margin-left: 0.4rem;\n vertical-align: 1px;\n border-radius: 4px;\n background: var(--np-color-muted);\n color: var(--np-color-muted-foreground);\n font-weight: 500;\n}\n.np-docs-sidebar-badge.new { background: #dcfce7; color: #166534; }\n.np-docs-sidebar-badge.beta { background: #fef3c7; color: #92400e; }\n.np-docs-sidebar-badge.api {\n background: color-mix(in oklab, var(--np-color-primary) 16%, var(--np-color-card));\n color: var(--np-color-primary);\n}\n\n/* ============================================================\n * Doc page — article column. h1 + lede + meta row + sections\n * with hovered anchor link icon.\n * ============================================================ */\n.np-docs-page {\n max-width: 760px;\n min-width: 0;\n}\n.np-docs-breadcrumbs {\n display: flex;\n align-items: center;\n gap: 0.4rem;\n font-size: 0.8125rem;\n color: var(--np-color-muted-foreground);\n margin-bottom: 1rem;\n}\n.np-docs-breadcrumbs a {\n color: inherit;\n text-decoration: none;\n}\n.np-docs-breadcrumbs a:hover { color: var(--np-color-foreground); }\n.np-docs-breadcrumbs-sep { opacity: 0.5; }\n\n.np-docs-page h1 {\n font-size: clamp(2rem, 3.6vw, 2.5rem);\n font-weight: 700;\n letter-spacing: -0.03em;\n line-height: 1.1;\n margin: 0 0 0.5rem;\n text-wrap: balance;\n}\n.np-docs-page-lede {\n font-size: 1.125rem;\n color: var(--np-color-muted-foreground);\n line-height: 1.55;\n margin: 0 0 2rem;\n max-width: 38rem;\n text-wrap: pretty;\n}\n.np-docs-page-meta {\n display: flex;\n flex-wrap: wrap;\n gap: 0.5rem;\n align-items: center;\n font-size: 0.8125rem;\n color: var(--np-color-muted-foreground);\n padding: 0.85rem 0;\n margin-bottom: 2rem;\n border-top: 1px solid var(--np-color-border);\n border-bottom: 1px solid var(--np-color-border);\n}\n.np-docs-page-meta-pill {\n display: inline-flex;\n align-items: center;\n gap: 0.35rem;\n padding: 0.15rem 0.55rem;\n font-family: var(--np-font-mono);\n font-size: 0.72rem;\n border: 1px solid var(--np-color-border);\n border-radius: 999px;\n background: var(--np-color-card);\n}\n.np-docs-page-meta-pill.status {\n color: #047857;\n border-color: #bbf7d0;\n background: #f0fdf4;\n}\n.np-docs-page-meta-pill.status::before {\n content: \"\";\n width: 0.4rem;\n height: 0.4rem;\n border-radius: 50%;\n background: #047857;\n}\n.np-docs-page-meta-sep { opacity: 0.4; }\n.np-docs-page-meta a {\n color: var(--np-color-primary);\n text-decoration: none;\n margin-left: auto;\n}\n.np-docs-page-meta a:hover { text-decoration: underline; }\n\n.np-docs-page h2 {\n font-size: 1.5rem;\n font-weight: 600;\n letter-spacing: -0.02em;\n line-height: 1.25;\n margin: 3rem 0 0.85rem;\n scroll-margin-top: 5rem;\n position: relative;\n}\n.np-docs-page h2:first-of-type { margin-top: 2.5rem; }\n.np-docs-page h3 {\n font-size: 1.1rem;\n font-weight: 600;\n letter-spacing: -0.01em;\n margin: 2.25rem 0 0.7rem;\n scroll-margin-top: 5rem;\n position: relative;\n}\n.np-docs-page p { margin: 0 0 1rem; }\n.np-docs-page p code,\n.np-docs-page li code {\n font-size: 0.875em;\n padding: 0.1em 0.35em;\n background: var(--np-color-muted);\n border: 1px solid var(--np-color-border);\n border-radius: 4px;\n}\n.np-docs-page strong { font-weight: 600; }\n.np-docs-page ul,\n.np-docs-page ol {\n margin: 0 0 1rem;\n padding-left: 1.4rem;\n}\n.np-docs-page li { margin: 0.35rem 0; }\n.np-docs-page a:not(.np-docs-prev-next a):not(.np-docs-anchor) {\n color: var(--np-color-primary);\n text-decoration: underline;\n text-underline-offset: 3px;\n text-decoration-thickness: 1px;\n text-decoration-color: color-mix(in oklab, var(--np-color-primary) 45%, transparent);\n}\n.np-docs-page a:not(.np-docs-prev-next a):not(.np-docs-anchor):hover {\n text-decoration-color: currentColor;\n}\n\n/* Anchor icon — visible only on heading hover. */\n.np-docs-anchor {\n position: absolute;\n left: -1.3rem;\n top: 50%;\n transform: translateY(-50%);\n color: var(--np-color-muted-foreground);\n opacity: 0;\n text-decoration: none !important;\n font-weight: 400;\n}\n.np-docs-page h2:hover .np-docs-anchor,\n.np-docs-page h3:hover .np-docs-anchor { opacity: 1; }\n\n/* ============================================================\n * Callouts — info (default) / note (indigo) / warn (amber) /\n * danger (red). 3px left rule carries the variant color.\n * ============================================================ */\n.np-docs-callout {\n display: grid;\n grid-template-columns: auto 1fr;\n gap: 0.85rem;\n padding: 1rem 1.15rem;\n border: 1px solid var(--np-color-border);\n border-left: 3px solid var(--np-color-primary);\n border-radius: 8px;\n background: var(--np-color-card);\n margin: 1.25rem 0;\n font-size: 0.95rem;\n line-height: 1.55;\n}\n.np-docs-callout > svg,\n.np-docs-callout-icon {\n width: 1.25rem;\n height: 1.25rem;\n flex-shrink: 0;\n color: var(--np-color-primary);\n margin-top: 0.1rem;\n}\n.np-docs-callout p { margin: 0; }\n.np-docs-callout-title {\n font-weight: 600;\n margin-bottom: 0.15rem;\n color: var(--np-color-foreground);\n}\n.np-docs-callout--warn {\n border-left-color: #b45309;\n background: #fffbeb;\n border-color: #fde68a;\n}\n.np-docs-callout--warn .np-docs-callout-icon,\n.np-docs-callout--warn > svg { color: #b45309; }\n.np-docs-callout--note {\n border-left-color: #6366f1;\n background: #eef2ff;\n border-color: #c7d2fe;\n}\n.np-docs-callout--note .np-docs-callout-icon,\n.np-docs-callout--note > svg { color: #4338ca; }\n.np-docs-callout--danger {\n border-left-color: #b91c1c;\n background: #fef2f2;\n border-color: #fecaca;\n}\n.np-docs-callout--danger .np-docs-callout-icon,\n.np-docs-callout--danger > svg { color: #b91c1c; }\n\n/* ============================================================\n * Code blocks — dark surface with a file-named header and a\n * copy button. Syntax tokens (.tk-*) cover the common slots\n * (keyword / string / function / number / type / punctuation /\n * comment) using a muted neutral-paired palette so the block\n * reads at the same contrast as the page chrome.\n * ============================================================ */\n.np-docs-code {\n margin: 1.25rem 0;\n border-radius: 10px;\n background: #0b1220;\n color: #e6edf6;\n overflow: hidden;\n border: 1px solid #1e2939;\n}\n.np-docs-code-head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0.55rem 0.85rem;\n background: #0f1a2b;\n border-bottom: 1px solid #1e293b;\n}\n.np-docs-code-file {\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n font-family: var(--np-font-mono);\n font-size: 0.78rem;\n color: #94a3b8;\n}\n.np-docs-code-file svg { color: #64748b; }\n.np-docs-code-copy {\n display: inline-flex;\n align-items: center;\n gap: 0.35rem;\n padding: 0.25rem 0.55rem;\n font-size: 0.72rem;\n font-family: var(--np-font-mono);\n color: #94a3b8;\n background: transparent;\n border: 1px solid #1e293b;\n border-radius: 5px;\n cursor: pointer;\n}\n.np-docs-code-copy:hover {\n color: #e2e8f0;\n border-color: #334155;\n}\n.np-docs-code pre {\n margin: 0;\n padding: 1rem 1.1rem;\n font-size: 0.825rem;\n line-height: 1.65;\n overflow-x: auto;\n}\n.np-docs-code pre code {\n display: block;\n font-family: inherit;\n background: transparent;\n border: 0;\n padding: 0;\n color: inherit;\n}\n.tk-c { color: #64748b; font-style: italic; }\n.tk-k { color: #c084fc; }\n.tk-s { color: #86efac; }\n.tk-f { color: #93c5fd; }\n.tk-t { color: #fcd34d; }\n.tk-n { color: #f9a8d4; }\n.tk-p { color: #e2e8f0; }\n\n/* Inline shell snippet — for terse \\`pnpm dev\\` style commands.\n * Named \\`cmdline\\` (not \\`shell\\`) so it doesn't collide with the\n * route shell container at \\`.np-docs-shell\\`. */\n.np-docs-cmdline {\n display: grid;\n grid-template-columns: auto 1fr auto;\n gap: 0.7rem;\n align-items: center;\n padding: 0.75rem 1rem;\n margin: 1.25rem 0;\n background: #0b1220;\n color: #e6edf6;\n border-radius: 9px;\n font-family: var(--np-font-mono);\n font-size: 0.875rem;\n}\n.np-docs-cmdline-prompt { color: #34d399; }\n.np-docs-cmdline-cmd { color: #e2e8f0; }\n.np-docs-cmdline-copy {\n padding: 0.2rem 0.55rem;\n font-size: 0.7rem;\n color: #94a3b8;\n background: transparent;\n border: 1px solid #1e293b;\n border-radius: 5px;\n cursor: pointer;\n}\n.np-docs-cmdline-copy:hover { color: #e2e8f0; border-color: #334155; }\n\n/* ============================================================\n * Numbered steps — counter on a soft pill before each step.\n * ============================================================ */\n.np-docs-steps {\n counter-reset: step;\n list-style: none;\n padding: 0;\n margin: 1.5rem 0;\n display: grid;\n gap: 1rem;\n}\n.np-docs-steps > li {\n counter-increment: step;\n display: grid;\n grid-template-columns: 2.1rem 1fr;\n gap: 0.85rem;\n align-items: start;\n}\n.np-docs-steps > li::before {\n content: counter(step);\n width: 1.85rem;\n height: 1.85rem;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-family: var(--np-font-mono);\n font-size: 0.85rem;\n font-weight: 600;\n color: var(--np-color-primary);\n background: color-mix(in oklab, var(--np-color-primary) 14%, var(--np-color-card));\n border-radius: 50%;\n}\n.np-docs-step-title {\n font-weight: 600;\n margin: 0.25rem 0 0.25rem;\n}\n.np-docs-step-body {\n margin: 0;\n color: var(--np-color-muted-foreground);\n}\n\n/* ============================================================\n * API / reference tables — uppercase mono headers.\n * ============================================================ */\n.np-docs-table {\n width: 100%;\n border-collapse: collapse;\n font-size: 0.875rem;\n margin: 1.25rem 0;\n}\n.np-docs-table thead { background: var(--np-color-muted); }\n.np-docs-table th,\n.np-docs-table td {\n text-align: left;\n padding: 0.7rem 0.85rem;\n border-bottom: 1px solid var(--np-color-border);\n vertical-align: top;\n}\n.np-docs-table th {\n font-family: var(--np-font-mono);\n font-size: 0.72rem;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n color: var(--np-color-muted-foreground);\n font-weight: 600;\n}\n.np-docs-table td:first-child code {\n color: var(--np-color-foreground);\n font-weight: 500;\n}\n.np-docs-table-required {\n display: inline-block;\n font-family: var(--np-font-mono);\n font-size: 0.65rem;\n padding: 0.05rem 0.35rem;\n margin-left: 0.4rem;\n background: #fef3c7;\n color: #92400e;\n border-radius: 4px;\n vertical-align: 1px;\n}\n\n/* ============================================================\n * Prev / next — symmetric pair at the foot of every doc page.\n * Hover lifts the bordered card and tints the border primary.\n * ============================================================ */\n.np-docs-prev-next {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 1rem;\n margin: 3.5rem 0 1rem;\n padding-top: 2rem;\n border-top: 1px solid var(--np-color-border);\n}\n.np-docs-prev-next a {\n display: block;\n padding: 1rem 1.15rem;\n background: var(--np-color-card);\n border: 1px solid var(--np-color-border);\n border-radius: 10px;\n text-decoration: none;\n transition: border-color 0.15s ease, transform 0.2s ease;\n}\n.np-docs-prev-next a:hover {\n border-color: var(--np-color-primary);\n transform: translateY(-1px);\n}\n.np-docs-prev-next-dir,\n.np-docs-prev-next-label {\n font-family: var(--np-font-mono);\n font-size: 0.72rem;\n color: var(--np-color-muted-foreground);\n letter-spacing: 0.05em;\n margin-bottom: 0.25rem;\n}\n.np-docs-prev-next-title {\n font-weight: 600;\n font-size: 0.95rem;\n}\n.np-docs-prev-next a.np-docs-prev-next-next,\n.np-docs-prev-next a:last-child { text-align: right; }\n\n/* ============================================================\n * Feedback row — Yes / Could be better buttons under each page.\n * ============================================================ */\n.np-docs-feedback {\n margin-top: 3rem;\n padding: 1.25rem;\n background: var(--np-color-muted);\n border: 1px solid var(--np-color-border);\n border-radius: 10px;\n display: flex;\n gap: 1rem;\n align-items: center;\n justify-content: space-between;\n flex-wrap: wrap;\n}\n.np-docs-feedback-title { font-weight: 600; font-size: 0.95rem; }\n.np-docs-feedback-helper {\n font-size: 0.825rem;\n color: var(--np-color-muted-foreground);\n margin-top: 0.15rem;\n}\n.np-docs-feedback-buttons {\n display: flex;\n gap: 0.5rem;\n}\n.np-docs-feedback-buttons button {\n padding: 0.4rem 0.85rem;\n font: inherit;\n font-size: 0.825rem;\n background: var(--np-color-card);\n border: 1px solid var(--np-color-border);\n border-radius: 7px;\n cursor: pointer;\n}\n.np-docs-feedback-buttons button:hover {\n border-color: var(--np-color-primary);\n color: var(--np-color-primary);\n}\n\n/* ============================================================\n * On-page TOC — right rail, sticky, current section gets a\n * primary border + soft gradient.\n * ============================================================ */\n.np-docs-toc {\n position: sticky;\n top: 4.25rem;\n align-self: start;\n max-height: calc(100vh - 5rem);\n overflow-y: auto;\n font-size: 0.825rem;\n}\n.np-docs-toc-eyebrow {\n font-family: var(--np-font-mono);\n font-size: 0.7rem;\n text-transform: uppercase;\n letter-spacing: 0.08em;\n color: var(--np-color-muted-foreground);\n margin: 0 0 0.75rem;\n font-weight: 600;\n}\n.np-docs-toc ul {\n list-style: none;\n padding: 0;\n margin: 0;\n}\n.np-docs-toc li { margin: 0.05rem 0; }\n.np-docs-toc a {\n display: block;\n padding: 0.3rem 0.5rem;\n color: var(--np-color-muted-foreground);\n text-decoration: none;\n border-left: 2px solid transparent;\n margin-left: -2px;\n line-height: 1.4;\n}\n.np-docs-toc a:hover { color: var(--np-color-foreground); }\n.np-docs-toc a[data-current=\"true\"],\n.np-docs-toc a[aria-current=\"location\"],\n.np-docs-toc a[aria-current=\"true\"] {\n color: var(--np-color-primary);\n border-left-color: var(--np-color-primary);\n background: linear-gradient(\n to right,\n color-mix(in oklab, var(--np-color-primary) 14%, var(--np-color-card)),\n transparent 80%\n );\n}\n.np-docs-toc ul ul { margin-left: 0.85rem; }\n.np-docs-toc-secondary {\n margin-top: 1.5rem;\n padding-top: 1rem;\n border-top: 1px solid var(--np-color-border);\n}\n.np-docs-toc-secondary a {\n display: inline-flex;\n align-items: center;\n gap: 0.35rem;\n padding: 0.2rem 0;\n border-left: 0;\n margin: 0;\n}\n.np-docs-toc-secondary a:hover { background: transparent; }\n\n/* Empty / not-found surfaces — used by routes/not-found and\n * the docs collection's empty state. */\n.np-docs-empty {\n padding: 4rem 1.5rem;\n text-align: center;\n color: var(--np-color-muted-foreground);\n}\n.np-docs-empty h1 {\n font-size: 1.5rem;\n margin: 0 0 0.5rem;\n color: var(--np-color-foreground);\n}\n`;\n"],"mappings":"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AAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;AbHvB,IAAM,WAAW;AAAA,EACf,QAAQ;AAAA,IACN,EAAE,IAAI,iBAAiB,OAAO,QAAQ,MAAM,QAAiB,KAAK,QAAQ;AAAA,IAC1E,EAAE,IAAI,sBAAsB,OAAO,aAAa,MAAM,QAAiB,KAAK,kBAAkB;AAAA,IAC9F,EAAE,IAAI,iBAAiB,OAAO,QAAQ,MAAM,QAAiB,KAAK,QAAQ;AAAA,EAC5E;AAAA,EACA,QAAQ;AAAA,IACN,EAAE,IAAI,wBAAwB,OAAO,iBAAiB,MAAM,QAAiB,KAAK,QAAQ;AAAA,IAC1F,EAAE,IAAI,6BAA6B,OAAO,aAAa,MAAM,QAAiB,KAAK,kBAAkB;AAAA,IACrG,EAAE,IAAI,6BAA6B,OAAO,aAAa,MAAM,QAAiB,KAAK,aAAa;AAAA,IAChG,EAAE,IAAI,0BAA0B,OAAO,UAAU,MAAM,QAAiB,KAAK,qBAAqB;AAAA,EACpG;AACF;AAyBO,IAAM,YAAY,YAAY;AAAA,EACnC,UAAU;AAAA,IACR,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,SAAS;AAAA,IACT,aACE;AAAA,IACF,QAAQ,EAAE,MAAM,WAAW;AAAA,IAC3B,UAAU,EAAE,YAAY,QAAQ;AAAA,IAChC,UAAU;AAAA,MACR,aAAa;AAAA,QACX,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UAQL,QAAQ;AAAA,YACN,MAAM;AAAA,cACJ,MAAM;AAAA,cACN,SAAS,CAAC,EAAE,OAAO,OAAO,OAAO,MAAM,CAAC;AAAA,YAC1C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAMA,MAAM;AAAA,cACJ,MAAM;AAAA,cACN,MAAM;AAAA,cACN,OAAO;AAAA,gBACL,UAAU;AAAA,gBACV,OAAO;AAAA,gBACP,WAAW,EAAE,MAAM,QAAQ,QAAQ,MAAM;AAAA,cAC3C;AAAA,YACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAOA,aAAa;AAAA,cACX,MAAM;AAAA,cACN,MAAM;AAAA,cACN,OAAO;AAAA,gBACL,UAAU;AAAA,gBACV,OAAO;AAAA,gBACP,WAAW,EAAE,MAAM,QAAQ,QAAQ,MAAM;AAAA,cAC3C;AAAA,YACF;AAAA,UACF;AAAA,UACA,WAAW;AAAA,YACT,MAAM;AAAA,cACJ,MAAM;AAAA,cACN,aAAa;AAAA,YACf;AAAA,UACF;AAAA,UACA,OAAO;AAAA,YACL,KAAK;AAAA,cACH,OAAO;AAAA,cACP,aAAa;AAAA,cACb,MAAM;AAAA;AAAA;AAAA;AAAA,cAIN,YAAY;AAAA;AAAA;AAAA,cAGZ,cAAc;AAAA,YAChB;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA,gBAAgB;AAAA,EAClB;AAAA,EACA,MAAM;AAAA,IACJ,OAAO;AAAA,IACP,OAAO;AAAA,MACL,QAAQ;AAAA,MACR,SAAS;AAAA,IACX;AAAA,IACA,KAAK;AAAA,IACL,QAAQ;AAAA,MACN,QAAQ;AAAA,QACN,SAAS;AAAA,QACT,mBAAmB;AAAA,QACnB,YAAY;AAAA,QACZ,YAAY;AAAA,QACZ,OAAO;AAAA,QACP,iBAAiB;AAAA,QACjB,QAAQ;AAAA,QACR,MAAM;AAAA,MACR;AAAA,MACA,YAAY;AAAA,QACV,aACE;AAAA,QACF,UACE;AAAA,QACF,UACE;AAAA,MACJ;AAAA,MACA,OAAO;AAAA,QACL,UAAU;AAAA,QACV,UAAU;AAAA,QACV,UAAU;AAAA,MACZ;AAAA,IACF;AAAA,IACA,aAAa;AAAA,MACX,YAAY;AAAA,IACd;AAAA,IACA,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAOT,OAAO;AAAA,QACL,KAAK;AAAA,UACH,OAAO;AAAA,UACP,aACE;AAAA,UACF,WAAW;AAAA,QACb;AAAA,MACF;AAAA,IACF;AAAA,IACA,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAeN,EAAE,SAAS,gBAAgB,WAAW,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAMjD,EAAE,SAAS,eAAe,WAAW,gBAAgB;AAAA,IACvD;AAAA,IACA,cAAc;AAAA,MACZ,SAAS;AAAA,QACP,OAAO;AAAA,QACP,aAAa;AAAA,QACb,UAAU;AAAA,MACZ;AAAA,IACF;AAAA,IACA,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAkBV,SAAS;AAAA,MACP,OAAO;AAAA,MACP,UAAU;AAAA,IACZ;AAAA,EACF;AACF,CAAC;","names":["jsx","jsxs","jsx","jsxs","jsx","jsxs","findDocuments","Fragment","jsx","jsxs","jsx","findDocuments","jsx","jsxs","jsx","findDocuments","jsx","jsxs","findDocuments"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nexpress/theme-docs",
3
- "version": "0.2.2",
3
+ "version": "0.3.1",
4
4
  "description": "Documentation theme for NexPress — hierarchical sidebar, prev/next nav, in-page TOC.",
5
5
  "license": "MIT",
6
6
  "author": "Nexpress",
@@ -48,11 +48,11 @@
48
48
  },
49
49
  "dependencies": {
50
50
  "zod": "^4.4.3",
51
- "@nexpress/blocks": "0.2.2",
52
- "@nexpress/core": "0.2.2",
53
- "@nexpress/editor": "0.2.2",
54
- "@nexpress/next": "0.2.2",
55
- "@nexpress/theme": "0.2.2"
51
+ "@nexpress/blocks": "0.3.1",
52
+ "@nexpress/core": "0.3.1",
53
+ "@nexpress/editor": "0.3.1",
54
+ "@nexpress/next": "0.3.1",
55
+ "@nexpress/theme": "0.3.1"
56
56
  },
57
57
  "devDependencies": {
58
58
  "@types/react": "^19.0.0",
@@ -64,7 +64,7 @@
64
64
  "typescript": "^5.8.0"
65
65
  },
66
66
  "scripts": {
67
- "build": "tsup",
67
+ "build": "rm -rf dist && tsup",
68
68
  "dev": "tsup --watch --no-clean",
69
69
  "clean": "rm -rf dist",
70
70
  "typecheck": "tsc --noEmit",