feat: deployable design studio and updated component showcase

This commit is contained in:
Clintchiz committed 2026-10-19 13:18:06 +05:30
1 parent 3dddcaac1a
commit 3987ddbcfe
30 files changed
+4154 -649

No files matched your search

+35
View File
@@ -69,3 +69,38 @@ bun run --cwd examples/component-showcase check
Review representative component pages at mobile, tablet, and desktop widths and
in light, dark, keyboard-only, and reduced-motion modes before publishing.
## Design Studio on the deployed site
The navigation opens `/design-studio/`. It includes guided alternatives, decision
locks, natural-language edits, component recipes, previews and portable exports.
Drafts and incomplete source edits remain in each browser's local storage; use
Export raw draft before clearing browser data or changing the site's origin.
The hosted demo uses local rule generation, needs no AI credentials, and cannot
apply designs to server files or access agent workspaces.
On the VM, pull this repository and use Bun 1.3 or newer:
```sh
git pull --ff-only
bun install --frozen-lockfile
bun run check
PORT=3000 bun run start
```
`start` runs the production component site and an export-only Studio sidecar
bound to loopback port 4320. Include `deploy/nginx-design-studio.conf` inside your
existing nginx server block, retain its existing component-site proxy, validate
with `nginx -t`, then reload nginx. The proxy must preserve `/design-studio/` and
Host, and pass Origin unchanged. If port 4320 is occupied, set DESIGN_STUDIO_PORT
and update the proxy upstream to the same port. Manage the `bun run start`
process using your existing service manager and restart it after each build.
The private `@wrnexus` registry is configured in `.npmrc`. Supply registry
credentials on the VM through its user configuration or secret store; no tokens
are committed. Dependencies are pinned and bun.lock is the deployment lock.
A refreshed package-lock.json is retained for npm tooling, but Bun runs the app.
After deployment, check `/`, a component playground and `/design-studio/`.
Create a draft, generate alternatives, open a preview, export JSON, then reload
and confirm draft recovery. Existing Studio drafts on other origins remain there.
+2 -2
View File
@@ -9,7 +9,7 @@ layout Showcase {
<label class="docs-search"><span class="icon-[lucide--search] size-4" aria-hidden="true"></span><input type="search" placeholder="Search documentation..." data-docs-search /><kbd>⌘ K</kbd></label>
</div>
<div class="showcase-header-end">
<nav aria-label="Primary navigation" class="showcase-nav"><a href="/preview">Examples</a><a href="/docs">Docs</a><a href="/block-library">Blocks</a><a href="/templates">Templates</a></nav>
<nav aria-label="Primary navigation" class="showcase-nav"><a href="/preview">Examples</a><a href="/docs">Docs</a><a href="/block-library">Blocks</a><a href="/templates">Templates</a><a href="/design-studio/" data-no-nav>Design Studio</a></nav>
<button type="button" class="showcase-theme" data-design-panel-toggle aria-label="Customize design"><span class="icon-[lucide--palette] size-5" aria-hidden="true"></span></button>
</div>
</header>
@@ -34,7 +34,7 @@ layout Showcase {
</section>
<section class="docs-directory-group">
<a class="docs-directory-heading" href="/core">Core</a>
<div><a data-docs-component-link href="/components/preference-switcher">Preference Switcher</a><a data-docs-component-link href="/components/toaster">Toaster</a></div>
<div><a data-docs-component-link href="/components/drawflow-canvas">Drawflow Canvas</a><a data-docs-component-link href="/components/flow-canvas">Flow Canvas</a><a data-docs-component-link href="/components/preference-switcher">Preference Switcher</a><a data-docs-component-link href="/components/toaster">Toaster</a></div>
</section>
<section class="docs-directory-group">
<a class="docs-directory-heading" href="/data">Data</a>
+583 -44
View File
@@ -5,6 +5,9 @@ page ChartDetail {
state playground_description = ctx.url.searchParams.get("pg_description") ?? "Completed tasks this week"
state playground_items = JSON.parse(ctx.url.searchParams.get("pg_items") ?? "[{\"label\":\"Mon\",\"value\":24},{\"label\":\"Tue\",\"value\":38},{\"label\":\"Wed\",\"value\":29},{\"label\":\"Thu\",\"value\":52},{\"label\":\"Fri\",\"value\":45}]")
state playground_data = JSON.parse(ctx.url.searchParams.get("pg_data") ?? "[]")
state playground_labels = JSON.parse(ctx.url.searchParams.get("pg_labels") ?? "[]")
state playground_datasets = JSON.parse(ctx.url.searchParams.get("pg_datasets") ?? "[]")
state playground_options = JSON.parse(ctx.url.searchParams.get("pg_options") ?? "{}")
state playground_type = ctx.url.searchParams.get("pg_type") ?? ""
state playground_valueKey = ctx.url.searchParams.get("pg_valueKey") ?? "value"
state playground_labelKey = ctx.url.searchParams.get("pg_labelKey") ?? "label"
@@ -15,6 +18,17 @@ page ChartDetail {
state playground_color = ctx.url.searchParams.get("pg_color") ?? "primary"
state playground_variant = ctx.url.searchParams.get("pg_variant") ?? "bar"
state playground_class = ctx.url.searchParams.get("pg_class") ?? ""
state demo_obj_0 = JSON.parse("{\"labels\":[\"Mon\",\"Tue\",\"Wed\",\"Thu\",\"Fri\"],\"datasets\":[{\"label\":\"Series A\",\"data\":[24,38,29,52,45]}]}")
state demo_obj_1 = JSON.parse("{\"labels\":[\"Mon\",\"Tue\",\"Wed\",\"Thu\",\"Fri\"],\"datasets\":[{\"label\":\"Series A\",\"data\":[24,38,29,52,45]}]}")
state demo_obj_2 = JSON.parse("{\"labels\":[\"Mon\",\"Tue\",\"Wed\",\"Thu\",\"Fri\"],\"datasets\":[{\"label\":\"Series A\",\"data\":[24,38,29,52,45]}]}")
state demo_obj_3 = JSON.parse("{\"labels\":[\"Mon\",\"Tue\",\"Wed\",\"Thu\",\"Fri\"],\"datasets\":[{\"label\":\"Series A\",\"data\":[24,38,29,52,45]}]}")
state demo_obj_4 = JSON.parse("{\"labels\":[\"Mon\",\"Tue\",\"Wed\",\"Thu\",\"Fri\"],\"datasets\":[{\"label\":\"Series A\",\"data\":[24,38,29,52,45]}]}")
state demo_obj_5 = JSON.parse("{\"labels\":[\"Mon\",\"Tue\",\"Wed\",\"Thu\",\"Fri\"],\"datasets\":[{\"label\":\"Series A\",\"data\":[24,38,29,52,45]}]}")
state demo_obj_6 = JSON.parse("{\"datasets\":[{\"label\":\"Observations\",\"data\":[{\"x\":1,\"y\":4},{\"x\":3,\"y\":8},{\"x\":5,\"y\":3}]}]}")
state demo_obj_7 = JSON.parse("{\"datasets\":[{\"label\":\"Observations\",\"data\":[{\"x\":1,\"y\":4,\"r\":8},{\"x\":3,\"y\":8,\"r\":16},{\"x\":5,\"y\":3,\"r\":12}]}]}")
state demo_obj_8 = JSON.parse("{\"labels\":[\"Jan\",\"Feb\",\"Mar\"],\"datasets\":[{\"type\":\"bar\",\"label\":\"Actual\",\"data\":[20,35,28]},{\"type\":\"line\",\"label\":\"Target\",\"data\":[25,30,40]}]}")
state demo_obj_9 = JSON.parse("{\"labels\":[\"Jan\",\"Feb\",\"Mar\"],\"datasets\":[{\"label\":\"A\",\"data\":[20,35,28]},{\"label\":\"B\",\"data\":[25,30,40]}]}")
state demo_obj_10 = JSON.parse("{\"indexAxis\":\"y\",\"scales\":{\"x\":{\"stacked\":true},\"y\":{\"stacked\":true}}}")
seo {
title = "Chart"
description = "Theme-aware, responsive chart component."
@@ -28,7 +42,7 @@ page ChartDetail {
<span class="showcase-eyebrow">Integrations component</span>
<h1>Chart</h1>
<p>Theme-aware, responsive chart component.</p>
<div class="detail-badges"><span>14 props</span><span>1 slots</span><span>3 outputs</span><span>Theme ready</span><span>Responsive</span></div>
<div class="detail-badges"><span>17 props</span><span>1 slots</span><span>3 outputs</span><span>Theme ready</span><span>Responsive</span></div>
</div>
<div class="detail-hero-icon"><span class="icon-[lucide--component] size-10" aria-hidden="true"></span></div>
</header>
@@ -37,7 +51,7 @@ page ChartDetail {
<div class="playground-workbench">
<div class="playground-preview">
<div class="demo-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
<div class="playground-preview-source" data-playground-preview><Chart title='{playground_title}' description='{playground_description}' items='{playground_items}' data='{playground_data}' type='{playground_type}' valueKey='{playground_valueKey}' labelKey='{playground_labelKey}' height='{playground_height}' showLegend='{playground_showLegend}' showValues='{playground_showValues}' size='{playground_size}' color='{playground_color}' variant='{playground_variant}' class='{playground_class}' /></div>
<div class="playground-preview-source" data-playground-preview><Chart title='{playground_title}' description='{playground_description}' items='{playground_items}' data='{playground_data}' labels='{playground_labels}' datasets='{playground_datasets}' options='{playground_options}' type='{playground_type}' valueKey='{playground_valueKey}' labelKey='{playground_labelKey}' height='{playground_height}' showLegend='{playground_showLegend}' showValues='{playground_showValues}' size='{playground_size}' color='{playground_color}' variant='{playground_variant}' class='{playground_class}' /></div>
<section class="playground-code" aria-label="Current component code">
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component code</span><button type="button" data-playground-copy><span class="icon-[lucide--copy] size-4" aria-hidden="true"></span>Copy</button></header>
<pre><code data-playground-code>page ChartExample <span>&#123;</span>
@@ -63,13 +77,15 @@ page ChartDetail {
"value": 45
<span>&#125;</span>
]
state data = []
state labels = []
state datasets = []
view <span>&#123;</span>
&lt;Chart
title="Weekly activity"
description="Completed tasks this week"
items="<span>&#123;</span>items<span>&#125;</span>"
data="<span>&#123;</span>data<span>&#125;</span>"
labels="<span>&#123;</span>labels<span>&#125;</span>"
datasets="<span>&#123;</span>datasets<span>&#125;</span>"
height="220"
showLegend="false"
/&gt;
@@ -80,7 +96,7 @@ page ChartDetail {
<div class="playground-event-log" data-playground-event-log aria-live="polite"><strong>Event output</strong><span>Interact with the preview to inspect the typed <code>payload</code>.</span></div>
</div>
<form class="playground-controls" data-playground-form>
<header><div><span>Component props</span><strong>14 controls</strong></div><button type="reset"><span class="icon-[lucide--rotate-ccw] size-4" aria-hidden="true"></span>Reset</button></header>
<header><div><span>Component props</span><strong>17 controls</strong></div><button type="reset"><span class="icon-[lucide--rotate-ccw] size-4" aria-hidden="true"></span>Reset</button></header>
<div class="playground-fields"><label class="playground-field" for="playground-chart-title"><span><strong>title</strong><small>string</small></span><input id="playground-chart-title" name="pg_title" type="text" value="Weekly activity" /></label><label class="playground-field" for="playground-chart-description"><span><strong>description</strong><small>string</small></span><input id="playground-chart-description" name="pg_description" type="text" value="Completed tasks this week" /></label><label class="playground-field" for="playground-chart-items"><span><strong>items</strong><small>unknown[]</small></span><textarea id="playground-chart-items" name="pg_items" rows="5" spellcheck="false" data-playground-json>[
&#123;
"label": "Mon",
@@ -102,7 +118,7 @@ page ChartDetail {
"label": "Fri",
"value": 45
&#125;
]</textarea><em data-playground-error></em></label><label class="playground-field" for="playground-chart-data"><span><strong>data</strong><small>unknown[]</small></span><textarea id="playground-chart-data" name="pg_data" rows="5" spellcheck="false" data-playground-json>[]</textarea><em data-playground-error></em></label><label class="playground-field" for="playground-chart-type"><span><strong>type</strong><small>string</small></span><select id="playground-chart-type" name="pg_type"><option value="" selected>Auto / default</option><option value="bar">bar</option><option value="line">line</option></select></label><label class="playground-field" for="playground-chart-valueKey"><span><strong>value Key</strong><small>string</small></span><input id="playground-chart-valueKey" name="pg_valueKey" type="text" value="value" /></label><label class="playground-field" for="playground-chart-labelKey"><span><strong>label Key</strong><small>string</small></span><input id="playground-chart-labelKey" name="pg_labelKey" type="text" value="label" /></label><label class="playground-field" for="playground-chart-height"><span><strong>height</strong><small>number</small></span><input id="playground-chart-height" name="pg_height" type="number" value="220" /></label><label class="playground-toggle" for="playground-chart-showLegend"><span><strong>show Legend</strong><small>boolean</small></span><input id="playground-chart-showLegend" name="pg_showLegend" type="checkbox" value="true" data-playground-boolean /><i aria-hidden="true"></i></label><label class="playground-toggle" for="playground-chart-showValues"><span><strong>show Values</strong><small>boolean</small></span><input id="playground-chart-showValues" name="pg_showValues" type="checkbox" value="true" checked data-playground-boolean /><i aria-hidden="true"></i></label><label class="playground-field" for="playground-chart-size"><span><strong>size</strong><small>string</small></span><select id="playground-chart-size" name="pg_size"><option value="default" selected>default</option><option value="xs">xs</option><option value="sm">sm</option><option value="md">md</option><option value="lg">lg</option><option value="xl">xl</option><option value="icon">icon</option><option value="icon-xs">icon-xs</option><option value="icon-sm">icon-sm</option><option value="icon-lg">icon-lg</option></select></label><label class="playground-field" for="playground-chart-color"><span><strong>color</strong><small>string</small></span><select id="playground-chart-color" name="pg_color"><option value="primary" selected>primary</option><option value="secondary">secondary</option><option value="success">success</option><option value="warning">warning</option><option value="danger">danger</option><option value="info">info</option></select></label><label class="playground-field" for="playground-chart-variant"><span><strong>variant</strong><small>string</small></span><input id="playground-chart-variant" name="pg_variant" type="text" value="bar" /></label><label class="playground-field" for="playground-chart-class"><span><strong>class</strong><small>string</small></span><input id="playground-chart-class" name="pg_class" type="text" value="" /></label></div>
]</textarea><em data-playground-error></em></label><label class="playground-field" for="playground-chart-data"><span><strong>data</strong><small>unknown</small></span><input id="playground-chart-data" name="pg_data" type="text" value="" /></label><label class="playground-field" for="playground-chart-labels"><span><strong>labels</strong><small>unknown[]</small></span><textarea id="playground-chart-labels" name="pg_labels" rows="5" spellcheck="false" data-playground-json>[]</textarea><em data-playground-error></em></label><label class="playground-field" for="playground-chart-datasets"><span><strong>datasets</strong><small>unknown[]</small></span><textarea id="playground-chart-datasets" name="pg_datasets" rows="5" spellcheck="false" data-playground-json>[]</textarea><em data-playground-error></em></label><label class="playground-field" for="playground-chart-options"><span><strong>options</strong><small>object</small></span><textarea id="playground-chart-options" name="pg_options" rows="5" spellcheck="false" data-playground-json></textarea><em data-playground-error></em></label><label class="playground-field" for="playground-chart-type"><span><strong>type</strong><small>string</small></span><select id="playground-chart-type" name="pg_type"><option value="" selected>Auto / default</option><option value="bar">bar</option><option value="line">line</option><option value="area">area</option><option value="pie">pie</option><option value="doughnut">doughnut</option><option value="radar">radar</option><option value="polarArea">polarArea</option><option value="scatter">scatter</option><option value="bubble">bubble</option></select></label><label class="playground-field" for="playground-chart-valueKey"><span><strong>value Key</strong><small>string</small></span><input id="playground-chart-valueKey" name="pg_valueKey" type="text" value="value" /></label><label class="playground-field" for="playground-chart-labelKey"><span><strong>label Key</strong><small>string</small></span><input id="playground-chart-labelKey" name="pg_labelKey" type="text" value="label" /></label><label class="playground-field" for="playground-chart-height"><span><strong>height</strong><small>number</small></span><input id="playground-chart-height" name="pg_height" type="number" value="220" /></label><label class="playground-toggle" for="playground-chart-showLegend"><span><strong>show Legend</strong><small>boolean</small></span><input id="playground-chart-showLegend" name="pg_showLegend" type="checkbox" value="true" data-playground-boolean /><i aria-hidden="true"></i></label><label class="playground-toggle" for="playground-chart-showValues"><span><strong>show Values</strong><small>boolean</small></span><input id="playground-chart-showValues" name="pg_showValues" type="checkbox" value="true" checked data-playground-boolean /><i aria-hidden="true"></i></label><label class="playground-field" for="playground-chart-size"><span><strong>size</strong><small>string</small></span><select id="playground-chart-size" name="pg_size"><option value="default" selected>default</option><option value="xs">xs</option><option value="sm">sm</option><option value="md">md</option><option value="lg">lg</option><option value="xl">xl</option><option value="icon">icon</option><option value="icon-xs">icon-xs</option><option value="icon-sm">icon-sm</option><option value="icon-lg">icon-lg</option></select></label><label class="playground-field" for="playground-chart-color"><span><strong>color</strong><small>string</small></span><select id="playground-chart-color" name="pg_color"><option value="primary" selected>primary</option><option value="secondary">secondary</option><option value="success">success</option><option value="warning">warning</option><option value="danger">danger</option><option value="info">info</option></select></label><label class="playground-field" for="playground-chart-variant"><span><strong>variant</strong><small>string</small></span><input id="playground-chart-variant" name="pg_variant" type="text" value="bar" /></label><label class="playground-field" for="playground-chart-class"><span><strong>class</strong><small>string</small></span><input id="playground-chart-class" name="pg_class" type="text" value="" /></label></div>
</form>
</div>
</section>
@@ -111,27 +127,34 @@ page ChartDetail {
<section class="detail-section"><div class="detail-section-heading"><span>Live examples</span><h2>Designed for real product surfaces</h2><p>Compare configurations and resize the browser to check responsive behavior.</p></div><div class="demo-list">
<article class="demo-case">
<header class="demo-case-header">
<div><span class="demo-case-eyebrow">Recommended</span><h2>Bar chart</h2><p>Pass an array of label/value objects through data.</p></div>
<div><span class="demo-case-eyebrow">Recommended</span><h2>Bar chart</h2><p>Chart.js bars with positive and negative values.</p></div>
<span class="demo-case-number">01</span>
</header>
<div class="demo-workbench">
<div id="chart-demo-1" class="demo-canvas demo-canvas--1">
<div class="demo-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
<div class="demo-render"><Chart title="Weekly signups" description="Completed tasks this week" items='[]' data='[{"label":"Mon","value":24},{"label":"Tue","value":38},{"label":"Wed","value":29},{"label":"Thu","value":52},{"label":"Fri","value":45}]' type="bar" valueKey="value" labelKey="label" height="220" showLegend="false" showValues="true" size="default" color="primary" variant="bar" class="" /></div>
<div class="demo-render"><Chart title="Sample weekly changes" description="Sample data" items='[]' data='[{"label":"Mon","value":24},{"label":"Tue","value":-12},{"label":"Wed","value":29},{"label":"Thu","value":52},{"label":"Fri","value":45}]' labels='[]' datasets='[]' type="bar" valueKey="value" labelKey="label" height="220" showLegend="true" showValues="false" size="default" color="primary" variant="bar" class="" /></div>
</div>
<section class="demo-code" aria-label="Bar chart usage">
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
<pre><code>page ChartExample <span>&#123;</span>
state items = []
state data = [
state labels = []
state datasets = []
view <span>&#123;</span>
&lt;Chart
title="Sample weekly changes"
description="Sample data"
items="<span>&#123;</span>items<span>&#125;</span>"
data='[
<span>&#123;</span>
"label": "Mon",
"value": 24
<span>&#125;</span>,
<span>&#123;</span>
"label": "Tue",
"value": 38
"value": -12
<span>&#125;</span>,
<span>&#123;</span>
"label": "Wed",
@@ -145,16 +168,12 @@ page ChartDetail {
"label": "Fri",
"value": 45
<span>&#125;</span>
]
view <span>&#123;</span>
&lt;Chart
title="Weekly signups"
description="Completed tasks this week"
items="<span>&#123;</span>items<span>&#125;</span>"
data="<span>&#123;</span>data<span>&#125;</span>"
]'
labels="<span>&#123;</span>labels<span>&#125;</span>"
datasets="<span>&#123;</span>datasets<span>&#125;</span>"
type="bar"
height="220"
showLegend="false"
showValues="false"
/&gt;
<span>&#125;</span>
<span>&#125;</span></code></pre>
@@ -163,46 +182,566 @@ page ChartDetail {
</article>
<article class="demo-case">
<header class="demo-case-header">
<div><span class="demo-case-eyebrow">Compact</span><h2>Line chart</h2><p>Use type=line to compare a trend over time.</p></div>
<div><span class="demo-case-eyebrow">Compact</span><h2>line chart</h2><p>Rendered by Chart.js with native tooltips and legend interactions.</p></div>
<span class="demo-case-number">02</span>
</header>
<div class="demo-workbench">
<div id="chart-demo-2" class="demo-canvas demo-canvas--2">
<div class="demo-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
<div class="demo-render"><Chart title="Monthly revenue" description="Completed tasks this week" items='[]' data='[{"label":"Jan","value":20},{"label":"Feb","value":35},{"label":"Mar","value":28},{"label":"Apr","value":55}]' type="line" valueKey="value" labelKey="label" height="220" showLegend="false" showValues="true" size="default" color="primary" variant="bar" class="" /></div>
<div class="demo-render"><Chart title="Sample line" description="Sample data" items='[]' data='{demo_obj_0}' labels='[]' datasets='[]' type="line" valueKey="value" labelKey="label" height="220" showLegend="true" showValues="false" size="default" color="primary" variant="bar" class="" /></div>
</div>
<section class="demo-code" aria-label="Line chart usage">
<section class="demo-code" aria-label="line chart usage">
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
<pre><code>page ChartExample <span>&#123;</span>
state items = []
state data = [
<span>&#123;</span>
"label": "Jan",
"value": 20
<span>&#125;</span>,
<span>&#123;</span>
"label": "Feb",
"value": 35
<span>&#125;</span>,
<span>&#123;</span>
"label": "Mar",
"value": 28
<span>&#125;</span>,
<span>&#123;</span>
"label": "Apr",
"value": 55
<span>&#125;</span>
]
state labels = []
state datasets = []
view <span>&#123;</span>
&lt;Chart
title="Monthly revenue"
description="Completed tasks this week"
title="Sample line"
description="Sample data"
items="<span>&#123;</span>items<span>&#125;</span>"
data="<span>&#123;</span>data<span>&#125;</span>"
data='<span>&#123;</span>
"labels": [
"Mon",
"Tue",
"Wed",
"Thu",
"Fri"
],
"datasets": [
<span>&#123;</span>
"label": "Series A",
"data": [
24,
38,
29,
52,
45
]
<span>&#125;</span>
]
<span>&#125;</span>'
labels="<span>&#123;</span>labels<span>&#125;</span>"
datasets="<span>&#123;</span>datasets<span>&#125;</span>"
type="line"
height="220"
showValues="false"
/&gt;
<span>&#125;</span>
<span>&#125;</span></code></pre>
</section>
</div>
</article>
<article class="demo-case">
<header class="demo-case-header">
<div><span class="demo-case-eyebrow">Compact</span><h2>area chart</h2><p>Rendered by Chart.js with native tooltips and legend interactions.</p></div>
<span class="demo-case-number">03</span>
</header>
<div class="demo-workbench">
<div id="chart-demo-3" class="demo-canvas demo-canvas--3">
<div class="demo-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
<div class="demo-render"><Chart title="Sample area" description="Sample data" items='[]' data='{demo_obj_1}' labels='[]' datasets='[]' type="area" valueKey="value" labelKey="label" height="220" showLegend="true" showValues="false" size="default" color="primary" variant="bar" class="" /></div>
</div>
<section class="demo-code" aria-label="area chart usage">
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
<pre><code>page ChartExample <span>&#123;</span>
state items = []
state labels = []
state datasets = []
view <span>&#123;</span>
&lt;Chart
title="Sample area"
description="Sample data"
items="<span>&#123;</span>items<span>&#125;</span>"
data='<span>&#123;</span>
"labels": [
"Mon",
"Tue",
"Wed",
"Thu",
"Fri"
],
"datasets": [
<span>&#123;</span>
"label": "Series A",
"data": [
24,
38,
29,
52,
45
]
<span>&#125;</span>
]
<span>&#125;</span>'
labels="<span>&#123;</span>labels<span>&#125;</span>"
datasets="<span>&#123;</span>datasets<span>&#125;</span>"
type="area"
height="220"
showValues="false"
/&gt;
<span>&#125;</span>
<span>&#125;</span></code></pre>
</section>
</div>
</article>
<article class="demo-case">
<header class="demo-case-header">
<div><span class="demo-case-eyebrow">Compact</span><h2>pie chart</h2><p>Rendered by Chart.js with native tooltips and legend interactions.</p></div>
<span class="demo-case-number">04</span>
</header>
<div class="demo-workbench">
<div id="chart-demo-4" class="demo-canvas demo-canvas--4">
<div class="demo-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
<div class="demo-render"><Chart title="Sample pie" description="Sample data" items='[]' data='{demo_obj_2}' labels='[]' datasets='[]' type="pie" valueKey="value" labelKey="label" height="220" showLegend="true" showValues="false" size="default" color="primary" variant="bar" class="" /></div>
</div>
<section class="demo-code" aria-label="pie chart usage">
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
<pre><code>page ChartExample <span>&#123;</span>
state items = []
state labels = []
state datasets = []
view <span>&#123;</span>
&lt;Chart
title="Sample pie"
description="Sample data"
items="<span>&#123;</span>items<span>&#125;</span>"
data='<span>&#123;</span>
"labels": [
"Mon",
"Tue",
"Wed",
"Thu",
"Fri"
],
"datasets": [
<span>&#123;</span>
"label": "Series A",
"data": [
24,
38,
29,
52,
45
]
<span>&#125;</span>
]
<span>&#125;</span>'
labels="<span>&#123;</span>labels<span>&#125;</span>"
datasets="<span>&#123;</span>datasets<span>&#125;</span>"
type="pie"
height="220"
showValues="false"
/&gt;
<span>&#125;</span>
<span>&#125;</span></code></pre>
</section>
</div>
</article>
<article class="demo-case">
<header class="demo-case-header">
<div><span class="demo-case-eyebrow">Compact</span><h2>doughnut chart</h2><p>Rendered by Chart.js with native tooltips and legend interactions.</p></div>
<span class="demo-case-number">05</span>
</header>
<div class="demo-workbench">
<div id="chart-demo-5" class="demo-canvas demo-canvas--5">
<div class="demo-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
<div class="demo-render"><Chart title="Sample doughnut" description="Sample data" items='[]' data='{demo_obj_3}' labels='[]' datasets='[]' type="doughnut" valueKey="value" labelKey="label" height="220" showLegend="true" showValues="false" size="default" color="primary" variant="bar" class="" /></div>
</div>
<section class="demo-code" aria-label="doughnut chart usage">
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
<pre><code>page ChartExample <span>&#123;</span>
state items = []
state labels = []
state datasets = []
view <span>&#123;</span>
&lt;Chart
title="Sample doughnut"
description="Sample data"
items="<span>&#123;</span>items<span>&#125;</span>"
data='<span>&#123;</span>
"labels": [
"Mon",
"Tue",
"Wed",
"Thu",
"Fri"
],
"datasets": [
<span>&#123;</span>
"label": "Series A",
"data": [
24,
38,
29,
52,
45
]
<span>&#125;</span>
]
<span>&#125;</span>'
labels="<span>&#123;</span>labels<span>&#125;</span>"
datasets="<span>&#123;</span>datasets<span>&#125;</span>"
type="doughnut"
height="220"
showValues="false"
/&gt;
<span>&#125;</span>
<span>&#125;</span></code></pre>
</section>
</div>
</article>
<article class="demo-case">
<header class="demo-case-header">
<div><span class="demo-case-eyebrow">Compact</span><h2>radar chart</h2><p>Rendered by Chart.js with native tooltips and legend interactions.</p></div>
<span class="demo-case-number">06</span>
</header>
<div class="demo-workbench">
<div id="chart-demo-6" class="demo-canvas demo-canvas--6">
<div class="demo-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
<div class="demo-render"><Chart title="Sample radar" description="Sample data" items='[]' data='{demo_obj_4}' labels='[]' datasets='[]' type="radar" valueKey="value" labelKey="label" height="220" showLegend="true" showValues="false" size="default" color="primary" variant="bar" class="" /></div>
</div>
<section class="demo-code" aria-label="radar chart usage">
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
<pre><code>page ChartExample <span>&#123;</span>
state items = []
state labels = []
state datasets = []
view <span>&#123;</span>
&lt;Chart
title="Sample radar"
description="Sample data"
items="<span>&#123;</span>items<span>&#125;</span>"
data='<span>&#123;</span>
"labels": [
"Mon",
"Tue",
"Wed",
"Thu",
"Fri"
],
"datasets": [
<span>&#123;</span>
"label": "Series A",
"data": [
24,
38,
29,
52,
45
]
<span>&#125;</span>
]
<span>&#125;</span>'
labels="<span>&#123;</span>labels<span>&#125;</span>"
datasets="<span>&#123;</span>datasets<span>&#125;</span>"
type="radar"
height="220"
showValues="false"
/&gt;
<span>&#125;</span>
<span>&#125;</span></code></pre>
</section>
</div>
</article>
<article class="demo-case">
<header class="demo-case-header">
<div><span class="demo-case-eyebrow">Compact</span><h2>polarArea chart</h2><p>Rendered by Chart.js with native tooltips and legend interactions.</p></div>
<span class="demo-case-number">07</span>
</header>
<div class="demo-workbench">
<div id="chart-demo-7" class="demo-canvas demo-canvas--7">
<div class="demo-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
<div class="demo-render"><Chart title="Sample polarArea" description="Sample data" items='[]' data='{demo_obj_5}' labels='[]' datasets='[]' type="polarArea" valueKey="value" labelKey="label" height="220" showLegend="true" showValues="false" size="default" color="primary" variant="bar" class="" /></div>
</div>
<section class="demo-code" aria-label="polarArea chart usage">
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
<pre><code>page ChartExample <span>&#123;</span>
state items = []
state labels = []
state datasets = []
view <span>&#123;</span>
&lt;Chart
title="Sample polarArea"
description="Sample data"
items="<span>&#123;</span>items<span>&#125;</span>"
data='<span>&#123;</span>
"labels": [
"Mon",
"Tue",
"Wed",
"Thu",
"Fri"
],
"datasets": [
<span>&#123;</span>
"label": "Series A",
"data": [
24,
38,
29,
52,
45
]
<span>&#125;</span>
]
<span>&#125;</span>'
labels="<span>&#123;</span>labels<span>&#125;</span>"
datasets="<span>&#123;</span>datasets<span>&#125;</span>"
type="polarArea"
height="220"
showValues="false"
/&gt;
<span>&#125;</span>
<span>&#125;</span></code></pre>
</section>
</div>
</article>
<article class="demo-case">
<header class="demo-case-header">
<div><span class="demo-case-eyebrow">Advanced</span><h2>Scatter chart</h2><p>Pass native x/y coordinates without flattening them.</p></div>
<span class="demo-case-number">08</span>
</header>
<div class="demo-workbench">
<div id="chart-demo-8" class="demo-canvas demo-canvas--8">
<div class="demo-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
<div class="demo-render"><Chart title="Sample coordinates" description="Sample data" items='[]' data='{demo_obj_6}' labels='[]' datasets='[]' type="scatter" valueKey="value" labelKey="label" height="220" showLegend="false" showValues="false" size="default" color="primary" variant="bar" class="" /></div>
</div>
<section class="demo-code" aria-label="Scatter chart usage">
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
<pre><code>page ChartExample <span>&#123;</span>
state items = []
state labels = []
state datasets = []
view <span>&#123;</span>
&lt;Chart
title="Sample coordinates"
description="Sample data"
items="<span>&#123;</span>items<span>&#125;</span>"
data='<span>&#123;</span>
"datasets": [
<span>&#123;</span>
"label": "Observations",
"data": [
<span>&#123;</span>
"x": 1,
"y": 4
<span>&#125;</span>,
<span>&#123;</span>
"x": 3,
"y": 8
<span>&#125;</span>,
<span>&#123;</span>
"x": 5,
"y": 3
<span>&#125;</span>
]
<span>&#125;</span>
]
<span>&#125;</span>'
labels="<span>&#123;</span>labels<span>&#125;</span>"
datasets="<span>&#123;</span>datasets<span>&#125;</span>"
type="scatter"
height="220"
showLegend="false"
showValues="false"
/&gt;
<span>&#125;</span>
<span>&#125;</span></code></pre>
</section>
</div>
</article>
<article class="demo-case">
<header class="demo-case-header">
<div><span class="demo-case-eyebrow">Advanced</span><h2>Bubble chart</h2><p>Native x/y/r points preserve bubble radii.</p></div>
<span class="demo-case-number">09</span>
</header>
<div class="demo-workbench">
<div id="chart-demo-9" class="demo-canvas demo-canvas--9">
<div class="demo-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
<div class="demo-render"><Chart title="Sample bubbles" description="Sample data" items='[]' data='{demo_obj_7}' labels='[]' datasets='[]' type="bubble" valueKey="value" labelKey="label" height="220" showLegend="false" showValues="false" size="default" color="primary" variant="bar" class="" /></div>
</div>
<section class="demo-code" aria-label="Bubble chart usage">
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
<pre><code>page ChartExample <span>&#123;</span>
state items = []
state labels = []
state datasets = []
view <span>&#123;</span>
&lt;Chart
title="Sample bubbles"
description="Sample data"
items="<span>&#123;</span>items<span>&#125;</span>"
data='<span>&#123;</span>
"datasets": [
<span>&#123;</span>
"label": "Observations",
"data": [
<span>&#123;</span>
"x": 1,
"y": 4,
"r": 8
<span>&#125;</span>,
<span>&#123;</span>
"x": 3,
"y": 8,
"r": 16
<span>&#125;</span>,
<span>&#123;</span>
"x": 5,
"y": 3,
"r": 12
<span>&#125;</span>
]
<span>&#125;</span>
]
<span>&#125;</span>'
labels="<span>&#123;</span>labels<span>&#125;</span>"
datasets="<span>&#123;</span>datasets<span>&#125;</span>"
type="bubble"
height="220"
showLegend="false"
showValues="false"
/&gt;
<span>&#125;</span>
<span>&#125;</span></code></pre>
</section>
</div>
</article>
<article class="demo-case">
<header class="demo-case-header">
<div><span class="demo-case-eyebrow">Advanced</span><h2>Mixed chart</h2><p>Set each dataset's type and pass native Chart.js options.</p></div>
<span class="demo-case-number">010</span>
</header>
<div class="demo-workbench">
<div id="chart-demo-10" class="demo-canvas demo-canvas--10">
<div class="demo-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
<div class="demo-render"><Chart title="Sample mixed chart" description="Sample data" items='[]' data='{demo_obj_8}' labels='[]' datasets='[]' type="bar" valueKey="value" labelKey="label" height="220" showLegend="false" showValues="false" size="default" color="primary" variant="bar" class="" /></div>
</div>
<section class="demo-code" aria-label="Mixed chart usage">
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
<pre><code>page ChartExample <span>&#123;</span>
state items = []
state labels = []
state datasets = []
view <span>&#123;</span>
&lt;Chart
title="Sample mixed chart"
description="Sample data"
items="<span>&#123;</span>items<span>&#125;</span>"
data='<span>&#123;</span>
"labels": [
"Jan",
"Feb",
"Mar"
],
"datasets": [
<span>&#123;</span>
"type": "bar",
"label": "Actual",
"data": [
20,
35,
28
]
<span>&#125;</span>,
<span>&#123;</span>
"type": "line",
"label": "Target",
"data": [
25,
30,
40
]
<span>&#125;</span>
]
<span>&#125;</span>'
labels="<span>&#123;</span>labels<span>&#125;</span>"
datasets="<span>&#123;</span>datasets<span>&#125;</span>"
type="bar"
height="220"
showLegend="false"
showValues="false"
/&gt;
<span>&#125;</span>
<span>&#125;</span></code></pre>
</section>
</div>
</article>
<article class="demo-case">
<header class="demo-case-header">
<div><span class="demo-case-eyebrow">Advanced</span><h2>Horizontal stacked bars</h2><p>Configure indexAxis and stacked scales through options.</p></div>
<span class="demo-case-number">011</span>
</header>
<div class="demo-workbench">
<div id="chart-demo-11" class="demo-canvas demo-canvas--11">
<div class="demo-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
<div class="demo-render"><Chart title="Sample stacked chart" description="Sample data" items='[]' data='{demo_obj_9}' labels='[]' datasets='[]' options='{demo_obj_10}' type="bar" valueKey="value" labelKey="label" height="220" showLegend="false" showValues="false" size="default" color="primary" variant="bar" class="" /></div>
</div>
<section class="demo-code" aria-label="Horizontal stacked bars usage">
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
<pre><code>page ChartExample <span>&#123;</span>
state items = []
state labels = []
state datasets = []
view <span>&#123;</span>
&lt;Chart
title="Sample stacked chart"
description="Sample data"
items="<span>&#123;</span>items<span>&#125;</span>"
data='<span>&#123;</span>
"labels": [
"Jan",
"Feb",
"Mar"
],
"datasets": [
<span>&#123;</span>
"label": "A",
"data": [
20,
35,
28
]
<span>&#125;</span>,
<span>&#123;</span>
"label": "B",
"data": [
25,
30,
40
]
<span>&#125;</span>
]
<span>&#125;</span>'
labels="<span>&#123;</span>labels<span>&#125;</span>"
datasets="<span>&#123;</span>datasets<span>&#125;</span>"
options='<span>&#123;</span>
"indexAxis": "y",
"scales": <span>&#123;</span>
"x": <span>&#123;</span>
"stacked": true
<span>&#125;</span>,
"y": <span>&#123;</span>
"stacked": true
<span>&#125;</span>
<span>&#125;</span>
<span>&#125;</span>'
type="bar"
height="220"
showLegend="false"
showValues="false"
/&gt;
<span>&#125;</span>
<span>&#125;</span></code></pre>
@@ -228,10 +767,10 @@ if (component) registerOutputHandler(component, "dataPointClick", (payload) =&gt
if (component) registerOutputHandler(component, "legendToggle", (payload) =&gt; <span>&#123;</span>
console.log("legendToggle", payload)
<span>&#125;</span>)</code></pre></section></div></div></section>
<section id="api" class="detail-section"><div class="detail-section-heading"><span>Component API</span><h2>Props and configuration</h2><p>All content and behavior shown above is supplied through these props and slots.</p></div><div class="docs-table-wrap"><table class="docs-table"><thead><tr><th>Prop</th><th>Type</th><th>Default</th><th>Required</th></tr></thead><tbody><tr><td><code>title</code></td><td>string</td><td><code>"Chart"</code></td><td>No</td></tr><tr><td><code>description</code></td><td>string</td><td><code>""</code></td><td>No</td></tr><tr><td><code>items</code></td><td>unknown[]</td><td><code>[]</code></td><td>No</td></tr><tr><td><code>data</code></td><td>unknown[]</td><td><code>[]</code></td><td>No</td></tr><tr><td><code>type</code></td><td>string</td><td><code>""</code></td><td>No</td></tr><tr><td><code>valueKey</code></td><td>string</td><td><code>"value"</code></td><td>No</td></tr><tr><td><code>labelKey</code></td><td>string</td><td><code>"label"</code></td><td>No</td></tr><tr><td><code>height</code></td><td>number</td><td><code>240</code></td><td>No</td></tr><tr><td><code>showLegend</code></td><td>boolean</td><td><code>true</code></td><td>No</td></tr><tr><td><code>showValues</code></td><td>boolean</td><td><code>true</code></td><td>No</td></tr><tr><td><code>size</code></td><td>string</td><td><code>"default"</code></td><td>No</td></tr><tr><td><code>color</code></td><td>string</td><td><code>"primary"</code></td><td>No</td></tr><tr><td><code>variant</code></td><td>string</td><td><code>"bar"</code></td><td>No</td></tr><tr><td><code>class</code></td><td>string</td><td><code>""</code></td><td>No</td></tr></tbody></table></div></section>
<section id="api" class="detail-section"><div class="detail-section-heading"><span>Component API</span><h2>Props and configuration</h2><p>All content and behavior shown above is supplied through these props and slots.</p></div><div class="docs-table-wrap"><table class="docs-table"><thead><tr><th>Prop</th><th>Type</th><th>Default</th><th>Required</th></tr></thead><tbody><tr><td><code>title</code></td><td>string</td><td><code>"Chart"</code></td><td>No</td></tr><tr><td><code>description</code></td><td>string</td><td><code>""</code></td><td>No</td></tr><tr><td><code>items</code></td><td>unknown[]</td><td><code>[]</code></td><td>No</td></tr><tr><td><code>data</code></td><td>unknown</td><td><code>undefined</code></td><td>No</td></tr><tr><td><code>labels</code></td><td>unknown[]</td><td><code>[]</code></td><td>No</td></tr><tr><td><code>datasets</code></td><td>unknown[]</td><td><code>[]</code></td><td>No</td></tr><tr><td><code>options</code></td><td>object</td><td><code><span>&#123;</span><span>&#125;</span></code></td><td>No</td></tr><tr><td><code>type</code></td><td>string</td><td><code>""</code></td><td>No</td></tr><tr><td><code>valueKey</code></td><td>string</td><td><code>"value"</code></td><td>No</td></tr><tr><td><code>labelKey</code></td><td>string</td><td><code>"label"</code></td><td>No</td></tr><tr><td><code>height</code></td><td>number</td><td><code>240</code></td><td>No</td></tr><tr><td><code>showLegend</code></td><td>boolean</td><td><code>true</code></td><td>No</td></tr><tr><td><code>showValues</code></td><td>boolean</td><td><code>true</code></td><td>No</td></tr><tr><td><code>size</code></td><td>string</td><td><code>"default"</code></td><td>No</td></tr><tr><td><code>color</code></td><td>string</td><td><code>"primary"</code></td><td>No</td></tr><tr><td><code>variant</code></td><td>string</td><td><code>"bar"</code></td><td>No</td></tr><tr><td><code>class</code></td><td>string</td><td><code>""</code></td><td>No</td></tr></tbody></table></div></section>
</main>
<aside class="detail-aside">
<div class="detail-toc"><strong>On this page</strong><a href="#playground">Playground</a><a href="#chart-demo-1">Bar chart</a><a href="#chart-demo-2">Line chart</a><a href="#events">Outputs</a><a href="#api">Props API</a></div>
<div class="detail-toc"><strong>On this page</strong><a href="#playground">Playground</a><a href="#chart-demo-1">Bar chart</a><a href="#chart-demo-2">line chart</a><a href="#chart-demo-3">area chart</a><a href="#chart-demo-4">pie chart</a><a href="#chart-demo-5">doughnut chart</a><a href="#chart-demo-6">radar chart</a><a href="#chart-demo-7">polarArea chart</a><a href="#chart-demo-8">Scatter chart</a><a href="#chart-demo-9">Bubble chart</a><a href="#chart-demo-10">Mixed chart</a><a href="#chart-demo-11">Horizontal stacked bars</a><a href="#events">Outputs</a><a href="#api">Props API</a></div>
</aside>
</div>
<nav class="detail-pagination">
+132
View File
@@ -0,0 +1,132 @@
// Generated by scripts/generate-showcase.mjs. Do not edit directly.
page DrawflowCanvasDetail {
layout = "showcase"
state playground_nodes = JSON.parse(ctx.url.searchParams.get("pg_nodes") ?? "[]")
state playground_toolbar = (ctx.url.searchParams.get("pg_toolbar") ?? "true") === "true"
state playground_class = ctx.url.searchParams.get("pg_class") ?? "showcase-instance showcase-instance--1"
seo {
title = "Drawflow Canvas"
description = "Reusable drawflow canvas component."
}
view {
<nav class="docs-breadcrumbs" aria-label="Breadcrumb">
<a href="/">Components</a><span aria-hidden="true">/</span><a href="/core">Core</a><span aria-hidden="true">/</span><span>Drawflow Canvas</span>
</nav>
<header class="detail-hero">
<div class="detail-hero-copy">
<span class="showcase-eyebrow">Core component</span>
<h1>Drawflow Canvas</h1>
<p>Reusable drawflow canvas component.</p>
<div class="detail-badges"><span>3 props</span><span>0 slots</span><span>4 outputs</span><span>Theme ready</span><span>Responsive</span></div>
</div>
<div class="detail-hero-icon"><span class="icon-[lucide--component] size-10" aria-hidden="true"></span></div>
</header>
<section id="playground" class="detail-section playground-section" data-playground data-playground-component="DrawflowCanvas" data-playground-public-tag="true" data-playground-has-slot="false" data-playground-events="select,connect,move,add">
<div class="detail-section-heading"><span>Interactive playground</span><h2>Configure Drawflow Canvas</h2><p>Change any prop and inspect the server-rendered component immediately.</p></div>
<div class="playground-workbench">
<div class="playground-preview">
<div class="demo-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
<div class="playground-preview-source" data-playground-preview><DrawflowCanvas nodes='{playground_nodes}' toolbar='{playground_toolbar}' class='{playground_class}' /></div>
<section class="playground-code" aria-label="Current component code">
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component code</span><button type="button" data-playground-copy><span class="icon-[lucide--copy] size-4" aria-hidden="true"></span>Copy</button></header>
<pre><code data-playground-code>&lt;DrawflowCanvas /&gt;</code></pre>
</section>
<div class="playground-status" data-playground-status aria-live="polite"></div>
<div class="playground-event-log" data-playground-event-log aria-live="polite"><strong>Event output</strong><span>Interact with the preview to inspect the typed <code>payload</code>.</span></div>
</div>
<form class="playground-controls" data-playground-form>
<header><div><span>Component props</span><strong>3 controls</strong></div><button type="reset"><span class="icon-[lucide--rotate-ccw] size-4" aria-hidden="true"></span>Reset</button></header>
<div class="playground-fields"><label class="playground-field" for="playground-drawflow-canvas-nodes"><span><strong>nodes</strong><small>string</small></span><textarea id="playground-drawflow-canvas-nodes" name="pg_nodes" rows="5" spellcheck="false" data-playground-json></textarea><em data-playground-error></em></label><label class="playground-toggle" for="playground-drawflow-canvas-toolbar"><span><strong>toolbar</strong><small>boolean</small></span><input id="playground-drawflow-canvas-toolbar" name="pg_toolbar" type="checkbox" value="true" checked data-playground-boolean /><i aria-hidden="true"></i></label><label class="playground-field" for="playground-drawflow-canvas-class"><span><strong>class</strong><small>string</small></span><input id="playground-drawflow-canvas-class" name="pg_class" type="text" value="showcase-instance showcase-instance--1" /></label></div>
</form>
</div>
</section>
<div class="detail-layout">
<main class="detail-content">
<section class="detail-section"><div class="detail-section-heading"><span>Live examples</span><h2>Designed for real product surfaces</h2><p>Compare configurations and resize the browser to check responsive behavior.</p></div><div class="demo-list">
<article class="demo-case">
<header class="demo-case-header">
<div><span class="demo-case-eyebrow">Recommended</span><h2>Production default</h2><p>Balanced spacing, hierarchy, and content for the most common product workflow.</p></div>
<span class="demo-case-number">01</span>
</header>
<div class="demo-workbench">
<div id="drawflow-canvas-demo-1" class="demo-canvas demo-canvas--1">
<div class="demo-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
<div class="demo-render"><DrawflowCanvas toolbar="true" class="showcase-instance showcase-instance--1" /></div>
</div>
<section class="demo-code" aria-label="Production default usage">
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
<pre><code>&lt;DrawflowCanvas /&gt;</code></pre>
</section>
</div>
</article>
<article class="demo-case">
<header class="demo-case-header">
<div><span class="demo-case-eyebrow">Dense UI</span><h2>Compact application</h2><p>A tighter variation for dashboards, side panels, tables, and operational interfaces.</p></div>
<span class="demo-case-number">02</span>
</header>
<div class="demo-workbench">
<div id="drawflow-canvas-demo-2" class="demo-canvas demo-canvas--2">
<div class="demo-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
<div class="demo-render"><DrawflowCanvas toolbar="true" class="showcase-instance showcase-instance--2" /></div>
</div>
<section class="demo-code" aria-label="Compact application usage">
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
<pre><code>&lt;DrawflowCanvas /&gt;</code></pre>
</section>
</div>
</article>
<article class="demo-case">
<header class="demo-case-header">
<div><span class="demo-case-eyebrow">Extended</span><h2>Rich configuration</h2><p>A more expressive variation using additional data, stronger emphasis, and optional states.</p></div>
<span class="demo-case-number">03</span>
</header>
<div class="demo-workbench">
<div id="drawflow-canvas-demo-3" class="demo-canvas demo-canvas--3">
<div class="demo-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
<div class="demo-render"><DrawflowCanvas toolbar="true" class="showcase-instance showcase-instance--3" /></div>
</div>
<section class="demo-code" aria-label="Rich configuration usage">
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
<pre><code>&lt;DrawflowCanvas /&gt;</code></pre>
</section>
</div>
</article></div></section>
<section id="events" class="detail-section"><div class="detail-section-heading"><span>Component outputs</span><h2>Receive every typed component output</h2><p>Use declarative output handlers in <code>.wrn</code> files or register a direct output handler from JavaScript. The canonical API exposes <code>payload</code> and does not require <code>event.detail</code>.</p></div><div class="detail-events-grid"><div class="detail-events-list"><div><code>@select</code><span>Fires when an item, option, card, or result is selected.</span></div><div><code>@connect</code><span>Fires when the component emits the connect event.</span></div><div><code>@move</code><span>Fires when the component emits the move event.</span></div><div><code>@add</code><span>Fires when the component emits the add event.</span></div></div><div class="detail-event-examples"><section class="demo-code"><header><span><span class="icon-[lucide--braces] size-4" aria-hidden="true"></span>Declarative handlers</span><small>.wrn</small></header><pre><code>&lt;DrawflowCanvas
@select='console.log(payload)'
@connect='console.log(payload)'
@move='console.log(payload)'
@add='console.log(payload)'
/&gt;</code></pre></section><section class="demo-code"><header><span><span class="icon-[lucide--radio] size-4" aria-hidden="true"></span>Direct output handlers</span><small>.js</small></header><pre><code>import <span>&#123;</span> registerOutputHandler <span>&#125;</span> from "@wrnexus/csr/outputs"
const component = document.querySelector("[data-ui-component=\"DrawflowCanvas\"], [data-component=\"DrawflowCanvas\"]")
if (component) registerOutputHandler(component, "select", (payload) =&gt; <span>&#123;</span>
console.log("select", payload)
<span>&#125;</span>)
if (component) registerOutputHandler(component, "connect", (payload) =&gt; <span>&#123;</span>
console.log("connect", payload)
<span>&#125;</span>)
if (component) registerOutputHandler(component, "move", (payload) =&gt; <span>&#123;</span>
console.log("move", payload)
<span>&#125;</span>)
if (component) registerOutputHandler(component, "add", (payload) =&gt; <span>&#123;</span>
console.log("add", payload)
<span>&#125;</span>)</code></pre></section></div></div></section>
<section id="api" class="detail-section"><div class="detail-section-heading"><span>Component API</span><h2>Props and configuration</h2><p>All content and behavior shown above is supplied through these props and slots.</p></div><div class="docs-table-wrap"><table class="docs-table"><thead><tr><th>Prop</th><th>Type</th><th>Default</th><th>Required</th></tr></thead><tbody><tr><td><code>nodes</code></td><td>string</td><td><code>[] palette=[] activeNode="" label="Workflow" arrangeLabel="Arrange nodes" connectLabel="Connect" color="primary" size="default"</code></td><td>No</td></tr><tr><td><code>toolbar</code></td><td>boolean</td><td><code>true</code></td><td>No</td></tr><tr><td><code>class</code></td><td>string</td><td><code>""</code></td><td>No</td></tr></tbody></table></div></section>
</main>
<aside class="detail-aside">
<div class="detail-toc"><strong>On this page</strong><a href="#playground">Playground</a><a href="#drawflow-canvas-demo-1">Production default</a><a href="#drawflow-canvas-demo-2">Compact application</a><a href="#drawflow-canvas-demo-3">Rich configuration</a><a href="#events">Outputs</a><a href="#api">Props API</a></div>
</aside>
</div>
<nav class="detail-pagination">
<span></span>
<a href="/components/flow-canvas"><small>Next</small><strong>Flow Canvas →</strong></a>
</nav>
}
}
File diff suppressed because it is too large. Load diff
+1 -1
View File
@@ -154,7 +154,7 @@ if (component) registerOutputHandler(component, "language", (payload) =&gt; <spa
</aside>
</div>
<nav class="detail-pagination">
<span></span>
<a href="/components/flow-canvas"><small>Previous</small><strong>← Flow Canvas</strong></a>
<a href="/components/toaster"><small>Next</small><strong>Toaster →</strong></a>
</nav>
}
+6 -6
View File
@@ -12,7 +12,7 @@ page SwitchDetail {
state playground_icon = ctx.url.searchParams.get("pg_icon") ?? ""
state playground_iconPosition = ctx.url.searchParams.get("pg_iconPosition") ?? "start"
state playground_value = ctx.url.searchParams.get("pg_value") ?? "sample-1"
state playground_checked = (ctx.url.searchParams.get("pg_checked") ?? "false") === "true"
state playground_checked = ctx.url.searchParams.get("pg_checked") ?? ""
state playground_helperText = ctx.url.searchParams.get("pg_helperText") ?? ""
state playground_cornerHint = ctx.url.searchParams.get("pg_cornerHint") ?? ""
state playground_error = ctx.url.searchParams.get("pg_error") ?? ""
@@ -56,7 +56,7 @@ page SwitchDetail {
</div>
<form class="playground-controls" data-playground-form>
<header><div><span>Component props</span><strong>20 controls</strong></div><button type="reset"><span class="icon-[lucide--rotate-ccw] size-4" aria-hidden="true"></span>Reset</button></header>
<div class="playground-fields"><label class="playground-field" for="playground-switch-size"><span><strong>size</strong><small>string</small></span><select id="playground-switch-size" name="pg_size"><option value="default" selected>default</option><option value="xs">xs</option><option value="sm">sm</option><option value="md">md</option><option value="lg">lg</option><option value="xl">xl</option><option value="icon">icon</option><option value="icon-xs">icon-xs</option><option value="icon-sm">icon-sm</option><option value="icon-lg">icon-lg</option></select></label><label class="playground-field" for="playground-switch-color"><span><strong>color</strong><small>string</small></span><select id="playground-switch-color" name="pg_color"><option value="primary" selected>primary</option><option value="secondary">secondary</option><option value="success">success</option><option value="warning">warning</option><option value="danger">danger</option><option value="info">info</option></select></label><label class="playground-field" for="playground-switch-id"><span><strong>id</strong><small>string</small></span><input id="playground-switch-id" name="pg_id" type="text" value="" /></label><label class="playground-field" for="playground-switch-name"><span><strong>name</strong><small>string</small></span><input id="playground-switch-name" name="pg_name" type="text" value="" /></label><label class="playground-field" for="playground-switch-label"><span><strong>label</strong><small>string</small></span><input id="playground-switch-label" name="pg_label" type="text" value="Switch" /></label><label class="playground-toggle" for="playground-switch-hiddenLabel"><span><strong>hidden Label</strong><small>boolean</small></span><input id="playground-switch-hiddenLabel" name="pg_hiddenLabel" type="checkbox" value="true" data-playground-boolean /><i aria-hidden="true"></i></label><label class="playground-field" for="playground-switch-placeholder"><span><strong>placeholder</strong><small>string</small></span><input id="playground-switch-placeholder" name="pg_placeholder" type="text" value="Enter a sample value" /></label><label class="playground-field" for="playground-switch-variant"><span><strong>variant</strong><small>string</small></span><input id="playground-switch-variant" name="pg_variant" type="text" value="normal" /></label><label class="playground-field" for="playground-switch-icon"><span><strong>icon</strong><small>string</small></span><input id="playground-switch-icon" name="pg_icon" type="text" value="" /></label><label class="playground-field" for="playground-switch-iconPosition"><span><strong>icon Position</strong><small>string</small></span><select id="playground-switch-iconPosition" name="pg_iconPosition"><option value="start" selected>start</option><option value="end">end</option><option value="left">left</option><option value="right">right</option></select></label><label class="playground-field" for="playground-switch-value"><span><strong>value</strong><small>string</small></span><input id="playground-switch-value" name="pg_value" type="text" value="sample-1" /></label><label class="playground-toggle" for="playground-switch-checked"><span><strong>checked</strong><small>boolean</small></span><input id="playground-switch-checked" name="pg_checked" type="checkbox" value="true" data-playground-boolean /><i aria-hidden="true"></i></label><label class="playground-field" for="playground-switch-helperText"><span><strong>helper Text</strong><small>string</small></span><input id="playground-switch-helperText" name="pg_helperText" type="text" value="" /></label><label class="playground-field" for="playground-switch-cornerHint"><span><strong>corner Hint</strong><small>string</small></span><input id="playground-switch-cornerHint" name="pg_cornerHint" type="text" value="" /></label><label class="playground-field" for="playground-switch-error"><span><strong>error</strong><small>string</small></span><input id="playground-switch-error" name="pg_error" type="text" value="" /></label><label class="playground-toggle" for="playground-switch-inline"><span><strong>inline</strong><small>boolean</small></span><input id="playground-switch-inline" name="pg_inline" type="checkbox" value="true" data-playground-boolean /><i aria-hidden="true"></i></label><label class="playground-toggle" for="playground-switch-readonly"><span><strong>readonly</strong><small>boolean</small></span><input id="playground-switch-readonly" name="pg_readonly" type="checkbox" value="true" data-playground-boolean /><i aria-hidden="true"></i></label><label class="playground-toggle" for="playground-switch-disabled"><span><strong>disabled</strong><small>boolean</small></span><input id="playground-switch-disabled" name="pg_disabled" type="checkbox" value="true" data-playground-boolean /><i aria-hidden="true"></i></label><label class="playground-toggle" for="playground-switch-required"><span><strong>required</strong><small>boolean</small></span><input id="playground-switchLine truncated
<div class="playground-fields"><label class="playground-field" for="playground-switch-size"><span><strong>size</strong><small>string</small></span><select id="playground-switch-size" name="pg_size"><option value="default" selected>default</option><option value="xs">xs</option><option value="sm">sm</option><option value="md">md</option><option value="lg">lg</option><option value="xl">xl</option><option value="icon">icon</option><option value="icon-xs">icon-xs</option><option value="icon-sm">icon-sm</option><option value="icon-lg">icon-lg</option></select></label><label class="playground-field" for="playground-switch-color"><span><strong>color</strong><small>string</small></span><select id="playground-switch-color" name="pg_color"><option value="primary" selected>primary</option><option value="secondary">secondary</option><option value="success">success</option><option value="warning">warning</option><option value="danger">danger</option><option value="info">info</option></select></label><label class="playground-field" for="playground-switch-id"><span><strong>id</strong><small>string</small></span><input id="playground-switch-id" name="pg_id" type="text" value="" /></label><label class="playground-field" for="playground-switch-name"><span><strong>name</strong><small>string</small></span><input id="playground-switch-name" name="pg_name" type="text" value="" /></label><label class="playground-field" for="playground-switch-label"><span><strong>label</strong><small>string</small></span><input id="playground-switch-label" name="pg_label" type="text" value="Switch" /></label><label class="playground-toggle" for="playground-switch-hiddenLabel"><span><strong>hidden Label</strong><small>boolean</small></span><input id="playground-switch-hiddenLabel" name="pg_hiddenLabel" type="checkbox" value="true" data-playground-boolean /><i aria-hidden="true"></i></label><label class="playground-field" for="playground-switch-placeholder"><span><strong>placeholder</strong><small>string</small></span><input id="playground-switch-placeholder" name="pg_placeholder" type="text" value="Enter a sample value" /></label><label class="playground-field" for="playground-switch-variant"><span><strong>variant</strong><small>string</small></span><input id="playground-switch-variant" name="pg_variant" type="text" value="normal" /></label><label class="playground-field" for="playground-switch-icon"><span><strong>icon</strong><small>string</small></span><input id="playground-switch-icon" name="pg_icon" type="text" value="" /></label><label class="playground-field" for="playground-switch-iconPosition"><span><strong>icon Position</strong><small>string</small></span><select id="playground-switch-iconPosition" name="pg_iconPosition"><option value="start" selected>start</option><option value="end">end</option><option value="left">left</option><option value="right">right</option></select></label><label class="playground-field" for="playground-switch-value"><span><strong>value</strong><small>string</small></span><input id="playground-switch-value" name="pg_value" type="text" value="sample-1" /></label><label class="playground-field" for="playground-switch-checked"><span><strong>checked</strong><small>boolean | null</small></span><input id="playground-switch-checked" name="pg_checked" type="text" value="" /></label><label class="playground-field" for="playground-switch-helperText"><span><strong>helper Text</strong><small>string</small></span><input id="playground-switch-helperText" name="pg_helperText" type="text" value="" /></label><label class="playground-field" for="playground-switch-cornerHint"><span><strong>corner Hint</strong><small>string</small></span><input id="playground-switch-cornerHint" name="pg_cornerHint" type="text" value="" /></label><label class="playground-field" for="playground-switch-error"><span><strong>error</strong><small>string</small></span><input id="playground-switch-error" name="pg_error" type="text" value="" /></label><label class="playground-toggle" for="playground-switch-inline"><span><strong>inline</strong><small>boolean</small></span><input id="playground-switch-inline" name="pg_inline" type="checkbox" value="true" data-playground-boolean /><i aria-hidden="true"></i></label><label class="playground-toggle" for="playground-switch-readonly"><span><strong>readonly</strong><small>boolean</small></span><input id="playground-switch-readonly" name="pg_readonly" type="checkbox" value="true" data-playground-boolean /><i aria-hidden="true"></i></label><label class="playground-toggle" for="playground-switch-disabled"><span><strong>disabled</strong><small>boolean</small></span><input id="playground-switch-disabled" name="pg_disabled" type="checkbox" value="true" data-playground-boolean /><i aria-hidden="true"></i></label><label class="playground-toggle" for="playground-switch-required"><span><strong>required</strong><small>boolean</small></span><input id="playground-switch-required" name="pg_required" type="checkbox" value=Line truncated
</form>
</div>
</section>
@@ -72,7 +72,7 @@ page SwitchDetail {
<div id="switch-demo-1" class="demo-canvas demo-canvas--1">
<div class="demo-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
<div class="demo-render"><Switch size="default" label="Switch" hiddenLabel="false" placeholder="Enter a sample value" variant="normal" icon="" value="sample-1" checked="false" inline="false" readonly="false" disabled="false" required="false" class="showcase-instance showcase-instance--1" /></div>
<div class="demo-render"><Switch size="default" label="Switch" hiddenLabel="false" placeholder="Enter a sample value" variant="normal" icon="" value="sample-1" inline="false" readonly="false" disabled="false" required="false" class="showcase-instance showcase-instance--1" /></div>
</div>
<section class="demo-code" aria-label="Production default usage">
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
@@ -92,7 +92,7 @@ page SwitchDetail {
<div id="switch-demo-2" class="demo-canvas demo-canvas--2">
<div class="demo-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
<div class="demo-render"><Switch size="sm" label="Compact example" hiddenLabel="false" placeholder="Enter a sample value" variant="secondary" icon="icon-[lucide--arrow-right]" value="sample-2" checked="false" inline="false" readonly="false" disabled="false" required="false" class="showcase-instance showcase-instance--2" /></div>
<div class="demo-render"><Switch size="sm" label="Compact example" hiddenLabel="false" placeholder="Enter a sample value" variant="secondary" icon="icon-[lucide--arrow-right]" value="sample-2" inline="false" readonly="false" disabled="false" required="false" class="showcase-instance showcase-instance--2" /></div>
</div>
<section class="demo-code" aria-label="Compact application usage">
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
@@ -116,7 +116,7 @@ page SwitchDetail {
<div id="switch-demo-3" class="demo-canvas demo-canvas--3">
<div class="demo-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
<div class="demo-render"><Switch size="lg" label="Advanced example" hiddenLabel="false" placeholder="Search by name, email, or identifier" variant="success" icon="icon-[lucide--trash-2]" value="sample-3" checked="false" inline="false" readonly="false" disabled="false" required="false" class="showcase-instance showcase-instance--3" /></div>
<div class="demo-render"><Switch size="lg" label="Advanced example" hiddenLabel="false" placeholder="Search by name, email, or identifier" variant="success" icon="icon-[lucide--trash-2]" value="sample-3" inline="false" readonly="false" disabled="false" required="false" class="showcase-instance showcase-instance--3" /></div>
</div>
<section class="demo-code" aria-label="Rich configuration usage">
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
@@ -155,7 +155,7 @@ if (component) registerOutputHandler(component, "focus", (payload) =&gt; <span>&
if (component) registerOutputHandler(component, "blur", (payload) =&gt; <span>&#123;</span>
console.log("blur", payload)
<span>&#125;</span>)</code></pre></section></div></div></section>
<section id="api" class="detail-section"><div class="detail-section-heading"><span>Component API</span><h2>Props and configuration</h2><p>All content and behavior shown above is supplied through these props and slots.</p></div><div class="docs-table-wrap"><table class="docs-table"><thead><tr><th>Prop</th><th>Type</th><th>Default</th><th>Required</th></tr></thead><tbody><tr><td><code>size</code></td><td>string</td><td><code>"default"</code></td><td>No</td></tr><tr><td><code>color</code></td><td>string</td><td><code>"primary"</code></td><td>No</td></tr><tr><td><code>id</code></td><td>string</td><td><code>""</code></td><td>No</td></tr><tr><td><code>name</code></td><td>string</td><td><code>""</code></td><td>No</td></tr><tr><td><code>label</code></td><td>string</td><td><code>"Switch"</code></td><td>No</td></tr><tr><td><code>hiddenLabel</code></td><td>boolean</td><td><code>false</code></td><td>No</td></tr><tr><td><code>placeholder</code></td><td>string</td><td><code>""</code></td><td>No</td></tr><tr><td><code>variant</code></td><td>string</td><td><code>"normal"</code></td><td>No</td></tr><tr><td><code>icon</code></td><td>string</td><td><code>""</code></td><td>No</td></tr><tr><td><code>iconPosition</code></td><td>string</td><td><code>"start"</code></td><td>No</td></tr><tr><td><code>value</code></td><td>string</td><td><code>"on"</code></td><td>No</td></tr><tr><td><code>checked</code></td><td>boolean</td><td><code>false</code></td><td>No</td></tr><tr><td><code>helperText</code></td><td>string</td><td><code>""</code></td><td>No</td></tr><tr><td><code>cornerHint</code></td><td>string</td><td><code>""</code></td><td>No</td></tr><tr><td><code>error</code></td><td>string</td><td><code>""</code></td><td>No</td></tr><tr><td><code>inline</code></td><td>boolean</td><td><code>false</code></td><td>No</td></tr><tr><td><code>readonly</code></td><td>boolean</td><td><code>false</code></td><td>No</td></tr><tr><td><code>disabled</code></td><td>boolean</td><td><code>false</code></td><td>No</td></tr><tr><td><code>required</code></td><td>boolean</td><td><code>false</code></td><td>No</td></tr><tr><td><code>class</code></td><td>string</td><td><code>""</code></td><td>No</td></tr></tbody></table></div></section>
<section id="api" class="detail-section"><div class="detail-section-heading"><span>Component API</span><h2>Props and configuration</h2><p>All content and behavior shown above is supplied through these props and slots.</p></div><div class="docs-table-wrap"><table class="docs-table"><thead><tr><th>Prop</th><th>Type</th><th>Default</th><th>Required</th></tr></thead><tbody><tr><td><code>size</code></td><td>string</td><td><code>"default"</code></td><td>No</td></tr><tr><td><code>color</code></td><td>string</td><td><code>"primary"</code></td><td>No</td></tr><tr><td><code>id</code></td><td>string</td><td><code>""</code></td><td>No</td></tr><tr><td><code>name</code></td><td>string</td><td><code>""</code></td><td>No</td></tr><tr><td><code>label</code></td><td>string</td><td><code>"Switch"</code></td><td>No</td></tr><tr><td><code>hiddenLabel</code></td><td>boolean</td><td><code>false</code></td><td>No</td></tr><tr><td><code>placeholder</code></td><td>string</td><td><code>""</code></td><td>No</td></tr><tr><td><code>variant</code></td><td>string</td><td><code>"normal"</code></td><td>No</td></tr><tr><td><code>icon</code></td><td>string</td><td><code>""</code></td><td>No</td></tr><tr><td><code>iconPosition</code></td><td>string</td><td><code>"start"</code></td><td>No</td></tr><tr><td><code>value</code></td><td>string</td><td><code>"on"</code></td><td>No</td></tr><tr><td><code>checked</code></td><td>boolean | null</td><td><code>null</code></td><td>No</td></tr><tr><td><code>helperText</code></td><td>string</td><td><code>""</code></td><td>No</td></tr><tr><td><code>cornerHint</code></td><td>string</td><td><code>""</code></td><td>No</td></tr><tr><td><code>error</code></td><td>string</td><td><code>""</code></td><td>No</td></tr><tr><td><code>inline</code></td><td>boolean</td><td><code>false</code></td><td>No</td></tr><tr><td><code>readonly</code></td><td>boolean</td><td><code>false</code></td><td>No</td></tr><tr><td><code>disabled</code></td><td>boolean</td><td><code>false</code></td><td>No</td></tr><tr><td><code>required</code></td><td>boolean</td><td><code>false</code></td><td>No</td></tr><tr><td><code>class</code></td><td>string</td><td><code>""</code></td><td>No</td></tr></tbody></table></div></section>
</main>
<aside class="detail-aside">
<div class="detail-toc"><strong>On this page</strong><a href="#playground">Playground</a><a href="#switch-demo-1">Production default</a><a href="#switch-demo-2">Compact application</a><a href="#switch-demo-3">Rich configuration</a><a href="#events">Outputs</a><a href="#api">Props API</a></div>
+23 -3
View File
@@ -3,16 +3,36 @@ page CoreShowcase {
layout = "showcase"
seo {
title = "Core components"
description = "2 core components from @wrnexus/ui."
description = "4 core components from @wrnexus/ui."
}
view {
<header class="showcase-hero showcase-hero--category">
<span class="showcase-eyebrow">Component category</span>
<h1 class="showcase-title">Core</h1>
<p class="showcase-description">2 unique, responsive, theme-aware components. Open a component to inspect multiple live configurations and its complete props API.</p>
<div class="category-meta"><span>2 components</span><span>Multiple use cases</span><span>4 live configurations</span></div>
<p class="showcase-description">4 unique, responsive, theme-aware components. Open a component to inspect multiple live configurations and its complete props API.</p>
<div class="category-meta"><span>4 components</span><span>Multiple use cases</span><span>10 live configurations</span></div>
</header>
<div class="catalog-grid">
<article class="catalog-card" data-interactive-preview="false">
<div class="catalog-card-preview">
<div class="catalog-card-glow" aria-hidden="true"></div>
<div class="catalog-card-stage"><DrawflowCanvas toolbar="true" class="showcase-instance showcase-instance--1" /></div>
</div>
<div class="catalog-card-body">
<div><span class="catalog-card-category">Core</span><h2>Drawflow Canvas</h2><p>Reusable drawflow canvas component.</p></div>
<div class="catalog-card-footer"><span>3 props · 0 slots</span><a href="/components/drawflow-canvas">Explore component <span aria-hidden="true">→</span></a></div>
</div>
</article>
<article class="catalog-card" data-interactive-preview="false">
<div class="catalog-card-preview">
<div class="catalog-card-glow" aria-hidden="true"></div>
<div class="catalog-card-stage"><FlowCanvas nodes='[{"id":"flow-canvas-0-1","key":"flow-canvas-0-1","value":"primary","label":"Primary workflow","title":"Primary workflow","description":"A clean default configuration for everyday product interfaces.","text":"A configurable sample message.","href":"#flow-canvas-demo","actionHref":"#flow-canvas-demo","actionLabel":"View details","icon":"icon-[lucide--sparkles]","iconClass":"icon-[lucide--sparkles]","variant":"primary","status":"Active","time":"09:30","current":true,"selected":true,"checked":true,"disabled":false,"outgoing":false,"open":true,"number":1,"count":16,"percentage":72,"color":"#7c3aed","target":"_self","ariaLabel":"Open primary workflow 1","items":[{"label":"Nested option A","value":"nested-a"},{"label":"Nested option B","value":"nested-b"}],"links":[{"label":"Documentation","href":"#documentation"},{"label":"API reference","href":"#api-reference"}],"values":["Included","Standard"]},{"id":"flow-canvas-0-2","key":"flow-canvas-0-2","value":"secondary","label":"Additional option","title":"Supporting example","description":"A clean default configuration for everyday product interfaces.","text":"Another configurable message.","href":"#flow-canvas-demo","actionHref":"#flow-canvas-demo","actionLabel":"View details","icon":"icon-[lucide--sparkles]","iconClass":"icon-[lucide--sparkles]","variant":"primary","status":"Active","time":"09:30","current":false,"selected":false,"checked":false,"disabled":false,"outgoing":true,"open":true,"number":2,"count":32,"percentage":72,"color":"#7c3aed","target":"_self","ariaLabel":"Open primary workflow 2","items":[{"label":"Nested option A","value":"nested-a"},{"label":"Nested option B","value":"nested-b"}],"links":[{"label":"Documentation","href":"#documentation"},{"label":"API reference","href":"#api-reference"}],"values":["Included","Standard"]}]' palette='[{"id":"flow-canvas-0-1","key":"flow-canvas-0-1","value":"primary","label":"Primary workflow","title":"Primary workflow","description":"A clean default configuration for everyday product interfaces.","text":"A configurable sample message.","href":"#flow-canvas-demo","actionHref":"#flow-canvas-demo","actionLabel":"View details","icon":"icon-[lucide--sparkles]","iconClass":"icon-[lucide--sparkles]","variant":"primary","status":"Active","time":"09:30","current":true,"selected":true,"checked":true,"disabled":false,"outgoing":false,"open":true,"number":1,"count":16,"percentage":72,"color":"#7c3aed","target":"_self","ariaLabel":"Open primary workflow 1","items":[{"label":"Nested option A","value":"nested-a"},{"label":"Nested option B","value":"nested-b"}],"links":[{"label":"Documentation","href":"#documentation"},{"label":"API reference","href":"#api-reference"}],"values":["Included","Standard"]},{"id":"flow-canvas-0-2","key":"flow-canvas-0-2","value":"secondary","label":"Additional option","title":"Supporting example","description":"A clean default configuration for everyday product interfaces.","text":"Another configurable message.","href":"#flow-canvas-demo","actionHref":"#flow-canvas-demo","actionLabel":"View details","icon":"icon-[lucide--sparkles]","iconClass":"icon-[lucide--sparkles]","variant":"primary","status":"Active","time":"09:30","current":false,"selected":false,"checked":false,"disabled":false,"outgoing":true,"open":true,"number":2,"count":32,"percentage":72,"color":"#7c3aed","target":"_self","ariaLabel":"Open primary workflow 2","items":[{"label":"Nested option A","value":"nested-a"},{"label":"Nested option B","value":"nested-b"}],"links":[{"label":"Documentation","href":"#documentation"},{"label":"API reference","href":"#api-reference"}],"values":["Included","Standard"]}]' label="Flow Canvas" arrangeLabel="Flow Canvas" connectLabel="Flow Canvas" size="default" class="showcase-instance showcase-instance--1" /></div>
</div>
<div class="catalog-card-body">
<div><span class="catalog-card-category">Core</span><h2>Flow Canvas</h2><p>Reusable flow canvas component.</p></div>
<div class="catalog-card-footer"><span>9 props · 0 slots</span><a href="/components/flow-canvas">Explore component <span aria-hidden="true">→</span></a></div>
</div>
</article>
<article class="catalog-card" data-interactive-preview="false">
<div class="catalog-card-preview">
<div class="catalog-card-glow" aria-hidden="true"></div>
+1 -1
View File
@@ -106,7 +106,7 @@ page FormsShowcase {
<article class="catalog-card" data-interactive-preview="false">
<div class="catalog-card-preview">
<div class="catalog-card-glow" aria-hidden="true"></div>
<div class="catalog-card-stage"><Switch size="default" label="Switch" hiddenLabel="false" placeholder="Enter a sample value" variant="normal" icon="" value="sample-1" checked="false" inline="false" readonly="false" disabled="false" required="false" class="showcase-instance showcase-instance--1" /></div>
<div class="catalog-card-stage"><Switch size="default" label="Switch" hiddenLabel="false" placeholder="Enter a sample value" variant="normal" icon="" value="sample-1" inline="false" readonly="false" disabled="false" required="false" class="showcase-instance showcase-instance--1" /></div>
</div>
<div class="catalog-card-body">
<div><span class="catalog-card-category">Forms</span><h2>Switch</h2><p>Theme-aware, responsive switch component.</p></div>
+5 -5
View File
@@ -10,18 +10,18 @@ page ComponentShowcase {
<header class="showcase-hero showcase-hero--home">
<span class="showcase-eyebrow">The UI foundation for WRNexus</span>
<h1 class="showcase-title">Build modern products<br /><em>at framework speed.</em></h1>
<p class="showcase-description">A complete, accessible component system with 84 primitives, ready-made blocks, page templates, responsive behavior, and deeply configurable design tokens.</p>
<p class="showcase-description">A complete, accessible component system with 86 primitives, ready-made blocks, page templates, responsive behavior, and deeply configurable design tokens.</p>
<div class="home-actions"><a class="home-primary-action" href="/docs">Get started <span aria-hidden="true">→</span></a><a class="home-secondary-action" href="/block-library">Explore blocks</a></div>
<div class="home-install"><span>$</span><code>bun add @wrnexus/ui</code><button type="button" data-copy-text="bun add @wrnexus/ui" aria-label="Copy install command"><span class="icon-[lucide--copy] size-4" aria-hidden="true"></span></button></div>
</header>
<section class="home-product-grid"><article><span class="icon-[lucide--component] size-7"></span><strong>84 components</strong><p>Accessible primitives for every product surface.</p><a href="/base">Browse components →</a></article><article><span class="icon-[lucide--layout-template] size-7"></span><strong>Ready-made blocks</strong><p>Composable sections assembled from WRNexus UI.</p><a href="/block-library">Explore blocks →</a></article><article><span class="icon-[lucide--panels-top-left] size-7"></span><strong>Page templates</strong><p>Complete responsive pages ready to customize.</p><a href="/templates">View templates →</a></article></section>
<section class="home-product-grid"><article><span class="icon-[lucide--component] size-7"></span><strong>86 components</strong><p>Accessible primitives for every product surface.</p><a href="/base">Browse components →</a></article><article><span class="icon-[lucide--layout-template] size-7"></span><strong>Ready-made blocks</strong><p>Composable sections assembled from WRNexus UI.</p><a href="/block-library">Explore blocks →</a></article><article><span class="icon-[lucide--panels-top-left] size-7"></span><strong>Page templates</strong><p>Complete responsive pages ready to customize.</p><a href="/templates">View templates →</a></article></section>
<section class="showcase-stats">
<div class="showcase-stat"><strong>84</strong><span>Unique components</span></div>
<div class="showcase-stat"><strong>346</strong><span>Live configurations</span></div>
<div class="showcase-stat"><strong>86</strong><span>Unique components</span></div>
<div class="showcase-stat"><strong>361</strong><span>Live configurations</span></div>
<div class="showcase-stat"><strong>0</strong><span>Duplicate implementations</span></div>
<div class="showcase-stat"><strong>11</strong><span>Focused categories</span></div>
</section>
<section class="home-categories"><div class="home-section-heading"><span>Explore the system</span><h2>Everything your product needs</h2></div><div class="home-category-grid"><a class="home-category home-category--1" href="/base"><span class="home-category-index">01</span><div><strong>Base</strong><p>26 components · 85 live demos</p></div><span class="icon-[lucide--arrow-up-right] size-5" aria-hidden="true"></span></a><a class="home-category home-category--2" href="/core"><span class="home-category-index">02</span><div><strong>Core</strong><p>2 components · 4 live demos</p></div><span class="icon-[lucide--arrow-up-right] size-5" aria-hidden="true"></span></a><a class="home-category home-category--3" href="/data"><span class="home-category-index">03</span><div><strong>Data</strong><p>1 components · 3 live demos</p></div><span class="icon-[lucide--arrow-up-right] size-5" aria-hidden="true"></span></a><a class="home-category home-category--4" href="/forms"><span class="home-category-index">04</span><div><strong>Forms</strong><p>12 components · 32 live demos</p></div><span class="icon-[lucide--arrow-up-right] size-5" aria-hidden="true"></span></a><a class="home-category home-category--1" href="/integrations"><span class="home-category-index">05</span><div><strong>Integrations</strong><p>7 components · 19 live demos</p></div><span class="icon-[lucide--arrow-up-right] size-5" aria-hidden="true"></span></a><a class="home-category home-category--2" href="/layout"><span class="home-category-index">06</span><div><strong>Layout</strong><p>11 components · 31 live demos</p></div><span class="icon-[lucide--arrow-up-right] size-5" aria-hidden="true"></span></a><a class="home-category home-category--3" href="/marketing"><span class="home-category-index">07</span><div><strong>Marketing</strong><p>1 components · 3 live demos</p></div><span class="icon-[lucide--arrow-up-right] size-5" aria-hidden="true"></span></a><a class="home-category home-category--4" href="/navigation"><span class="home-category-index">08</span><div><strong>Navigation</strong><p>10 components · 30 live demos</p></div><span class="icon-[lucide--arrow-up-right] size-5" aria-hidden="true"></span></a><a class="home-category home-category--1" href="/overlays"><span class="home-category-index">09</span><div><strong>Overlays</strong><p>6 components · 21 live demos</p></div><span class="icon-[lucide--arrow-up-right] size-5" aria-hidden="true"></span></a><a class="home-category home-category--2" href="/tables"><span class="home-category-index">010</span><div><strong>Tables</strong><p>1 components · 9 live demos</p></div><span class="icon-[lucide--arrow-up-right] size-5" aria-hidden="true"></span></a><a class="home-category home-category--3" href="/advanced-forms"><span class="home-category-index">011</span><div><strong>Advanced Forms</strong><p>7 components · 109 live demos</p></div><span class="icon-[lucide--arrow-up-right] size-5" aria-hidden="true"></span></a></div></section>
<section class="home-categories"><div class="home-section-heading"><span>Explore the system</span><h2>Everything your product needs</h2></div><div class="home-category-grid"><a class="home-category home-category--1" href="/base"><span class="home-category-index">01</span><div><strong>Base</strong><p>26 components · 85 live demos</p></div><span class="icon-[lucide--arrow-up-right] size-5" aria-hidden="true"></span></a><a class="home-category home-category--2" href="/core"><span class="home-category-index">02</span><div><strong>Core</strong><p>4 components · 10 live demos</p></div><span class="icon-[lucide--arrow-up-right] size-5" aria-hidden="true"></span></a><a class="home-category home-category--3" href="/data"><span class="home-category-index">03</span><div><strong>Data</strong><p>1 components · 3 live demos</p></div><span class="icon-[lucide--arrow-up-right] size-5" aria-hidden="true"></span></a><a class="home-category home-category--4" href="/forms"><span class="home-category-index">04</span><div><strong>Forms</strong><p>12 components · 32 live demos</p></div><span class="icon-[lucide--arrow-up-right] size-5" aria-hidden="true"></span></a><a class="home-category home-category--1" href="/integrations"><span class="home-category-index">05</span><div><strong>Integrations</strong><p>7 components · 28 live demos</p></div><span class="icon-[lucide--arrow-up-right] size-5" aria-hidden="true"></span></a><a class="home-category home-category--2" href="/layout"><span class="home-category-index">06</span><div><strong>Layout</strong><p>11 components · 31 live demos</p></div><span class="icon-[lucide--arrow-up-right] size-5" aria-hidden="true"></span></a><a class="home-category home-category--3" href="/marketing"><span class="home-category-index">07</span><div><strong>Marketing</strong><p>1 components · 3 live demos</p></div><span class="icon-[lucide--arrow-up-right] size-5" aria-hidden="true"></span></a><a class="home-category home-category--4" href="/navigation"><span class="home-category-index">08</span><div><strong>Navigation</strong><p>10 components · 30 live demos</p></div><span class="icon-[lucide--arrow-up-right] size-5" aria-hidden="true"></span></a><a class="home-category home-category--1" href="/overlays"><span class="home-category-index">09</span><div><strong>Overlays</strong><p>6 components · 21 live demos</p></div><span class="icon-[lucide--arrow-up-right] size-5" aria-hidden="true"></span></a><a class="home-category home-category--2" href="/tables"><span class="home-category-index">010</span><div><strong>Tables</strong><p>1 components · 9 live demos</p></div><span class="icon-[lucide--arrow-up-right] size-5" aria-hidden="true"></span></a><a class="home-category home-category--3" href="/advanced-forms"><span class="home-category-index">011</span><div><strong>Advanced Forms</strong><p>7 components · 109 live demos</p></div><span class="icon-[lucide--arrow-up-right] size-5" aria-hidden="true"></span></a></div></section>
</div>
}
}
+3 -3
View File
@@ -10,17 +10,17 @@ page IntegrationsShowcase {
<span class="showcase-eyebrow">Component category</span>
<h1 class="showcase-title">Integrations</h1>
<p class="showcase-description">7 unique, responsive, theme-aware components. Open a component to inspect multiple live configurations and its complete props API.</p>
<div class="category-meta"><span>7 components</span><span>Multiple use cases</span><span>19 live configurations</span></div>
<div class="category-meta"><span>7 components</span><span>Multiple use cases</span><span>28 live configurations</span></div>
</header>
<div class="catalog-grid">
<article class="catalog-card" data-interactive-preview="false">
<div class="catalog-card-preview">
<div class="catalog-card-glow" aria-hidden="true"></div>
<div class="catalog-card-stage"><Chart title="Weekly signups" description="Completed tasks this week" items='[]' data='[{"label":"Mon","value":24},{"label":"Tue","value":38},{"label":"Wed","value":29},{"label":"Thu","value":52},{"label":"Fri","value":45}]' type="bar" valueKey="value" labelKey="label" height="220" showLegend="false" showValues="true" size="default" color="primary" variant="bar" class="" /></div>
<div class="catalog-card-stage"><Chart title="Sample weekly changes" description="Sample data" items='[]' data='[{"label":"Mon","value":24},{"label":"Tue","value":-12},{"label":"Wed","value":29},{"label":"Thu","value":52},{"label":"Fri","value":45}]' labels='[]' datasets='[]' type="bar" valueKey="value" labelKey="label" height="220" showLegend="true" showValues="false" size="default" color="primary" variant="bar" class="" /></div>
</div>
<div class="catalog-card-body">
<div><span class="catalog-card-category">Integrations</span><h2>Chart</h2><p>Theme-aware, responsive chart component.</p></div>
<div class="catalog-card-footer"><span>14 props · 1 slots</span><a href="/components/chart">Explore component <span aria-hidden="true">→</span></a></div>
<div class="catalog-card-footer"><span>17 props · 1 slots</span><a href="/components/chart">Explore component <span aria-hidden="true">→</span></a></div>
</div>
</article>
<article class="catalog-card" data-interactive-preview="false">
+6
View File
@@ -55,9 +55,11 @@ export interface Routes {
"/components/divider": Record<string, never>;
"/components/drag-and-drop": Record<string, never>;
"/components/drawer": Record<string, never>;
"/components/drawflow-canvas": Record<string, never>;
"/components/dropdown": Record<string, never>;
"/components/file-input": Record<string, never>;
"/components/file-upload-progress": Record<string, never>;
"/components/flow-canvas": Record<string, never>;
"/components/grid": Record<string, never>;
"/components/image": Record<string, never>;
"/components/input": Record<string, never>;
@@ -200,9 +202,11 @@ export interface RouteNames {
"components.divider": "/components/divider";
"components.drag.and.drop": "/components/drag-and-drop";
"components.drawer": "/components/drawer";
"components.drawflow.canvas": "/components/drawflow-canvas";
"components.dropdown": "/components/dropdown";
"components.file.input": "/components/file-input";
"components.file.upload.progress": "/components/file-upload-progress";
"components.flow.canvas": "/components/flow-canvas";
"components.grid": "/components/grid";
"components.image": "/components/image";
"components.input": "/components/input";
@@ -414,9 +418,11 @@ export function route<N extends RouteName>(
"components.divider": "/components/divider",
"components.drag.and.drop": "/components/drag-and-drop",
"components.drawer": "/components/drawer",
"components.drawflow.canvas": "/components/drawflow-canvas",
"components.dropdown": "/components/dropdown",
"components.file.input": "/components/file-input",
"components.file.upload.progress": "/components/file-upload-progress",
"components.flow.canvas": "/components/flow-canvas",
"components.grid": "/components/grid",
"components.image": "/components/image",
"components.input": "/components/input",
+161 -30
View File
@@ -2415,7 +2415,7 @@ body {
.detail-hero {
grid-template-columns: minmax(0, 1fr) auto;
gap: .75rem;
gap: 0.75rem;
padding: 1rem 0;
border-radius: var(--wrn-radius-md);
}
@@ -2428,7 +2428,10 @@ body {
box-shadow: none;
}
.detail-hero-icon > span { width: 1.5rem; height: 1.5rem; }
.detail-hero-icon > span {
width: 1.5rem;
height: 1.5rem;
}
.detail-hero h1 {
font-size: clamp(1.5rem, 6vw, 2rem);
@@ -3016,34 +3019,162 @@ body {
min-height: 18rem;
}
[data-docs-empty][hidden] { display:none !important; }
.demo-render:has(.wrn-back-to-top), .playground-preview-source:has(.wrn-back-to-top) { position:relative; transform:translateZ(0); }
.demo-render:has(.wrn-chart,.wrn-map,.wrn-editor,.wrn-table), .playground-preview-source:has(.wrn-chart,.wrn-map,.wrn-editor,.wrn-table) { padding:1rem; }
.demo-case:has(.wrn-chart,.wrn-map,.wrn-editor,.wrn-table) .demo-workbench { grid-template-columns:minmax(0,1fr); }
[data-docs-empty][hidden] {
display: none !important;
}
.demo-render:has(.wrn-back-to-top),
.playground-preview-source:has(.wrn-back-to-top) {
position: relative;
transform: translateZ(0);
}
.demo-render:has(.wrn-chart, .wrn-map, .wrn-editor, .wrn-table),
.playground-preview-source:has(.wrn-chart, .wrn-map, .wrn-editor, .wrn-table) {
padding: 1rem;
}
.demo-case:has(.wrn-chart, .wrn-map, .wrn-editor, .wrn-table) .demo-workbench {
grid-template-columns: minmax(0, 1fr);
}
.example-catalog { display:grid; grid-template-columns:repeat(auto-fit,minmax(min(100%,18rem),1fr)); gap:1.25rem; }
.example-card { display:block; overflow:hidden; border:1px solid var(--wrn-color-border); border-radius:12px; color:var(--wrn-color-text); background:var(--wrn-color-surface); text-decoration:none; }
.example-card__art { display:grid; place-items:center; height:9rem; background:var(--wrn-color-surface-2); border-bottom:1px solid var(--wrn-color-border); }
.example-card__art span { width:2.5rem; height:2.5rem; color:var(--wrn-color-primary-text); }
.example-card > div:last-child { padding:1.25rem; }
.example-card h2 { font-size:1.1rem; margin:0 0 .5rem; }
.example-card p { font-size:.875rem; color:var(--wrn-color-muted); min-height:2.8rem; }
.example-card strong { font-size:.8rem; color:var(--wrn-color-primary-text); }
.example-toolbar { display:flex; justify-content:space-between; padding:1rem 2rem; border-bottom:1px solid var(--wrn-color-border); background:var(--wrn-color-surface); }
.example-code-panel { margin:2rem auto; width:min(100% - 2rem,80rem); border:1px solid var(--wrn-color-border); border-radius:10px; overflow:hidden; background:var(--wrn-color-surface); }
.example-code-panel header { display:flex; justify-content:space-between; align-items:center; padding:1rem; border-bottom:1px solid var(--wrn-color-border); }
.example-code-panel h2 { font-size:1rem; margin:0; }
.example-code-panel button { padding:.45rem .8rem; border:1px solid var(--wrn-color-border); border-radius:6px; background:var(--wrn-color-surface-2); color:var(--wrn-color-text); cursor:pointer; }
.example-code-panel pre { margin:0; padding:1.25rem; max-height:32rem; overflow:auto; font-size:.8rem; white-space:pre; }
.example-code-panel summary { padding:1rem; cursor:pointer; }
.block-live-preview { padding:clamp(1rem,3vw,2rem); border:1px solid var(--wrn-color-border); border-radius:10px; background:var(--wrn-color-bg); overflow:auto; }
.example-form-page { max-width:42rem; margin:3rem auto; padding:1.5rem; display:grid; gap:1.5rem; }
.example-form-page h1 { margin:0; font-size:1.75rem; }
.example-catalog {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));
gap: 1.25rem;
}
.example-card {
display: block;
overflow: hidden;
border: 1px solid var(--wrn-color-border);
border-radius: 12px;
color: var(--wrn-color-text);
background: var(--wrn-color-surface);
text-decoration: none;
}
.example-card__art {
display: grid;
place-items: center;
height: 9rem;
background: var(--wrn-color-surface-2);
border-bottom: 1px solid var(--wrn-color-border);
}
.example-card__art span {
width: 2.5rem;
height: 2.5rem;
color: var(--wrn-color-primary-text);
}
.example-card > div:last-child {
padding: 1.25rem;
}
.example-card h2 {
font-size: 1.1rem;
margin: 0 0 0.5rem;
}
.example-card p {
font-size: 0.875rem;
color: var(--wrn-color-muted);
min-height: 2.8rem;
}
.example-card strong {
font-size: 0.8rem;
color: var(--wrn-color-primary-text);
}
.example-toolbar {
display: flex;
justify-content: space-between;
padding: 1rem 2rem;
border-bottom: 1px solid var(--wrn-color-border);
background: var(--wrn-color-surface);
}
.example-code-panel {
margin: 2rem auto;
width: min(100% - 2rem, 80rem);
border: 1px solid var(--wrn-color-border);
border-radius: 10px;
overflow: hidden;
background: var(--wrn-color-surface);
}
.example-code-panel header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem;
border-bottom: 1px solid var(--wrn-color-border);
}
.example-code-panel h2 {
font-size: 1rem;
margin: 0;
}
.example-code-panel button {
padding: 0.45rem 0.8rem;
border: 1px solid var(--wrn-color-border);
border-radius: 6px;
background: var(--wrn-color-surface-2);
color: var(--wrn-color-text);
cursor: pointer;
}
.example-code-panel pre {
margin: 0;
padding: 1.25rem;
max-height: 32rem;
overflow: auto;
font-size: 0.8rem;
white-space: pre;
}
.example-code-panel summary {
padding: 1rem;
cursor: pointer;
}
.block-live-preview {
padding: clamp(1rem, 3vw, 2rem);
border: 1px solid var(--wrn-color-border);
border-radius: 10px;
background: var(--wrn-color-bg);
overflow: auto;
}
.example-form-page {
max-width: 42rem;
margin: 3rem auto;
padding: 1.5rem;
display: grid;
gap: 1.5rem;
}
.example-form-page h1 {
margin: 0;
font-size: 1.75rem;
}
.gallery-header { display:flex; align-items:center; justify-content:space-between; gap:1rem; padding:1.25rem clamp(1rem,5vw,5rem); border-bottom:1px solid var(--wrn-color-border); }
.gallery-header nav { display:flex; flex-wrap:wrap; gap:1.5rem; font-size:.875rem; }
.gallery-main { max-width:1440px; margin:auto; padding:clamp(1rem,4vw,4rem); }
.template-products { display:grid; grid-template-columns:repeat(auto-fit,minmax(min(100%,240px),1fr)); gap:1.25rem; }
@media(max-width:600px) { .gallery-header { align-items:flex-start; flex-direction:column; } }
.gallery-header {
display: flex;
align-items: center;
justify-content: space-between;
gap: 1rem;
padding: 1.25rem clamp(1rem, 5vw, 5rem);
border-bottom: 1px solid var(--wrn-color-border);
}
.gallery-header nav {
display: flex;
flex-wrap: wrap;
gap: 1.5rem;
font-size: 0.875rem;
}
.gallery-main {
max-width: 1440px;
margin: auto;
padding: clamp(1rem, 4vw, 4rem);
}
.template-products {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr));
gap: 1.25rem;
}
@media (max-width: 600px) {
.gallery-header {
align-items: flex-start;
flex-direction: column;
}
}
.playground-preview-source:has(.wrn-confetti), .demo-render:has(.wrn-confetti) { justify-items:center; overflow:hidden; }
.playground-preview-source:has(.wrn-confetti),
.demo-render:has(.wrn-confetti) {
justify-items: center;
overflow: hidden;
}
+1 -1
View File
@@ -13,7 +13,7 @@ declare namespace WRNexusGenerated {
: never;
type RealtimeMessage<T> = T extends import("@wrnexus/core").RoomDefinition<any, infer M> ? M : unknown;
type QueuePayload<T> = T extends import("@wrnexus/queue").JobDefinition<infer I> ? I : unknown;
type RouteName = "accessibility" | "advanced.forms" | "base" | "block.library" | "blocks" | "blocks.announcement.bar" | "blocks.ctasection" | "blocks.feature.card" | "blocks.feature.grid" | "blocks.feature.icon.card" | "blocks.footer" | "blocks.hero" | "blocks.hero.actions" | "blocks.marketing.section.header" | "blocks.metric.grid" | "blocks.page.header" | "blocks.section.header" | "blocks.split.hero" | "blocks.stats.bar" | "colors" | "components.accordion" | "components.advanced.select" | "components.alert" | "components.avatar" | "components.avatar.group" | "components.back.to.top" | "components.badge" | "components.blockquote" | "components.breadcrumb" | "components.button" | "components.button.group" | "components.card" | "components.carousel" | "components.chart" | "components.chat.bubble" | "components.checkbox" | "components.clipboard" | "components.collapse" | "components.color.picker" | "components.columns" | "components.combo.box" | "components.confetti" | "components.container" | "components.context.menu" | "components.custom.scrollbar" | "components.data.map" | "components.data.table" | "components.date.picker" | "components.device.frame" | "components.divider" | "components.drag.and.drop" | "components.drawer" | "components.dropdown" | "components.file.input" | "components.file.upload.progress" | "components.grid" | "components.image" | "components.input" | "components.input.group" | "components.input.number" | "components.kbd" | "components.layout.splitter" | "components.legend.indicator" | "components.link" | "components.list" | "components.list.group" | "components.map" | "components.marquee" | "components.mega.menu" | "components.metric.card" | "components.modal" | "components.nav" | "components.navbar" | "components.pagination" | "components.pin.input" | "components.popover" | "components.preference.switcher" | "components.progress" | "components.radio" | "components.range.slider" | "components.rating" | "components.scrollspy" | "components.search.box" | "components.section" | "components.select" | "components.sidebar" | "components.skeleton" | "components.spinner" | "components.stepper" | "components.strong.password" | "components.styled.icon" | "components.switch" | "components.tabs" | "components.text.link" | "components.textarea" | "components.time.picker" | "components.timeline" | "components.toaster" | "components.toggle.count" | "components.toggle.password" | "components.tooltip" | "components.tree.view" | "components.typography" | "components.wysiwyg.editor" | "core" | "dark.mode" | "data" | "docs" | "fonts" | "forms" | "framework.guides" | "index" | "installation" | "integrations" | "layout" | "marketing" | "navigation" | "overlays" | "preview" | "preview.custom.modal" | "preview.profile" | "preview.project.board" | "preview.scheduling" | "preview.sign.in" | "preview.workspace" | "resources" | "sizing" | "tables" | "templates" | "templates.commerce" | "templates.dashboards" | "templates.marketing" | "templates.productivity" | "themes" | "v06.functions" | "v06.imports" | "v06.migration" | "v06.outputs" | "v06.runtime" | "v06.state" | "v06.stores" | "v06.types";
type RouteName = "accessibility" | "advanced.forms" | "base" | "block.library" | "blocks" | "blocks.announcement.bar" | "blocks.ctasection" | "blocks.feature.card" | "blocks.feature.grid" | "blocks.feature.icon.card" | "blocks.footer" | "blocks.hero" | "blocks.hero.actions" | "blocks.marketing.section.header" | "blocks.metric.grid" | "blocks.page.header" | "blocks.section.header" | "blocks.split.hero" | "blocks.stats.bar" | "colors" | "components.accordion" | "components.advanced.select" | "components.alert" | "components.avatar" | "components.avatar.group" | "components.back.to.top" | "components.badge" | "components.blockquote" | "components.breadcrumb" | "components.button" | "components.button.group" | "components.card" | "components.carousel" | "components.chart" | "components.chat.bubble" | "components.checkbox" | "components.clipboard" | "components.collapse" | "components.color.picker" | "components.columns" | "components.combo.box" | "components.confetti" | "components.container" | "components.context.menu" | "components.custom.scrollbar" | "components.data.map" | "components.data.table" | "components.date.picker" | "components.device.frame" | "components.divider" | "components.drag.and.drop" | "components.drawer" | "components.drawflow.canvas" | "components.dropdown" | "components.file.input" | "components.file.upload.progress" | "components.flow.canvas" | "components.grid" | "components.image" | "components.input" | "components.input.group" | "components.input.number" | "components.kbd" | "components.layout.splitter" | "components.legend.indicator" | "components.link" | "components.list" | "components.list.group" | "components.map" | "components.marquee" | "components.mega.menu" | "components.metric.card" | "components.modal" | "components.nav" | "components.navbar" | "components.pagination" | "components.pin.input" | "components.popover" | "components.preference.switcher" | "components.progress" | "components.radio" | "components.range.slider" | "components.rating" | "components.scrollspy" | "components.search.box" | "components.section" | "components.select" | "components.sidebar" | "components.skeleton" | "components.spinner" | "components.stepper" | "components.strong.password" | "components.styled.icon" | "components.switch" | "components.tabs" | "components.text.link" | "components.textarea" | "components.time.picker" | "components.timeline" | "components.toaster" | "components.toggle.count" | "components.toggle.password" | "components.tooltip" | "components.tree.view" | "components.typography" | "components.wysiwyg.editor" | "core" | "dark.mode" | "data" | "docs" | "fonts" | "forms" | "framework.guides" | "index" | "installation" | "integrations" | "layout" | "marketing" | "navigation" | "overlays" | "preview" | "preview.custom.modal" | "preview.profile" | "preview.project.board" | "preview.scheduling" | "preview.sign.in" | "preview.workspace" | "resources" | "sizing" | "tables" | "templates" | "templates.commerce" | "templates.dashboards" | "templates.marketing" | "templates.productivity" | "themes" | "v06.functions" | "v06.imports" | "v06.migration" | "v06.outputs" | "v06.runtime" | "v06.state" | "v06.stores" | "v06.types";
type ApiRoute = "/api/teams";
type RealtimeRoute = never;
type EnvironmentKey = never;
+54 -40
View File
@@ -5,21 +5,23 @@
"": {
"name": "component-showcase",
"dependencies": {
"@wrnexus/core": "^0.8.16",
"@wrnexus/dev-server": "^0.8.66",
"@wrnexus/helpers": "^0.8.9",
"@wrnexus/plugin": "^0.8.9",
"@wrnexus/styles": "^0.8.26",
"@wrnexus/syntax": "^0.8.19",
"@wrnexus/ui": "^0.8.88",
"@wrnexus/core": "0.8.25",
"@wrnexus/design-studio": "0.1.0",
"@wrnexus/design-system": "0.1.0",
"@wrnexus/dev-server": "0.8.83",
"@wrnexus/helpers": "0.8.10",
"@wrnexus/plugin": "0.8.10",
"@wrnexus/styles": "0.8.27",
"@wrnexus/syntax": "0.8.20",
"@wrnexus/ui": "0.8.118",
},
"devDependencies": {
"@iconify-json/lucide": "^1.2.123",
"@iconify/tailwind4": "^1.2.3",
"@tailwindcss/cli": "^4.3.3",
"@types/bun": "^1.3.14",
"@wrnexus/cli": "^0.8.72",
"@wrnexus/compiler": "^0.8.30",
"@wrnexus/cli": "0.8.77",
"@wrnexus/compiler": "0.8.44",
"happy-dom": "^20.11.6",
"prettier": "^3.6.2",
"tailwindcss": "^4.3.3",
@@ -52,6 +54,8 @@
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],
"@kurkle/color": ["@kurkle/color@0.3.4", "", {}, "sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w=="],
"@noble/hashes": ["@noble/hashes@1.4.0", "", {}, "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg=="],
"@parcel/watcher": ["@parcel/watcher@2.5.1", "", { "dependencies": { "detect-libc": "^1.0.3", "is-glob": "^4.0.3", "micromatch": "^4.0.5", "node-addon-api": "^7.0.0" }, "optionalDependencies": { "@parcel/watcher-android-arm64": "2.5.1", "@parcel/watcher-darwin-arm64": "2.5.1", "@parcel/watcher-darwin-x64": "2.5.1", "@parcel/watcher-freebsd-x64": "2.5.1", "@parcel/watcher-linux-arm-glibc": "2.5.1", "@parcel/watcher-linux-arm-musl": "2.5.1", "@parcel/watcher-linux-arm64-glibc": "2.5.1", "@parcel/watcher-linux-arm64-musl": "2.5.1", "@parcel/watcher-linux-x64-glibc": "2.5.1", "@parcel/watcher-linux-x64-musl": "2.5.1", "@parcel/watcher-win32-arm64": "2.5.1", "@parcel/watcher-win32-ia32": "2.5.1", "@parcel/watcher-win32-x64": "2.5.1" } }, "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg=="],
@@ -144,67 +148,73 @@
"@types/ws": ["@types/ws@8.18.2", "", { "dependencies": { "@types/node": "*" } }, "sha512-67MQl+fpWKVTT1NYdnmo3U4sc/xPo/zQBncVnI74qmQa0z/b+1g6iYqNmGCPbxO+zz2aklb08a0oHfegiVd0/w=="],
"@wrnexus/authz": ["@wrnexus/authz@0.8.15", "https://registry.workroot.in/repository/npm/@wrnexus/authz/-/authz-0.8.15.tgz", { "dependencies": { "@wrnexus/core": "^0.8.12", "@wrnexus/db": "^0.8.20", "@wrnexus/plugin": "^0.8.8" } }, "sha512-ZV1cvHrOkephfjs/gzzcLkN4HEHSFWJVZVmfsvir/GZs/X7+ZQbPNYUQZV7SsRlyMkUxgTKMCiZ8Ym49eOBSQw=="],
"@wrnexus/ai": ["@wrnexus/ai@0.8.10", "https://registry.workroot.in/repository/npm/@wrnexus/ai/-/ai-0.8.10.tgz", {}, "sha512-/vCpdkB4DpTRQ6g7UtwXLx95pWpBTfqvBukNjjRy5/L3hLiIp29n5RzPw+n3kRVhE8uGRCaKc9yUBxlhNKHUMA=="],
"@wrnexus/cache": ["@wrnexus/cache@0.8.8", "https://registry.workroot.in/repository/npm/@wrnexus/cache/-/cache-0.8.8.tgz", { "dependencies": { "@wrnexus/core": "^0.8.9" } }, "sha512-GSV2myyy8xVeI8LdtJoIffW6fveCqB4WWN0CaodhVpI+4Y2aEmfJ6qwFikf34qI8Fy1+2ca9sKl5t1494kZBvw=="],
"@wrnexus/authz": ["@wrnexus/authz@0.8.16", "https://registry.workroot.in/repository/npm/@wrnexus/authz/-/authz-0.8.16.tgz", { "dependencies": { "@wrnexus/core": "^0.8.25", "@wrnexus/db": "^0.8.24", "@wrnexus/plugin": "^0.8.10" } }, "sha512-bKs6X+nAU7w7m4Vvdf92/5ZjZ0MCPRxmCHvHAI376LtYlLVqqiDVRN2j1JWCkPdrvYaXeqsz6DMhPIKdKzS8Zg=="],
"@wrnexus/cli": ["@wrnexus/cli@0.8.72", "https://registry.workroot.in/repository/npm/@wrnexus/cli/-/cli-0.8.72.tgz", { "dependencies": { "@wrnexus/authz": "^0.8.15", "@wrnexus/compiler": "^0.8.30", "@wrnexus/core": "^0.8.16", "@wrnexus/csr": "^0.8.41", "@wrnexus/db": "^0.8.23", "@wrnexus/dev-server": "^0.8.66", "@wrnexus/i18n": "^0.8.12", "@wrnexus/mcp": "^0.8.8", "@wrnexus/playground": "^0.8.8", "@wrnexus/plugin": "^0.8.9", "@wrnexus/react": "^0.8.9", "@wrnexus/router": "^0.8.10", "@wrnexus/security": "^0.8.9", "@wrnexus/styles": "^0.8.25", "@wrnexus/syntax": "^0.8.19", "@wrnexus/typecheck": "^0.8.17", "@wrnexus/ui": "^0.8.85", "@wrnexus/validation": "^0.8.13", "selfsigned": "^5.5.0" }, "bin": { "wrnexus": "dist/index.js" } }, "sha512-JeFsDMldcjiUFMhal11V/bfg/dNcG+OJh7+Bt6lmU3ojxTajvxV6pjLPp022hYDBZPu83jupiF4WZPwOLy/+Bw=="],
"@wrnexus/cache": ["@wrnexus/cache@0.8.9", "https://registry.workroot.in/repository/npm/@wrnexus/cache/-/cache-0.8.9.tgz", { "dependencies": { "@wrnexus/core": "^0.8.25" } }, "sha512-NftsbOsRtKCV77xxqNENIeUgcJjDgWuZL8KjxYJOdc6vVevoJ/fWU/EprqIuZ6YNtqm7TFFqMEENpb6GLvidGg=="],
"@wrnexus/compiler": ["@wrnexus/compiler@0.8.30", "https://registry.workroot.in/repository/npm/@wrnexus/compiler/-/compiler-0.8.30.tgz", { "dependencies": { "@wrnexus/csr": "^0.8.41", "@wrnexus/store": "^0.8.12", "@wrnexus/syntax": "^0.8.19", "@wrnexus/validation": "^0.8.13" } }, "sha512-zsxqcIMOzXxX98z6RFffwQUa6VuniOqGZO/vxDdOJiyJ8RTs7gOk8dsBhA6MTLQ1fafPxJPV3zkGotKXOuxhCQ=="],
"@wrnexus/cli": ["@wrnexus/cli@0.8.77", "https://registry.workroot.in/repository/npm/@wrnexus/cli/-/cli-0.8.77.tgz", { "dependencies": { "@wrnexus/authz": "^0.8.16", "@wrnexus/compiler": "^0.8.44", "@wrnexus/core": "^0.8.25", "@wrnexus/csr": "^0.8.74", "@wrnexus/db": "^0.8.24", "@wrnexus/design-system": "^0.1.0", "@wrnexus/dev-server": "^0.8.83", "@wrnexus/i18n": "^0.8.13", "@wrnexus/mcp": "^0.8.9", "@wrnexus/playground": "^0.8.9", "@wrnexus/plugin": "^0.8.10", "@wrnexus/react": "^0.8.10", "@wrnexus/router": "^0.8.11", "@wrnexus/security": "^0.8.10", "@wrnexus/styles": "^0.8.27", "@wrnexus/syntax": "^0.8.20", "@wrnexus/typecheck": "^0.8.18", "@wrnexus/ui": "^0.8.118", "@wrnexus/validation": "^0.8.14", "selfsigned": "^5.5.0" }, "bin": { "wrnexus": "dist/index.js" } }, "sha512-zFkifdFVwkcja9H8ctEZMPD5khBqmhp32yqSGjBvJnfuFCBdaRB9U5uCkqBbPCQUELrqTvCG2lafvQaptBo8xQ=="],
"@wrnexus/core": ["@wrnexus/core@0.8.16", "https://registry.workroot.in/repository/npm/@wrnexus/core/-/core-0.8.16.tgz", {}, "sha512-lTNigmTpJsgQnB95xMhalJ6Xbp/QBUf9J0MM4cuiecZ1DQLpaSgGC12Sn7FIC46rTU4w8878XJXlVWDCabe16Q=="],
"@wrnexus/compiler": ["@wrnexus/compiler@0.8.44", "https://registry.workroot.in/repository/npm/@wrnexus/compiler/-/compiler-0.8.44.tgz", { "dependencies": { "@wrnexus/csr": "^0.8.74", "@wrnexus/store": "^0.8.13", "@wrnexus/syntax": "^0.8.20", "@wrnexus/validation": "^0.8.14" } }, "sha512-TJ3qPfD+2VsmpuVXgA6CUIlv2fqU2tW8xrIvHUFkGYJpVzF5jbSBUsoHNDfCT9/t5gw3CGazJnPqgzdcIm5XCg=="],
"@wrnexus/csr": ["@wrnexus/csr@0.8.43", "https://registry.workroot.in/repository/npm/@wrnexus/csr/-/csr-0.8.43.tgz", { "dependencies": { "@wrnexus/core": "^0.8.12" } }, "sha512-czmxeLxvNvD7XjU3TufFBGMzuDWpNB0qpYbmbiARB7l6rslBw3+GuBWf2U5k4DH6oYiN/DGD6Jj+/G3bEh6ARw=="],
"@wrnexus/core": ["@wrnexus/core@0.8.25", "https://registry.workroot.in/repository/npm/@wrnexus/core/-/core-0.8.25.tgz", {}, "sha512-od4TyDIKoX0RhjTDq+1HJ5fGQPID04Ao+BvWEkJU0beWRbXLZ6u5iRsh58+h/T2so8NSI9sW4rorC4N+BSMaqQ=="],
"@wrnexus/db": ["@wrnexus/db@0.8.23", "https://registry.workroot.in/repository/npm/@wrnexus/db/-/db-0.8.23.tgz", {}, "sha512-ncZlvclHW98Enah9wlHOf9+StoVGLrCOCVBAOEFdZKV91vKnYDltcFlmG7i7crndN37kayyb319Wiwol8Hmhyg=="],
"@wrnexus/csr": ["@wrnexus/csr@0.8.74", "https://registry.workroot.in/repository/npm/@wrnexus/csr/-/csr-0.8.74.tgz", { "dependencies": { "@wrnexus/core": "^0.8.12" } }, "sha512-hqU7zqWRlkiOxJ8Ke9YidqwRN/CvmvozsK24XPsnlo7zt1IpNma0Woo9J5ZnO3MO9ihVU4sa8tmg61ucKHFFpQ=="],
"@wrnexus/dev-server": ["@wrnexus/dev-server@0.8.66", "https://registry.workroot.in/repository/npm/@wrnexus/dev-server/-/dev-server-0.8.66.tgz", { "dependencies": { "@wrnexus/authz": "^0.8.15", "@wrnexus/cache": "^0.8.8", "@wrnexus/compiler": "^0.8.30", "@wrnexus/core": "^0.8.16", "@wrnexus/csr": "^0.8.41", "@wrnexus/db": "^0.8.23", "@wrnexus/dev-toolbar": "^0.8.18", "@wrnexus/i18n": "^0.8.12", "@wrnexus/observability": "^0.8.8", "@wrnexus/plugin": "^0.8.9", "@wrnexus/pubsub": "^0.8.9", "@wrnexus/pwa": "^0.8.12", "@wrnexus/queue": "^0.8.14", "@wrnexus/react": "^0.8.9", "@wrnexus/router": "^0.8.10", "@wrnexus/rpc": "^0.8.10", "@wrnexus/security": "^0.8.9", "@wrnexus/ssr": "^0.8.12", "@wrnexus/store": "^0.8.12", "@wrnexus/styles": "^0.8.23", "@wrnexus/ui": "^0.8.84", "@wrnexus/uploader": "^0.8.13", "@wrnexus/validation": "^0.8.13" } }, "sha512-RBJWyUEGmOS6ZgIm5NvNPB4BVhVIpGFEEf4NSLDKJtp/Z5K2+G44KbRhZaaYvl6F4IEZM2Zg5x+ZAX+o5XB34w=="],
"@wrnexus/db": ["@wrnexus/db@0.8.24", "https://registry.workroot.in/repository/npm/@wrnexus/db/-/db-0.8.24.tgz", {}, "sha512-zLT7e+C1nWhYs3BnqEjEO0QSli0JNl5sSnSHObjSX0C+wty30ASWD1WyBnfu9xFjOFn1eucZGthzo1xdGGQ1TQ=="],
"@wrnexus/dev-toolbar": ["@wrnexus/dev-toolbar@0.8.18", "https://registry.workroot.in/repository/npm/@wrnexus/dev-toolbar/-/dev-toolbar-0.8.18.tgz", {}, "sha512-7mj/FLIhLjx/DxH/gUlYwZqm63o/rcwH/0K/K6Efxvu9zfM5OyAh2w3L2eDWI9asK5foZkit8cKMUXVgmqHkcA=="],
"@wrnexus/design-studio": ["@wrnexus/design-studio@0.1.0", "https://registry.workroot.in/repository/npm/@wrnexus/design-studio/-/design-studio-0.1.0.tgz", { "dependencies": { "@wrnexus/ai": "^0.8.10", "@wrnexus/compiler": "^0.8.44", "@wrnexus/core": "^0.8.25", "@wrnexus/csr": "^0.8.74", "@wrnexus/design-system": "^0.1.0", "@wrnexus/ssr": "^0.8.20", "@wrnexus/styles": "^0.8.27", "@wrnexus/ui": "^0.8.118" }, "bin": { "wrnexus-design-studio": "dist/cli.js" } }, "sha512-HeY3zG45oEvsLy1my9nCgKHb11ip9eTthhp/bzeOIXEn8vk71pRhqdgrltEwn2vFKIlKuPBQlA4xftmLDhSWTQ=="],
"@wrnexus/helpers": ["@wrnexus/helpers@0.8.9", "https://registry.workroot.in/repository/npm/@wrnexus/helpers/-/helpers-0.8.9.tgz", { "dependencies": { "@wrnexus/authz": "^0.8.14", "@wrnexus/core": "^0.8.12", "@wrnexus/db": "^0.8.20" } }, "sha512-EzT9LSZJXIAIm2fO62BMbPJOnrloC1lujW+5UNsSd4kj44mBt6WMpBwaCSDGUcVy2/b7GKXlgBnUVZtIIGn0gw=="],
"@wrnexus/design-system": ["@wrnexus/design-system@0.1.0", "https://registry.workroot.in/repository/npm/@wrnexus/design-system/-/design-system-0.1.0.tgz", {}, "sha512-gNH/B+kYYZy+Pvlvl3gXoQZlTS6iP/teXct2MoClmsGp6M1vKa8IEptVXKs7po3E83zj5kSh3FIXwcBJHtZqLg=="],
"@wrnexus/i18n": ["@wrnexus/i18n@0.8.12", "https://registry.workroot.in/repository/npm/@wrnexus/i18n/-/i18n-0.8.12.tgz", { "dependencies": { "@wrnexus/core": "^0.8.9", "@wrnexus/plugin": "^0.8.8", "@wrnexus/ui": "^0.8.19" } }, "sha512-pgDJZpS8qB3tz+FMY+CNUF7AZXJVRFWbFDSHk+QMeUAwkU7JbNDxwmKioa6QU50F6C0SUMbfVwDR3kBXZKBflQ=="],
"@wrnexus/dev-server": ["@wrnexus/dev-server@0.8.83", "https://registry.workroot.in/repository/npm/@wrnexus/dev-server/-/dev-server-0.8.83.tgz", { "dependencies": { "@wrnexus/authz": "^0.8.16", "@wrnexus/cache": "^0.8.9", "@wrnexus/compiler": "^0.8.44", "@wrnexus/core": "^0.8.25", "@wrnexus/csr": "^0.8.74", "@wrnexus/db": "^0.8.24", "@wrnexus/dev-toolbar": "^0.8.19", "@wrnexus/i18n": "^0.8.13", "@wrnexus/observability": "^0.8.9", "@wrnexus/plugin": "^0.8.10", "@wrnexus/pubsub": "^0.8.10", "@wrnexus/pwa": "^0.8.13", "@wrnexus/queue": "^0.8.15", "@wrnexus/react": "^0.8.10", "@wrnexus/router": "^0.8.11", "@wrnexus/rpc": "^0.8.11", "@wrnexus/security": "^0.8.10", "@wrnexus/ssr": "^0.8.20", "@wrnexus/store": "^0.8.13", "@wrnexus/styles": "^0.8.27", "@wrnexus/ui": "^0.8.118", "@wrnexus/uploader": "^0.8.14", "@wrnexus/validation": "^0.8.14" } }, "sha512-Ue6Q2KF7nZycvghRvWQBC9PA0DZ2aE+8fC3FaIFMkbID9HLK64Xe+MgMnLDJvQ7mlBJlC+9Ztj8yOYqSavtq1g=="],
"@wrnexus/jwt": ["@wrnexus/jwt@0.8.9", "https://registry.workroot.in/repository/npm/@wrnexus/jwt/-/jwt-0.8.9.tgz", { "dependencies": { "@wrnexus/core": "^0.8.9" } }, "sha512-LcjXLdDp8pnJ3F6dDGlB3COlvg7jVBIZe+UnF48i7Hy12gHZu0Rbv/iBn9w203tpzT2EmcpGtMyI/J+uLQUeVg=="],
"@wrnexus/dev-toolbar": ["@wrnexus/dev-toolbar@0.8.19", "https://registry.workroot.in/repository/npm/@wrnexus/dev-toolbar/-/dev-toolbar-0.8.19.tgz", {}, "sha512-Rfl94o7Tkd9KpwB7RO13DPm7vrqSjaHE5AFyiNL9ypKEXWJhvQf6yvQ6NvlU0gy8j119Fgqg+zBUkVN16QZVMA=="],
"@wrnexus/mcp": ["@wrnexus/mcp@0.8.8", "https://registry.workroot.in/repository/npm/@wrnexus/mcp/-/mcp-0.8.8.tgz", { "bin": { "wrnexus-mcp": "dist/stdio.js" } }, "sha512-E4Rz03RVjzyjTdwL9d2zzMKLIkyTw1DMcwiRrdAcAEk6/HYJr4rnttiIGcw1lu58ptrLM/lUeqYWEWV+SyDXcQ=="],
"@wrnexus/helpers": ["@wrnexus/helpers@0.8.10", "https://registry.workroot.in/repository/npm/@wrnexus/helpers/-/helpers-0.8.10.tgz", { "dependencies": { "@wrnexus/authz": "^0.8.16", "@wrnexus/core": "^0.8.25", "@wrnexus/db": "^0.8.24" } }, "sha512-uwH83Mc0qqfE2eEYu5NNMYhhGB4xvUd2WPaY3B7RlV7RwR/SXNcmr0Ei76KPNhYWzhLO6bx5bWDlFuWENm1BoQ=="],
"@wrnexus/observability": ["@wrnexus/observability@0.8.8", "https://registry.workroot.in/repository/npm/@wrnexus/observability/-/observability-0.8.8.tgz", { "dependencies": { "@wrnexus/core": "^0.8.9" } }, "sha512-P7R4IYm7o6OfP1TmQ6L537DAOMH5WbC74TP4rw/Stwx8RxS/ORYPWw0mGB8f+1eamOV40Y5U4E04nmf3Tugj0Q=="],
"@wrnexus/i18n": ["@wrnexus/i18n@0.8.13", "https://registry.workroot.in/repository/npm/@wrnexus/i18n/-/i18n-0.8.13.tgz", { "dependencies": { "@wrnexus/core": "^0.8.25", "@wrnexus/plugin": "^0.8.10", "@wrnexus/ui": "^0.8.118" } }, "sha512-Go4JT+mc/SYnqWiv0ha+7/NLLPY/1HVFbCz8m2oLwtYKMrsZtn62Ows4uW54fzTY3fp8RkaVxDgkiC2p2jA1tw=="],
"@wrnexus/playground": ["@wrnexus/playground@0.8.8", "https://registry.workroot.in/repository/npm/@wrnexus/playground/-/playground-0.8.8.tgz", { "dependencies": { "@wrnexus/compiler": "^0.8.10", "@wrnexus/syntax": "^0.8.9" } }, "sha512-FpQ2n81GWSJSc0LccH6zDYm0pfdUk54LdDYma0Y72pyLfRjSY0ymQJcCr6Jp/EE5iBIhRowD6ag7vd26h27pZA=="],
"@wrnexus/jwt": ["@wrnexus/jwt@0.8.10", "https://registry.workroot.in/repository/npm/@wrnexus/jwt/-/jwt-0.8.10.tgz", { "dependencies": { "@wrnexus/core": "^0.8.25" } }, "sha512-axXx1aCrIgpNhJyreKDQ78IlqGH+3AeKtfEW+/pzPFUXU03DU/YdCasK+WcZYYAQPPcZnegJA9MP9cYZYAFBCQ=="],
"@wrnexus/plugin": ["@wrnexus/plugin@0.8.9", "https://registry.workroot.in/repository/npm/@wrnexus/plugin/-/plugin-0.8.9.tgz", { "dependencies": { "@wrnexus/syntax": "^0.8.19" } }, "sha512-XpkQL4/MpiNxoNcH1l7dL5cYEu8HN54/b5bx6DBXWutU4tMrAjChtbJ+SsE2YrNve4uWVUhF8wPgsdBrJONOQQ=="],
"@wrnexus/mcp": ["@wrnexus/mcp@0.8.9", "https://registry.workroot.in/repository/npm/@wrnexus/mcp/-/mcp-0.8.9.tgz", { "peerDependencies": { "@wrnexus/design-studio": "^0.1.0" }, "optionalPeers": ["@wrnexus/design-studio"], "bin": { "wrnexus-mcp": "dist/stdio.js" } }, "sha512-OVSL2ZZeTh6pwuQiWK4gjTLDVfzu4INuf5PvMjyynzphXwsFWpL5m8BvVD4or4R9Jvm/R8WAhHIO8gLWZHF1oA=="],
"@wrnexus/pubsub": ["@wrnexus/pubsub@0.8.9", "https://registry.workroot.in/repository/npm/@wrnexus/pubsub/-/pubsub-0.8.9.tgz", { "dependencies": { "@wrnexus/core": "^0.8.9", "@wrnexus/rpc": "^0.8.9" } }, "sha512-Z696WHuzJsPJvkvz3aRcifiZEqHXSIzoH3ji/wPqBP+vqmKIiZ/WIzViSQ0j8QJgtHiiq1mo2d4GFxsfdAPbqg=="],
"@wrnexus/observability": ["@wrnexus/observability@0.8.9", "https://registry.workroot.in/repository/npm/@wrnexus/observability/-/observability-0.8.9.tgz", { "dependencies": { "@wrnexus/core": "^0.8.25" } }, "sha512-f+kUNBATorCxKl04HsNuQi7o8pOgyW8qpfljWsFgauIdYxtTDFSxCERZIlprHyvin5l5ffAKFZcXeSutGqiPgQ=="],
"@wrnexus/pwa": ["@wrnexus/pwa@0.8.12", "https://registry.workroot.in/repository/npm/@wrnexus/pwa/-/pwa-0.8.12.tgz", {}, "sha512-XI5wgn+vbPcSbAt3EsqnrPjkx2cd/Zpo3xy2deawuU5k7irkRImPNUWvtjkTar5GaNedVvuZQAhXLghb9p/GQQ=="],
"@wrnexus/playground": ["@wrnexus/playground@0.8.9", "https://registry.workroot.in/repository/npm/@wrnexus/playground/-/playground-0.8.9.tgz", { "dependencies": { "@wrnexus/compiler": "^0.8.44", "@wrnexus/syntax": "^0.8.20" } }, "sha512-hQCmKoi6gthyYLZDtvcDJFwq5THuxIWDijltDWTDOe9Gy7WdVn9UhrRVEFFYZ6VLtBRXAxnzlGb7eqJAMBKTaA=="],
"@wrnexus/queue": ["@wrnexus/queue@0.8.14", "https://registry.workroot.in/repository/npm/@wrnexus/queue/-/queue-0.8.14.tgz", { "dependencies": { "@wrnexus/core": "^0.8.12", "@wrnexus/db": "^0.8.20", "@wrnexus/rpc": "^0.8.10" } }, "sha512-uulbyU1AF3gnfylmlFMIoBjAKgAgHsHg+FfEmLtoYwsaQ+JtMNk5PEZ/GUUBxEmK9ZbEAdgBAxgEX69E7ne9aA=="],
"@wrnexus/plugin": ["@wrnexus/plugin@0.8.10", "https://registry.workroot.in/repository/npm/@wrnexus/plugin/-/plugin-0.8.10.tgz", { "dependencies": { "@wrnexus/syntax": "^0.8.20" } }, "sha512-YVSLW8Lzq3/eFzAOj9B2A6ngFvdm2jmzSCEd2tI491rGqLbQWyFx3NzCuN/CnAZOA3kyHE+W4oiG6/3cyWWZsg=="],
"@wrnexus/react": ["@wrnexus/react@0.8.9", "https://registry.workroot.in/repository/npm/@wrnexus/react/-/react-0.8.9.tgz", { "dependencies": { "@wrnexus/store": "^0.8.8" } }, "sha512-031RC/EBF1nzSeiwo2gXhOJ+xMLRtPUniN612ZVzj+pqGdn1J8I8vajZwRYKYC2xAVdCiB/EGoZ3FQaT75h8qw=="],
"@wrnexus/pubsub": ["@wrnexus/pubsub@0.8.10", "https://registry.workroot.in/repository/npm/@wrnexus/pubsub/-/pubsub-0.8.10.tgz", { "dependencies": { "@wrnexus/core": "^0.8.25", "@wrnexus/rpc": "^0.8.11" } }, "sha512-X0ZEEvcSjUqvNT49vyYTmxgtEiQl6l8gFPfkbWWixsvAGQO55QGjZCvtUu/R0ItJ+1an45DKx9R4Z6K7ppqcUQ=="],
"@wrnexus/router": ["@wrnexus/router@0.8.10", "https://registry.workroot.in/repository/npm/@wrnexus/router/-/router-0.8.10.tgz", { "dependencies": { "@wrnexus/compiler": "^0.8.17", "@wrnexus/core": "^0.8.12" } }, "sha512-zh+h+VDNshSsh2iryqbOCWOhcIbKXg58iWkHz3wKNovlWT0uAgLhmea6IHsiApI8RC/VPw4TAmAhfkaK1c4BBA=="],
"@wrnexus/pwa": ["@wrnexus/pwa@0.8.13", "https://registry.workroot.in/repository/npm/@wrnexus/pwa/-/pwa-0.8.13.tgz", {}, "sha512-u4D8jfI5ZHJbZrOTfeEJ9CTq+wCTqJ7ZjoRlTddf1RnAV/w8d6Vg72KDy6ApdoNuiJMqHRu44nqK053UyP00Sw=="],
"@wrnexus/rpc": ["@wrnexus/rpc@0.8.10", "https://registry.workroot.in/repository/npm/@wrnexus/rpc/-/rpc-0.8.10.tgz", { "dependencies": { "@wrnexus/core": "^0.8.9", "@wrnexus/helpers": "^0.8.8", "@wrnexus/jwt": "^0.8.9", "@wrnexus/validation": "^0.8.10" } }, "sha512-KbfSxEe0D0ZiM1CckxiEVIEBSzYRYb3iEJYyJnT8DqlrEpos1hCwT22XnTMC3ldsCAusoUPO5gTXMBXL9qMKDQ=="],
"@wrnexus/queue": ["@wrnexus/queue@0.8.15", "https://registry.workroot.in/repository/npm/@wrnexus/queue/-/queue-0.8.15.tgz", { "dependencies": { "@wrnexus/core": "^0.8.25", "@wrnexus/db": "^0.8.24", "@wrnexus/rpc": "^0.8.11" } }, "sha512-xJPZUqxYRMEgrgPIZoaZRMDWwwB8rUu0mrizNAGoZIwz1BzPsdVJaXOhsFvZd/mkHgk1CupxYXMNHuYA2pRGDg=="],
"@wrnexus/security": ["@wrnexus/security@0.8.9", "https://registry.workroot.in/repository/npm/@wrnexus/security/-/security-0.8.9.tgz", { "dependencies": { "@wrnexus/core": "^0.8.11" } }, "sha512-dgz2fYwiw7uhBdsMuLqlPQaqajJx1McTjAhx8Pp1lf8gddsXm+Dnmri/1LXSbPwuSpWB7gsNq326JlVICfipVQ=="],
"@wrnexus/react": ["@wrnexus/react@0.8.10", "https://registry.workroot.in/repository/npm/@wrnexus/react/-/react-0.8.10.tgz", { "dependencies": { "@wrnexus/store": "^0.8.13" }, "peerDependencies": { "react": "^19.0.0", "react-dom": "^19.0.0" }, "optionalPeers": ["react", "react-dom"] }, "sha512-n5mdbb7ZWxOylL4I28GCEjLSFArPLNB8pCEIT3CxYXQQXkHgGXNS+++ls6R1XwnTrGLUJfVECpzRmf6mfeszUQ=="],
"@wrnexus/ssr": ["@wrnexus/ssr@0.8.12", "https://registry.workroot.in/repository/npm/@wrnexus/ssr/-/ssr-0.8.12.tgz", { "dependencies": { "@wrnexus/core": "^0.8.16", "@wrnexus/security": "^0.8.9", "@wrnexus/store": "^0.8.12" } }, "sha512-fPoxMfnlwuUs6syJ6LMjqzxIKGsghQ3UCKjSFkRXlvdwdPpWRSxW0g0+jJF66/OTyCo2kB0dwMRGVLhICLgvLw=="],
"@wrnexus/router": ["@wrnexus/router@0.8.11", "https://registry.workroot.in/repository/npm/@wrnexus/router/-/router-0.8.11.tgz", { "dependencies": { "@wrnexus/compiler": "^0.8.44", "@wrnexus/core": "^0.8.25" } }, "sha512-9hry5s0GQ0RdBXWue3I6JBijZMHcO+7J9oJnKqwPD2zScHdmU8ooJ4LyuI9kqf9Wc22Zl9Whgp/OjxGMa8aRtw=="],
"@wrnexus/store": ["@wrnexus/store@0.8.12", "https://registry.workroot.in/repository/npm/@wrnexus/store/-/store-0.8.12.tgz", {}, "sha512-5AiJXZ6AFT2eshp21JEyeHlmBgHuxyeRslN6YZiIvUfoO4Dre3VtR4pI+hN3lOGloLXwXBUfEMm2mgGsXS36Kg=="],
"@wrnexus/rpc": ["@wrnexus/rpc@0.8.11", "https://registry.workroot.in/repository/npm/@wrnexus/rpc/-/rpc-0.8.11.tgz", { "dependencies": { "@wrnexus/core": "^0.8.25", "@wrnexus/helpers": "^0.8.10", "@wrnexus/jwt": "^0.8.10", "@wrnexus/validation": "^0.8.14" } }, "sha512-SKxM0ACMsz3MQ7J0tYam2ZlE6WI3immFgak/bxtdwarMM6CVV6t3zxq/zw5EGfeWuCQxmTefOpvaTuhvzgKf5A=="],
"@wrnexus/styles": ["@wrnexus/styles@0.8.26", "https://registry.workroot.in/repository/npm/@wrnexus/styles/-/styles-0.8.26.tgz", { "dependencies": { "@wrnexus/core": "^0.8.16", "@wrnexus/plugin": "^0.8.9", "@wrnexus/uploader": "^0.8.13" } }, "sha512-B1FgQYks6S9SohlWjDkRabbzAAW9IIKbR5rHrdXegr6QY3nQMtJYPMG8xUVMTpQ8gRL+GODtuhDYPHD/igHuPg=="],
"@wrnexus/security": ["@wrnexus/security@0.8.10", "https://registry.workroot.in/repository/npm/@wrnexus/security/-/security-0.8.10.tgz", { "dependencies": { "@wrnexus/core": "^0.8.25" } }, "sha512-DRPI1TpMbVNtx91jnsIHN+ONvNs6RYKW5hot8Gez6y/XRliksAQAv4qPlW3V/Jctzsfue7Bz0qhERtqcnUzKPw=="],
"@wrnexus/syntax": ["@wrnexus/syntax@0.8.19", "https://registry.workroot.in/repository/npm/@wrnexus/syntax/-/syntax-0.8.19.tgz", {}, "sha512-/OZ+Z/cdFmfqKeqCZZpmwN2ZRSITA2ByqmVjGVONtMRfxHBj99T5jB0be6qlxrmoK0cgntRxEe2JCS/d9h54YA=="],
"@wrnexus/ssr": ["@wrnexus/ssr@0.8.20", "https://registry.workroot.in/repository/npm/@wrnexus/ssr/-/ssr-0.8.20.tgz", { "dependencies": { "@wrnexus/core": "^0.8.25", "@wrnexus/security": "^0.8.10", "@wrnexus/store": "^0.8.13" } }, "sha512-0+I9C9Mjtpk8IeOfU+TIPo4/Wb1r3TC+xZBytj0v1Sper8IWSGw0At6opbJMnw5PPERnsQC0XJDhcSVlj2Wbuw=="],
"@wrnexus/typecheck": ["@wrnexus/typecheck@0.8.17", "https://registry.workroot.in/repository/npm/@wrnexus/typecheck/-/typecheck-0.8.17.tgz", { "dependencies": { "@wrnexus/syntax": "^0.8.19", "typescript": "^6.0.3" } }, "sha512-sEvCraG7qudT61h0SbuccIegi37nVWW2B1+BjmPg6Zrtc0251lUozASOYMW2ntjiizASDXMTSnZvSJ36EJPflA=="],
"@wrnexus/store": ["@wrnexus/store@0.8.13", "https://registry.workroot.in/repository/npm/@wrnexus/store/-/store-0.8.13.tgz", {}, "sha512-EHfjbs3qcVVFA5QkLDubH8bBdVWHAinx+5GYeo7asYSs/4qcfd6K0X0bsXp73FVm3CHgGeN9I+Ih6bNJmAEEWQ=="],
"@wrnexus/ui": ["@wrnexus/ui@0.8.88", "https://registry.workroot.in/repository/npm/@wrnexus/ui/-/ui-0.8.88.tgz", { "dependencies": { "@wrnexus/core": "^0.8.16" } }, "sha512-C6q3c85tJm0Ajhgb8i+DYOWyICNxeXVsR3KbD5yP0rC2XS5Vj9TP72x7NPux798jGLpbOpSPRiIPUff7zAod7w=="],
"@wrnexus/styles": ["@wrnexus/styles@0.8.27", "https://registry.workroot.in/repository/npm/@wrnexus/styles/-/styles-0.8.27.tgz", { "dependencies": { "@wrnexus/core": "^0.8.25", "@wrnexus/design-system": "^0.1.0", "@wrnexus/plugin": "^0.8.10", "@wrnexus/uploader": "^0.8.14" } }, "sha512-2DTZycU9LVaEn5/7ZsV87LDgDcm1fht6MHXp+alTBmlmkJ2tjeJnJm2wiMydStWKjf8E3AKAhZWg/3f2wOGi1g=="],
"@wrnexus/uploader": ["@wrnexus/uploader@0.8.13", "https://registry.workroot.in/repository/npm/@wrnexus/uploader/-/uploader-0.8.13.tgz", { "dependencies": { "@wrnexus/core": "^0.8.12", "@wrnexus/plugin": "^0.8.8", "@wrnexus/ui": "^0.8.23" } }, "sha512-Cfj5Iqtbk/ccXV/YXQ4I8v0GkcE7cFnzMEB33qy3DcWo4fA5ndiWU9CN4Ap1oysA5MWEmcCKuJlcTKdWLhiTvw=="],
"@wrnexus/syntax": ["@wrnexus/syntax@0.8.20", "https://registry.workroot.in/repository/npm/@wrnexus/syntax/-/syntax-0.8.20.tgz", {}, "sha512-vd3EQLjLeNnnlSRVUMY4m+VksKpUHfTla0eWSZ8N+GroEVDgYegHW79tWcRAlmCxPe/jrpUSGri6dZoty2b72A=="],
"@wrnexus/validation": ["@wrnexus/validation@0.8.13", "https://registry.workroot.in/repository/npm/@wrnexus/validation/-/validation-0.8.13.tgz", { "dependencies": { "@wrnexus/core": "^0.8.12", "@wrnexus/plugin": "^0.8.8", "@wrnexus/ui": "^0.8.76" } }, "sha512-ud9bzeSaOzbYnmu6pKEr5XbBT25FW+ROOI9iB0YJBc624juurslgHm2lpmpOu2WKUWulgktb/2vl9nsvtI8pSw=="],
"@wrnexus/typecheck": ["@wrnexus/typecheck@0.8.18", "https://registry.workroot.in/repository/npm/@wrnexus/typecheck/-/typecheck-0.8.18.tgz", { "dependencies": { "@wrnexus/syntax": "^0.8.20", "typescript": "^6.0.3" } }, "sha512-oS5x6hUs6VUNEupDARzFTzXvvdRAV6l8nO3wi+5rdfeDIDSz/5QNeQfVwzJg7SDGVkuTVOHH8lqyiMtSW+8Nbg=="],
"@wrnexus/ui": ["@wrnexus/ui@0.8.118", "https://registry.workroot.in/repository/npm/@wrnexus/ui/-/ui-0.8.118.tgz", { "dependencies": { "@wrnexus/core": "^0.8.25", "@wrnexus/design-system": "^0.1.0", "@wrnexus/plugin": "^0.8.10", "chart.js": "^4.5.1", "drawflow": "0.0.60" } }, "sha512-a0RWv3P+Z0f19Pqvaq+mHcBrAYni1k8iXQKMf9r83rYp3m6V4e00Fahg661VcF4Y6o3SAn151YVTH3zrRwsaWw=="],
"@wrnexus/uploader": ["@wrnexus/uploader@0.8.14", "https://registry.workroot.in/repository/npm/@wrnexus/uploader/-/uploader-0.8.14.tgz", { "dependencies": { "@wrnexus/core": "^0.8.25", "@wrnexus/plugin": "^0.8.10", "@wrnexus/ui": "^0.8.118" } }, "sha512-LticgG17uYu65IYRNDGagtvjfdUNrVHR2drbv6r/J4pycNX6CcGGn0hbjZFPA1uSHfH/hp//hA+KTOcoE14aMQ=="],
"@wrnexus/validation": ["@wrnexus/validation@0.8.14", "https://registry.workroot.in/repository/npm/@wrnexus/validation/-/validation-0.8.14.tgz", { "dependencies": { "@wrnexus/core": "^0.8.25", "@wrnexus/plugin": "^0.8.10", "@wrnexus/ui": "^0.8.118" } }, "sha512-cdy8soKgKqGI3FP1wvbHsmdKAnDAzN6h0LcUadgjqz9sfp7RSsYuFBxEw/lkZiWkUbBbAuAaQ/sI7FgXWDnPxg=="],
"asn1js": ["asn1js@3.0.10", "", { "dependencies": { "pvtsutils": "^1.3.6", "pvutils": "^1.1.5", "tslib": "^2.8.1" } }, "sha512-S2s3aOytiKdFRdulw2qPE51MzjzVOisppcVv7jVFR+Kw0kxwvFrDcYA0h7Ndqbmj0HkMIXYWaoj7fli8kgx1eg=="],
@@ -218,6 +228,8 @@
"bytestreamjs": ["bytestreamjs@2.0.1", "", {}, "sha512-U1Z/ob71V/bXfVABvNr/Kumf5VyeQRBEm6Txb0PQ6S7V5GpBM3w4Cbqz/xPDicR5tN0uvDifng8C+5qECeGwyQ=="],
"chart.js": ["chart.js@4.5.1", "", { "dependencies": { "@kurkle/color": "^0.3.0" } }, "sha512-GIjfiT9dbmHRiYi6Nl2yFCq7kkwdkp1W/lp2J99rX0yo9tgJGn3lKQATztIjb5tVtevcBtIdICNWqlq5+E8/Pw=="],
"commander": ["commander@11.1.0", "", {}, "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ=="],
"css-select": ["css-select@5.2.2", "", { "dependencies": { "boolbase": "^1.0.0", "css-what": "^6.1.0", "domhandler": "^5.0.2", "domutils": "^3.0.1", "nth-check": "^2.0.1" } }, "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw=="],
@@ -238,6 +250,8 @@
"domutils": ["domutils@3.2.2", "", { "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3" } }, "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw=="],
"drawflow": ["drawflow@0.0.60", "", {}, "sha512-UGj1+1DnWCVY6vJXBb6Ayt7KpPINBGqncVqpYDumVeBdIKxlBGn0tksp2yciVzQjkYsjFwMMDEdoVyWzUa2wkA=="],
"enhanced-resolve": ["enhanced-resolve@5.24.3", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.3.3" } }, "sha512-PwKooW9JUzh5chmYfHM3IQl5OkK2u2Nm011MgeZrss3JmFraUx/fqrf78kk8GUMYoibx/14MdwTl/1WKkG7TpQ=="],
"entities": ["entities@7.0.1", "", {}, "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA=="],
+14
View File
@@ -0,0 +1,14 @@
# Include INSIDE the existing component site's nginx server block.
# The existing location / continues to proxy the component app on its usual port.
location = /design-studio {
return 308 /design-studio/;
}
location /design-studio/ {
# Preserve the path and the external Host so same-origin validation works.
proxy_pass http://127.0.0.1:4320;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_read_timeout 60s;
client_max_body_size 2m;
}
+283 -191
View File
@@ -1,28 +1,30 @@
{
"name": "component-showcase",
"version": "0.8.7",
"version": "0.8.8",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "component-showcase",
"version": "0.8.7",
"version": "0.8.8",
"dependencies": {
"@wrnexus/core": "^0.8.16",
"@wrnexus/dev-server": "^0.8.66",
"@wrnexus/helpers": "^0.8.9",
"@wrnexus/plugin": "^0.8.9",
"@wrnexus/styles": "^0.8.26",
"@wrnexus/syntax": "^0.8.19",
"@wrnexus/ui": "^0.8.88"
"@wrnexus/core": "0.8.25",
"@wrnexus/design-studio": "0.1.0",
"@wrnexus/design-system": "0.1.0",
"@wrnexus/dev-server": "0.8.83",
"@wrnexus/helpers": "0.8.10",
"@wrnexus/plugin": "0.8.10",
"@wrnexus/styles": "0.8.27",
"@wrnexus/syntax": "0.8.20",
"@wrnexus/ui": "0.8.118"
},
"devDependencies": {
"@iconify-json/lucide": "^1.2.123",
"@iconify/tailwind4": "^1.2.3",
"@tailwindcss/cli": "^4.3.3",
"@types/bun": "^1.3.14",
"@wrnexus/cli": "^0.8.72",
"@wrnexus/compiler": "^0.8.30",
"@wrnexus/cli": "0.8.77",
"@wrnexus/compiler": "0.8.44",
"happy-dom": "^20.11.6",
"prettier": "^3.6.2",
"tailwindcss": "^4.3.3",
@@ -144,6 +146,12 @@
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
"node_modules/@kurkle/color": {
"version": "0.3.4",
"resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.4.tgz",
"integrity": "sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w==",
"license": "MIT"
},
"node_modules/@noble/hashes": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz",
@@ -1062,57 +1070,67 @@
"@types/node": "*"
}
},
"node_modules/@wrnexus/ai": {
"version": "0.8.10",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/ai/-/ai-0.8.10.tgz",
"integrity": "sha512-/vCpdkB4DpTRQ6g7UtwXLx95pWpBTfqvBukNjjRy5/L3hLiIp29n5RzPw+n3kRVhE8uGRCaKc9yUBxlhNKHUMA==",
"license": "MIT",
"engines": {
"bun": ">=1.3.0"
}
},
"node_modules/@wrnexus/authz": {
"version": "0.8.15",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/authz/-/authz-0.8.15.tgz",
"integrity": "sha512-ZV1cvHrOkephfjs/gzzcLkN4HEHSFWJVZVmfsvir/GZs/X7+ZQbPNYUQZV7SsRlyMkUxgTKMCiZ8Ym49eOBSQw==",
"version": "0.8.16",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/authz/-/authz-0.8.16.tgz",
"integrity": "sha512-bKs6X+nAU7w7m4Vvdf92/5ZjZ0MCPRxmCHvHAI376LtYlLVqqiDVRN2j1JWCkPdrvYaXeqsz6DMhPIKdKzS8Zg==",
"license": "MIT",
"dependencies": {
"@wrnexus/core": "^0.8.12",
"@wrnexus/db": "^0.8.20",
"@wrnexus/plugin": "^0.8.8"
"@wrnexus/core": "^0.8.25",
"@wrnexus/db": "^0.8.24",
"@wrnexus/plugin": "^0.8.10"
},
"engines": {
"bun": ">=1.3.0"
}
},
"node_modules/@wrnexus/cache": {
"version": "0.8.8",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/cache/-/cache-0.8.8.tgz",
"integrity": "sha512-GSV2myyy8xVeI8LdtJoIffW6fveCqB4WWN0CaodhVpI+4Y2aEmfJ6qwFikf34qI8Fy1+2ca9sKl5t1494kZBvw==",
"version": "0.8.9",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/cache/-/cache-0.8.9.tgz",
"integrity": "sha512-NftsbOsRtKCV77xxqNENIeUgcJjDgWuZL8KjxYJOdc6vVevoJ/fWU/EprqIuZ6YNtqm7TFFqMEENpb6GLvidGg==",
"license": "MIT",
"dependencies": {
"@wrnexus/core": "^0.8.9"
"@wrnexus/core": "^0.8.25"
},
"engines": {
"bun": ">=1.3.0"
}
},
"node_modules/@wrnexus/cli": {
"version": "0.8.72",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/cli/-/cli-0.8.72.tgz",
"integrity": "sha512-JeFsDMldcjiUFMhal11V/bfg/dNcG+OJh7+Bt6lmU3ojxTajvxV6pjLPp022hYDBZPu83jupiF4WZPwOLy/+Bw==",
"version": "0.8.77",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/cli/-/cli-0.8.77.tgz",
"integrity": "sha512-zFkifdFVwkcja9H8ctEZMPD5khBqmhp32yqSGjBvJnfuFCBdaRB9U5uCkqBbPCQUELrqTvCG2lafvQaptBo8xQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@wrnexus/authz": "^0.8.15",
"@wrnexus/compiler": "^0.8.30",
"@wrnexus/core": "^0.8.16",
"@wrnexus/csr": "^0.8.41",
"@wrnexus/db": "^0.8.23",
"@wrnexus/dev-server": "^0.8.66",
"@wrnexus/i18n": "^0.8.12",
"@wrnexus/mcp": "^0.8.8",
"@wrnexus/playground": "^0.8.8",
"@wrnexus/plugin": "^0.8.9",
"@wrnexus/react": "^0.8.9",
"@wrnexus/router": "^0.8.10",
"@wrnexus/security": "^0.8.9",
"@wrnexus/styles": "^0.8.25",
"@wrnexus/syntax": "^0.8.19",
"@wrnexus/typecheck": "^0.8.17",
"@wrnexus/ui": "^0.8.85",
"@wrnexus/validation": "^0.8.13",
"@wrnexus/authz": "^0.8.16",
"@wrnexus/compiler": "^0.8.44",
"@wrnexus/core": "^0.8.25",
"@wrnexus/csr": "^0.8.74",
"@wrnexus/db": "^0.8.24",
"@wrnexus/design-system": "^0.1.0",
"@wrnexus/dev-server": "^0.8.83",
"@wrnexus/i18n": "^0.8.13",
"@wrnexus/mcp": "^0.8.9",
"@wrnexus/playground": "^0.8.9",
"@wrnexus/plugin": "^0.8.10",
"@wrnexus/react": "^0.8.10",
"@wrnexus/router": "^0.8.11",
"@wrnexus/security": "^0.8.10",
"@wrnexus/styles": "^0.8.27",
"@wrnexus/syntax": "^0.8.20",
"@wrnexus/typecheck": "^0.8.18",
"@wrnexus/ui": "^0.8.118",
"@wrnexus/validation": "^0.8.14",
"selfsigned": "^5.5.0"
},
"bin": {
@@ -1123,33 +1141,33 @@
}
},
"node_modules/@wrnexus/compiler": {
"version": "0.8.30",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/compiler/-/compiler-0.8.30.tgz",
"integrity": "sha512-zsxqcIMOzXxX98z6RFffwQUa6VuniOqGZO/vxDdOJiyJ8RTs7gOk8dsBhA6MTLQ1fafPxJPV3zkGotKXOuxhCQ==",
"version": "0.8.44",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/compiler/-/compiler-0.8.44.tgz",
"integrity": "sha512-TJ3qPfD+2VsmpuVXgA6CUIlv2fqU2tW8xrIvHUFkGYJpVzF5jbSBUsoHNDfCT9/t5gw3CGazJnPqgzdcIm5XCg==",
"license": "MIT",
"dependencies": {
"@wrnexus/csr": "^0.8.41",
"@wrnexus/store": "^0.8.12",
"@wrnexus/syntax": "^0.8.19",
"@wrnexus/validation": "^0.8.13"
"@wrnexus/csr": "^0.8.74",
"@wrnexus/store": "^0.8.13",
"@wrnexus/syntax": "^0.8.20",
"@wrnexus/validation": "^0.8.14"
},
"engines": {
"bun": ">=1.3.0"
}
},
"node_modules/@wrnexus/core": {
"version": "0.8.16",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/core/-/core-0.8.16.tgz",
"integrity": "sha512-lTNigmTpJsgQnB95xMhalJ6Xbp/QBUf9J0MM4cuiecZ1DQLpaSgGC12Sn7FIC46rTU4w8878XJXlVWDCabe16Q==",
"version": "0.8.25",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/core/-/core-0.8.25.tgz",
"integrity": "sha512-od4TyDIKoX0RhjTDq+1HJ5fGQPID04Ao+BvWEkJU0beWRbXLZ6u5iRsh58+h/T2so8NSI9sW4rorC4N+BSMaqQ==",
"license": "MIT",
"engines": {
"bun": ">=1.3.0"
}
},
"node_modules/@wrnexus/csr": {
"version": "0.8.43",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/csr/-/csr-0.8.43.tgz",
"integrity": "sha512-czmxeLxvNvD7XjU3TufFBGMzuDWpNB0qpYbmbiARB7l6rslBw3+GuBWf2U5k4DH6oYiN/DGD6Jj+/G3bEh6ARw==",
"version": "0.8.74",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/csr/-/csr-0.8.74.tgz",
"integrity": "sha512-hqU7zqWRlkiOxJ8Ke9YidqwRN/CvmvozsK24XPsnlo7zt1IpNma0Woo9J5ZnO3MO9ihVU4sa8tmg61ucKHFFpQ==",
"license": "MIT",
"dependencies": {
"@wrnexus/core": "^0.8.12"
@@ -1159,101 +1177,132 @@
}
},
"node_modules/@wrnexus/db": {
"version": "0.8.23",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/db/-/db-0.8.23.tgz",
"integrity": "sha512-ncZlvclHW98Enah9wlHOf9+StoVGLrCOCVBAOEFdZKV91vKnYDltcFlmG7i7crndN37kayyb319Wiwol8Hmhyg==",
"version": "0.8.24",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/db/-/db-0.8.24.tgz",
"integrity": "sha512-zLT7e+C1nWhYs3BnqEjEO0QSli0JNl5sSnSHObjSX0C+wty30ASWD1WyBnfu9xFjOFn1eucZGthzo1xdGGQ1TQ==",
"license": "MIT",
"engines": {
"bun": ">=1.3.0"
}
},
"node_modules/@wrnexus/design-studio": {
"version": "0.1.0",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/design-studio/-/design-studio-0.1.0.tgz",
"integrity": "sha512-HeY3zG45oEvsLy1my9nCgKHb11ip9eTthhp/bzeOIXEn8vk71pRhqdgrltEwn2vFKIlKuPBQlA4xftmLDhSWTQ==",
"license": "MIT",
"dependencies": {
"@wrnexus/ai": "^0.8.10",
"@wrnexus/compiler": "^0.8.44",
"@wrnexus/core": "^0.8.25",
"@wrnexus/csr": "^0.8.74",
"@wrnexus/design-system": "^0.1.0",
"@wrnexus/ssr": "^0.8.20",
"@wrnexus/styles": "^0.8.27",
"@wrnexus/ui": "^0.8.118"
},
"bin": {
"wrnexus-design-studio": "dist/cli.js"
},
"engines": {
"bun": ">=1.3.0"
}
},
"node_modules/@wrnexus/design-system": {
"version": "0.1.0",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/design-system/-/design-system-0.1.0.tgz",
"integrity": "sha512-gNH/B+kYYZy+Pvlvl3gXoQZlTS6iP/teXct2MoClmsGp6M1vKa8IEptVXKs7po3E83zj5kSh3FIXwcBJHtZqLg==",
"license": "MIT",
"engines": {
"bun": ">=1.3.0"
}
},
"node_modules/@wrnexus/dev-server": {
"version": "0.8.66",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/dev-server/-/dev-server-0.8.66.tgz",
"integrity": "sha512-RBJWyUEGmOS6ZgIm5NvNPB4BVhVIpGFEEf4NSLDKJtp/Z5K2+G44KbRhZaaYvl6F4IEZM2Zg5x+ZAX+o5XB34w==",
"version": "0.8.83",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/dev-server/-/dev-server-0.8.83.tgz",
"integrity": "sha512-Ue6Q2KF7nZycvghRvWQBC9PA0DZ2aE+8fC3FaIFMkbID9HLK64Xe+MgMnLDJvQ7mlBJlC+9Ztj8yOYqSavtq1g==",
"license": "MIT",
"dependencies": {
"@wrnexus/authz": "^0.8.15",
"@wrnexus/cache": "^0.8.8",
"@wrnexus/compiler": "^0.8.30",
"@wrnexus/core": "^0.8.16",
"@wrnexus/csr": "^0.8.41",
"@wrnexus/db": "^0.8.23",
"@wrnexus/dev-toolbar": "^0.8.18",
"@wrnexus/i18n": "^0.8.12",
"@wrnexus/observability": "^0.8.8",
"@wrnexus/plugin": "^0.8.9",
"@wrnexus/pubsub": "^0.8.9",
"@wrnexus/pwa": "^0.8.12",
"@wrnexus/queue": "^0.8.14",
"@wrnexus/react": "^0.8.9",
"@wrnexus/router": "^0.8.10",
"@wrnexus/rpc": "^0.8.10",
"@wrnexus/security": "^0.8.9",
"@wrnexus/ssr": "^0.8.12",
"@wrnexus/store": "^0.8.12",
"@wrnexus/styles": "^0.8.23",
"@wrnexus/ui": "^0.8.84",
"@wrnexus/uploader": "^0.8.13",
"@wrnexus/validation": "^0.8.13"
"@wrnexus/authz": "^0.8.16",
"@wrnexus/cache": "^0.8.9",
"@wrnexus/compiler": "^0.8.44",
"@wrnexus/core": "^0.8.25",
"@wrnexus/csr": "^0.8.74",
"@wrnexus/db": "^0.8.24",
"@wrnexus/dev-toolbar": "^0.8.19",
"@wrnexus/i18n": "^0.8.13",
"@wrnexus/observability": "^0.8.9",
"@wrnexus/plugin": "^0.8.10",
"@wrnexus/pubsub": "^0.8.10",
"@wrnexus/pwa": "^0.8.13",
"@wrnexus/queue": "^0.8.15",
"@wrnexus/react": "^0.8.10",
"@wrnexus/router": "^0.8.11",
"@wrnexus/rpc": "^0.8.11",
"@wrnexus/security": "^0.8.10",
"@wrnexus/ssr": "^0.8.20",
"@wrnexus/store": "^0.8.13",
"@wrnexus/styles": "^0.8.27",
"@wrnexus/ui": "^0.8.118",
"@wrnexus/uploader": "^0.8.14",
"@wrnexus/validation": "^0.8.14"
},
"engines": {
"bun": ">=1.3.0"
}
},
"node_modules/@wrnexus/dev-toolbar": {
"version": "0.8.18",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/dev-toolbar/-/dev-toolbar-0.8.18.tgz",
"integrity": "sha512-7mj/FLIhLjx/DxH/gUlYwZqm63o/rcwH/0K/K6Efxvu9zfM5OyAh2w3L2eDWI9asK5foZkit8cKMUXVgmqHkcA==",
"version": "0.8.19",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/dev-toolbar/-/dev-toolbar-0.8.19.tgz",
"integrity": "sha512-Rfl94o7Tkd9KpwB7RO13DPm7vrqSjaHE5AFyiNL9ypKEXWJhvQf6yvQ6NvlU0gy8j119Fgqg+zBUkVN16QZVMA==",
"license": "MIT",
"engines": {
"bun": ">=1.3.0"
}
},
"node_modules/@wrnexus/helpers": {
"version": "0.8.9",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/helpers/-/helpers-0.8.9.tgz",
"integrity": "sha512-EzT9LSZJXIAIm2fO62BMbPJOnrloC1lujW+5UNsSd4kj44mBt6WMpBwaCSDGUcVy2/b7GKXlgBnUVZtIIGn0gw==",
"version": "0.8.10",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/helpers/-/helpers-0.8.10.tgz",
"integrity": "sha512-uwH83Mc0qqfE2eEYu5NNMYhhGB4xvUd2WPaY3B7RlV7RwR/SXNcmr0Ei76KPNhYWzhLO6bx5bWDlFuWENm1BoQ==",
"license": "MIT",
"dependencies": {
"@wrnexus/authz": "^0.8.14",
"@wrnexus/core": "^0.8.12",
"@wrnexus/db": "^0.8.20"
"@wrnexus/authz": "^0.8.16",
"@wrnexus/core": "^0.8.25",
"@wrnexus/db": "^0.8.24"
},
"engines": {
"bun": ">=1.3.0"
}
},
"node_modules/@wrnexus/i18n": {
"version": "0.8.12",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/i18n/-/i18n-0.8.12.tgz",
"integrity": "sha512-pgDJZpS8qB3tz+FMY+CNUF7AZXJVRFWbFDSHk+QMeUAwkU7JbNDxwmKioa6QU50F6C0SUMbfVwDR3kBXZKBflQ==",
"version": "0.8.13",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/i18n/-/i18n-0.8.13.tgz",
"integrity": "sha512-Go4JT+mc/SYnqWiv0ha+7/NLLPY/1HVFbCz8m2oLwtYKMrsZtn62Ows4uW54fzTY3fp8RkaVxDgkiC2p2jA1tw==",
"license": "MIT",
"dependencies": {
"@wrnexus/core": "^0.8.9",
"@wrnexus/plugin": "^0.8.8",
"@wrnexus/ui": "^0.8.19"
"@wrnexus/core": "^0.8.25",
"@wrnexus/plugin": "^0.8.10",
"@wrnexus/ui": "^0.8.118"
},
"engines": {
"bun": ">=1.3.0"
}
},
"node_modules/@wrnexus/jwt": {
"version": "0.8.9",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/jwt/-/jwt-0.8.9.tgz",
"integrity": "sha512-LcjXLdDp8pnJ3F6dDGlB3COlvg7jVBIZe+UnF48i7Hy12gHZu0Rbv/iBn9w203tpzT2EmcpGtMyI/J+uLQUeVg==",
"version": "0.8.10",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/jwt/-/jwt-0.8.10.tgz",
"integrity": "sha512-axXx1aCrIgpNhJyreKDQ78IlqGH+3AeKtfEW+/pzPFUXU03DU/YdCasK+WcZYYAQPPcZnegJA9MP9cYZYAFBCQ==",
"license": "MIT",
"dependencies": {
"@wrnexus/core": "^0.8.9"
"@wrnexus/core": "^0.8.25"
},
"engines": {
"bun": ">=1.3.0"
}
},
"node_modules/@wrnexus/mcp": {
"version": "0.8.8",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/mcp/-/mcp-0.8.8.tgz",
"integrity": "sha512-E4Rz03RVjzyjTdwL9d2zzMKLIkyTw1DMcwiRrdAcAEk6/HYJr4rnttiIGcw1lu58ptrLM/lUeqYWEWV+SyDXcQ==",
"version": "0.8.9",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/mcp/-/mcp-0.8.9.tgz",
"integrity": "sha512-OVSL2ZZeTh6pwuQiWK4gjTLDVfzu4INuf5PvMjyynzphXwsFWpL5m8BvVD4or4R9Jvm/R8WAhHIO8gLWZHF1oA==",
"dev": true,
"license": "MIT",
"bin": {
@@ -1261,188 +1310,209 @@
},
"engines": {
"bun": ">=1.3.0"
},
"peerDependencies": {
"@wrnexus/design-studio": "^0.1.0"
},
"peerDependenciesMeta": {
"@wrnexus/design-studio": {
"optional": true
}
}
},
"node_modules/@wrnexus/observability": {
"version": "0.8.8",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/observability/-/observability-0.8.8.tgz",
"integrity": "sha512-P7R4IYm7o6OfP1TmQ6L537DAOMH5WbC74TP4rw/Stwx8RxS/ORYPWw0mGB8f+1eamOV40Y5U4E04nmf3Tugj0Q==",
"version": "0.8.9",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/observability/-/observability-0.8.9.tgz",
"integrity": "sha512-f+kUNBATorCxKl04HsNuQi7o8pOgyW8qpfljWsFgauIdYxtTDFSxCERZIlprHyvin5l5ffAKFZcXeSutGqiPgQ==",
"license": "MIT",
"dependencies": {
"@wrnexus/core": "^0.8.9"
"@wrnexus/core": "^0.8.25"
},
"engines": {
"bun": ">=1.3.0"
}
},
"node_modules/@wrnexus/playground": {
"version": "0.8.8",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/playground/-/playground-0.8.8.tgz",
"integrity": "sha512-FpQ2n81GWSJSc0LccH6zDYm0pfdUk54LdDYma0Y72pyLfRjSY0ymQJcCr6Jp/EE5iBIhRowD6ag7vd26h27pZA==",
"version": "0.8.9",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/playground/-/playground-0.8.9.tgz",
"integrity": "sha512-hQCmKoi6gthyYLZDtvcDJFwq5THuxIWDijltDWTDOe9Gy7WdVn9UhrRVEFFYZ6VLtBRXAxnzlGb7eqJAMBKTaA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@wrnexus/compiler": "^0.8.10",
"@wrnexus/syntax": "^0.8.9"
"@wrnexus/compiler": "^0.8.44",
"@wrnexus/syntax": "^0.8.20"
},
"engines": {
"bun": ">=1.3.0"
}
},
"node_modules/@wrnexus/plugin": {
"version": "0.8.9",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/plugin/-/plugin-0.8.9.tgz",
"integrity": "sha512-XpkQL4/MpiNxoNcH1l7dL5cYEu8HN54/b5bx6DBXWutU4tMrAjChtbJ+SsE2YrNve4uWVUhF8wPgsdBrJONOQQ==",
"version": "0.8.10",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/plugin/-/plugin-0.8.10.tgz",
"integrity": "sha512-YVSLW8Lzq3/eFzAOj9B2A6ngFvdm2jmzSCEd2tI491rGqLbQWyFx3NzCuN/CnAZOA3kyHE+W4oiG6/3cyWWZsg==",
"license": "MIT",
"dependencies": {
"@wrnexus/syntax": "^0.8.19"
"@wrnexus/syntax": "^0.8.20"
},
"engines": {
"bun": ">=1.3.0"
}
},
"node_modules/@wrnexus/pubsub": {
"version": "0.8.9",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/pubsub/-/pubsub-0.8.9.tgz",
"integrity": "sha512-Z696WHuzJsPJvkvz3aRcifiZEqHXSIzoH3ji/wPqBP+vqmKIiZ/WIzViSQ0j8QJgtHiiq1mo2d4GFxsfdAPbqg==",
"version": "0.8.10",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/pubsub/-/pubsub-0.8.10.tgz",
"integrity": "sha512-X0ZEEvcSjUqvNT49vyYTmxgtEiQl6l8gFPfkbWWixsvAGQO55QGjZCvtUu/R0ItJ+1an45DKx9R4Z6K7ppqcUQ==",
"license": "MIT",
"dependencies": {
"@wrnexus/core": "^0.8.9",
"@wrnexus/rpc": "^0.8.9"
"@wrnexus/core": "^0.8.25",
"@wrnexus/rpc": "^0.8.11"
},
"engines": {
"bun": ">=1.3.0"
}
},
"node_modules/@wrnexus/pwa": {
"version": "0.8.12",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/pwa/-/pwa-0.8.12.tgz",
"integrity": "sha512-XI5wgn+vbPcSbAt3EsqnrPjkx2cd/Zpo3xy2deawuU5k7irkRImPNUWvtjkTar5GaNedVvuZQAhXLghb9p/GQQ==",
"version": "0.8.13",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/pwa/-/pwa-0.8.13.tgz",
"integrity": "sha512-u4D8jfI5ZHJbZrOTfeEJ9CTq+wCTqJ7ZjoRlTddf1RnAV/w8d6Vg72KDy6ApdoNuiJMqHRu44nqK053UyP00Sw==",
"license": "MIT",
"engines": {
"bun": ">=1.3.0"
}
},
"node_modules/@wrnexus/queue": {
"version": "0.8.14",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/queue/-/queue-0.8.14.tgz",
"integrity": "sha512-uulbyU1AF3gnfylmlFMIoBjAKgAgHsHg+FfEmLtoYwsaQ+JtMNk5PEZ/GUUBxEmK9ZbEAdgBAxgEX69E7ne9aA==",
"version": "0.8.15",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/queue/-/queue-0.8.15.tgz",
"integrity": "sha512-xJPZUqxYRMEgrgPIZoaZRMDWwwB8rUu0mrizNAGoZIwz1BzPsdVJaXOhsFvZd/mkHgk1CupxYXMNHuYA2pRGDg==",
"license": "MIT",
"dependencies": {
"@wrnexus/core": "^0.8.12",
"@wrnexus/db": "^0.8.20",
"@wrnexus/rpc": "^0.8.10"
"@wrnexus/core": "^0.8.25",
"@wrnexus/db": "^0.8.24",
"@wrnexus/rpc": "^0.8.11"
},
"engines": {
"bun": ">=1.3.0"
}
},
"node_modules/@wrnexus/react": {
"version": "0.8.9",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/react/-/react-0.8.9.tgz",
"integrity": "sha512-031RC/EBF1nzSeiwo2gXhOJ+xMLRtPUniN612ZVzj+pqGdn1J8I8vajZwRYKYC2xAVdCiB/EGoZ3FQaT75h8qw==",
"version": "0.8.10",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/react/-/react-0.8.10.tgz",
"integrity": "sha512-n5mdbb7ZWxOylL4I28GCEjLSFArPLNB8pCEIT3CxYXQQXkHgGXNS+++ls6R1XwnTrGLUJfVECpzRmf6mfeszUQ==",
"license": "MIT",
"dependencies": {
"@wrnexus/store": "^0.8.8"
"@wrnexus/store": "^0.8.13"
},
"engines": {
"bun": ">=1.3.0"
},
"peerDependencies": {
"react": "^19.0.0",
"react-dom": "^19.0.0"
},
"peerDependenciesMeta": {
"react": {
"optional": true
},
"react-dom": {
"optional": true
}
}
},
"node_modules/@wrnexus/router": {
"version": "0.8.10",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/router/-/router-0.8.10.tgz",
"integrity": "sha512-zh+h+VDNshSsh2iryqbOCWOhcIbKXg58iWkHz3wKNovlWT0uAgLhmea6IHsiApI8RC/VPw4TAmAhfkaK1c4BBA==",
"version": "0.8.11",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/router/-/router-0.8.11.tgz",
"integrity": "sha512-9hry5s0GQ0RdBXWue3I6JBijZMHcO+7J9oJnKqwPD2zScHdmU8ooJ4LyuI9kqf9Wc22Zl9Whgp/OjxGMa8aRtw==",
"license": "MIT",
"dependencies": {
"@wrnexus/compiler": "^0.8.17",
"@wrnexus/core": "^0.8.12"
"@wrnexus/compiler": "^0.8.44",
"@wrnexus/core": "^0.8.25"
},
"engines": {
"bun": ">=1.3.0"
}
},
"node_modules/@wrnexus/rpc": {
"version": "0.8.10",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/rpc/-/rpc-0.8.10.tgz",
"integrity": "sha512-KbfSxEe0D0ZiM1CckxiEVIEBSzYRYb3iEJYyJnT8DqlrEpos1hCwT22XnTMC3ldsCAusoUPO5gTXMBXL9qMKDQ==",
"version": "0.8.11",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/rpc/-/rpc-0.8.11.tgz",
"integrity": "sha512-SKxM0ACMsz3MQ7J0tYam2ZlE6WI3immFgak/bxtdwarMM6CVV6t3zxq/zw5EGfeWuCQxmTefOpvaTuhvzgKf5A==",
"license": "MIT",
"dependencies": {
"@wrnexus/core": "^0.8.9",
"@wrnexus/helpers": "^0.8.8",
"@wrnexus/jwt": "^0.8.9",
"@wrnexus/validation": "^0.8.10"
"@wrnexus/core": "^0.8.25",
"@wrnexus/helpers": "^0.8.10",
"@wrnexus/jwt": "^0.8.10",
"@wrnexus/validation": "^0.8.14"
},
"engines": {
"bun": ">=1.3.0"
}
},
"node_modules/@wrnexus/security": {
"version": "0.8.9",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/security/-/security-0.8.9.tgz",
"integrity": "sha512-dgz2fYwiw7uhBdsMuLqlPQaqajJx1McTjAhx8Pp1lf8gddsXm+Dnmri/1LXSbPwuSpWB7gsNq326JlVICfipVQ==",
"version": "0.8.10",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/security/-/security-0.8.10.tgz",
"integrity": "sha512-DRPI1TpMbVNtx91jnsIHN+ONvNs6RYKW5hot8Gez6y/XRliksAQAv4qPlW3V/Jctzsfue7Bz0qhERtqcnUzKPw==",
"license": "MIT",
"dependencies": {
"@wrnexus/core": "^0.8.11"
"@wrnexus/core": "^0.8.25"
},
"engines": {
"bun": ">=1.3.0"
}
},
"node_modules/@wrnexus/ssr": {
"version": "0.8.12",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/ssr/-/ssr-0.8.12.tgz",
"integrity": "sha512-fPoxMfnlwuUs6syJ6LMjqzxIKGsghQ3UCKjSFkRXlvdwdPpWRSxW0g0+jJF66/OTyCo2kB0dwMRGVLhICLgvLw==",
"version": "0.8.20",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/ssr/-/ssr-0.8.20.tgz",
"integrity": "sha512-0+I9C9Mjtpk8IeOfU+TIPo4/Wb1r3TC+xZBytj0v1Sper8IWSGw0At6opbJMnw5PPERnsQC0XJDhcSVlj2Wbuw==",
"license": "MIT",
"dependencies": {
"@wrnexus/core": "^0.8.16",
"@wrnexus/security": "^0.8.9",
"@wrnexus/store": "^0.8.12"
"@wrnexus/core": "^0.8.25",
"@wrnexus/security": "^0.8.10",
"@wrnexus/store": "^0.8.13"
},
"engines": {
"bun": ">=1.3.0"
}
},
"node_modules/@wrnexus/store": {
"version": "0.8.12",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/store/-/store-0.8.12.tgz",
"integrity": "sha512-5AiJXZ6AFT2eshp21JEyeHlmBgHuxyeRslN6YZiIvUfoO4Dre3VtR4pI+hN3lOGloLXwXBUfEMm2mgGsXS36Kg==",
"version": "0.8.13",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/store/-/store-0.8.13.tgz",
"integrity": "sha512-EHfjbs3qcVVFA5QkLDubH8bBdVWHAinx+5GYeo7asYSs/4qcfd6K0X0bsXp73FVm3CHgGeN9I+Ih6bNJmAEEWQ==",
"license": "MIT",
"engines": {
"bun": ">=1.3.0"
}
},
"node_modules/@wrnexus/styles": {
"version": "0.8.26",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/styles/-/styles-0.8.26.tgz",
"integrity": "sha512-B1FgQYks6S9SohlWjDkRabbzAAW9IIKbR5rHrdXegr6QY3nQMtJYPMG8xUVMTpQ8gRL+GODtuhDYPHD/igHuPg==",
"version": "0.8.27",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/styles/-/styles-0.8.27.tgz",
"integrity": "sha512-2DTZycU9LVaEn5/7ZsV87LDgDcm1fht6MHXp+alTBmlmkJ2tjeJnJm2wiMydStWKjf8E3AKAhZWg/3f2wOGi1g==",
"license": "MIT",
"dependencies": {
"@wrnexus/core": "^0.8.16",
"@wrnexus/plugin": "^0.8.9",
"@wrnexus/uploader": "^0.8.13"
"@wrnexus/core": "^0.8.25",
"@wrnexus/design-system": "^0.1.0",
"@wrnexus/plugin": "^0.8.10",
"@wrnexus/uploader": "^0.8.14"
},
"engines": {
"bun": ">=1.3.0"
}
},
"node_modules/@wrnexus/syntax": {
"version": "0.8.19",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/syntax/-/syntax-0.8.19.tgz",
"integrity": "sha512-/OZ+Z/cdFmfqKeqCZZpmwN2ZRSITA2ByqmVjGVONtMRfxHBj99T5jB0be6qlxrmoK0cgntRxEe2JCS/d9h54YA==",
"version": "0.8.20",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/syntax/-/syntax-0.8.20.tgz",
"integrity": "sha512-vd3EQLjLeNnnlSRVUMY4m+VksKpUHfTla0eWSZ8N+GroEVDgYegHW79tWcRAlmCxPe/jrpUSGri6dZoty2b72A==",
"license": "MIT",
"engines": {
"bun": ">=1.3.0"
}
},
"node_modules/@wrnexus/typecheck": {
"version": "0.8.17",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/typecheck/-/typecheck-0.8.17.tgz",
"integrity": "sha512-sEvCraG7qudT61h0SbuccIegi37nVWW2B1+BjmPg6Zrtc0251lUozASOYMW2ntjiizASDXMTSnZvSJ36EJPflA==",
"version": "0.8.18",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/typecheck/-/typecheck-0.8.18.tgz",
"integrity": "sha512-oS5x6hUs6VUNEupDARzFTzXvvdRAV6l8nO3wi+5rdfeDIDSz/5QNeQfVwzJg7SDGVkuTVOHH8lqyiMtSW+8Nbg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@wrnexus/syntax": "^0.8.19",
"@wrnexus/syntax": "^0.8.20",
"typescript": "^6.0.3"
},
"engines": {
@@ -1464,40 +1534,44 @@
}
},
"node_modules/@wrnexus/ui": {
"version": "0.8.88",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/ui/-/ui-0.8.88.tgz",
"integrity": "sha512-C6q3c85tJm0Ajhgb8i+DYOWyICNxeXVsR3KbD5yP0rC2XS5Vj9TP72x7NPux798jGLpbOpSPRiIPUff7zAod7w==",
"version": "0.8.118",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/ui/-/ui-0.8.118.tgz",
"integrity": "sha512-a0RWv3P+Z0f19Pqvaq+mHcBrAYni1k8iXQKMf9r83rYp3m6V4e00Fahg661VcF4Y6o3SAn151YVTH3zrRwsaWw==",
"license": "MIT",
"dependencies": {
"@wrnexus/core": "^0.8.16"
"@wrnexus/core": "^0.8.25",
"@wrnexus/design-system": "^0.1.0",
"@wrnexus/plugin": "^0.8.10",
"chart.js": "^4.5.1",
"drawflow": "0.0.60"
},
"engines": {
"bun": ">=1.3.0"
}
},
"node_modules/@wrnexus/uploader": {
"version": "0.8.13",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/uploader/-/uploader-0.8.13.tgz",
"integrity": "sha512-Cfj5Iqtbk/ccXV/YXQ4I8v0GkcE7cFnzMEB33qy3DcWo4fA5ndiWU9CN4Ap1oysA5MWEmcCKuJlcTKdWLhiTvw==",
"version": "0.8.14",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/uploader/-/uploader-0.8.14.tgz",
"integrity": "sha512-LticgG17uYu65IYRNDGagtvjfdUNrVHR2drbv6r/J4pycNX6CcGGn0hbjZFPA1uSHfH/hp//hA+KTOcoE14aMQ==",
"license": "MIT",
"dependencies": {
"@wrnexus/core": "^0.8.12",
"@wrnexus/plugin": "^0.8.8",
"@wrnexus/ui": "^0.8.23"
"@wrnexus/core": "^0.8.25",
"@wrnexus/plugin": "^0.8.10",
"@wrnexus/ui": "^0.8.118"
},
"engines": {
"bun": ">=1.3.0"
}
},
"node_modules/@wrnexus/validation": {
"version": "0.8.13",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/validation/-/validation-0.8.13.tgz",
"integrity": "sha512-ud9bzeSaOzbYnmu6pKEr5XbBT25FW+ROOI9iB0YJBc624juurslgHm2lpmpOu2WKUWulgktb/2vl9nsvtI8pSw==",
"version": "0.8.14",
"resolved": "https://registry.workroot.in/repository/npm/@wrnexus/validation/-/validation-0.8.14.tgz",
"integrity": "sha512-cdy8soKgKqGI3FP1wvbHsmdKAnDAzN6h0LcUadgjqz9sfp7RSsYuFBxEw/lkZiWkUbBbAuAaQ/sI7FgXWDnPxg==",
"license": "MIT",
"dependencies": {
"@wrnexus/core": "^0.8.12",
"@wrnexus/plugin": "^0.8.8",
"@wrnexus/ui": "^0.8.76"
"@wrnexus/core": "^0.8.25",
"@wrnexus/plugin": "^0.8.10",
"@wrnexus/ui": "^0.8.118"
},
"engines": {
"bun": ">=1.3.0"
@@ -1567,6 +1641,18 @@
"node": ">=6.0.0"
}
},
"node_modules/chart.js": {
"version": "4.5.1",
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.5.1.tgz",
"integrity": "sha512-GIjfiT9dbmHRiYi6Nl2yFCq7kkwdkp1W/lp2J99rX0yo9tgJGn3lKQATztIjb5tVtevcBtIdICNWqlq5+E8/Pw==",
"license": "MIT",
"dependencies": {
"@kurkle/color": "^0.3.0"
},
"engines": {
"pnpm": ">=8"
}
},
"node_modules/commander": {
"version": "11.1.0",
"dev": true,
@@ -1705,6 +1791,12 @@
"url": "https://github.com/fb55/domutils?sponsor=1"
}
},
"node_modules/drawflow": {
"version": "0.0.60",
"resolved": "https://registry.npmjs.org/drawflow/-/drawflow-0.0.60.tgz",
"integrity": "sha512-UGj1+1DnWCVY6vJXBb6Ayt7KpPINBGqncVqpYDumVeBdIKxlBGn0tksp2yciVzQjkYsjFwMMDEdoVyWzUa2wkA==",
"license": "MIT"
},
"node_modules/enhanced-resolve": {
"version": "5.24.3",
"dev": true,
+17 -13
View File
@@ -1,6 +1,6 @@
{
"name": "component-showcase",
"version": "0.8.7",
"version": "0.8.8",
"private": true,
"type": "module",
"scripts": {
@@ -10,35 +10,39 @@
"typecheck": "tsc --noEmit -p tsconfig.json",
"test": "bun test test",
"check": "bun run generate && bun run typecheck && bun run test && bun run build",
"start": "bun dist/server.js",
"start": "bun scripts/start.ts",
"production": "bun run build && bun run start",
"doctor": "wrnexus doctor .",
"config:explain": "wrnexus config . --explain",
"analyze": "wrnexus analyze .",
"update:preview": "wrnexus update . --dry-run"
"update:preview": "wrnexus update . --dry-run",
"start:site": "bun dist/server.js",
"studio": "bun scripts/studio.ts"
},
"dependencies": {
"@wrnexus/core": "^0.8.16",
"@wrnexus/dev-server": "^0.8.66",
"@wrnexus/helpers": "^0.8.9",
"@wrnexus/plugin": "^0.8.9",
"@wrnexus/styles": "^0.8.26",
"@wrnexus/syntax": "^0.8.19",
"@wrnexus/ui": "^0.8.88"
"@wrnexus/core": "0.8.25",
"@wrnexus/dev-server": "0.8.83",
"@wrnexus/helpers": "0.8.10",
"@wrnexus/plugin": "0.8.10",
"@wrnexus/styles": "0.8.27",
"@wrnexus/syntax": "0.8.20",
"@wrnexus/ui": "0.8.118",
"@wrnexus/design-studio": "0.1.0",
"@wrnexus/design-system": "0.1.0"
},
"devDependencies": {
"@iconify-json/lucide": "^1.2.123",
"@iconify/tailwind4": "^1.2.3",
"@tailwindcss/cli": "^4.3.3",
"@types/bun": "^1.3.14",
"@wrnexus/cli": "^0.8.72",
"@wrnexus/compiler": "^0.8.30",
"@wrnexus/cli": "0.8.77",
"@wrnexus/compiler": "0.8.44",
"happy-dom": "^20.11.6",
"prettier": "^3.6.2",
"tailwindcss": "^4.3.3",
"typescript": "^5.5.0"
},
"wrnexus": {
"version": "0.8.72"
"version": "0.8.77"
}
}
+17 -4
View File
@@ -153,7 +153,9 @@
declarations.push(` state ${name} = ${JSON.stringify(data, null, 2)}`);
attributes.push(`${name}="{${name}}"`);
continue;
} catch { /* Keep invalid JSON visible for correction. */ }
} catch {
/* Keep invalid JSON visible for correction. */
}
}
if (field instanceof HTMLInputElement && field.type === "checkbox") {
attributes.push(`${name}="${field.checked}"`);
@@ -172,7 +174,8 @@
let source = hasSlot
? `${opening}>\n <!-- Add slot content here -->\n</${tag}>`
: `${opening}\n/>`;
if (declarations.length) source = `page ${component.replace(/[^A-Za-z0-9]/g, "")}Example {\n${declarations.join("\n")}\n view {\n${source}\n }\n}`;
if (declarations.length)
source = `page ${component.replace(/[^A-Za-z0-9]/g, "")}Example {\n${declarations.join("\n")}\n view {\n${source}\n }\n}`;
writeCode(code, source);
}
@@ -335,7 +338,10 @@
const initializedCode = new WeakSet();
function bindPlaygroundEvents(root = document) {
for (const playground of root.querySelectorAll?.(SELECTOR) ?? []) {
if (!initializedCode.has(playground)) { initializedCode.add(playground); updateCode(playground); }
if (!initializedCode.has(playground)) {
initializedCode.add(playground);
updateCode(playground);
}
const outputNames = (playground.getAttribute("data-playground-events") || "")
.split(",")
.map((name) => name.trim())
@@ -413,7 +419,14 @@
const copyTarget = event.target.closest?.("[data-copy-target]");
if (copyTarget) {
const target = document.querySelector(copyTarget.dataset.copyTarget);
if (target) { try { await navigator.clipboard.writeText(target.textContent || ""); copyTarget.textContent = "Copied"; } catch { copyTarget.textContent = "Select code to copy"; } }
if (target) {
try {
await navigator.clipboard.writeText(target.textContent || "");
copyTarget.textContent = "Copied";
} catch {
copyTarget.textContent = "Select code to copy";
}
}
return;
}
const copyText = event.target.closest?.("[data-copy-text]");
+183 -49
View File
@@ -1,67 +1,201 @@
import { existsSync, unlinkSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
import {
existsSync,
unlinkSync,
mkdirSync,
readFileSync,
readdirSync,
writeFileSync,
} from "node:fs";
import { join } from "node:path";
export async function generateCatalogPages({ exampleRoot, pagesDir, blockComponents, componentMount, sourceSnippet, demoConfiguration, slugOf, displayName, escapeCode, escapeText, resetHoistedObjects, hoistedObjectStates }) {
const write = (path, text) => { mkdirSync(join(pagesDir, path.substring(0,path.lastIndexOf('/')) || '.'), {recursive:true}); writeFileSync(join(pagesDir,path), text); };
const codePanel = (source, id="example-source") => `<section class="example-code-panel"><header><h2>Copy this example</h2><button type="button" data-copy-target="#${id}">Copy code</button></header><pre><code id="${id}">${escapeCode(source)}</code></pre></section>`;
const page = (name,title,body) => `page ${name} {\n layout = "gallery"\n seo { title = "${title}" }\n view { ${body} }\n}\n`;
const cards = entries => `<div class="example-catalog">${entries.map(e=>`<a class="example-card" href="${e.href}"><div class="example-card__art"><span class="icon-[lucide--${e.icon}]" aria-hidden="true"></span></div><div><h2>${e.title}</h2><p>${e.description}</p><strong>Open example →</strong></div></a>`).join('')}</div>`;
export async function generateCatalogPages({
exampleRoot,
pagesDir,
blockComponents,
componentMount,
demoConfiguration,
slugOf,
displayName,
escapeCode,
resetHoistedObjects,
hoistedObjectStates,
}) {
const write = (path, text) => {
mkdirSync(join(pagesDir, path.substring(0, path.lastIndexOf("/")) || "."), { recursive: true });
writeFileSync(join(pagesDir, path), text);
};
const codePanel = (source, id = "example-source") =>
`<section class="example-code-panel"><header><h2>Copy this example</h2><button type="button" data-copy-target="#${id}">Copy code</button></header><pre><code id="${id}">${escapeCode(source)}</code></pre></section>`;
const page = (name, title, body) =>
`page ${name} {\n layout = "gallery"\n seo { title = "${title}" }\n view { ${body} }\n}\n`;
const cards = (entries) =>
`<div class="example-catalog">${entries.map((e) => `<a class="example-card" href="${e.href}"><div class="example-card__art"><span class="icon-[lucide--${e.icon}]" aria-hidden="true"></span></div><div><h2>${e.title}</h2><p>${e.description}</p><strong>Open example →</strong></div></a>`).join("")}</div>`;
const examples = [
{slug:'workspace',title:'Workspace overview',icon:'layout-dashboard',description:'A complete dashboard with navigation, metrics, and service cards.'},
{slug:'profile',title:'Profile & preferences',icon:'user-round',description:'A responsive settings form with grouped fields and save feedback.'},
{slug:'sign-in',title:'Sign in',icon:'log-in',description:'A focused authentication page with a compact form.'},
{slug:'scheduling',title:'Scheduling',icon:'calendar-days',description:'Date, date-and-time, and time controls in a practical form.'},
{slug:'custom-modal',title:'Custom modal',icon:'panels-top-left',description:'Open and close a fully controlled dialog from your own buttons.'},
{slug:'project-board',title:'Project workspace',icon:'list-checks',description:'Reorder priorities and write rich-text project updates.'},
{
slug: "workspace",
title: "Workspace overview",
icon: "layout-dashboard",
description: "A complete dashboard with navigation, metrics, and service cards.",
},
{
slug: "profile",
title: "Profile & preferences",
icon: "user-round",
description: "A responsive settings form with grouped fields and save feedback.",
},
{
slug: "sign-in",
title: "Sign in",
icon: "log-in",
description: "A focused authentication page with a compact form.",
},
{
slug: "scheduling",
title: "Scheduling",
icon: "calendar-days",
description: "Date, date-and-time, and time controls in a practical form.",
},
{
slug: "custom-modal",
title: "Custom modal",
icon: "panels-top-left",
description: "Open and close a fully controlled dialog from your own buttons.",
},
{
slug: "project-board",
title: "Project workspace",
icon: "list-checks",
description: "Reorder priorities and write rich-text project updates.",
},
];
const extra = {
scheduling:`page SchedulingExample {\n view { <main class="example-form-page" style="max-width:42rem;margin:3rem auto;padding:1.5rem;display:grid;gap:1.5rem"><h1>Schedule a meeting</h1><p>Choose the date and time that work for your team.</p><DatePicker label="Meeting date" name="date" /><DatePicker type="datetime-local" label="Send reminder" name="reminder" value="2026-09-20T09:30" /><TimePicker label="Start time" name="time" value="09:30" /></main> }\n}`,
'custom-modal':`page CustomModalExample {\n state dialogOpen: boolean = false\n view { <main class="example-form-page" style="max-width:42rem;margin:3rem auto;padding:1.5rem;display:grid;gap:1.5rem"><h1>Your own modal controls</h1><Button label="Invite a teammate" @click="dialogOpen = true" /><Modal open="{dialogOpen}" @close="dialogOpen = false" title="" description="" showFooter="true" cancelLabel="" confirmLabel=""><div data-slot="header"><h2>Invite a teammate</h2></div><Input label="Email address" type="email" name="invite-email" placeholder="name@company.com" /><div data-slot="footer"><Button label="Cancel" variant="secondary" @click="dialogOpen = false" /><Button label="Done" @click="dialogOpen = false" /></div></Modal></main> }\n}`,
'project-board':`page ProjectBoardExample {\n state tasks = [{label:"Review designs"},{label:"Build the dashboard"},{label:"Test accessibility"}]\n view { <main class="example-form-page" style="max-width:42rem;margin:3rem auto;padding:1.5rem;display:grid;gap:1.5rem"><h1>Project workspace</h1><DragAndDrop title="Priorities" description="Drag a row or use its arrow buttons." items="{tasks}" /><WysiwygEditor title="Team update" value="Share what you are working on this week." /></main> }\n}`,
scheduling: `page SchedulingExample {\n view { <main class="example-form-page" style="max-width:42rem;margin:3rem auto;padding:1.5rem;display:grid;gap:1.5rem"><h1>Schedule a meeting</h1><p>Choose the date and time that work for your team.</p><DatePicker label="Meeting date" name="date" /><DatePicker type="datetime-local" label="Send reminder" name="reminder" value="2026-09-20T09:30" /><TimePicker label="Start time" name="time" value="09:30" /></main> }\n}`,
"custom-modal": `page CustomModalExample {\n state dialogOpen: boolean = false\n view { <main class="example-form-page" style="max-width:42rem;margin:3rem auto;padding:1.5rem;display:grid;gap:1.5rem"><h1>Your own modal controls</h1><Button label="Invite a teammate" @click="dialogOpen = true" /><Modal open="{dialogOpen}" @close="dialogOpen = false" title="" description="" showFooter="true" cancelLabel="" confirmLabel=""><div data-slot="header"><h2>Invite a teammate</h2></div><Input label="Email address" type="email" name="invite-email" placeholder="name@company.com" /><div data-slot="footer"><Button label="Cancel" variant="secondary" @click="dialogOpen = false" /><Button label="Done" @click="dialogOpen = false" /></div></Modal></main> }\n}`,
"project-board": `page ProjectBoardExample {\n state tasks = [{label:"Review designs"},{label:"Build the dashboard"},{label:"Test accessibility"}]\n view { <main class="example-form-page" style="max-width:42rem;margin:3rem auto;padding:1.5rem;display:grid;gap:1.5rem"><h1>Project workspace</h1><DragAndDrop title="Priorities" description="Drag a row or use its arrow buttons." items="{tasks}" /><WysiwygEditor title="Team update" value="Share what you are working on this week." /></main> }\n}`,
};
for (const e of examples) { const old = join(pagesDir,'templates',e.slug+'.wrn'); if(existsSync(old)) unlinkSync(old); }
const css = readFileSync(join(exampleRoot,'app/styles/workspace-preview.css'),'utf8');
for(const e of examples) {
const source = extra[e.slug] || readFileSync(join(exampleRoot,'examples',e.slug+'.wrn'),'utf8');
const at = source.lastIndexOf('\n }');
let rendered;
if(at>=0) rendered = source.slice(0,at)+codePanel(source)+`<details class="example-code-panel"><summary>Page styles · copy with the example</summary><button type="button" data-copy-target="#example-styles">Copy CSS</button><pre><code id="example-styles">${escapeCode(css)}</code></pre></details>`+source.slice(at);
else rendered = source.replace(/}\s*}\s*$/,codePanel(source)+' } }');
rendered = rendered.replace(/\bview\s*\{/, 'view {\n<nav class="example-toolbar"><a href="/preview">← All examples</a><a href="#example-source">View code</a></nav>');
write(`preview/${e.slug}.wrn`, rendered);
for (const e of examples) {
const old = join(pagesDir, "templates", e.slug + ".wrn");
if (existsSync(old)) unlinkSync(old);
}
write('preview/index.wrn',page('PreviewIndex','Examples',`<header class="docs-intro"><span class="showcase-eyebrow">Ready to use</span><h1>Page examples</h1><p>Explore complete layouts, interact with the controls, and copy the source.</p></header>${cards(examples.map(e=>({...e,href:'/preview/'+e.slug})))}`));
const css = readFileSync(join(exampleRoot, "app/styles/workspace-preview.css"), "utf8");
for (const e of examples) {
const source =
extra[e.slug] || readFileSync(join(exampleRoot, "examples", e.slug + ".wrn"), "utf8");
const at = source.lastIndexOf("\n }");
let rendered;
if (at >= 0)
rendered =
source.slice(0, at) +
codePanel(source) +
`<details class="example-code-panel"><summary>Page styles · copy with the example</summary><button type="button" data-copy-target="#example-styles">Copy CSS</button><pre><code id="example-styles">${escapeCode(css)}</code></pre></details>` +
source.slice(at);
else rendered = source.replace(/}\s*}\s*$/, codePanel(source) + " } }");
rendered = rendered.replace(
/\bview\s*\{/,
'view {\n<nav class="example-toolbar"><a href="/preview">← All examples</a><a href="#example-source">View code</a></nav>',
);
write(`preview/${e.slug}.wrn`, rendered);
}
write(
"preview/index.wrn",
page(
"PreviewIndex",
"Examples",
`<header class="docs-intro"><span class="showcase-eyebrow">Ready to use</span><h1>Page examples</h1><p>Explore complete layouts, interact with the controls, and copy the source.</p></header>${cards(examples.map((e) => ({ ...e, href: "/preview/" + e.slug })))}`,
),
);
const templateGroups = [
{slug:'dashboards',title:'Dashboards & admin',icon:'layout-dashboard',description:'Analytics and account operations with meaningful metrics.',heading:'Workspace performance',body:`<MetricCard title="Active accounts" value="1,284" /><Chart title="Weekly activity" type="bar" data='[{"label":"Mon","value":24},{"label":"Tue","value":38},{"label":"Wed","value":52}]' showLegend="false" /><Card title="Team access" description="Manage roles and permissions for your workspace." actionLabel="Manage team" actionHref="/preview/profile" />`},
{slug:'commerce',title:'Commerce',icon:'shopping-bag',description:'A product collection with a working shopping bag.',heading:'Everyday essentials',body:`<p>Thoughtfully made tools for your desk.</p><div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,240px),1fr));gap:1.25rem"><Card title="Studio notebook" description="Dot grid · recycled paper" footer="$18"><Button label="Add notebook" @click="bag = bag + 1" /></Card><Card title="Desk organizer" description="Solid oak · natural finish" footer="$42"><Button label="Add organizer" @click="bag = bag + 1" /></Card><Card title="Travel tumbler" description="Insulated · 350 ml" footer="$24"><Button label="Add tumbler" @click="bag = bag + 1" /></Card></div><p role="status">Shopping bag: {bag} items</p><Button label="Clear bag" variant="secondary" @click="bag = 0" />`},
{slug:'marketing',title:'Marketing websites',icon:'sparkles',description:'A SaaS landing page with benefits, pricing, and a clear next step.',heading:'Make room for your best work.',body:`<p>One calm workspace for projects, notes, and the people behind them.</p><Button label="Explore the workspace" href="/preview/workspace" /><div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,240px),1fr));gap:1.25rem"><Card title="Plan together" description="Turn your next idea into clear, shared priorities." /><Card title="Stay focused" description="Keep tasks, notes, and decisions in one place." /><Card title="Grow naturally" description="Start with your team. Add more space when you need it." /></div><Card title="Team plan" description="Everything your team needs to get started." footer="$19 / member / month" actionLabel="Get started" actionHref="/preview/sign-in" />`},
{slug:'productivity',title:'Productivity',icon:'list-checks',description:'A planning workspace for priorities, deadlines, and notes.',heading:'Your week, in focus',body:`<DragAndDrop title="Priorities" items='[{"label":"Review the launch plan"},{"label":"Prepare customer interviews"},{"label":"Share the weekly update"}]' /><DatePicker label="Next milestone" name="milestone" /><WysiwygEditor title="Meeting notes" value="Capture decisions and next steps here." />`},
{
slug: "dashboards",
title: "Dashboards & admin",
icon: "layout-dashboard",
description: "Analytics and account operations with meaningful metrics.",
heading: "Workspace performance",
body: `<MetricCard title="Active accounts" value="1,284" /><Chart title="Weekly activity" type="bar" data='[{"label":"Mon","value":24},{"label":"Tue","value":38},{"label":"Wed","value":52}]' showLegend="false" /><Card title="Team access" description="Manage roles and permissions for your workspace." actionLabel="Manage team" actionHref="/preview/profile" />`,
},
{
slug: "commerce",
title: "Commerce",
icon: "shopping-bag",
description: "A product collection with a working shopping bag.",
heading: "Everyday essentials",
body: `<p>Thoughtfully made tools for your desk.</p><div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,240px),1fr));gap:1.25rem"><Card title="Studio notebook" description="Dot grid · recycled paper" footer="$18"><Button label="Add notebook" @click="bag = bag + 1" /></Card><Card title="Desk organizer" description="Solid oak · natural finish" footer="$42"><Button label="Add organizer" @click="bag = bag + 1" /></Card><Card title="Travel tumbler" description="Insulated · 350 ml" footer="$24"><Button label="Add tumbler" @click="bag = bag + 1" /></Card></div><p role="status">Shopping bag: {bag} items</p><Button label="Clear bag" variant="secondary" @click="bag = 0" />`,
},
{
slug: "marketing",
title: "Marketing websites",
icon: "sparkles",
description: "A SaaS landing page with benefits, pricing, and a clear next step.",
heading: "Make room for your best work.",
body: `<p>One calm workspace for projects, notes, and the people behind them.</p><Button label="Explore the workspace" href="/preview/workspace" /><div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,240px),1fr));gap:1.25rem"><Card title="Plan together" description="Turn your next idea into clear, shared priorities." /><Card title="Stay focused" description="Keep tasks, notes, and decisions in one place." /><Card title="Grow naturally" description="Start with your team. Add more space when you need it." /></div><Card title="Team plan" description="Everything your team needs to get started." footer="$19 / member / month" actionLabel="Get started" actionHref="/preview/sign-in" />`,
},
{
slug: "productivity",
title: "Productivity",
icon: "list-checks",
description: "A planning workspace for priorities, deadlines, and notes.",
heading: "Your week, in focus",
body: `<DragAndDrop title="Priorities" items='[{"label":"Review the launch plan"},{"label":"Prepare customer interviews"},{"label":"Share the weekly update"}]' /><DatePicker label="Next milestone" name="milestone" /><WysiwygEditor title="Meeting notes" value="Capture decisions and next steps here." />`,
},
];
write('templates.wrn',page('Templates','Templates',`<header class="docs-intro"><span class="showcase-eyebrow">Start a product</span><h1>Templates for your next idea</h1><p>Four starting points with complete layouts and copyable source. Examples demonstrate controls; templates combine them into a product page.</p></header>${cards(templateGroups.map(e=>({...e,href:'/templates/'+e.slug})))}`));
write(
"templates.wrn",
page(
"Templates",
"Templates",
`<header class="docs-intro"><span class="showcase-eyebrow">Start a product</span><h1>Templates for your next idea</h1><p>Four starting points with complete layouts and copyable source. Examples demonstrate controls; templates combine them into a product page.</p></header>${cards(templateGroups.map((e) => ({ ...e, href: "/templates/" + e.slug })))}`,
),
);
for (const t of templateGroups) {
const source = `page ${t.slug.replace(/-/g,'')}Template {
const source = `page ${t.slug.replace(/-/g, "")}Template {
state bag: number = 0
view { <main style="max-width:72rem;margin:3rem auto;padding:2rem;display:grid;gap:1.5rem"><h1>${t.heading}</h1>${t.body}</main> }
}`;
write(`templates/${t.slug}.wrn`, source.replace('view {', 'view {<nav class="example-toolbar"><a href="/templates">← All templates</a><a href="#example-source">View code</a></nav>').replace(/}\s*}\s*$/,codePanel(source)+' } }'));
write(
`templates/${t.slug}.wrn`,
source
.replace(
"view {",
'view {<nav class="example-toolbar"><a href="/templates">← All templates</a><a href="#example-source">View code</a></nav>',
)
.replace(/}\s*}\s*$/, codePanel(source) + " } }"),
);
}
const blockCards=[];
for(const c of blockComponents) {
const slug=slugOf(c.name); resetHoistedObjects();
const config=demoConfiguration(c,0);
const mount=componentMount(c,0,config);
const states=hoistedObjectStates();
const source=`page ${c.name}Example {${states}\n view {\n ${mount}\n }\n}`;
write(`blocks/${slug}.wrn`, `page ${c.name}Block {\n layout = "gallery"\n ${states}\n seo { title = "${displayName(c.name)} block" }\n view { <header class="docs-intro"><a href="/block-library">← All blocks</a><h1>${displayName(c.name)}</h1><p>A ready-to-use section. Copy the complete example below.</p></header><section class="block-live-preview">${mount}</section>${codePanel(source)} }\n}`);
blockCards.push({title:displayName(c.name),description:c.purpose || 'A complete reusable page section.',icon:'layout-template',href:'/blocks/'+slug});
const blockCards = [];
for (const c of blockComponents) {
const slug = slugOf(c.name);
resetHoistedObjects();
const config = demoConfiguration(c, 0);
const mount = componentMount(c, 0, config);
const states = hoistedObjectStates();
const source = `page ${c.name}Example {${states}\n view {\n ${mount}\n }\n}`;
write(
`blocks/${slug}.wrn`,
`page ${c.name}Block {\n layout = "gallery"\n ${states}\n seo { title = "${displayName(c.name)} block" }\n view { <header class="docs-intro"><a href="/block-library">← All blocks</a><h1>${displayName(c.name)}</h1><p>A ready-to-use section. Copy the complete example below.</p></header><section class="block-live-preview">${mount}</section>${codePanel(source)} }\n}`,
);
blockCards.push({
title: displayName(c.name),
description: c.purpose || "A complete reusable page section.",
icon: "layout-template",
href: "/blocks/" + slug,
});
}
write('block-library.wrn',page('BlockLibrary','UI blocks',`<header class="docs-intro"><span class="showcase-eyebrow">Composed sections</span><h1>Ready-to-use blocks</h1><p>Real sections with live previews and complete source code.</p></header>${cards(blockCards)}`));
write('blocks/index.wrn',page('BlocksIndex','UI blocks',cards(blockCards)));
write(
"block-library.wrn",
page(
"BlockLibrary",
"UI blocks",
`<header class="docs-intro"><span class="showcase-eyebrow">Composed sections</span><h1>Ready-to-use blocks</h1><p>Real sections with live previews and complete source code.</p></header>${cards(blockCards)}`,
),
);
write("blocks/index.wrn", page("BlocksIndex", "UI blocks", cards(blockCards)));
// Update internal guides to point to the moved block documentation.
for(const directory of [pagesDir,join(pagesDir,'components')]) for(const file of readdirSync(directory).filter(f=>f.endsWith('.wrn'))) {
const path=join(directory,file);let text=readFileSync(path,'utf8');
for(const c of blockComponents) text=text.replaceAll('/components/'+slugOf(c.name),'/blocks/'+slugOf(c.name));
if (text !== readFileSync(path,"utf8")) writeFileSync(path,text);
for (const directory of [pagesDir, join(pagesDir, "components")])
for (const file of readdirSync(directory).filter((f) => f.endsWith(".wrn"))) {
const path = join(directory, file);
let text = readFileSync(path, "utf8");
for (const c of blockComponents)
text = text.replaceAll("/components/" + slugOf(c.name), "/blocks/" + slugOf(c.name));
if (text !== readFileSync(path, "utf8")) writeFileSync(path, text);
}
}
File diff suppressed because it is too large. Load diff
+330 -24
View File
@@ -2873,7 +2873,10 @@ export const componentProfiles = {
},
),
],
options: { size: ["sm", "default", "lg"], variant: ["default", "soft", "raised", "outline", "minimal", "compact", "alternate"] },
options: {
size: ["sm", "default", "lg"],
variant: ["default", "soft", "raised", "outline", "minimal", "compact", "alternate"],
},
},
Typography: {
@@ -2958,28 +2961,280 @@ const genericEventDescriptions = {
toggle: "Fires when the component changes between open and closed or on and off states.",
};
componentProfiles.Card.demos.push(
standard("Image with footer", "A cover image, concise body, and separate footer.", {title:"Design your next chapter",description:"A practical guide to building thoughtful products.",imageSrc:"/showcase-images/green-hero.svg",imageAlt:"Green abstract cover",footer:"6 min read",actionLabel:"Read guide",actionHref:"#guide"}),
compact("Without a header", "Body content with an optional footer; no reserved heading space.", {title:"",description:"Your workspace is ready. Invite your teammates to get started.",footer:"Updated just now"}, {default:""}),
advanced("Image-only card", "A simple image surface without header or footer chrome.", {title:"",description:"",imageSrc:"/showcase-images/blue-mountain.svg",imageAlt:"Blue geometric landscape"}, {default:""}),
standard("Image with footer", "A cover image, concise body, and separate footer.", {
title: "Design your next chapter",
description: "A practical guide to building thoughtful products.",
imageSrc: "/showcase-images/green-hero.svg",
imageAlt: "Green abstract cover",
footer: "6 min read",
actionLabel: "Read guide",
actionHref: "#guide",
}),
compact(
"Without a header",
"Body content with an optional footer; no reserved heading space.",
{
title: "",
description: "Your workspace is ready. Invite your teammates to get started.",
footer: "Updated just now",
},
{ default: "" },
),
advanced(
"Image-only card",
"A simple image surface without header or footer chrome.",
{
title: "",
description: "",
imageSrc: "/showcase-images/blue-mountain.svg",
imageAlt: "Blue geometric landscape",
},
{ default: "" },
),
);
componentProfiles.Map = { demos:[
standard("OpenStreetMap", "A real interactive geographic map. Set latitude, longitude and zoomLevel; no API key is needed.", {title:"Bengaluru",description:"Pan and zoom to explore the city",provider:"openstreetmap",latitude:12.9716,longitude:77.5946,zoomLevel:13,imageSrc:"",items:[]}),
compact("Google Maps", "Pass your restricted Maps Embed API key and a place query to show Google Maps.", {title:"Google Maps",provider:"google",apiKey:"",query:"Bengaluru",imageSrc:"",items:[]}),
], playground:{title:"Bengaluru",description:"Interactive geographic map",provider:"openstreetmap",latitude:12.9716,longitude:77.5946,zoomLevel:13,imageSrc:"",items:[]}, options:{provider:["openstreetmap","google"]} };
componentProfiles.Rating = {demos:[standard("Whole stars", "Choose a rating from zero to five with step 1.",{title:"Rate your experience",value:3,step:1}),compact("Half stars", "Click a half star or use the precise slider and arrow keys.",{title:"Half-star rating",value:3.5,step:0.5}),advanced("Fine increments", "Use increments of 0.2 for a more precise rating.",{title:"Detailed score",value:4.2,step:0.2})]};
componentProfiles.LegendIndicator = {demos:[standard("Chart legend", "Toggle a series and handle @toggle to update your chart.",{title:"Traffic sources",description:"Select a source to toggle its visibility.",items:[{label:"Direct",color:"#8b5cf6",value:"42%"},{label:"Search",color:"#14b8a6",value:"35%"},{label:"Referral",color:"#f59e0b",value:"23%"}]})]};
componentProfiles.Chart = {demos:[standard("Bar chart", "Pass an array of label/value objects through data.",{title:"Weekly signups",type:"bar",data:[{label:"Mon",value:24},{label:"Tue",value:38},{label:"Wed",value:29},{label:"Thu",value:52},{label:"Fri",value:45}],items:[],showLegend:false}),compact("Line chart", "Use type=line to compare a trend over time.",{title:"Monthly revenue",type:"line",data:[{label:"Jan",value:20},{label:"Feb",value:35},{label:"Mar",value:28},{label:"Apr",value:55}],items:[],showLegend:false})],options:{type:["bar","line"]}};
componentProfiles.DatePicker = { demos:[
standard("Date picker", "An anchored calendar that does not move surrounding content.", {label:"Start date",name:"start-date",type:"date"}),
compact("Date and time", "Choose a calendar date and a time in one field.", {label:"Schedule for",name:"schedule",type:"datetime-local",value:"2026-09-20T09:30"}),
advanced("Disabled date", "A read-only scheduled date.", {label:"Scheduled date",readonly:true}),
], options:{type:["date","datetime-local"]} };
componentProfiles.TimePicker = { demos:[standard("Time picker", "Choose an hour and minute in an anchored panel.", {label:"Meeting time",name:"meeting-time",value:"09:30"})] };
componentProfiles.Map = {
demos: [
standard(
"OpenStreetMap",
"A real interactive geographic map. Set latitude, longitude and zoomLevel; no API key is needed.",
{
title: "Bengaluru",
description: "Pan and zoom to explore the city",
provider: "openstreetmap",
latitude: 12.9716,
longitude: 77.5946,
zoomLevel: 13,
imageSrc: "",
items: [],
},
),
compact(
"Google Maps",
"Pass your restricted Maps Embed API key and a place query to show Google Maps.",
{
title: "Google Maps",
provider: "google",
apiKey: "",
query: "Bengaluru",
imageSrc: "",
items: [],
},
),
],
playground: {
title: "Bengaluru",
description: "Interactive geographic map",
provider: "openstreetmap",
latitude: 12.9716,
longitude: 77.5946,
zoomLevel: 13,
imageSrc: "",
items: [],
},
options: { provider: ["openstreetmap", "google"] },
};
componentProfiles.Rating = {
demos: [
standard("Whole stars", "Choose a rating from zero to five with step 1.", {
title: "Rate your experience",
value: 3,
step: 1,
}),
compact("Half stars", "Click a half star or use the precise slider and arrow keys.", {
title: "Half-star rating",
value: 3.5,
step: 0.5,
}),
advanced("Fine increments", "Use increments of 0.2 for a more precise rating.", {
title: "Detailed score",
value: 4.2,
step: 0.2,
}),
],
};
componentProfiles.LegendIndicator = {
demos: [
standard("Chart legend", "Toggle a series and handle @toggle to update your chart.", {
title: "Traffic sources",
description: "Select a source to toggle its visibility.",
items: [
{ label: "Direct", color: "#8b5cf6", value: "42%" },
{ label: "Search", color: "#14b8a6", value: "35%" },
{ label: "Referral", color: "#f59e0b", value: "23%" },
],
}),
],
};
componentProfiles.Chart = {
demos: [
standard("Bar chart", "Chart.js bars with positive and negative values.", {
title: "Sample weekly changes",
description: "Sample data",
type: "bar",
data: [
{ label: "Mon", value: 24 },
{ label: "Tue", value: -12 },
{ label: "Wed", value: 29 },
{ label: "Thu", value: 52 },
{ label: "Fri", value: 45 },
],
items: [],
showLegend: true,
showValues: false,
}),
...["line", "area", "pie", "doughnut", "radar", "polarArea"].map((type) =>
compact(
type + " chart",
"Rendered by Chart.js with native tooltips and legend interactions.",
{
title: "Sample " + type,
description: "Sample data",
type,
data: {
labels: ["Mon", "Tue", "Wed", "Thu", "Fri"],
datasets: [{ label: "Series A", data: [24, 38, 29, 52, 45] }],
},
items: [],
showLegend: true,
showValues: false,
},
),
),
advanced("Scatter chart", "Pass native x/y coordinates without flattening them.", {
title: "Sample coordinates",
description: "Sample data",
type: "scatter",
items: [],
data: {
datasets: [
{
label: "Observations",
data: [
{ x: 1, y: 4 },
{ x: 3, y: 8 },
{ x: 5, y: 3 },
],
},
],
},
showValues: false,
}),
advanced("Bubble chart", "Native x/y/r points preserve bubble radii.", {
title: "Sample bubbles",
description: "Sample data",
type: "bubble",
items: [],
data: {
datasets: [
{
label: "Observations",
data: [
{ x: 1, y: 4, r: 8 },
{ x: 3, y: 8, r: 16 },
{ x: 5, y: 3, r: 12 },
],
},
],
},
showValues: false,
}),
advanced("Mixed chart", "Set each dataset's type and pass native Chart.js options.", {
title: "Sample mixed chart",
description: "Sample data",
type: "bar",
items: [],
data: {
labels: ["Jan", "Feb", "Mar"],
datasets: [
{ type: "bar", label: "Actual", data: [20, 35, 28] },
{ type: "line", label: "Target", data: [25, 30, 40] },
],
},
showValues: false,
}),
advanced("Horizontal stacked bars", "Configure indexAxis and stacked scales through options.", {
title: "Sample stacked chart",
description: "Sample data",
type: "bar",
items: [],
data: {
labels: ["Jan", "Feb", "Mar"],
datasets: [
{ label: "A", data: [20, 35, 28] },
{ label: "B", data: [25, 30, 40] },
],
},
options: { indexAxis: "y", scales: { x: { stacked: true }, y: { stacked: true } } },
showValues: false,
}),
],
options: {
type: ["bar", "line", "area", "pie", "doughnut", "radar", "polarArea", "scatter", "bubble"],
},
};
componentProfiles.DatePicker = {
demos: [
standard("Date picker", "An anchored calendar that does not move surrounding content.", {
label: "Start date",
name: "start-date",
type: "date",
}),
compact("Date and time", "Choose a calendar date and a time in one field.", {
label: "Schedule for",
name: "schedule",
type: "datetime-local",
value: "2026-09-20T09:30",
}),
advanced("Disabled date", "A read-only scheduled date.", {
label: "Scheduled date",
readonly: true,
}),
],
options: { type: ["date", "datetime-local"] },
};
componentProfiles.TimePicker = {
demos: [
standard("Time picker", "Choose an hour and minute in an anchored panel.", {
label: "Meeting time",
name: "meeting-time",
value: "09:30",
}),
],
};
componentProfiles.Modal.demos.push(
advanced("Custom header and footer", "Supply your own header, body, and footer actions.", {title:"",description:"",cancelLabel:"",confirmLabel:"",triggerLabel:"Open custom dialog"}, {header:'<h2>Invite a teammate</h2>',default:'<p>Give your teammate access to your workspace.</p>',footer:`<button type="button" class="showcase-action" data-modal-close="true">Done</button>`}),
compact("Centered content", "Omit the standard header and footer for a fully custom composition.", {showHeader:false,showFooter:false,title:"",description:"",icon:"",size:"sm",triggerLabel:"Open centered dialog"}, {default:`<div style="text-align:center;padding:2rem"><h2>You are all set</h2><p>Your preferences have been saved.</p><button type="button" class="showcase-action" data-modal-close="true">Continue</button></div>`}),
advanced(
"Custom header and footer",
"Supply your own header, body, and footer actions.",
{
title: "",
description: "",
cancelLabel: "",
confirmLabel: "",
triggerLabel: "Open custom dialog",
},
{
header: "<h2>Invite a teammate</h2>",
default: "<p>Give your teammate access to your workspace.</p>",
footer: `<button type="button" class="showcase-action" data-modal-close="true">Done</button>`,
},
),
compact(
"Centered content",
"Omit the standard header and footer for a fully custom composition.",
{
showHeader: false,
showFooter: false,
title: "",
description: "",
icon: "",
size: "sm",
triggerLabel: "Open centered dialog",
},
{
default: `<div style="text-align:center;padding:2rem"><h2>You are all set</h2><p>Your preferences have been saved.</p><button type="button" class="showcase-action" data-modal-close="true">Continue</button></div>`,
},
),
);
export function profileFor(name) {
@@ -2992,8 +3247,59 @@ export function eventDescriptionFor(_componentName, eventName) {
);
}
componentProfiles.Card.demos.push(advanced("Custom slots", "Supply arbitrary header, body, and footer content. Use showHeader and showFooter to hide either region.", {title:"",description:"",showHeader:true,showFooter:true,footer:"",actionLabel:""}, {header:"<strong>Team invitation</strong>",default:'<Input label="Email" placeholder="name@company.com" />',footer:'<Button label="Send invitation" />'}));
componentProfiles.RangeSlider = { demos: [compact("Fractional steps", "Use step=0.2 for precise increments with buttons, dragging, or arrow keys.", {label:"Scale",min:0,max:5,value:2.4,step:0.2})] };
componentProfiles.Card.demos.push(
advanced(
"Custom slots",
"Supply arbitrary header, body, and footer content. Use showHeader and showFooter to hide either region.",
{ title: "", description: "", showHeader: true, showFooter: true, footer: "", actionLabel: "" },
{
header: "<strong>Team invitation</strong>",
default: '<Input label="Email" placeholder="name@company.com" />',
footer: '<Button label="Send invitation" />',
},
),
);
componentProfiles.RangeSlider = {
demos: [
compact(
"Fractional steps",
"Use step=0.2 for precise increments with buttons, dragging, or arrow keys.",
{ label: "Scale", min: 0, max: 5, value: 2.4, step: 0.2 },
),
],
};
componentProfiles.FileInput = {demos:[standard("Choose a document", "Select a PDF or image. The selected filename replaces the placeholder.", {label:"Attachment",name:"attachment",value:"",accept:".pdf,image/*",helperText:"PDF or image",placeholder:"Choose a file"}),compact("Multiple attachments", "Select several files; each filename is shown in the control.",{label:"Attachments",name:"attachments",value:"",multiple:true,placeholder:"Choose files"}),advanced("Disabled upload", "A disabled control cannot open the file chooser.",{label:"Attachment",name:"disabled-file",value:"",disabled:true,placeholder:"Uploads unavailable"})]};
componentProfiles.FileInput = {
demos: [
standard(
"Choose a document",
"Select a PDF or image. The selected filename replaces the placeholder.",
{
label: "Attachment",
name: "attachment",
value: "",
accept: ".pdf,image/*",
helperText: "PDF or image",
placeholder: "Choose a file",
},
),
compact(
"Multiple attachments",
"Select several files; each filename is shown in the control.",
{
label: "Attachments",
name: "attachments",
value: "",
multiple: true,
placeholder: "Choose files",
},
),
advanced("Disabled upload", "A disabled control cannot open the file chooser.", {
label: "Attachment",
name: "disabled-file",
value: "",
disabled: true,
placeholder: "Uploads unavailable",
}),
],
};
+18
View File
@@ -0,0 +1,18 @@
import { startStudio } from "./studio.ts";
const studio = await startStudio();
const site = Bun.spawn([process.execPath, "dist/server.js"], {
stdout: "inherit",
stderr: "inherit",
stdin: "inherit",
env: process.env,
});
const stop = () => {
studio.stop(true);
site.kill("SIGTERM");
};
process.on("SIGINT", stop);
process.on("SIGTERM", stop);
const code = await site.exited;
studio.stop(true);
process.exit(code);
+18
View File
@@ -0,0 +1,18 @@
import { createStudioHandler } from "@wrnexus/design-studio/server";
export async function startStudio() {
const fetch = await createStudioHandler({
hosted: { basePath: "/design-studio" },
});
const server = Bun.serve({
hostname: "127.0.0.1",
port: Number(process.env.DESIGN_STUDIO_PORT ?? 4320),
fetch,
});
console.log(
`Export-only Design Studio listening on ${server.url}design-studio/`,
);
return server;
}
if (import.meta.main) await startStudio();
+28 -4
View File
@@ -73,9 +73,9 @@
"path": "/blocks/stats-bar"
}
],
"componentCount": 84,
"componentCount": 86,
"categoryCount": 11,
"totalDemoCount": 346,
"totalDemoCount": 361,
"components": [
{
"name": "Accordion",
@@ -250,8 +250,8 @@
"slug": "chart",
"category": "integrations",
"purpose": "Theme-aware, responsive chart component.",
"demoCount": 2,
"propCount": 14,
"demoCount": 11,
"propCount": 17,
"slots": ["default"],
"events": ["select", "dataPointClick", "legendToggle"],
"profiled": true
@@ -481,6 +481,18 @@
"events": ["open", "close", "cancel"],
"profiled": true
},
{
"name": "DrawflowCanvas",
"mount": "DrawflowCanvas",
"slug": "drawflow-canvas",
"category": "core",
"purpose": "Reusable drawflow canvas component.",
"demoCount": 3,
"propCount": 3,
"slots": [],
"events": ["select", "connect", "move", "add"],
"profiled": false
},
{
"name": "Dropdown",
"mount": "Dropdown",
@@ -517,6 +529,18 @@
"events": ["cancel", "retry", "complete"],
"profiled": false
},
{
"name": "FlowCanvas",
"mount": "FlowCanvas",
"slug": "flow-canvas",
"category": "core",
"purpose": "Reusable flow canvas component.",
"demoCount": 3,
"propCount": 9,
"slots": [],
"events": ["select", "connect", "move", "add"],
"profiled": false
},
{
"name": "Grid",
"mount": "Grid",
+33
View File
@@ -0,0 +1,33 @@
import { expect, test } from "bun:test";
import { createStudioHandler } from "@wrnexus/design-studio/server";
import { CORE_DESIGN_SYSTEMS } from "@wrnexus/design-system";
test("deployed Studio serves assets and isolated previews without application writes", async () => {
const handler = await createStudioHandler({
hosted: { basePath: "/design-studio" },
});
const origin = "https://components.example";
const html = await handler(new Request(origin + "/design-studio/"));
expect(await html.text()).toContain('<base href="/design-studio/">');
expect(
(await handler(new Request(origin + "/design-studio/studio.js"))).status,
).toBe(200);
const request = (path: string, from = origin) =>
handler(
new Request(origin + "/design-studio/api/" + path, {
method: "POST",
headers: { "content-type": "application/json", origin: from },
body: JSON.stringify({
system: CORE_DESIGN_SYSTEMS.soft,
base: "none",
}),
}),
);
expect((await request("apply")).status).toBe(409);
expect((await request("preview", "https://other.example")).status).toBe(403);
const preview = await request("preview");
expect(preview.status).toBe(200);
const { url } = await preview.json();
expect(url).toStartWith("/design-studio/preview/");
expect((await handler(new Request(origin + url))).status).toBe(200);
});
+5 -2
View File
@@ -31,9 +31,12 @@ test("preview input never requests a replacement; settings still do", async () =
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.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");
expect(window.document.querySelector("link")?.getAttribute("href")).toBe(
"/__wrnexus/theme/light/violet.css",
);
await window.happyDOM.close();
});
+171 -50
View File
@@ -8,7 +8,10 @@ const root = join(import.meta.dir, "..");
const pagesDir = join(root, "app", "pages");
const detailPagesDir = join(pagesDir, "components");
const reference = JSON.parse(
readFileSync(join(root, "node_modules", "@wrnexus", "ui", "component-reference.json"), "utf8"),
readFileSync(
join(root, "node_modules", "@wrnexus", "ui", "component-reference.json"),
"utf8",
),
) as {
count: number;
components: Array<{
@@ -20,9 +23,11 @@ const reference = JSON.parse(
events: string[];
}>;
};
const manifest = JSON.parse(readFileSync(join(root, "showcase-manifest.json"), "utf8")) as {
const manifest = JSON.parse(
readFileSync(join(root, "showcase-manifest.json"), "utf8"),
) as {
removed: string[];
blocks: Array<{name: string; slug: string; path: string}>;
blocks: Array<{ name: string; slug: string; path: string }>;
componentCount: number;
categoryCount: number;
totalDemoCount: number;
@@ -39,7 +44,8 @@ const manifest = JSON.parse(readFileSync(join(root, "showcase-manifest.json"), "
}>;
};
const detailSource = (slug: string) => readFileSync(join(detailPagesDir, `${slug}.wrn`), "utf8");
const detailSource = (slug: string) =>
readFileSync(join(detailPagesDir, `${slug}.wrn`), "utf8");
const interactiveOverlayNames = [
"ContextMenu",
@@ -57,32 +63,56 @@ function mountCount(source: string, mount: string): number {
}
test("showcase configures local Lucide icon generation", () => {
const packageJson = JSON.parse(readFileSync(join(root, "package.json"), "utf8")) as {
const packageJson = JSON.parse(
readFileSync(join(root, "package.json"), "utf8"),
) as {
devDependencies: Record<string, string>;
};
const styles = readFileSync(join(root, "app", "styles", "global.css"), "utf8");
const styles = readFileSync(
join(root, "app", "styles", "global.css"),
"utf8",
);
expect(packageJson.devDependencies["@iconify/tailwind4"]).toBeTruthy();
expect(packageJson.devDependencies["@iconify-json/lucide"]).toBeTruthy();
expect(styles).toContain('@plugin "@iconify/tailwind4";');
expect(styles).toContain(".playground-preview-source > .wrn-action:not(.w-full)");
expect(styles).toContain(
".playground-preview-source > .wrn-action:not(.w-full)",
);
expect(styles).toContain('[data-ui-component="MetricGrid"]');
expect(styles).toContain("width: 100%;");
});
test("showcase manifest matches the generated UI reference", () => {
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(
manifest.componentCount,
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(manifest.componentCount);
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);
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);
expect(documented?.events).toEqual(component.events);
@@ -91,20 +121,31 @@ test("showcase manifest matches the generated UI reference", () => {
});
test("showcase uses a searchable documentation shell", () => {
const layout = readFileSync(join(root, "app", "layouts", "showcase.wrn"), "utf8");
const styles = readFileSync(join(root, "app", "styles", "global.css"), "utf8");
const layout = readFileSync(
join(root, "app", "layouts", "showcase.wrn"),
"utf8",
);
const styles = readFileSync(
join(root, "app", "styles", "global.css"),
"utf8",
);
const runtime = readFileSync(join(root, "public", "playground.js"), "utf8");
expect(layout).toContain("data-docs-directory");
expect(layout).toContain("data-docs-search");
expect(layout.match(/data-docs-component-link/g)).toHaveLength(manifest.componentCount);
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"');
});
test("showcase SSR document layout maps persisted design cookies to html attributes", () => {
const source = readFileSync(join(root, "app", "layouts", "document.wrn"), "utf8");
const source = readFileSync(
join(root, "app", "layouts", "document.wrn"),
"utf8",
);
expect(source).toContain("<html");
expect(source).toContain("<head></head>");
expect(source).toContain('<div id="app"><slot /></div>');
@@ -116,22 +157,39 @@ test("showcase SSR document layout maps persisted design cookies to html attribu
test("category pages preview every UI component exactly once", () => {
const categoryPages = readdirSync(pagesDir)
.filter((file) => manifest.components.some((component) => `${component.category}.wrn` === file))
.filter((file) =>
manifest.components.some(
(component) => `${component.category}.wrn` === file,
),
)
.map((file) => readFileSync(join(pagesDir, file), "utf8"))
.join("\n");
const invalidPreviews = reference.components.filter(entry => manifest.components.some(component => component.name === entry.name)).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
? []
: [{ name: component.name, mount: component.mount, category: component.category, count }];
: [
{
name: component.name,
mount: component.mount,
category: component.category,
count,
},
];
});
expect(invalidPreviews).toEqual([]);
});
test("every component has a detail page, playground, and manifest-driven demos", () => {
const files = readdirSync(detailPagesDir).filter((entry) => entry.endsWith(".wrn"));
const files = readdirSync(detailPagesDir).filter((entry) =>
entry.endsWith(".wrn"),
);
expect(files).toHaveLength(manifest.componentCount);
for (const component of manifest.components) {
@@ -140,13 +198,20 @@ test("every component has a detail page, playground, and manifest-driven demos",
expect(source).toContain("data-playground-form");
expect(source).toContain("data-playground-code");
expect(source).toContain('href="#playground"');
expect(source.match(/class="demo-workbench"/g)).toHaveLength(component.demoCount);
expect(mountCount(source, component.mount)).toBeGreaterThanOrEqual(component.demoCount + 1);
expect(source.match(/class="demo-workbench"/g)).toHaveLength(
component.demoCount,
);
expect(mountCount(source, component.mount)).toBeGreaterThanOrEqual(
component.demoCount + 1,
);
}
}, 20_000);
test("playgrounds preserve typed values, safe DOM replacement, themes, and event output", () => {
const generator = readFileSync(join(root, "scripts", "generate-showcase.mjs"), "utf8");
const generator = readFileSync(
join(root, "scripts", "generate-showcase.mjs"),
"utf8",
);
const runtime = readFileSync(join(root, "public", "playground.js"), "utf8");
expect(generator).toContain("JSON.parse(");
@@ -158,7 +223,9 @@ test("playgrounds preserve typed values, safe DOM replacement, themes, and event
'data-slot="${escapeAttribute(slot)}"',
"",
);
expect(generatorWithoutDataSlots).not.toContain('slot="${escapeAttribute(slot)}"');
expect(generatorWithoutDataSlots).not.toContain(
'slot="${escapeAttribute(slot)}"',
);
expect(runtime).toContain("fetch(url");
expect(runtime).toContain("navigator.clipboard.writeText");
@@ -171,21 +238,34 @@ test("playgrounds preserve typed values, safe DOM replacement, themes, and event
});
test("playground enum controls use public profiles instead of inferred implementation comparisons", () => {
const generator = readFileSync(join(root, "scripts", "generate-showcase.mjs"), "utf8");
expect(generator).toContain("profileFor(component.name)?.options?.[prop.name]");
const generator = readFileSync(
join(root, "scripts", "generate-showcase.mjs"),
"utf8",
);
expect(generator).toContain(
"profileFor(component.name)?.options?.[prop.name]",
);
expect(generator).not.toContain("source.matchAll(pattern)");
const pageHeader = manifest.components.find((component) => component.name === "PageHeader");
const pageHeader = manifest.components.find(
(component) => component.name === "PageHeader",
);
if (pageHeader) {
const source = detailSource(pageHeader.slug);
expect(source).toContain('name="pg_icon" type="text"');
expect(source).toMatch(/<option value="default"(?: selected)?>default<\/option>/);
expect(source).toMatch(/<option value="solid"(?: selected)?>solid<\/option>/);
expect(source).toMatch(
/<option value="default"(?: selected)?>default<\/option>/,
);
expect(source).toMatch(
/<option value="solid"(?: selected)?>solid<\/option>/,
);
}
});
test("every declared public event is documented and visible in the playground", () => {
for (const component of manifest.components.filter((entry) => entry.events.length > 0)) {
for (const component of manifest.components.filter(
(entry) => entry.events.length > 0,
)) {
const source = detailSource(component.slug);
expect(source).toContain('id="events"');
expect(source).toContain('href="#events"');
@@ -232,12 +312,17 @@ test("new and recently repaired components have production use-case profiles", (
if (!component) continue;
expect(component.profiled).toBe(true);
const source = detailSource(component.slug);
expect(source.match(/class="demo-workbench"/g)?.length ?? 0).toBeGreaterThanOrEqual(3);
expect(
source.match(/class="demo-workbench"/g)?.length ?? 0,
).toBeGreaterThanOrEqual(3);
}
});
test("grid, hero, shell, and overlay detail pages use responsive showcase stages", () => {
const styles = readFileSync(join(root, "app", "styles", "global.css"), "utf8");
const styles = readFileSync(
join(root, "app", "styles", "global.css"),
"utf8",
);
for (const name of [
"MetricGrid",
"FeatureGrid",
@@ -251,7 +336,9 @@ test("grid, hero, shell, and overlay detail pages use responsive showcase stages
expect(styles).toContain(`[data-ui-component="${name}"]`);
}
const metricGrid = manifest.components.find((component) => component.name === "MetricGrid");
const metricGrid = manifest.components.find(
(component) => component.name === "MetricGrid",
);
if (metricGrid) {
const source = detailSource(metricGrid.slug);
expect(source).toContain('columns="3"');
@@ -266,9 +353,18 @@ test("grid, hero, shell, and overlay detail pages use responsive showcase stages
});
test("overlay previews start closed and expose usable click, hover, or context triggers", () => {
const generator = readFileSync(join(root, "scripts", "generate-showcase.mjs"), "utf8");
const profiles = readFileSync(join(root, "scripts", "showcase-profiles.mjs"), "utf8");
const styles = readFileSync(join(root, "app", "styles", "global.css"), "utf8");
const generator = readFileSync(
join(root, "scripts", "generate-showcase.mjs"),
"utf8",
);
const profiles = readFileSync(
join(root, "scripts", "showcase-profiles.mjs"),
"utf8",
);
const styles = readFileSync(
join(root, "app", "styles", "global.css"),
"utf8",
);
expect(generator).toContain("interactiveOverlayComponents");
expect(generator).toContain("overlayVisibilityProps.has(name)");
@@ -286,7 +382,9 @@ test("overlay previews start closed and expose usable click, hover, or context t
const detail = detailSource(component.slug);
expect(detail).toContain("demo-interaction-hint");
expect(detail).not.toMatch(new RegExp(`<${component.mount}[^>]*(?:open|defaultOpen)="true"`));
expect(detail).not.toMatch(
new RegExp(`<${component.mount}[^>]*(?:open|defaultOpen)="true"`),
);
expect(overlaysPage).not.toMatch(
new RegExp(`<${component.mount}[^>]*(?:open|defaultOpen)="true"`),
);
@@ -302,17 +400,24 @@ test("overlay previews start closed and expose usable click, hover, or context t
});
test("advanced select demos use validation schemas and a real remote API", () => {
const component = manifest.components.find((entry) => entry.name === "AdvancedSelect");
const component = manifest.components.find(
(entry) => entry.name === "AdvancedSelect",
);
if (!component) return;
const page = detailSource(component.slug);
expect(page).toContain('data-schema="advanced-select-validation"');
expect(page).toContain('data-schema="advanced-select-dynamic-validation"');
expect(readFileSync(join(root, "app", "api", "teams.ts"), "utf8")).toContain("export const GET");
expect(readFileSync(join(root, "app", "api", "teams.ts"), "utf8")).toContain(
"export const GET",
);
});
test("specialized form component examples remain complete", () => {
const checks: Array<[string, string[]]> = [
["PinInput", ["Different lengths", 'length="3"', 'length="5"', 'length="7"']],
[
"PinInput",
["Different lengths", 'length="3"', 'length="5"', 'length="7"'],
],
[
"TogglePassword",
[
@@ -323,7 +428,11 @@ test("specialized form component examples remain complete", () => {
],
[
"StrongPassword",
["Live strength meter", "Requirements in a popover", 'specialCharactersSet="@#_-."'],
[
"Live strength meter",
"Requirements in a popover",
'specialCharactersSet="@#_-."',
],
],
];
for (const [name, needles] of checks) {
@@ -335,22 +444,34 @@ test("specialized form component examples remain complete", () => {
});
test("complex component props are complete readable multiline values", () => {
for (const name of ["AdvancedSelect", "ComboBox", "Select", "TogglePassword"]) {
for (const name of [
"AdvancedSelect",
"ComboBox",
"Select",
"TogglePassword",
]) {
const component = manifest.components.find((entry) => entry.name === name);
if (!component) continue;
const source = detailSource(component.slug);
expect(source).not.toMatch(/\b(?:options|groups|items|fields)='\[\.\.\.\]'/);
expect(source).not.toMatch(
/\b(?:options|groups|items|fields)='\[\.\.\.\]'/,
);
}
});
test("generated playground boolean states avoid multiline-sensitive ternaries", () => {
const generator = readFileSync(join(root, "scripts", "generate-showcase.mjs"), "utf8");
const generator = readFileSync(
join(root, "scripts", "generate-showcase.mjs"),
"utf8",
);
expect(generator).toContain('?? "${initial}") === "true"');
expect(generator).not.toContain("=== null ? ${initial} :");
for (const component of manifest.components) {
const source = detailSource(component.slug);
expect(source).not.toMatch(/state\s+playground_[A-Za-z0-9_$]+\s*=.*===\s*null\s*\?/);
expect(source).not.toMatch(
/state\s+playground_[A-Za-z0-9_$]+\s*=.*===\s*null\s*\?/,
);
}
});
+1 -1
View File
@@ -15,6 +15,6 @@
"jsx": "react-jsx",
"jsxImportSource": "@wrnexus/core"
},
"include": ["wrnexus.config.ts", "test/**/*.ts"],
"include": ["wrnexus.config.ts", "test/**/*.ts", "scripts/**/*.ts"],
"exclude": ["node_modules", "dist", "**/dist", "**/.wrnexus"]
}
+7 -1
View File
@@ -9,7 +9,13 @@ const config: AppConfig = {
robots: "noindex,nofollow",
themeColor: "#7c3aed",
},
security: { contentSecurityPolicy: { directives: { "frame-src": ["'self'", "https://www.openstreetmap.org", "https://www.google.com"] } } },
security: {
contentSecurityPolicy: {
directives: {
"frame-src": ["'self'", "https://www.openstreetmap.org", "https://www.google.com"],
},
},
},
theme: {
palette: "violet",
default: "light",