release: WRNexusJS 0.5.13

This commit is contained in:
2026-07-30 20:46:47 +05:30
parent d64e899993
commit 9dffe83f32
404 changed files with 345 additions and 67025 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/ai",
"version": "0.5.12",
"version": "0.5.13",
"private": true,
"type": "module",
"description": "Zero-dependency Claude (Anthropic) client for WrNexus apps.",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/auth",
"version": "0.5.12",
"version": "0.5.13",
"description": "Complete authentication, account security, MFA, passkeys, recovery, devices, risk, and audit system for WRNexusJS.",
"type": "module",
"sideEffects": false,
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/authz",
"version": "0.5.12",
"version": "0.5.13",
"private": true,
"type": "module",
"main": "src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/captcha",
"version": "0.5.12",
"version": "0.5.13",
"description": "First-class CAPTCHA challenges, providers, verification guards, page gates, and WRNexusJS UI.",
"type": "module",
"sideEffects": false,
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/cli",
"version": "0.5.12",
"version": "0.5.13",
"type": "module",
"main": "src/index.ts",
"exports": {
+8
View File
@@ -1153,6 +1153,14 @@ const MIGRATIONS: Migration[] = [
// Gateway, helper, validation, and UI improvements are package-managed.
},
},
{
version: "0.5.13",
id: "latest-release-after-upgrade",
description: "Latest New Packages and release ready packages",
apply() {
// Gateway, helper, validation, and UI improvements are package-managed.
},
},
];
/** Release tooling uses this to require an explicit migration entry per version. */
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/compiler",
"version": "0.5.12",
"version": "0.5.13",
"type": "module",
"main": "src/index.ts",
"exports": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/core",
"version": "0.5.12",
"version": "0.5.13",
"type": "module",
"main": "src/index.ts",
"exports": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/csr",
"version": "0.5.12",
"version": "0.5.13",
"type": "module",
"main": "src/index.ts",
"exports": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/db",
"version": "0.5.12",
"version": "0.5.13",
"private": true,
"type": "module",
"main": "src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/dev-server",
"version": "0.5.12",
"version": "0.5.13",
"type": "module",
"main": "src/index.ts",
"exports": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/dev-toolbar",
"version": "0.5.12",
"version": "0.5.13",
"private": true,
"type": "module",
"sideEffects": false,
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/encryption",
"version": "0.5.12",
"version": "0.5.13",
"private": true,
"type": "module",
"main": "src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/helpers",
"version": "0.5.12",
"version": "0.5.13",
"private": true,
"type": "module",
"description": "Safe convenience helpers for WrNexus request contexts and common application flows.",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/i18n",
"version": "0.5.12",
"version": "0.5.13",
"private": true,
"type": "module",
"main": "src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/jwt",
"version": "0.5.12",
"version": "0.5.13",
"private": true,
"type": "module",
"main": "src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/mobile",
"version": "0.5.12",
"version": "0.5.13",
"type": "module",
"main": "src/index.ts",
"exports": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/native",
"version": "0.5.12",
"version": "0.5.13",
"type": "module",
"main": "src/index.ts",
"exports": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/oauth",
"version": "0.5.12",
"version": "0.5.13",
"private": true,
"type": "module",
"main": "src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/plugin",
"version": "0.5.12",
"version": "0.5.13",
"type": "module",
"main": "src/index.ts",
"exports": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/pubsub",
"version": "0.5.12",
"version": "0.5.13",
"private": true,
"type": "module",
"main": "src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/queue",
"version": "0.5.12",
"version": "0.5.13",
"private": true,
"type": "module",
"main": "src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/reactive",
"version": "0.5.12",
"version": "0.5.13",
"type": "module",
"main": "src/index.ts",
"exports": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/router",
"version": "0.5.12",
"version": "0.5.13",
"type": "module",
"main": "src/index.ts",
"exports": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/ssr",
"version": "0.5.12",
"version": "0.5.13",
"type": "module",
"main": "src/index.ts",
"exports": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/styles",
"version": "0.5.12",
"version": "0.5.13",
"type": "module",
"main": "src/index.ts",
"exports": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/syntax",
"version": "0.5.12",
"version": "0.5.13",
"type": "module",
"main": "src/index.ts",
"exports": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/test",
"version": "0.5.12",
"version": "0.5.13",
"private": true,
"type": "module",
"main": "src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/tracking",
"version": "0.5.12",
"version": "0.5.13",
"private": true,
"type": "module",
"main": "src/index.ts",
+1 -1
View File
@@ -841,7 +841,7 @@ Responsive application footer with structured links and pre/post content slots.
- Mount: `data-component="Footer"`
- Props: `size: string = "default"`, `color: string = "primary"`, `label: string = "Footer navigation"`, `items: string = []`, `columns: number = 3`, `maxWidth: string = "compact"`, `copyright: string = ""`, `class: string = ""`
- Slots: `pre-footer`, `copyright-left`, `copyright-right`, `post-footer`
- Slots: `pre-footer`, `post-footer`, `copyright-left`, `copyright-right`
- Events: `select`, `action`
### MegaMenu
+1 -1
View File
@@ -4534,7 +4534,7 @@
"default": "\"\""
}
],
"slots": ["pre-footer", "copyright-left", "copyright-right", "post-footer"],
"slots": ["pre-footer", "post-footer", "copyright-left", "copyright-right"],
"events": ["select", "action"],
"source": "components/Footer.wrn"
},
+228 -89
View File
@@ -2,6 +2,7 @@ component Footer {
props {
@event select = function
@event action = function
size = "default"
color = "primary"
label = "Footer navigation"
@@ -18,127 +19,265 @@ component Footer {
data-ui-component="Footer"
data-size='{size}'
data-color='{color}'
class='wire-footer border-t border-[var(--wire-color-border)] bg-[var(--wire-color-surface-raised)] text-[var(--wire-color-text)] {class}'
class='wire-footer {maxWidth === "full" ? "wire-footer--width-full" : ""} {class}'
>
<slot name="pre-footer"></slot>
<div
class="wire-footer__inner mx-auto w-full px-4 py-12 sm:px-6 lg:px-8"
class:max-w-5xl='maxWidth === "compact"'
class:max-w-7xl='maxWidth === "wide" || maxWidth === "xl"'
class:max-w-screen-2xl='maxWidth === "full"'
class:py-8='size === "compact"'
class:py-16='size === "spacious"'
class="wire-footer__grid"
>
<nav aria-label='{label}'>
<div class='wire-footer__columns wire-footer--columns-{columns}'>
<div
class="wire-footer__pre"
>
<slot
name="pre-footer"
>
</slot>
</div>
{#if items.length > 0}
<nav
class='wire-footer__links wire-footer--columns-{columns}'
aria-label='{label}'
>
{#each items as item, itemIndex}
{#if item.type === "header"}
<section class="wire-footer__column" aria-labelledby='footer-heading-{itemIndex}'>
<h2 id='footer-heading-{itemIndex}' class="wire-footer__heading">
<section
class="wire-footer__column"
aria-labelledby='footer-heading-{itemIndex}'
>
{#if item.icon}
<span
class='{item.icon}'
aria-hidden="true"
>
</span>
{/if}
<h2
id='footer-heading-{itemIndex}'
class="wire-footer__heading"
>
{item.label || item.title}
</h2>
{#if item.description}
<p class="wire-footer__description">{item.description}</p>
<p>
{item.description}
</p>
{/if}
{#if (item.items || item.links || []).length > 0}
<ul class="wire-footer__column-links">
<div
class="wire-footer__column-links"
>
{#each item.items || item.links || [] as child, childIndex}
<li>
<a
href='{child.href || "#"}'
target='{child.target || ""}'
rel='{child.external ? "noopener noreferrer" : (child.rel || "")}'
class="wire-footer__link"
@click='event.currentTarget.dispatchEvent(new CustomEvent("select", { bubbles: true, detail: { item: child, parent: item, itemIndex: childIndex, sectionIndex: itemIndex } })); child.action && event.currentTarget.dispatchEvent(new CustomEvent("action", { bubbles: true, detail: { item: child, parent: item, itemIndex: childIndex, sectionIndex: itemIndex } }))'
>
{#if child.icon}
<span class='{child.icon}' aria-hidden="true"></span>
{/if}
<span>{child.label || child.title}</span>
{#if child.external}
<span class="icon-[lucide--external-link]" aria-hidden="true"></span>
{/if}
</a>
</li>
{/each}
</ul>
{/if}
</section>
{:else if item.type === "link" || item.href}
<section class="wire-footer__column">
<ul class="wire-footer__column-links">
<li>
<a
href='{item.href || "#"}'
target='{item.target || ""}'
rel='{item.external ? "noopener noreferrer" : (item.rel || "")}'
class="wire-footer__link"
@click='event.currentTarget.dispatchEvent(new CustomEvent("select", { bubbles: true, detail: { item: item, itemIndex: itemIndex } })); item.action && event.currentTarget.dispatchEvent(new CustomEvent("action", { bubbles: true, detail: { item: item, itemIndex: itemIndex } }))'
>
{#if item.icon}
<span class='{item.icon}' aria-hidden="true"></span>
{/if}
<span>{item.label || item.title}</span>
{#if item.external}
<span class="icon-[lucide--external-link]" aria-hidden="true"></span>
{/if}
</a>
</li>
</ul>
</section>
{:else}
<section class="wire-footer__column">
{#if item.title || item.label}
<h2 class="wire-footer__heading">{item.title || item.label}</h2>
{/if}
{#if item.description}
<p class="wire-footer__description">{item.description}</p>
{/if}
<ul class="wire-footer__column-links">
{#each item.items || item.links || [] as child, childIndex}
<li>
<a
href='{child.href || "#"}'
target='{child.target || ""}'
rel='{child.external ? "noopener noreferrer" : (child.rel || "")}'
aria-current='{child.active ? "page" : ""}'
class="wire-footer__link"
@click='event.currentTarget.dispatchEvent(new CustomEvent("select", { bubbles: true, detail: { item: child, parent: item, itemIndex: childIndex, sectionIndex: itemIndex } })); child.action && event.currentTarget.dispatchEvent(new CustomEvent("action", { bubbles: true, detail: { item: child, parent: item, itemIndex: childIndex, sectionIndex: itemIndex } }))'
>
{#if child.icon}
<span class='{child.icon}' aria-hidden="true"></span>
<span
class='{child.icon}'
aria-hidden="true"
>
</span>
{/if}
<span>{child.label || child.title}</span>
<span>
{child.label || child.title}
</span>
{#if child.badge}
<span
class="wire-badge wire-badge--default"
>
{child.badge}
</span>
{/if}
{#if child.external}
<span class="icon-[lucide--external-link]" aria-hidden="true"></span>
<span
class="icon-[lucide--arrow-up-right]"
aria-hidden="true"
>
</span>
{/if}
</a>
</li>
{/each}
</ul>
{/each}
</div>
{/if}
</section>
{:else if item.type === "link" || item.href}
<section
class="wire-footer__column"
>
<div
class="wire-footer__column-links"
>
<a
href='{item.href || "#"}'
target='{item.target || ""}'
rel='{item.external ? "noopener noreferrer" : (item.rel || "")}'
aria-current='{item.active ? "page" : ""}'
class="wire-footer__link"
@click='event.currentTarget.dispatchEvent(new CustomEvent("select", { bubbles: true, detail: { item: item, itemIndex: itemIndex } })); item.action && event.currentTarget.dispatchEvent(new CustomEvent("action", { bubbles: true, detail: { item: item, itemIndex: itemIndex } }))'
>
{#if item.icon}
<span
class='{item.icon}'
aria-hidden="true"
>
</span>
{/if}
<span>
{item.label || item.title}
</span>
{#if item.badge}
<span
class="wire-badge wire-badge--default"
>
{item.badge}
</span>
{/if}
{#if item.external}
<span
class="icon-[lucide--arrow-up-right]"
aria-hidden="true"
>
</span>
{/if}
</a>
</div>
</section>
{:else}
<section
class="wire-footer__column"
aria-labelledby='footer-heading-{itemIndex}'
>
{#if item.icon}
<span
class='{item.icon}'
aria-hidden="true"
>
</span>
{/if}
{#if item.title || item.label}
<h2
id='footer-heading-{itemIndex}'
class="wire-footer__heading"
>
{item.title || item.label}
</h2>
{/if}
{#if item.description}
<p>
{item.description}
</p>
{/if}
{#if (item.items || item.links || []).length > 0}
<div
class="wire-footer__column-links"
>
{#each item.items || item.links || [] as child, childIndex}
<a
href='{child.href || "#"}'
target='{child.target || ""}'
rel='{child.external ? "noopener noreferrer" : (child.rel || "")}'
aria-current='{child.active ? "page" : ""}'
class="wire-footer__link"
@click='event.currentTarget.dispatchEvent(new CustomEvent("select", { bubbles: true, detail: { item: child, parent: item, itemIndex: childIndex, sectionIndex: itemIndex } })); child.action && event.currentTarget.dispatchEvent(new CustomEvent("action", { bubbles: true, detail: { item: child, parent: item, itemIndex: childIndex, sectionIndex: itemIndex } }))'
>
{#if child.icon}
<span
class='{child.icon}'
aria-hidden="true"
>
</span>
{/if}
<span>
{child.label || child.title}
</span>
{#if child.badge}
<span
class="wire-badge wire-badge--default"
>
{child.badge}
</span>
{/if}
{#if child.external}
<span
class="icon-[lucide--arrow-up-right]"
aria-hidden="true"
>
</span>
{/if}
</a>
{/each}
</div>
{/if}
</section>
{/if}
{/each}
</div>
</nav>
</nav>
{/if}
<div class="wire-footer__copyright">
<div class="wire-footer__copyright-left">
<slot name="copyright-left"></slot>
{#if copyright}
<p>{copyright}</p>
{/if}
</div>
<div class="wire-footer__copyright-right">
<slot name="copyright-right"></slot>
</div>
<div
class="wire-footer__post"
>
<slot
name="post-footer"
>
</slot>
</div>
</div>
<slot name="post-footer"></slot>
<div
class="wire-footer__bottom wire-footer__bottom--slots"
>
<div
class="wire-footer__copyright-left"
>
<slot
name="copyright-left"
>
</slot>
</div>
<div
class="wire-footer__copyright-right"
>
<slot
name="copyright-right"
>
</slot>
</div>
</div>
{#if copyright}
<div
class="wire-footer__bottom"
>
<div></div>
<p class="wire-footer__copyright">
{copyright}
</p>
<div></div>
</div>
{/if}
</footer>
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/ui",
"version": "0.5.12",
"version": "0.5.13",
"private": true,
"type": "module",
"main": "src/index.ts",
+4 -4
View File
@@ -194,10 +194,10 @@ test("auth form uses package schemas, disables native validation, and renders a
test("footer supports typed entries, responsive columns, pre/post slots, and events", () => {
const source = readFileSync(uiComponentPath("Footer"), "utf8");
expect(source).toContain('slot name="pre-footer"');
expect(source).toContain('slot name="post-footer"');
expect(source).toContain('slot name="copyright-left"');
expect(source).toContain('slot name="copyright-right"');
expect(source).toMatch(/<slot\s+name="pre-footer"\s*>/);
expect(source).toMatch(/<slot\s+name="post-footer"\s*>/);
expect(source).toMatch(/<slot\s+name="copyright-left"\s*>/);
expect(source).toMatch(/<slot\s+name="copyright-right"\s*>/);
expect(source).toContain('item.type === "header"');
expect(source).toContain("wire-footer--columns-{columns}");
expect(source).toContain("@event select = function");
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/uploader",
"version": "0.5.12",
"version": "0.5.13",
"private": true,
"type": "module",
"main": "src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/validation",
"version": "0.5.12",
"version": "0.5.13",
"private": true,
"type": "module",
"main": "src/index.ts",