Use declarative output handlers in .wrn files or register a direct output handler from JavaScript. The canonical API exposes payload and does not require event.detail.
${eventRows}
Declarative handlers.wrn
${escapeCode(declarativeCode)}
Direct output handlers.js
${escapeCode(listenerCode)}
`;
}
function detailPage(component, categoryComponents) {
// Names are per page; without this they accumulate across the whole run.
resetHoistedObjects();
const index = categoryComponents.findIndex((item) => item.name === component.name);
const previous = categoryComponents[index - 1];
const next = categoryComponents[index + 1];
const uses = demoUses(component);
const demos = uses
.map((useCase, variation) => {
const configuredDemo = demoConfiguration(component, variation);
const isPinLengthDemo = component.name === "PinInput" && variation === 1;
const pinLengths = [3, 5, 7];
const mount = isPinLengthDemo
? `
`,
)
.join("");
writeFileSync(
join(pagesDir, "index.wrn"),
`// Generated by scripts/generate-showcase.mjs. Do not edit directly.
page ComponentShowcase {
layout = "showcase"
seo {
title = "WRNexus component system"
description = "Explore every unique @wrnexus/ui component through live, production-quality examples."
}
view {
The UI foundation for WRNexus
Build modern products at framework speed.
A complete, accessible component system with ${reference.count} primitives, ready-made blocks, page templates, responsive behavior, and deeply configurable design tokens.
}
}
`,
"utf8",
);
const docsSections = [
[
"installation",
"Installation",
"Install the package and import the shared stylesheet once in your application.",
"bun add @wrnexus/ui",
],
[
"framework-guides",
"Framework guides",
"WRNexus components use native HTML semantics and framework component mounts.",
],
[
"accessibility",
"Accessibility",
"Keyboard interaction, visible focus states, labels, and reduced-motion support ship by default.",
],
[
"dark-mode",
"Dark mode",
"Choose light, dark, or system mode. The selection persists and updates every preview.",
],
[
"themes",
"Themes",
"Theme presets control radius, surface treatment, borders, shadows, and motion.",
],
[
"colors",
"Colors",
"Semantic primary, secondary, success, warning, danger, and info tokens remain available in every palette.",
],
[
"fonts",
"Fonts",
"Select a font family globally while components continue to inherit typography correctly.",
],
[
"sizing",
"Sizing",
"Compact through large scales adjust the complete component system consistently.",
],
[
"resources",
"Resources",
"Use the component API pages, blocks, and templates as production starting points.",
],
];
writeFileSync(
join(pagesDir, "docs.wrn"),
`page Documentation {
layout = "showcase"
seo { title = "Documentation" description = "Install, configure, and use WRNexus UI." }
view {
Getting started
Build with WRNexus UI
Configure one design system and use it across components, blocks, and complete page templates.
Explore the documentation
Every Getting Started and Customization topic now has its own page. Choose a guide from the sidebar to continue.
}
}
`,
"utf8",
);
const v06Guides = [
[
"types",
"Types",
"TypeScript contracts for props, state, outputs, imported application types, and generated declarations.",
[
[
"Application types",
"Load ambient app/types/global.d.ts and explicitly import types from app/types/*.ts.",
],
[
"Typed contracts",
"Validate component props, state assignments, function parameters, returns, and output payloads.",
],
[
"Generated declarations",
"Generate component, output, store, layout, and server-call declarations under dist/types.",
],
],
],
[
"functions",
"Functions",
"Classify behavior for the browser, server, or both runtimes from one functions block.",
[
["Client", "Compile browser-only functions into CSP-safe client modules."],
[
"Server",
"Keep server-only functions out of browser artifacts and expose typed RPC calls when referenced.",
],
["Shared", "Emit deterministic shared helpers to both compilation targets."],
],
],
[
"outputs",
"Outputs",
"Use typed callable outputs for child-to-parent communication without application-level $emit or event.detail.",
[
["Declare", "Define zero- or one-payload output signatures in an outputs block."],
["Invoke", "Call output.name(payload) from client functions."],
["Consume", "Receive the typed payload local in parent component listeners."],
],
],
[
"stores",
"Stores",
"Create request-safe global stores and route-scoped page stores with typed actions and computed state.",
[
["Global stores", "Survive CSR navigation while remaining isolated for every SSR request."],
[
"Page stores",
"Share state with route descendants and dispose it when navigation leaves the route.",
],
["Persistence", "Persist include-only safe fields to memory, session, or local storage."],
],
],
[
"imports",
"Imports",
"Declare component, layout, store, package, and type dependencies explicitly while retaining compatibility mode.",
[
["Application imports", "Resolve @/ aliases to the active application directory."],
["Package imports", "Use named imports for components exported by @wrnexus/ui."],
[
"Compatibility",
"Run legacy, compatible, or explicit import modes during project migration.",
],
],
],
[
"state",
"State",
"Use individual or grouped typed state declarations with shared, client-only, and server-only scopes.",
[
[
"Shared state",
"Render during SSR and safely hydrate serializable values into the browser.",
],
["Client state", "Keep browser-only interaction state out of server artifacts."],
["Server state", "Keep sensitive request-only state out of hydration data."],
],
],
[
"runtime",
"Runtime",
"Split server and browser artifacts, hydrate only interactive components, and preserve compatible state during HMR.",
[
[
"Partial hydration",
"Load client code using load, idle, visible, interaction, media, or none strategies.",
],
[
"RPC",
"Validate browser-to-server inputs and outputs with same-origin and CSRF-aware defaults.",
],
["HMR", "Replace functions and preserve compatible component and store state."],
],
],
[
"migration",
"Migration",
"Upgrade older projects through idempotent v0.6 migrations with backups, dry runs, and review reports.",
[
[
"Legacy outputs",
"Convert @event declarations, $emit calls, and event.detail listeners to outputs and payload.",
],
[
"Explicit dependencies",
"Add component and layout imports only when resolution is unambiguous.",
],
[
"Safety",
"Parse and type-check changed files and roll back when migration validation fails.",
],
],
],
];
for (const [slug, title, description, sections] of v06Guides) {
writeFileSync(
join(pagesDir, `v06-${slug}.wrn`),
`// Generated by scripts/generate-showcase.mjs. Do not edit directly.
page V06${identifier(title)}Guide {
layout = "showcase"
seo {
title = "WRNexusJS v0.6 ${escapeAttribute(title)}"
description = "${escapeAttribute(description)}"
}
view {
WRNexusJS v0.6
${escapeText(title)}
${escapeText(description)}
${sections.map(([heading, copy]) => `
${escapeText(heading)}
${escapeText(copy)}
`).join("")}
}
}
`,
"utf8",
);
}
const customizationGuides = new Set(["dark-mode", "themes", "colors", "fonts", "sizing"]);
const guideOutcomes = {
installation: "The UI package becomes discoverable by development, type-check, and production builds without manually copying component CSS.",
"framework-guides": "The page depends on public component props, slots, and outputs, so framework upgrades do not depend on private markup.",
accessibility: "Keyboard, focus, naming, contrast, zoom, and reduced-motion behavior become explicit acceptance criteria.",
resources: "You can move from component contract to composed block, diagnose ownership, and preview upgrades with supported tools.",
"dark-mode": "The initial server document and hydrated client agree on light, dark, or system mode without a theme flash.",
themes: "Only the selected theme is active while semantic tokens keep every component visually consistent.",
colors: "Status and hierarchy use named semantic roles that remain understandable in both light and dark modes.",
fonts: "Typography loads only required families and weights while preserving a readable system fallback.",
sizing: "Control size and application density remain consistent without shrinking accessible touch targets.",
};
const guideDetails = {
installation: {
sections: [
["Prerequisites", "Use Bun 1.3 or newer and a WRNexus application whose framework packages share the same version. Private-preview installs require npm credentials with access to the @wrnexus scope."],
["Install the UI package", "Add @wrnexus/ui to the application. The dev server and production builder discover its component directory, styles, tokens, and metadata automatically."],
["Verify discovery", "Run the type checker and inspect packages. A healthy application reports valid application types and lists @wrnexus/ui among its resolved packages."],
["Production check", "Build once before deployment. Confirm the report lists UI components, the selected active theme, and the application stylesheet without loading the complete theme matrix."],
],
code: `bun add @wrnexus/ui@0.8.7\nbunx wrnexus typecheck .\nbunx wrnexus inspect packages .\nbunx wrnexus build .`,
},
"framework-guides": {
sections: [
["Mount components", "Use the component mount name directly in .wrn views. Props are typed, slots remain server-rendered, and declared outputs reach parent bindings."],
["Own page composition", "Keep application structure in pages and layouts. Use library components for reusable behavior, then add application-specific styles in the owning .wrn file."],
["Prefer semantic contracts", "Choose props, slots, and outputs over selectors that depend on a component's internal markup. This keeps applications compatible with framework upgrades."],
["Inspect before integrating", "Use the CLI component inspector for the exact prop, slot, and output contract, then type-check the finished page."],
],
code: `bunx wrnexus inspect component Navbar .\nbunx wrnexus typecheck .`,
},
accessibility: {
sections: [
["Keyboard first", "Every interactive control must be reachable in a logical order and operable without a pointer. Preserve native elements and the component's documented keyboard behavior."],
["Names and descriptions", "Provide visible labels or accessible names for icon-only actions. Associate help and validation messages with their fields rather than relying on color alone."],
["Focus and overlays", "Keep visible focus rings. Modal, drawer, dropdown, and popover components manage focus and dismissal; test Escape, Tab, Shift+Tab, and focus restoration."],
["Motion and contrast", "Theme tokens preserve semantic contrast, while components honor reduced motion. Verify custom colors in light and dark modes at 200% zoom."],
],
code: `bunx wrnexus test accessibility .\nbunx wrnexus security headers .`,
},
resources: {
sections: [
["Component contracts", "Each component page contains live variants, typed props, slots, outputs, copyable WRN source, behavior notes, and responsive guidance."],
["Blocks and templates", "Blocks demonstrate production composition patterns. Templates combine those patterns into public pages, authentication surfaces, and application dashboards."],
["Framework diagnostics", "Use inspect, explain, doctor, and typecheck when a component does not render or hydrate as expected. These commands expose resolved ownership rather than requiring guesswork."],
["Upgrade safely", "Preview framework migrations, commit the current application, apply the update, and review generated migration reports before deployment."],
],
code: `bunx wrnexus doctor .\nbunx wrnexus inspect styles .\nbunx wrnexus update . --latest --dry-run`,
},
"dark-mode": {
sections: [
["Choose a default", "Set light, dark, or system in wrnexus.config.ts. System mode follows the operating-system preference until the user selects an explicit value."],
["Persist preference", "Use PreferenceSwitcher or your own control to update the document theme. The selected value persists and is applied before interactive components hydrate."],
["Author with tokens", "Use semantic --wire-* variables instead of hard-coded light colors. Tokens switch surfaces, text, borders, focus, and status colors together."],
["Test both modes", "Check content, overlays, charts, disabled controls, focus rings, and browser autofill in both modes. Do not treat dark mode as a simple color inversion."],
],
code: `theme: {\n default: "system",\n palette: "violet",\n}`,
},
themes: {
sections: [
["Theme anatomy", "A theme combines mode, palette, accent, radius, elevation, borders, motion, and typography. Components consume semantic tokens rather than palette-specific values."],
["Select only what ships", "Production pages link the active palette/accent sheet. Keep alternative themes available for user selection without placing the complete matrix on every page."],
["Customize globally", "Override tokens at the application boundary for brand-wide changes. Keep component-local adjustments in the owning page or component."],
["Validate the system", "Use the design panel to compare presets, then verify the production build's theme link and CSS report."],
],
code: `theme: {\n default: "light",\n palette: "violet",\n accent: "violet",\n}`,
},
colors: {
sections: [
["Semantic roles", "Primary and secondary communicate hierarchy; success, warning, danger, and info communicate state. Use roles consistently instead of choosing colors by appearance."],
["Component colors", "Every maintained component accepts the shared color contract. Prefer the color prop for supported variants and tokens for application-owned surfaces."],
["Accessible combinations", "Check text, icons, borders, hover, focus, selected, and disabled states. Never make color the only carrier of meaning."],
["Brand overrides", "Define brand values once through theme tokens. Derived surfaces and on-colors keep contrast coherent across light and dark modes."],
],
code: `\nUnable to save`,
},
fonts: {
sections: [
["Configure families", "Declare the application sans family and optional hosted families in wrnexus.config.ts. Components inherit typography without per-component imports."],
["Control loading", "Request only used weights and styles. Keep a system fallback so content remains readable before hosted fonts finish loading."],
["Preserve hierarchy", "Use semantic heading, body, label, caption, and code roles. Avoid arbitrary sizes that break density and responsive rhythm."],
["Test real content", "Check long headings, translated labels, numeric tables, code, and form errors. Font choices must remain legible at zoom and on narrow screens."],
],
code: `fonts: {\n sans: '"Plus Jakarta Sans", system-ui, sans-serif',\n google: [{ family: "Plus Jakarta Sans", weights: [400, 500, 600, 700] }],\n}`,
},
sizing: {
sections: [
["Component size", "Use xs, sm, default, md, lg, or xl when a component needs an explicit scale. Related controls should use the same size within one task."],
["Interface density", "Compact, default, comfortable, and large adjust the system globally. Choose density from audience and task complexity rather than viewport alone."],
["Responsive composition", "Let containers, grids, columns, navigation, and sections adapt layout. Avoid shrinking touch targets to force desktop arrangements onto mobile."],
["Override deliberately", "Use tokens for application-wide spacing changes and component props for local intent. Measure dense tables and large marketing layouts separately."],
],
code: `\n`,
},
};
for (const [slug, title, description, code] of docsSections) {
const section = customizationGuides.has(slug) ? "Customization" : "Getting Started";
const details = guideDetails[slug] ?? {
sections: [["Overview", description]],
code,
};
writeFileSync(
join(pagesDir, `${slug}.wrn`),
`page ${identifier(slug)}Guide {
layout = "showcase"
seo {
title = "${escapeAttribute(title)}"
description = "${escapeAttribute(description)}"
}
view {
${section}
${escapeText(title)}
${escapeText(description)}
${details.code ? `
Configure and use it
This is the smallest useful starting point. Copy it into the indicated application file or run it from the project root, then adjust the documented values for your product.
${escapeCode(details.code)}
What changes after this
${escapeText(guideOutcomes[slug] ?? "The application adopts the documented component-library contract and can verify it through the production toolchain.")}
Type-check the application, inspect the resolved package and styles, and build the production artifact. Test the page at a narrow viewport, with keyboard navigation, and in both color modes before shipping.
The commands exit successfully, the build reports the installed UI components and active theme, and the rendered page remains usable before and after hydration.
}
}
`,
"utf8",
);
}
const blockCards = [
[
"Hero sections",
"Marketing",
"layout-template",
"Hero, actions, product proof, and visual stage.",
],
[
"Feature grids",
"Marketing",
"grid-2x2",
"Responsive benefits and product capability sections.",
],
["Pricing sections", "Marketing", "badge-dollar-sign", "Tier cards, comparison grids, and CTAs."],
[
"Application shells",
"Application UI",
"panel-left",
"Headers, sidebars, content, and command areas.",
],
[
"Dashboard stats",
"Application UI",
"chart-no-axes-combined",
"Metrics, trends, filters, and summaries.",
],
["Checkout panels", "Ecommerce", "shopping-cart", "Cart, address, payment, and order summary."],
[
"Article layouts",
"Blog & Articles",
"newspaper",
"Editorial headers, content, author, and sharing.",
],
[
"Authentication",
"Application UI",
"shield-check",
"Sign in, registration, recovery, and verification.",
],
];
// Keep /blocks for the generated Blocks component category.
writeFileSync(
join(pagesDir, "block-library.wrn"),
`page BlockLibrary {
layout = "showcase"
seo { title = "UI blocks" description = "Complete sections composed from WRNexus UI components." }
view {
Composable sections
Ready-to-use UI blocks
Complete responsive sections composed exclusively from the components in this library.