diff --git a/.publish/ai/package.json b/.publish/ai/package.json
index 694ef9be..204f0f04 100644
--- a/.publish/ai/package.json
+++ b/.publish/ai/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/ai",
- "version": "0.2.51",
+ "version": "0.2.52",
"type": "module",
"description": "Zero-dependency Claude (Anthropic) client for WrNexus apps.",
"license": "MIT",
diff --git a/.publish/authz/package.json b/.publish/authz/package.json
index 84404d72..7a6bba35 100644
--- a/.publish/authz/package.json
+++ b/.publish/authz/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/authz",
- "version": "0.2.51",
+ "version": "0.2.52",
"type": "module",
"description": "@wrnexus/authz — part of the WrNexus framework.",
"license": "MIT",
diff --git a/.publish/cli/package.json b/.publish/cli/package.json
index 3662e500..a05561e1 100644
--- a/.publish/cli/package.json
+++ b/.publish/cli/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/cli",
- "version": "0.2.51",
+ "version": "0.2.52",
"type": "module",
"description": "@wrnexus/cli — part of the WrNexus framework.",
"license": "MIT",
@@ -28,16 +28,16 @@
"wrnexus": "./dist/index.js"
},
"dependencies": {
- "@wrnexus/core": "^0.2.51",
- "@wrnexus/router": "^0.2.51",
- "@wrnexus/csr": "^0.2.51",
- "@wrnexus/compiler": "^0.2.51",
- "@wrnexus/styles": "^0.2.51",
- "@wrnexus/dev-server": "^0.2.51",
- "@wrnexus/ui": "^0.2.51",
- "@wrnexus/validation": "^0.2.51",
- "@wrnexus/i18n": "^0.2.51",
- "@wrnexus/db": "^0.2.51"
+ "@wrnexus/core": "^0.2.52",
+ "@wrnexus/router": "^0.2.52",
+ "@wrnexus/csr": "^0.2.52",
+ "@wrnexus/compiler": "^0.2.52",
+ "@wrnexus/styles": "^0.2.52",
+ "@wrnexus/dev-server": "^0.2.52",
+ "@wrnexus/ui": "^0.2.52",
+ "@wrnexus/validation": "^0.2.52",
+ "@wrnexus/i18n": "^0.2.52",
+ "@wrnexus/db": "^0.2.52"
},
"files": [
"dist"
diff --git a/.publish/compiler/package.json b/.publish/compiler/package.json
index e8ec989c..b1630050 100644
--- a/.publish/compiler/package.json
+++ b/.publish/compiler/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/compiler",
- "version": "0.2.51",
+ "version": "0.2.52",
"type": "module",
"description": "@wrnexus/compiler — part of the WrNexus framework.",
"license": "MIT",
diff --git a/.publish/core/package.json b/.publish/core/package.json
index eefaf8a4..f59cb7f9 100644
--- a/.publish/core/package.json
+++ b/.publish/core/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/core",
- "version": "0.2.51",
+ "version": "0.2.52",
"type": "module",
"description": "@wrnexus/core — part of the WrNexus framework.",
"license": "MIT",
diff --git a/.publish/csr/package.json b/.publish/csr/package.json
index 2d1815bd..fefb6651 100644
--- a/.publish/csr/package.json
+++ b/.publish/csr/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/csr",
- "version": "0.2.51",
+ "version": "0.2.52",
"type": "module",
"description": "@wrnexus/csr — part of the WrNexus framework.",
"license": "MIT",
@@ -21,7 +21,7 @@
}
},
"dependencies": {
- "@wrnexus/core": "^0.2.51"
+ "@wrnexus/core": "^0.2.52"
},
"files": [
"dist"
diff --git a/.publish/db/package.json b/.publish/db/package.json
index eb3e530a..83991f25 100644
--- a/.publish/db/package.json
+++ b/.publish/db/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/db",
- "version": "0.2.51",
+ "version": "0.2.52",
"type": "module",
"description": "@wrnexus/db — part of the WrNexus framework.",
"license": "MIT",
diff --git a/.publish/dev-server/package.json b/.publish/dev-server/package.json
index 488d7442..a9b9b70b 100644
--- a/.publish/dev-server/package.json
+++ b/.publish/dev-server/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/dev-server",
- "version": "0.2.51",
+ "version": "0.2.52",
"type": "module",
"description": "@wrnexus/dev-server — part of the WrNexus framework.",
"license": "MIT",
@@ -25,18 +25,18 @@
}
},
"dependencies": {
- "@wrnexus/core": "^0.2.51",
- "@wrnexus/router": "^0.2.51",
- "@wrnexus/ssr": "^0.2.51",
- "@wrnexus/csr": "^0.2.51",
- "@wrnexus/compiler": "^0.2.51",
- "@wrnexus/styles": "^0.2.51",
- "@wrnexus/ui": "^0.2.51",
- "@wrnexus/validation": "^0.2.51",
- "@wrnexus/i18n": "^0.2.51",
- "@wrnexus/db": "^0.2.51",
- "@wrnexus/pubsub": "^0.2.51",
- "@wrnexus/uploader": "^0.2.51"
+ "@wrnexus/core": "^0.2.52",
+ "@wrnexus/router": "^0.2.52",
+ "@wrnexus/ssr": "^0.2.52",
+ "@wrnexus/csr": "^0.2.52",
+ "@wrnexus/compiler": "^0.2.52",
+ "@wrnexus/styles": "^0.2.52",
+ "@wrnexus/ui": "^0.2.52",
+ "@wrnexus/validation": "^0.2.52",
+ "@wrnexus/i18n": "^0.2.52",
+ "@wrnexus/db": "^0.2.52",
+ "@wrnexus/pubsub": "^0.2.52",
+ "@wrnexus/uploader": "^0.2.52"
},
"files": [
"dist"
diff --git a/.publish/encryption/package.json b/.publish/encryption/package.json
index 4613833a..4cceca62 100644
--- a/.publish/encryption/package.json
+++ b/.publish/encryption/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/encryption",
- "version": "0.2.51",
+ "version": "0.2.52",
"type": "module",
"description": "@wrnexus/encryption — part of the WrNexus framework.",
"license": "MIT",
diff --git a/.publish/helpers/package.json b/.publish/helpers/package.json
index ae15bb32..8b4d9df3 100644
--- a/.publish/helpers/package.json
+++ b/.publish/helpers/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/helpers",
- "version": "0.2.51",
+ "version": "0.2.52",
"type": "module",
"description": "Safe convenience helpers for WrNexus request contexts and common application flows.",
"license": "MIT",
@@ -21,7 +21,7 @@
}
},
"dependencies": {
- "@wrnexus/core": "^0.2.51"
+ "@wrnexus/core": "^0.2.52"
},
"files": [
"dist"
diff --git a/.publish/i18n/package.json b/.publish/i18n/package.json
index 7d8c48a7..a201c694 100644
--- a/.publish/i18n/package.json
+++ b/.publish/i18n/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/i18n",
- "version": "0.2.51",
+ "version": "0.2.52",
"type": "module",
"description": "@wrnexus/i18n — part of the WrNexus framework.",
"license": "MIT",
@@ -21,7 +21,7 @@
}
},
"dependencies": {
- "@wrnexus/core": "^0.2.51"
+ "@wrnexus/core": "^0.2.52"
},
"files": [
"dist"
diff --git a/.publish/jwt/package.json b/.publish/jwt/package.json
index 256ab1e4..f36aae7b 100644
--- a/.publish/jwt/package.json
+++ b/.publish/jwt/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/jwt",
- "version": "0.2.51",
+ "version": "0.2.52",
"type": "module",
"description": "@wrnexus/jwt — part of the WrNexus framework.",
"license": "MIT",
diff --git a/.publish/mobile/package.json b/.publish/mobile/package.json
index e1893d0b..c3ac670b 100644
--- a/.publish/mobile/package.json
+++ b/.publish/mobile/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/mobile",
- "version": "0.2.51",
+ "version": "0.2.52",
"type": "module",
"description": "@wrnexus/mobile — part of the WrNexus framework.",
"license": "MIT",
@@ -21,7 +21,7 @@
}
},
"dependencies": {
- "@wrnexus/native": "^0.2.51"
+ "@wrnexus/native": "^0.2.52"
},
"files": [
"dist"
diff --git a/.publish/native/package.json b/.publish/native/package.json
index 1f8192b2..e3e918e7 100644
--- a/.publish/native/package.json
+++ b/.publish/native/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/native",
- "version": "0.2.51",
+ "version": "0.2.52",
"type": "module",
"description": "@wrnexus/native — part of the WrNexus framework.",
"license": "MIT",
diff --git a/.publish/oauth/package.json b/.publish/oauth/package.json
index 23b563bc..b5c14e48 100644
--- a/.publish/oauth/package.json
+++ b/.publish/oauth/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/oauth",
- "version": "0.2.51",
+ "version": "0.2.52",
"type": "module",
"description": "@wrnexus/oauth — part of the WrNexus framework.",
"license": "MIT",
diff --git a/.publish/pubsub/package.json b/.publish/pubsub/package.json
index ca709f38..03095911 100644
--- a/.publish/pubsub/package.json
+++ b/.publish/pubsub/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/pubsub",
- "version": "0.2.51",
+ "version": "0.2.52",
"type": "module",
"description": "@wrnexus/pubsub — part of the WrNexus framework.",
"license": "MIT",
diff --git a/.publish/queue/package.json b/.publish/queue/package.json
index 835c6c9b..59f22f8f 100644
--- a/.publish/queue/package.json
+++ b/.publish/queue/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/queue",
- "version": "0.2.51",
+ "version": "0.2.52",
"type": "module",
"description": "@wrnexus/queue — part of the WrNexus framework.",
"license": "MIT",
diff --git a/.publish/reactive/package.json b/.publish/reactive/package.json
index 255afb24..062b082f 100644
--- a/.publish/reactive/package.json
+++ b/.publish/reactive/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/reactive",
- "version": "0.2.51",
+ "version": "0.2.52",
"type": "module",
"description": "@wrnexus/reactive — part of the WrNexus framework.",
"license": "MIT",
diff --git a/.publish/router/package.json b/.publish/router/package.json
index b7f621d8..39e36c52 100644
--- a/.publish/router/package.json
+++ b/.publish/router/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/router",
- "version": "0.2.51",
+ "version": "0.2.52",
"type": "module",
"description": "@wrnexus/router — part of the WrNexus framework.",
"license": "MIT",
@@ -21,8 +21,8 @@
}
},
"dependencies": {
- "@wrnexus/compiler": "^0.2.51",
- "@wrnexus/core": "^0.2.51"
+ "@wrnexus/compiler": "^0.2.52",
+ "@wrnexus/core": "^0.2.52"
},
"files": [
"dist"
diff --git a/.publish/ssr/package.json b/.publish/ssr/package.json
index 63997d61..0ffdd411 100644
--- a/.publish/ssr/package.json
+++ b/.publish/ssr/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/ssr",
- "version": "0.2.51",
+ "version": "0.2.52",
"type": "module",
"description": "@wrnexus/ssr — part of the WrNexus framework.",
"license": "MIT",
@@ -21,7 +21,7 @@
}
},
"dependencies": {
- "@wrnexus/core": "^0.2.51"
+ "@wrnexus/core": "^0.2.52"
},
"files": [
"dist"
diff --git a/.publish/styles/package.json b/.publish/styles/package.json
index 066b454c..3628991b 100644
--- a/.publish/styles/package.json
+++ b/.publish/styles/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/styles",
- "version": "0.2.51",
+ "version": "0.2.52",
"type": "module",
"description": "@wrnexus/styles — part of the WrNexus framework.",
"license": "MIT",
@@ -21,7 +21,7 @@
}
},
"dependencies": {
- "@wrnexus/uploader": "^0.2.51"
+ "@wrnexus/uploader": "^0.2.52"
},
"files": [
"dist"
diff --git a/.publish/test/package.json b/.publish/test/package.json
index 3463d98c..57b08fee 100644
--- a/.publish/test/package.json
+++ b/.publish/test/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/test",
- "version": "0.2.51",
+ "version": "0.2.52",
"type": "module",
"description": "@wrnexus/test — part of the WrNexus framework.",
"license": "MIT",
diff --git a/.publish/tracking/package.json b/.publish/tracking/package.json
index 2dba0a11..0a328b7f 100644
--- a/.publish/tracking/package.json
+++ b/.publish/tracking/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/tracking",
- "version": "0.2.51",
+ "version": "0.2.52",
"type": "module",
"description": "@wrnexus/tracking — part of the WrNexus framework.",
"license": "MIT",
diff --git a/.publish/ui/README.md b/.publish/ui/README.md
index c9f2a6b3..2c59dba4 100644
--- a/.publish/ui/README.md
+++ b/.publish/ui/README.md
@@ -65,7 +65,7 @@ body from either a named prop or the default slot.
### Additional controls & data display
Also shipped: `select`, `radio`, `switch`, `progress`, `tag`, `skeleton`,
-`tooltip`, and `table`.
+`tooltip`, `table`, `FAQAccordion`, `AnnouncementBar`, and `BackToTop`.
The authoritative, always-current list is `uiComponentNames()` (below), which reads
the component directory at runtime.
diff --git a/.publish/ui/components/AnnouncementBar.wrn b/.publish/ui/components/AnnouncementBar.wrn
new file mode 100644
index 00000000..eac8f090
--- /dev/null
+++ b/.publish/ui/components/AnnouncementBar.wrn
@@ -0,0 +1,88 @@
+component AnnouncementBar {
+ props {
+ badge = "New"
+ message = "WrNexus Organizations is now available."
+ description = "Build secure multi-tenant applications with teams, roles, domains, and enterprise SSO."
+ href = "/organizations"
+ actionLabel = "Explore organizations"
+ ariaLabel = "Announcement"
+ }
+
+ state visible = true
+
+ view {
+
+ }
+}
diff --git a/.publish/ui/components/BackToTop.wrn b/.publish/ui/components/BackToTop.wrn
new file mode 100644
index 00000000..a4670fa6
--- /dev/null
+++ b/.publish/ui/components/BackToTop.wrn
@@ -0,0 +1,93 @@
+component BackToTop {
+ props {
+ label = "Back to top"
+ assistiveLabel = "Return to the top of the page"
+ threshold = 500
+ }
+
+ state visible = false
+
+ functions {
+ function updateBackToTopVisibility() {
+ visible = window.scrollY > threshold
+ }
+
+ function scrollToTop() {
+ window.scrollTo({
+ top: 0,
+ behavior: "smooth"
+ })
+ }
+ }
+
+ lifecycle {
+ mount {
+ updateBackToTopVisibility()
+
+ window.addEventListener(
+ "scroll",
+ updateBackToTopVisibility,
+ { passive: true }
+ )
+ }
+
+ unmount {
+ window.removeEventListener(
+ "scroll",
+ updateBackToTopVisibility
+ )
+ }
+ }
+
+ watch visible {
+ console.debug(
+ "Back-to-top visibility:",
+ value,
+ previous
+ )
+ }
+
+ view {
+
+
+
+ {label}
+
+
+
+
+
+
+
+
+
+
+ }
+}
diff --git a/.publish/ui/components/FAQAccordion.wrn b/.publish/ui/components/FAQAccordion.wrn
new file mode 100644
index 00000000..a9e74e1b
--- /dev/null
+++ b/.publish/ui/components/FAQAccordion.wrn
@@ -0,0 +1,234 @@
+component FAQAccordion {
+ props {
+ eyebrow = ""
+ title = "Frequently asked questions"
+ description = ""
+
+ items = []
+
+ centered = true
+ compact = false
+
+ allowMultiple = false
+ defaultOpenIndex = 0
+
+ showContact = false
+ contactText = "Still have questions?"
+ contactLabel = "Contact support"
+ contactHref = "/support"
+ }
+
+ state openIndexes = defaultOpenIndex >= 0 ? [defaultOpenIndex] : []
+
+ functions {
+ function isOpen(index) {
+ return openIndexes.includes(index)
+ }
+
+ function toggleItem(index) {
+ if (isOpen(index)) {
+ openIndexes = openIndexes.filter(
+ (itemIndex) => itemIndex !== index
+ )
+ } else if (allowMultiple) {
+ openIndexes = [...openIndexes, index]
+ } else {
+ openIndexes = [index]
+ }
+ }
+ }
+
+ view {
+
+
+
+
+
+
+
+ {eyebrow}
+
+
+
+
+ {title}
+
+
+
+
+ {description}
+
+
+
+
+
+
+
+
+
+ {#each items as item, index}
+
+
+
+
+
+
+
+ {/each}
+
+
+
+
+
+
+
+
+ }
+}
diff --git a/.publish/ui/package.json b/.publish/ui/package.json
index 0c861e73..93915012 100644
--- a/.publish/ui/package.json
+++ b/.publish/ui/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/ui",
- "version": "0.2.51",
+ "version": "0.2.52",
"type": "module",
"description": "@wrnexus/ui — part of the WrNexus framework.",
"license": "MIT",
@@ -23,7 +23,7 @@
"./ui.css": "./ui.css"
},
"dependencies": {
- "@wrnexus/core": "^0.2.51"
+ "@wrnexus/core": "^0.2.52"
},
"files": [
"dist",
diff --git a/.publish/uploader/package.json b/.publish/uploader/package.json
index 1e836b17..b7c1aadf 100644
--- a/.publish/uploader/package.json
+++ b/.publish/uploader/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/uploader",
- "version": "0.2.51",
+ "version": "0.2.52",
"type": "module",
"description": "@wrnexus/uploader — part of the WrNexus framework.",
"license": "MIT",
@@ -21,7 +21,7 @@
}
},
"dependencies": {
- "@wrnexus/core": "^0.2.51"
+ "@wrnexus/core": "^0.2.52"
},
"files": [
"dist"
diff --git a/.publish/validation/package.json b/.publish/validation/package.json
index 90ddfb11..8ecb7622 100644
--- a/.publish/validation/package.json
+++ b/.publish/validation/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/validation",
- "version": "0.2.51",
+ "version": "0.2.52",
"type": "module",
"description": "@wrnexus/validation — part of the WrNexus framework.",
"license": "MIT",
diff --git a/editors/vscode/test/diagnostics.test.js b/editors/vscode/test/diagnostics.test.js
index aff1a999..27725198 100644
--- a/editors/vscode/test/diagnostics.test.js
+++ b/editors/vscode/test/diagnostics.test.js
@@ -33,7 +33,7 @@ const {
} = require("../src/diagnostics");
Module._load = originalLoad;
-function mockDocument(source) {
+function mockDocument() {
return {
positionAt(offset) {
return offset;
diff --git a/packages/ai/package.json b/packages/ai/package.json
index 1e7eed9f..759018a6 100644
--- a/packages/ai/package.json
+++ b/packages/ai/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/ai",
- "version": "0.2.51",
+ "version": "0.2.52",
"private": true,
"type": "module",
"description": "Zero-dependency Claude (Anthropic) client for WrNexus apps.",
diff --git a/packages/authz/package.json b/packages/authz/package.json
index 0b1f8614..9dbf92c3 100644
--- a/packages/authz/package.json
+++ b/packages/authz/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/authz",
- "version": "0.2.51",
+ "version": "0.2.52",
"private": true,
"type": "module",
"main": "src/index.ts",
diff --git a/packages/cli/package.json b/packages/cli/package.json
index 73d28dae..dfc60de4 100644
--- a/packages/cli/package.json
+++ b/packages/cli/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/cli",
- "version": "0.2.51",
+ "version": "0.2.52",
"type": "module",
"main": "src/index.ts",
"exports": {
diff --git a/packages/cli/src/update.ts b/packages/cli/src/update.ts
index 16591c07..26e2ee61 100644
--- a/packages/cli/src/update.ts
+++ b/packages/cli/src/update.ts
@@ -533,6 +533,14 @@ const MIGRATIONS: Migration[] = [
// No generated application files require automatic migration.
},
},
+ {
+ version: "0.2.52",
+ id: "shared-marketing-components",
+ description: "Adds reusable FAQ, announcement, and back-to-top UI components.",
+ apply() {
+ // No generated application files require automatic migration.
+ },
+ },
];
/** Release tooling uses this to require an explicit migration entry per version. */
diff --git a/packages/compiler/package.json b/packages/compiler/package.json
index 72c7de50..48bc25b0 100644
--- a/packages/compiler/package.json
+++ b/packages/compiler/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/compiler",
- "version": "0.2.51",
+ "version": "0.2.52",
"type": "module",
"main": "src/index.ts",
"exports": {
diff --git a/packages/core/package.json b/packages/core/package.json
index 035d10e8..194aa925 100644
--- a/packages/core/package.json
+++ b/packages/core/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/core",
- "version": "0.2.51",
+ "version": "0.2.52",
"type": "module",
"main": "src/index.ts",
"exports": {
diff --git a/packages/csr/package.json b/packages/csr/package.json
index efe7758d..bd349a92 100644
--- a/packages/csr/package.json
+++ b/packages/csr/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/csr",
- "version": "0.2.51",
+ "version": "0.2.52",
"type": "module",
"main": "src/index.ts",
"exports": {
diff --git a/packages/db/package.json b/packages/db/package.json
index 3673e882..e5a72026 100644
--- a/packages/db/package.json
+++ b/packages/db/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/db",
- "version": "0.2.51",
+ "version": "0.2.52",
"private": true,
"type": "module",
"main": "src/index.ts",
diff --git a/packages/dev-server/package.json b/packages/dev-server/package.json
index f1ec8c4e..2494b9c5 100644
--- a/packages/dev-server/package.json
+++ b/packages/dev-server/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/dev-server",
- "version": "0.2.51",
+ "version": "0.2.52",
"type": "module",
"main": "src/index.ts",
"exports": {
diff --git a/packages/encryption/package.json b/packages/encryption/package.json
index e8df45c8..d2d6c3f9 100644
--- a/packages/encryption/package.json
+++ b/packages/encryption/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/encryption",
- "version": "0.2.51",
+ "version": "0.2.52",
"private": true,
"type": "module",
"main": "src/index.ts",
diff --git a/packages/helpers/package.json b/packages/helpers/package.json
index c049b1d1..b6e5b1d0 100644
--- a/packages/helpers/package.json
+++ b/packages/helpers/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/helpers",
- "version": "0.2.51",
+ "version": "0.2.52",
"private": true,
"type": "module",
"description": "Safe convenience helpers for WrNexus request contexts and common application flows.",
diff --git a/packages/i18n/package.json b/packages/i18n/package.json
index 8a163abf..e27f97c0 100644
--- a/packages/i18n/package.json
+++ b/packages/i18n/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/i18n",
- "version": "0.2.51",
+ "version": "0.2.52",
"private": true,
"type": "module",
"main": "src/index.ts",
diff --git a/packages/jwt/package.json b/packages/jwt/package.json
index d4f833f6..8fb2c6a3 100644
--- a/packages/jwt/package.json
+++ b/packages/jwt/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/jwt",
- "version": "0.2.51",
+ "version": "0.2.52",
"private": true,
"type": "module",
"main": "src/index.ts",
diff --git a/packages/mobile/package.json b/packages/mobile/package.json
index 4d6b6d07..ff94ab0d 100644
--- a/packages/mobile/package.json
+++ b/packages/mobile/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/mobile",
- "version": "0.2.51",
+ "version": "0.2.52",
"type": "module",
"main": "src/index.ts",
"exports": {
diff --git a/packages/native/package.json b/packages/native/package.json
index 4fd8dd48..c5d57df9 100644
--- a/packages/native/package.json
+++ b/packages/native/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/native",
- "version": "0.2.51",
+ "version": "0.2.52",
"type": "module",
"main": "src/index.ts",
"exports": {
diff --git a/packages/oauth/package.json b/packages/oauth/package.json
index 2fd7c03a..da3bfa4c 100644
--- a/packages/oauth/package.json
+++ b/packages/oauth/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/oauth",
- "version": "0.2.51",
+ "version": "0.2.52",
"private": true,
"type": "module",
"main": "src/index.ts",
diff --git a/packages/pubsub/package.json b/packages/pubsub/package.json
index 13aa3d9d..a535d33b 100644
--- a/packages/pubsub/package.json
+++ b/packages/pubsub/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/pubsub",
- "version": "0.2.51",
+ "version": "0.2.52",
"private": true,
"type": "module",
"main": "src/index.ts",
diff --git a/packages/queue/package.json b/packages/queue/package.json
index 77b641d6..fbcb6a92 100644
--- a/packages/queue/package.json
+++ b/packages/queue/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/queue",
- "version": "0.2.51",
+ "version": "0.2.52",
"private": true,
"type": "module",
"main": "src/index.ts",
diff --git a/packages/reactive/package.json b/packages/reactive/package.json
index f93b08c5..8f8d2fa2 100644
--- a/packages/reactive/package.json
+++ b/packages/reactive/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/reactive",
- "version": "0.2.51",
+ "version": "0.2.52",
"type": "module",
"main": "src/index.ts",
"exports": {
diff --git a/packages/router/package.json b/packages/router/package.json
index 2060649d..434e5a13 100644
--- a/packages/router/package.json
+++ b/packages/router/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/router",
- "version": "0.2.51",
+ "version": "0.2.52",
"type": "module",
"main": "src/index.ts",
"exports": {
diff --git a/packages/ssr/package.json b/packages/ssr/package.json
index 91302234..94d7cc5c 100644
--- a/packages/ssr/package.json
+++ b/packages/ssr/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/ssr",
- "version": "0.2.51",
+ "version": "0.2.52",
"type": "module",
"main": "src/index.ts",
"exports": {
diff --git a/packages/styles/package.json b/packages/styles/package.json
index 91b646ab..a28dba94 100644
--- a/packages/styles/package.json
+++ b/packages/styles/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/styles",
- "version": "0.2.51",
+ "version": "0.2.52",
"type": "module",
"main": "src/index.ts",
"exports": {
diff --git a/packages/test/package.json b/packages/test/package.json
index 90ee93ca..e23e27f3 100644
--- a/packages/test/package.json
+++ b/packages/test/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/test",
- "version": "0.2.51",
+ "version": "0.2.52",
"private": true,
"type": "module",
"main": "src/index.ts",
diff --git a/packages/tracking/package.json b/packages/tracking/package.json
index e0c309d6..cd4cb4ac 100644
--- a/packages/tracking/package.json
+++ b/packages/tracking/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/tracking",
- "version": "0.2.51",
+ "version": "0.2.52",
"private": true,
"type": "module",
"main": "src/index.ts",
diff --git a/packages/ui/README.md b/packages/ui/README.md
index c9f2a6b3..2c59dba4 100644
--- a/packages/ui/README.md
+++ b/packages/ui/README.md
@@ -65,7 +65,7 @@ body from either a named prop or the default slot.
### Additional controls & data display
Also shipped: `select`, `radio`, `switch`, `progress`, `tag`, `skeleton`,
-`tooltip`, and `table`.
+`tooltip`, `table`, `FAQAccordion`, `AnnouncementBar`, and `BackToTop`.
The authoritative, always-current list is `uiComponentNames()` (below), which reads
the component directory at runtime.
diff --git a/packages/ui/components/AnnouncementBar.wrn b/packages/ui/components/AnnouncementBar.wrn
new file mode 100644
index 00000000..eac8f090
--- /dev/null
+++ b/packages/ui/components/AnnouncementBar.wrn
@@ -0,0 +1,88 @@
+component AnnouncementBar {
+ props {
+ badge = "New"
+ message = "WrNexus Organizations is now available."
+ description = "Build secure multi-tenant applications with teams, roles, domains, and enterprise SSO."
+ href = "/organizations"
+ actionLabel = "Explore organizations"
+ ariaLabel = "Announcement"
+ }
+
+ state visible = true
+
+ view {
+
+ }
+}
diff --git a/packages/ui/components/BackToTop.wrn b/packages/ui/components/BackToTop.wrn
new file mode 100644
index 00000000..a4670fa6
--- /dev/null
+++ b/packages/ui/components/BackToTop.wrn
@@ -0,0 +1,93 @@
+component BackToTop {
+ props {
+ label = "Back to top"
+ assistiveLabel = "Return to the top of the page"
+ threshold = 500
+ }
+
+ state visible = false
+
+ functions {
+ function updateBackToTopVisibility() {
+ visible = window.scrollY > threshold
+ }
+
+ function scrollToTop() {
+ window.scrollTo({
+ top: 0,
+ behavior: "smooth"
+ })
+ }
+ }
+
+ lifecycle {
+ mount {
+ updateBackToTopVisibility()
+
+ window.addEventListener(
+ "scroll",
+ updateBackToTopVisibility,
+ { passive: true }
+ )
+ }
+
+ unmount {
+ window.removeEventListener(
+ "scroll",
+ updateBackToTopVisibility
+ )
+ }
+ }
+
+ watch visible {
+ console.debug(
+ "Back-to-top visibility:",
+ value,
+ previous
+ )
+ }
+
+ view {
+
+
+
+ {label}
+
+
+
+
+
+
+
+
+
+
+ }
+}
diff --git a/packages/ui/components/FAQAccordion.wrn b/packages/ui/components/FAQAccordion.wrn
new file mode 100644
index 00000000..a9e74e1b
--- /dev/null
+++ b/packages/ui/components/FAQAccordion.wrn
@@ -0,0 +1,234 @@
+component FAQAccordion {
+ props {
+ eyebrow = ""
+ title = "Frequently asked questions"
+ description = ""
+
+ items = []
+
+ centered = true
+ compact = false
+
+ allowMultiple = false
+ defaultOpenIndex = 0
+
+ showContact = false
+ contactText = "Still have questions?"
+ contactLabel = "Contact support"
+ contactHref = "/support"
+ }
+
+ state openIndexes = defaultOpenIndex >= 0 ? [defaultOpenIndex] : []
+
+ functions {
+ function isOpen(index) {
+ return openIndexes.includes(index)
+ }
+
+ function toggleItem(index) {
+ if (isOpen(index)) {
+ openIndexes = openIndexes.filter(
+ (itemIndex) => itemIndex !== index
+ )
+ } else if (allowMultiple) {
+ openIndexes = [...openIndexes, index]
+ } else {
+ openIndexes = [index]
+ }
+ }
+ }
+
+ view {
+
+
+
+
+
+
+
+ {eyebrow}
+
+
+
+
+ {title}
+
+
+
+
+ {description}
+
+
+
+
+
+
+
+
+
+ {#each items as item, index}
+
+
+
+
+
+
+
+ {/each}
+
+
+
+
+
+
+
+
+ }
+}
diff --git a/packages/ui/package.json b/packages/ui/package.json
index ca5953a9..7947b079 100644
--- a/packages/ui/package.json
+++ b/packages/ui/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/ui",
- "version": "0.2.51",
+ "version": "0.2.52",
"private": true,
"type": "module",
"main": "src/index.ts",
diff --git a/packages/ui/test/ui.test.ts b/packages/ui/test/ui.test.ts
index 39e27fe1..1222f640 100644
--- a/packages/ui/test/ui.test.ts
+++ b/packages/ui/test/ui.test.ts
@@ -6,6 +6,9 @@ import { uiComponentNames, uiComponentsDir, uiCss } from "../src/index.ts";
test("bundled UI assets are discoverable and readable", () => {
expect(uiComponentNames()).toContain("Button");
+ expect(uiComponentNames()).toContain("FAQAccordion");
+ expect(uiComponentNames()).toContain("AnnouncementBar");
+ expect(uiComponentNames()).toContain("BackToTop");
expect(readFileSync(join(uiComponentsDir(), "Button.wrn"), "utf8")).toContain("component Button");
expect(uiCss()).toContain("--wire-");
});
diff --git a/packages/uploader/package.json b/packages/uploader/package.json
index 82ca40bc..c0ac361d 100644
--- a/packages/uploader/package.json
+++ b/packages/uploader/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/uploader",
- "version": "0.2.51",
+ "version": "0.2.52",
"private": true,
"type": "module",
"main": "src/index.ts",
diff --git a/packages/validation/package.json b/packages/validation/package.json
index f18249f2..bd2e623d 100644
--- a/packages/validation/package.json
+++ b/packages/validation/package.json
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/validation",
- "version": "0.2.51",
+ "version": "0.2.52",
"private": true,
"type": "module",
"main": "src/index.ts",
diff --git a/update-package-versions.mjs b/update-package-versions.mjs
index 2835856e..ce1b0fc1 100644
--- a/update-package-versions.mjs
+++ b/update-package-versions.mjs
@@ -1,7 +1,7 @@
import { existsSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
import { join } from "node:path";
-const version = "0.2.51";
+const version = "0.2.52";
const dependencyGroups = [
"dependencies",