Refresh UI components and showcase; release updated framework packages

This commit is contained in:
Clintchiz committed 2026-09-20 18:13:24 +05:30
1 parent d800228585
commit c77f5e1cec
293 files changed
+22544 -35778

No files matched your search

@@ -0,0 +1,39 @@
import { test, expect } from "bun:test";
import { readFileSync } from "node:fs";
import { Window } from "happy-dom";
test("preview input never requests a replacement; settings still do", async () => {
const window = new Window({ url: "http://localhost/components/input" });
window.document.body.innerHTML = `<div data-playground data-playground-component="Input">
<div data-playground-preview><input aria-label="Example" /></div>
<form data-playground-form><input name="label" value="Name" /></form>
<pre data-playground-code></pre><span data-playground-status></span>
</div>`;
let requests = 0;
window.fetch = async () => {
requests++;
return new window.Response("", { status: 500 });
};
window.eval(readFileSync(new URL("../public/playground.js", import.meta.url), "utf8"));
const preview = window.document.querySelector("[data-playground-preview] input")!;
preview.dispatchEvent(new window.Event("input", { bubbles: true }));
preview.dispatchEvent(new window.Event("change", { bubbles: true }));
await new Promise((resolve) => setTimeout(resolve, 250));
expect(requests).toBe(0);
window.document
.querySelector("[data-playground-form] input")!
.dispatchEvent(new window.Event("input", { bubbles: true }));
await new Promise((resolve) => setTimeout(resolve, 250));
expect(requests).toBe(1);
await window.happyDOM.close();
});
test("stored theme updates its stylesheet before the theme runtime loads", async () => {
const window = new Window({ url: "http://localhost/components/alert" });
window.document.cookie = "wrn-ui-mode=light;path=/";
window.document.head.innerHTML = '<link rel="stylesheet" data-wrnexus-theme href="/__wrnexus/theme/dark/violet.css">';
window.eval(readFileSync(new URL("../public/playground.js", import.meta.url), "utf8"));
expect(window.document.documentElement.dataset.theme).toBe("light");
expect(window.document.querySelector("link")?.getAttribute("href")).toBe("/__wrnexus/theme/light/violet.css");
await window.happyDOM.close();
});
@@ -21,6 +21,8 @@ const reference = JSON.parse(
}>;
};
const manifest = JSON.parse(readFileSync(join(root, "showcase-manifest.json"), "utf8")) as {
removed: string[];
blocks: Array<{name: string; slug: string; path: string}>;
componentCount: number;
categoryCount: number;
totalDemoCount: number;
@@ -69,14 +71,17 @@ test("showcase configures local Lucide icon generation", () => {
});
test("showcase manifest matches the generated UI reference", () => {
expect(manifest.componentCount).toBe(reference.count);
expect(manifest.components).toHaveLength(reference.count);
expect(manifest.totalDemoCount).toBeGreaterThanOrEqual(reference.count * 3);
expect(manifest.componentCount + manifest.blocks.length + manifest.removed.length).toBe(reference.count);
expect(manifest.removed).toEqual(["AuthForm", "AuthSplitLayout", "PortalDashboard", "PublicPageShell"]);
expect(manifest.blocks.some(block => block.name === "Hero")).toBe(true);
expect(manifest.blocks.some(block => block.name === "CTASection")).toBe(true);
expect(manifest.components).toHaveLength(manifest.componentCount);
expect(manifest.totalDemoCount).toBeGreaterThanOrEqual(manifest.componentCount * 2);
expect(new Set(manifest.components.map((component) => component.slug)).size).toBe(
reference.count,
manifest.componentCount,
);
for (const component of reference.components) {
for (const component of reference.components.filter(entry => !manifest.removed.includes(entry.name) && !manifest.blocks.some(block => block.name === entry.name))) {
const documented = manifest.components.find((entry) => entry.name === component.name);
expect(documented).toBeTruthy();
expect(documented?.mount).toBe(component.mount);
@@ -92,8 +97,8 @@ test("showcase uses a searchable documentation shell", () => {
expect(layout).toContain("data-docs-directory");
expect(layout).toContain("data-docs-search");
expect(layout.match(/data-docs-component-link/g)).toHaveLength(reference.count);
expect(styles).toContain("grid-template-columns: 17rem minmax(0, 1fr)");
expect(layout.match(/data-docs-component-link/g)).toHaveLength(manifest.componentCount);
expect(styles).toContain("grid-template-columns: 15rem minmax(0, 1fr)");
expect(runtime).toContain("data-docs-menu-toggle");
expect(runtime).toContain('event.key.toLowerCase() === "k"');
});
@@ -115,7 +120,7 @@ test("category pages preview every UI component exactly once", () => {
.map((file) => readFileSync(join(pagesDir, file), "utf8"))
.join("\n");
const invalidPreviews = reference.components.flatMap((component) => {
const invalidPreviews = reference.components.filter(entry => manifest.components.some(component => component.name === entry.name)).flatMap((component) => {
const count = mountCount(categoryPages, component.mount);
return count === 1
? []
@@ -127,7 +132,7 @@ test("category pages preview every UI component exactly once", () => {
test("every component has a detail page, playground, and manifest-driven demos", () => {
const files = readdirSync(detailPagesDir).filter((entry) => entry.endsWith(".wrn"));
expect(files).toHaveLength(reference.count);
expect(files).toHaveLength(manifest.componentCount);
for (const component of manifest.components) {
const source = detailSource(component.slug);