Compare commits
20
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
247f360ae7 | ||
|
|
790b81330a | ||
|
|
69020b2555 | ||
|
|
9ed896d2b9 | ||
|
|
8389d9674e | ||
|
|
5112cc1a62 | ||
|
|
30d1632252 | ||
|
|
7a2b58652a | ||
|
|
5e65627305 | ||
|
|
84dc4e06a2 | ||
|
|
c7ab605e85 | ||
|
|
8aa28205e0 | ||
|
|
b56cb8cba5 | ||
|
|
b3a4d80df3 | ||
|
|
7bd4574b08 | ||
|
|
e32d83933e | ||
|
|
5ce2771718 | ||
|
|
68c7b96a9f | ||
|
|
6a9c48a207 | ||
|
|
9a03b7c8d4 |
+20
-2
@@ -1,11 +1,29 @@
|
|||||||
{
|
{
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"configurations": [
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "basic-app",
|
||||||
|
"runtimeExecutable": "bun",
|
||||||
|
"runtimeArgs": [
|
||||||
|
"run",
|
||||||
|
"packages/cli/src/index.ts",
|
||||||
|
"dev",
|
||||||
|
"examples/basic-app",
|
||||||
|
"--port=3520"
|
||||||
|
],
|
||||||
|
"port": 3520
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "component-showcase",
|
"name": "component-showcase",
|
||||||
"runtimeExecutable": "bun",
|
"runtimeExecutable": "bun",
|
||||||
"runtimeArgs": ["run", "--cwd", "examples/component-showcase", "dev"],
|
"runtimeArgs": [
|
||||||
"port": 3000
|
"run",
|
||||||
|
"packages/cli/src/index.ts",
|
||||||
|
"dev",
|
||||||
|
"examples/component-showcase",
|
||||||
|
"--port=3400"
|
||||||
|
],
|
||||||
|
"port": 3400
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/ai",
|
"name": "@wrnexus/ai",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "Zero-dependency Claude (Anthropic) client for WrNexus apps.",
|
"description": "Zero-dependency Claude (Anthropic) client for WrNexus apps.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/authz",
|
"name": "@wrnexus/authz",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/authz — part of the WrNexus framework.",
|
"description": "@wrnexus/authz — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -41,8 +41,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "^0.8.5",
|
"@wrnexus/core": "^0.8.6",
|
||||||
"@wrnexus/db": "^0.8.5"
|
"@wrnexus/db": "^0.8.6"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist",
|
"dist",
|
||||||
|
|||||||
+18
-18
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/cli",
|
"name": "@wrnexus/cli",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/cli — part of the WrNexus framework.",
|
"description": "@wrnexus/cli — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -44,23 +44,23 @@
|
|||||||
"wrnexus": "./dist/index.js"
|
"wrnexus": "./dist/index.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "^0.8.5",
|
"@wrnexus/core": "^0.8.6",
|
||||||
"@wrnexus/router": "^0.8.5",
|
"@wrnexus/router": "^0.8.6",
|
||||||
"@wrnexus/csr": "^0.8.5",
|
"@wrnexus/csr": "^0.8.6",
|
||||||
"@wrnexus/compiler": "^0.8.5",
|
"@wrnexus/compiler": "^0.8.6",
|
||||||
"@wrnexus/styles": "^0.8.5",
|
"@wrnexus/styles": "^0.8.6",
|
||||||
"@wrnexus/dev-server": "^0.8.5",
|
"@wrnexus/dev-server": "^0.8.6",
|
||||||
"@wrnexus/ui": "^0.8.5",
|
"@wrnexus/ui": "^0.8.6",
|
||||||
"@wrnexus/validation": "^0.8.5",
|
"@wrnexus/validation": "^0.8.6",
|
||||||
"@wrnexus/i18n": "^0.8.5",
|
"@wrnexus/i18n": "^0.8.6",
|
||||||
"@wrnexus/mcp": "^0.8.5",
|
"@wrnexus/mcp": "^0.8.6",
|
||||||
"@wrnexus/playground": "^0.8.5",
|
"@wrnexus/playground": "^0.8.6",
|
||||||
"@wrnexus/db": "^0.8.5",
|
"@wrnexus/db": "^0.8.6",
|
||||||
"@wrnexus/authz": "^0.8.5",
|
"@wrnexus/authz": "^0.8.6",
|
||||||
"@wrnexus/plugin": "^0.8.5",
|
"@wrnexus/plugin": "^0.8.6",
|
||||||
"@wrnexus/syntax": "^0.8.5",
|
"@wrnexus/syntax": "^0.8.6",
|
||||||
"@wrnexus/typecheck": "^0.8.5",
|
"@wrnexus/typecheck": "^0.8.6",
|
||||||
"@wrnexus/security": "^0.8.5",
|
"@wrnexus/security": "^0.8.6",
|
||||||
"selfsigned": "^5.5.0"
|
"selfsigned": "^5.5.0"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/compiler",
|
"name": "@wrnexus/compiler",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/compiler — part of the WrNexus framework.",
|
"description": "@wrnexus/compiler — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -37,10 +37,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/csr": "^0.8.5",
|
"@wrnexus/csr": "^0.8.6",
|
||||||
"@wrnexus/syntax": "^0.8.5",
|
"@wrnexus/syntax": "^0.8.6",
|
||||||
"@wrnexus/store": "^0.8.5",
|
"@wrnexus/store": "^0.8.6",
|
||||||
"@wrnexus/validation": "^0.8.5"
|
"@wrnexus/validation": "^0.8.6"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist",
|
"dist",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/core",
|
"name": "@wrnexus/core",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/core — part of the WrNexus framework.",
|
"description": "@wrnexus/core — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/csr",
|
"name": "@wrnexus/csr",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/csr — part of the WrNexus framework.",
|
"description": "@wrnexus/csr — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "^0.8.5"
|
"@wrnexus/core": "^0.8.6"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist",
|
"dist",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/db",
|
"name": "@wrnexus/db",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "Typed database drivers, migrations, instrumentation, repositories, pagination, and transaction helpers.",
|
"description": "Typed database drivers, migrations, instrumentation, repositories, pagination, and transaction helpers.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/dev-server",
|
"name": "@wrnexus/dev-server",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/dev-server — part of the WrNexus framework.",
|
"description": "@wrnexus/dev-server — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -41,27 +41,27 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/authz": "^0.8.5",
|
"@wrnexus/authz": "^0.8.6",
|
||||||
"@wrnexus/rpc": "^0.8.5",
|
"@wrnexus/rpc": "^0.8.6",
|
||||||
"@wrnexus/core": "^0.8.5",
|
"@wrnexus/core": "^0.8.6",
|
||||||
"@wrnexus/dev-toolbar": "^0.8.5",
|
"@wrnexus/dev-toolbar": "^0.8.6",
|
||||||
"@wrnexus/router": "^0.8.5",
|
"@wrnexus/router": "^0.8.6",
|
||||||
"@wrnexus/ssr": "^0.8.5",
|
"@wrnexus/ssr": "^0.8.6",
|
||||||
"@wrnexus/csr": "^0.8.5",
|
"@wrnexus/csr": "^0.8.6",
|
||||||
"@wrnexus/compiler": "^0.8.5",
|
"@wrnexus/compiler": "^0.8.6",
|
||||||
"@wrnexus/styles": "^0.8.5",
|
"@wrnexus/styles": "^0.8.6",
|
||||||
"@wrnexus/ui": "^0.8.5",
|
"@wrnexus/ui": "^0.8.6",
|
||||||
"@wrnexus/validation": "^0.8.5",
|
"@wrnexus/validation": "^0.8.6",
|
||||||
"@wrnexus/i18n": "^0.8.5",
|
"@wrnexus/i18n": "^0.8.6",
|
||||||
"@wrnexus/db": "^0.8.5",
|
"@wrnexus/db": "^0.8.6",
|
||||||
"@wrnexus/pubsub": "^0.8.5",
|
"@wrnexus/pubsub": "^0.8.6",
|
||||||
"@wrnexus/uploader": "^0.8.5",
|
"@wrnexus/uploader": "^0.8.6",
|
||||||
"@wrnexus/plugin": "^0.8.5",
|
"@wrnexus/plugin": "^0.8.6",
|
||||||
"@wrnexus/store": "^0.8.5",
|
"@wrnexus/store": "^0.8.6",
|
||||||
"@wrnexus/security": "^0.8.5",
|
"@wrnexus/security": "^0.8.6",
|
||||||
"@wrnexus/observability": "^0.8.5",
|
"@wrnexus/observability": "^0.8.6",
|
||||||
"@wrnexus/cache": "^0.8.5",
|
"@wrnexus/cache": "^0.8.6",
|
||||||
"@wrnexus/pwa": "^0.8.5"
|
"@wrnexus/pwa": "^0.8.6"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist",
|
"dist",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/dev-toolbar",
|
"name": "@wrnexus/dev-toolbar",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/dev-toolbar — part of the WrNexus framework.",
|
"description": "@wrnexus/dev-toolbar — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/encryption",
|
"name": "@wrnexus/encryption",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "Authenticated encryption, key rotation, hashing, and optional application-layer encrypted HTTP envelopes.",
|
"description": "Authenticated encryption, key rotation, hashing, and optional application-layer encrypted HTTP envelopes.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "^0.8.5"
|
"@wrnexus/core": "^0.8.6"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist",
|
"dist",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/helpers",
|
"name": "@wrnexus/helpers",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "Safe convenience helpers for WrNexus request contexts and common application flows.",
|
"description": "Safe convenience helpers for WrNexus request contexts and common application flows.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "^0.8.5"
|
"@wrnexus/core": "^0.8.6"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist",
|
"dist",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/i18n",
|
"name": "@wrnexus/i18n",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "Locale loading, fallback resolution, SSR/browser translations, formatters, and WRNexusJS language components.",
|
"description": "Locale loading, fallback resolution, SSR/browser translations, formatters, and WRNexusJS language components.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -42,9 +42,9 @@
|
|||||||
"./components/*": "./components/*"
|
"./components/*": "./components/*"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "^0.8.5",
|
"@wrnexus/core": "^0.8.6",
|
||||||
"@wrnexus/plugin": "^0.8.5",
|
"@wrnexus/plugin": "^0.8.6",
|
||||||
"@wrnexus/ui": "^0.8.5"
|
"@wrnexus/ui": "^0.8.6"
|
||||||
},
|
},
|
||||||
"wrnexus": {
|
"wrnexus": {
|
||||||
"plugin": {
|
"plugin": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/jwt",
|
"name": "@wrnexus/jwt",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "HS256 JSON Web Tokens, key rotation, access/refresh helpers, scopes, cookies, and auth middleware.",
|
"description": "HS256 JSON Web Tokens, key rotation, access/refresh helpers, scopes, cookies, and auth middleware.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "^0.8.5"
|
"@wrnexus/core": "^0.8.6"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist",
|
"dist",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/mobile",
|
"name": "@wrnexus/mobile",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/mobile — part of the WrNexus framework.",
|
"description": "@wrnexus/mobile — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/native": "^0.8.5"
|
"@wrnexus/native": "^0.8.6"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist",
|
"dist",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/native",
|
"name": "@wrnexus/native",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/native — part of the WrNexus framework.",
|
"description": "@wrnexus/native — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/oauth",
|
"name": "@wrnexus/oauth",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/oauth — part of the WrNexus framework.",
|
"description": "@wrnexus/oauth — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/jwt": "^0.8.5"
|
"@wrnexus/jwt": "^0.8.6"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist",
|
"dist",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/plugin",
|
"name": "@wrnexus/plugin",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/plugin — part of the WrNexus framework.",
|
"description": "@wrnexus/plugin — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -49,7 +49,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/syntax": "^0.8.5"
|
"@wrnexus/syntax": "^0.8.6"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist",
|
"dist",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/pubsub",
|
"name": "@wrnexus/pubsub",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/pubsub — part of the WrNexus framework.",
|
"description": "@wrnexus/pubsub — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/queue",
|
"name": "@wrnexus/queue",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/queue — part of the WrNexus framework.",
|
"description": "@wrnexus/queue — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "^0.8.5"
|
"@wrnexus/core": "^0.8.6"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist",
|
"dist",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/reactive",
|
"name": "@wrnexus/reactive",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/reactive — part of the WrNexus framework.",
|
"description": "@wrnexus/reactive — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/router",
|
"name": "@wrnexus/router",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/router — part of the WrNexus framework.",
|
"description": "@wrnexus/router — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -37,8 +37,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/compiler": "^0.8.5",
|
"@wrnexus/compiler": "^0.8.6",
|
||||||
"@wrnexus/core": "^0.8.5"
|
"@wrnexus/core": "^0.8.6"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist",
|
"dist",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/ssr",
|
"name": "@wrnexus/ssr",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/ssr — part of the WrNexus framework.",
|
"description": "@wrnexus/ssr — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -45,9 +45,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "^0.8.5",
|
"@wrnexus/core": "^0.8.6",
|
||||||
"@wrnexus/store": "^0.8.5",
|
"@wrnexus/store": "^0.8.6",
|
||||||
"@wrnexus/security": "^0.8.5"
|
"@wrnexus/security": "^0.8.6"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist",
|
"dist",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/styles",
|
"name": "@wrnexus/styles",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/styles — part of the WrNexus framework.",
|
"description": "@wrnexus/styles — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -37,9 +37,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/uploader": "^0.8.5",
|
"@wrnexus/uploader": "^0.8.6",
|
||||||
"@wrnexus/core": "^0.8.5",
|
"@wrnexus/core": "^0.8.6",
|
||||||
"@wrnexus/plugin": "^0.8.5"
|
"@wrnexus/plugin": "^0.8.6"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist",
|
"dist",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/syntax",
|
"name": "@wrnexus/syntax",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/syntax — part of the WrNexus framework.",
|
"description": "@wrnexus/syntax — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/test",
|
"name": "@wrnexus/test",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/test — part of the WrNexus framework.",
|
"description": "@wrnexus/test — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/tracking",
|
"name": "@wrnexus/tracking",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/tracking — part of the WrNexus framework.",
|
"description": "@wrnexus/tracking — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
+33
-33
@@ -229,7 +229,7 @@ Present structured responsive linked or status items with icons, descriptions, a
|
|||||||
- Mount: `data-component="List"`
|
- Mount: `data-component="List"`
|
||||||
- Props: `size: string = "default"`, `color: string = "primary"`, `title: string = "List"`, `description: string = ""`, `items: unknown[] = []`, `variant: string = "default"`, `class: string = ""`
|
- Props: `size: string = "default"`, `color: string = "primary"`, `title: string = "List"`, `description: string = ""`, `items: unknown[] = []`, `variant: string = "default"`, `class: string = ""`
|
||||||
- Slots: `default`
|
- Slots: `default`
|
||||||
- Outputs: None
|
- Outputs: `select({ sourceEvent?: Event; [key: string]: string | number | boolean | null | object })`
|
||||||
|
|
||||||
### ListGroup
|
### ListGroup
|
||||||
|
|
||||||
@@ -247,7 +247,7 @@ Continuously present responsive labels, partners, notices, or capabilities with
|
|||||||
- Mount: `data-component="Marquee"`
|
- Mount: `data-component="Marquee"`
|
||||||
- Props: `size: string = "default"`, `color: string = "primary"`, `title: string = "Marquee"`, `description: string = ""`, `items: unknown[] = []`, `variant: string = "default"`, `class: string = ""`
|
- Props: `size: string = "default"`, `color: string = "primary"`, `title: string = "Marquee"`, `description: string = ""`, `items: unknown[] = []`, `variant: string = "default"`, `class: string = ""`
|
||||||
- Slots: `default`
|
- Slots: `default`
|
||||||
- Outputs: None
|
- Outputs: `pause({ sourceEvent?: Event; [key: string]: string | number | boolean | null | object })`, `resume({ sourceEvent?: Event; [key: string]: string | number | boolean | null | object })`
|
||||||
|
|
||||||
### Progress
|
### Progress
|
||||||
|
|
||||||
@@ -301,7 +301,7 @@ Present responsive chronological activity, milestones, or workflow status with r
|
|||||||
- Mount: `data-component="Timeline"`
|
- Mount: `data-component="Timeline"`
|
||||||
- Props: `size: string = "default"`, `color: string = "primary"`, `title: string = "Timeline"`, `description: string = ""`, `items: unknown[] = []`, `variant: string = "default"`, `class: string = ""`
|
- Props: `size: string = "default"`, `color: string = "primary"`, `title: string = "Timeline"`, `description: string = ""`, `items: unknown[] = []`, `variant: string = "default"`, `class: string = ""`
|
||||||
- Slots: `default`
|
- Slots: `default`
|
||||||
- Outputs: None
|
- Outputs: `select({ sourceEvent?: Event; [key: string]: string | number | boolean | null | object })`
|
||||||
|
|
||||||
### Toast
|
### Toast
|
||||||
|
|
||||||
@@ -469,7 +469,7 @@ Provide an accessible responsive search field with labels, validation states, si
|
|||||||
- Mount: `data-component="SearchBox"`
|
- Mount: `data-component="SearchBox"`
|
||||||
- Props: `size: string = "default"`, `color: string = "primary"`, `label: string = "Search Box"`, `name: string = ""`, `value: string = ""`, `placeholder: string = ""`, `type: string = "search"`, `min: string = ""`, `max: string = ""`, `step: string = ""`, `disabled: boolean = false`, `required: boolean = false`, `class: string = ""`
|
- Props: `size: string = "default"`, `color: string = "primary"`, `label: string = "Search Box"`, `name: string = ""`, `value: string = ""`, `placeholder: string = ""`, `type: string = "search"`, `min: string = ""`, `max: string = ""`, `step: string = ""`, `disabled: boolean = false`, `required: boolean = false`, `class: string = ""`
|
||||||
- Slots: None
|
- Slots: None
|
||||||
- Outputs: None
|
- Outputs: `search({ sourceEvent?: Event; [key: string]: string | number | boolean | null | object })`, `clear({ sourceEvent?: Event; [key: string]: string | number | boolean | null | object })`
|
||||||
|
|
||||||
### Select
|
### Select
|
||||||
|
|
||||||
@@ -588,7 +588,7 @@ Present responsive location information and markers with map-ready metadata and
|
|||||||
- Mount: `data-component="Map"`
|
- Mount: `data-component="Map"`
|
||||||
- Props: `size: string = "default"`, `color: string = "primary"`, `title: string = "Map"`, `description: string = ""`, `items: unknown[] = []`, `variant: string = "default"`, `class: string = ""`
|
- Props: `size: string = "default"`, `color: string = "primary"`, `title: string = "Map"`, `description: string = ""`, `items: unknown[] = []`, `variant: string = "default"`, `class: string = ""`
|
||||||
- Slots: `default`
|
- Slots: `default`
|
||||||
- Outputs: None
|
- Outputs: `markerClick({ sourceEvent?: Event; [key: string]: string | number | boolean | null | object })`, `select({ sourceEvent?: Event; [key: string]: string | number | boolean | null | object })`, `zoom({ sourceEvent?: Event; [key: string]: string | number | boolean | null | object })`
|
||||||
|
|
||||||
### ToastNotifications
|
### ToastNotifications
|
||||||
|
|
||||||
@@ -624,7 +624,7 @@ Create responsive balanced content columns with configurable count, gap, density
|
|||||||
Constrain and align page content with responsive gutters and compact, wide, or full width options.
|
Constrain and align page content with responsive gutters and compact, wide, or full width options.
|
||||||
|
|
||||||
- Mount: `data-component="Container"`
|
- Mount: `data-component="Container"`
|
||||||
- Props: `size: string = "default"`, `color: string = "primary"`, `columns: number = 2`, `gap: string = "md"`, `maxWidth: string = "xl"`, `class: string = ""`
|
- Props: `size: string = "default"`, `color: string = "primary"`, `columns: number = 2`, `gap: string = "md"`, `maxWidth: string = "xl"`, `centered: boolean = true`, `class: string = ""`
|
||||||
- Slots: `default`
|
- Slots: `default`
|
||||||
- Outputs: None
|
- Outputs: None
|
||||||
|
|
||||||
@@ -633,16 +633,16 @@ Constrain and align page content with responsive gutters and compact, wide, or f
|
|||||||
Theme-aware, responsive custom scrollbar component.
|
Theme-aware, responsive custom scrollbar component.
|
||||||
|
|
||||||
- Mount: `data-component="CustomScrollbar"`
|
- Mount: `data-component="CustomScrollbar"`
|
||||||
- Props: `size: string = "default"`, `color: string = "primary"`, `columns: number = 2`, `gap: string = "md"`, `maxWidth: string = "xl"`, `class: string = ""`
|
- Props: `color: string = "primary"`, `size: string = "default"`, `axis: string = "vertical"`, `thickness: number = 8`, `maxHeight: string = "20rem"`, `radius: string = "999px"`, `class: string = ""`
|
||||||
- Slots: `default`
|
- Slots: `default`
|
||||||
- Outputs: `scroll({ sourceEvent?: Event; value: string | number | boolean | null | object; [key: string]: string | number | boolean | null | object } | string | number | boolean | null | object[])`
|
- Outputs: None
|
||||||
|
|
||||||
### Divider
|
### Divider
|
||||||
|
|
||||||
Separate related horizontal or vertical content with optional labels, sizes, and semantic colors.
|
Separate related horizontal or vertical content with optional labels, sizes, and semantic colors.
|
||||||
|
|
||||||
- Mount: `data-component="Divider"`
|
- Mount: `data-component="Divider"`
|
||||||
- Props: `size: string = "default"`, `color: string = "primary"`, `label: string = ""`, `orientation: string = "horizontal"`, `class: string = ""`
|
- Props: `size: string = "default"`, `color: string = "primary"`, `label: string = ""`, `orientation: string = "horizontal"`, `variant: string = "solid"`, `class: string = ""`
|
||||||
- Slots: None
|
- Slots: None
|
||||||
- Outputs: None
|
- Outputs: None
|
||||||
|
|
||||||
@@ -669,7 +669,7 @@ Render structured responsive footer navigation, pre and post content, copyright
|
|||||||
Arrange arbitrary content in a responsive configurable CSS grid with stable columns, gaps, alignment, and width.
|
Arrange arbitrary content in a responsive configurable CSS grid with stable columns, gaps, alignment, and width.
|
||||||
|
|
||||||
- Mount: `data-component="Grid"`
|
- Mount: `data-component="Grid"`
|
||||||
- Props: `size: string = "default"`, `color: string = "primary"`, `columns: number = 2`, `gap: string = "md"`, `maxWidth: string = "xl"`, `class: string = ""`
|
- Props: `size: string = "default"`, `color: string = "primary"`, `columns: number = 2`, `gap: string = "md"`, `maxWidth: string = "xl"`, `minItemWidth: string = ""`, `class: string = ""`
|
||||||
- Slots: `default`
|
- Slots: `default`
|
||||||
- Outputs: None
|
- Outputs: None
|
||||||
|
|
||||||
@@ -678,7 +678,7 @@ Arrange arbitrary content in a responsive configurable CSS grid with stable colu
|
|||||||
Render a responsive image with explicit dimensions, loading behavior, alternative text, sizing, and rounded treatment.
|
Render a responsive image with explicit dimensions, loading behavior, alternative text, sizing, and rounded treatment.
|
||||||
|
|
||||||
- Mount: `data-component="Image"`
|
- Mount: `data-component="Image"`
|
||||||
- Props: `size: string = "default"`, `color: string = "primary"`, `src: string = ""`, `alt: string = ""`, `width: string = ""`, `height: string = ""`, `loading: string = "lazy"`, `rounded: boolean = false`, `class: string = ""`
|
- Props: `size: string = "default"`, `color: string = "primary"`, `src: string = ""`, `alt: string = ""`, `width: string = ""`, `height: string = ""`, `loading: string = "lazy"`, `fit: string = "cover"`, `rounded: boolean = false`, `class: string = ""`
|
||||||
- Slots: `default`
|
- Slots: `default`
|
||||||
- Outputs: None
|
- Outputs: None
|
||||||
|
|
||||||
@@ -687,7 +687,7 @@ Render a responsive image with explicit dimensions, loading behavior, alternativ
|
|||||||
Theme-aware, responsive kbd component.
|
Theme-aware, responsive kbd component.
|
||||||
|
|
||||||
- Mount: `data-component="Kbd"`
|
- Mount: `data-component="Kbd"`
|
||||||
- Props: `size: string = "default"`, `color: string = "primary"`, `label: string = "⌘ K"`, `class: string = ""`
|
- Props: `size: string = "default"`, `color: string = "primary"`, `label: string = "K"`, `class: string = ""`
|
||||||
- Slots: `default`
|
- Slots: `default`
|
||||||
- Outputs: None
|
- Outputs: None
|
||||||
|
|
||||||
@@ -696,16 +696,16 @@ Theme-aware, responsive kbd component.
|
|||||||
Theme-aware, responsive layout splitter component.
|
Theme-aware, responsive layout splitter component.
|
||||||
|
|
||||||
- Mount: `data-component="LayoutSplitter"`
|
- Mount: `data-component="LayoutSplitter"`
|
||||||
- Props: `size: string = "default"`, `color: string = "primary"`, `columns: number = 2`, `gap: string = "md"`, `maxWidth: string = "xl"`, `class: string = ""`
|
- Props: `color: string = "primary"`, `size: number = 50`, `orientation: string = "horizontal"`, `minSize: number = 15`, `step: number = 5`, `label: string = "Resize panels"`, `class: string = ""`
|
||||||
- Slots: `default`
|
- Slots: `start`, `end`, `default`
|
||||||
- Outputs: `resizeStart({ sourceEvent?: Event; value: string | number | boolean | null | object; [key: string]: string | number | boolean | null | object } | string | number | boolean | null | object[])`, `resize({ sourceEvent?: Event; value: string | number | boolean | null | object; [key: string]: string | number | boolean | null | object } | string | number | boolean | null | object[])`, `resizeEnd({ sourceEvent?: Event; value: string | number | boolean | null | object; [key: string]: string | number | boolean | null | object } | string | number | boolean | null | object[])`
|
- Outputs: `sizeChange({ size: number })`
|
||||||
|
|
||||||
### Link
|
### Link
|
||||||
|
|
||||||
Render an accessible internal or external link with target, relation, size, color, and public focus or click events.
|
Render an accessible internal or external link with target, relation, size, color, and public focus or click events.
|
||||||
|
|
||||||
- Mount: `data-component="Link"`
|
- Mount: `data-component="Link"`
|
||||||
- Props: `size: string = "default"`, `color: string = "primary"`, `label: string = "Link"`, `href: string = "#"`, `target: string = ""`, `rel: string = ""`, `external: boolean = false`, `class: string = ""`
|
- Props: `size: string = "default"`, `color: string = "primary"`, `label: string = "Link"`, `href: string = "#"`, `target: string = ""`, `rel: string = ""`, `underline: string = "hover"`, `external: boolean = false`, `class: string = ""`
|
||||||
- Slots: `default`
|
- Slots: `default`
|
||||||
- Outputs: None
|
- Outputs: None
|
||||||
|
|
||||||
@@ -862,18 +862,18 @@ Show responsive hierarchical navigation with home support, separators, current-p
|
|||||||
Theme-aware, responsive mega menu component.
|
Theme-aware, responsive mega menu component.
|
||||||
|
|
||||||
- Mount: `data-component="MegaMenu"`
|
- Mount: `data-component="MegaMenu"`
|
||||||
- Props: `size: string = "default"`, `color: string = "primary"`, `label: string = "Mega Menu"`, `items: unknown[] = []`, `active: string = ""`, `orientation: string = "horizontal"`, `class: string = ""`
|
- Props: `color: string = "primary"`, `size: string = "default"`, `label: string = "Menu"`, `icon: string = ""`, `columns: unknown[] = []`, `footer: string = ""`, `defaultOpen: boolean = false`, `class: string = ""`
|
||||||
- Slots: `default`
|
- Slots: `default`
|
||||||
- Outputs: `open({ sourceEvent?: Event; [key: string]: string | number | boolean | null | object })`, `close({ sourceEvent?: Event; [key: string]: string | number | boolean | null | object })`, `select({ value?: string | number | boolean | null; values?: Array<string | number | boolean | null | object>; sourceEvent?: Event; [key: string]: string | number | boolean | null | object } | string | number | boolean | null)`
|
- Outputs: `open({ sourceEvent: Event })`, `close({ reason: string })`, `select({ item: object; value: string })`
|
||||||
|
|
||||||
### Nav
|
### Nav
|
||||||
|
|
||||||
Theme-aware, responsive nav component.
|
Theme-aware, responsive nav component.
|
||||||
|
|
||||||
- Mount: `data-component="Nav"`
|
- Mount: `data-component="Nav"`
|
||||||
- Props: `size: string = "default"`, `color: string = "primary"`, `label: string = "Nav"`, `items: unknown[] = []`, `active: string = ""`, `orientation: string = "horizontal"`, `class: string = ""`
|
- Props: `color: string = "primary"`, `size: string = "default"`, `items: unknown[] = []`, `active: string = ""`, `orientation: string = "horizontal"`, `label: string = "Main"`, `collapsible: boolean = true`, `toggleLabel: string = "Menu"`, `class: string = ""`
|
||||||
- Slots: `default`
|
- Slots: `default`
|
||||||
- Outputs: `select({ value?: string | number | boolean | null; values?: Array<string | number | boolean | null | object>; sourceEvent?: Event; [key: string]: string | number | boolean | null | object } | string | number | boolean | null)`, `change({ value?: string | number | boolean | null; values?: Array<string | number | boolean | null | object>; sourceEvent?: Event; [key: string]: string | number | boolean | null | object } | string | number | boolean | null)`
|
- Outputs: `select({ item: object; value: string })`
|
||||||
|
|
||||||
### Navbar
|
### Navbar
|
||||||
|
|
||||||
@@ -889,45 +889,45 @@ Theme-aware, responsive navbar component.
|
|||||||
Theme-aware, responsive pagination component.
|
Theme-aware, responsive pagination component.
|
||||||
|
|
||||||
- Mount: `data-component="Pagination"`
|
- Mount: `data-component="Pagination"`
|
||||||
- Props: `size: string = "default"`, `color: string = "primary"`, `label: string = "Pagination"`, `items: unknown[] = []`, `active: string = ""`, `orientation: string = "horizontal"`, `class: string = ""`
|
- Props: `color: string = "primary"`, `size: string = "default"`, `page: number = 1`, `pageSize: number = 10`, `total: number = 0`, `variant: string = "compact"`, `siblingCount: number = 1`, `showSummary: boolean = true`, `label: string = "Pagination"`, `previousLabel: string = "Previous"`, `nextLabel: string = "Next"`, `class: string = ""`
|
||||||
- Slots: `default`
|
- Slots: `default`
|
||||||
- Outputs: `change({ value?: string | number | boolean | null; values?: Array<string | number | boolean | null | object>; sourceEvent?: Event; [key: string]: string | number | boolean | null | object } | string | number | boolean | null)`, `previous({ sourceEvent?: Event; [key: string]: string | number | boolean | null | object })`, `next({ sourceEvent?: Event; [key: string]: string | number | boolean | null | object })`
|
- Outputs: `change({ page: number; pageSize: number })`, `previous({ page: number })`, `next({ page: number })`
|
||||||
|
|
||||||
### Scrollspy
|
### Scrollspy
|
||||||
|
|
||||||
Theme-aware, responsive scrollspy component.
|
Theme-aware, responsive scrollspy component.
|
||||||
|
|
||||||
- Mount: `data-component="Scrollspy"`
|
- Mount: `data-component="Scrollspy"`
|
||||||
- Props: `size: string = "default"`, `color: string = "primary"`, `label: string = "Scrollspy"`, `items: unknown[] = []`, `active: string = ""`, `orientation: string = "horizontal"`, `class: string = ""`
|
- Props: `color: string = "primary"`, `size: string = "default"`, `items: unknown[] = []`, `active: string = ""`, `label: string = "On this page"`, `heading: string = ""`, `class: string = ""`
|
||||||
- Slots: `default`
|
- Slots: `default`
|
||||||
- Outputs: `change({ value?: string | number | boolean | null; values?: Array<string | number | boolean | null | object>; sourceEvent?: Event; [key: string]: string | number | boolean | null | object } | string | number | boolean | null)`
|
- Outputs: `change({ href: string; label: string })`
|
||||||
|
|
||||||
### Sidebar
|
### Sidebar
|
||||||
|
|
||||||
Theme-aware, responsive sidebar component.
|
Theme-aware, responsive sidebar component.
|
||||||
|
|
||||||
- Mount: `data-component="Sidebar"`
|
- Mount: `data-component="Sidebar"`
|
||||||
- Props: `size: string = "default"`, `color: string = "primary"`, `label: string = "Sidebar"`, `items: unknown[] = []`, `active: string = ""`, `orientation: string = "horizontal"`, `mobileLabel: string = "Open navigation"`, `class: string = ""`
|
- Props: `color: string = "primary"`, `size: string = "default"`, `label: string = "Sidebar"`, `items: unknown[] = []`, `active: string = ""`, `mobileLabel: string = "Open navigation"`, `drawerTitle: string = "Navigation"`, `class: string = ""`
|
||||||
- Slots: `default`
|
- Slots: `default`, `drawer`
|
||||||
- Outputs: `toggle({ open: boolean })`, `open({ sourceEvent?: Event; [key: string]: string | number | boolean | null | object })`, `close({ source: string })`, `select({ item: string | number | boolean | null | object; value: string | number | boolean; level: string })`
|
- Outputs: `toggle({ open: boolean })`, `open({ sourceEvent: Event })`, `close({ source: string })`, `select({ item: object; value: string; level: number })`
|
||||||
|
|
||||||
### Stepper
|
### Stepper
|
||||||
|
|
||||||
Theme-aware, responsive stepper component.
|
Theme-aware, responsive stepper component.
|
||||||
|
|
||||||
- Mount: `data-component="Stepper"`
|
- Mount: `data-component="Stepper"`
|
||||||
- Props: `size: string = "default"`, `color: string = "primary"`, `label: string = "Stepper"`, `items: unknown[] = []`, `active: string = ""`, `orientation: string = "horizontal"`, `class: string = ""`
|
- Props: `color: string = "primary"`, `size: string = "default"`, `steps: unknown[] = []`, `active: number = 0`, `orientation: string = "horizontal"`, `clickable: boolean = false`, `label: string = "Progress"`, `showPanel: boolean = false`, `controls: boolean = false`, `allowSkip: boolean = false`, `nextDisabled: boolean = false`, `backLabel: string = "Back"`, `nextLabel: string = "Next"`, `skipLabel: string = "Skip"`, `finishLabel: string = "Finish"`, `class: string = ""`
|
||||||
- Slots: `default`
|
- Slots: `step-{index}`, `panel-{index}`, `default`
|
||||||
- Outputs: `change({ value?: string | number | boolean | null; values?: Array<string | number | boolean | null | object>; sourceEvent?: Event; [key: string]: string | number | boolean | null | object } | string | number | boolean | null)`, `previous({ sourceEvent?: Event; [key: string]: string | number | boolean | null | object })`, `next({ sourceEvent?: Event; [key: string]: string | number | boolean | null | object })`, `complete({ sourceEvent?: Event; [key: string]: string | number | boolean | null | object })`
|
- Outputs: `change({ index: number; step: object })`, `back({ index: number; step: object })`, `next({ index: number; step: object })`, `skip({ index: number; step: object })`, `finish({ index: number; step: object })`
|
||||||
|
|
||||||
### Tabs
|
### Tabs
|
||||||
|
|
||||||
Switch between related responsive content panels with horizontal or vertical orientation and selection events.
|
Switch between related responsive content panels with horizontal or vertical orientation and selection events.
|
||||||
|
|
||||||
- Mount: `data-component="Tabs"`
|
- Mount: `data-component="Tabs"`
|
||||||
- Props: `size: string = "default"`, `color: string = "primary"`, `label: string = "Tabs"`, `items: unknown[] = []`, `active: string = ""`, `orientation: string = "horizontal"`, `class: string = ""`
|
- Props: `color: string = "primary"`, `size: string = "default"`, `items: unknown[] = []`, `active: string = ""`, `orientation: string = "horizontal"`, `mode: string = "client"`, `param: string = "tab"`, `label: string = "Tabs"`, `class: string = ""`
|
||||||
- Slots: `default`
|
- Slots: `panel-{valueOf(item, index)}`, `default`
|
||||||
- Outputs: None
|
- Outputs: `change({ value: string; item: object; index: number })`, `select({ value: string; item: object; index: number })`
|
||||||
|
|
||||||
## Overlays
|
## Overlays
|
||||||
|
|
||||||
|
|||||||
@@ -4153,6 +4153,13 @@
|
|||||||
"default": "\"xl\"",
|
"default": "\"xl\"",
|
||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "centered",
|
||||||
|
"type": "boolean",
|
||||||
|
"required": false,
|
||||||
|
"default": "true",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "class",
|
"name": "class",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -4443,13 +4450,6 @@
|
|||||||
"category": "layout",
|
"category": "layout",
|
||||||
"purpose": "Theme-aware, responsive custom scrollbar component.",
|
"purpose": "Theme-aware, responsive custom scrollbar component.",
|
||||||
"props": [
|
"props": [
|
||||||
{
|
|
||||||
"name": "size",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"default\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "color",
|
"name": "color",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -4458,24 +4458,38 @@
|
|||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "columns",
|
"name": "size",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"default\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "axis",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"vertical\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "thickness",
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"required": false,
|
"required": false,
|
||||||
"default": "2",
|
"default": "8",
|
||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "gap",
|
"name": "maxHeight",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"required": false,
|
"required": false,
|
||||||
"default": "\"md\"",
|
"default": "\"20rem\"",
|
||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "maxWidth",
|
"name": "radius",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"required": false,
|
"required": false,
|
||||||
"default": "\"xl\"",
|
"default": "\"999px\"",
|
||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -4487,13 +4501,8 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"slots": ["default"],
|
"slots": ["default"],
|
||||||
"outputs": [
|
"outputs": [],
|
||||||
{
|
"events": [],
|
||||||
"name": "scroll",
|
|
||||||
"payloadType": "{ sourceEvent?: Event; value: string | number | boolean | null | object; [key: string]: string | number | boolean | null | object } | string | number | boolean | null | object[]"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"events": ["scroll"],
|
|
||||||
"source": "components/CustomScrollbar.wrn"
|
"source": "components/CustomScrollbar.wrn"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -5192,6 +5201,13 @@
|
|||||||
"default": "\"horizontal\"",
|
"default": "\"horizontal\"",
|
||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "variant",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"solid\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "class",
|
"name": "class",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -6548,6 +6564,13 @@
|
|||||||
"default": "\"xl\"",
|
"default": "\"xl\"",
|
||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "minItemWidth",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "class",
|
"name": "class",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -6962,6 +6985,13 @@
|
|||||||
"default": "\"lazy\"",
|
"default": "\"lazy\"",
|
||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "fit",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"cover\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "rounded",
|
"name": "rounded",
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
@@ -7750,7 +7780,7 @@
|
|||||||
"name": "label",
|
"name": "label",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"required": false,
|
"required": false,
|
||||||
"default": "\"⌘ K\"",
|
"default": "\"K\"",
|
||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -7772,13 +7802,6 @@
|
|||||||
"category": "layout",
|
"category": "layout",
|
||||||
"purpose": "Theme-aware, responsive layout splitter component.",
|
"purpose": "Theme-aware, responsive layout splitter component.",
|
||||||
"props": [
|
"props": [
|
||||||
{
|
|
||||||
"name": "size",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"default\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "color",
|
"name": "color",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -7787,24 +7810,38 @@
|
|||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "columns",
|
"name": "size",
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"required": false,
|
"required": false,
|
||||||
"default": "2",
|
"default": "50",
|
||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "gap",
|
"name": "orientation",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"required": false,
|
"required": false,
|
||||||
"default": "\"md\"",
|
"default": "\"horizontal\"",
|
||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "maxWidth",
|
"name": "minSize",
|
||||||
|
"type": "number",
|
||||||
|
"required": false,
|
||||||
|
"default": "15",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "step",
|
||||||
|
"type": "number",
|
||||||
|
"required": false,
|
||||||
|
"default": "5",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "label",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"required": false,
|
"required": false,
|
||||||
"default": "\"xl\"",
|
"default": "\"Resize panels\"",
|
||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -7815,22 +7852,14 @@
|
|||||||
"options": []
|
"options": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"slots": ["default"],
|
"slots": ["start", "end", "default"],
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"name": "resizeStart",
|
"name": "sizeChange",
|
||||||
"payloadType": "{ sourceEvent?: Event; value: string | number | boolean | null | object; [key: string]: string | number | boolean | null | object } | string | number | boolean | null | object[]"
|
"payloadType": "{ size: number }"
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "resize",
|
|
||||||
"payloadType": "{ sourceEvent?: Event; value: string | number | boolean | null | object; [key: string]: string | number | boolean | null | object } | string | number | boolean | null | object[]"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "resizeEnd",
|
|
||||||
"payloadType": "{ sourceEvent?: Event; value: string | number | boolean | null | object; [key: string]: string | number | boolean | null | object } | string | number | boolean | null | object[]"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"events": ["resizeStart", "resize", "resizeEnd"],
|
"events": ["sizeChange"],
|
||||||
"source": "components/LayoutSplitter.wrn"
|
"source": "components/LayoutSplitter.wrn"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -7951,6 +7980,13 @@
|
|||||||
"default": "\"\"",
|
"default": "\"\"",
|
||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "underline",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"hover\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "external",
|
"name": "external",
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
@@ -8028,8 +8064,13 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"slots": ["default"],
|
"slots": ["default"],
|
||||||
"outputs": [],
|
"outputs": [
|
||||||
"events": [],
|
{
|
||||||
|
"name": "select",
|
||||||
|
"payloadType": "{ sourceEvent?: Event; [key: string]: string | number | boolean | null | object }"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"events": ["select"],
|
||||||
"source": "components/List.wrn"
|
"source": "components/List.wrn"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -8159,8 +8200,21 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"slots": ["default"],
|
"slots": ["default"],
|
||||||
"outputs": [],
|
"outputs": [
|
||||||
"events": [],
|
{
|
||||||
|
"name": "markerClick",
|
||||||
|
"payloadType": "{ sourceEvent?: Event; [key: string]: string | number | boolean | null | object }"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "select",
|
||||||
|
"payloadType": "{ sourceEvent?: Event; [key: string]: string | number | boolean | null | object }"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "zoom",
|
||||||
|
"payloadType": "{ sourceEvent?: Event; [key: string]: string | number | boolean | null | object }"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"events": ["markerClick", "select", "zoom"],
|
||||||
"source": "components/Map.wrn"
|
"source": "components/Map.wrn"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -8316,8 +8370,17 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"slots": ["default"],
|
"slots": ["default"],
|
||||||
"outputs": [],
|
"outputs": [
|
||||||
"events": [],
|
{
|
||||||
|
"name": "pause",
|
||||||
|
"payloadType": "{ sourceEvent?: Event; [key: string]: string | number | boolean | null | object }"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "resume",
|
||||||
|
"payloadType": "{ sourceEvent?: Event; [key: string]: string | number | boolean | null | object }"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"events": ["pause", "resume"],
|
||||||
"source": "components/Marquee.wrn"
|
"source": "components/Marquee.wrn"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -8326,13 +8389,6 @@
|
|||||||
"category": "navigation",
|
"category": "navigation",
|
||||||
"purpose": "Theme-aware, responsive mega menu component.",
|
"purpose": "Theme-aware, responsive mega menu component.",
|
||||||
"props": [
|
"props": [
|
||||||
{
|
|
||||||
"name": "size",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"default\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "color",
|
"name": "color",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -8340,32 +8396,46 @@
|
|||||||
"default": "\"primary\"",
|
"default": "\"primary\"",
|
||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "size",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"default\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "label",
|
"name": "label",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"required": false,
|
"required": false,
|
||||||
"default": "\"Mega Menu\"",
|
"default": "\"Menu\"",
|
||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "items",
|
"name": "icon",
|
||||||
"type": "unknown[]",
|
|
||||||
"required": false,
|
|
||||||
"default": "[]",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "active",
|
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"required": false,
|
"required": false,
|
||||||
"default": "\"\"",
|
"default": "\"\"",
|
||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "orientation",
|
"name": "columns",
|
||||||
|
"type": "unknown[]",
|
||||||
|
"required": false,
|
||||||
|
"default": "[]",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "footer",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"required": false,
|
"required": false,
|
||||||
"default": "\"horizontal\"",
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "defaultOpen",
|
||||||
|
"type": "boolean",
|
||||||
|
"required": false,
|
||||||
|
"default": "false",
|
||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -8380,15 +8450,15 @@
|
|||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"name": "open",
|
"name": "open",
|
||||||
"payloadType": "{ sourceEvent?: Event; [key: string]: string | number | boolean | null | object }"
|
"payloadType": "{ sourceEvent: Event }"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "close",
|
"name": "close",
|
||||||
"payloadType": "{ sourceEvent?: Event; [key: string]: string | number | boolean | null | object }"
|
"payloadType": "{ reason: string }"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "select",
|
"name": "select",
|
||||||
"payloadType": "{ value?: string | number | boolean | null; values?: Array<string | number | boolean | null | object>; sourceEvent?: Event; [key: string]: string | number | boolean | null | object } | string | number | boolean | null"
|
"payloadType": "{ item: object; value: string }"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"events": ["open", "close", "select"],
|
"events": ["open", "close", "select"],
|
||||||
@@ -8961,13 +9031,6 @@
|
|||||||
"category": "navigation",
|
"category": "navigation",
|
||||||
"purpose": "Theme-aware, responsive nav component.",
|
"purpose": "Theme-aware, responsive nav component.",
|
||||||
"props": [
|
"props": [
|
||||||
{
|
|
||||||
"name": "size",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"default\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "color",
|
"name": "color",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -8976,10 +9039,10 @@
|
|||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "label",
|
"name": "size",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"required": false,
|
"required": false,
|
||||||
"default": "\"Nav\"",
|
"default": "\"default\"",
|
||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -9003,6 +9066,27 @@
|
|||||||
"default": "\"horizontal\"",
|
"default": "\"horizontal\"",
|
||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "label",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"Main\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "collapsible",
|
||||||
|
"type": "boolean",
|
||||||
|
"required": false,
|
||||||
|
"default": "true",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "toggleLabel",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"Menu\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "class",
|
"name": "class",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -9015,14 +9099,10 @@
|
|||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"name": "select",
|
"name": "select",
|
||||||
"payloadType": "{ value?: string | number | boolean | null; values?: Array<string | number | boolean | null | object>; sourceEvent?: Event; [key: string]: string | number | boolean | null | object } | string | number | boolean | null"
|
"payloadType": "{ item: object; value: string }"
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "change",
|
|
||||||
"payloadType": "{ value?: string | number | boolean | null; values?: Array<string | number | boolean | null | object>; sourceEvent?: Event; [key: string]: string | number | boolean | null | object } | string | number | boolean | null"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"events": ["select", "change"],
|
"events": ["select"],
|
||||||
"source": "components/Nav.wrn"
|
"source": "components/Nav.wrn"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -9342,6 +9422,13 @@
|
|||||||
"category": "navigation",
|
"category": "navigation",
|
||||||
"purpose": "Theme-aware, responsive pagination component.",
|
"purpose": "Theme-aware, responsive pagination component.",
|
||||||
"props": [
|
"props": [
|
||||||
|
{
|
||||||
|
"name": "color",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"primary\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "size",
|
"name": "size",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -9350,10 +9437,45 @@
|
|||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "color",
|
"name": "page",
|
||||||
|
"type": "number",
|
||||||
|
"required": false,
|
||||||
|
"default": "1",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "pageSize",
|
||||||
|
"type": "number",
|
||||||
|
"required": false,
|
||||||
|
"default": "10",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "total",
|
||||||
|
"type": "number",
|
||||||
|
"required": false,
|
||||||
|
"default": "0",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "variant",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"required": false,
|
"required": false,
|
||||||
"default": "\"primary\"",
|
"default": "\"compact\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "siblingCount",
|
||||||
|
"type": "number",
|
||||||
|
"required": false,
|
||||||
|
"default": "1",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "showSummary",
|
||||||
|
"type": "boolean",
|
||||||
|
"required": false,
|
||||||
|
"default": "true",
|
||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -9364,24 +9486,17 @@
|
|||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "items",
|
"name": "previousLabel",
|
||||||
"type": "unknown[]",
|
"type": "string",
|
||||||
"required": false,
|
"required": false,
|
||||||
"default": "[]",
|
"default": "\"Previous\"",
|
||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "active",
|
"name": "nextLabel",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"required": false,
|
"required": false,
|
||||||
"default": "\"\"",
|
"default": "\"Next\"",
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "orientation",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"horizontal\"",
|
|
||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -9396,15 +9511,15 @@
|
|||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"name": "change",
|
"name": "change",
|
||||||
"payloadType": "{ value?: string | number | boolean | null; values?: Array<string | number | boolean | null | object>; sourceEvent?: Event; [key: string]: string | number | boolean | null | object } | string | number | boolean | null"
|
"payloadType": "{ page: number; pageSize: number }"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "previous",
|
"name": "previous",
|
||||||
"payloadType": "{ sourceEvent?: Event; [key: string]: string | number | boolean | null | object }"
|
"payloadType": "{ page: number }"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "next",
|
"name": "next",
|
||||||
"payloadType": "{ sourceEvent?: Event; [key: string]: string | number | boolean | null | object }"
|
"payloadType": "{ page: number }"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"events": ["change", "previous", "next"],
|
"events": ["change", "previous", "next"],
|
||||||
@@ -10664,13 +10779,6 @@
|
|||||||
"category": "navigation",
|
"category": "navigation",
|
||||||
"purpose": "Theme-aware, responsive scrollspy component.",
|
"purpose": "Theme-aware, responsive scrollspy component.",
|
||||||
"props": [
|
"props": [
|
||||||
{
|
|
||||||
"name": "size",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"default\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "color",
|
"name": "color",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -10679,10 +10787,10 @@
|
|||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "label",
|
"name": "size",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"required": false,
|
"required": false,
|
||||||
"default": "\"Scrollspy\"",
|
"default": "\"default\"",
|
||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -10700,10 +10808,17 @@
|
|||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "orientation",
|
"name": "label",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"required": false,
|
"required": false,
|
||||||
"default": "\"horizontal\"",
|
"default": "\"On this page\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "heading",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -10718,7 +10833,7 @@
|
|||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"name": "change",
|
"name": "change",
|
||||||
"payloadType": "{ value?: string | number | boolean | null; values?: Array<string | number | boolean | null | object>; sourceEvent?: Event; [key: string]: string | number | boolean | null | object } | string | number | boolean | null"
|
"payloadType": "{ href: string; label: string }"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"events": ["change"],
|
"events": ["change"],
|
||||||
@@ -10823,8 +10938,17 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"slots": [],
|
"slots": [],
|
||||||
"outputs": [],
|
"outputs": [
|
||||||
"events": [],
|
{
|
||||||
|
"name": "search",
|
||||||
|
"payloadType": "{ sourceEvent?: Event; [key: string]: string | number | boolean | null | object }"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "clear",
|
||||||
|
"payloadType": "{ sourceEvent?: Event; [key: string]: string | number | boolean | null | object }"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"events": ["search", "clear"],
|
||||||
"source": "components/SearchBox.wrn"
|
"source": "components/SearchBox.wrn"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -11192,13 +11316,6 @@
|
|||||||
"category": "navigation",
|
"category": "navigation",
|
||||||
"purpose": "Theme-aware, responsive sidebar component.",
|
"purpose": "Theme-aware, responsive sidebar component.",
|
||||||
"props": [
|
"props": [
|
||||||
{
|
|
||||||
"name": "size",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"default\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "color",
|
"name": "color",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -11206,6 +11323,13 @@
|
|||||||
"default": "\"primary\"",
|
"default": "\"primary\"",
|
||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "size",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"default\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "label",
|
"name": "label",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -11227,13 +11351,6 @@
|
|||||||
"default": "\"\"",
|
"default": "\"\"",
|
||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "orientation",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"horizontal\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "mobileLabel",
|
"name": "mobileLabel",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -11241,6 +11358,13 @@
|
|||||||
"default": "\"Open navigation\"",
|
"default": "\"Open navigation\"",
|
||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "drawerTitle",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"Navigation\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "class",
|
"name": "class",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -11249,7 +11373,7 @@
|
|||||||
"options": []
|
"options": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"slots": ["default"],
|
"slots": ["default", "drawer"],
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"name": "toggle",
|
"name": "toggle",
|
||||||
@@ -11257,7 +11381,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "open",
|
"name": "open",
|
||||||
"payloadType": "{ sourceEvent?: Event; [key: string]: string | number | boolean | null | object }"
|
"payloadType": "{ sourceEvent: Event }"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "close",
|
"name": "close",
|
||||||
@@ -11265,7 +11389,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "select",
|
"name": "select",
|
||||||
"payloadType": "{ item: string | number | boolean | null | object; value: string | number | boolean; level: string }"
|
"payloadType": "{ item: object; value: string; level: number }"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"events": ["toggle", "open", "close", "select"],
|
"events": ["toggle", "open", "close", "select"],
|
||||||
@@ -11682,13 +11806,6 @@
|
|||||||
"category": "navigation",
|
"category": "navigation",
|
||||||
"purpose": "Theme-aware, responsive stepper component.",
|
"purpose": "Theme-aware, responsive stepper component.",
|
||||||
"props": [
|
"props": [
|
||||||
{
|
|
||||||
"name": "size",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"default\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "color",
|
"name": "color",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -11697,14 +11814,14 @@
|
|||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "label",
|
"name": "size",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"required": false,
|
"required": false,
|
||||||
"default": "\"Stepper\"",
|
"default": "\"default\"",
|
||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "items",
|
"name": "steps",
|
||||||
"type": "unknown[]",
|
"type": "unknown[]",
|
||||||
"required": false,
|
"required": false,
|
||||||
"default": "[]",
|
"default": "[]",
|
||||||
@@ -11712,9 +11829,9 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "active",
|
"name": "active",
|
||||||
"type": "string",
|
"type": "number",
|
||||||
"required": false,
|
"required": false,
|
||||||
"default": "\"\"",
|
"default": "0",
|
||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -11724,6 +11841,76 @@
|
|||||||
"default": "\"horizontal\"",
|
"default": "\"horizontal\"",
|
||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "clickable",
|
||||||
|
"type": "boolean",
|
||||||
|
"required": false,
|
||||||
|
"default": "false",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "label",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"Progress\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "showPanel",
|
||||||
|
"type": "boolean",
|
||||||
|
"required": false,
|
||||||
|
"default": "false",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "controls",
|
||||||
|
"type": "boolean",
|
||||||
|
"required": false,
|
||||||
|
"default": "false",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "allowSkip",
|
||||||
|
"type": "boolean",
|
||||||
|
"required": false,
|
||||||
|
"default": "false",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "nextDisabled",
|
||||||
|
"type": "boolean",
|
||||||
|
"required": false,
|
||||||
|
"default": "false",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "backLabel",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"Back\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "nextLabel",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"Next\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "skipLabel",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"Skip\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "finishLabel",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"Finish\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "class",
|
"name": "class",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -11732,26 +11919,30 @@
|
|||||||
"options": []
|
"options": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"slots": ["default"],
|
"slots": ["step-{index}", "panel-{index}", "default"],
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"name": "change",
|
"name": "change",
|
||||||
"payloadType": "{ value?: string | number | boolean | null; values?: Array<string | number | boolean | null | object>; sourceEvent?: Event; [key: string]: string | number | boolean | null | object } | string | number | boolean | null"
|
"payloadType": "{ index: number; step: object }"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "previous",
|
"name": "back",
|
||||||
"payloadType": "{ sourceEvent?: Event; [key: string]: string | number | boolean | null | object }"
|
"payloadType": "{ index: number; step: object }"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "next",
|
"name": "next",
|
||||||
"payloadType": "{ sourceEvent?: Event; [key: string]: string | number | boolean | null | object }"
|
"payloadType": "{ index: number; step: object }"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "complete",
|
"name": "skip",
|
||||||
"payloadType": "{ sourceEvent?: Event; [key: string]: string | number | boolean | null | object }"
|
"payloadType": "{ index: number; step: object }"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "finish",
|
||||||
|
"payloadType": "{ index: number; step: object }"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"events": ["change", "previous", "next", "complete"],
|
"events": ["change", "back", "next", "skip", "finish"],
|
||||||
"source": "components/Stepper.wrn"
|
"source": "components/Stepper.wrn"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -12204,13 +12395,6 @@
|
|||||||
"category": "navigation",
|
"category": "navigation",
|
||||||
"purpose": "Switch between related responsive content panels with horizontal or vertical orientation and selection events.",
|
"purpose": "Switch between related responsive content panels with horizontal or vertical orientation and selection events.",
|
||||||
"props": [
|
"props": [
|
||||||
{
|
|
||||||
"name": "size",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"default": "\"default\"",
|
|
||||||
"options": []
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "color",
|
"name": "color",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -12219,10 +12403,10 @@
|
|||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "label",
|
"name": "size",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"required": false,
|
"required": false,
|
||||||
"default": "\"Tabs\"",
|
"default": "\"default\"",
|
||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -12246,6 +12430,27 @@
|
|||||||
"default": "\"horizontal\"",
|
"default": "\"horizontal\"",
|
||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "mode",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"client\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "param",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"tab\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "label",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"Tabs\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "class",
|
"name": "class",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -12254,9 +12459,18 @@
|
|||||||
"options": []
|
"options": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"slots": ["default"],
|
"slots": ["panel-{valueOf(item, index)}", "default"],
|
||||||
"outputs": [],
|
"outputs": [
|
||||||
"events": [],
|
{
|
||||||
|
"name": "change",
|
||||||
|
"payloadType": "{ value: string; item: object; index: number }"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "select",
|
||||||
|
"payloadType": "{ value: string; item: object; index: number }"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"events": ["change", "select"],
|
||||||
"source": "components/Tabs.wrn"
|
"source": "components/Tabs.wrn"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -12856,8 +13070,13 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"slots": ["default"],
|
"slots": ["default"],
|
||||||
"outputs": [],
|
"outputs": [
|
||||||
"events": [],
|
{
|
||||||
|
"name": "select",
|
||||||
|
"payloadType": "{ sourceEvent?: Event; [key: string]: string | number | boolean | null | object }"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"events": ["select"],
|
||||||
"source": "components/Timeline.wrn"
|
"source": "components/Timeline.wrn"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -49,22 +49,24 @@ component Accordion {
|
|||||||
return multiple || alwaysOpen
|
return multiple || alwaysOpen
|
||||||
}
|
}
|
||||||
|
|
||||||
client function dispatchAccordionEvent(sourceEvent, eventName, value, item, root, customEvent) {
|
// Named rather than computed: an output is resolved as a property name, so
|
||||||
root = sourceEvent.currentTarget.closest("[data-wrn-accordion]")
|
// output[eventName] would not reach a parent binding.
|
||||||
|
client function dispatchAccordionEvent(sourceEvent, eventName, value, item, payload) {
|
||||||
if (!root) {
|
payload = {
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
customEvent = document.createEvent("CustomEvent")
|
|
||||||
customEvent.initCustomEvent(eventName, true, false, {
|
|
||||||
component: "Accordion",
|
component: "Accordion",
|
||||||
value: value,
|
value: value,
|
||||||
item: item,
|
item: item,
|
||||||
open: isOpen(value),
|
open: isOpen(value),
|
||||||
openValues: openValues
|
openValues: openValues
|
||||||
})
|
}
|
||||||
root.dispatchEvent(customEvent)
|
|
||||||
|
if (eventName === "open") {
|
||||||
|
output.open(payload)
|
||||||
|
} else if (eventName === "close") {
|
||||||
|
output.close(payload)
|
||||||
|
} else {
|
||||||
|
output.change(payload)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
client function toggleItem(sourceEvent, value, item, wasOpen) {
|
client function toggleItem(sourceEvent, value, item, wasOpen) {
|
||||||
|
|||||||
@@ -30,17 +30,13 @@ component AvatarGroup {
|
|||||||
return items.slice(Number(maxVisible))
|
return items.slice(Number(maxVisible))
|
||||||
}
|
}
|
||||||
|
|
||||||
client function toggleOverflow(sourceEvent, root, customEvent) {
|
client function toggleOverflow() {
|
||||||
overflowOpen = !overflowOpen
|
overflowOpen = !overflowOpen
|
||||||
root = sourceEvent.currentTarget.closest("[data-wrn-avatar-group]")
|
output.overflow({
|
||||||
|
|
||||||
customEvent = document.createEvent("CustomEvent")
|
|
||||||
customEvent.initCustomEvent("overflow", true, false, {
|
|
||||||
component: "AvatarGroup",
|
component: "AvatarGroup",
|
||||||
open: overflowOpen,
|
open: overflowOpen,
|
||||||
hiddenCount: hiddenMembers().length
|
hiddenCount: hiddenMembers().length
|
||||||
})
|
})
|
||||||
root.dispatchEvent(customEvent)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ label: string = "Breadcrumb"
|
|||||||
<a
|
<a
|
||||||
href='{homeHref || "/"}'
|
href='{homeHref || "/"}'
|
||||||
class="wire-breadcrumb__link wire-breadcrumb__home"
|
class="wire-breadcrumb__link wire-breadcrumb__home"
|
||||||
@click='event.currentTarget.dispatchEvent(new CustomEvent("select", { bubbles: true, detail: { item: { label: homeLabel, href: homeHref || "/", value: "home" }, itemIndex: -1 } }))'
|
@click='output.select({ item: { label: homeLabel, href: homeHref || "/", value: "home" }, itemIndex: -1 })'
|
||||||
>
|
>
|
||||||
{#if homeIcon === "icon-[lucide--house]"}
|
{#if homeIcon === "icon-[lucide--house]"}
|
||||||
<span class="icon-[lucide--house] wire-breadcrumb__icon" aria-hidden="true"></span>
|
<span class="icon-[lucide--house] wire-breadcrumb__icon" aria-hidden="true"></span>
|
||||||
@@ -72,7 +72,7 @@ label: string = "Breadcrumb"
|
|||||||
target='{item.target || ""}'
|
target='{item.target || ""}'
|
||||||
rel='{item.external ? "noopener noreferrer" : (item.rel || "")}'
|
rel='{item.external ? "noopener noreferrer" : (item.rel || "")}'
|
||||||
class="wire-breadcrumb__link"
|
class="wire-breadcrumb__link"
|
||||||
@click='event.currentTarget.dispatchEvent(new CustomEvent("select", { bubbles: true, detail: { item: item, itemIndex: itemIndex } }))'
|
@click='output.select({ item: item, itemIndex: itemIndex })'
|
||||||
>
|
>
|
||||||
{#if item.icon}
|
{#if item.icon}
|
||||||
<span class='{item.icon} wire-breadcrumb__icon' aria-hidden="true"></span>
|
<span class='{item.icon} wire-breadcrumb__icon' aria-hidden="true"></span>
|
||||||
@@ -87,7 +87,7 @@ label: string = "Breadcrumb"
|
|||||||
{:else}
|
{:else}
|
||||||
<span
|
<span
|
||||||
class="wire-breadcrumb__current"
|
class="wire-breadcrumb__current"
|
||||||
aria-current='{item.active || item.current || (active && active === (item.value || item.label || item.title)) || (!active && itemIndex === items.length - 1) ? "page" : ""}'
|
aria-current='{item.active || item.current || (active && active === (item.value || item.label || item.title)) || (!active && itemIndex === items.length - 1) ? "page" : "false"}'
|
||||||
aria-disabled='{item.disabled ? "true" : "false"}'
|
aria-disabled='{item.disabled ? "true" : "false"}'
|
||||||
>
|
>
|
||||||
{#if item.icon}
|
{#if item.icon}
|
||||||
|
|||||||
@@ -1,3 +1,13 @@
|
|||||||
|
// Columns -- a simple multi-column split for page content.
|
||||||
|
//
|
||||||
|
// <Columns columns={2} gap="lg">...</Columns>
|
||||||
|
//
|
||||||
|
// Columns and Grid overlap deliberately: Columns is the coarse two or three
|
||||||
|
// way split of a page, and its gaps are wider for that reason. Grid is the one
|
||||||
|
// to reach for when the items are cards and the count matters.
|
||||||
|
//
|
||||||
|
// NOTE: the style block uses /* */ comments only -- // is not a CSS comment
|
||||||
|
// and silently swallows the rule that follows it.
|
||||||
component Columns {
|
component Columns {
|
||||||
props {
|
props {
|
||||||
size: string = "default"
|
size: string = "default"
|
||||||
@@ -8,28 +18,92 @@ component Columns {
|
|||||||
class: string = ""
|
class: string = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
functions {
|
||||||
|
shared function columnCount() {
|
||||||
|
var value = Number(columns)
|
||||||
|
if (!value || value < 1) {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return Math.min(4, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
view {
|
view {
|
||||||
<div
|
<div
|
||||||
|
{...attrs}
|
||||||
data-ui-component="Columns"
|
data-ui-component="Columns"
|
||||||
|
class='wire-columns {class}'
|
||||||
data-size='{size}'
|
data-size='{size}'
|
||||||
data-color='{color}'
|
data-color='{color}'
|
||||||
data-columns='{columns}'
|
|
||||||
data-gap='{gap}'
|
data-gap='{gap}'
|
||||||
class='grid w-full grid-cols-1 items-start {class}'
|
data-max-width='{maxWidth}'
|
||||||
class:max-w-3xl='maxWidth === "md"'
|
data-columns='{columnCount()}'
|
||||||
class:max-w-5xl='maxWidth === "lg"'
|
|
||||||
class:max-w-7xl='maxWidth === "xl"'
|
|
||||||
class:max-w-screen-2xl='maxWidth === "2xl"'
|
|
||||||
class:max-w-none='maxWidth === "full"'
|
|
||||||
class:md:grid-cols-2='columns >= 2'
|
|
||||||
class:lg:grid-cols-3='columns === 3'
|
|
||||||
class:lg:grid-cols-4='columns === 4'
|
|
||||||
class:gap-3='gap === "sm"'
|
|
||||||
class:gap-6='gap === "md"'
|
|
||||||
class:gap-10='gap === "lg"'
|
|
||||||
class:gap-14='gap === "xl"'
|
|
||||||
>
|
>
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
style {
|
||||||
|
.wire-columns {
|
||||||
|
--columns-gap: 1.5rem;
|
||||||
|
display: grid;
|
||||||
|
width: 100%;
|
||||||
|
min-width: 0;
|
||||||
|
gap: var(--columns-gap);
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
align-items: start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-columns[data-max-width="md"] {
|
||||||
|
max-width: 48rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-columns[data-max-width="lg"] {
|
||||||
|
max-width: 64rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-columns[data-max-width="xl"] {
|
||||||
|
max-width: 80rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-columns[data-max-width="2xl"] {
|
||||||
|
max-width: 96rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-columns[data-max-width="full"] {
|
||||||
|
max-width: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-columns[data-gap="sm"] {
|
||||||
|
--columns-gap: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-columns[data-gap="lg"] {
|
||||||
|
--columns-gap: 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-columns[data-gap="xl"] {
|
||||||
|
--columns-gap: 3.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Splits at the tablet breakpoint rather than the phone one: a page split
|
||||||
|
* is worth keeping single-column for longer than a card deck is.
|
||||||
|
*/
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.wire-columns:not([data-columns="1"]) {
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
.wire-columns[data-columns="3"] {
|
||||||
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-columns[data-columns="4"] {
|
||||||
|
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,122 @@
|
|||||||
|
// CustomScrollbar -- a scrolling region with a themed scrollbar.
|
||||||
|
//
|
||||||
|
// <CustomScrollbar maxHeight="20rem">...long content...</CustomScrollbar>
|
||||||
|
//
|
||||||
|
// Scrollbar appearance is CSS, not script: scrollbar-width and scrollbar-color
|
||||||
|
// are the standard properties, and the ::-webkit-scrollbar rules cover the
|
||||||
|
// browsers that still need them.
|
||||||
|
//
|
||||||
|
// This component used to declare a scroll output it never emitted, and its
|
||||||
|
// props were columns, gap and maxWidth copied from a grid scaffold. The output
|
||||||
|
// is removed rather than left unimplemented -- a caller can listen for a plain
|
||||||
|
// scroll event on the element, which is what it would have been anyway.
|
||||||
|
//
|
||||||
|
// NOTE: the style block uses /* */ comments only -- // is not a CSS comment
|
||||||
|
// and silently swallows the rule that follows it.
|
||||||
component CustomScrollbar {
|
component CustomScrollbar {
|
||||||
outputs {
|
|
||||||
scroll(payload: { sourceEvent?: Event; value: string | number | boolean | null | object; [key: string]: string | number | boolean | null | object } | string | number | boolean | null | object[])
|
|
||||||
}
|
|
||||||
|
|
||||||
props {
|
props {
|
||||||
size: string = "default"
|
|
||||||
color: string = "primary"
|
color: string = "primary"
|
||||||
columns: number = 2
|
size: string = "default"
|
||||||
gap: string = "md"
|
axis: string = "vertical"
|
||||||
maxWidth: string = "xl"
|
// Track thickness in pixels. Clamped, because it arrives as an attribute
|
||||||
|
// and a scrollbar wider than the content is not useful to anyone.
|
||||||
|
thickness: number = 8
|
||||||
|
maxHeight: string = "20rem"
|
||||||
|
radius: string = "999px"
|
||||||
class: string = ""
|
class: string = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
functions {
|
||||||
|
shared function trackSize() {
|
||||||
|
var value = Number(thickness)
|
||||||
|
if (!value || value < 2) {
|
||||||
|
return 8
|
||||||
|
}
|
||||||
|
return Math.min(24, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
view {
|
view {
|
||||||
<div class="wire-next wire-next--color-{color} wire-next--size-{size} wire-next--custom-scrollbar wire-next--gap-{gap} wire-next--columns-{columns} wire-next--max-{maxWidth} {class}"><slot /></div>
|
<div
|
||||||
|
{...attrs}
|
||||||
|
data-ui-component="CustomScrollbar"
|
||||||
|
class='wire-scrollbar {class}'
|
||||||
|
data-color='{color}'
|
||||||
|
data-size='{size}'
|
||||||
|
data-axis='{axis}'
|
||||||
|
style='--scrollbar-thickness:{trackSize()}px;--scrollbar-radius:{radius};max-height:{maxHeight};'
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
style {
|
||||||
|
.wire-scrollbar {
|
||||||
|
--scrollbar-accent: var(--wire-color-primary);
|
||||||
|
min-width: 0;
|
||||||
|
overflow: auto;
|
||||||
|
/*
|
||||||
|
* The standard properties. Firefox and current Chrome honour these; the
|
||||||
|
* webkit rules below are only for the engines that still ignore them.
|
||||||
|
*/
|
||||||
|
scrollbar-width: thin;
|
||||||
|
scrollbar-color: color-mix(in srgb, var(--scrollbar-accent) 55%, transparent) transparent;
|
||||||
|
overscroll-behavior: contain;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-scrollbar[data-color="secondary"] {
|
||||||
|
--scrollbar-accent: var(--wire-color-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-scrollbar[data-color="success"] {
|
||||||
|
--scrollbar-accent: var(--wire-color-success);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-scrollbar[data-color="danger"] {
|
||||||
|
--scrollbar-accent: var(--wire-color-danger);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-scrollbar[data-color="info"] {
|
||||||
|
--scrollbar-accent: var(--wire-color-info);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-scrollbar[data-axis="vertical"] {
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-scrollbar[data-axis="horizontal"] {
|
||||||
|
overflow-x: auto;
|
||||||
|
overflow-y: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-scrollbar::-webkit-scrollbar {
|
||||||
|
width: var(--scrollbar-thickness, 8px);
|
||||||
|
height: var(--scrollbar-thickness, 8px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-scrollbar::-webkit-scrollbar-track {
|
||||||
|
background: var(--wire-color-surface-soft);
|
||||||
|
border-radius: var(--scrollbar-radius, 999px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-scrollbar::-webkit-scrollbar-thumb {
|
||||||
|
background: color-mix(in srgb, var(--scrollbar-accent) 45%, transparent);
|
||||||
|
border-radius: var(--scrollbar-radius, 999px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-scrollbar::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: var(--scrollbar-accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A pointer-less device paints its own overlay scrollbar and ignores the
|
||||||
|
* width above, so the region keeps its own padding instead.
|
||||||
|
*/
|
||||||
|
@media (hover: none) {
|
||||||
|
.wire-scrollbar {
|
||||||
|
scrollbar-width: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,13 @@
|
|||||||
|
// Image -- a framed image with a reserved aspect ratio.
|
||||||
|
//
|
||||||
|
// <Image src="/hero.jpg" alt="Dashboard" size="video" rounded={true} />
|
||||||
|
//
|
||||||
|
// The frame keeps its ratio whether or not the image has loaded, so the page
|
||||||
|
// does not jump when it arrives. Without a src it renders a labelled
|
||||||
|
// placeholder of the same shape rather than collapsing.
|
||||||
|
//
|
||||||
|
// NOTE: the style block uses /* */ comments only -- // is not a CSS comment
|
||||||
|
// and silently swallows the rule that follows it.
|
||||||
component Image {
|
component Image {
|
||||||
props {
|
props {
|
||||||
size: string = "default"
|
size: string = "default"
|
||||||
@@ -7,41 +17,111 @@ component Image {
|
|||||||
width: string = ""
|
width: string = ""
|
||||||
height: string = ""
|
height: string = ""
|
||||||
loading: string = "lazy"
|
loading: string = "lazy"
|
||||||
|
fit: string = "cover"
|
||||||
rounded: boolean = false
|
rounded: boolean = false
|
||||||
class: string = ""
|
class: string = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
view {
|
view {
|
||||||
<figure
|
<figure
|
||||||
|
{...attrs}
|
||||||
data-ui-component="Image"
|
data-ui-component="Image"
|
||||||
class='relative m-0 overflow-hidden bg-[var(--wire-color-surface-soft)] {class}'
|
class='wire-image {class}'
|
||||||
class:rounded-2xl='rounded'
|
data-size='{size}'
|
||||||
|
data-color='{color}'
|
||||||
|
data-fit='{fit}'
|
||||||
|
data-rounded='{rounded}'
|
||||||
>
|
>
|
||||||
{#if src}
|
|
||||||
<img
|
<img
|
||||||
|
class="wire-image__img"
|
||||||
|
data-show="src"
|
||||||
src='{src}'
|
src='{src}'
|
||||||
alt='{alt}'
|
alt='{alt}'
|
||||||
width='{width}'
|
width='{width}'
|
||||||
height='{height}'
|
height='{height}'
|
||||||
loading='{loading}'
|
loading='{loading}'
|
||||||
decoding="async"
|
decoding="async"
|
||||||
class="block h-auto w-full object-cover transition duration-300"
|
|
||||||
class:aspect-square='size === "square"'
|
|
||||||
class:aspect-video='size === "video"'
|
|
||||||
class:aspect-[4/3]='size === "landscape"'
|
|
||||||
class:aspect-[3/4]='size === "portrait"'
|
|
||||||
/>
|
/>
|
||||||
{:else}
|
|
||||||
<div
|
<div
|
||||||
class="flex min-h-48 w-full items-center justify-center text-[var(--wire-color-text-muted)]"
|
class="wire-image__placeholder"
|
||||||
|
data-show="!src"
|
||||||
role="img"
|
role="img"
|
||||||
aria-label='{alt || "Image placeholder"}'
|
aria-label='{alt || "Image placeholder"}'
|
||||||
>
|
>
|
||||||
<span class="icon-[lucide--image] size-8" aria-hidden="true"></span>
|
<span class="icon-[lucide--image] wire-image__placeholder-icon" aria-hidden="true"></span>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
|
||||||
|
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</figure>
|
</figure>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
style {
|
||||||
|
.wire-image {
|
||||||
|
position: relative;
|
||||||
|
margin: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
width: 100%;
|
||||||
|
min-width: 0;
|
||||||
|
background: var(--wire-color-surface-soft);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-image[data-rounded="true"] {
|
||||||
|
border-radius: var(--wire-radius-lg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The ratio sits on the frame rather than the image, so the space is
|
||||||
|
* reserved before the file arrives and the page does not jump.
|
||||||
|
*/
|
||||||
|
.wire-image[data-size="square"] {
|
||||||
|
aspect-ratio: 1 / 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-image[data-size="video"] {
|
||||||
|
aspect-ratio: 16 / 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-image[data-size="landscape"] {
|
||||||
|
aspect-ratio: 4 / 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-image[data-size="portrait"] {
|
||||||
|
aspect-ratio: 3 / 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-image__img {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-image[data-fit="contain"] .wire-image__img {
|
||||||
|
object-fit: contain;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-image[data-fit="fill"] .wire-image__img {
|
||||||
|
object-fit: fill;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-image[data-size="default"] .wire-image__img {
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-image__placeholder {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 100%;
|
||||||
|
min-height: 12rem;
|
||||||
|
height: 100%;
|
||||||
|
color: var(--wire-color-text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-image__placeholder-icon {
|
||||||
|
width: 2rem;
|
||||||
|
height: 2rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -232,26 +232,17 @@ component InputNumber {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Outputs are resolved by name, so each one is written out. Raw
|
||||||
|
// CustomEvents dispatched on the root -- what this did before -- never
|
||||||
|
// reach a parent @binding.
|
||||||
client function dispatchInputNumberEvent(
|
client function dispatchInputNumberEvent(
|
||||||
sourceEvent,
|
sourceEvent,
|
||||||
eventName,
|
eventName,
|
||||||
action,
|
action,
|
||||||
previousValue,
|
previousValue,
|
||||||
root,
|
payload
|
||||||
customEvent
|
|
||||||
) {
|
) {
|
||||||
root = sourceEvent.currentTarget.closest("[data-wrn-input-number]")
|
payload = {
|
||||||
|
|
||||||
if (!root && sourceEvent.target) {
|
|
||||||
root = sourceEvent.target.closest("[data-wrn-input-number]")
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!root) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
customEvent = document.createEvent("CustomEvent")
|
|
||||||
customEvent.initCustomEvent(eventName, true, false, {
|
|
||||||
component: "InputNumber",
|
component: "InputNumber",
|
||||||
name: name,
|
name: name,
|
||||||
value: currentValue,
|
value: currentValue,
|
||||||
@@ -261,8 +252,17 @@ component InputNumber {
|
|||||||
max: hasMax() ? Number(max) : null,
|
max: hasMax() ? Number(max) : null,
|
||||||
step: normalizedStep(),
|
step: normalizedStep(),
|
||||||
valid: !isInvalid()
|
valid: !isInvalid()
|
||||||
})
|
}
|
||||||
root.dispatchEvent(customEvent)
|
|
||||||
|
if (eventName === "input") {
|
||||||
|
output.input(payload)
|
||||||
|
} else if (eventName === "change") {
|
||||||
|
output.change(payload)
|
||||||
|
} else if (eventName === "increment") {
|
||||||
|
output.increment(payload)
|
||||||
|
} else if (eventName === "decrement") {
|
||||||
|
output.decrement(payload)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
client function applyControlValue(nextValue, action, sourceEvent, previousValue) {
|
client function applyControlValue(nextValue, action, sourceEvent, previousValue) {
|
||||||
|
|||||||
@@ -1,9 +1,55 @@
|
|||||||
|
// Kbd -- a keyboard key.
|
||||||
|
//
|
||||||
|
// <Kbd label="Ctrl" />
|
||||||
|
//
|
||||||
|
// Deliberately small. A kbd element is a kbd element; the work here is making
|
||||||
|
// it look like a key and follow the theme.
|
||||||
|
//
|
||||||
|
// NOTE: the style block uses /* */ comments only -- // is not a CSS comment
|
||||||
|
// and silently swallows the rule that follows it.
|
||||||
component Kbd {
|
component Kbd {
|
||||||
props {
|
props {
|
||||||
size: string = "default"
|
size: string = "default"
|
||||||
color: string = "primary"
|
color: string = "primary"
|
||||||
label: string = "⌘ K"
|
label: string = "K"
|
||||||
class: string = ""
|
class: string = ""
|
||||||
}
|
}
|
||||||
view { <kbd class="wire-next wire-next--color-{color} wire-next--size-{size} wire-next--kbd {class}"><slot>{label}</slot></kbd> }
|
|
||||||
|
view {
|
||||||
|
<kbd {...attrs} class='wire-kbd {class}' data-size='{size}' data-color='{color}'>
|
||||||
|
<slot>{label}</slot>
|
||||||
|
</kbd>
|
||||||
|
}
|
||||||
|
|
||||||
|
style {
|
||||||
|
.wire-kbd {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
min-width: 1.6rem;
|
||||||
|
padding: 0.15rem 0.4rem;
|
||||||
|
border: 1px solid var(--wire-color-border);
|
||||||
|
/* The lower edge is what reads as a physical key. */
|
||||||
|
border-bottom-width: 2px;
|
||||||
|
border-radius: var(--wire-radius-sm);
|
||||||
|
background: var(--wire-color-surface-soft);
|
||||||
|
color: var(--wire-color-text);
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: 0.78rem;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-kbd[data-size="sm"] {
|
||||||
|
min-width: 1.4rem;
|
||||||
|
padding: 0.1rem 0.3rem;
|
||||||
|
font-size: 0.7rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-kbd[data-size="lg"] {
|
||||||
|
min-width: 2rem;
|
||||||
|
padding: 0.3rem 0.55rem;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,225 @@
|
|||||||
|
// LayoutSplitter -- two panes with a divider the reader can move.
|
||||||
|
//
|
||||||
|
// <LayoutSplitter size={40} minSize={20}>
|
||||||
|
// <div data-slot="start">...</div>
|
||||||
|
// <div data-slot="end">...</div>
|
||||||
|
// </LayoutSplitter>
|
||||||
|
//
|
||||||
|
// The dragging lives in the reactive runtime behind data-wrn-splitter. Pointer
|
||||||
|
// moves fire far too often to route through a client function, and a state
|
||||||
|
// write made inside a pointermove callback is dropped, so the resolved size is
|
||||||
|
// held in the DOM as the --wrn-split custom property and these styles read it.
|
||||||
|
//
|
||||||
|
// This component previously declared resizeStart, resize and resizeEnd with no
|
||||||
|
// pointer handling whatsoever: a caller wired up @resize and received nothing,
|
||||||
|
// for ever, with no error.
|
||||||
|
//
|
||||||
|
// NOTE: the style block uses /* */ comments only -- // is not a CSS comment
|
||||||
|
// and silently swallows the rule that follows it.
|
||||||
component LayoutSplitter {
|
component LayoutSplitter {
|
||||||
outputs {
|
outputs {
|
||||||
resizeStart(payload: { sourceEvent?: Event; value: string | number | boolean | null | object; [key: string]: string | number | boolean | null | object } | string | number | boolean | null | object[])
|
// Named sizeChange rather than resize so it cannot be confused with the
|
||||||
resize(payload: { sourceEvent?: Event; value: string | number | boolean | null | object; [key: string]: string | number | boolean | null | object } | string | number | boolean | null | object[])
|
// native window event a caller may already be listening for. An earlier
|
||||||
resizeEnd(payload: { sourceEvent?: Event; value: string | number | boolean | null | object; [key: string]: string | number | boolean | null | object } | string | number | boolean | null | object[])
|
// comment here claimed a natively-named output could never reach a parent
|
||||||
|
// binding; that was wrong, and the rename was never what fixed anything.
|
||||||
|
sizeChange(payload: { size: number })
|
||||||
}
|
}
|
||||||
|
|
||||||
props {
|
props {
|
||||||
size: string = "default"
|
|
||||||
color: string = "primary"
|
color: string = "primary"
|
||||||
columns: number = 2
|
size: number = 50
|
||||||
gap: string = "md"
|
orientation: string = "horizontal"
|
||||||
maxWidth: string = "xl"
|
// Smallest share either pane may take, as a percentage. It also fixes the
|
||||||
|
// upper bound at 100 - minSize, so neither pane can be dragged away to
|
||||||
|
// nothing and left unrecoverable by pointer.
|
||||||
|
minSize: number = 15
|
||||||
|
step: number = 5
|
||||||
|
label: string = "Resize panels"
|
||||||
class: string = ""
|
class: string = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
functions {
|
||||||
|
// The runtime resolves the size and announces it; this turns that into the
|
||||||
|
// declared output so a parent @resize binding receives it.
|
||||||
|
client function reportResize(sourceEvent) {
|
||||||
|
var detail = sourceEvent ? sourceEvent.detail : null
|
||||||
|
if (!detail) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
output.sizeChange({ size: detail.size })
|
||||||
|
}
|
||||||
|
|
||||||
|
shared function isVertical() {
|
||||||
|
return orientation === "vertical"
|
||||||
|
}
|
||||||
|
|
||||||
|
shared function lowerBound() {
|
||||||
|
var value = Number(minSize)
|
||||||
|
if (!value || value < 0) {
|
||||||
|
return 15
|
||||||
|
}
|
||||||
|
return Math.min(45, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
shared function upperBound() {
|
||||||
|
return 100 - lowerBound()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sizes arrive as HTML attributes, so a value outside the bounds is
|
||||||
|
// routine rather than exceptional. Clamp instead of rendering something
|
||||||
|
// the reader cannot undo.
|
||||||
|
shared function currentSize() {
|
||||||
|
var value = Number(size)
|
||||||
|
if (!value || value < 0) {
|
||||||
|
return 50
|
||||||
|
}
|
||||||
|
return Math.min(upperBound(), Math.max(lowerBound(), value))
|
||||||
|
}
|
||||||
|
|
||||||
|
shared function stepSize() {
|
||||||
|
var value = Number(step)
|
||||||
|
return value && value > 0 ? value : 5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
view {
|
view {
|
||||||
<div class="wire-next wire-next--color-{color} wire-next--size-{size} wire-next--layout-splitter wire-next--gap-{gap} wire-next--columns-{columns} wire-next--max-{maxWidth} {class}"><slot /></div>
|
<div
|
||||||
|
{...attrs}
|
||||||
|
data-ui-component="LayoutSplitter"
|
||||||
|
class='wire-splitter {class}'
|
||||||
|
data-color='{color}'
|
||||||
|
data-orientation='{orientation}'
|
||||||
|
data-wrn-splitter='{isVertical() ? "vertical" : "horizontal"}'
|
||||||
|
data-wrn-splitter-min='{lowerBound()}'
|
||||||
|
data-wrn-splitter-step='{stepSize()}'
|
||||||
|
style='--wrn-split:{currentSize()}%;'
|
||||||
|
@wrnexus:splitter:resize='reportResize(event)'
|
||||||
|
>
|
||||||
|
<div class="wire-splitter__pane wire-splitter__pane--start">
|
||||||
|
<slot name="start"></slot>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="wire-splitter__handle"
|
||||||
|
data-wrn-splitter-handle="true"
|
||||||
|
role="separator"
|
||||||
|
tabindex="0"
|
||||||
|
aria-label='{label}'
|
||||||
|
aria-orientation='{isVertical() ? "horizontal" : "vertical"}'
|
||||||
|
aria-valuenow='{currentSize()}'
|
||||||
|
aria-valuemin='{lowerBound()}'
|
||||||
|
aria-valuemax='{upperBound()}'
|
||||||
|
>
|
||||||
|
<span class="wire-splitter__grip" aria-hidden="true"></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="wire-splitter__pane wire-splitter__pane--end">
|
||||||
|
<slot name="end"></slot>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
style {
|
||||||
|
.wire-splitter {
|
||||||
|
--splitter-accent: var(--wire-color-primary);
|
||||||
|
display: grid;
|
||||||
|
/* The first track follows the size the runtime resolves. */
|
||||||
|
grid-template-columns: var(--wrn-split, 50%) auto minmax(0, 1fr);
|
||||||
|
align-items: stretch;
|
||||||
|
width: 100%;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-splitter[data-color="secondary"] {
|
||||||
|
--splitter-accent: var(--wire-color-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-splitter[data-color="success"] {
|
||||||
|
--splitter-accent: var(--wire-color-success);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-splitter[data-color="danger"] {
|
||||||
|
--splitter-accent: var(--wire-color-danger);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-splitter[data-color="info"] {
|
||||||
|
--splitter-accent: var(--wire-color-info);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-splitter[data-orientation="vertical"] {
|
||||||
|
grid-template-columns: minmax(0, 1fr);
|
||||||
|
grid-template-rows: var(--wrn-split, 50%) auto minmax(0, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-splitter__pane {
|
||||||
|
min-width: 0;
|
||||||
|
min-height: 0;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-splitter__handle {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
padding: 0 0.25rem;
|
||||||
|
border: 0;
|
||||||
|
background: transparent;
|
||||||
|
cursor: col-resize;
|
||||||
|
/* Without this the pointer drag selects the text in both panes. */
|
||||||
|
touch-action: none;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-splitter[data-orientation="vertical"] .wire-splitter__handle {
|
||||||
|
padding: 0.25rem 0;
|
||||||
|
cursor: row-resize;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-splitter__grip {
|
||||||
|
display: block;
|
||||||
|
width: 2px;
|
||||||
|
height: 100%;
|
||||||
|
min-height: 1.5rem;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: var(--wire-color-border);
|
||||||
|
transition: background 140ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-splitter[data-orientation="vertical"] .wire-splitter__grip {
|
||||||
|
width: 100%;
|
||||||
|
min-width: 1.5rem;
|
||||||
|
height: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-splitter__handle:hover .wire-splitter__grip,
|
||||||
|
.wire-splitter[data-wrn-splitter-dragging="true"] .wire-splitter__grip {
|
||||||
|
background: var(--splitter-accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-splitter__handle:focus-visible {
|
||||||
|
outline: 2px solid var(--splitter-accent);
|
||||||
|
outline-offset: -2px;
|
||||||
|
border-radius: var(--wire-radius-sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Two panes side by side stop making sense on a phone. Stacking them keeps
|
||||||
|
* both readable, and the divider stops being draggable because the grid
|
||||||
|
* no longer has a second track to trade against.
|
||||||
|
*/
|
||||||
|
@media (max-width: 639px) {
|
||||||
|
.wire-splitter,
|
||||||
|
.wire-splitter[data-orientation="vertical"] {
|
||||||
|
grid-template-columns: minmax(0, 1fr);
|
||||||
|
grid-template-rows: auto auto auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-splitter__handle {
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+111
-21
@@ -1,3 +1,13 @@
|
|||||||
|
// Link -- a text link that follows the theme.
|
||||||
|
//
|
||||||
|
// <Link href="/docs" label="Documentation" />
|
||||||
|
// <Link href="https://example.com" label="Spec" external={true} />
|
||||||
|
//
|
||||||
|
// external adds rel="noopener noreferrer" and an outbound icon, so the reader
|
||||||
|
// is told the link leaves the site before they follow it.
|
||||||
|
//
|
||||||
|
// NOTE: the style block uses /* */ comments only -- // is not a CSS comment
|
||||||
|
// and silently swallows the rule that follows it.
|
||||||
component Link {
|
component Link {
|
||||||
props {
|
props {
|
||||||
size: string = "default"
|
size: string = "default"
|
||||||
@@ -6,42 +16,122 @@ component Link {
|
|||||||
href: string = "#"
|
href: string = "#"
|
||||||
target: string = ""
|
target: string = ""
|
||||||
rel: string = ""
|
rel: string = ""
|
||||||
|
underline: string = "hover"
|
||||||
external: boolean = false
|
external: boolean = false
|
||||||
class: string = ""
|
class: string = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
view {
|
view {
|
||||||
<a
|
<a
|
||||||
|
{...attrs}
|
||||||
data-ui-component="Link"
|
data-ui-component="Link"
|
||||||
|
class='wire-link {class}'
|
||||||
href='{href}'
|
href='{href}'
|
||||||
target='{target}'
|
target='{target}'
|
||||||
rel='{external ? (rel || "noopener noreferrer") : rel}'
|
rel='{external ? (rel || "noopener noreferrer") : rel}'
|
||||||
class='inline-flex min-w-0 items-center gap-1.5 rounded-md font-semibold underline-offset-4 outline-none transition-colors focus-visible:ring-2 focus-visible:ring-[var(--wire-color-focus)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--wire-color-background)] {class}'
|
data-size='{size}'
|
||||||
class:text-xs='size === "xs"'
|
data-color='{color}'
|
||||||
class:text-sm='size === "sm" || size === "default"'
|
data-underline='{underline}'
|
||||||
class:text-base='size === "md"'
|
data-external='{external}'
|
||||||
class:text-lg='size === "lg"'
|
|
||||||
class:text-[var(--wire-color-primary)]='color === "primary"'
|
|
||||||
class:hover:text-[var(--wire-color-primary-hover)]='color === "primary"'
|
|
||||||
class:text-[var(--wire-color-secondary)]='color === "secondary"'
|
|
||||||
class:hover:text-[var(--wire-color-secondary-hover)]='color === "secondary"'
|
|
||||||
class:text-[var(--wire-color-success)]='color === "success"'
|
|
||||||
class:text-[var(--wire-color-warning-text)]='color === "warning"'
|
|
||||||
class:text-[var(--wire-color-danger)]='color === "danger"'
|
|
||||||
class:text-[var(--wire-color-info)]='color === "info"'
|
|
||||||
class:text-[var(--wire-color-text)]='color === "neutral"'
|
|
||||||
class:hover:underline='external === false'
|
|
||||||
>
|
>
|
||||||
<span class="truncate">{label}</span>
|
<span class="wire-link__label">{label}</span>
|
||||||
|
|
||||||
{#if external}
|
|
||||||
<span
|
<span
|
||||||
class="icon-[lucide--external-link] size-3.5 shrink-0"
|
class="icon-[lucide--external-link] wire-link__icon"
|
||||||
|
data-show="external"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
></span>
|
></span>
|
||||||
{/if}
|
|
||||||
|
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</a>
|
</a>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
style {
|
||||||
|
.wire-link {
|
||||||
|
--link-tone: var(--wire-color-primary);
|
||||||
|
--link-tone-hover: var(--wire-color-primary-hover);
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.35rem;
|
||||||
|
min-width: 0;
|
||||||
|
border-radius: var(--wire-radius-sm);
|
||||||
|
color: var(--link-tone);
|
||||||
|
font-size: 0.875rem;
|
||||||
|
font-weight: 600;
|
||||||
|
text-decoration: none;
|
||||||
|
text-underline-offset: 4px;
|
||||||
|
transition: color 140ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-link[data-color="secondary"] {
|
||||||
|
--link-tone: var(--wire-color-secondary);
|
||||||
|
--link-tone-hover: var(--wire-color-secondary-hover);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-link[data-color="success"] {
|
||||||
|
--link-tone: var(--wire-color-success);
|
||||||
|
--link-tone-hover: var(--wire-color-success);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-link[data-color="warning"] {
|
||||||
|
--link-tone: var(--wire-color-warning-text);
|
||||||
|
--link-tone-hover: var(--wire-color-warning-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-link[data-color="danger"] {
|
||||||
|
--link-tone: var(--wire-color-danger);
|
||||||
|
--link-tone-hover: var(--wire-color-danger);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-link[data-color="info"] {
|
||||||
|
--link-tone: var(--wire-color-info);
|
||||||
|
--link-tone-hover: var(--wire-color-info);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-link[data-color="neutral"] {
|
||||||
|
--link-tone: var(--wire-color-text);
|
||||||
|
--link-tone-hover: var(--wire-color-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-link[data-size="xs"] {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-link[data-size="md"] {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-link[data-size="lg"] {
|
||||||
|
font-size: 1.125rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-link[data-underline="always"] {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-link[data-underline="hover"]:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-link:hover {
|
||||||
|
color: var(--link-tone-hover);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-link:focus-visible {
|
||||||
|
outline: 2px solid var(--wire-color-focus);
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The label truncates; the outbound icon must not shrink with it. */
|
||||||
|
.wire-link__label {
|
||||||
|
min-width: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-link__icon {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
width: 0.875rem;
|
||||||
|
height: 0.875rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
component List {
|
component List {
|
||||||
|
outputs {
|
||||||
|
select(payload: { sourceEvent?: Event; [key: string]: string | number | boolean | null | object })
|
||||||
|
}
|
||||||
|
|
||||||
props {
|
props {
|
||||||
size: string = "default"
|
size: string = "default"
|
||||||
color: string = "primary"
|
color: string = "primary"
|
||||||
@@ -52,7 +56,7 @@ component List {
|
|||||||
class:py-2.5='size === "sm"'
|
class:py-2.5='size === "sm"'
|
||||||
class:px-5='size === "lg"'
|
class:px-5='size === "lg"'
|
||||||
class:py-4='size === "lg"'
|
class:py-4='size === "lg"'
|
||||||
@click='event.currentTarget.dispatchEvent(new CustomEvent("select", { bubbles: true, detail: { item: item, index: index } }))'
|
@click='output.select({ item: item, index: index })'
|
||||||
>
|
>
|
||||||
{#if item.icon}
|
{#if item.icon}
|
||||||
<span class="flex size-10 shrink-0 items-center justify-center rounded-xl bg-[var(--wire-color-primary-soft)] text-[var(--wire-color-primary)]">
|
<span class="flex size-10 shrink-0 items-center justify-center rounded-xl bg-[var(--wire-color-primary-soft)] text-[var(--wire-color-primary)]">
|
||||||
|
|||||||
@@ -1,4 +1,12 @@
|
|||||||
component Map {
|
component Map {
|
||||||
|
outputs {
|
||||||
|
// markerClick and select both fire for a marker press; select is the
|
||||||
|
// generic name callers reach for, markerClick the explicit one.
|
||||||
|
markerClick(payload: { sourceEvent?: Event; [key: string]: string | number | boolean | null | object })
|
||||||
|
select(payload: { sourceEvent?: Event; [key: string]: string | number | boolean | null | object })
|
||||||
|
zoom(payload: { sourceEvent?: Event; [key: string]: string | number | boolean | null | object })
|
||||||
|
}
|
||||||
|
|
||||||
props {
|
props {
|
||||||
size: string = "default"
|
size: string = "default"
|
||||||
color: string = "primary"
|
color: string = "primary"
|
||||||
@@ -54,7 +62,7 @@ component Map {
|
|||||||
aria-label='{item.label || item.title || "Map marker"}'
|
aria-label='{item.label || item.title || "Map marker"}'
|
||||||
class="absolute inline-flex size-10 items-center justify-center rounded-full border-4 border-[var(--wire-color-surface-raised)] bg-[var(--wire-color-primary)] text-[var(--wire-color-on-primary)] shadow-lg transition hover:scale-110 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--wire-color-focus)]"
|
class="absolute inline-flex size-10 items-center justify-center rounded-full border-4 border-[var(--wire-color-surface-raised)] bg-[var(--wire-color-primary)] text-[var(--wire-color-on-primary)] shadow-lg transition hover:scale-110 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--wire-color-focus)]"
|
||||||
style='left: {item.x || (20 + index * 12)}%; top: {item.y || (30 + (index % 3) * 18)}%;'
|
style='left: {item.x || (20 + index * 12)}%; top: {item.y || (30 + (index % 3) * 18)}%;'
|
||||||
@click='event.currentTarget.dispatchEvent(new CustomEvent("markerClick", { bubbles: true, detail: item })); event.currentTarget.dispatchEvent(new CustomEvent("select", { bubbles: true, detail: item }))'
|
@click='output.markerClick(item); output.select(item)'
|
||||||
>
|
>
|
||||||
<span class='{item.icon || "icon-[lucide--map-pin]"}' aria-hidden="true"></span>
|
<span class='{item.icon || "icon-[lucide--map-pin]"}' aria-hidden="true"></span>
|
||||||
</button>
|
</button>
|
||||||
@@ -66,7 +74,7 @@ component Map {
|
|||||||
type="button"
|
type="button"
|
||||||
aria-label="Zoom in"
|
aria-label="Zoom in"
|
||||||
class="inline-flex size-10 items-center justify-center rounded-xl border border-[var(--wire-color-border)] bg-[var(--wire-color-surface-raised)] text-[var(--wire-color-text)] shadow-sm transition hover:bg-[var(--wire-color-surface-soft)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--wire-color-focus)]"
|
class="inline-flex size-10 items-center justify-center rounded-xl border border-[var(--wire-color-border)] bg-[var(--wire-color-surface-raised)] text-[var(--wire-color-text)] shadow-sm transition hover:bg-[var(--wire-color-surface-soft)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--wire-color-focus)]"
|
||||||
@click='event.currentTarget.dispatchEvent(new CustomEvent("zoom", { bubbles: true, detail: { direction: "in" } }))'
|
@click='output.zoom({ direction: "in" })'
|
||||||
>
|
>
|
||||||
<span class="icon-[lucide--plus] size-4" aria-hidden="true"></span>
|
<span class="icon-[lucide--plus] size-4" aria-hidden="true"></span>
|
||||||
</button>
|
</button>
|
||||||
@@ -74,7 +82,7 @@ component Map {
|
|||||||
type="button"
|
type="button"
|
||||||
aria-label="Zoom out"
|
aria-label="Zoom out"
|
||||||
class="inline-flex size-10 items-center justify-center rounded-xl border border-[var(--wire-color-border)] bg-[var(--wire-color-surface-raised)] text-[var(--wire-color-text)] shadow-sm transition hover:bg-[var(--wire-color-surface-soft)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--wire-color-focus)]"
|
class="inline-flex size-10 items-center justify-center rounded-xl border border-[var(--wire-color-border)] bg-[var(--wire-color-surface-raised)] text-[var(--wire-color-text)] shadow-sm transition hover:bg-[var(--wire-color-surface-soft)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--wire-color-focus)]"
|
||||||
@click='event.currentTarget.dispatchEvent(new CustomEvent("zoom", { bubbles: true, detail: { direction: "out" } }))'
|
@click='output.zoom({ direction: "out" })'
|
||||||
>
|
>
|
||||||
<span class="icon-[lucide--minus] size-4" aria-hidden="true"></span>
|
<span class="icon-[lucide--minus] size-4" aria-hidden="true"></span>
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -1,4 +1,10 @@
|
|||||||
component Marquee {
|
component Marquee {
|
||||||
|
outputs {
|
||||||
|
// Fired when the reader pauses the scroll, by hover, focus or the button.
|
||||||
|
pause(payload: { sourceEvent?: Event; [key: string]: string | number | boolean | null | object })
|
||||||
|
resume(payload: { sourceEvent?: Event; [key: string]: string | number | boolean | null | object })
|
||||||
|
}
|
||||||
|
|
||||||
props {
|
props {
|
||||||
size: string = "default"
|
size: string = "default"
|
||||||
color: string = "primary"
|
color: string = "primary"
|
||||||
@@ -27,8 +33,8 @@ component Marquee {
|
|||||||
|
|
||||||
<div
|
<div
|
||||||
class="group relative min-w-0 flex-1 overflow-hidden"
|
class="group relative min-w-0 flex-1 overflow-hidden"
|
||||||
@mouseenter='paused = true; event.currentTarget.dispatchEvent(new CustomEvent("pause", { bubbles: true }))'
|
@mouseenter='paused = true; output.pause({})'
|
||||||
@mouseleave='paused = false; event.currentTarget.dispatchEvent(new CustomEvent("resume", { bubbles: true }))'
|
@mouseleave='paused = false; output.resume({})'
|
||||||
@focusin='paused = true'
|
@focusin='paused = true'
|
||||||
@focusout='paused = false'
|
@focusout='paused = false'
|
||||||
>
|
>
|
||||||
@@ -77,7 +83,7 @@ component Marquee {
|
|||||||
type="button"
|
type="button"
|
||||||
aria-label='{paused ? "Resume announcements" : "Pause announcements"}'
|
aria-label='{paused ? "Resume announcements" : "Pause announcements"}'
|
||||||
class="flex shrink-0 items-center justify-center border-l border-[var(--wire-color-border)] px-4 text-[var(--wire-color-text-muted)] transition hover:bg-[var(--wire-color-surface-soft)] hover:text-[var(--wire-color-text)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-[var(--wire-color-focus)]"
|
class="flex shrink-0 items-center justify-center border-l border-[var(--wire-color-border)] px-4 text-[var(--wire-color-text-muted)] transition hover:bg-[var(--wire-color-surface-soft)] hover:text-[var(--wire-color-text)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-[var(--wire-color-focus)]"
|
||||||
@click='paused = !paused; event.currentTarget.dispatchEvent(new CustomEvent(paused ? "pause" : "resume", { bubbles: true }))'
|
@click='paused = !paused; paused ? output.pause({}) : output.resume({})'
|
||||||
>
|
>
|
||||||
<span class="icon-[lucide--pause] size-4" data-show='!paused' aria-hidden="true"></span>
|
<span class="icon-[lucide--pause] size-4" data-show='!paused' aria-hidden="true"></span>
|
||||||
<span class="icon-[lucide--play] size-4" data-show='paused' aria-hidden="true"></span>
|
<span class="icon-[lucide--play] size-4" data-show='paused' aria-hidden="true"></span>
|
||||||
|
|||||||
@@ -1,23 +1,344 @@
|
|||||||
|
// MegaMenu -- a trigger and a wide panel of grouped links.
|
||||||
|
//
|
||||||
|
// <MegaMenu label="Products" columns='[{"heading":"Platform",
|
||||||
|
// "items":[{"label":"Runtime","href":"/runtime"}]}]' />
|
||||||
|
//
|
||||||
|
// Deliberately one level deep. A mega menu exists to show breadth flat, so
|
||||||
|
// everything is one click away; nesting inside the panel buries content behind
|
||||||
|
// hover-within-hover and is close to unusable by keyboard and touch. Use Nav
|
||||||
|
// when you actually want cascading submenus.
|
||||||
|
//
|
||||||
|
// The panel carries data-wrn-anchored so the runtime clamp keeps it inside the
|
||||||
|
// viewport instead of hanging off the edge of a wide layout.
|
||||||
|
//
|
||||||
|
// NOTE: the style block uses /* */ comments only -- // is not a CSS comment
|
||||||
|
// and silently swallows the rule that follows it.
|
||||||
component MegaMenu {
|
component MegaMenu {
|
||||||
outputs {
|
outputs {
|
||||||
open(payload: { sourceEvent?: Event; [key: string]: string | number | boolean | null | object })
|
open(payload: { sourceEvent: Event })
|
||||||
close(payload: { sourceEvent?: Event; [key: string]: string | number | boolean | null | object })
|
close(payload: { reason: string })
|
||||||
select(payload: { value?: string | number | boolean | null; values?: Array<string | number | boolean | null | object>; sourceEvent?: Event; [key: string]: string | number | boolean | null | object } | string | number | boolean | null)
|
select(payload: { item: object; value: string })
|
||||||
}
|
}
|
||||||
|
|
||||||
props {
|
props {
|
||||||
size: string = "default"
|
|
||||||
color: string = "primary"
|
color: string = "primary"
|
||||||
label: string = "Mega Menu"
|
size: string = "default"
|
||||||
items: unknown[] = []
|
label: string = "Menu"
|
||||||
active: string = ""
|
icon: string = ""
|
||||||
orientation: string = "horizontal"
|
columns: unknown[] = []
|
||||||
|
footer: string = ""
|
||||||
|
defaultOpen: boolean = false
|
||||||
class: string = ""
|
class: string = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state visible = defaultOpen
|
||||||
|
|
||||||
|
functions {
|
||||||
|
shared function columnList() {
|
||||||
|
return Array.isArray(columns) ? columns : []
|
||||||
|
}
|
||||||
|
|
||||||
|
shared function itemsOf(column) {
|
||||||
|
return column && Array.isArray(column.items) ? column.items : []
|
||||||
|
}
|
||||||
|
|
||||||
|
client function showPanel(sourceEvent) {
|
||||||
|
visible = true
|
||||||
|
output.open({ sourceEvent: sourceEvent })
|
||||||
|
}
|
||||||
|
|
||||||
|
client function hidePanel(reason) {
|
||||||
|
visible = false
|
||||||
|
output.close({ reason: reason })
|
||||||
|
}
|
||||||
|
|
||||||
|
client function togglePanel(sourceEvent) {
|
||||||
|
if (visible) {
|
||||||
|
hidePanel("toggle")
|
||||||
|
} else {
|
||||||
|
showPanel(sourceEvent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
client function handleKeydown(sourceEvent) {
|
||||||
|
if (sourceEvent.key === "Escape" && visible) {
|
||||||
|
sourceEvent.preventDefault()
|
||||||
|
hidePanel("escape")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
client function choose(item) {
|
||||||
|
if (item.disabled) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
output.select({ item: item, value: item.value || item.label || "" })
|
||||||
|
hidePanel("select")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
view {
|
view {
|
||||||
<nav class="wire-next wire-next--color-{color} wire-next--size-{size} wire-next--mega-menu wire-next--{orientation} {class}" aria-label="{label}">
|
<div
|
||||||
{#each items as item}<a href="{item.href}" aria-current="{item.value === active ? 'page' : ''}">{item.label}</a>{/each}
|
{...attrs}
|
||||||
|
data-ui-component="MegaMenu"
|
||||||
|
class='wire-mega {class}'
|
||||||
|
data-color='{color}'
|
||||||
|
data-size='{size}'
|
||||||
|
data-open='{visible}'
|
||||||
|
@keydown='handleKeydown(event)'
|
||||||
|
@mouseleave='hidePanel("pointer-leave")'
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="wire-mega__trigger"
|
||||||
|
aria-haspopup="true"
|
||||||
|
aria-expanded='{visible}'
|
||||||
|
@click='togglePanel(event)'
|
||||||
|
@mouseenter='showPanel(event)'
|
||||||
|
@focus='showPanel(event)'
|
||||||
|
>
|
||||||
|
<span class='wire-mega__trigger-icon {icon}' data-show="icon" aria-hidden="true"></span>
|
||||||
|
<span class="wire-mega__trigger-label">{label}</span>
|
||||||
|
<span class="wire-mega__arrow" aria-hidden="true">›</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="wire-mega__panel"
|
||||||
|
data-wrn-anchored="true"
|
||||||
|
data-show="visible"
|
||||||
|
data-wrn-roving="both"
|
||||||
|
>
|
||||||
|
<div class="wire-mega__columns">
|
||||||
|
{#each columnList() as column}
|
||||||
|
<section class="wire-mega__column">
|
||||||
|
<h3 class="wire-mega__heading" data-show="column.heading">{column.heading}</h3>
|
||||||
|
<ul class="wire-mega__list">
|
||||||
|
{#each itemsOf(column) as item}
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
class="wire-mega__link"
|
||||||
|
href='{item.href || "#"}'
|
||||||
|
data-wrn-roving-item="true"
|
||||||
|
aria-disabled='{item.disabled ? "true" : "false"}'
|
||||||
|
@click='choose(item)'
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class='wire-mega__link-icon {item.icon}'
|
||||||
|
data-show="item.icon"
|
||||||
|
aria-hidden="true"
|
||||||
|
></span>
|
||||||
|
<span class="wire-mega__link-body">
|
||||||
|
<span class="wire-mega__link-label">{item.label}</span>
|
||||||
|
<span class="wire-mega__link-description" data-show="item.description">
|
||||||
|
{item.description}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{/each}
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="wire-mega__footer" data-show="footer">{footer}</p>
|
||||||
<slot />
|
<slot />
|
||||||
</nav>
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
style {
|
||||||
|
.wire-mega {
|
||||||
|
--mega-accent: var(--wire-color-primary);
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-mega[data-color="secondary"] {
|
||||||
|
--mega-accent: var(--wire-color-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-mega[data-color="success"] {
|
||||||
|
--mega-accent: var(--wire-color-success);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-mega[data-color="danger"] {
|
||||||
|
--mega-accent: var(--wire-color-danger);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-mega[data-color="info"] {
|
||||||
|
--mega-accent: var(--wire-color-info);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-mega[data-size="sm"] {
|
||||||
|
font-size: 0.82rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-mega[data-size="lg"] {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-mega__trigger {
|
||||||
|
appearance: none;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.4rem;
|
||||||
|
padding: 0.45rem 0.7rem;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
border-radius: var(--wire-radius-sm);
|
||||||
|
background: transparent;
|
||||||
|
color: var(--wire-color-text-muted);
|
||||||
|
font: inherit;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
font-weight: 600;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-mega__trigger:hover,
|
||||||
|
.wire-mega[data-open="true"] .wire-mega__trigger {
|
||||||
|
background: var(--wire-color-surface-soft);
|
||||||
|
color: var(--wire-color-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-mega__trigger:focus-visible {
|
||||||
|
outline: 2px solid var(--mega-accent);
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-mega__arrow {
|
||||||
|
display: inline-block;
|
||||||
|
transition: transform 160ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-mega[data-open="true"] .wire-mega__arrow {
|
||||||
|
transform: rotate(90deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The panel is offset below the trigger for looks, which used to close the
|
||||||
|
* menu on the way to it: that offset is dead space belonging to neither
|
||||||
|
* element, so crossing it fired mouseleave on the root. The bridge below
|
||||||
|
* covers the gap with a descendant, so the pointer never actually leaves.
|
||||||
|
*/
|
||||||
|
.wire-mega__panel::before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 100%;
|
||||||
|
height: 0.6rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-mega__panel {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 40;
|
||||||
|
top: calc(100% + 0.4rem);
|
||||||
|
left: 0;
|
||||||
|
width: max-content;
|
||||||
|
max-width: min(60rem, calc(100vw - 2rem));
|
||||||
|
padding: 1rem;
|
||||||
|
border: 1px solid var(--wire-color-border);
|
||||||
|
border-radius: var(--wire-radius-lg);
|
||||||
|
background: var(--wire-color-surface);
|
||||||
|
box-shadow: var(--wire-shadow-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-mega__columns {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
|
||||||
|
gap: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-mega__column {
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-mega__heading {
|
||||||
|
margin: 0 0 0.5rem;
|
||||||
|
color: var(--wire-color-text-muted);
|
||||||
|
font-size: 0.72rem;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 0.08em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-mega__list {
|
||||||
|
display: grid;
|
||||||
|
gap: 0.15rem;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-mega__link {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 0.5rem;
|
||||||
|
padding: 0.45rem 0.5rem;
|
||||||
|
border-radius: var(--wire-radius-sm);
|
||||||
|
color: var(--wire-color-text);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-mega__link:hover {
|
||||||
|
background: var(--wire-color-surface-soft);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-mega__link:focus-visible {
|
||||||
|
outline: 2px solid var(--mega-accent);
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-mega__link[aria-disabled="true"] {
|
||||||
|
opacity: 0.5;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-mega__link-body {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-mega__link-label {
|
||||||
|
font-size: 0.88rem;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-mega__link-description {
|
||||||
|
color: var(--wire-color-text-muted);
|
||||||
|
font-size: 0.78rem;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-mega__footer {
|
||||||
|
margin: 1rem 0 0;
|
||||||
|
padding-top: 0.75rem;
|
||||||
|
border-top: 1px solid var(--wire-color-border);
|
||||||
|
color: var(--wire-color-text-muted);
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* On a phone the panel stops floating and becomes part of the flow. A
|
||||||
|
* pointer-opened overlay pinned to a trigger is unreachable on touch, and
|
||||||
|
* a 60rem grid has nowhere to go on a 360px screen.
|
||||||
|
*/
|
||||||
|
@media (max-width: 767px) {
|
||||||
|
.wire-mega {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-mega__panel {
|
||||||
|
position: static;
|
||||||
|
width: auto;
|
||||||
|
max-width: 100%;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-mega__columns {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,354 @@
|
|||||||
|
// Nav -- a navigation link list, flat or with submenus.
|
||||||
|
//
|
||||||
|
// <Nav items='[{"label":"Home","href":"/","value":"home"}]' active="home" />
|
||||||
|
//
|
||||||
|
// An item carrying its own items array becomes a submenu. Depth is capped at
|
||||||
|
// three levels: this template language has no component recursion, so each
|
||||||
|
// level is written out, and three covers any realistic navigation.
|
||||||
|
//
|
||||||
|
// NOTE: the style block uses /* */ comments only -- // is not a CSS comment
|
||||||
|
// and silently swallows the rule that follows it.
|
||||||
component Nav {
|
component Nav {
|
||||||
outputs {
|
outputs {
|
||||||
select(payload: { value?: string | number | boolean | null; values?: Array<string | number | boolean | null | object>; sourceEvent?: Event; [key: string]: string | number | boolean | null | object } | string | number | boolean | null)
|
select(payload: { item: object; value: string })
|
||||||
change(payload: { value?: string | number | boolean | null; values?: Array<string | number | boolean | null | object>; sourceEvent?: Event; [key: string]: string | number | boolean | null | object } | string | number | boolean | null)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
props {
|
props {
|
||||||
size: string = "default"
|
|
||||||
color: string = "primary"
|
color: string = "primary"
|
||||||
label: string = "Nav"
|
size: string = "default"
|
||||||
items: unknown[] = []
|
items: unknown[] = []
|
||||||
active: string = ""
|
active: string = ""
|
||||||
orientation: string = "horizontal"
|
orientation: string = "horizontal"
|
||||||
|
label: string = "Main"
|
||||||
|
collapsible: boolean = true
|
||||||
|
toggleLabel: string = "Menu"
|
||||||
class: string = ""
|
class: string = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state expanded = false
|
||||||
|
|
||||||
|
functions {
|
||||||
|
shared function itemList() {
|
||||||
|
return Array.isArray(items) ? items : []
|
||||||
|
}
|
||||||
|
|
||||||
|
shared function childrenOf(item) {
|
||||||
|
return item && Array.isArray(item.items) ? item.items : []
|
||||||
|
}
|
||||||
|
|
||||||
|
shared function isActive(item) {
|
||||||
|
return Boolean(item.value) && item.value === active
|
||||||
|
}
|
||||||
|
|
||||||
|
shared function rovingAxis() {
|
||||||
|
return orientation === "vertical" ? "vertical" : "horizontal"
|
||||||
|
}
|
||||||
|
|
||||||
|
client function choose(item) {
|
||||||
|
if (item.disabled) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
output.select({ item: item, value: item.value || "" })
|
||||||
|
}
|
||||||
|
|
||||||
|
client function toggleMenu() {
|
||||||
|
expanded = !expanded
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
view {
|
view {
|
||||||
<nav class="wire-next wire-next--color-{color} wire-next--size-{size} wire-next--nav wire-next--{orientation} {class}" aria-label="{label}">
|
<nav
|
||||||
{#each items as item}<a href="{item.href}" aria-current="{item.value === active ? 'page' : ''}">{item.label}</a>{/each}
|
{...attrs}
|
||||||
|
data-ui-component="Nav"
|
||||||
|
class='wire-nav {class}'
|
||||||
|
data-orientation='{orientation}'
|
||||||
|
data-color='{color}'
|
||||||
|
data-size='{size}'
|
||||||
|
data-expanded='{expanded}'
|
||||||
|
role="navigation"
|
||||||
|
aria-label='{label}'
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="wire-nav__toggle"
|
||||||
|
data-show="collapsible"
|
||||||
|
aria-expanded='{expanded}'
|
||||||
|
aria-label='{toggleLabel}'
|
||||||
|
@click='toggleMenu()'
|
||||||
|
>
|
||||||
|
<span class="wire-nav__toggle-bar" aria-hidden="true"></span>
|
||||||
|
<span class="wire-nav__toggle-text">{toggleLabel}</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<ul class="wire-nav__list" data-wrn-roving='{rovingAxis()}'>
|
||||||
|
{#each itemList() as item}
|
||||||
|
<li class="wire-nav__item" data-has-children='{childrenOf(item).length > 0}'>
|
||||||
|
<a
|
||||||
|
class="wire-nav__link"
|
||||||
|
href='{item.href || "#"}'
|
||||||
|
data-wrn-roving-item="true"
|
||||||
|
data-active='{isActive(item)}'
|
||||||
|
aria-current='{isActive(item) ? "page" : "false"}'
|
||||||
|
aria-disabled='{item.disabled ? "true" : "false"}'
|
||||||
|
@click='choose(item)'
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class='wire-nav__icon {item.icon}'
|
||||||
|
data-show="item.icon"
|
||||||
|
aria-hidden="true"
|
||||||
|
></span>
|
||||||
|
<span class="wire-nav__label">{item.label}</span>
|
||||||
|
<span class="wire-nav__badge" data-show="item.badge">{item.badge}</span>
|
||||||
|
<span
|
||||||
|
class="wire-nav__arrow"
|
||||||
|
data-show="childrenOf(item).length > 0"
|
||||||
|
aria-hidden="true"
|
||||||
|
>›</span>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<ul
|
||||||
|
class="wire-nav__submenu"
|
||||||
|
data-wrn-anchored="true"
|
||||||
|
data-show="childrenOf(item).length > 0"
|
||||||
|
>
|
||||||
|
{#each childrenOf(item) as child}
|
||||||
|
<li class="wire-nav__item" data-has-children='{childrenOf(child).length > 0}'>
|
||||||
|
<a
|
||||||
|
class="wire-nav__link"
|
||||||
|
href='{child.href || "#"}'
|
||||||
|
data-active='{isActive(child)}'
|
||||||
|
aria-current='{isActive(child) ? "page" : "false"}'
|
||||||
|
aria-disabled='{child.disabled ? "true" : "false"}'
|
||||||
|
@click='choose(child)'
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class='wire-nav__icon {child.icon}'
|
||||||
|
data-show="child.icon"
|
||||||
|
aria-hidden="true"
|
||||||
|
></span>
|
||||||
|
<span class="wire-nav__label">{child.label}</span>
|
||||||
|
<span class="wire-nav__badge" data-show="child.badge">{child.badge}</span>
|
||||||
|
<span
|
||||||
|
class="wire-nav__arrow"
|
||||||
|
data-show="childrenOf(child).length > 0"
|
||||||
|
aria-hidden="true"
|
||||||
|
>›</span>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<ul
|
||||||
|
class="wire-nav__submenu wire-nav__submenu--level3"
|
||||||
|
data-wrn-anchored="true"
|
||||||
|
data-show="childrenOf(child).length > 0"
|
||||||
|
>
|
||||||
|
{#each childrenOf(child) as leaf}
|
||||||
|
<li class="wire-nav__item">
|
||||||
|
<a
|
||||||
|
class="wire-nav__link"
|
||||||
|
href='{leaf.href || "#"}'
|
||||||
|
data-active='{isActive(leaf)}'
|
||||||
|
aria-current='{isActive(leaf) ? "page" : "false"}'
|
||||||
|
aria-disabled='{leaf.disabled ? "true" : "false"}'
|
||||||
|
@click='choose(leaf)'
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class='wire-nav__icon {leaf.icon}'
|
||||||
|
data-show="leaf.icon"
|
||||||
|
aria-hidden="true"
|
||||||
|
></span>
|
||||||
|
<span class="wire-nav__label">{leaf.label}</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{/each}
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
{/each}
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
{/each}
|
||||||
|
</ul>
|
||||||
|
|
||||||
<slot />
|
<slot />
|
||||||
</nav>
|
</nav>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
style {
|
||||||
|
.wire-nav {
|
||||||
|
--nav-accent: var(--wire-color-primary);
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-nav[data-color="secondary"] {
|
||||||
|
--nav-accent: var(--wire-color-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-nav[data-color="success"] {
|
||||||
|
--nav-accent: var(--wire-color-success);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-nav[data-color="danger"] {
|
||||||
|
--nav-accent: var(--wire-color-danger);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-nav[data-color="info"] {
|
||||||
|
--nav-accent: var(--wire-color-info);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-nav[data-size="sm"] {
|
||||||
|
font-size: 0.82rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-nav[data-size="lg"] {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-nav__list {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.25rem;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-nav[data-orientation="vertical"] .wire-nav__list {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-nav__item {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-nav__link {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.45rem;
|
||||||
|
padding: 0.45rem 0.7rem;
|
||||||
|
border-radius: var(--wire-radius-sm);
|
||||||
|
color: var(--wire-color-text-muted);
|
||||||
|
font-size: 0.9rem;
|
||||||
|
font-weight: 600;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-nav__link:hover {
|
||||||
|
background: var(--wire-color-surface-soft);
|
||||||
|
color: var(--wire-color-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-nav__link:focus-visible {
|
||||||
|
outline: 2px solid var(--nav-accent);
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-nav__link[data-active="true"] {
|
||||||
|
background: color-mix(in srgb, var(--nav-accent) 16%, transparent);
|
||||||
|
color: var(--nav-accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-nav__link[aria-disabled="true"] {
|
||||||
|
opacity: 0.5;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-nav__badge {
|
||||||
|
padding: 0.05rem 0.4rem;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: color-mix(in srgb, var(--nav-accent) 16%, transparent);
|
||||||
|
color: var(--nav-accent);
|
||||||
|
font-size: 0.72rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-nav__arrow {
|
||||||
|
display: inline-block;
|
||||||
|
transition: transform 160ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-nav__item:hover > .wire-nav__link > .wire-nav__arrow,
|
||||||
|
.wire-nav__item:focus-within > .wire-nav__link > .wire-nav__arrow {
|
||||||
|
transform: rotate(90deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-nav__submenu {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 30;
|
||||||
|
top: 100%;
|
||||||
|
left: 0;
|
||||||
|
min-width: 12rem;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0.35rem;
|
||||||
|
border: 1px solid var(--wire-color-border);
|
||||||
|
border-radius: var(--wire-radius-md);
|
||||||
|
background: var(--wire-color-surface);
|
||||||
|
box-shadow: var(--wire-shadow-1);
|
||||||
|
list-style: none;
|
||||||
|
opacity: 0;
|
||||||
|
visibility: hidden;
|
||||||
|
transition: opacity 160ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-nav__item:hover > .wire-nav__submenu,
|
||||||
|
.wire-nav__item:focus-within > .wire-nav__submenu {
|
||||||
|
opacity: 1;
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-nav__submenu--level3 {
|
||||||
|
top: 0;
|
||||||
|
left: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-nav__toggle {
|
||||||
|
display: none;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
padding: 0.45rem 0.7rem;
|
||||||
|
border: 1px solid var(--wire-color-border);
|
||||||
|
border-radius: var(--wire-radius-sm);
|
||||||
|
background: var(--wire-color-surface);
|
||||||
|
color: var(--wire-color-text);
|
||||||
|
font: inherit;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-nav__toggle-bar {
|
||||||
|
width: 1rem;
|
||||||
|
height: 2px;
|
||||||
|
background: currentColor;
|
||||||
|
box-shadow:
|
||||||
|
0 -5px 0 currentColor,
|
||||||
|
0 5px 0 currentColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* On a phone the bar becomes a disclosure: submenus stop being floating
|
||||||
|
* overlays and stack inline, because a hover-opened overlay is
|
||||||
|
* unreachable on touch.
|
||||||
|
*/
|
||||||
|
@media (max-width: 767px) {
|
||||||
|
.wire-nav__toggle {
|
||||||
|
display: inline-flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-nav__list {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-nav[data-expanded="false"] .wire-nav__list {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-nav__submenu,
|
||||||
|
.wire-nav__submenu--level3 {
|
||||||
|
position: static;
|
||||||
|
opacity: 1;
|
||||||
|
visibility: visible;
|
||||||
|
border: 0;
|
||||||
|
box-shadow: none;
|
||||||
|
padding-left: 1rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,11 +86,11 @@ size: string = "default"
|
|||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div class="wire-navbar__collapse {mobileOpen ? 'is-open' : ''}">
|
<div class="wire-navbar__collapse {mobileOpen ? 'is-open' : ''}">
|
||||||
<nav class="wire-navbar__menus" aria-label="{label}">
|
<nav class="wire-navbar__menus" aria-label="{label}" data-wrn-roving="horizontal">
|
||||||
{#each items as item}
|
{#each items as item}
|
||||||
{#if item.children && item.children.length}
|
{#if item.children && item.children.length}
|
||||||
<details class="wire-navbar__dropdown wire-navbar__dropdown--{item.type || 'dropdown'}" name="wire-navbar-menu" @toggle="toggleDropdown(event, item)">
|
<details class="wire-navbar__dropdown wire-navbar__dropdown--{item.type || 'dropdown'}" name="wire-navbar-menu" @toggle="toggleDropdown(event, item)">
|
||||||
<summary aria-current="{isItemActive(item) ? 'page' : ''}">
|
<summary data-wrn-roving-item="true" aria-current="{isItemActive(item) ? 'page' : 'false'}">
|
||||||
{#if item.icon}<span class="{item.icon}" aria-hidden="true"></span>{/if}
|
{#if item.icon}<span class="{item.icon}" aria-hidden="true"></span>{/if}
|
||||||
<span>{item.label}</span>
|
<span>{item.label}</span>
|
||||||
<span class="wire-navbar__chevron" aria-hidden="true"></span>
|
<span class="wire-navbar__chevron" aria-hidden="true"></span>
|
||||||
@@ -103,13 +103,13 @@ size: string = "default"
|
|||||||
{#if child.label}<strong class="wire-navbar__group-title">{child.label}</strong>{/if}
|
{#if child.label}<strong class="wire-navbar__group-title">{child.label}</strong>{/if}
|
||||||
{#if child.description}<small>{child.description}</small>{/if}
|
{#if child.description}<small>{child.description}</small>{/if}
|
||||||
{#each child.children as nested}
|
{#each child.children as nested}
|
||||||
<a href="{nested.href || '#'}" target="{nested.target || ''}" rel="{nested.rel || ''}" aria-current="{nested.value === active ? 'page' : ''}" @click="selectItem(nested, 3)">
|
<a href="{nested.href || '#'}" target="{nested.target || ''}" rel="{nested.rel || ''}" aria-current="{nested.value === active ? 'page' : 'false'}" @click="selectItem(nested, 3)">
|
||||||
{#if nested.icon}<span class="{nested.icon}" aria-hidden="true"></span>{/if}
|
{#if nested.icon}<span class="{nested.icon}" aria-hidden="true"></span>{/if}
|
||||||
<span><strong>{nested.label}</strong>{#if nested.description}<small>{nested.description}</small>{/if}</span>
|
<span><strong>{nested.label}</strong>{#if nested.description}<small>{nested.description}</small>{/if}</span>
|
||||||
</a>
|
</a>
|
||||||
{/each}
|
{/each}
|
||||||
{:else}
|
{:else}
|
||||||
<a href="{child.href || '#'}" target="{child.target || ''}" rel="{child.rel || ''}" aria-current="{child.value === active ? 'page' : ''}" @click="selectItem(child, 2)">
|
<a href="{child.href || '#'}" target="{child.target || ''}" rel="{child.rel || ''}" aria-current="{child.value === active ? 'page' : 'false'}" @click="selectItem(child, 2)">
|
||||||
{#if child.icon}<span class="{child.icon}" aria-hidden="true"></span>{/if}
|
{#if child.icon}<span class="{child.icon}" aria-hidden="true"></span>{/if}
|
||||||
<span><strong>{child.label}</strong>{#if child.description}<small>{child.description}</small>{/if}</span>
|
<span><strong>{child.label}</strong>{#if child.description}<small>{child.description}</small>{/if}</span>
|
||||||
</a>
|
</a>
|
||||||
@@ -119,7 +119,7 @@ size: string = "default"
|
|||||||
</div>
|
</div>
|
||||||
</details>
|
</details>
|
||||||
{:else}
|
{:else}
|
||||||
<a class="wire-navbar__menu-link" href="{item.href || '#'}" target="{item.target || ''}" rel="{item.rel || ''}" aria-current="{item.value === active ? 'page' : ''}" @click="selectItem(item, 1)">
|
<a class="wire-navbar__menu-link" data-wrn-roving-item="true" href="{item.href || '#'}" target="{item.target || ''}" rel="{item.rel || ''}" aria-current="{item.value === active ? 'page' : 'false'}" @click="selectItem(item, 1)">
|
||||||
{#if item.icon}<span class="{item.icon}" aria-hidden="true"></span>{/if}
|
{#if item.icon}<span class="{item.icon}" aria-hidden="true"></span>{/if}
|
||||||
<span>{item.label}</span>
|
<span>{item.label}</span>
|
||||||
</a>
|
</a>
|
||||||
@@ -140,4 +140,440 @@ size: string = "default"
|
|||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
style {
|
||||||
|
/* Full application navigation */
|
||||||
|
.wire-navbar {
|
||||||
|
position: relative;
|
||||||
|
z-index: 40;
|
||||||
|
width: 100%;
|
||||||
|
color: var(--wire-color-text);
|
||||||
|
background: color-mix(in srgb, var(--wire-color-surface) 96%, transparent);
|
||||||
|
border-bottom: 1px solid var(--wire-color-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-navbar--sticky {
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
backdrop-filter: blur(16px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-navbar__topbar:empty,
|
||||||
|
.wire-navbar__topbar:not(:has(*)) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-navbar__topbar:not(:empty) {
|
||||||
|
display: flex;
|
||||||
|
min-height: 2.25rem;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 1rem;
|
||||||
|
padding: 0.35rem clamp(1rem, 4vw, 3rem);
|
||||||
|
color: var(--wire-color-muted);
|
||||||
|
background: var(--wire-color-surface-2);
|
||||||
|
border-bottom: 1px solid var(--wire-color-border);
|
||||||
|
font-size: 0.75rem;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-navbar__main {
|
||||||
|
display: flex;
|
||||||
|
min-height: 4.25rem;
|
||||||
|
width: min(100%, 90rem);
|
||||||
|
margin-inline: auto;
|
||||||
|
padding: 0.75rem clamp(1rem, 4vw, 3rem);
|
||||||
|
align-items: center;
|
||||||
|
gap: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-navbar--width-full .wire-navbar__main {
|
||||||
|
width: 100%;
|
||||||
|
max-width: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-navbar--width-compact .wire-navbar__main {
|
||||||
|
width: min(86%, 80rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-navbar__brand,
|
||||||
|
.wire-navbar__menu-link,
|
||||||
|
.wire-navbar__dropdown summary,
|
||||||
|
.wire-navbar__action,
|
||||||
|
.wire-navbar__panel a {
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-navbar__brand {
|
||||||
|
display: inline-flex;
|
||||||
|
min-width: 0;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.75rem;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-navbar__brand-logo {
|
||||||
|
display: block;
|
||||||
|
width: auto;
|
||||||
|
max-width: 11rem;
|
||||||
|
height: 2.5rem;
|
||||||
|
object-fit: contain;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-navbar__brand-icon {
|
||||||
|
width: 2.5rem;
|
||||||
|
height: 2.5rem;
|
||||||
|
color: var(--wire-component-color, var(--wire-color-primary));
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-navbar__brand-copy {
|
||||||
|
display: grid;
|
||||||
|
min-width: 0;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-navbar__brand-copy strong {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-navbar__brand-copy small {
|
||||||
|
margin-top: 0.2rem;
|
||||||
|
color: var(--wire-color-muted);
|
||||||
|
font-size: 0.6875rem;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-navbar__collapse,
|
||||||
|
.wire-navbar__menus,
|
||||||
|
.wire-navbar__actions {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-navbar__collapse {
|
||||||
|
min-width: 0;
|
||||||
|
flex: 1;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-navbar__menus {
|
||||||
|
justify-content: center;
|
||||||
|
flex: 1;
|
||||||
|
gap: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-navbar__actions {
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-navbar__menu-link,
|
||||||
|
.wire-navbar__dropdown > summary,
|
||||||
|
.wire-navbar__action {
|
||||||
|
display: inline-flex;
|
||||||
|
min-height: 2.75rem;
|
||||||
|
padding: 0.65rem 0.8rem;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.45rem;
|
||||||
|
border-radius: 0.65rem;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 0.8125rem;
|
||||||
|
font-weight: 500;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-navbar__menu-link:hover,
|
||||||
|
.wire-navbar__dropdown > summary:hover {
|
||||||
|
color: var(--wire-color-text);
|
||||||
|
background: var(--wire-color-surface-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-navbar__menu-link[aria-current="page"],
|
||||||
|
.wire-navbar__dropdown > summary[aria-current="page"] {
|
||||||
|
color: var(--wire-component-color, var(--wire-color-primary));
|
||||||
|
font-weight: 600;
|
||||||
|
background: color-mix(
|
||||||
|
in srgb,
|
||||||
|
var(--wire-component-color, var(--wire-color-primary)) 12%,
|
||||||
|
transparent
|
||||||
|
);
|
||||||
|
box-shadow: inset 0 -2px 0 var(--wire-component-color, var(--wire-color-primary));
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-navbar__menu-link[aria-current="page"]:hover,
|
||||||
|
.wire-navbar__dropdown > summary[aria-current="page"]:hover {
|
||||||
|
color: var(--wire-component-color, var(--wire-color-primary));
|
||||||
|
background: color-mix(
|
||||||
|
in srgb,
|
||||||
|
var(--wire-component-color, var(--wire-color-primary)) 16%,
|
||||||
|
transparent
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-navbar__dropdown {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-navbar__dropdown > summary {
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-navbar__dropdown > summary::-webkit-details-marker {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-navbar__chevron {
|
||||||
|
width: 0.45rem;
|
||||||
|
height: 0.45rem;
|
||||||
|
border-right: 1.5px solid currentColor;
|
||||||
|
border-bottom: 1.5px solid currentColor;
|
||||||
|
transform: rotate(45deg) translateY(-0.15rem);
|
||||||
|
transition: transform var(--wire-motion-fast, 150ms) ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-navbar__dropdown[open] .wire-navbar__chevron {
|
||||||
|
transform: rotate(225deg) translate(-0.1rem, -0.1rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-navbar__panel {
|
||||||
|
position: absolute;
|
||||||
|
top: calc(100% + 0.55rem);
|
||||||
|
left: 50%;
|
||||||
|
display: grid;
|
||||||
|
width: max-content;
|
||||||
|
min-width: 15rem;
|
||||||
|
max-width: min(90vw, 64rem);
|
||||||
|
padding: 0.65rem;
|
||||||
|
gap: 0.45rem;
|
||||||
|
border: 1px solid var(--wire-color-border);
|
||||||
|
border-radius: 0.9rem;
|
||||||
|
color: var(--wire-color-text);
|
||||||
|
background: var(--wire-color-surface);
|
||||||
|
box-shadow: 0 18px 48px rgb(15 23 42 / 0.16);
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateX(-50%) translateY(0) scale(1);
|
||||||
|
transform-origin: top center;
|
||||||
|
transition:
|
||||||
|
opacity 180ms ease,
|
||||||
|
transform 180ms cubic-bezier(0.22, 1, 0.36, 1),
|
||||||
|
display 180ms allow-discrete;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-navbar__panel::before {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
bottom: 100%;
|
||||||
|
left: 0;
|
||||||
|
height: 0.65rem;
|
||||||
|
content: "";
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-navbar__dropdown:not([open]) > .wire-navbar__panel {
|
||||||
|
display: none;
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateX(-50%) translateY(-0.5rem) scale(0.98);
|
||||||
|
}
|
||||||
|
|
||||||
|
@starting-style {
|
||||||
|
.wire-navbar__dropdown[open] > .wire-navbar__panel {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateX(-50%) translateY(-0.5rem) scale(0.98);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-navbar__dropdown--mega {
|
||||||
|
position: static;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-navbar__dropdown--mega .wire-navbar__panel {
|
||||||
|
right: auto;
|
||||||
|
left: 50%;
|
||||||
|
width: min(calc(100vw - 2rem), 64rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-navbar__panel--columns-2 {
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-navbar__panel--columns-3 {
|
||||||
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-navbar__panel--columns-4 {
|
||||||
|
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-navbar__panel-intro {
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0.5rem 0.65rem;
|
||||||
|
color: var(--wire-color-muted);
|
||||||
|
font-size: 0.8125rem;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-navbar__group {
|
||||||
|
display: grid;
|
||||||
|
align-content: start;
|
||||||
|
gap: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-navbar__group-title {
|
||||||
|
padding: 0.55rem 0.65rem 0.25rem;
|
||||||
|
font-size: 0.7rem;
|
||||||
|
font-weight: 600;
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-navbar__group > small {
|
||||||
|
padding: 0 0.65rem 0.4rem;
|
||||||
|
color: var(--wire-color-muted);
|
||||||
|
font-size: 0.7rem;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-navbar__panel a {
|
||||||
|
display: flex;
|
||||||
|
min-height: 2.75rem;
|
||||||
|
padding: 0.65rem;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 0.65rem;
|
||||||
|
border-radius: 0.6rem;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
font-weight: 450;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-navbar__panel a:hover {
|
||||||
|
background: var(--wire-color-surface-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-navbar__panel a span:last-child {
|
||||||
|
display: grid;
|
||||||
|
gap: 0.15rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-navbar__panel a strong {
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-navbar__panel a small {
|
||||||
|
color: var(--wire-color-muted);
|
||||||
|
font-size: 0.7rem;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-navbar__action {
|
||||||
|
border: 1px solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-navbar__action--primary {
|
||||||
|
color: var(--wire-color-on-primary, #fff);
|
||||||
|
background: var(--wire-component-color, var(--wire-color-primary));
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-navbar__action--outline {
|
||||||
|
border-color: var(--wire-color-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-navbar__toggle {
|
||||||
|
display: none;
|
||||||
|
width: 2.75rem;
|
||||||
|
height: 2.75rem;
|
||||||
|
margin-left: auto;
|
||||||
|
padding: 0.65rem;
|
||||||
|
border: 1px solid var(--wire-color-border);
|
||||||
|
border-radius: 0.65rem;
|
||||||
|
color: inherit;
|
||||||
|
background: var(--wire-color-surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-navbar__toggle span {
|
||||||
|
display: block;
|
||||||
|
height: 2px;
|
||||||
|
margin: 0.25rem 0;
|
||||||
|
background: currentColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 900px) {
|
||||||
|
.wire-navbar--width-compact .wire-navbar__main {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.wire-navbar__toggle {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.wire-navbar__collapse {
|
||||||
|
position: absolute;
|
||||||
|
top: 100%;
|
||||||
|
right: 0;
|
||||||
|
left: 0;
|
||||||
|
display: none;
|
||||||
|
padding: 0.75rem 1rem 1rem;
|
||||||
|
align-items: stretch;
|
||||||
|
flex-direction: column;
|
||||||
|
background: var(--wire-color-surface);
|
||||||
|
border-bottom: 1px solid var(--wire-color-border);
|
||||||
|
box-shadow: 0 16px 32px rgb(15 23 42 / 0.12);
|
||||||
|
max-height: calc(100dvh - 4rem);
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: auto;
|
||||||
|
overscroll-behavior: contain;
|
||||||
|
}
|
||||||
|
.wire-navbar__collapse.is-open {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
.wire-navbar__menus,
|
||||||
|
.wire-navbar__actions {
|
||||||
|
width: 100%;
|
||||||
|
align-items: stretch;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
.wire-navbar__menu-link,
|
||||||
|
.wire-navbar__dropdown > summary,
|
||||||
|
.wire-navbar__action {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.wire-navbar__panel,
|
||||||
|
.wire-navbar__dropdown--mega .wire-navbar__panel {
|
||||||
|
position: static;
|
||||||
|
width: 100%;
|
||||||
|
max-width: none;
|
||||||
|
margin-top: 0.25rem;
|
||||||
|
box-shadow: none;
|
||||||
|
transform: none;
|
||||||
|
overflow: hidden;
|
||||||
|
animation: wire-navbar-mobile-panel 180ms ease both;
|
||||||
|
}
|
||||||
|
.wire-navbar__dropdown:not([open]) > .wire-navbar__panel,
|
||||||
|
.wire-navbar__dropdown[open] > .wire-navbar__panel {
|
||||||
|
transform: none;
|
||||||
|
}
|
||||||
|
.wire-navbar__panel[class*="wire-navbar__panel--columns-"] {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
.wire-navbar__panel::before {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
.wire-navbar__brand-copy small {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes wire-navbar-mobile-panel {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-0.35rem);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +1,291 @@
|
|||||||
|
// Pagination -- page controls over a known total.
|
||||||
|
//
|
||||||
|
// <Pagination page={2} pageSize={10} total={137} variant="numbered" />
|
||||||
|
//
|
||||||
|
// The component owns no data. It reports the requested page through its
|
||||||
|
// change output and lets the caller fetch or slice.
|
||||||
|
//
|
||||||
|
// NOTE: the style block uses /* */ comments only -- // is not a CSS comment
|
||||||
|
// and silently swallows the rule that follows it.
|
||||||
component Pagination {
|
component Pagination {
|
||||||
outputs {
|
outputs {
|
||||||
change(payload: { value?: string | number | boolean | null; values?: Array<string | number | boolean | null | object>; sourceEvent?: Event; [key: string]: string | number | boolean | null | object } | string | number | boolean | null)
|
change(payload: { page: number; pageSize: number })
|
||||||
previous(payload: { sourceEvent?: Event; [key: string]: string | number | boolean | null | object })
|
previous(payload: { page: number })
|
||||||
next(payload: { sourceEvent?: Event; [key: string]: string | number | boolean | null | object })
|
next(payload: { page: number })
|
||||||
}
|
}
|
||||||
|
|
||||||
props {
|
props {
|
||||||
size: string = "default"
|
|
||||||
color: string = "primary"
|
color: string = "primary"
|
||||||
|
size: string = "default"
|
||||||
|
page: number = 1
|
||||||
|
pageSize: number = 10
|
||||||
|
total: number = 0
|
||||||
|
variant: string = "compact"
|
||||||
|
siblingCount: number = 1
|
||||||
|
showSummary: boolean = true
|
||||||
label: string = "Pagination"
|
label: string = "Pagination"
|
||||||
items: unknown[] = []
|
previousLabel: string = "Previous"
|
||||||
active: string = ""
|
nextLabel: string = "Next"
|
||||||
orientation: string = "horizontal"
|
|
||||||
class: string = ""
|
class: string = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
functions {
|
||||||
|
shared function lastPage() {
|
||||||
|
var size = Number(pageSize) > 0 ? Number(pageSize) : 10
|
||||||
|
var count = Number(total) > 0 ? Number(total) : 0
|
||||||
|
return Math.max(1, Math.ceil(count / size))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Out-of-range values arrive routinely: page travels as an HTML attribute
|
||||||
|
// and callers compute it from data that may have shrunk underneath them.
|
||||||
|
shared function currentPage() {
|
||||||
|
var value = Number(page)
|
||||||
|
if (!value || value < 1) {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return Math.min(value, lastPage())
|
||||||
|
}
|
||||||
|
|
||||||
|
shared function firstShown() {
|
||||||
|
if (Number(total) < 1) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return (currentPage() - 1) * (Number(pageSize) || 10) + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
shared function lastShown() {
|
||||||
|
return Math.min(currentPage() * (Number(pageSize) || 10), Number(total) || 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
shared function pageNumbers() {
|
||||||
|
var last = lastPage()
|
||||||
|
var current = currentPage()
|
||||||
|
var siblings = Math.max(0, Number(siblingCount) || 0)
|
||||||
|
var start = Math.max(1, current - siblings)
|
||||||
|
var end = Math.min(last, current + siblings)
|
||||||
|
var pages = []
|
||||||
|
if (start > 1) {
|
||||||
|
pages.push({ value: 1, label: "1", gap: false })
|
||||||
|
if (start > 2) {
|
||||||
|
pages.push({ value: 0, label: "...", gap: true })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (var index = start; index <= end; index += 1) {
|
||||||
|
pages.push({ value: index, label: String(index), gap: false })
|
||||||
|
}
|
||||||
|
if (end < last) {
|
||||||
|
if (end < last - 1) {
|
||||||
|
pages.push({ value: 0, label: "...", gap: true })
|
||||||
|
}
|
||||||
|
pages.push({ value: last, label: String(last), gap: false })
|
||||||
|
}
|
||||||
|
return pages
|
||||||
|
}
|
||||||
|
|
||||||
|
client function goToPage(target) {
|
||||||
|
var next = Math.min(Math.max(1, Number(target) || 1), lastPage())
|
||||||
|
output.change({ page: next, pageSize: Number(pageSize) || 10 })
|
||||||
|
}
|
||||||
|
|
||||||
|
client function goPrevious() {
|
||||||
|
var target = Math.max(1, currentPage() - 1)
|
||||||
|
output.previous({ page: target })
|
||||||
|
output.change({ page: target, pageSize: Number(pageSize) || 10 })
|
||||||
|
}
|
||||||
|
|
||||||
|
client function goNext() {
|
||||||
|
var target = Math.min(lastPage(), currentPage() + 1)
|
||||||
|
output.next({ page: target })
|
||||||
|
output.change({ page: target, pageSize: Number(pageSize) || 10 })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
view {
|
view {
|
||||||
<nav class="wire-next wire-next--color-{color} wire-next--size-{size} wire-next--pagination wire-next--{orientation} {class}" aria-label="{label}">
|
<nav
|
||||||
{#each items as item}<a href="{item.href}" aria-current="{item.value === active ? 'page' : ''}">{item.label}</a>{/each}
|
{...attrs}
|
||||||
|
data-ui-component="Pagination"
|
||||||
|
class='wire-pagination {class}'
|
||||||
|
data-variant='{variant}'
|
||||||
|
data-color='{color}'
|
||||||
|
data-size='{size}'
|
||||||
|
role="navigation"
|
||||||
|
aria-label='{label}'
|
||||||
|
>
|
||||||
|
<p class="wire-pagination__summary" data-show="showSummary">
|
||||||
|
{firstShown()} to {lastShown()} of {total}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="wire-pagination__controls">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="wire-pagination__step"
|
||||||
|
aria-label='{previousLabel}'
|
||||||
|
@click='goPrevious()'
|
||||||
|
>
|
||||||
|
<span class="wire-pagination__step-icon" aria-hidden="true">‹</span>
|
||||||
|
<span class="wire-pagination__step-label">{previousLabel}</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<ol class="wire-pagination__pages" data-show="variant === 'numbered'">
|
||||||
|
{#each pageNumbers() as entry}
|
||||||
|
<li class="wire-pagination__slot">
|
||||||
|
<span class="wire-pagination__gap" data-show="entry.gap">{entry.label}</span>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="wire-pagination__page"
|
||||||
|
data-show="!entry.gap"
|
||||||
|
data-active='{entry.value === currentPage()}'
|
||||||
|
aria-current='{entry.value === currentPage() ? "page" : "false"}'
|
||||||
|
@click='goToPage(entry.value)'
|
||||||
|
>
|
||||||
|
{entry.label}
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
{/each}
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<p class="wire-pagination__compact" data-show="variant !== 'numbered'">
|
||||||
|
{currentPage()} / {lastPage()}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="wire-pagination__step"
|
||||||
|
aria-label='{nextLabel}'
|
||||||
|
@click='goNext()'
|
||||||
|
>
|
||||||
|
<span class="wire-pagination__step-label">{nextLabel}</span>
|
||||||
|
<span class="wire-pagination__step-icon" aria-hidden="true">›</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<slot />
|
<slot />
|
||||||
</nav>
|
</nav>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
style {
|
||||||
|
.wire-pagination {
|
||||||
|
--pagination-accent: var(--wire-color-primary);
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 0.75rem;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-pagination[data-color="secondary"] {
|
||||||
|
--pagination-accent: var(--wire-color-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-pagination[data-color="success"] {
|
||||||
|
--pagination-accent: var(--wire-color-success);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-pagination[data-color="danger"] {
|
||||||
|
--pagination-accent: var(--wire-color-danger);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-pagination[data-color="info"] {
|
||||||
|
--pagination-accent: var(--wire-color-info);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-pagination[data-size="sm"] {
|
||||||
|
font-size: 0.82rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-pagination[data-size="lg"] {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-pagination__summary {
|
||||||
|
margin: 0;
|
||||||
|
color: var(--wire-color-text-muted);
|
||||||
|
font-size: 0.82rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-pagination__controls {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.35rem;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-pagination__pages {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.25rem;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-pagination__slot {
|
||||||
|
display: inline-flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-pagination__page,
|
||||||
|
.wire-pagination__step {
|
||||||
|
appearance: none;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.35rem;
|
||||||
|
min-width: 2.25rem;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 0.4rem 0.6rem;
|
||||||
|
border: 1px solid var(--wire-color-border);
|
||||||
|
border-radius: var(--wire-radius-sm);
|
||||||
|
background: var(--wire-color-surface);
|
||||||
|
color: var(--wire-color-text);
|
||||||
|
font: inherit;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-pagination__page:hover,
|
||||||
|
.wire-pagination__step:hover {
|
||||||
|
background: var(--wire-color-surface-soft);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-pagination__page:focus-visible,
|
||||||
|
.wire-pagination__step:focus-visible {
|
||||||
|
outline: 2px solid var(--pagination-accent);
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-pagination__page[data-active="true"] {
|
||||||
|
border-color: var(--pagination-accent);
|
||||||
|
background: var(--pagination-accent);
|
||||||
|
color: var(--wire-color-primary-contrast);
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-pagination__gap {
|
||||||
|
padding: 0 0.35rem;
|
||||||
|
color: var(--wire-color-text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-pagination__compact {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 0.5rem;
|
||||||
|
color: var(--wire-color-text-muted);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Below the small breakpoint the word labels crowd the arrows out. */
|
||||||
|
@media (max-width: 639px) {
|
||||||
|
.wire-pagination {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-pagination__step-label {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-pagination__summary {
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,172 @@
|
|||||||
|
// Scrollspy -- a table of contents that follows the reader.
|
||||||
|
//
|
||||||
|
// <Scrollspy items='[{"label":"Overview","href":"#overview"}]' />
|
||||||
|
//
|
||||||
|
// Each href points at an element on the page. The runtime observes those
|
||||||
|
// elements and moves aria-current to the link for whichever one is in view.
|
||||||
|
//
|
||||||
|
// The runtime writes the marker straight onto the links rather than into
|
||||||
|
// component state. An IntersectionObserver callback fires long after the
|
||||||
|
// client function that registered it has returned, and a state write made
|
||||||
|
// there is dropped -- so the DOM is the only place the answer can live.
|
||||||
|
//
|
||||||
|
// NOTE: the style block uses /* */ comments only -- // is not a CSS comment
|
||||||
|
// and silently swallows the rule that follows it.
|
||||||
component Scrollspy {
|
component Scrollspy {
|
||||||
outputs {
|
outputs {
|
||||||
change(payload: { value?: string | number | boolean | null; values?: Array<string | number | boolean | null | object>; sourceEvent?: Event; [key: string]: string | number | boolean | null | object } | string | number | boolean | null)
|
change(payload: { href: string; label: string })
|
||||||
}
|
}
|
||||||
|
|
||||||
props {
|
props {
|
||||||
size: string = "default"
|
|
||||||
color: string = "primary"
|
color: string = "primary"
|
||||||
label: string = "Scrollspy"
|
size: string = "default"
|
||||||
items: unknown[] = []
|
items: unknown[] = []
|
||||||
active: string = ""
|
active: string = ""
|
||||||
orientation: string = "horizontal"
|
label: string = "On this page"
|
||||||
|
heading: string = ""
|
||||||
class: string = ""
|
class: string = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
functions {
|
||||||
|
shared function itemList() {
|
||||||
|
return Array.isArray(items) ? items : []
|
||||||
|
}
|
||||||
|
|
||||||
|
shared function isActive(item) {
|
||||||
|
return Boolean(item.href) && item.href === active
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
view {
|
view {
|
||||||
<nav class="wire-next wire-next--color-{color} wire-next--size-{size} wire-next--scrollspy wire-next--{orientation} {class}" aria-label="{label}">
|
<nav
|
||||||
{#each items as item}<a href="{item.href}" aria-current="{item.value === active ? 'page' : ''}">{item.label}</a>{/each}
|
{...attrs}
|
||||||
|
data-ui-component="Scrollspy"
|
||||||
|
class='wire-scrollspy {class}'
|
||||||
|
data-color='{color}'
|
||||||
|
data-size='{size}'
|
||||||
|
data-wrn-scrollspy="true"
|
||||||
|
role="navigation"
|
||||||
|
aria-label='{label}'
|
||||||
|
>
|
||||||
|
<p class="wire-scrollspy__heading" data-show="heading">{heading}</p>
|
||||||
|
|
||||||
|
<ul class="wire-scrollspy__list">
|
||||||
|
{#each itemList() as item}
|
||||||
|
<li class="wire-scrollspy__item">
|
||||||
|
<a
|
||||||
|
class="wire-scrollspy__link"
|
||||||
|
href='{item.href || "#"}'
|
||||||
|
data-active='{isActive(item)}'
|
||||||
|
aria-current='{isActive(item) ? "location" : "false"}'
|
||||||
|
>
|
||||||
|
<span class="wire-scrollspy__label">{item.label}</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{/each}
|
||||||
|
</ul>
|
||||||
|
|
||||||
<slot />
|
<slot />
|
||||||
</nav>
|
</nav>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
style {
|
||||||
|
.wire-scrollspy {
|
||||||
|
--scrollspy-accent: var(--wire-color-primary);
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-scrollspy[data-color="secondary"] {
|
||||||
|
--scrollspy-accent: var(--wire-color-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-scrollspy[data-color="success"] {
|
||||||
|
--scrollspy-accent: var(--wire-color-success);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-scrollspy[data-color="danger"] {
|
||||||
|
--scrollspy-accent: var(--wire-color-danger);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-scrollspy[data-color="info"] {
|
||||||
|
--scrollspy-accent: var(--wire-color-info);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-scrollspy[data-size="sm"] {
|
||||||
|
font-size: 0.82rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-scrollspy[data-size="lg"] {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-scrollspy__heading {
|
||||||
|
margin: 0 0 0.5rem;
|
||||||
|
color: var(--wire-color-text-muted);
|
||||||
|
font-size: 0.72rem;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 0.08em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-scrollspy__list {
|
||||||
|
display: grid;
|
||||||
|
gap: 0.1rem;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
list-style: none;
|
||||||
|
border-left: 1px solid var(--wire-color-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-scrollspy__link {
|
||||||
|
display: block;
|
||||||
|
padding: 0.3rem 0.75rem;
|
||||||
|
margin-left: -1px;
|
||||||
|
border-left: 2px solid transparent;
|
||||||
|
color: var(--wire-color-text-muted);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-scrollspy__link:hover {
|
||||||
|
color: var(--wire-color-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-scrollspy__link:focus-visible {
|
||||||
|
outline: 2px solid var(--scrollspy-accent);
|
||||||
|
outline-offset: -2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-scrollspy__link[data-active="true"] {
|
||||||
|
border-left-color: var(--scrollspy-accent);
|
||||||
|
color: var(--scrollspy-accent);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A table of contents is a sidebar affordance. On a phone it stops being
|
||||||
|
* a rail and becomes a horizontal strip that scrolls, so it costs one
|
||||||
|
* line rather than a screenful.
|
||||||
|
*/
|
||||||
|
@media (max-width: 767px) {
|
||||||
|
.wire-scrollspy__list {
|
||||||
|
grid-auto-flow: column;
|
||||||
|
grid-auto-columns: max-content;
|
||||||
|
overflow-x: auto;
|
||||||
|
border-left: 0;
|
||||||
|
border-bottom: 1px solid var(--wire-color-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-scrollspy__link {
|
||||||
|
margin-left: 0;
|
||||||
|
border-left: 0;
|
||||||
|
border-bottom: 2px solid transparent;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-scrollspy__link[data-active="true"] {
|
||||||
|
border-left-color: transparent;
|
||||||
|
border-bottom-color: var(--scrollspy-accent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,9 @@
|
|||||||
component SearchBox {
|
component SearchBox {
|
||||||
|
outputs {
|
||||||
|
search(payload: { sourceEvent?: Event; [key: string]: string | number | boolean | null | object })
|
||||||
|
clear(payload: { sourceEvent?: Event; [key: string]: string | number | boolean | null | object })
|
||||||
|
}
|
||||||
|
|
||||||
props {
|
props {
|
||||||
size: string = "default"
|
size: string = "default"
|
||||||
color: string = "primary"
|
color: string = "primary"
|
||||||
@@ -22,7 +27,7 @@ component SearchBox {
|
|||||||
data-ui-component="SearchBox"
|
data-ui-component="SearchBox"
|
||||||
role="search"
|
role="search"
|
||||||
class='w-full {class}'
|
class='w-full {class}'
|
||||||
@submit='event.preventDefault(); event.currentTarget.dispatchEvent(new CustomEvent("search", { bubbles: true, detail: { value: query, name: name } }))'
|
@submit='event.preventDefault(); output.search({ value: query, name: name })'
|
||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
class="mb-2 block text-sm font-semibold text-[var(--wire-color-text)]"
|
class="mb-2 block text-sm font-semibold text-[var(--wire-color-text)]"
|
||||||
@@ -61,7 +66,7 @@ component SearchBox {
|
|||||||
aria-label="Clear search"
|
aria-label="Clear search"
|
||||||
data-show='query.length > 0 && !disabled'
|
data-show='query.length > 0 && !disabled'
|
||||||
class="absolute right-12 inline-flex size-8 items-center justify-center rounded-lg text-[var(--wire-color-text-muted)] transition hover:bg-[var(--wire-color-surface-soft)] hover:text-[var(--wire-color-text)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--wire-color-focus)]"
|
class="absolute right-12 inline-flex size-8 items-center justify-center rounded-lg text-[var(--wire-color-text-muted)] transition hover:bg-[var(--wire-color-surface-soft)] hover:text-[var(--wire-color-text)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--wire-color-focus)]"
|
||||||
@click='query = ""; event.currentTarget.parentElement.querySelector("input")?.focus(); event.currentTarget.dispatchEvent(new CustomEvent("clear", { bubbles: true, detail: { value: "", name: name } }))'
|
@click='query = ""; event.currentTarget.parentElement.querySelector("input")?.focus(); output.clear({ value: "", name: name })'
|
||||||
>
|
>
|
||||||
<span class="icon-[lucide--x] size-4" aria-hidden="true"></span>
|
<span class="icon-[lucide--x] size-4" aria-hidden="true"></span>
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -1,82 +1,335 @@
|
|||||||
|
// Sidebar -- a vertical navigation rail that becomes a drawer on small screens.
|
||||||
|
//
|
||||||
|
// <Sidebar items='[{"label":"Dashboard","href":"/","value":"dash"}]' active="dash" />
|
||||||
|
//
|
||||||
|
// An entry is one of three shapes:
|
||||||
|
// { label, href, value } a single link
|
||||||
|
// { heading, items: [...] } a labelled group
|
||||||
|
// { label, items: [...] } a collapsible branch, nested to 3 levels
|
||||||
|
//
|
||||||
|
// The off-canvas presentation is Drawer rather than a second implementation,
|
||||||
|
// so the focus trap and the body scroll lock come from one place.
|
||||||
|
//
|
||||||
|
// NOTE: the style block uses /* */ comments only -- // is not a CSS comment
|
||||||
|
// and silently swallows the rule that follows it.
|
||||||
|
import Drawer from "./Drawer.wrn"
|
||||||
|
|
||||||
component Sidebar {
|
component Sidebar {
|
||||||
outputs {
|
outputs {
|
||||||
toggle(payload: { open: boolean })
|
toggle(payload: { open: boolean })
|
||||||
open(payload: { sourceEvent?: Event; [key: string]: string | number | boolean | null | object })
|
open(payload: { sourceEvent: Event })
|
||||||
close(payload: { source: string })
|
close(payload: { source: string })
|
||||||
select(payload: { item: string | number | boolean | null | object; value: string | number | boolean; level: string })
|
select(payload: { item: object; value: string; level: number })
|
||||||
}
|
}
|
||||||
|
|
||||||
props {
|
props {
|
||||||
size: string = "default"
|
|
||||||
color: string = "primary"
|
color: string = "primary"
|
||||||
|
size: string = "default"
|
||||||
label: string = "Sidebar"
|
label: string = "Sidebar"
|
||||||
items: unknown[] = []
|
items: unknown[] = []
|
||||||
active: string = ""
|
active: string = ""
|
||||||
orientation: string = "horizontal"
|
|
||||||
mobileLabel: string = "Open navigation"
|
mobileLabel: string = "Open navigation"
|
||||||
|
drawerTitle: string = "Navigation"
|
||||||
class: string = ""
|
class: string = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
state mobileOpen: boolean = false
|
state drawerOpen = false
|
||||||
|
|
||||||
functions {
|
functions {
|
||||||
client function toggleSidebar() {
|
shared function entryList() {
|
||||||
mobileOpen = !mobileOpen
|
return Array.isArray(items) ? items : []
|
||||||
output.toggle({ open: mobileOpen })
|
|
||||||
output[mobileOpen ? "open" : "close"]({ source: "mobile" })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
client function closeSidebar() {
|
// Accepts children as well as items: children is what shipped in 0.8.5
|
||||||
mobileOpen = false
|
// and existing callers should keep working.
|
||||||
output.close({ source: "mobile" })
|
shared function childrenOf(entry) {
|
||||||
|
if (!entry) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
if (Array.isArray(entry.items)) {
|
||||||
|
return entry.items
|
||||||
|
}
|
||||||
|
return Array.isArray(entry.children) ? entry.children : []
|
||||||
}
|
}
|
||||||
|
|
||||||
client function selectItem(item, level) {
|
shared function isGroup(entry) {
|
||||||
mobileOpen = false
|
return Boolean(entry.heading)
|
||||||
output.select({ item: item, value: item.value || "", level: level })
|
}
|
||||||
|
|
||||||
|
shared function isActive(entry) {
|
||||||
|
return Boolean(entry.value) && entry.value === active
|
||||||
|
}
|
||||||
|
|
||||||
|
client function choose(entry, level) {
|
||||||
|
if (entry.disabled) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
output.select({ item: entry, value: entry.value || "", level: level })
|
||||||
|
if (drawerOpen) {
|
||||||
|
drawerOpen = false
|
||||||
|
output.close({ source: "select" })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
client function openDrawer(sourceEvent) {
|
||||||
|
drawerOpen = true
|
||||||
|
output.open({ sourceEvent: sourceEvent })
|
||||||
|
output.toggle({ open: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
client function closeDrawer() {
|
||||||
|
drawerOpen = false
|
||||||
|
output.close({ source: "drawer" })
|
||||||
|
output.toggle({ open: false })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
view {
|
view {
|
||||||
<div class="wire-sidebar-shell wire-next--color-{color} wire-next--size-{size} {mobileOpen ? 'is-open' : ''} {class}">
|
<div
|
||||||
<button type="button" class="wire-sidebar-toggle" aria-label="{mobileLabel}" aria-expanded="{mobileOpen}" @click="toggleSidebar()">
|
{...attrs}
|
||||||
<span class="icon-[lucide--panel-left-open]" aria-hidden="true"></span>
|
data-ui-component="Sidebar"
|
||||||
<span>{label}</span>
|
class='wire-sidebar {class}'
|
||||||
|
data-color='{color}'
|
||||||
|
data-size='{size}'
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="wire-sidebar__launcher"
|
||||||
|
aria-label='{mobileLabel}'
|
||||||
|
aria-expanded='{drawerOpen}'
|
||||||
|
@click='openDrawer(event)'
|
||||||
|
>
|
||||||
|
<span class="wire-sidebar__launcher-bar" aria-hidden="true"></span>
|
||||||
|
<span class="wire-sidebar__launcher-text">{mobileLabel}</span>
|
||||||
</button>
|
</button>
|
||||||
<button type="button" class="wire-sidebar-backdrop" aria-label="Close navigation" @click="closeSidebar()"></button>
|
|
||||||
<nav class="wire-next wire-next--sidebar wire-next--{orientation} wire-sidebar-panel" aria-label="{label}">
|
<nav class="wire-sidebar__rail" aria-label='{label}'>
|
||||||
<div class="wire-sidebar-panel__head">
|
<ul class="wire-sidebar__list" data-wrn-roving="vertical">
|
||||||
<strong>{label}</strong>
|
{#each entryList() as entry}
|
||||||
<button type="button" aria-label="Close navigation" @click="closeSidebar()"><span class="icon-[lucide--x]" aria-hidden="true"></span></button>
|
<li class="wire-sidebar__entry" data-group='{isGroup(entry)}'>
|
||||||
</div>
|
<p class="wire-sidebar__heading" data-show="entry.heading">{entry.heading}</p>
|
||||||
<div class="wire-sidebar-items">
|
|
||||||
{#each items as item}
|
<a
|
||||||
{#if item.children && item.children.length}
|
class="wire-sidebar__link"
|
||||||
<details class="wire-sidebar-group" name="wire-sidebar-group">
|
data-show="!entry.heading"
|
||||||
<summary>
|
href='{entry.href || "#"}'
|
||||||
{#if item.icon}<span class="{item.icon}" aria-hidden="true"></span>{/if}
|
data-wrn-roving-item="true"
|
||||||
<span>{item.label}</span>
|
data-active='{isActive(entry)}'
|
||||||
<span class="icon-[lucide--chevron-down]" aria-hidden="true"></span>
|
aria-current='{isActive(entry) ? "page" : "false"}'
|
||||||
</summary>
|
aria-disabled='{entry.disabled ? "true" : "false"}'
|
||||||
<div class="wire-sidebar-group__children">
|
@click='choose(entry, 1)'
|
||||||
{#each item.children as child}
|
>
|
||||||
<a href="{child.href || '#'}" aria-current="{child.value === active ? 'page' : ''}" @click="selectItem(child, 2)">
|
<span
|
||||||
{#if child.icon}<span class="{child.icon}" aria-hidden="true"></span>{/if}
|
class='wire-sidebar__icon {entry.icon}'
|
||||||
<span>{child.label}</span>
|
data-show="entry.icon"
|
||||||
|
aria-hidden="true"
|
||||||
|
></span>
|
||||||
|
<span class="wire-sidebar__label">{entry.label}</span>
|
||||||
|
<span class="wire-sidebar__badge" data-show="entry.badge">{entry.badge}</span>
|
||||||
</a>
|
</a>
|
||||||
{/each}
|
|
||||||
</div>
|
<ul class="wire-sidebar__sublist" data-show="childrenOf(entry).length > 0">
|
||||||
</details>
|
{#each childrenOf(entry) as child}
|
||||||
{:else}
|
<li class="wire-sidebar__entry">
|
||||||
<a href="{item.href || '#'}" aria-current="{item.value === active ? 'page' : ''}" @click="selectItem(item, 1)">
|
<a
|
||||||
{#if item.icon}<span class="{item.icon}" aria-hidden="true"></span>{/if}
|
class="wire-sidebar__link"
|
||||||
<span>{item.label}</span>
|
href='{child.href || "#"}'
|
||||||
|
data-active='{isActive(child)}'
|
||||||
|
aria-current='{isActive(child) ? "page" : "false"}'
|
||||||
|
aria-disabled='{child.disabled ? "true" : "false"}'
|
||||||
|
@click='choose(child, 2)'
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class='wire-sidebar__icon {child.icon}'
|
||||||
|
data-show="child.icon"
|
||||||
|
aria-hidden="true"
|
||||||
|
></span>
|
||||||
|
<span class="wire-sidebar__label">{child.label}</span>
|
||||||
|
<span class="wire-sidebar__badge" data-show="child.badge">{child.badge}</span>
|
||||||
</a>
|
</a>
|
||||||
{/if}
|
|
||||||
|
<ul
|
||||||
|
class="wire-sidebar__sublist wire-sidebar__sublist--level3"
|
||||||
|
data-show="childrenOf(child).length > 0"
|
||||||
|
>
|
||||||
|
{#each childrenOf(child) as leaf}
|
||||||
|
<li class="wire-sidebar__entry">
|
||||||
|
<a
|
||||||
|
class="wire-sidebar__link"
|
||||||
|
href='{leaf.href || "#"}'
|
||||||
|
data-active='{isActive(leaf)}'
|
||||||
|
aria-current='{isActive(leaf) ? "page" : "false"}'
|
||||||
|
@click='choose(leaf, 3)'
|
||||||
|
>
|
||||||
|
<span class="wire-sidebar__label">{leaf.label}</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</ul>
|
||||||
|
</li>
|
||||||
|
{/each}
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
{/each}
|
||||||
|
</ul>
|
||||||
<slot />
|
<slot />
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
|
<Drawer
|
||||||
|
open={drawerOpen}
|
||||||
|
placement="left"
|
||||||
|
title={drawerTitle}
|
||||||
|
label={label}
|
||||||
|
@close="closeDrawer()"
|
||||||
|
>
|
||||||
|
<slot name="drawer"></slot>
|
||||||
|
</Drawer>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
style {
|
||||||
|
.wire-sidebar {
|
||||||
|
--sidebar-accent: var(--wire-color-primary);
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-sidebar[data-color="secondary"] {
|
||||||
|
--sidebar-accent: var(--wire-color-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-sidebar[data-color="success"] {
|
||||||
|
--sidebar-accent: var(--wire-color-success);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-sidebar[data-color="danger"] {
|
||||||
|
--sidebar-accent: var(--wire-color-danger);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-sidebar[data-color="info"] {
|
||||||
|
--sidebar-accent: var(--wire-color-info);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-sidebar[data-size="sm"] {
|
||||||
|
font-size: 0.82rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-sidebar[data-size="lg"] {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-sidebar__rail {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-sidebar__list,
|
||||||
|
.wire-sidebar__sublist {
|
||||||
|
display: grid;
|
||||||
|
gap: 0.1rem;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-sidebar__sublist {
|
||||||
|
margin-left: 0.85rem;
|
||||||
|
padding-left: 0.5rem;
|
||||||
|
border-left: 1px solid var(--wire-color-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-sidebar__entry[data-group="true"] + .wire-sidebar__entry {
|
||||||
|
margin-top: 0.35rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-sidebar__heading {
|
||||||
|
margin: 0.9rem 0 0.35rem;
|
||||||
|
color: var(--wire-color-text-muted);
|
||||||
|
font-size: 0.7rem;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 0.08em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-sidebar__link {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
padding: 0.45rem 0.6rem;
|
||||||
|
border-radius: var(--wire-radius-sm);
|
||||||
|
color: var(--wire-color-text-muted);
|
||||||
|
font-size: 0.88rem;
|
||||||
|
font-weight: 600;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-sidebar__link:hover {
|
||||||
|
background: var(--wire-color-surface-soft);
|
||||||
|
color: var(--wire-color-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-sidebar__link:focus-visible {
|
||||||
|
outline: 2px solid var(--sidebar-accent);
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-sidebar__link[data-active="true"] {
|
||||||
|
background: color-mix(in srgb, var(--sidebar-accent) 16%, transparent);
|
||||||
|
color: var(--sidebar-accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-sidebar__link[aria-disabled="true"] {
|
||||||
|
opacity: 0.5;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-sidebar__label {
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-sidebar__badge {
|
||||||
|
margin-left: auto;
|
||||||
|
padding: 0.05rem 0.4rem;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: color-mix(in srgb, var(--sidebar-accent) 16%, transparent);
|
||||||
|
color: var(--sidebar-accent);
|
||||||
|
font-size: 0.72rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-sidebar__launcher {
|
||||||
|
display: none;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
padding: 0.45rem 0.7rem;
|
||||||
|
border: 1px solid var(--wire-color-border);
|
||||||
|
border-radius: var(--wire-radius-sm);
|
||||||
|
background: var(--wire-color-surface);
|
||||||
|
color: var(--wire-color-text);
|
||||||
|
font: inherit;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-sidebar__launcher-bar {
|
||||||
|
width: 1rem;
|
||||||
|
height: 2px;
|
||||||
|
background: currentColor;
|
||||||
|
box-shadow:
|
||||||
|
0 -5px 0 currentColor,
|
||||||
|
0 5px 0 currentColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Below the tablet breakpoint the rail is replaced by the drawer launcher.
|
||||||
|
* A permanent rail eats most of a phone screen, and Drawer already handles
|
||||||
|
* the focus trap and the scroll lock.
|
||||||
|
*/
|
||||||
|
@media (max-width: 767px) {
|
||||||
|
.wire-sidebar__launcher {
|
||||||
|
display: inline-flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-sidebar__rail {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,24 +1,442 @@
|
|||||||
|
// Stepper -- ordered progress through a sequence.
|
||||||
|
//
|
||||||
|
// <Stepper steps='[{"label":"Account"},{"label":"Billing"}]' active={1} />
|
||||||
|
//
|
||||||
|
// Each step can be authored by hand instead of using the built-in body, by
|
||||||
|
// passing a slot named for its index:
|
||||||
|
//
|
||||||
|
// <Stepper steps={steps} active={1}>
|
||||||
|
// <div data-slot="step-1">...anything...</div>
|
||||||
|
// </Stepper>
|
||||||
|
//
|
||||||
|
// NOTE: the style block uses /* */ comments only -- // is not a CSS comment
|
||||||
|
// and silently swallows the rule that follows it.
|
||||||
component Stepper {
|
component Stepper {
|
||||||
outputs {
|
outputs {
|
||||||
change(payload: { value?: string | number | boolean | null; values?: Array<string | number | boolean | null | object>; sourceEvent?: Event; [key: string]: string | number | boolean | null | object } | string | number | boolean | null)
|
change(payload: { index: number; step: object })
|
||||||
previous(payload: { sourceEvent?: Event; [key: string]: string | number | boolean | null | object })
|
back(payload: { index: number; step: object })
|
||||||
next(payload: { sourceEvent?: Event; [key: string]: string | number | boolean | null | object })
|
next(payload: { index: number; step: object })
|
||||||
complete(payload: { sourceEvent?: Event; [key: string]: string | number | boolean | null | object })
|
skip(payload: { index: number; step: object })
|
||||||
|
finish(payload: { index: number; step: object })
|
||||||
}
|
}
|
||||||
|
|
||||||
props {
|
props {
|
||||||
size: string = "default"
|
|
||||||
color: string = "primary"
|
color: string = "primary"
|
||||||
label: string = "Stepper"
|
size: string = "default"
|
||||||
items: unknown[] = []
|
steps: unknown[] = []
|
||||||
active: string = ""
|
active: number = 0
|
||||||
orientation: string = "horizontal"
|
orientation: string = "horizontal"
|
||||||
|
clickable: boolean = false
|
||||||
|
label: string = "Progress"
|
||||||
|
// Render each step body, showing only the active one -- same contract as
|
||||||
|
// Tabs, so a wizard does not have to hand-roll the panel switching.
|
||||||
|
showPanel: boolean = false
|
||||||
|
controls: boolean = false
|
||||||
|
allowSkip: boolean = false
|
||||||
|
// Lets a form hold the step. The component never validates anything
|
||||||
|
// itself: the page owns the form, so it sets this while the step is
|
||||||
|
// incomplete and clears it once the step passes.
|
||||||
|
nextDisabled: boolean = false
|
||||||
|
backLabel: string = "Back"
|
||||||
|
nextLabel: string = "Next"
|
||||||
|
skipLabel: string = "Skip"
|
||||||
|
finishLabel: string = "Finish"
|
||||||
class: string = ""
|
class: string = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
functions {
|
||||||
|
shared function stepList() {
|
||||||
|
return Array.isArray(steps) ? steps : []
|
||||||
|
}
|
||||||
|
|
||||||
|
shared function activeIndex() {
|
||||||
|
var count = stepList().length
|
||||||
|
if (count < 1) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
var value = Number(active)
|
||||||
|
if (!value || value < 0) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return Math.min(value, count - 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
shared function statusFor(index) {
|
||||||
|
if (index < activeIndex()) {
|
||||||
|
return "complete"
|
||||||
|
}
|
||||||
|
if (index === activeIndex()) {
|
||||||
|
return "current"
|
||||||
|
}
|
||||||
|
return "upcoming"
|
||||||
|
}
|
||||||
|
|
||||||
|
// An empty orientation is how the roving runtime is told to stay out of
|
||||||
|
// the way, so a read-only stepper never takes arrow-key focus.
|
||||||
|
shared function rovingAxis() {
|
||||||
|
if (!clickable) {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return orientation === "vertical" ? "vertical" : "horizontal"
|
||||||
|
}
|
||||||
|
|
||||||
|
shared function isActiveStep(index) {
|
||||||
|
return index === activeIndex()
|
||||||
|
}
|
||||||
|
|
||||||
|
shared function lastIndex() {
|
||||||
|
return Math.max(0, stepList().length - 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
shared function onLastStep() {
|
||||||
|
return activeIndex() >= lastIndex()
|
||||||
|
}
|
||||||
|
|
||||||
|
shared function activeStep() {
|
||||||
|
var list = stepList()
|
||||||
|
return list.length ? list[activeIndex()] : {}
|
||||||
|
}
|
||||||
|
|
||||||
|
client function goBack() {
|
||||||
|
var target = Math.max(0, activeIndex() - 1)
|
||||||
|
output.back({ index: target, step: stepList()[target] || {} })
|
||||||
|
output.change({ index: target, step: stepList()[target] || {} })
|
||||||
|
}
|
||||||
|
|
||||||
|
client function goNext() {
|
||||||
|
if (nextDisabled) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (onLastStep()) {
|
||||||
|
output.finish({ index: activeIndex(), step: activeStep() })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var target = Math.min(lastIndex(), activeIndex() + 1)
|
||||||
|
output.next({ index: target, step: stepList()[target] || {} })
|
||||||
|
output.change({ index: target, step: stepList()[target] || {} })
|
||||||
|
}
|
||||||
|
|
||||||
|
client function goSkip() {
|
||||||
|
var target = Math.min(lastIndex(), activeIndex() + 1)
|
||||||
|
output.skip({ index: target, step: stepList()[target] || {} })
|
||||||
|
output.change({ index: target, step: stepList()[target] || {} })
|
||||||
|
}
|
||||||
|
|
||||||
|
client function selectStep(index, step) {
|
||||||
|
if (!clickable) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
output.change({ index: index, step: step })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
view {
|
view {
|
||||||
<nav class="wire-next wire-next--color-{color} wire-next--size-{size} wire-next--stepper wire-next--{orientation} {class}" aria-label="{label}">
|
<div
|
||||||
{#each items as item}<a href="{item.href}" aria-current="{item.value === active ? 'page' : ''}">{item.label}</a>{/each}
|
{...attrs}
|
||||||
|
data-ui-component="Stepper"
|
||||||
|
class='wire-stepper {class}'
|
||||||
|
data-orientation='{orientation}'
|
||||||
|
data-color='{color}'
|
||||||
|
data-size='{size}'
|
||||||
|
data-clickable='{clickable}'
|
||||||
|
>
|
||||||
|
<ol
|
||||||
|
class="wire-stepper__list"
|
||||||
|
data-wrn-roving='{rovingAxis()}'
|
||||||
|
aria-label='{label}'
|
||||||
|
>
|
||||||
|
{#each stepList() as step, index}
|
||||||
|
<li
|
||||||
|
class="wire-stepper__step"
|
||||||
|
data-status='{statusFor(index)}'
|
||||||
|
aria-current='{statusFor(index) === "current" ? "step" : "false"}'
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="wire-stepper__button"
|
||||||
|
data-wrn-roving-item='{clickable ? "true" : "false"}'
|
||||||
|
@click='selectStep(index, step)'
|
||||||
|
>
|
||||||
|
<span class="wire-stepper__marker" aria-hidden="true">
|
||||||
|
<span class='wire-stepper__icon {step.icon}' data-show="step.icon"></span>
|
||||||
|
<span class="wire-stepper__number" data-show="!step.icon">{index + 1}</span>
|
||||||
|
</span>
|
||||||
|
<span class="wire-stepper__body">
|
||||||
|
<span class="wire-stepper__label">{step.label}</span>
|
||||||
|
<span class="wire-stepper__description" data-show="step.description">
|
||||||
|
{step.description}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
<span class="wire-stepper__custom">
|
||||||
|
<slot name="step-{index}"></slot>
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
{/each}
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<div class="wire-stepper__panels" data-show="showPanel">
|
||||||
|
{#each stepList() as step, index}
|
||||||
|
<div
|
||||||
|
class="wire-stepper__panel"
|
||||||
|
data-show='isActiveStep(index)'
|
||||||
|
aria-hidden='{index === activeIndex() ? "false" : "true"}'
|
||||||
|
>
|
||||||
|
<h4 class="wire-stepper__panel-title" data-show="step.title">{step.title}</h4>
|
||||||
|
<p class="wire-stepper__panel-body" data-show="step.content">{step.content}</p>
|
||||||
|
<slot name="panel-{index}"></slot>
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="wire-stepper__controls" data-show="controls">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="wire-stepper__button-control wire-stepper__back"
|
||||||
|
disabled='{activeIndex() === 0}'
|
||||||
|
@click='goBack()'
|
||||||
|
>
|
||||||
|
{backLabel}
|
||||||
|
</button>
|
||||||
|
<span class="wire-stepper__controls-spacer"></span>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="wire-stepper__button-control wire-stepper__skip"
|
||||||
|
data-show="allowSkip && !onLastStep()"
|
||||||
|
@click='goSkip()'
|
||||||
|
>
|
||||||
|
{skipLabel}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="wire-stepper__button-control wire-stepper__next"
|
||||||
|
data-primary="true"
|
||||||
|
disabled='{nextDisabled}'
|
||||||
|
@click='goNext()'
|
||||||
|
>
|
||||||
|
{onLastStep() ? finishLabel : nextLabel}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<slot />
|
<slot />
|
||||||
</nav>
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
style {
|
||||||
|
.wire-stepper {
|
||||||
|
--stepper-accent: var(--wire-color-primary);
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-stepper__list {
|
||||||
|
display: flex;
|
||||||
|
gap: 0.5rem;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
list-style: none;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-stepper[data-color="secondary"] {
|
||||||
|
--stepper-accent: var(--wire-color-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-stepper[data-color="success"] {
|
||||||
|
--stepper-accent: var(--wire-color-success);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-stepper[data-color="danger"] {
|
||||||
|
--stepper-accent: var(--wire-color-danger);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-stepper[data-color="info"] {
|
||||||
|
--stepper-accent: var(--wire-color-info);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-stepper[data-size="sm"] {
|
||||||
|
font-size: 0.82rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-stepper[data-size="lg"] {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-stepper[data-orientation="vertical"] .wire-stepper__list {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-stepper__step {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex: 1 1 0;
|
||||||
|
min-width: 0;
|
||||||
|
gap: 0.35rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-stepper__button {
|
||||||
|
appearance: none;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.6rem;
|
||||||
|
width: 100%;
|
||||||
|
padding: 0.5rem;
|
||||||
|
border: 0;
|
||||||
|
border-radius: var(--wire-radius-sm);
|
||||||
|
background: transparent;
|
||||||
|
color: inherit;
|
||||||
|
font: inherit;
|
||||||
|
text-align: left;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-stepper[data-clickable="true"] .wire-stepper__button {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-stepper[data-clickable="true"] .wire-stepper__button:hover {
|
||||||
|
background: var(--wire-color-surface-soft);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-stepper__button:focus-visible {
|
||||||
|
outline: 2px solid var(--stepper-accent);
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-stepper__marker {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
width: 2rem;
|
||||||
|
height: 2rem;
|
||||||
|
border: 1px solid var(--wire-color-border);
|
||||||
|
border-radius: 999px;
|
||||||
|
background: var(--wire-color-surface);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-stepper__step[data-status="complete"] .wire-stepper__marker {
|
||||||
|
border-color: var(--stepper-accent);
|
||||||
|
background: var(--stepper-accent);
|
||||||
|
color: var(--wire-color-primary-contrast);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-stepper__step[data-status="current"] .wire-stepper__marker {
|
||||||
|
border-color: var(--stepper-accent);
|
||||||
|
color: var(--stepper-accent);
|
||||||
|
box-shadow: 0 0 0 3px color-mix(in srgb, var(--stepper-accent) 22%, transparent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-stepper__step[data-status="upcoming"] .wire-stepper__marker {
|
||||||
|
color: var(--wire-color-text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-stepper__body {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-stepper__label {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-stepper__description {
|
||||||
|
color: var(--wire-color-text-muted);
|
||||||
|
font-size: 0.78rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-stepper__step[data-status="upcoming"] .wire-stepper__label {
|
||||||
|
color: var(--wire-color-text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-stepper__panels {
|
||||||
|
margin-top: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-stepper__panel {
|
||||||
|
padding: 1rem;
|
||||||
|
border: 1px solid var(--wire-color-border);
|
||||||
|
border-radius: var(--wire-radius-md);
|
||||||
|
background: var(--wire-color-surface);
|
||||||
|
animation: wire-stepper-in 200ms ease both;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-stepper__panel-title {
|
||||||
|
margin: 0 0 0.35rem;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-stepper__panel-body {
|
||||||
|
margin: 0;
|
||||||
|
color: var(--wire-color-text-muted);
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-stepper__controls {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
margin-top: 0.85rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-stepper__controls-spacer {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-stepper__button-control {
|
||||||
|
appearance: none;
|
||||||
|
padding: 0.45rem 0.9rem;
|
||||||
|
border: 1px solid var(--wire-color-border);
|
||||||
|
border-radius: var(--wire-radius-sm);
|
||||||
|
background: var(--wire-color-surface);
|
||||||
|
color: var(--wire-color-text);
|
||||||
|
font: inherit;
|
||||||
|
font-size: 0.86rem;
|
||||||
|
font-weight: 600;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-stepper__button-control:hover:not(:disabled) {
|
||||||
|
background: var(--wire-color-surface-soft);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-stepper__button-control:focus-visible {
|
||||||
|
outline: 2px solid var(--stepper-accent);
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-stepper__button-control[data-primary="true"] {
|
||||||
|
border-color: var(--stepper-accent);
|
||||||
|
background: var(--stepper-accent);
|
||||||
|
color: var(--wire-color-primary-contrast);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A held step has to look held, or the button reads as broken. */
|
||||||
|
.wire-stepper__button-control:disabled {
|
||||||
|
opacity: 0.45;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes wire-stepper-in {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateX(0.75rem);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A horizontal stepper cannot stay side by side on a phone. */
|
||||||
|
@media (max-width: 639px) {
|
||||||
|
.wire-stepper__list {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+325
-53
@@ -1,90 +1,362 @@
|
|||||||
|
// Tabs -- a tablist over panels.
|
||||||
|
//
|
||||||
|
// <Tabs items='[{"label":"Overview","value":"overview"}]' active="overview" />
|
||||||
|
//
|
||||||
|
// With mode="url" the selection is mirrored into a query parameter using
|
||||||
|
// history.pushState, so the panel swaps without a page load and the back
|
||||||
|
// button works. The query parameter is used rather than the hash because it
|
||||||
|
// survives a reload and does not collide with in-page anchors or Scrollspy.
|
||||||
|
//
|
||||||
|
// NOTE: the style block uses /* */ comments only -- // is not a CSS comment
|
||||||
|
// and silently swallows the rule that follows it.
|
||||||
component Tabs {
|
component Tabs {
|
||||||
|
outputs {
|
||||||
|
change(payload: { value: string; item: object; index: number })
|
||||||
|
select(payload: { value: string; item: object; index: number })
|
||||||
|
}
|
||||||
|
|
||||||
props {
|
props {
|
||||||
size: string = "default"
|
|
||||||
color: string = "primary"
|
color: string = "primary"
|
||||||
label: string = "Tabs"
|
size: string = "default"
|
||||||
items: unknown[] = []
|
items: unknown[] = []
|
||||||
active: string = ""
|
active: string = ""
|
||||||
orientation: string = "horizontal"
|
orientation: string = "horizontal"
|
||||||
|
mode: string = "client"
|
||||||
|
param: string = "tab"
|
||||||
|
label: string = "Tabs"
|
||||||
class: string = ""
|
class: string = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
state activeValue = active || (items[0] ? (items[0].value || items[0].id || "0") : "")
|
state activeValue = ""
|
||||||
|
// Which way the panel should slide in. Set on every change so the animation
|
||||||
|
// follows the direction of travel rather than always coming from one side.
|
||||||
|
state slideFrom = "forward"
|
||||||
|
|
||||||
|
functions {
|
||||||
|
shared function itemList() {
|
||||||
|
return Array.isArray(items) ? items : []
|
||||||
|
}
|
||||||
|
|
||||||
|
shared function valueOf(item, index) {
|
||||||
|
return String(item.value || item.id || index)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In url mode the query parameter is the source of truth, not local state.
|
||||||
|
*
|
||||||
|
* The client router owns popstate and swaps the whole page on back and
|
||||||
|
* forward, which discards component state anyway. Reading the URL means
|
||||||
|
* the right tab simply falls out of whatever render happens next, with no
|
||||||
|
* listener to lose and nothing to keep in step.
|
||||||
|
*/
|
||||||
|
shared function currentValue() {
|
||||||
|
if (mode === "url" && typeof window !== "undefined" && window.location) {
|
||||||
|
var fromUrl = new URLSearchParams(window.location.search).get(param || "tab")
|
||||||
|
return fromUrl ? fromUrl : defaultValue()
|
||||||
|
}
|
||||||
|
if (activeValue) {
|
||||||
|
return activeValue
|
||||||
|
}
|
||||||
|
return defaultValue()
|
||||||
|
}
|
||||||
|
|
||||||
|
// The selection this instance started with. The runtime falls back to it
|
||||||
|
// when the back button lands on a URL that has no tab parameter at all.
|
||||||
|
shared function defaultValue() {
|
||||||
|
if (active) {
|
||||||
|
return active
|
||||||
|
}
|
||||||
|
var list = itemList()
|
||||||
|
return list.length ? valueOf(list[0], 0) : ""
|
||||||
|
}
|
||||||
|
|
||||||
|
shared function isSelected(item, index) {
|
||||||
|
return valueOf(item, index) === currentValue()
|
||||||
|
}
|
||||||
|
|
||||||
|
shared function rovingAxis() {
|
||||||
|
return orientation === "vertical" ? "vertical" : "horizontal"
|
||||||
|
}
|
||||||
|
|
||||||
|
client function selectTab(item, index, sourceEvent) {
|
||||||
|
if (item.disabled) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var value = valueOf(item, index)
|
||||||
|
var list = itemList()
|
||||||
|
var previous = -1
|
||||||
|
for (var scan = 0; scan < list.length; scan += 1) {
|
||||||
|
if (valueOf(list[scan], scan) === currentValue()) {
|
||||||
|
previous = scan
|
||||||
|
}
|
||||||
|
}
|
||||||
|
slideFrom = previous > index ? "back" : "forward"
|
||||||
|
activeValue = value
|
||||||
|
|
||||||
|
if (mode === "url" && window.history && window.history.pushState) {
|
||||||
|
var url = new URL(window.location.href)
|
||||||
|
url.searchParams.set(param || "tab", value)
|
||||||
|
window.history.pushState({}, "", url.toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
output.change({ value: value, item: item, index: index })
|
||||||
|
output.select({ value: value, item: item, index: index })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
view {
|
view {
|
||||||
<section
|
<section
|
||||||
|
{...attrs}
|
||||||
data-ui-component="Tabs"
|
data-ui-component="Tabs"
|
||||||
class='w-full {class}'
|
class='wire-tabs {class}'
|
||||||
class:flex='orientation === "vertical"'
|
data-orientation='{orientation}'
|
||||||
class:items-start='orientation === "vertical"'
|
data-color='{color}'
|
||||||
class:gap-6='orientation === "vertical"'
|
data-size='{size}'
|
||||||
|
data-slide='{slideFrom}'
|
||||||
|
data-mode='{mode}'
|
||||||
|
data-param='{param}'
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
|
class="wire-tabs__list"
|
||||||
role="tablist"
|
role="tablist"
|
||||||
aria-label='{label}'
|
aria-label='{label}'
|
||||||
aria-orientation='{orientation}'
|
aria-orientation='{orientation}'
|
||||||
class="flex min-w-0 gap-1 overflow-x-auto rounded-xl border border-[var(--wire-color-border)] bg-[var(--wire-color-surface-soft)] p-1"
|
data-wrn-roving='{rovingAxis()}'
|
||||||
class:flex-col='orientation === "vertical"'
|
|
||||||
class:w-56='orientation === "vertical"'
|
|
||||||
class:shrink-0='orientation === "vertical"'
|
|
||||||
>
|
>
|
||||||
{#each items as item, index}
|
{#each itemList() as item, index}
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
|
class="wire-tabs__tab"
|
||||||
role="tab"
|
role="tab"
|
||||||
id='tab-{item.value || item.id || index}'
|
data-value='{valueOf(item, index)}'
|
||||||
aria-selected='{activeValue === (item.value || item.id || String(index))}'
|
data-wrn-roving-item="true"
|
||||||
aria-controls='panel-{item.value || item.id || index}'
|
id='wire-tab-{valueOf(item, index)}'
|
||||||
tabindex='{activeValue === (item.value || item.id || String(index)) ? "0" : "-1"}'
|
aria-controls='wire-panel-{valueOf(item, index)}'
|
||||||
disabled='{item.disabled || false}'
|
aria-selected='{isSelected(item, index) ? "true" : "false"}'
|
||||||
class="inline-flex min-w-max flex-1 items-center justify-center gap-2 rounded-lg px-4 py-2.5 text-sm font-semibold outline-none transition disabled:cursor-not-allowed disabled:opacity-50"
|
aria-disabled='{item.disabled ? "true" : "false"}'
|
||||||
class:bg-[var(--wire-color-surface-raised)]='activeValue === (item.value || item.id || String(index))'
|
@click='selectTab(item, index, event)'
|
||||||
class:text-[var(--wire-color-primary)]='activeValue === (item.value || item.id || String(index))'
|
|
||||||
class:shadow-sm='activeValue === (item.value || item.id || String(index))'
|
|
||||||
class:text-[var(--wire-color-text-muted)]='activeValue !== (item.value || item.id || String(index))'
|
|
||||||
class:hover:text-[var(--wire-color-text)]='activeValue !== (item.value || item.id || String(index))'
|
|
||||||
class:justify-start='orientation === "vertical"'
|
|
||||||
class:px-3='size === "sm"'
|
|
||||||
class:py-2='size === "sm"'
|
|
||||||
class:px-5='size === "lg"'
|
|
||||||
class:py-3='size === "lg"'
|
|
||||||
@click='activeValue = item.value || item.id || String(index); event.currentTarget.dispatchEvent(new CustomEvent("change", { bubbles: true, detail: { item: item, index: index, value: activeValue } })); event.currentTarget.dispatchEvent(new CustomEvent("select", { bubbles: true, detail: { item: item, index: index, value: activeValue } }))'
|
|
||||||
>
|
>
|
||||||
{#if item.icon}
|
<span class='wire-tabs__icon {item.icon}' data-show="item.icon" aria-hidden="true"></span>
|
||||||
<span class='{item.icon + " size-4"}' aria-hidden="true"></span>
|
<span class="wire-tabs__label">{item.label || item.title}</span>
|
||||||
{/if}
|
<span class="wire-tabs__badge" data-show="item.badge">{item.badge}</span>
|
||||||
<span>{item.label || item.title}</span>
|
|
||||||
{#if item.badge}
|
|
||||||
<span class="rounded-full bg-[var(--wire-color-primary-soft)] px-2 py-0.5 text-xs text-[var(--wire-color-primary)]">{item.badge}</span>
|
|
||||||
{/if}
|
|
||||||
</button>
|
</button>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="min-w-0 flex-1 pt-4" class:pt-0='orientation === "vertical"'>
|
<div class="wire-tabs__panels">
|
||||||
{#each items as item, index}
|
{#each itemList() as item, index}
|
||||||
<div
|
<div
|
||||||
|
class="wire-tabs__panel"
|
||||||
role="tabpanel"
|
role="tabpanel"
|
||||||
id='panel-{item.value || item.id || index}'
|
id='wire-panel-{valueOf(item, index)}'
|
||||||
aria-labelledby='tab-{item.value || item.id || index}'
|
aria-labelledby='wire-tab-{valueOf(item, index)}'
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
data-show='activeValue === (item.value || item.id || String(index))'
|
data-show='isSelected(item, index)'
|
||||||
class="rounded-xl outline-none focus-visible:ring-2 focus-visible:ring-[var(--wire-color-focus)]"
|
|
||||||
>
|
>
|
||||||
{#if item.title && item.title !== item.label}
|
<h3 class="wire-tabs__title" data-show="item.title && item.title !== item.label">
|
||||||
<h3 class="text-lg font-bold text-[var(--wire-color-text)]">{item.title}</h3>
|
{item.title}
|
||||||
{/if}
|
</h3>
|
||||||
{#if item.description}
|
<p class="wire-tabs__description" data-show="item.description">{item.description}</p>
|
||||||
<p class="mt-2 leading-7 text-[var(--wire-color-text-muted)]">{item.description}</p>
|
<div class="wire-tabs__content" data-show="item.content">{item.content}</div>
|
||||||
{/if}
|
<slot name="panel-{valueOf(item, index)}"></slot>
|
||||||
{#if item.content}
|
|
||||||
<div class="mt-4 text-[var(--wire-color-text)]">{item.content}</div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
|
<slot />
|
||||||
<slot></slot>
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
style {
|
||||||
|
.wire-tabs {
|
||||||
|
--tabs-accent: var(--wire-color-primary);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1rem;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-tabs[data-color="secondary"] {
|
||||||
|
--tabs-accent: var(--wire-color-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-tabs[data-color="success"] {
|
||||||
|
--tabs-accent: var(--wire-color-success);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-tabs[data-color="danger"] {
|
||||||
|
--tabs-accent: var(--wire-color-danger);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-tabs[data-color="info"] {
|
||||||
|
--tabs-accent: var(--wire-color-info);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-tabs[data-size="sm"] {
|
||||||
|
font-size: 0.82rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-tabs[data-size="lg"] {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-tabs[data-orientation="vertical"] {
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-tabs__list {
|
||||||
|
display: flex;
|
||||||
|
gap: 0.25rem;
|
||||||
|
min-width: 0;
|
||||||
|
padding: 0.25rem;
|
||||||
|
border: 1px solid var(--wire-color-border);
|
||||||
|
border-radius: var(--wire-radius-md);
|
||||||
|
background: var(--wire-color-surface-soft);
|
||||||
|
/* A long tablist scrolls rather than wrapping into an unusable stack. */
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-tabs[data-orientation="vertical"] .wire-tabs__list {
|
||||||
|
flex-direction: column;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
width: 14rem;
|
||||||
|
overflow-x: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-tabs__tab {
|
||||||
|
appearance: none;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 0.4rem;
|
||||||
|
flex: 1 0 auto;
|
||||||
|
padding: 0.55rem 0.9rem;
|
||||||
|
border: 0;
|
||||||
|
border-radius: var(--wire-radius-sm);
|
||||||
|
background: transparent;
|
||||||
|
color: var(--wire-color-text-muted);
|
||||||
|
font: inherit;
|
||||||
|
font-size: 0.88rem;
|
||||||
|
font-weight: 600;
|
||||||
|
white-space: nowrap;
|
||||||
|
cursor: pointer;
|
||||||
|
transition:
|
||||||
|
background 160ms ease,
|
||||||
|
color 160ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-tabs[data-orientation="vertical"] .wire-tabs__tab {
|
||||||
|
justify-content: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-tabs__tab:hover {
|
||||||
|
color: var(--wire-color-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-tabs__tab:focus-visible {
|
||||||
|
outline: 2px solid var(--tabs-accent);
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-tabs__tab[aria-selected="true"] {
|
||||||
|
background: var(--wire-color-surface);
|
||||||
|
color: var(--tabs-accent);
|
||||||
|
box-shadow: var(--wire-shadow-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-tabs__tab[aria-disabled="true"] {
|
||||||
|
opacity: 0.5;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-tabs__badge {
|
||||||
|
padding: 0.05rem 0.4rem;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: color-mix(in srgb, var(--tabs-accent) 16%, transparent);
|
||||||
|
color: var(--tabs-accent);
|
||||||
|
font-size: 0.72rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-tabs__panels {
|
||||||
|
min-width: 0;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-tabs__panel {
|
||||||
|
outline: none;
|
||||||
|
animation: wire-tabs-slide-forward 220ms cubic-bezier(0.22, 1, 0.36, 1) both;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-tabs[data-slide="back"] .wire-tabs__panel {
|
||||||
|
animation-name: wire-tabs-slide-back;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The panels clip their own slide so it never widens the page. */
|
||||||
|
.wire-tabs__panels {
|
||||||
|
overflow-x: clip;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-tabs__panel:focus-visible {
|
||||||
|
outline: 2px solid var(--tabs-accent);
|
||||||
|
outline-offset: 4px;
|
||||||
|
border-radius: var(--wire-radius-sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-tabs__title {
|
||||||
|
margin: 0 0 0.35rem;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-tabs__description {
|
||||||
|
margin: 0;
|
||||||
|
color: var(--wire-color-text-muted);
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-tabs__content {
|
||||||
|
margin-top: 0.6rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes wire-tabs-slide-forward {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateX(1.25rem);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes wire-tabs-slide-back {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateX(-1.25rem);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Respect a reduced-motion preference: swap instantly instead. */
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
.wire-tabs__panel {
|
||||||
|
animation: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 639px) {
|
||||||
|
.wire-tabs[data-orientation="vertical"] {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-tabs[data-orientation="vertical"] .wire-tabs__list {
|
||||||
|
width: 100%;
|
||||||
|
flex-direction: row;
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
component Timeline {
|
component Timeline {
|
||||||
|
outputs {
|
||||||
|
select(payload: { sourceEvent?: Event; [key: string]: string | number | boolean | null | object })
|
||||||
|
}
|
||||||
|
|
||||||
props {
|
props {
|
||||||
size: string = "default"
|
size: string = "default"
|
||||||
color: string = "primary"
|
color: string = "primary"
|
||||||
@@ -30,7 +34,7 @@ component Timeline {
|
|||||||
{#each items as item, index}
|
{#each items as item, index}
|
||||||
<li
|
<li
|
||||||
class="relative pb-8 pl-8 last:pb-0"
|
class="relative pb-8 pl-8 last:pb-0"
|
||||||
@click='event.currentTarget.dispatchEvent(new CustomEvent("select", { bubbles: true, detail: { item: item, index: index } }))'
|
@click='output.select({ item: item, index: index })'
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
class="absolute -left-[1.05rem] top-0 flex size-8 items-center justify-center rounded-full border-4 border-[var(--wire-color-background)] bg-[var(--wire-color-primary)] text-[var(--wire-color-on-primary)] shadow-sm"
|
class="absolute -left-[1.05rem] top-0 flex size-8 items-center justify-center rounded-full border-4 border-[var(--wire-color-background)] bg-[var(--wire-color-primary)] text-[var(--wire-color-on-primary)] shadow-sm"
|
||||||
|
|||||||
@@ -57,34 +57,17 @@ component ToggleCount {
|
|||||||
: emptyValue
|
: emptyValue
|
||||||
}
|
}
|
||||||
|
|
||||||
client function dispatchToggleEvent(sourceEvent, previousValue, root, customEvent) {
|
client function dispatchToggleEvent(sourceEvent, previousValue, payload) {
|
||||||
root = sourceEvent.currentTarget.closest("[data-wrn-toggle-count]")
|
payload = {
|
||||||
|
component: "ToggleCount",
|
||||||
if (!root) {
|
name: name,
|
||||||
return
|
value: selectedValue,
|
||||||
|
previousValue: previousValue,
|
||||||
|
firstValue: firstValue,
|
||||||
|
secondValue: secondValue
|
||||||
}
|
}
|
||||||
|
output.change(payload)
|
||||||
customEvent = document.createEvent("CustomEvent")
|
output.toggle(payload)
|
||||||
customEvent.initCustomEvent("change", true, false, {
|
|
||||||
component: "ToggleCount",
|
|
||||||
name: name,
|
|
||||||
value: selectedValue,
|
|
||||||
previousValue: previousValue,
|
|
||||||
firstValue: firstValue,
|
|
||||||
secondValue: secondValue
|
|
||||||
})
|
|
||||||
root.dispatchEvent(customEvent)
|
|
||||||
|
|
||||||
customEvent = document.createEvent("CustomEvent")
|
|
||||||
customEvent.initCustomEvent("toggle", true, false, {
|
|
||||||
component: "ToggleCount",
|
|
||||||
name: name,
|
|
||||||
value: selectedValue,
|
|
||||||
previousValue: previousValue,
|
|
||||||
firstValue: firstValue,
|
|
||||||
secondValue: secondValue
|
|
||||||
})
|
|
||||||
root.dispatchEvent(customEvent)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
client function selectValue(sourceEvent, nextValue, previousValue) {
|
client function selectValue(sourceEvent, nextValue, previousValue) {
|
||||||
|
|||||||
@@ -11,26 +11,74 @@ component Typography {
|
|||||||
view {
|
view {
|
||||||
<div
|
<div
|
||||||
data-ui-component="Typography"
|
data-ui-component="Typography"
|
||||||
class='wire-typography text-[var(--wire-color-text)] {class}'
|
class='wire-typography {class}'
|
||||||
class:max-w-3xl='maxWidth === "md"'
|
data-size='{size}'
|
||||||
class:max-w-5xl='maxWidth === "lg"'
|
data-columns='{columns}'
|
||||||
class:max-w-7xl='maxWidth === "xl"'
|
data-gap='{gap}'
|
||||||
class:max-w-none='maxWidth === "full"'
|
data-max-width='{maxWidth}'
|
||||||
class:text-sm='size === "sm"'
|
|
||||||
class:text-base='size === "default" || size === "md"'
|
|
||||||
class:text-lg='size === "lg"'
|
|
||||||
class:columns-1='columns === 1'
|
|
||||||
class:md:columns-2='columns === 2'
|
|
||||||
class:lg:columns-3='columns === 3'
|
|
||||||
class:gap-4='gap === "sm"'
|
|
||||||
class:gap-8='gap === "md"'
|
|
||||||
class:gap-12='gap === "lg"'
|
|
||||||
>
|
>
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
style {
|
style {
|
||||||
|
.wire-typography {
|
||||||
|
color: var(--wire-color-text);
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-typography[data-size="sm"] {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-typography[data-size="lg"] {
|
||||||
|
font-size: 1.125rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-typography[data-max-width="md"] {
|
||||||
|
max-width: 48rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-typography[data-max-width="lg"] {
|
||||||
|
max-width: 64rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-typography[data-max-width="xl"] {
|
||||||
|
max-width: 80rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-typography[data-max-width="full"] {
|
||||||
|
max-width: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Multi-column prose only below a comfortable reading width; a narrow
|
||||||
|
* screen split into columns is unreadable.
|
||||||
|
*/
|
||||||
|
.wire-typography[data-gap="sm"] {
|
||||||
|
column-gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-typography[data-gap="md"] {
|
||||||
|
column-gap: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-typography[data-gap="lg"] {
|
||||||
|
column-gap: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.wire-typography[data-columns="2"] {
|
||||||
|
column-count: 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
.wire-typography[data-columns="3"] {
|
||||||
|
column-count: 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.wire-typography :where(h1, h2, h3, h4) {
|
.wire-typography :where(h1, h2, h3, h4) {
|
||||||
color: var(--wire-color-text);
|
color: var(--wire-color-text);
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
|
|||||||
@@ -35,22 +35,23 @@ component Alert {
|
|||||||
state visible: boolean = true
|
state visible: boolean = true
|
||||||
|
|
||||||
functions {
|
functions {
|
||||||
client function dispatchAlertEvent(sourceEvent, eventName, action, root, customEvent) {
|
// The output name has to be written out rather than computed: outputs are
|
||||||
root = sourceEvent.currentTarget.closest("[data-wrn-alert]")
|
// resolved as named properties, so a dynamic key would not reach a parent
|
||||||
|
// binding. Only two names exist here, so a branch is honest and cheap.
|
||||||
if (!root) {
|
client function dispatchAlertEvent(sourceEvent, eventName, action, payload) {
|
||||||
return
|
payload = {
|
||||||
}
|
|
||||||
|
|
||||||
customEvent = document.createEvent("CustomEvent")
|
|
||||||
customEvent.initCustomEvent(eventName, true, false, {
|
|
||||||
component: "Alert",
|
component: "Alert",
|
||||||
title: title,
|
title: title,
|
||||||
color: color,
|
color: color,
|
||||||
variant: variant,
|
variant: variant,
|
||||||
action: action
|
action: action
|
||||||
})
|
}
|
||||||
root.dispatchEvent(customEvent)
|
|
||||||
|
if (eventName === "dismiss") {
|
||||||
|
output.dismiss(payload)
|
||||||
|
} else {
|
||||||
|
output.action(payload)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
client function dismissAlert(sourceEvent) {
|
client function dismissAlert(sourceEvent) {
|
||||||
|
|||||||
@@ -35,15 +35,13 @@ component Badge {
|
|||||||
state visible: boolean = true
|
state visible: boolean = true
|
||||||
|
|
||||||
functions {
|
functions {
|
||||||
client function dismissBadge(sourceEvent, root, customEvent) {
|
// output.dismiss reaches a parent @dismiss binding; a raw dispatchEvent on
|
||||||
|
// the root does not. The runtime registers parent handlers in a registry
|
||||||
|
// that only the output proxy consults, so the CustomEvent this used to
|
||||||
|
// build bubbled past every binding and was never seen by anyone.
|
||||||
|
client function dismissBadge() {
|
||||||
visible = false
|
visible = false
|
||||||
root = sourceEvent.currentTarget.closest("[data-wrn-badge]")
|
output.dismiss({ component: "Badge", label: label })
|
||||||
customEvent = document.createEvent("CustomEvent")
|
|
||||||
customEvent.initCustomEvent("dismiss", true, false, {
|
|
||||||
component: "Badge",
|
|
||||||
label: label
|
|
||||||
})
|
|
||||||
root.dispatchEvent(customEvent)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,67 +45,27 @@ component Card {
|
|||||||
state dismissed: boolean = false
|
state dismissed: boolean = false
|
||||||
|
|
||||||
functions {
|
functions {
|
||||||
client function dispatchCardNavigation(sourceEvent, item, index, root, customEvent) {
|
// Outputs must go through output.*; a CustomEvent dispatched on the root
|
||||||
root = sourceEvent.currentTarget.closest("[data-wrn-card]")
|
// bubbles past every parent @binding without being seen, because the
|
||||||
|
// runtime keeps parent handlers in a registry only the output proxy reads.
|
||||||
if (!root) {
|
client function dispatchCardNavigation(sourceEvent, item, index) {
|
||||||
return
|
output.navigate({ component: "Card", item: item, index: index })
|
||||||
}
|
}
|
||||||
|
|
||||||
customEvent = document.createEvent("CustomEvent")
|
client function dispatchCardNavigationValue(sourceEvent) {
|
||||||
customEvent.initCustomEvent("navigate", true, false, {
|
output.navigate({
|
||||||
component: "Card",
|
|
||||||
item: item,
|
|
||||||
index: index
|
|
||||||
})
|
|
||||||
root.dispatchEvent(customEvent)
|
|
||||||
}
|
|
||||||
|
|
||||||
client function dispatchCardNavigationValue(sourceEvent, root, customEvent) {
|
|
||||||
root = sourceEvent.currentTarget.closest("[data-wrn-card]")
|
|
||||||
|
|
||||||
if (!root) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
customEvent = document.createEvent("CustomEvent")
|
|
||||||
customEvent.initCustomEvent("navigate", true, false, {
|
|
||||||
component: "Card",
|
component: "Card",
|
||||||
value: sourceEvent.currentTarget.value
|
value: sourceEvent.currentTarget.value
|
||||||
})
|
})
|
||||||
root.dispatchEvent(customEvent)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
client function dispatchCardHeaderAction(sourceEvent, action, index, root, customEvent) {
|
client function dispatchCardHeaderAction(sourceEvent, action, index) {
|
||||||
root = sourceEvent.currentTarget.closest("[data-wrn-card]")
|
output.action({ component: "Card", action: action, index: index })
|
||||||
|
|
||||||
if (!root) {
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
customEvent = document.createEvent("CustomEvent")
|
client function dismissCard() {
|
||||||
customEvent.initCustomEvent("action", true, false, {
|
|
||||||
component: "Card",
|
|
||||||
action: action,
|
|
||||||
index: index
|
|
||||||
})
|
|
||||||
root.dispatchEvent(customEvent)
|
|
||||||
}
|
|
||||||
|
|
||||||
client function dismissCard(sourceEvent, root, customEvent) {
|
|
||||||
dismissed = true
|
dismissed = true
|
||||||
root = sourceEvent.currentTarget.closest("[data-wrn-card]")
|
output.dismiss({ component: "Card", title: title })
|
||||||
|
|
||||||
if (!root) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
customEvent = document.createEvent("CustomEvent")
|
|
||||||
customEvent.initCustomEvent("dismiss", true, false, {
|
|
||||||
component: "Card",
|
|
||||||
title: title
|
|
||||||
})
|
|
||||||
root.dispatchEvent(customEvent)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,8 +97,8 @@ component Card {
|
|||||||
alt='{item.imageAlt || item.alt || ""}'
|
alt='{item.imageAlt || item.alt || ""}'
|
||||||
loading='{item.loading || "lazy"}'
|
loading='{item.loading || "lazy"}'
|
||||||
decoding="async"
|
decoding="async"
|
||||||
@load='event.currentTarget.dispatchEvent(new CustomEvent("load", { bubbles: true, detail: { item: item, index: itemIndex } }))'
|
@load='output.load({ item: item, index: itemIndex })'
|
||||||
@error='event.currentTarget.dispatchEvent(new CustomEvent("error", { bubbles: true, detail: { item: item, index: itemIndex } }))'
|
@error='output.error({ item: item, index: itemIndex })'
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -157,7 +117,7 @@ component Card {
|
|||||||
<a
|
<a
|
||||||
href='{item.actionHref || item.href || "#"}'
|
href='{item.actionHref || item.href || "#"}'
|
||||||
class="wire-next__card-action"
|
class="wire-next__card-action"
|
||||||
@click='event.currentTarget.dispatchEvent(new CustomEvent("action", { bubbles: true, detail: { item: item, index: itemIndex } }))'
|
@click='output.action({ item: item, index: itemIndex })'
|
||||||
>
|
>
|
||||||
<span>{item.actionLabel || "Learn more"}</span>
|
<span>{item.actionLabel || "Learn more"}</span>
|
||||||
<span class="icon-[lucide--arrow-right]" aria-hidden="true"></span>
|
<span class="icon-[lucide--arrow-right]" aria-hidden="true"></span>
|
||||||
@@ -180,8 +140,8 @@ component Card {
|
|||||||
alt='{imageAlt}'
|
alt='{imageAlt}'
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
decoding="async"
|
decoding="async"
|
||||||
@load='event.currentTarget.dispatchEvent(new CustomEvent("load", { bubbles: true, detail: { src: imageSrc } }))'
|
@load='output.load({ src: imageSrc })'
|
||||||
@error='event.currentTarget.dispatchEvent(new CustomEvent("error", { bubbles: true, detail: { src: imageSrc } }))'
|
@error='output.error({ src: imageSrc })'
|
||||||
/>
|
/>
|
||||||
<div class="wire-next__card-overlay-shade" aria-hidden="true"></div>
|
<div class="wire-next__card-overlay-shade" aria-hidden="true"></div>
|
||||||
</div>
|
</div>
|
||||||
@@ -194,8 +154,8 @@ component Card {
|
|||||||
alt='{imageAlt}'
|
alt='{imageAlt}'
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
decoding="async"
|
decoding="async"
|
||||||
@load='event.currentTarget.dispatchEvent(new CustomEvent("load", { bubbles: true, detail: { src: imageSrc } }))'
|
@load='output.load({ src: imageSrc })'
|
||||||
@error='event.currentTarget.dispatchEvent(new CustomEvent("error", { bubbles: true, detail: { src: imageSrc } }))'
|
@error='output.error({ src: imageSrc })'
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -323,7 +283,7 @@ component Card {
|
|||||||
<a
|
<a
|
||||||
href='{actionHref || "#"}'
|
href='{actionHref || "#"}'
|
||||||
class="wire-next__card-action"
|
class="wire-next__card-action"
|
||||||
@click='event.currentTarget.dispatchEvent(new CustomEvent("action", { bubbles: true, detail: { href: actionHref, label: actionLabel } }))'
|
@click='output.action({ href: actionHref, label: actionLabel })'
|
||||||
>
|
>
|
||||||
<span>{actionLabel}</span>
|
<span>{actionLabel}</span>
|
||||||
<span class="icon-[lucide--arrow-right]" aria-hidden="true"></span>
|
<span class="icon-[lucide--arrow-right]" aria-hidden="true"></span>
|
||||||
@@ -340,8 +300,8 @@ component Card {
|
|||||||
alt='{imageAlt}'
|
alt='{imageAlt}'
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
decoding="async"
|
decoding="async"
|
||||||
@load='event.currentTarget.dispatchEvent(new CustomEvent("load", { bubbles: true, detail: { src: imageSrc } }))'
|
@load='output.load({ src: imageSrc })'
|
||||||
@error='event.currentTarget.dispatchEvent(new CustomEvent("error", { bubbles: true, detail: { src: imageSrc } }))'
|
@error='output.error({ src: imageSrc })'
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
@@ -1,46 +1,162 @@
|
|||||||
|
// Container -- a centred, width-limited page wrapper.
|
||||||
|
//
|
||||||
|
// <Container maxWidth="lg">...</Container>
|
||||||
|
//
|
||||||
|
// It also accepts columns and gap, because it always has and applications
|
||||||
|
// depend on it. Reach for Grid when a grid is the point; reach for Container
|
||||||
|
// when the point is the reading width.
|
||||||
|
//
|
||||||
|
// NOTE: the style block uses /* */ comments only -- // is not a CSS comment
|
||||||
|
// and silently swallows the rule that follows it.
|
||||||
component Container {
|
component Container {
|
||||||
props {
|
props {
|
||||||
size: string = "default"
|
size: string = "default"
|
||||||
color: string = "primary"
|
color: string = "primary"
|
||||||
|
// Stays 2 to match what shipped. A published default cannot be changed
|
||||||
|
// without silently reflowing every Container already in use.
|
||||||
columns: number = 2
|
columns: number = 2
|
||||||
gap: string = "md"
|
gap: string = "md"
|
||||||
maxWidth: string = "xl"
|
maxWidth: string = "xl"
|
||||||
|
centered: boolean = true
|
||||||
class: string = ""
|
class: string = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
functions {
|
||||||
|
shared function columnCount() {
|
||||||
|
var value = Number(columns)
|
||||||
|
if (!value || value < 1) {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return Math.min(6, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
view {
|
view {
|
||||||
<div
|
<div
|
||||||
|
{...attrs}
|
||||||
data-ui-component="Container"
|
data-ui-component="Container"
|
||||||
|
class='wire-container {class}'
|
||||||
data-size='{size}'
|
data-size='{size}'
|
||||||
data-color='{color}'
|
data-color='{color}'
|
||||||
data-columns='{columns}'
|
|
||||||
data-gap='{gap}'
|
data-gap='{gap}'
|
||||||
data-max-width='{maxWidth}'
|
data-max-width='{maxWidth}'
|
||||||
class='mx-auto w-full {class}'
|
data-centered='{centered}'
|
||||||
class:max-w-3xl='maxWidth === "md"'
|
data-columns='{columnCount()}'
|
||||||
class:max-w-5xl='maxWidth === "lg"'
|
|
||||||
class:max-w-7xl='maxWidth === "xl" || maxWidth === "wide"'
|
|
||||||
class:max-w-screen-2xl='maxWidth === "2xl"'
|
|
||||||
class:max-w-none='maxWidth === "full"'
|
|
||||||
class:px-4='size === "compact" || size === "default"'
|
|
||||||
class:px-5='size === "comfortable"'
|
|
||||||
class:px-6='size === "spacious"'
|
|
||||||
class:sm:px-6='size !== "compact"'
|
|
||||||
class:lg:px-8='size === "default" || size === "comfortable" || size === "spacious"'
|
|
||||||
class:grid='columns > 1'
|
|
||||||
class:grid-cols-1='columns > 1'
|
|
||||||
class:sm:grid-cols-2='columns === 2 || columns === 3 || columns === 4 || columns === 5 || columns === 6'
|
|
||||||
class:lg:grid-cols-3='columns === 3'
|
|
||||||
class:lg:grid-cols-4='columns === 4'
|
|
||||||
class:lg:grid-cols-5='columns === 5'
|
|
||||||
class:lg:grid-cols-6='columns === 6'
|
|
||||||
class:gap-2='gap === "xs"'
|
|
||||||
class:gap-3='gap === "sm"'
|
|
||||||
class:gap-5='gap === "md"'
|
|
||||||
class:gap-8='gap === "lg"'
|
|
||||||
class:gap-10='gap === "xl"'
|
|
||||||
>
|
>
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
style {
|
||||||
|
.wire-container {
|
||||||
|
--container-gap: 1.25rem;
|
||||||
|
width: 100%;
|
||||||
|
min-width: 0;
|
||||||
|
padding-inline: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-container[data-centered="true"] {
|
||||||
|
margin-inline: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reading widths, not breakpoints: the cap is about line length. */
|
||||||
|
.wire-container[data-max-width="md"] {
|
||||||
|
max-width: 48rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-container[data-max-width="lg"] {
|
||||||
|
max-width: 64rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-container[data-max-width="xl"],
|
||||||
|
.wire-container[data-max-width="wide"] {
|
||||||
|
max-width: 80rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-container[data-max-width="2xl"] {
|
||||||
|
max-width: 96rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-container[data-max-width="full"] {
|
||||||
|
max-width: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-container[data-size="compact"] {
|
||||||
|
padding-inline: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-container[data-size="comfortable"] {
|
||||||
|
padding-inline: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-container[data-size="spacious"] {
|
||||||
|
padding-inline: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-container[data-gap="xs"] {
|
||||||
|
--container-gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-container[data-gap="sm"] {
|
||||||
|
--container-gap: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-container[data-gap="lg"] {
|
||||||
|
--container-gap: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-container[data-gap="xl"] {
|
||||||
|
--container-gap: 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Columns are opt-in. One column stays plain flow so a container does not
|
||||||
|
* quietly turn every page into a grid.
|
||||||
|
*/
|
||||||
|
.wire-container:not([data-columns="1"]) {
|
||||||
|
display: grid;
|
||||||
|
gap: var(--container-gap);
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 640px) {
|
||||||
|
.wire-container[data-columns="2"],
|
||||||
|
.wire-container[data-columns="3"],
|
||||||
|
.wire-container[data-columns="4"],
|
||||||
|
.wire-container[data-columns="5"],
|
||||||
|
.wire-container[data-columns="6"] {
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-container[data-size="default"],
|
||||||
|
.wire-container[data-size="comfortable"],
|
||||||
|
.wire-container[data-size="spacious"] {
|
||||||
|
padding-inline: 1.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
.wire-container[data-columns="3"] {
|
||||||
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-container[data-columns="4"] {
|
||||||
|
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-container[data-columns="5"] {
|
||||||
|
grid-template-columns: repeat(5, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-container[data-columns="6"] {
|
||||||
|
grid-template-columns: repeat(6, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-container[data-size="default"],
|
||||||
|
.wire-container[data-size="comfortable"],
|
||||||
|
.wire-container[data-size="spacious"] {
|
||||||
|
padding-inline: 2rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,69 +1,141 @@
|
|||||||
|
// Divider -- a rule between sections, optionally labelled.
|
||||||
|
//
|
||||||
|
// <Divider />
|
||||||
|
// <Divider label="or" />
|
||||||
|
// <Divider orientation="vertical" />
|
||||||
|
//
|
||||||
|
// The label sits between two rules rather than on top of one, so the text
|
||||||
|
// never overlaps the line at any width.
|
||||||
|
//
|
||||||
|
// NOTE: the style block uses /* */ comments only -- // is not a CSS comment
|
||||||
|
// and silently swallows the rule that follows it.
|
||||||
component Divider {
|
component Divider {
|
||||||
props {
|
props {
|
||||||
size: string = "default"
|
size: string = "default"
|
||||||
color: string = "primary"
|
color: string = "primary"
|
||||||
label: string = ""
|
label: string = ""
|
||||||
orientation: string = "horizontal"
|
orientation: string = "horizontal"
|
||||||
|
variant: string = "solid"
|
||||||
class: string = ""
|
class: string = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
functions {
|
||||||
|
shared function isVertical() {
|
||||||
|
return orientation === "vertical"
|
||||||
|
}
|
||||||
|
|
||||||
|
// The rule only takes the component colour when there is a label. A plain
|
||||||
|
// divider is chrome and should stay the border token.
|
||||||
|
shared function tone() {
|
||||||
|
return label ? color : "border"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
view {
|
view {
|
||||||
<div
|
<div
|
||||||
{...attrs}
|
{...attrs}
|
||||||
data-ui-component="Divider"
|
data-ui-component="Divider"
|
||||||
|
class='wire-divider {class}'
|
||||||
data-size='{size}'
|
data-size='{size}'
|
||||||
data-color='{color}'
|
data-color='{color}'
|
||||||
|
data-tone='{tone()}'
|
||||||
|
data-variant='{variant}'
|
||||||
data-orientation='{orientation}'
|
data-orientation='{orientation}'
|
||||||
class='w-full {class}'
|
data-labelled='{label ? "true" : "false"}'
|
||||||
class:h-full='orientation === "vertical"'
|
|
||||||
class:w-auto='orientation === "vertical"'
|
|
||||||
>
|
|
||||||
{#if orientation === "vertical"}
|
|
||||||
<div
|
|
||||||
role="separator"
|
role="separator"
|
||||||
aria-orientation="vertical"
|
aria-orientation='{isVertical() ? "vertical" : "horizontal"}'
|
||||||
class="mx-3 h-full min-h-6 border-l border-[var(--wire-color-border)]"
|
|
||||||
class:border-l-2='size === "lg"'
|
|
||||||
class:border-[var(--wire-color-primary)]='color === "primary"'
|
|
||||||
class:border-[var(--wire-color-secondary)]='color === "secondary"'
|
|
||||||
class:border-[var(--wire-color-success)]='color === "success"'
|
|
||||||
class:border-[var(--wire-color-warning)]='color === "warning"'
|
|
||||||
class:border-[var(--wire-color-danger)]='color === "danger"'
|
|
||||||
></div>
|
|
||||||
{:else}
|
|
||||||
<div
|
|
||||||
role="separator"
|
|
||||||
aria-orientation="horizontal"
|
|
||||||
class="flex w-full items-center gap-4"
|
|
||||||
>
|
>
|
||||||
<span
|
<span class="wire-divider__rule" aria-hidden="true"></span>
|
||||||
class="h-px flex-1 bg-[var(--wire-color-border)]"
|
<span class="wire-divider__label" data-show="label">{label}</span>
|
||||||
class:h-0.5='size === "lg"'
|
<span class="wire-divider__rule" data-show="label" aria-hidden="true"></span>
|
||||||
class:bg-[var(--wire-color-primary)]='color === "primary" && label !== ""'
|
|
||||||
class:bg-[var(--wire-color-secondary)]='color === "secondary" && label !== ""'
|
|
||||||
class:bg-[var(--wire-color-success)]='color === "success" && label !== ""'
|
|
||||||
class:bg-[var(--wire-color-warning)]='color === "warning" && label !== ""'
|
|
||||||
class:bg-[var(--wire-color-danger)]='color === "danger" && label !== ""'
|
|
||||||
aria-hidden="true"
|
|
||||||
></span>
|
|
||||||
|
|
||||||
{#if label}
|
|
||||||
<span class="shrink-0 text-xs font-bold uppercase tracking-[0.16em] text-[var(--wire-color-text-muted)]">
|
|
||||||
{label}
|
|
||||||
</span>
|
|
||||||
<span
|
|
||||||
class="h-px flex-1 bg-[var(--wire-color-border)]"
|
|
||||||
class:h-0.5='size === "lg"'
|
|
||||||
class:bg-[var(--wire-color-primary)]='color === "primary"'
|
|
||||||
class:bg-[var(--wire-color-secondary)]='color === "secondary"'
|
|
||||||
class:bg-[var(--wire-color-success)]='color === "success"'
|
|
||||||
class:bg-[var(--wire-color-warning)]='color === "warning"'
|
|
||||||
class:bg-[var(--wire-color-danger)]='color === "danger"'
|
|
||||||
aria-hidden="true"
|
|
||||||
></span>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
style {
|
||||||
|
.wire-divider {
|
||||||
|
--divider-tone: var(--wire-color-border);
|
||||||
|
--divider-thickness: 1px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 1rem;
|
||||||
|
width: 100%;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-divider[data-tone="primary"] {
|
||||||
|
--divider-tone: var(--wire-color-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-divider[data-tone="secondary"] {
|
||||||
|
--divider-tone: var(--wire-color-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-divider[data-tone="success"] {
|
||||||
|
--divider-tone: var(--wire-color-success);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-divider[data-tone="warning"] {
|
||||||
|
--divider-tone: var(--wire-color-warning);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-divider[data-tone="danger"] {
|
||||||
|
--divider-tone: var(--wire-color-danger);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-divider[data-size="lg"] {
|
||||||
|
--divider-thickness: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-divider__rule {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
height: var(--divider-thickness);
|
||||||
|
background: var(--divider-tone);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-divider[data-variant="dashed"] .wire-divider__rule {
|
||||||
|
height: 0;
|
||||||
|
background: transparent;
|
||||||
|
border-top: var(--divider-thickness) dashed var(--divider-tone);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-divider[data-variant="dotted"] .wire-divider__rule {
|
||||||
|
height: 0;
|
||||||
|
background: transparent;
|
||||||
|
border-top: var(--divider-thickness) dotted var(--divider-tone);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-divider__label {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
color: var(--wire-color-text-muted);
|
||||||
|
font-size: 0.72rem;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 0.16em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-divider[data-orientation="vertical"] {
|
||||||
|
flex-direction: column;
|
||||||
|
width: auto;
|
||||||
|
height: 100%;
|
||||||
|
min-height: 1.5rem;
|
||||||
|
margin-inline: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-divider[data-orientation="vertical"] .wire-divider__rule {
|
||||||
|
width: var(--divider-thickness);
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-divider[data-orientation="vertical"][data-variant="dashed"] .wire-divider__rule {
|
||||||
|
width: 0;
|
||||||
|
border-top: 0;
|
||||||
|
border-left: var(--divider-thickness) dashed var(--divider-tone);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-divider[data-orientation="vertical"][data-variant="dotted"] .wire-divider__rule {
|
||||||
|
width: 0;
|
||||||
|
border-top: 0;
|
||||||
|
border-left: var(--divider-thickness) dotted var(--divider-tone);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+117
-19
@@ -1,3 +1,13 @@
|
|||||||
|
// Grid -- an equal-track grid that collapses on small screens.
|
||||||
|
//
|
||||||
|
// <Grid columns={3} gap="lg">...</Grid>
|
||||||
|
//
|
||||||
|
// Pass minItemWidth to let the browser decide the count instead: the track
|
||||||
|
// list becomes auto-fit, which reflows continuously rather than at fixed
|
||||||
|
// breakpoints and suits card decks whose item count is not known.
|
||||||
|
//
|
||||||
|
// NOTE: the style block uses /* */ comments only -- // is not a CSS comment
|
||||||
|
// and silently swallows the rule that follows it.
|
||||||
component Grid {
|
component Grid {
|
||||||
props {
|
props {
|
||||||
size: string = "default"
|
size: string = "default"
|
||||||
@@ -5,36 +15,124 @@ component Grid {
|
|||||||
columns: number = 2
|
columns: number = 2
|
||||||
gap: string = "md"
|
gap: string = "md"
|
||||||
maxWidth: string = "xl"
|
maxWidth: string = "xl"
|
||||||
|
// When set, the count is derived from the available width instead of the
|
||||||
|
// columns prop. Accepts any CSS length.
|
||||||
|
minItemWidth: string = ""
|
||||||
class: string = ""
|
class: string = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
functions {
|
||||||
|
shared function columnCount() {
|
||||||
|
var value = Number(columns)
|
||||||
|
if (!value || value < 1) {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return Math.min(6, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
shared function autoTrack() {
|
||||||
|
return minItemWidth ? "repeat(auto-fit, minmax(" + minItemWidth + ", 1fr))" : ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
view {
|
view {
|
||||||
<div
|
<div
|
||||||
|
{...attrs}
|
||||||
data-ui-component="Grid"
|
data-ui-component="Grid"
|
||||||
|
class='wire-grid {class}'
|
||||||
data-size='{size}'
|
data-size='{size}'
|
||||||
data-color='{color}'
|
data-color='{color}'
|
||||||
data-columns='{columns}'
|
|
||||||
data-gap='{gap}'
|
data-gap='{gap}'
|
||||||
class='grid w-full grid-cols-1 {class}'
|
data-max-width='{maxWidth}'
|
||||||
class:max-w-3xl='maxWidth === "md"'
|
data-columns='{columnCount()}'
|
||||||
class:max-w-5xl='maxWidth === "lg"'
|
data-auto='{minItemWidth ? "true" : "false"}'
|
||||||
class:max-w-7xl='maxWidth === "xl"'
|
style='--grid-auto-track:{autoTrack()};'
|
||||||
class:max-w-screen-2xl='maxWidth === "2xl"'
|
|
||||||
class:max-w-none='maxWidth === "full"'
|
|
||||||
class:sm:grid-cols-2='columns >= 2'
|
|
||||||
class:lg:grid-cols-3='columns === 3'
|
|
||||||
class:lg:grid-cols-4='columns === 4'
|
|
||||||
class:lg:grid-cols-5='columns === 5'
|
|
||||||
class:lg:grid-cols-6='columns === 6'
|
|
||||||
class:gap-2='gap === "xs"'
|
|
||||||
class:gap-3='gap === "sm"'
|
|
||||||
class:gap-5='gap === "md"'
|
|
||||||
class:gap-8='gap === "lg"'
|
|
||||||
class:gap-10='gap === "xl"'
|
|
||||||
class:items-start='size === "compact"'
|
|
||||||
class:items-stretch='size !== "compact"'
|
|
||||||
>
|
>
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
style {
|
||||||
|
.wire-grid {
|
||||||
|
--grid-gap: 1.25rem;
|
||||||
|
display: grid;
|
||||||
|
width: 100%;
|
||||||
|
min-width: 0;
|
||||||
|
gap: var(--grid-gap);
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-grid[data-size="compact"] {
|
||||||
|
align-items: start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-grid[data-max-width="md"] {
|
||||||
|
max-width: 48rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-grid[data-max-width="lg"] {
|
||||||
|
max-width: 64rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-grid[data-max-width="xl"] {
|
||||||
|
max-width: 80rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-grid[data-max-width="2xl"] {
|
||||||
|
max-width: 96rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-grid[data-max-width="full"] {
|
||||||
|
max-width: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-grid[data-gap="xs"] {
|
||||||
|
--grid-gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-grid[data-gap="sm"] {
|
||||||
|
--grid-gap: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-grid[data-gap="lg"] {
|
||||||
|
--grid-gap: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-grid[data-gap="xl"] {
|
||||||
|
--grid-gap: 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* auto-fit needs no breakpoints, so it wins over the fixed counts below
|
||||||
|
* and applies at every width.
|
||||||
|
*/
|
||||||
|
.wire-grid[data-auto="true"] {
|
||||||
|
grid-template-columns: var(--grid-auto-track);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 640px) {
|
||||||
|
.wire-grid[data-auto="false"]:not([data-columns="1"]) {
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
.wire-grid[data-auto="false"][data-columns="3"] {
|
||||||
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-grid[data-auto="false"][data-columns="4"] {
|
||||||
|
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-grid[data-auto="false"][data-columns="5"] {
|
||||||
|
grid-template-columns: repeat(5, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.wire-grid[data-auto="false"][data-columns="6"] {
|
||||||
|
grid-template-columns: repeat(6, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/ui",
|
"name": "@wrnexus/ui",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "@wrnexus/ui — part of the WrNexus framework.",
|
"description": "@wrnexus/ui — part of the WrNexus framework.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
"./ui.css": "./ui.css"
|
"./ui.css": "./ui.css"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "^0.8.5"
|
"@wrnexus/core": "^0.8.6"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist",
|
"dist",
|
||||||
|
|||||||
-2012
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/uploader",
|
"name": "@wrnexus/uploader",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "Secure upload drivers, policies, client runtime, helper functions, and reusable upload components.",
|
"description": "Secure upload drivers, policies, client runtime, helper functions, and reusable upload components.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -42,9 +42,9 @@
|
|||||||
"./components/*": "./components/*"
|
"./components/*": "./components/*"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "^0.8.5",
|
"@wrnexus/core": "^0.8.6",
|
||||||
"@wrnexus/plugin": "^0.8.5",
|
"@wrnexus/plugin": "^0.8.6",
|
||||||
"@wrnexus/ui": "^0.8.5"
|
"@wrnexus/ui": "^0.8.6"
|
||||||
},
|
},
|
||||||
"wrnexus": {
|
"wrnexus": {
|
||||||
"plugin": {
|
"plugin": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/validation",
|
"name": "@wrnexus/validation",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "Shared server/browser schemas, validation helpers, form runtime, and reusable error components.",
|
"description": "Shared server/browser schemas, validation helpers, form runtime, and reusable error components.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -42,9 +42,9 @@
|
|||||||
"./components/*": "./components/*"
|
"./components/*": "./components/*"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "^0.8.5",
|
"@wrnexus/core": "^0.8.6",
|
||||||
"@wrnexus/plugin": "^0.8.5",
|
"@wrnexus/plugin": "^0.8.6",
|
||||||
"@wrnexus/ui": "^0.8.5"
|
"@wrnexus/ui": "^0.8.6"
|
||||||
},
|
},
|
||||||
"wrnexus": {
|
"wrnexus": {
|
||||||
"plugin": {
|
"plugin": {
|
||||||
|
|||||||
@@ -105,13 +105,25 @@
|
|||||||
"typescript": "^5.9.2",
|
"typescript": "^5.9.2",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"examples/inter-app-api-showcase": {
|
||||||
|
"name": "inter-app-api-showcase",
|
||||||
|
"devDependencies": {
|
||||||
|
"@eslint/js": "^9.0.0",
|
||||||
|
"@types/bun": "latest",
|
||||||
|
"@wrnexus/cli": "0.8.6",
|
||||||
|
"eslint": "^9.0.0",
|
||||||
|
"prettier": "latest",
|
||||||
|
"typescript": "^5.5.0",
|
||||||
|
"typescript-eslint": "latest",
|
||||||
|
},
|
||||||
|
},
|
||||||
"packages/ai": {
|
"packages/ai": {
|
||||||
"name": "@wrnexus/ai",
|
"name": "@wrnexus/ai",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
},
|
},
|
||||||
"packages/auth": {
|
"packages/auth": {
|
||||||
"name": "@wrnexus/auth",
|
"name": "@wrnexus/auth",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/authz": "workspace:*",
|
"@wrnexus/authz": "workspace:*",
|
||||||
"@wrnexus/captcha": "workspace:*",
|
"@wrnexus/captcha": "workspace:*",
|
||||||
@@ -133,7 +145,7 @@
|
|||||||
},
|
},
|
||||||
"packages/authz": {
|
"packages/authz": {
|
||||||
"name": "@wrnexus/authz",
|
"name": "@wrnexus/authz",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "workspace:*",
|
"@wrnexus/core": "workspace:*",
|
||||||
"@wrnexus/db": "workspace:*",
|
"@wrnexus/db": "workspace:*",
|
||||||
@@ -141,18 +153,18 @@
|
|||||||
},
|
},
|
||||||
"packages/benchmark": {
|
"packages/benchmark": {
|
||||||
"name": "@wrnexus/benchmark",
|
"name": "@wrnexus/benchmark",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
},
|
},
|
||||||
"packages/cache": {
|
"packages/cache": {
|
||||||
"name": "@wrnexus/cache",
|
"name": "@wrnexus/cache",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "workspace:*",
|
"@wrnexus/core": "workspace:*",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"packages/captcha": {
|
"packages/captcha": {
|
||||||
"name": "@wrnexus/captcha",
|
"name": "@wrnexus/captcha",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "workspace:*",
|
"@wrnexus/core": "workspace:*",
|
||||||
"@wrnexus/plugin": "workspace:*",
|
"@wrnexus/plugin": "workspace:*",
|
||||||
@@ -167,7 +179,7 @@
|
|||||||
},
|
},
|
||||||
"packages/cli": {
|
"packages/cli": {
|
||||||
"name": "@wrnexus/cli",
|
"name": "@wrnexus/cli",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"bin": {
|
"bin": {
|
||||||
"wrnexus": "src/index.ts",
|
"wrnexus": "src/index.ts",
|
||||||
},
|
},
|
||||||
@@ -194,7 +206,7 @@
|
|||||||
},
|
},
|
||||||
"packages/compiler": {
|
"packages/compiler": {
|
||||||
"name": "@wrnexus/compiler",
|
"name": "@wrnexus/compiler",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/csr": "workspace:*",
|
"@wrnexus/csr": "workspace:*",
|
||||||
"@wrnexus/store": "workspace:*",
|
"@wrnexus/store": "workspace:*",
|
||||||
@@ -204,7 +216,7 @@
|
|||||||
},
|
},
|
||||||
"packages/content": {
|
"packages/content": {
|
||||||
"name": "@wrnexus/content",
|
"name": "@wrnexus/content",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bun": "^1.3.14",
|
"@types/bun": "^1.3.14",
|
||||||
"typescript": "^5.9.2",
|
"typescript": "^5.9.2",
|
||||||
@@ -212,18 +224,18 @@
|
|||||||
},
|
},
|
||||||
"packages/core": {
|
"packages/core": {
|
||||||
"name": "@wrnexus/core",
|
"name": "@wrnexus/core",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
},
|
},
|
||||||
"packages/csr": {
|
"packages/csr": {
|
||||||
"name": "@wrnexus/csr",
|
"name": "@wrnexus/csr",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "workspace:*",
|
"@wrnexus/core": "workspace:*",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"packages/db": {
|
"packages/db": {
|
||||||
"name": "@wrnexus/db",
|
"name": "@wrnexus/db",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bun": "^1.3.14",
|
"@types/bun": "^1.3.14",
|
||||||
"typescript": "^5.9.2",
|
"typescript": "^5.9.2",
|
||||||
@@ -231,7 +243,7 @@
|
|||||||
},
|
},
|
||||||
"packages/dev-server": {
|
"packages/dev-server": {
|
||||||
"name": "@wrnexus/dev-server",
|
"name": "@wrnexus/dev-server",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/authz": "workspace:*",
|
"@wrnexus/authz": "workspace:*",
|
||||||
"@wrnexus/cache": "workspace:*",
|
"@wrnexus/cache": "workspace:*",
|
||||||
@@ -258,7 +270,7 @@
|
|||||||
},
|
},
|
||||||
"packages/dev-toolbar": {
|
"packages/dev-toolbar": {
|
||||||
"name": "@wrnexus/dev-toolbar",
|
"name": "@wrnexus/dev-toolbar",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bun": "^1.3.14",
|
"@types/bun": "^1.3.14",
|
||||||
"typescript": "^5.9.2",
|
"typescript": "^5.9.2",
|
||||||
@@ -266,7 +278,7 @@
|
|||||||
},
|
},
|
||||||
"packages/encryption": {
|
"packages/encryption": {
|
||||||
"name": "@wrnexus/encryption",
|
"name": "@wrnexus/encryption",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "workspace:*",
|
"@wrnexus/core": "workspace:*",
|
||||||
},
|
},
|
||||||
@@ -277,21 +289,21 @@
|
|||||||
},
|
},
|
||||||
"packages/graphql": {
|
"packages/graphql": {
|
||||||
"name": "@wrnexus/graphql",
|
"name": "@wrnexus/graphql",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/plugin": "workspace:*",
|
"@wrnexus/plugin": "workspace:*",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"packages/helpers": {
|
"packages/helpers": {
|
||||||
"name": "@wrnexus/helpers",
|
"name": "@wrnexus/helpers",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "workspace:*",
|
"@wrnexus/core": "workspace:*",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"packages/i18n": {
|
"packages/i18n": {
|
||||||
"name": "@wrnexus/i18n",
|
"name": "@wrnexus/i18n",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "workspace:*",
|
"@wrnexus/core": "workspace:*",
|
||||||
"@wrnexus/plugin": "workspace:*",
|
"@wrnexus/plugin": "workspace:*",
|
||||||
@@ -305,7 +317,7 @@
|
|||||||
},
|
},
|
||||||
"packages/identity": {
|
"packages/identity": {
|
||||||
"name": "@wrnexus/identity",
|
"name": "@wrnexus/identity",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/auth": "workspace:*",
|
"@wrnexus/auth": "workspace:*",
|
||||||
"@wrnexus/authz": "workspace:*",
|
"@wrnexus/authz": "workspace:*",
|
||||||
@@ -314,7 +326,7 @@
|
|||||||
},
|
},
|
||||||
"packages/image": {
|
"packages/image": {
|
||||||
"name": "@wrnexus/image",
|
"name": "@wrnexus/image",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/plugin": "workspace:*",
|
"@wrnexus/plugin": "workspace:*",
|
||||||
"@wrnexus/security": "workspace:*",
|
"@wrnexus/security": "workspace:*",
|
||||||
@@ -334,7 +346,7 @@
|
|||||||
},
|
},
|
||||||
"packages/jwt": {
|
"packages/jwt": {
|
||||||
"name": "@wrnexus/jwt",
|
"name": "@wrnexus/jwt",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "workspace:*",
|
"@wrnexus/core": "workspace:*",
|
||||||
},
|
},
|
||||||
@@ -345,7 +357,7 @@
|
|||||||
},
|
},
|
||||||
"packages/language-server": {
|
"packages/language-server": {
|
||||||
"name": "@wrnexus/language-server",
|
"name": "@wrnexus/language-server",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"bin": {
|
"bin": {
|
||||||
"wrnexus-language-server": "src/server.ts",
|
"wrnexus-language-server": "src/server.ts",
|
||||||
},
|
},
|
||||||
@@ -356,39 +368,39 @@
|
|||||||
},
|
},
|
||||||
"packages/mcp": {
|
"packages/mcp": {
|
||||||
"name": "@wrnexus/mcp",
|
"name": "@wrnexus/mcp",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"bin": {
|
"bin": {
|
||||||
"wrnexus-mcp": "src/stdio.ts",
|
"wrnexus-mcp": "src/stdio.ts",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"packages/mobile": {
|
"packages/mobile": {
|
||||||
"name": "@wrnexus/mobile",
|
"name": "@wrnexus/mobile",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/native": "workspace:*",
|
"@wrnexus/native": "workspace:*",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"packages/native": {
|
"packages/native": {
|
||||||
"name": "@wrnexus/native",
|
"name": "@wrnexus/native",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
},
|
},
|
||||||
"packages/oauth": {
|
"packages/oauth": {
|
||||||
"name": "@wrnexus/oauth",
|
"name": "@wrnexus/oauth",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/jwt": "workspace:*",
|
"@wrnexus/jwt": "workspace:*",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"packages/observability": {
|
"packages/observability": {
|
||||||
"name": "@wrnexus/observability",
|
"name": "@wrnexus/observability",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "workspace:*",
|
"@wrnexus/core": "workspace:*",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"packages/playground": {
|
"packages/playground": {
|
||||||
"name": "@wrnexus/playground",
|
"name": "@wrnexus/playground",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/compiler": "workspace:*",
|
"@wrnexus/compiler": "workspace:*",
|
||||||
"@wrnexus/syntax": "workspace:*",
|
"@wrnexus/syntax": "workspace:*",
|
||||||
@@ -396,18 +408,22 @@
|
|||||||
},
|
},
|
||||||
"packages/plugin": {
|
"packages/plugin": {
|
||||||
"name": "@wrnexus/plugin",
|
"name": "@wrnexus/plugin",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/syntax": "workspace:*",
|
"@wrnexus/syntax": "workspace:*",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"packages/pubsub": {
|
"packages/pubsub": {
|
||||||
"name": "@wrnexus/pubsub",
|
"name": "@wrnexus/pubsub",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
|
"dependencies": {
|
||||||
|
"@wrnexus/core": "workspace:*",
|
||||||
|
"@wrnexus/rpc": "workspace:*",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
"packages/pwa": {
|
"packages/pwa": {
|
||||||
"name": "@wrnexus/pwa",
|
"name": "@wrnexus/pwa",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bun": "^1.3.14",
|
"@types/bun": "^1.3.14",
|
||||||
"typescript": "^5.9.2",
|
"typescript": "^5.9.2",
|
||||||
@@ -415,18 +431,19 @@
|
|||||||
},
|
},
|
||||||
"packages/queue": {
|
"packages/queue": {
|
||||||
"name": "@wrnexus/queue",
|
"name": "@wrnexus/queue",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "workspace:*",
|
"@wrnexus/core": "workspace:*",
|
||||||
|
"@wrnexus/rpc": "workspace:*",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"packages/reactive": {
|
"packages/reactive": {
|
||||||
"name": "@wrnexus/reactive",
|
"name": "@wrnexus/reactive",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
},
|
},
|
||||||
"packages/realtime": {
|
"packages/realtime": {
|
||||||
"name": "@wrnexus/realtime",
|
"name": "@wrnexus/realtime",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "workspace:*",
|
"@wrnexus/core": "workspace:*",
|
||||||
"@wrnexus/plugin": "workspace:*",
|
"@wrnexus/plugin": "workspace:*",
|
||||||
@@ -440,7 +457,7 @@
|
|||||||
},
|
},
|
||||||
"packages/router": {
|
"packages/router": {
|
||||||
"name": "@wrnexus/router",
|
"name": "@wrnexus/router",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/compiler": "workspace:*",
|
"@wrnexus/compiler": "workspace:*",
|
||||||
"@wrnexus/core": "workspace:*",
|
"@wrnexus/core": "workspace:*",
|
||||||
@@ -448,9 +465,8 @@
|
|||||||
},
|
},
|
||||||
"packages/rpc": {
|
"packages/rpc": {
|
||||||
"name": "@wrnexus/rpc",
|
"name": "@wrnexus/rpc",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/authz": "workspace:*",
|
|
||||||
"@wrnexus/core": "workspace:*",
|
"@wrnexus/core": "workspace:*",
|
||||||
"@wrnexus/helpers": "workspace:*",
|
"@wrnexus/helpers": "workspace:*",
|
||||||
"@wrnexus/jwt": "workspace:*",
|
"@wrnexus/jwt": "workspace:*",
|
||||||
@@ -463,14 +479,14 @@
|
|||||||
},
|
},
|
||||||
"packages/security": {
|
"packages/security": {
|
||||||
"name": "@wrnexus/security",
|
"name": "@wrnexus/security",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "workspace:*",
|
"@wrnexus/core": "workspace:*",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"packages/ssr": {
|
"packages/ssr": {
|
||||||
"name": "@wrnexus/ssr",
|
"name": "@wrnexus/ssr",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "workspace:*",
|
"@wrnexus/core": "workspace:*",
|
||||||
"@wrnexus/security": "workspace:*",
|
"@wrnexus/security": "workspace:*",
|
||||||
@@ -479,11 +495,11 @@
|
|||||||
},
|
},
|
||||||
"packages/store": {
|
"packages/store": {
|
||||||
"name": "@wrnexus/store",
|
"name": "@wrnexus/store",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
},
|
},
|
||||||
"packages/styles": {
|
"packages/styles": {
|
||||||
"name": "@wrnexus/styles",
|
"name": "@wrnexus/styles",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "workspace:*",
|
"@wrnexus/core": "workspace:*",
|
||||||
"@wrnexus/plugin": "workspace:*",
|
"@wrnexus/plugin": "workspace:*",
|
||||||
@@ -492,19 +508,19 @@
|
|||||||
},
|
},
|
||||||
"packages/syntax": {
|
"packages/syntax": {
|
||||||
"name": "@wrnexus/syntax",
|
"name": "@wrnexus/syntax",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
},
|
},
|
||||||
"packages/test": {
|
"packages/test": {
|
||||||
"name": "@wrnexus/test",
|
"name": "@wrnexus/test",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
},
|
},
|
||||||
"packages/tracking": {
|
"packages/tracking": {
|
||||||
"name": "@wrnexus/tracking",
|
"name": "@wrnexus/tracking",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
},
|
},
|
||||||
"packages/typecheck": {
|
"packages/typecheck": {
|
||||||
"name": "@wrnexus/typecheck",
|
"name": "@wrnexus/typecheck",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/syntax": "workspace:*",
|
"@wrnexus/syntax": "workspace:*",
|
||||||
"typescript": "^5.5.0",
|
"typescript": "^5.5.0",
|
||||||
@@ -512,14 +528,14 @@
|
|||||||
},
|
},
|
||||||
"packages/ui": {
|
"packages/ui": {
|
||||||
"name": "@wrnexus/ui",
|
"name": "@wrnexus/ui",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "workspace:*",
|
"@wrnexus/core": "workspace:*",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"packages/uploader": {
|
"packages/uploader": {
|
||||||
"name": "@wrnexus/uploader",
|
"name": "@wrnexus/uploader",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "workspace:*",
|
"@wrnexus/core": "workspace:*",
|
||||||
"@wrnexus/plugin": "workspace:*",
|
"@wrnexus/plugin": "workspace:*",
|
||||||
@@ -533,7 +549,7 @@
|
|||||||
},
|
},
|
||||||
"packages/validation": {
|
"packages/validation": {
|
||||||
"name": "@wrnexus/validation",
|
"name": "@wrnexus/validation",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "workspace:*",
|
"@wrnexus/core": "workspace:*",
|
||||||
"@wrnexus/plugin": "workspace:*",
|
"@wrnexus/plugin": "workspace:*",
|
||||||
@@ -628,6 +644,8 @@
|
|||||||
|
|
||||||
"@eslint/core": ["@eslint/core@1.2.1", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ=="],
|
"@eslint/core": ["@eslint/core@1.2.1", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ=="],
|
||||||
|
|
||||||
|
"@eslint/eslintrc": ["@eslint/eslintrc@3.3.6", "", { "dependencies": { "ajv": "^6.14.0", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.3.0", "minimatch": "^3.1.5", "strip-json-comments": "^3.1.1" } }, "sha512-l2Ul9PrHsPCKcEY/ac7VgFj9D80C7S68sOKc618SyHDPK36s1XcFebXY0iTzUVn4Yq+YbwvSnDmCz9yxjX+QrA=="],
|
||||||
|
|
||||||
"@eslint/js": ["@eslint/js@10.0.1", "", { "peerDependencies": { "eslint": "^10.0.0" }, "optionalPeers": ["eslint"] }, "sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA=="],
|
"@eslint/js": ["@eslint/js@10.0.1", "", { "peerDependencies": { "eslint": "^10.0.0" }, "optionalPeers": ["eslint"] }, "sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA=="],
|
||||||
|
|
||||||
"@eslint/object-schema": ["@eslint/object-schema@3.0.5", "", {}, "sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw=="],
|
"@eslint/object-schema": ["@eslint/object-schema@3.0.5", "", {}, "sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw=="],
|
||||||
@@ -934,8 +952,12 @@
|
|||||||
|
|
||||||
"ajv": ["ajv@6.15.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw=="],
|
"ajv": ["ajv@6.15.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw=="],
|
||||||
|
|
||||||
|
"ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
|
||||||
|
|
||||||
"any-promise": ["any-promise@1.3.0", "", {}, "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A=="],
|
"any-promise": ["any-promise@1.3.0", "", {}, "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A=="],
|
||||||
|
|
||||||
|
"argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
|
||||||
|
|
||||||
"asn1js": ["asn1js@3.0.10", "", { "dependencies": { "pvtsutils": "^1.3.6", "pvutils": "^1.1.5", "tslib": "^2.8.1" } }, "sha512-S2s3aOytiKdFRdulw2qPE51MzjzVOisppcVv7jVFR+Kw0kxwvFrDcYA0h7Ndqbmj0HkMIXYWaoj7fli8kgx1eg=="],
|
"asn1js": ["asn1js@3.0.10", "", { "dependencies": { "pvtsutils": "^1.3.6", "pvutils": "^1.1.5", "tslib": "^2.8.1" } }, "sha512-S2s3aOytiKdFRdulw2qPE51MzjzVOisppcVv7jVFR+Kw0kxwvFrDcYA0h7Ndqbmj0HkMIXYWaoj7fli8kgx1eg=="],
|
||||||
|
|
||||||
"auth-showcase": ["auth-showcase@workspace:examples/auth-showcase"],
|
"auth-showcase": ["auth-showcase@workspace:examples/auth-showcase"],
|
||||||
@@ -960,10 +982,18 @@
|
|||||||
|
|
||||||
"cac": ["cac@6.7.14", "", {}, "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ=="],
|
"cac": ["cac@6.7.14", "", {}, "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ=="],
|
||||||
|
|
||||||
|
"callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="],
|
||||||
|
|
||||||
"captcha-showcase": ["captcha-showcase@workspace:examples/captcha-showcase"],
|
"captcha-showcase": ["captcha-showcase@workspace:examples/captcha-showcase"],
|
||||||
|
|
||||||
|
"chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
|
||||||
|
|
||||||
"chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="],
|
"chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="],
|
||||||
|
|
||||||
|
"color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
|
||||||
|
|
||||||
|
"color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
|
||||||
|
|
||||||
"commander": ["commander@4.1.1", "", {}, "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA=="],
|
"commander": ["commander@4.1.1", "", {}, "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA=="],
|
||||||
|
|
||||||
"component-showcase": ["component-showcase@workspace:examples/component-showcase"],
|
"component-showcase": ["component-showcase@workspace:examples/component-showcase"],
|
||||||
@@ -1046,18 +1076,26 @@
|
|||||||
|
|
||||||
"glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="],
|
"glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="],
|
||||||
|
|
||||||
|
"globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="],
|
||||||
|
|
||||||
"graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
|
"graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
|
||||||
|
|
||||||
"happy-dom": ["happy-dom@20.11.1", "", { "dependencies": { "@types/node": ">=20.0.0", "@types/whatwg-mimetype": "^3.0.2", "@types/ws": "^8.18.1", "buffer-image-size": "^0.6.4", "entities": "^7.0.1", "whatwg-mimetype": "^3.0.0", "ws": "^8.21.0" } }, "sha512-XSt8tMzbW9ymE7687xztkO1ckR7qJNQ3LywY9vlYGhGi3zXrGBHuUo2Cl1ztZaICW+1eAGdkLbj6iwVqDT33kg=="],
|
"happy-dom": ["happy-dom@20.11.1", "", { "dependencies": { "@types/node": ">=20.0.0", "@types/whatwg-mimetype": "^3.0.2", "@types/ws": "^8.18.1", "buffer-image-size": "^0.6.4", "entities": "^7.0.1", "whatwg-mimetype": "^3.0.0", "ws": "^8.21.0" } }, "sha512-XSt8tMzbW9ymE7687xztkO1ckR7qJNQ3LywY9vlYGhGi3zXrGBHuUo2Cl1ztZaICW+1eAGdkLbj6iwVqDT33kg=="],
|
||||||
|
|
||||||
|
"has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="],
|
||||||
|
|
||||||
"i18n-showcase": ["i18n-showcase@workspace:examples/i18n-showcase"],
|
"i18n-showcase": ["i18n-showcase@workspace:examples/i18n-showcase"],
|
||||||
|
|
||||||
"ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],
|
"ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],
|
||||||
|
|
||||||
|
"import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="],
|
||||||
|
|
||||||
"import-meta-resolve": ["import-meta-resolve@4.2.0", "", {}, "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg=="],
|
"import-meta-resolve": ["import-meta-resolve@4.2.0", "", {}, "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg=="],
|
||||||
|
|
||||||
"imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="],
|
"imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="],
|
||||||
|
|
||||||
|
"inter-app-api-showcase": ["inter-app-api-showcase@workspace:examples/inter-app-api-showcase"],
|
||||||
|
|
||||||
"is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="],
|
"is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="],
|
||||||
|
|
||||||
"is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="],
|
"is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="],
|
||||||
@@ -1070,6 +1108,8 @@
|
|||||||
|
|
||||||
"joycon": ["joycon@3.1.1", "", {}, "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw=="],
|
"joycon": ["joycon@3.1.1", "", {}, "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw=="],
|
||||||
|
|
||||||
|
"js-yaml": ["js-yaml@4.3.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ=="],
|
||||||
|
|
||||||
"json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="],
|
"json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="],
|
||||||
|
|
||||||
"json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="],
|
"json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="],
|
||||||
@@ -1112,6 +1152,8 @@
|
|||||||
|
|
||||||
"locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="],
|
"locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="],
|
||||||
|
|
||||||
|
"lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="],
|
||||||
|
|
||||||
"magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="],
|
"magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="],
|
||||||
|
|
||||||
"mdn-data": ["mdn-data@2.27.1", "", {}, "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ=="],
|
"mdn-data": ["mdn-data@2.27.1", "", {}, "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ=="],
|
||||||
@@ -1146,6 +1188,8 @@
|
|||||||
|
|
||||||
"package-manager-detector": ["package-manager-detector@1.8.0", "", {}, "sha512-yQA4H19AmPEoMUeavPMDIe1higySl/gH/yaQrkT/s07Qp+7pp2hYz30N3z2l5BkjVkF9Ow6o0wjJamm2y7Sn0A=="],
|
"package-manager-detector": ["package-manager-detector@1.8.0", "", {}, "sha512-yQA4H19AmPEoMUeavPMDIe1higySl/gH/yaQrkT/s07Qp+7pp2hYz30N3z2l5BkjVkF9Ow6o0wjJamm2y7Sn0A=="],
|
||||||
|
|
||||||
|
"parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="],
|
||||||
|
|
||||||
"path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="],
|
"path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="],
|
||||||
|
|
||||||
"path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
|
"path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
|
||||||
@@ -1196,8 +1240,12 @@
|
|||||||
|
|
||||||
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
|
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
|
||||||
|
|
||||||
|
"strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="],
|
||||||
|
|
||||||
"sucrase": ["sucrase@3.35.1", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", "commander": "^4.0.0", "lines-and-columns": "^1.1.6", "mz": "^2.7.0", "pirates": "^4.0.1", "tinyglobby": "^0.2.11", "ts-interface-checker": "^0.1.9" }, "bin": { "sucrase": "bin/sucrase", "sucrase-node": "bin/sucrase-node" } }, "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw=="],
|
"sucrase": ["sucrase@3.35.1", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", "commander": "^4.0.0", "lines-and-columns": "^1.1.6", "mz": "^2.7.0", "pirates": "^4.0.1", "tinyglobby": "^0.2.11", "ts-interface-checker": "^0.1.9" }, "bin": { "sucrase": "bin/sucrase", "sucrase-node": "bin/sucrase-node" } }, "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw=="],
|
||||||
|
|
||||||
|
"supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
|
||||||
|
|
||||||
"svgo": ["svgo@4.0.2", "", { "dependencies": { "commander": "^11.1.0", "css-select": "^5.1.0", "css-tree": "^3.0.1", "css-what": "^6.1.0", "csso": "^5.0.5", "picocolors": "^1.1.1", "sax": "^1.5.0" }, "bin": "./bin/svgo.js" }, "sha512-ekx94z1rRc5LDi6oSUaeRnYhd0UOJxdtQCL2rF8xpWxD3TPAsISWOrxezqGovqS38GRZOdpDfvQe3ts6F7nsng=="],
|
"svgo": ["svgo@4.0.2", "", { "dependencies": { "commander": "^11.1.0", "css-select": "^5.1.0", "css-tree": "^3.0.1", "css-what": "^6.1.0", "csso": "^5.0.5", "picocolors": "^1.1.1", "sax": "^1.5.0" }, "bin": "./bin/svgo.js" }, "sha512-ekx94z1rRc5LDi6oSUaeRnYhd0UOJxdtQCL2rF8xpWxD3TPAsISWOrxezqGovqS38GRZOdpDfvQe3ts6F7nsng=="],
|
||||||
|
|
||||||
"tailwindcss": ["tailwindcss@4.3.2", "", {}, "sha512-WtctNNSH8A9jlMIqxzuYumOHU5uGZyRv0Q5svQl+oEPy5w84YpBxdb7MdqyiSPQge5jTJ6zFQLq0PFygdccSBA=="],
|
"tailwindcss": ["tailwindcss@4.3.2", "", {}, "sha512-WtctNNSH8A9jlMIqxzuYumOHU5uGZyRv0Q5svQl+oEPy5w84YpBxdb7MdqyiSPQge5jTJ6zFQLq0PFygdccSBA=="],
|
||||||
@@ -1252,6 +1300,10 @@
|
|||||||
|
|
||||||
"@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="],
|
"@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="],
|
||||||
|
|
||||||
|
"@eslint/eslintrc/espree": ["espree@10.4.0", "", { "dependencies": { "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.1" } }, "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ=="],
|
||||||
|
|
||||||
|
"@eslint/eslintrc/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.11.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.2", "tslib": "^2.4.0" }, "bundled": true }, "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ=="],
|
"@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.11.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.2", "tslib": "^2.4.0" }, "bundled": true }, "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.11.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw=="],
|
"@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.11.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw=="],
|
||||||
@@ -1270,6 +1322,14 @@
|
|||||||
|
|
||||||
"dom-serializer/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
|
"dom-serializer/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
|
||||||
|
|
||||||
|
"import-fresh/resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="],
|
||||||
|
|
||||||
|
"inter-app-api-showcase/@eslint/js": ["@eslint/js@9.39.5", "", {}, "sha512-QywQuszQh77pIXCsq998c8hbhSTI/azTty1Z6N53dmAudKHhy573j3yvRLsX2BSp8YpLtoCEG8E9DJe+8zUh4A=="],
|
||||||
|
|
||||||
|
"inter-app-api-showcase/eslint": ["eslint@9.39.5", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.2", "@eslint/config-helpers": "^0.4.2", "@eslint/core": "^0.17.0", "@eslint/eslintrc": "^3.3.6", "@eslint/js": "9.39.5", "@eslint/plugin-kit": "^0.4.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "ajv": "^6.14.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.4.0", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.5", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-DgZS62aPLXKlnxILS/AYCoRvHaZeXceIzlXPkkGGzJWSow1aEk0lbTlxUSlyjC8jcaKxAdOnTDz+o1JFSBsyjw=="],
|
||||||
|
|
||||||
|
"inter-app-api-showcase/typescript-eslint": ["typescript-eslint@8.66.0", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.66.0", "@typescript-eslint/parser": "8.66.0", "@typescript-eslint/typescript-estree": "8.66.0", "@typescript-eslint/utils": "8.66.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-QlEbBPz/RuJ1XUHj29nm3t0F/O/cSlEnntozqPOYHnnTGAXFamnMBu5i9Vn6vhUPHGAjR+Vl+5J8vPN/BMUrJw=="],
|
||||||
|
|
||||||
"lightningcss/detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
|
"lightningcss/detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
|
||||||
|
|
||||||
"micromatch/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="],
|
"micromatch/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="],
|
||||||
@@ -1278,6 +1338,68 @@
|
|||||||
|
|
||||||
"tsyringe/tslib": ["tslib@1.14.1", "", {}, "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="],
|
"tsyringe/tslib": ["tslib@1.14.1", "", {}, "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="],
|
||||||
|
|
||||||
|
"@eslint/eslintrc/espree/eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="],
|
||||||
|
|
||||||
"csso/css-tree/mdn-data": ["mdn-data@2.0.28", "", {}, "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g=="],
|
"csso/css-tree/mdn-data": ["mdn-data@2.0.28", "", {}, "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g=="],
|
||||||
|
|
||||||
|
"inter-app-api-showcase/eslint/@eslint/config-array": ["@eslint/config-array@0.21.2", "", { "dependencies": { "@eslint/object-schema": "^2.1.7", "debug": "^4.3.1", "minimatch": "^3.1.5" } }, "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw=="],
|
||||||
|
|
||||||
|
"inter-app-api-showcase/eslint/@eslint/config-helpers": ["@eslint/config-helpers@0.4.2", "", { "dependencies": { "@eslint/core": "^0.17.0" } }, "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw=="],
|
||||||
|
|
||||||
|
"inter-app-api-showcase/eslint/@eslint/core": ["@eslint/core@0.17.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ=="],
|
||||||
|
|
||||||
|
"inter-app-api-showcase/eslint/@eslint/plugin-kit": ["@eslint/plugin-kit@0.4.1", "", { "dependencies": { "@eslint/core": "^0.17.0", "levn": "^0.4.1" } }, "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA=="],
|
||||||
|
|
||||||
|
"inter-app-api-showcase/eslint/eslint-scope": ["eslint-scope@8.4.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg=="],
|
||||||
|
|
||||||
|
"inter-app-api-showcase/eslint/eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="],
|
||||||
|
|
||||||
|
"inter-app-api-showcase/eslint/espree": ["espree@10.4.0", "", { "dependencies": { "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.1" } }, "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ=="],
|
||||||
|
|
||||||
|
"inter-app-api-showcase/eslint/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="],
|
||||||
|
|
||||||
|
"inter-app-api-showcase/typescript-eslint/@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.66.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.12.2", "@typescript-eslint/scope-manager": "8.66.0", "@typescript-eslint/type-utils": "8.66.0", "@typescript-eslint/utils": "8.66.0", "@typescript-eslint/visitor-keys": "8.66.0", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.66.0", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-p088eaGrzYz1s+7cov0aMOCkNGTJlVxF4jgubf28c8L0Cv9Rloj8YBHnv4hXLq6IIEE1AsjNWavO+k+8kP2Y0A=="],
|
||||||
|
|
||||||
|
"inter-app-api-showcase/typescript-eslint/@typescript-eslint/parser": ["@typescript-eslint/parser@8.66.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.66.0", "@typescript-eslint/types": "8.66.0", "@typescript-eslint/typescript-estree": "8.66.0", "@typescript-eslint/visitor-keys": "8.66.0", "debug": "^4.4.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-X6ypGChaWYk6PBtUg2BwuTZEFFcHJAtGTVJ9/lCTOufhZ4i9fNolQNnktq+kkMCwMj7V8Svsq7+TxSDslmhE0g=="],
|
||||||
|
|
||||||
|
"inter-app-api-showcase/typescript-eslint/@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.66.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.66.0", "@typescript-eslint/tsconfig-utils": "8.66.0", "@typescript-eslint/types": "8.66.0", "@typescript-eslint/visitor-keys": "8.66.0", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-8/x4INiiQb10jGgXYD7116/zQ+OL84ZIFn0za68wwFHCanT/VLbBEroWht8RV8fn0/ZCAoazHLQgwUC0UQcDfg=="],
|
||||||
|
|
||||||
|
"inter-app-api-showcase/typescript-eslint/@typescript-eslint/utils": ["@typescript-eslint/utils@8.66.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.66.0", "@typescript-eslint/types": "8.66.0", "@typescript-eslint/typescript-estree": "8.66.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-jasearZPolBw5NJNYGMwxzHMF83niVWmMU1VdHzG1CyfI2VS7f7nZltnKtHcg20hW+7Uo5GfK4MeDPoU3qI8EA=="],
|
||||||
|
|
||||||
|
"inter-app-api-showcase/eslint/@eslint/config-array/@eslint/object-schema": ["@eslint/object-schema@2.1.7", "", {}, "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA=="],
|
||||||
|
|
||||||
|
"inter-app-api-showcase/typescript-eslint/@typescript-eslint/eslint-plugin/@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.66.0", "", { "dependencies": { "@typescript-eslint/types": "8.66.0", "@typescript-eslint/visitor-keys": "8.66.0" } }, "sha512-8TGcH25j9zqJ/IULB/ppyhRvxA8QYfFEZ7nfbg6/BN9spDgb8fPWQXlE5l8TWBL50EtUx007uZ1o9VOwrq2/9g=="],
|
||||||
|
|
||||||
|
"inter-app-api-showcase/typescript-eslint/@typescript-eslint/eslint-plugin/@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.66.0", "", { "dependencies": { "@typescript-eslint/types": "8.66.0", "@typescript-eslint/typescript-estree": "8.66.0", "@typescript-eslint/utils": "8.66.0", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-LG2dWfjZQQp0ADtAu/EWJVayefGL2UEZ3CDeI44D9v3rXB/WYUqE/jpO28KrEKul5AySrmI+Zh1v6v+xW2U9+g=="],
|
||||||
|
|
||||||
|
"inter-app-api-showcase/typescript-eslint/@typescript-eslint/eslint-plugin/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.66.0", "", { "dependencies": { "@typescript-eslint/types": "8.66.0", "eslint-visitor-keys": "^5.0.0" } }, "sha512-dkKR8q+lKciskj1Y3vthHktl+3cMLWGyVUP23bRiPZ5O9BRT++4EqDDV+TVeIKBL1VXVEqrJlz8MYbcnvJcAlg=="],
|
||||||
|
|
||||||
|
"inter-app-api-showcase/typescript-eslint/@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="],
|
||||||
|
|
||||||
|
"inter-app-api-showcase/typescript-eslint/@typescript-eslint/parser/@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.66.0", "", { "dependencies": { "@typescript-eslint/types": "8.66.0", "@typescript-eslint/visitor-keys": "8.66.0" } }, "sha512-8TGcH25j9zqJ/IULB/ppyhRvxA8QYfFEZ7nfbg6/BN9spDgb8fPWQXlE5l8TWBL50EtUx007uZ1o9VOwrq2/9g=="],
|
||||||
|
|
||||||
|
"inter-app-api-showcase/typescript-eslint/@typescript-eslint/parser/@typescript-eslint/types": ["@typescript-eslint/types@8.66.0", "", {}, "sha512-H6gcYaSDOyvL3AD/jHUtUFo2jqGgn/F6nuyuZSu0QTesxL+cP4dQoIMrODRofuJC09g64+WgZ6tE19Y1N2YIFQ=="],
|
||||||
|
|
||||||
|
"inter-app-api-showcase/typescript-eslint/@typescript-eslint/parser/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.66.0", "", { "dependencies": { "@typescript-eslint/types": "8.66.0", "eslint-visitor-keys": "^5.0.0" } }, "sha512-dkKR8q+lKciskj1Y3vthHktl+3cMLWGyVUP23bRiPZ5O9BRT++4EqDDV+TVeIKBL1VXVEqrJlz8MYbcnvJcAlg=="],
|
||||||
|
|
||||||
|
"inter-app-api-showcase/typescript-eslint/@typescript-eslint/typescript-estree/@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.66.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.66.0", "@typescript-eslint/types": "^8.66.0", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-7MthGPTt4BP69lSryqpqq8HQqxuzynssckL/jyDyk3+TNMQ3y2jFWkptCrktWvBrP+EH787Nl5N5Qpw7WZg+5g=="],
|
||||||
|
|
||||||
|
"inter-app-api-showcase/typescript-eslint/@typescript-eslint/typescript-estree/@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.66.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-9D5gLYZG4rOjcoag8MQ/fWI8WqA9wcPDyOGyWtWFhvM1lHRbliqUSPIY5J3zqCU1tvSwzXxnnjhQhz5Ne7mJ4g=="],
|
||||||
|
|
||||||
|
"inter-app-api-showcase/typescript-eslint/@typescript-eslint/typescript-estree/@typescript-eslint/types": ["@typescript-eslint/types@8.66.0", "", {}, "sha512-H6gcYaSDOyvL3AD/jHUtUFo2jqGgn/F6nuyuZSu0QTesxL+cP4dQoIMrODRofuJC09g64+WgZ6tE19Y1N2YIFQ=="],
|
||||||
|
|
||||||
|
"inter-app-api-showcase/typescript-eslint/@typescript-eslint/typescript-estree/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.66.0", "", { "dependencies": { "@typescript-eslint/types": "8.66.0", "eslint-visitor-keys": "^5.0.0" } }, "sha512-dkKR8q+lKciskj1Y3vthHktl+3cMLWGyVUP23bRiPZ5O9BRT++4EqDDV+TVeIKBL1VXVEqrJlz8MYbcnvJcAlg=="],
|
||||||
|
|
||||||
|
"inter-app-api-showcase/typescript-eslint/@typescript-eslint/utils/@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.66.0", "", { "dependencies": { "@typescript-eslint/types": "8.66.0", "@typescript-eslint/visitor-keys": "8.66.0" } }, "sha512-8TGcH25j9zqJ/IULB/ppyhRvxA8QYfFEZ7nfbg6/BN9spDgb8fPWQXlE5l8TWBL50EtUx007uZ1o9VOwrq2/9g=="],
|
||||||
|
|
||||||
|
"inter-app-api-showcase/typescript-eslint/@typescript-eslint/utils/@typescript-eslint/types": ["@typescript-eslint/types@8.66.0", "", {}, "sha512-H6gcYaSDOyvL3AD/jHUtUFo2jqGgn/F6nuyuZSu0QTesxL+cP4dQoIMrODRofuJC09g64+WgZ6tE19Y1N2YIFQ=="],
|
||||||
|
|
||||||
|
"inter-app-api-showcase/typescript-eslint/@typescript-eslint/eslint-plugin/@typescript-eslint/scope-manager/@typescript-eslint/types": ["@typescript-eslint/types@8.66.0", "", {}, "sha512-H6gcYaSDOyvL3AD/jHUtUFo2jqGgn/F6nuyuZSu0QTesxL+cP4dQoIMrODRofuJC09g64+WgZ6tE19Y1N2YIFQ=="],
|
||||||
|
|
||||||
|
"inter-app-api-showcase/typescript-eslint/@typescript-eslint/eslint-plugin/@typescript-eslint/type-utils/@typescript-eslint/types": ["@typescript-eslint/types@8.66.0", "", {}, "sha512-H6gcYaSDOyvL3AD/jHUtUFo2jqGgn/F6nuyuZSu0QTesxL+cP4dQoIMrODRofuJC09g64+WgZ6tE19Y1N2YIFQ=="],
|
||||||
|
|
||||||
|
"inter-app-api-showcase/typescript-eslint/@typescript-eslint/eslint-plugin/@typescript-eslint/visitor-keys/@typescript-eslint/types": ["@typescript-eslint/types@8.66.0", "", {}, "sha512-H6gcYaSDOyvL3AD/jHUtUFo2jqGgn/F6nuyuZSu0QTesxL+cP4dQoIMrODRofuJC09g64+WgZ6tE19Y1N2YIFQ=="],
|
||||||
|
|
||||||
|
"inter-app-api-showcase/typescript-eslint/@typescript-eslint/utils/@typescript-eslint/scope-manager/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.66.0", "", { "dependencies": { "@typescript-eslint/types": "8.66.0", "eslint-visitor-keys": "^5.0.0" } }, "sha512-dkKR8q+lKciskj1Y3vthHktl+3cMLWGyVUP23bRiPZ5O9BRT++4EqDDV+TVeIKBL1VXVEqrJlz8MYbcnvJcAlg=="],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,835 @@
|
|||||||
|
# Framework remediation plan
|
||||||
|
|
||||||
|
Written 2026-08-09, after the 0.8.6 release. Every number here was measured
|
||||||
|
against the tree at commit `7a2b5865`, not estimated. Where a cause is not yet
|
||||||
|
proven the item says so and makes proving it step one — nothing in this document
|
||||||
|
should be implemented on the strength of a guess.
|
||||||
|
|
||||||
|
Each work item has the same four fields:
|
||||||
|
|
||||||
|
- **Issue** — what is wrong, stated so it can be disagreed with.
|
||||||
|
- **Evidence** — how we know, with the file or the measurement.
|
||||||
|
- **Change** — what to do.
|
||||||
|
- **How to test** — the check that fails before and passes after. If an item's
|
||||||
|
test cannot fail before the change, the test is wrong; see the note on
|
||||||
|
vacuous gates in §0.2.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 0. Standing conventions
|
||||||
|
|
||||||
|
These are not tasks. They are the rules the tasks below are written against, and
|
||||||
|
they apply to all new work from now on.
|
||||||
|
|
||||||
|
### 0.1 A component owns everything it needs
|
||||||
|
|
||||||
|
**Every `.wrn` component is self-contained.** Markup, behaviour and styles live
|
||||||
|
in that one file. A component that needs a rule writes it in its own `style {}`
|
||||||
|
block, scoped to its own classes.
|
||||||
|
|
||||||
|
`ui.css` holds **global styles only** — resets, tokens, base element styling and
|
||||||
|
genuinely cross-cutting primitives. It is not a place to put component rules,
|
||||||
|
and no new component rule may be added to it. The reason is delivery: a
|
||||||
|
component's own styles ship only when that component renders, while `ui.css` is
|
||||||
|
served whole to every page on the site. See §4.1 for the migration and the
|
||||||
|
numbers.
|
||||||
|
|
||||||
|
Practical rules:
|
||||||
|
|
||||||
|
- CSS comments in a `style {}` block are `/* */` only. `//` is not a CSS comment
|
||||||
|
and silently swallows the rule that follows it.
|
||||||
|
- Style the component's own BEM classes (`wire-thing`, `wire-thing__part`).
|
||||||
|
Variants are data attributes: `[data-variant="soft"]`, not a class explosion.
|
||||||
|
- No Tailwind utility classes in component markup. See §4.3.
|
||||||
|
|
||||||
|
### 0.2 A test that cannot fail is not a test
|
||||||
|
|
||||||
|
Two gates in this repo passed for months while testing nothing, because both
|
||||||
|
were written against `getBoundingClientRect()`, which returns zeros in
|
||||||
|
happy-dom. The 0.8.5 focus trap had no coverage at all as a result.
|
||||||
|
|
||||||
|
**Before committing any test in this plan, delete the fix, watch the test fail,
|
||||||
|
then restore the fix.** If it passes with the fix removed, it is measuring
|
||||||
|
nothing. Never gate testable behaviour on measured geometry.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Bugs from this session
|
||||||
|
|
||||||
|
All five are **fixed and shipped in 0.8.6**. They are recorded here because each
|
||||||
|
one has a permanent guard that must not be removed, and because the pattern they
|
||||||
|
share is the subject of §2.
|
||||||
|
|
||||||
|
### 1.1 camelCase outputs never reached a parent binding — FIXED
|
||||||
|
|
||||||
|
**Issue.** HTML lowercases attribute names, so a parent writing `@sizeChange`
|
||||||
|
registered a handler under `sizechange`, while the component emitted
|
||||||
|
`sizeChange`. The registry lookup missed, fell through to a DOM dispatch, and
|
||||||
|
the parent binding was never invoked. No error at either end.
|
||||||
|
|
||||||
|
**Evidence.** All 17 camelCase outputs in the library were undeliverable:
|
||||||
|
`DataTable.pageChange`, `DataTable.rowClick`, `Map.markerClick`,
|
||||||
|
`ChatBubble.messageClick`, `LayoutSplitter.sizeChange`, the four `carousel.*`
|
||||||
|
and four `DragAndDrop.*` names, and the rest. Confirmed in a browser by reading
|
||||||
|
`__wrnexusOutputHandlers` off the component root and seeing the key casing.
|
||||||
|
|
||||||
|
**Change.** Done — `invokeComponentOutput` in
|
||||||
|
`packages/csr/src/reactive-runtime.ts` now falls back to a case-insensitive
|
||||||
|
lookup.
|
||||||
|
|
||||||
|
**How to test.**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bun test packages/csr/test/reactive.test.ts -t "camelCase output"
|
||||||
|
```
|
||||||
|
|
||||||
|
Verified failing with the fallback removed. Keep it that way.
|
||||||
|
|
||||||
|
### 1.2 Eighteen components emitted into the void — FIXED
|
||||||
|
|
||||||
|
**Issue.** An output only reaches a parent `@binding` when the component calls
|
||||||
|
`output.<name>()`. The runtime resolves parent handlers from a registry that
|
||||||
|
only `invokeComponentOutput` reads, so a component dispatching its own
|
||||||
|
`CustomEvent` — even a bubbling one on its own root — emits to nobody.
|
||||||
|
|
||||||
|
**Evidence.** 18 components did this. Card, Footer, Breadcrumb, Accordion,
|
||||||
|
alert, Badge, AnnouncementBar, AvatarGroup, ToggleCount and InputNumber were
|
||||||
|
converted; Marquee, Map, Timeline, List and SearchBox additionally had to
|
||||||
|
_declare_ the outputs they were already firing.
|
||||||
|
|
||||||
|
**Change.** Done. Note the deliberate exception: dispatching on `window` is
|
||||||
|
still correct and is left alone — that is how Toaster, Modal and DataTable
|
||||||
|
signal across component boundaries, where there is no parent binding to reach.
|
||||||
|
|
||||||
|
**How to test.**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bun test packages/ui/test/ui.test.ts -t "hand-built CustomEvent"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 1.3 Ten theme tokens were referenced and never defined — FIXED
|
||||||
|
|
||||||
|
**Issue.** An undefined custom property does not warn; it resolves to nothing.
|
||||||
|
Focus rings drew with no colour in 14 components, every soft surface rendered
|
||||||
|
transparent in 27.
|
||||||
|
|
||||||
|
**Change.** Done — derived in `packages/styles/src/theme.ts`. Two traps worth
|
||||||
|
remembering: a check that reads the theme _source_ produces about a dozen false
|
||||||
|
positives because most tokens are generated per palette, so any such check must
|
||||||
|
read the **rendered** CSS; and the semantic spread must sit _before_ the
|
||||||
|
primary/secondary palette entries or it overrides them.
|
||||||
|
|
||||||
|
**How to test.** Load a page, then in the console collect every `var(--wire-*)`
|
||||||
|
referenced by stylesheet rules and check each against
|
||||||
|
`getComputedStyle(document.documentElement)`. Expect 38 referenced, 0 undefined.
|
||||||
|
|
||||||
|
### 1.4 The modal focus trap had no coverage — FIXED
|
||||||
|
|
||||||
|
**Issue.** `isDialogVisible` and `focusableWithin` both gated on
|
||||||
|
`getBoundingClientRect()`, which is all zeros in happy-dom. The trap never ran
|
||||||
|
under test.
|
||||||
|
|
||||||
|
**Change.** Done — both read markers instead. One regression to remember: the
|
||||||
|
first fix used `data-show`, which broke Drawer, because a Drawer _animates_ open
|
||||||
|
and so cannot use `data-show`; every closed Drawer then looked open and held
|
||||||
|
`body { overflow: hidden }` forever. It reads `data-open` now.
|
||||||
|
|
||||||
|
**How to test.** `bun test packages/csr` — the dialog tests must fail if the
|
||||||
|
marker checks are reverted to geometry.
|
||||||
|
|
||||||
|
### 1.5 Roving focus matched `="false"` — FIXED
|
||||||
|
|
||||||
|
**Issue.** Attribute-presence selectors match any value, including `"false"`, so
|
||||||
|
read-only Steppers captured arrow keys from the page.
|
||||||
|
|
||||||
|
**Change.** Done — `rovingItemOff` treats bare as on and `"false"` as off.
|
||||||
|
|
||||||
|
**How to test.** `bun test packages/csr` roving cases; a read-only Stepper must
|
||||||
|
not consume `ArrowRight`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. The model is incomplete
|
||||||
|
|
||||||
|
This section is the real work. These are capability gaps, not defects, and they
|
||||||
|
are what currently limits what anyone can build. **§2.1 is the highest-value
|
||||||
|
item in this entire document.**
|
||||||
|
|
||||||
|
### 2.1 The framework fails silently, everywhere
|
||||||
|
|
||||||
|
**Issue.** Nothing in §1 produced a single diagnostic at any layer. That is not
|
||||||
|
five unlucky bugs; it is a systemic property. The failure mode is always
|
||||||
|
"nothing happens", which is the most expensive kind to debug because a bug is
|
||||||
|
indistinguishable from something you configured wrong.
|
||||||
|
|
||||||
|
**Evidence.** `packages/csr/src/reactive-runtime.ts` has 55 `catch` blocks, 11
|
||||||
|
of which swallow entirely, and 18 `console.error`/`console.warn` calls across
|
||||||
|
~70 kB of runtime. Undefined theme token → renders nothing. Wrong output casing
|
||||||
|
→ delivers nothing. Deferred state write → dropped. Component in a slot →
|
||||||
|
dropped. Object prop written inline → parsed as interpolation. None warn.
|
||||||
|
|
||||||
|
**Change.** Add a **dev-mode diagnostic layer**, stripped from production
|
||||||
|
builds. It should warn on at least:
|
||||||
|
|
||||||
|
1. `output.<name>()` called with no handler registered **and** no listener for
|
||||||
|
the event — include the registry keys actually present, which is exactly what
|
||||||
|
would have made §1.1 a five-minute bug.
|
||||||
|
2. A `@binding` naming a function that does not exist in scope.
|
||||||
|
3. A `var(--wire-*)` referenced by a component but absent from the rendered
|
||||||
|
theme.
|
||||||
|
4. A state write discarded because it happened after the client function
|
||||||
|
returned (see §2.2).
|
||||||
|
5. A component tag dropped during slot flattening (see §2.4).
|
||||||
|
6. A prop declared as an object or array that arrived as an unparsed string.
|
||||||
|
|
||||||
|
Gate it on `process.env.NODE_ENV !== "production"` so the production bundle is
|
||||||
|
byte-identical to today. Route everything through one `warnOnce(code, message)`
|
||||||
|
helper with stable `WRN-` codes, so warnings are greppable and documentable and
|
||||||
|
a loop cannot spam the console.
|
||||||
|
|
||||||
|
**How to test.** A test per diagnostic that asserts the warning fires, plus one
|
||||||
|
asserting the production build contains none of them:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bun test packages/csr/test/diagnostics.test.ts
|
||||||
|
bun run build && grep -c "WRN-DEV-" examples/basic-app/dist/reactive.js # expect 0
|
||||||
|
```
|
||||||
|
|
||||||
|
Add a runtime size assertion so the production bundle does not grow: it is
|
||||||
|
69,947 bytes minified today.
|
||||||
|
|
||||||
|
### 2.2 Deferred state writes are silently dropped
|
||||||
|
|
||||||
|
**Issue.** State written after a client function returns — in a `setTimeout`, a
|
||||||
|
promise callback, an observer, a `pointermove` — is discarded. The peer-function
|
||||||
|
wrapper flushes the entry-time snapshot, so the later write is simply lost.
|
||||||
|
|
||||||
|
**Evidence.** This is why the focus trap, scrollspy, roving focus and the
|
||||||
|
splitter all had to be written as bespoke controllers inside the runtime.
|
||||||
|
Component-specific controllers are roughly 18% of `reactive.js` — that is a
|
||||||
|
model limitation being paid for in bundle size.
|
||||||
|
|
||||||
|
**Change.** Two parts, in order.
|
||||||
|
|
||||||
|
1. **Diagnose it** (part of §2.1). A dropped write must warn with the state key
|
||||||
|
and the function name. Cheap, and it stops the silent-loss class immediately.
|
||||||
|
2. **Support it.** Let a client function return a promise, or expose an explicit
|
||||||
|
`commit()`, so async writes reach the scope. This is the design decision —
|
||||||
|
it wants a short written proposal before implementation, because it
|
||||||
|
interacts with re-render batching.
|
||||||
|
|
||||||
|
**How to test.** A test where a client function writes state inside a
|
||||||
|
`setTimeout` and the DOM reflects it after the timer. It must fail today.
|
||||||
|
|
||||||
|
### 2.3 Props and slot content render once
|
||||||
|
|
||||||
|
**Issue.** Component props and slot content do not track page state. The
|
||||||
|
controlled-component pattern does not work at all: passing `value={pageState}`
|
||||||
|
renders the initial value and never updates.
|
||||||
|
|
||||||
|
**Why it matters most.** This is the biggest ceiling in the framework. It means
|
||||||
|
composition breaks down exactly where a component library needs it — a parent
|
||||||
|
cannot drive a child. Every workaround today is "hoist into page state and
|
||||||
|
re-render", which does not compose.
|
||||||
|
|
||||||
|
**Change.** Make prop expressions reactive bindings rather than one-time
|
||||||
|
interpolations, the way attribute bindings already work (`data-wrn-bind-*`).
|
||||||
|
The mechanism exists for attributes; extend it to component props.
|
||||||
|
|
||||||
|
If there is a hard reason this cannot work, **document that reason in the
|
||||||
|
component authoring guide** and give people a supported pattern instead. What
|
||||||
|
is not acceptable is the current state, where it looks like it should work and
|
||||||
|
quietly doesn't.
|
||||||
|
|
||||||
|
**How to test.** A page with `state n`, a component bound to `value={n}`, and a
|
||||||
|
button incrementing `n`; the component's rendered output must follow. Must fail
|
||||||
|
today.
|
||||||
|
|
||||||
|
### 2.4 A component tag inside another component's slot is dropped
|
||||||
|
|
||||||
|
**Issue.** Nesting a component tag in another component's slot drops the tag and
|
||||||
|
leaves its children orphaned.
|
||||||
|
|
||||||
|
**Change.** Fix slot flattening to preserve nested component boundaries. Until
|
||||||
|
it is fixed, emit the §2.1 diagnostic — a dropped component must never be
|
||||||
|
silent.
|
||||||
|
|
||||||
|
**How to test.** Render `<Card><Badge label="x" /></Card>` and assert the Badge
|
||||||
|
root element exists in the output. Must fail today.
|
||||||
|
|
||||||
|
### 2.5 Object props must be hand-hoisted
|
||||||
|
|
||||||
|
**Issue.** An object or array prop written inline in an attribute is read as
|
||||||
|
interpolation. Three encodings were tried this session and all failed: bare
|
||||||
|
`{}` produced a 500, `({})` made `JSON.parse` throw so demos rendered silently
|
||||||
|
empty, and entity-escaping failed because the compiler passes attributes
|
||||||
|
undecoded. The only thing that works is hoisting to page state with
|
||||||
|
`JSON.parse`.
|
||||||
|
|
||||||
|
**Change.** Either support inline object literals in prop position, or reject
|
||||||
|
them at **compile time** with a message naming the prop and showing the hoist
|
||||||
|
pattern. A 500 at runtime and a silently empty component are both unacceptable
|
||||||
|
outcomes for a plain authoring mistake.
|
||||||
|
|
||||||
|
**How to test.** A compiler test asserting the specific diagnostic for
|
||||||
|
`items={{ a: 1 }}`, and one asserting the hoisted form still compiles.
|
||||||
|
|
||||||
|
### 2.6 i18n text is not server-rendered
|
||||||
|
|
||||||
|
**Issue.** Translated text ships as empty spans and is filled after hydration.
|
||||||
|
Navigation is blank until the runtime loads.
|
||||||
|
|
||||||
|
**Why it matters.** This is an SSR-first framework failing to server-render
|
||||||
|
text. It is an SEO problem, a layout-shift problem, and it undercuts the
|
||||||
|
framework's central claim.
|
||||||
|
|
||||||
|
**Change.** Resolve the active locale during SSR and emit the translated text
|
||||||
|
into the HTML, keeping the client path for locale switches.
|
||||||
|
|
||||||
|
**How to test.**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -s http://localhost:3520/ | grep -c "Navigation" # expect > 0
|
||||||
|
```
|
||||||
|
|
||||||
|
Assert against the raw server response with JavaScript disabled — not the
|
||||||
|
hydrated DOM, which already looks correct today.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Smaller but real
|
||||||
|
|
||||||
|
### 3.1 Twenty-two outputs still have no emitter
|
||||||
|
|
||||||
|
Everything needed to do this in one pass is in this section: what was already
|
||||||
|
done, what is left, and which disposition each remaining component takes.
|
||||||
|
|
||||||
|
#### 3.1.1 Already done in 0.8.6 — do not redo
|
||||||
|
|
||||||
|
Fifteen components were fixed. Ten had outputs that were **declared but
|
||||||
|
miswired** — they dispatched a hand-built `CustomEvent` instead of calling
|
||||||
|
`output.*`, so the declaration was right and only the emit was wrong. Nothing
|
||||||
|
was added to these; they were rewired:
|
||||||
|
|
||||||
|
> Card, Footer, Breadcrumb, Accordion, alert, Badge, AnnouncementBar,
|
||||||
|
> AvatarGroup, ToggleCount, InputNumber
|
||||||
|
|
||||||
|
Five more were **firing events they had never declared**, so no caller could
|
||||||
|
bind to them at all. These gained an `outputs {}` block _and_ were routed
|
||||||
|
through `output.*`:
|
||||||
|
|
||||||
|
| Component | Outputs added | Fires when |
|
||||||
|
| ----------- | ------------------------------- | ------------------------------------------------------ |
|
||||||
|
| `Map` | `markerClick`, `select`, `zoom` | marker pressed (both names fire); zoom in/out pressed |
|
||||||
|
| `SearchBox` | `search`, `clear` | form submitted; clear button pressed |
|
||||||
|
| `Marquee` | `pause`, `resume` | hover, focus, or the pause/play button |
|
||||||
|
| `List` | `select` | item pressed — **only items with an `href`**, see §3.4 |
|
||||||
|
| `Timeline` | `select` | item pressed |
|
||||||
|
|
||||||
|
Verified firing in a browser: `SearchBox`, `Marquee`, `List`, `Timeline`, plus
|
||||||
|
all ten rewired components. **`Map` was not verified** — its three outputs were
|
||||||
|
converted by the same mechanical change and the build passes, but no Map was on
|
||||||
|
the probe page. Put one on a page and confirm before treating it as done.
|
||||||
|
|
||||||
|
#### 3.1.2 What is left — 22 outputs, 9 components
|
||||||
|
|
||||||
|
**Issue.** These are not miswired. All nine are **pure scaffolds**: roughly 25
|
||||||
|
lines each, zero state, zero functions, no style block, no event handlers. They
|
||||||
|
are markup shells that declare outputs. "Add an emitter" is not the work — there
|
||||||
|
is nothing to emit from.
|
||||||
|
|
||||||
|
**The finding that should drive the decision: most of them duplicate a component
|
||||||
|
that already works.** This is the Table situation again, where Table was removed
|
||||||
|
because DataTable superseded it.
|
||||||
|
|
||||||
|
| Scaffold | Dead outputs | Already works elsewhere |
|
||||||
|
| --------------------- | ----------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
|
||||||
|
| `FileUpload` | upload, progress, success, cancel, remove | `FileInput` (3 fns, 4 outputs) + `FileUploadProgress` (5 fns, 3 outputs), plus the `@wrnexus/uploader` package |
|
||||||
|
| `ToastNotifications` | add, dismiss, clear, action | `Toaster` (961 lines, 40 fns, fully built) |
|
||||||
|
| `Toast` | dismiss | `Toaster`, same |
|
||||||
|
| `AdvancedDatePicker` | open, close, clear | `DatePicker` (8 fns, 8 outputs) |
|
||||||
|
| `AdvancedRangeSlider` | start, end | `RangeSlider` (11 fns, 8 outputs) |
|
||||||
|
| `Chart` | dataPointClick, legendToggle | nothing — needs building |
|
||||||
|
| `TreeView` | expand, collapse | nothing — needs building |
|
||||||
|
| `Confetti` | start, complete | nothing — needs building |
|
||||||
|
| `CopyMarkup` | success | nothing — and `Clipboard` is a scaffold too (0 fns) |
|
||||||
|
|
||||||
|
**Change, in two groups.**
|
||||||
|
|
||||||
|
_Group A — supersede and remove: 5 components, 15 of the 22 outputs._
|
||||||
|
`FileUpload`, `ToastNotifications`, `Toast`, `AdvancedDatePicker`,
|
||||||
|
`AdvancedRangeSlider`. Each has a working counterpart, so building them a second
|
||||||
|
time adds duplicated surface area to maintain for no new capability. Removing
|
||||||
|
them is a **breaking change** and needs a migration entry naming the replacement
|
||||||
|
per component, in the same shape as the Table removal.
|
||||||
|
|
||||||
|
This is a judgement call and it is yours: superseding is cheap and honest,
|
||||||
|
keeping them means committing to build five more components properly.
|
||||||
|
|
||||||
|
_Group B — build for real: 4 components, 7 outputs._ `Chart`, `TreeView`,
|
||||||
|
`Confetti`, `CopyMarkup` (and `Clipboard` alongside it, since it is in the same
|
||||||
|
state). These have no counterpart, so their outputs only become meaningful once
|
||||||
|
the component exists. Build each under §0.1 — markup, behaviour and styles in
|
||||||
|
its own `.wrn`.
|
||||||
|
|
||||||
|
Notes that will save time:
|
||||||
|
|
||||||
|
- **`Chart` needs a rendering decision before any output can mean anything.** An
|
||||||
|
inline SVG renderer keeps the CSP story intact and adds no dependency; a
|
||||||
|
charting library ships faster but introduces a third-party runtime dependency
|
||||||
|
the framework does not currently carry. Decide that first — `dataPointClick`
|
||||||
|
and `legendToggle` are trivial once something is actually drawn.
|
||||||
|
- **`TreeView` should reuse the existing roving-focus controller** rather than
|
||||||
|
growing a new one. Expand/collapse state must live in the component, not in a
|
||||||
|
deferred callback — see §2.2.
|
||||||
|
- **`CopyMarkup`'s props are generic input boilerplate** (`name`, `value`,
|
||||||
|
`placeholder`, `type`, `min`) rather than anything copy-related, which
|
||||||
|
suggests it was generated rather than designed. Worth deciding what it is
|
||||||
|
meant to be before building it, or folding it into `Clipboard`.
|
||||||
|
|
||||||
|
Rough effort: `CopyMarkup`/`Clipboard` and `Confetti` are small and
|
||||||
|
self-contained. `TreeView` is medium — recursive rendering plus expand state.
|
||||||
|
`Chart` is the large one.
|
||||||
|
|
||||||
|
**How to test.**
|
||||||
|
|
||||||
|
- The ratchet in `packages/ui/test/ui.test.ts` is pinned at 22 and only ever
|
||||||
|
moves down. Lower the ceiling **in the same commit** that fixes or removes a
|
||||||
|
component — never in a separate one, or the ratchet stops meaning anything.
|
||||||
|
- For a removal: `bun run check:public-api` flags the dropped export, and the
|
||||||
|
migration entry is required before `release:prepare` will pass.
|
||||||
|
- For a build: the component renders, its behaviour works in a browser, its
|
||||||
|
outputs reach a page-level `@binding`, and it carries its own styles. Bind the
|
||||||
|
output from a page and confirm it arrives — §1.1 and §1.2 are both cases where
|
||||||
|
reading the source said it worked and the browser said otherwise.
|
||||||
|
|
||||||
|
### 3.2 Twenty-eight components are still scaffolds
|
||||||
|
|
||||||
|
**Issue.** No style block, no functions and no event handlers — markup shells,
|
||||||
|
the same shape as the Table scaffold that was removed and the LayoutSplitter
|
||||||
|
scaffold that was rebuilt. A scaffold in a published library is a promise the
|
||||||
|
library does not keep.
|
||||||
|
|
||||||
|
**Evidence.** Counted as components with no `style {}`, no `function` and no
|
||||||
|
`@handler`. An earlier figure of 23 in the audit was measured with a looser rule;
|
||||||
|
28 is the number:
|
||||||
|
|
||||||
|
> AdvancedDatePicker, AdvancedRangeSlider, AuthSplitLayout, avatar, Blockquote,
|
||||||
|
> button, Chart, Clipboard, Confetti, CopyMarkup, DataMap, DragAndDrop,
|
||||||
|
> FeatureIconCard, FileUpload, HeroActions, LegendIndicator, ListGroup,
|
||||||
|
> MarketingSectionHeader, progress, Rating, skeleton, spinner, StyledIcon,
|
||||||
|
> TextLink, Toast, ToastNotifications, TreeView, WysiwygEditor
|
||||||
|
|
||||||
|
**Nine of these are the §3.1 dead-output components** — AdvancedDatePicker,
|
||||||
|
AdvancedRangeSlider, Chart, Confetti, CopyMarkup, FileUpload, Toast,
|
||||||
|
ToastNotifications, TreeView. Do §3.1 first and this list drops to 19 without
|
||||||
|
any extra work. Do not plan the two items separately.
|
||||||
|
|
||||||
|
Separately, **58 components still carry the `wire-next` scaffold class** in
|
||||||
|
their markup, including many that are otherwise finished. That class is a
|
||||||
|
generation artefact rather than a design, and it is what ties them to `ui.css`
|
||||||
|
instead of their own styles (§4.1).
|
||||||
|
|
||||||
|
**Change.** Rebuild them under §0.1, or remove them. Note that several are
|
||||||
|
primitives where a scaffold is nearly the right answer — `skeleton`, `spinner`,
|
||||||
|
`avatar`, `Blockquote` and `StyledIcon` need styles but genuinely need no
|
||||||
|
behaviour, so for those "rebuild" means moving their CSS out of `ui.css` into
|
||||||
|
the component and nothing more. Sort the list into "needs behaviour" and "needs
|
||||||
|
only its styles" before starting; the second group is much larger and much
|
||||||
|
cheaper than it looks.
|
||||||
|
|
||||||
|
**How to test.** Per component: it renders, any interactive behaviour works in a
|
||||||
|
browser, its outputs reach a page-level binding, and it carries its own styles.
|
||||||
|
Track the count down the same way as §4.1:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bun run build && gzip -c examples/basic-app/dist/ui.css | wc -c
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.3 Seven components still use Tailwind utilities
|
||||||
|
|
||||||
|
**Issue.** `List` (23 utility classes), `InputNumber` (22), `Marquee` (15),
|
||||||
|
`TextLink` (14), `Map` (12), `SearchBox` (8), `Timeline` (8) still style
|
||||||
|
themselves with utility classes in markup.
|
||||||
|
|
||||||
|
**Change.** Migrate to `wire-*` BEM classes in the component's own `style {}`
|
||||||
|
block, per §0.1. Note this changes the rendered class list, so application CSS
|
||||||
|
selecting on those utilities stops matching — it needs a migration note, exactly
|
||||||
|
as the layout group did in 0.8.6.
|
||||||
|
|
||||||
|
**How to test.**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bun run check:ui-visual # review the rendered diff deliberately
|
||||||
|
bun run generate:ui-visual # only after reviewing
|
||||||
|
```
|
||||||
|
|
||||||
|
Compare screenshots before and after; the visual result should be unchanged.
|
||||||
|
|
||||||
|
### 3.4 `List` only fires `select` for items with an href
|
||||||
|
|
||||||
|
**Issue.** The `@click` handler sits on the `item.href` branch only, so an item
|
||||||
|
without a link is not selectable. Pre-existing, and surprising.
|
||||||
|
|
||||||
|
**Change.** Decide deliberately: either fire `select` for all items, or document
|
||||||
|
that `List` is a navigation component and non-link items are inert.
|
||||||
|
|
||||||
|
**How to test.** Render a `List` with items lacking `href`, click one, assert
|
||||||
|
whichever behaviour was chosen.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Delivery and the dev loop
|
||||||
|
|
||||||
|
### 4.1 `ui.css` ships whole to every page
|
||||||
|
|
||||||
|
**Issue.** `ui.css` is **175,848 bytes, 26,350 gzipped**, served on every page.
|
||||||
|
Only **42 of 108** components have a local `style {}` block, so 66 still depend
|
||||||
|
on it.
|
||||||
|
|
||||||
|
**Change.** Migrate the remaining 66 under §0.1. This is mechanical, high-value,
|
||||||
|
and shrinks `ui.css` toward the global-only baseline it should be. Do it in
|
||||||
|
groups, one commit per group, regenerating the visual contract each time.
|
||||||
|
|
||||||
|
**How to test.** Track the number down, every time:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ls packages/ui/components/*.wrn | wc -l # 108
|
||||||
|
grep -l '^ style {' packages/ui/components/*.wrn | wc -l # 42 today
|
||||||
|
bun run build && gzip -c examples/basic-app/dist/ui.css | wc -c # 26350 today
|
||||||
|
```
|
||||||
|
|
||||||
|
Add a ratchet test asserting the gzipped size only ever decreases, so this
|
||||||
|
cannot silently regress.
|
||||||
|
|
||||||
|
### 4.2 Dev server: `packages/ui` edits do not take effect
|
||||||
|
|
||||||
|
**Issue.** Editing a component under `packages/ui` does not hot-reload. Every UI
|
||||||
|
change this session needed a full server restart, which is the single biggest
|
||||||
|
drag on the edit loop.
|
||||||
|
|
||||||
|
**Evidence, and what is _not_ yet proven.** The watcher is wired correctly:
|
||||||
|
`componentDirs` includes `uiComponentsDir()` and is passed as `extraDirs`
|
||||||
|
(`packages/dev-server/src/index.ts:706-723`), external paths arrive absolute
|
||||||
|
(`packages/dev-server/src/watch.ts:104`), and `hotUpdate` calls
|
||||||
|
`invalidateModule` and rebuilds the router with `componentDirs`
|
||||||
|
(`index.ts:600-616`). So the change _is_ observed. **Why it does not take effect
|
||||||
|
is not yet diagnosed.**
|
||||||
|
|
||||||
|
One concrete lead, not a conclusion: `index.ts:619` filters to
|
||||||
|
`files.filter((file) => !isAbsolute(file))`, which excludes every
|
||||||
|
`packages/ui` path from the app-file branch below it.
|
||||||
|
|
||||||
|
**Change.** Step one is to confirm the cause — add a log at the top of
|
||||||
|
`hotUpdate` printing the received paths, edit a `.wrn` under `packages/ui`, and
|
||||||
|
follow it. Only then fix. Do not implement against the lead above without
|
||||||
|
confirming it.
|
||||||
|
|
||||||
|
**How to test.** Start the dev server, edit visible text in a
|
||||||
|
`packages/ui/components/*.wrn`, reload the page **without restarting**, and see
|
||||||
|
the change. That is the whole acceptance criterion.
|
||||||
|
|
||||||
|
### 4.3 Running tests wipes the cache of a live dev server
|
||||||
|
|
||||||
|
**Issue.** Running `bun test` or `check:production` while a dev server is up
|
||||||
|
empties `.wrnexus`, and every client module then 404s until a restart. This
|
||||||
|
produced several confusing "the Sidebar is broken" symptoms this session that
|
||||||
|
were not component bugs at all.
|
||||||
|
|
||||||
|
**Evidence.** `resetDevCache` in `packages/dev-server/src/cache.ts:24-30`
|
||||||
|
`rmSync`s the whole cache directory on startup, unless
|
||||||
|
`WRNEXUS_PRESERVE_CACHE=1`. Any dev server a test spawns against the repo root
|
||||||
|
therefore deletes the running server's cache.
|
||||||
|
|
||||||
|
**Change.** Two options, both cheap:
|
||||||
|
|
||||||
|
- Give each dev-server instance its own cache directory (keyed by port or pid),
|
||||||
|
so instances cannot collide; or
|
||||||
|
- Have the test harness set `WRNEXUS_PRESERVE_CACHE=1` and use a temp cache dir
|
||||||
|
for every spawned server.
|
||||||
|
|
||||||
|
Prefer the first — it fixes the class rather than one caller. Either way,
|
||||||
|
`resetDevCache` should refuse to delete a cache directory another live server
|
||||||
|
owns.
|
||||||
|
|
||||||
|
**How to test.** Start the dev server, load a page, run `bun test packages` to
|
||||||
|
completion, reload the page without restarting. It must still work. This fails
|
||||||
|
reliably today.
|
||||||
|
|
||||||
|
### 4.4 Generated artefacts have an order dependency
|
||||||
|
|
||||||
|
**Issue.** The component reference must be regenerated **before** the showcase,
|
||||||
|
or newly added props and outputs are invisible to the showcase generator. This
|
||||||
|
is undocumented and cost real time.
|
||||||
|
|
||||||
|
**Change.** Make the showcase generator depend on the reference explicitly, or
|
||||||
|
fail loudly when the reference is older than the component sources.
|
||||||
|
|
||||||
|
**How to test.** Add a prop to a component, run the showcase generator without
|
||||||
|
regenerating the reference, and assert it errors rather than silently emitting a
|
||||||
|
stale page.
|
||||||
|
|
||||||
|
### 4.5 Two authoring traps worth compiler errors
|
||||||
|
|
||||||
|
**Issue.** Block comments are not allowed inside `props {}` — line comments
|
||||||
|
only — and `state page` collides with the `page` keyword. Both currently fail in
|
||||||
|
confusing ways.
|
||||||
|
|
||||||
|
**Change.** Detect both at compile time with a message that names the problem.
|
||||||
|
|
||||||
|
**How to test.** Compiler tests asserting the specific diagnostics.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4.6 Runtime and client-module size — measured
|
||||||
|
|
||||||
|
A per-subsystem measurement of `reactive.js` and of the generated client
|
||||||
|
modules, made by minifying the runtime repeatedly with one subsystem removed
|
||||||
|
each time. Source-byte share was not used: it overstates code that minifies
|
||||||
|
well and understates code that does not, and the split/keep decision turns on
|
||||||
|
the real number.
|
||||||
|
|
||||||
|
**This corrects the earlier audit**, which claimed component controllers were
|
||||||
|
"about 18%" of the runtime and concluded that splitting saves "3-4 kB gzipped".
|
||||||
|
Both figures were wrong, and the conclusion that followed from them was wrong.
|
||||||
|
|
||||||
|
#### The runtime today
|
||||||
|
|
||||||
|
`reactive.js` is **70,101 bytes minified, 21,736 gzipped**. Removing each
|
||||||
|
subsystem and re-minifying gives its true cost:
|
||||||
|
|
||||||
|
| Subsystem | Minified | Share |
|
||||||
|
| ----------------- | -------- | ----- |
|
||||||
|
| Select/combobox | 7,852 | 11.2% |
|
||||||
|
| PinInput | 3,734 | 5.3% |
|
||||||
|
| async boundaries | 3,151 | 4.5% |
|
||||||
|
| Navbar | 2,419 | 3.5% |
|
||||||
|
| splitters | 2,083 | 3.0% |
|
||||||
|
| roving focus | 1,646 | 2.3% |
|
||||||
|
| modal dialogs | 1,611 | 2.3% |
|
||||||
|
| csr fetch | 1,547 | 2.2% |
|
||||||
|
| anchored overlays | 1,419 | 2.0% |
|
||||||
|
| scrollspy | 1,373 | 2.0% |
|
||||||
|
| preferences | 1,045 | 1.5% |
|
||||||
|
| toast | 534 | 0.8% |
|
||||||
|
|
||||||
|
Component-specific controllers (everything except async boundaries and csr
|
||||||
|
fetch, which are framework features) total **23,722 minified / 6,660 gzipped —
|
||||||
|
30.6% of what a visitor downloads.** The irreducible core is 46,379 minified /
|
||||||
|
15,076 gzipped: the expression engine, the scope and reactivity core, and loop
|
||||||
|
diffing.
|
||||||
|
|
||||||
|
#### How much of it a page actually uses
|
||||||
|
|
||||||
|
Measured against the example app by checking which controller markers appear in
|
||||||
|
the served HTML:
|
||||||
|
|
||||||
|
| Page | Controllers used |
|
||||||
|
| ------------- | ------------------ |
|
||||||
|
| `/` | **0 of 10** |
|
||||||
|
| `/login` | **0 of 10** |
|
||||||
|
| `/layout` | 1 of 10 (splitter) |
|
||||||
|
| `/navigation` | 5 of 10 |
|
||||||
|
|
||||||
|
A typical page downloads and parses 6.6 kB gzipped of controller code it never
|
||||||
|
executes. The Select controller — the single largest item at 7,852 bytes — is
|
||||||
|
used by none of the pages above.
|
||||||
|
|
||||||
|
**Change.** Split the component controllers out of the core runtime and load
|
||||||
|
them on demand, keyed on the marker attribute that already gates each one
|
||||||
|
(`data-wrn-select`, `data-wrn-splitter`, `data-wrn-scrollspy` and so on). The
|
||||||
|
gating logic exists; only the loading boundary is missing. Keep the core
|
||||||
|
runtime as one immutable-cached file.
|
||||||
|
|
||||||
|
**How to test.** Assert the core bundle size, and per page assert that a
|
||||||
|
controller chunk is requested only when its marker is present:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bun run scripts/lib/measure-runtime-size.ts # core must stay under budget
|
||||||
|
```
|
||||||
|
|
||||||
|
Plus a browser check on `/`: zero controller chunks requested.
|
||||||
|
|
||||||
|
#### The bigger problem: generated client modules
|
||||||
|
|
||||||
|
The runtime is not where the weight is. On `/navigation`:
|
||||||
|
|
||||||
|
- **490,212 bytes decoded** across 11 client modules, **21,026 transferred** —
|
||||||
|
a 23:1 compression ratio.
|
||||||
|
- The largest single module is **269,117 bytes** decoded, of which **89.8% is
|
||||||
|
duplicated lines**.
|
||||||
|
- One line appears **162 times**: `brand = context.state.brand; topLinks =
|
||||||
|
context.state.topLinks; ...` — the full state-restore prologue.
|
||||||
|
|
||||||
|
Gzip hides this on the wire, but **parse and compile cost scales with decoded
|
||||||
|
bytes, not transferred bytes**. Half a megabyte of JavaScript is parsed to run
|
||||||
|
one page.
|
||||||
|
|
||||||
|
**Cause.** `packages/compiler/src/client-codegen.ts:228-264` inlines the state
|
||||||
|
sync into _every peer-function alias, in every client function_. Each alias
|
||||||
|
emits `syncStateToContext` once and `syncStateFromContext` three times — the
|
||||||
|
catch path, the promise `finally`, and the synchronous path. The output is
|
||||||
|
O(functions x peers x state variables). With ~19 state variables and 81 peer
|
||||||
|
aliases in that module, that is several thousand generated assignments.
|
||||||
|
|
||||||
|
**Change.** Hoist the sync out of the per-alias wrapper. The cheapest version
|
||||||
|
with no change to how bodies are written: emit **one** pair of closures per
|
||||||
|
client function and have every peer alias call them, instead of inlining the
|
||||||
|
sync per alias:
|
||||||
|
|
||||||
|
```js
|
||||||
|
const __flush = () => {
|
||||||
|
context.state.brand = brand; /* ... */
|
||||||
|
};
|
||||||
|
const __restore = () => {
|
||||||
|
brand = context.state.brand; /* ... */
|
||||||
|
};
|
||||||
|
const __peer =
|
||||||
|
(name) =>
|
||||||
|
(...args) => {
|
||||||
|
__flush();
|
||||||
|
let r;
|
||||||
|
try {
|
||||||
|
r = context.functions[name](...args);
|
||||||
|
} catch (e) {
|
||||||
|
__restore();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
if (r && typeof r.then === "function") return Promise.resolve(r).finally(__restore);
|
||||||
|
__restore();
|
||||||
|
return r;
|
||||||
|
};
|
||||||
|
const doThing = __peer("doThing");
|
||||||
|
```
|
||||||
|
|
||||||
|
That removes the peer multiplier — the dominant factor — and takes the 81
|
||||||
|
copies down to roughly one per function. It is a codegen change only, with no
|
||||||
|
change to semantics or to how anyone writes a component.
|
||||||
|
|
||||||
|
A larger follow-up, if the first is not enough: keep state in a single object
|
||||||
|
and rewrite state identifiers in the body to reference it, which removes the
|
||||||
|
per-variable multiplier as well. That one needs the body transform and should
|
||||||
|
be measured before it is attempted.
|
||||||
|
|
||||||
|
**How to test.** Pin decoded size, because gzip hides regressions here:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bun run build
|
||||||
|
# assert the largest generated client module is under budget, DECODED not gzipped
|
||||||
|
```
|
||||||
|
|
||||||
|
Add the ratio itself as a signal: any module compressing better than about 10:1
|
||||||
|
is duplicating itself and should fail the check. Existing behaviour is covered
|
||||||
|
by the current suite, so correctness is the 1,427 tests; this is purely a size
|
||||||
|
assertion on top.
|
||||||
|
|
||||||
|
### 4.7 `generate-ui-complete-catalog.mjs` is broken and destructive
|
||||||
|
|
||||||
|
**Issue.** The script fails partway through with
|
||||||
|
`TypeError: factories[entry.category] is not a function`
|
||||||
|
(`scripts/generate-ui-complete-catalog.mjs:156`) — but not before it has already
|
||||||
|
started writing. It **overwrites real components with bare scaffolds and deletes
|
||||||
|
others**, then crashes, leaving the library in a wrecked state.
|
||||||
|
|
||||||
|
**Evidence.** Running it on 2026-08-09 rewrote Accordion, alert, Badge,
|
||||||
|
AvatarGroup, ToggleCount and LayoutSplitter down to ~15-line stubs, deleted 24
|
||||||
|
component files, and renamed `Card`, `Container`, `Divider` and `Grid` to
|
||||||
|
lowercase — 113 files changed in total. Nothing in `package.json` references it,
|
||||||
|
so no gate runs it and no gate would have caught the damage.
|
||||||
|
|
||||||
|
**Why it is worse than it looks.** The rename is the dangerous part. Windows is
|
||||||
|
case-insensitive, so after `git checkout -- .` the tree reported **clean** while
|
||||||
|
four components were still misnamed on disk. Only a test failure exposed it. On
|
||||||
|
a case-sensitive filesystem the same script produces duplicate files instead.
|
||||||
|
|
||||||
|
**Change.** Pick one:
|
||||||
|
|
||||||
|
- **Delete it.** `generate-ui-component-reference.mjs` is the maintained
|
||||||
|
generator, it is wired into `release:prepare`, and it works. If this script is
|
||||||
|
redundant, it is a loaded gun in the repo for no benefit.
|
||||||
|
- **Or fix and gate it**: make it write to a temp directory and swap atomically
|
||||||
|
only on success, so a mid-run crash cannot leave a partial library. Then add
|
||||||
|
it to a check so it cannot rot again.
|
||||||
|
|
||||||
|
Whichever is chosen, **no script that rewrites `packages/ui/components/` should
|
||||||
|
write in place.** Generate to a staging directory, validate, then move.
|
||||||
|
|
||||||
|
**Related, and worth doing regardless:** several other ungated scripts mutate
|
||||||
|
the repository or start servers when run — `install-captcha.mjs`, the
|
||||||
|
`validate-*.mjs` and `verify-*.mjs` families, and `benchmark-framework.mjs`. All
|
||||||
|
of them fail today. They should either be repaired and gated, or removed. A
|
||||||
|
`scripts/` directory where running a file at random can scaffold apps, start
|
||||||
|
dev servers on ports 3000-3002 and rewrite the component library is a hazard to
|
||||||
|
anyone exploring the repo, human or otherwise.
|
||||||
|
|
||||||
|
**How to test.** After fixing or deleting:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git status --porcelain # must be empty after running any generator twice
|
||||||
|
```
|
||||||
|
|
||||||
|
Add a check that runs each generator in `--check` mode and fails if it would
|
||||||
|
modify tracked files, the way `check:workspace` and `check:public-api` already
|
||||||
|
do.
|
||||||
|
|
||||||
|
### 4.8 Filename casing is not consistent with the git index
|
||||||
|
|
||||||
|
**Issue.** Four components were tracked in git under lowercase names
|
||||||
|
(`card.wrn`, `container.wrn`, `divider.wrn`, `grid.wrn`) while existing on disk
|
||||||
|
under capitalised ones. Windows hid the discrepancy; `git status` reported clean.
|
||||||
|
|
||||||
|
**Why it matters.** `ui-redesign-contract.test.ts` reads the real directory and
|
||||||
|
expects `Card.wrn`. **On a fresh clone on Linux or in CI the files arrive
|
||||||
|
lowercase and that test fails** — a latent break that could not reproduce on a
|
||||||
|
Windows workstation.
|
||||||
|
|
||||||
|
**Change.** Done — the index now tracks the capitalised names, matching the
|
||||||
|
component each file declares (`component Card`, `component Container`, and so
|
||||||
|
on) and matching every other component in the library.
|
||||||
|
|
||||||
|
**How to test.**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git ls-files packages/ui/components/ | grep -iE '/(card|container|divider|grid)\.wrn'
|
||||||
|
```
|
||||||
|
|
||||||
|
must return the capitalised names. Better, set `git config core.ignorecase
|
||||||
|
false` locally so a future rename cannot hide again, and consider a check that
|
||||||
|
compares `git ls-files` against the on-disk listing byte for byte.
|
||||||
|
|
||||||
|
## 5. Order of work
|
||||||
|
|
||||||
|
Ranked by return, not by size. The first item changes the cost of every item
|
||||||
|
below it, which is why it is first.
|
||||||
|
|
||||||
|
| # | Item | Why now |
|
||||||
|
| --- | --------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
|
| 0 | §4.7 neutralise the destructive generator | Safety, not improvement. Running one file in `scripts/` at random can shred the component library. Do this before anyone else touches the repo. |
|
||||||
|
| 1 | §2.1 dev-mode diagnostics | Changes the debugging economics of everything else. Every §1 bug would have been minutes instead of hours. |
|
||||||
|
| 2 | §2.3 reactive props | The biggest capability ceiling. Composition does not work without it. |
|
||||||
|
| 3 | §2.6 server-rendered i18n | Contained work; the core SSR claim currently fails on text. |
|
||||||
|
| 4 | §4.2 + §4.3 dev loop | Cheap, and it compounds across every task below. |
|
||||||
|
| 5 | §4.6 de-duplicate generated client modules | 490 kB decoded parsed per page, 90% of it duplicated. Codegen-only, no API impact. |
|
||||||
|
| 6 | §4.1 finish the CSS migration | 66 components, mechanical, takes ~26 kB off every page. |
|
||||||
|
| 7 | §4.6 split controllers out of the core runtime | 6.6 kB gzipped a typical page never executes. |
|
||||||
|
| 8 | §3.1 Group A: supersede the 5 duplicate scaffolds | 15 of the 22 dead outputs, and 5 fewer components to maintain. Needs a migration entry, not new code. |
|
||||||
|
| 9 | §3.2 scaffolds that need only their styles | Larger and cheaper than it looks; folds into item 6. |
|
||||||
|
| 10 | §3.1 Group B: build Chart, TreeView, Confetti, CopyMarkup | Real component work. Chart needs a rendering decision first. |
|
||||||
|
|
||||||
|
§2.2, §2.4 and §2.5 fold into item 1 as diagnostics first, then into item 2 as
|
||||||
|
model work.
|
||||||
|
|
||||||
|
**What I would resist: adding more components.** The library is 108 wide and
|
||||||
|
roughly 60% deep. Everything above is depth.
|
||||||
|
|
||||||
|
## 6. A note on strategy
|
||||||
|
|
||||||
|
47 packages before 1.0 is a large surface area. Each is a public API you have
|
||||||
|
committed to, a version to align and a migration note to write — the 0.8.6
|
||||||
|
release touched 117 files to change one behaviour. The gate makes that
|
||||||
|
tractable, but tractable is not free. Some packages (`native`, `mobile`,
|
||||||
|
`playground`, `mcp`, `graphql`) look like option value rather than load-bearing.
|
||||||
|
Consolidating them would buy speed on exactly the model gaps in §2 that
|
||||||
|
currently limit users.
|
||||||
|
|
||||||
|
This is a judgement call, not a defect, and it is yours to make.
|
||||||
@@ -2158,11 +2158,13 @@
|
|||||||
"PubSub",
|
"PubSub",
|
||||||
"PubSubDriver",
|
"PubSubDriver",
|
||||||
"ResilientPubSubOptions",
|
"ResilientPubSubOptions",
|
||||||
|
"SubjectPubSub",
|
||||||
"createPubSub",
|
"createPubSub",
|
||||||
"createResilientPubSub",
|
"createResilientPubSub",
|
||||||
"kafkaDriver",
|
"kafkaDriver",
|
||||||
"memoryDriver",
|
"memoryDriver",
|
||||||
"natsDriver"
|
"natsDriver",
|
||||||
|
"subjectPubSub"
|
||||||
],
|
],
|
||||||
"./brokers": [
|
"./brokers": [
|
||||||
"KafkaClient",
|
"KafkaClient",
|
||||||
@@ -2224,6 +2226,8 @@
|
|||||||
"RedisQueueClient",
|
"RedisQueueClient",
|
||||||
"ScheduledJob",
|
"ScheduledJob",
|
||||||
"SqlQueueClient",
|
"SqlQueueClient",
|
||||||
|
"SubjectJob",
|
||||||
|
"SubjectQueue",
|
||||||
"WorkflowDefinition",
|
"WorkflowDefinition",
|
||||||
"WorkflowEngine",
|
"WorkflowEngine",
|
||||||
"WorkflowRunContext",
|
"WorkflowRunContext",
|
||||||
@@ -2246,7 +2250,8 @@
|
|||||||
"queueDashboardSnapshot",
|
"queueDashboardSnapshot",
|
||||||
"redisQueueStore",
|
"redisQueueStore",
|
||||||
"renderQueueDashboard",
|
"renderQueueDashboard",
|
||||||
"runQueueDaemon"
|
"runQueueDaemon",
|
||||||
|
"subjectQueue"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"@wrnexus/reactive": {
|
"@wrnexus/reactive": {
|
||||||
@@ -2392,6 +2397,8 @@
|
|||||||
"RPC_IDENTITY_HEADER",
|
"RPC_IDENTITY_HEADER",
|
||||||
"RPC_INTERNAL_HEADER",
|
"RPC_INTERNAL_HEADER",
|
||||||
"RPC_PATH_PREFIX",
|
"RPC_PATH_PREFIX",
|
||||||
|
"RPC_STREAM_PATH_PREFIX",
|
||||||
|
"RetryTransportOptions",
|
||||||
"RpcErrorCode",
|
"RpcErrorCode",
|
||||||
"RpcTarget",
|
"RpcTarget",
|
||||||
"ServiceClient",
|
"ServiceClient",
|
||||||
@@ -2401,6 +2408,13 @@
|
|||||||
"ServiceHandlers",
|
"ServiceHandlers",
|
||||||
"ServiceImplementation",
|
"ServiceImplementation",
|
||||||
"ServiceResult",
|
"ServiceResult",
|
||||||
|
"StreamClient",
|
||||||
|
"StreamClientOptions",
|
||||||
|
"StreamHandlers",
|
||||||
|
"StreamImplementOptions",
|
||||||
|
"StreamImplementation",
|
||||||
|
"StreamMetrics",
|
||||||
|
"StreamMetricsSnapshot",
|
||||||
"SubjectContext",
|
"SubjectContext",
|
||||||
"ToResultOptions",
|
"ToResultOptions",
|
||||||
"Transport",
|
"Transport",
|
||||||
@@ -2409,14 +2423,18 @@
|
|||||||
"failure",
|
"failure",
|
||||||
"httpTransport",
|
"httpTransport",
|
||||||
"implement",
|
"implement",
|
||||||
|
"implementStream",
|
||||||
"importSubjectContext",
|
"importSubjectContext",
|
||||||
"inProcessTransport",
|
"inProcessTransport",
|
||||||
"isRetryableStatus",
|
"isRetryableStatus",
|
||||||
"procedure",
|
"procedure",
|
||||||
"resolveAppOrigin",
|
"resolveAppOrigin",
|
||||||
|
"retryingTransport",
|
||||||
"rpcPath",
|
"rpcPath",
|
||||||
"rpcSecret",
|
"rpcSecret",
|
||||||
|
"rpcStreamPath",
|
||||||
"serviceClient",
|
"serviceClient",
|
||||||
|
"streamClient",
|
||||||
"success"
|
"success"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,178 @@
|
|||||||
|
# Layout and page-structure components — design
|
||||||
|
|
||||||
|
Date: 2026-08-08
|
||||||
|
Status: approved, not yet implemented
|
||||||
|
|
||||||
|
## Problem
|
||||||
|
|
||||||
|
Two problems, in different proportions to the navigation group.
|
||||||
|
|
||||||
|
**Three components advertise behaviour they do not have.**
|
||||||
|
|
||||||
|
`LayoutSplitter` is the worst component in the library. It declares
|
||||||
|
`resizeStart`, `resize` and `resizeEnd`, so a caller reasonably wires up
|
||||||
|
`@resize` and receives nothing, forever, with no error. It has no pointer
|
||||||
|
handling at all, and its props are `columns`, `gap` and `maxWidth`, copied
|
||||||
|
wholesale from a grid scaffold. `CustomScrollbar` is the same shape: a
|
||||||
|
`scroll` output, no behaviour, and the same wrong grid props.
|
||||||
|
|
||||||
|
`Kbd` is nine lines, but that is not the same failure — a `<kbd>` element
|
||||||
|
genuinely does not need more. It is thin, not dishonest.
|
||||||
|
|
||||||
|
**Most of the group is built on Tailwind utilities.**
|
||||||
|
|
||||||
|
Seven of the ten use utility classes and `class:` conditionals rather than
|
||||||
|
`wire-*` classes and a local style block. They are theme-aware, because the
|
||||||
|
utilities carry arbitrary values bound to tokens
|
||||||
|
(`bg-[var(--wire-color-surface-soft)]`), but they depend on Tailwind being
|
||||||
|
present and produce a class explosion. `SectionHeader` has 38 such lines.
|
||||||
|
|
||||||
|
A correction that shaped this survey: when Tabs was rewritten it was described
|
||||||
|
as "the only component in the library using Tailwind utility classes". That
|
||||||
|
was wrong. **20 of 108 do**, and seven of those are in this group.
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
The ten layout components plus the four page and section primitives, because
|
||||||
|
the goal is composing whole pages and the section-level pieces live in other
|
||||||
|
categories:
|
||||||
|
|
||||||
|
| | |
|
||||||
|
| ---------------- | ------------------------------------------------------------------------------------------------ |
|
||||||
|
| Layout | Container, Columns, Grid, LayoutSplitter, Typography, Image, Link, Divider, Kbd, CustomScrollbar |
|
||||||
|
| Page and section | Section, SectionHeader, PageHeader, PublicPageShell |
|
||||||
|
|
||||||
|
`PageHeader` is already on the target convention — 696 lines, its own style
|
||||||
|
block, zero Tailwind. It is the model the rest migrate toward, and it needs an
|
||||||
|
audit rather than a rewrite.
|
||||||
|
|
||||||
|
## Decisions
|
||||||
|
|
||||||
|
### Styling
|
||||||
|
|
||||||
|
Every component in scope moves to `wire-*` classes with a local `style {}`
|
||||||
|
block and `data-*` attributes for variants, matching PageHeader, DataTable,
|
||||||
|
Toaster and the navigation group.
|
||||||
|
|
||||||
|
Variants become data attributes rather than `class:` conditionals, so
|
||||||
|
`variant="soft"` renders `data-variant="soft"` and the style block selects on
|
||||||
|
it. That replaces roughly a dozen `class:` lines per component with one
|
||||||
|
attribute and a handful of rules.
|
||||||
|
|
||||||
|
Tailwind stays available to applications. This is about the shipped library
|
||||||
|
not requiring it.
|
||||||
|
|
||||||
|
### LayoutSplitter
|
||||||
|
|
||||||
|
Real resizing, driven from the reactive runtime by a declarative attribute:
|
||||||
|
|
||||||
|
- `data-wrn-splitter="horizontal|vertical"` on the container
|
||||||
|
- `data-wrn-splitter-handle` on the divider
|
||||||
|
- the runtime writes the resolved size onto the container as a CSS custom
|
||||||
|
property, so the component styles from it
|
||||||
|
|
||||||
|
Pointer events fire far too often to route through client functions, and drag
|
||||||
|
state written inside a `pointermove` callback is dropped — the same constraint
|
||||||
|
that put roving focus and scrollspy in the runtime.
|
||||||
|
|
||||||
|
Keyboard support is part of the contract, not an extra: arrow keys move the
|
||||||
|
divider by a step, Home and End jump to the bounds, and the handle carries
|
||||||
|
`role="separator"` with `aria-valuenow`, `aria-valuemin` and `aria-valuemax`.
|
||||||
|
|
||||||
|
Sizes are clamped to a `minSize` per pane so a pane cannot be dragged to
|
||||||
|
nothing and become unrecoverable.
|
||||||
|
|
||||||
|
### CustomScrollbar
|
||||||
|
|
||||||
|
Scrollbar styling is CSS: `scrollbar-width` and `scrollbar-color` for the
|
||||||
|
standard property, with `::-webkit-scrollbar` rules for browsers that still
|
||||||
|
need them. No runtime, no scroll output — the existing `scroll` output is
|
||||||
|
removed rather than left unimplemented, since a caller can listen for a plain
|
||||||
|
`scroll` event on the element.
|
||||||
|
|
||||||
|
Its grid props (`columns`, `gap`, `maxWidth`) are replaced with ones that mean
|
||||||
|
something: `axis`, `thickness`, `thumb`, `track`, `maxHeight`.
|
||||||
|
|
||||||
|
### Kbd
|
||||||
|
|
||||||
|
Left as it is, beyond the `wire-*` migration. It is thin because a `<kbd>`
|
||||||
|
is thin.
|
||||||
|
|
||||||
|
### Runtime budget
|
||||||
|
|
||||||
|
The splitter is roughly 2k minified against 67.7k of an 80k budget. It fits.
|
||||||
|
The budget now measures minified output, so comments cost nothing.
|
||||||
|
|
||||||
|
## Components
|
||||||
|
|
||||||
|
| Component | Work |
|
||||||
|
| --------------- | -------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
|
| LayoutSplitter | Build. Runtime-driven pointer resize, keyboard steps, `role="separator"` with value attributes, per-pane `minSize`, real outputs |
|
||||||
|
| CustomScrollbar | Build. Themed scrollbar styling, meaningful props, the fake `scroll` output removed |
|
||||||
|
| Container | Migrate. `maxWidth`, `padding`, `centered` as data attributes |
|
||||||
|
| Columns | Migrate. `columns`, `gap`, responsive collapse in a media query rather than `md:` prefixes |
|
||||||
|
| Grid | Migrate. `columns`, `gap`, `minItemWidth` for an auto-fit track |
|
||||||
|
| Typography | Migrate the remaining Tailwind lines into its existing style block |
|
||||||
|
| Image | Migrate. `ratio`, `fit`, `rounded`, `loading` |
|
||||||
|
| Link | Migrate. `variant`, `underline`, external-link affordance |
|
||||||
|
| Divider | Migrate. `orientation`, `variant`, optional label |
|
||||||
|
| Kbd | Migrate only |
|
||||||
|
| Section | Migrate. `spacing`, `variant`, `color` as data attributes |
|
||||||
|
| SectionHeader | Migrate. Its 38 Tailwind lines collapse into a style block |
|
||||||
|
| PublicPageShell | Migrate. `minHeight`, `overflow`, `background`, `headerOffset` |
|
||||||
|
| PageHeader | Audit only — already on the convention |
|
||||||
|
|
||||||
|
Component count stays at 108; every file already exists.
|
||||||
|
|
||||||
|
## Data flow
|
||||||
|
|
||||||
|
Props in, outputs out, no global state. The splitter is the only component
|
||||||
|
with runtime state, and that state lives in the DOM as a custom property
|
||||||
|
rather than in component state.
|
||||||
|
|
||||||
|
## Error handling
|
||||||
|
|
||||||
|
Numeric props (`columns`, `minSize`, `thickness`) clamp rather than throw,
|
||||||
|
because they arrive as HTML attributes. A splitter with one child renders that
|
||||||
|
child full width instead of erroring.
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
- Per-component entries in `packages/ui/test/ui.test.ts`
|
||||||
|
- Splitter drag and keyboard covered in `packages/csr/test/reactive.test.ts`,
|
||||||
|
using markers rather than measured size: the test DOM reports every element
|
||||||
|
as zero-sized
|
||||||
|
- Showcase profiles for each, so every component gets live demos
|
||||||
|
- Regenerate the component reference **before** the showcase — the generator
|
||||||
|
cannot see new props otherwise
|
||||||
|
- Each phase ends with `bun run check:production` green
|
||||||
|
|
||||||
|
## Phases
|
||||||
|
|
||||||
|
1. **Scaffolds** — splitter runtime and component, CustomScrollbar
|
||||||
|
2. **Layout migration** — Container, Columns, Grid, Divider, Image, Link,
|
||||||
|
Typography, Kbd
|
||||||
|
3. **Page and section** — Section, SectionHeader, PublicPageShell, PageHeader
|
||||||
|
audit, plus a page in `examples/basic-app` composing the whole set
|
||||||
|
|
||||||
|
## Risks
|
||||||
|
|
||||||
|
- The migration rewrites working markup. Visual regressions are the main
|
||||||
|
danger, and the browser pane cannot take screenshots, so verification is
|
||||||
|
computed styles and the UI visual contract rather than eyes on pixels.
|
||||||
|
- Removing `class:` conditionals changes the rendered class list, so any
|
||||||
|
application selecting on those utility classes breaks. This needs a
|
||||||
|
migration entry alongside the Tabs and Sidebar changes already outstanding.
|
||||||
|
|
||||||
|
## Codebase constraints to respect
|
||||||
|
|
||||||
|
- No apostrophes in `.wrn` comments
|
||||||
|
- `/* */` only inside style blocks; `//` silently eats the next CSS rule
|
||||||
|
- Block comments are not allowed inside `props {}` — line comments only
|
||||||
|
- `data-show` takes a bare expression, not `{...}`
|
||||||
|
- One root element per component
|
||||||
|
- No deferred state writes in client functions
|
||||||
|
- Object props are passed through state, never inline braces in an attribute
|
||||||
|
- Package components need explicit imports
|
||||||
|
- Stop the dev server before running tests; it wipes `.wrnexus`
|
||||||
|
- Restart the dev server after changing a package component
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
# UI library audit — 2026-08-08
|
||||||
|
|
||||||
|
A measured pass over `@wrnexus/ui` after the navigation and layout groups were
|
||||||
|
rebuilt. Numbers come from the source and from a browser, not from estimates.
|
||||||
|
|
||||||
|
## Fixed in this pass
|
||||||
|
|
||||||
|
**Ten theme tokens were referenced and never defined.** An undefined custom
|
||||||
|
property does not warn — it resolves to nothing — so the styles that used them
|
||||||
|
silently did nothing:
|
||||||
|
|
||||||
|
| Token | Effect while undefined |
|
||||||
|
| ----------------------------- | --------------------------------------------------------- |
|
||||||
|
| `--wire-color-focus` | Focus rings drew with no colour, in 14 components |
|
||||||
|
| `--wire-color-surface-soft` | Every soft surface rendered transparent, in 27 components |
|
||||||
|
| `--wire-color-on-danger` | Text on danger fills had no colour |
|
||||||
|
| `--wire-color-surface-subtle` | Subtle panels rendered transparent |
|
||||||
|
| `--wire-color-input-*` (6) | Input backgrounds, borders and placeholders unstyled |
|
||||||
|
| `*-hover`, `*-contrast` | Missing for info, success, warning and danger |
|
||||||
|
|
||||||
|
They are derived in the theme now, so they follow the palette and the accent.
|
||||||
|
Verified in a browser: 38 tokens referenced, **0 undefined** (was 10).
|
||||||
|
|
||||||
|
Two mistakes worth recording, because both nearly became wrong conclusions:
|
||||||
|
|
||||||
|
- A first version of the check read the theme _source_ and reported a dozen
|
||||||
|
false positives, because most tokens are generated per palette rather than
|
||||||
|
written as literals. The check now reads the **rendered** theme CSS.
|
||||||
|
- The semantic token spread sat _after_ the primary and secondary palette
|
||||||
|
entries, so it would have overridden them. It now sits before.
|
||||||
|
|
||||||
|
## Correction: outputs, and what was actually wrong
|
||||||
|
|
||||||
|
The first version of this audit called the LayoutSplitter output failure
|
||||||
|
"narrow and unexplained" and treated 32 dead outputs as 16 components needing a
|
||||||
|
rebuild. Both were wrong, and the real cause was found by binding a page
|
||||||
|
handler to a component in a browser and watching what arrived.
|
||||||
|
|
||||||
|
**Two distinct faults were hiding behind one symptom.**
|
||||||
|
|
||||||
|
_Emitting the wrong way._ An output only reaches a parent `@binding` when the
|
||||||
|
component calls `output.<name>()`. The runtime resolves parent handlers from a
|
||||||
|
registry that only `invokeComponentOutput` reads, so a component that builds
|
||||||
|
its own `CustomEvent` — even a bubbling one, dispatched on its own root —
|
||||||
|
emits into nothing. Eighteen components did exactly that, so their outputs were
|
||||||
|
declared, documented, apparently fired, and never delivered. Converting them
|
||||||
|
took ten dead outputs off the list and cost no new machinery.
|
||||||
|
|
||||||
|
_Case._ HTML lowercases attribute names, so a parent's `@sizeChange` registers
|
||||||
|
under `sizechange` while the component emits `sizeChange`. The lookup missed,
|
||||||
|
fell through to a DOM dispatch, and the binding was never invoked — silently,
|
||||||
|
with no error at either end. **All 17 camelCase outputs in the library were
|
||||||
|
undeliverable**, including `DataTable.pageChange` and `DataTable.rowClick`,
|
||||||
|
`Map.markerClick`, `ChatBubble.messageClick` and `LayoutSplitter.sizeChange`.
|
||||||
|
The runtime now falls back to a case-insensitive lookup, and a test in
|
||||||
|
`packages/csr` fails without that fallback.
|
||||||
|
|
||||||
|
The lesson worth keeping: "outputs work elsewhere" was an assumption, not a
|
||||||
|
measurement. The components that worked happened to use all-lowercase names and
|
||||||
|
`output.*`; that coincidence made a framework-wide bug look like one broken
|
||||||
|
component.
|
||||||
|
|
||||||
|
## Outstanding, with numbers
|
||||||
|
|
||||||
|
**22 outputs across 9 components have no emitter of any kind** (was 32 across
|
||||||
|
16; see the correction above). The component advertises an output, a caller
|
||||||
|
binds to it, and nothing ever fires. Native event names are excluded — the
|
||||||
|
runtime binds a DOM-listener fallback on component tags, so `click` and `input`
|
||||||
|
do arrive.
|
||||||
|
|
||||||
|
| Component | Dead outputs |
|
||||||
|
| ------------------- | ----------------------------------------- |
|
||||||
|
| FileUpload | upload, progress, success, cancel, remove |
|
||||||
|
| ToastNotifications | add, dismiss, clear, action |
|
||||||
|
| AdvancedDatePicker | open, close, clear |
|
||||||
|
| AdvancedRangeSlider | start, end |
|
||||||
|
| Chart | dataPointClick, legendToggle |
|
||||||
|
| Confetti | start, complete |
|
||||||
|
| TreeView | expand, collapse |
|
||||||
|
| Toast | dismiss |
|
||||||
|
| CopyMarkup | success |
|
||||||
|
|
||||||
|
A test pins this at 22 as a ceiling that only moves down.
|
||||||
|
|
||||||
|
**28 components are still scaffolds** — no style block, no functions and no
|
||||||
|
handlers. Nine of them also declare outputs nothing emits. (An earlier figure of
|
||||||
|
23 here used a looser rule; see §3.2 of the remediation plan.)
|
||||||
|
These are the same shape as the Table scaffold that was removed and the
|
||||||
|
LayoutSplitter scaffold that was rebuilt.
|
||||||
|
|
||||||
|
**66 of 108 components have no local style block**, so they depend on
|
||||||
|
`ui.css`. That matters for delivery: a migrated component ships its CSS only
|
||||||
|
when it renders, while `ui.css` is served whole to every page — 175,848 bytes,
|
||||||
|
**25,908 gzipped**. Migrating the remainder would shrink it toward nothing.
|
||||||
|
|
||||||
|
**10 components still use Tailwind utilities**: FeatureIconCard, HeroActions,
|
||||||
|
InputNumber, List, Map, Marquee, SearchBox, TextLink, Timeline, button.
|
||||||
|
|
||||||
|
## Not worth doing
|
||||||
|
|
||||||
|
**Splitting the runtime into chunks.** Measured rather than assumed:
|
||||||
|
`reactive.js` is 69,947 bytes minified, roughly 21 kB gzipped, served as its
|
||||||
|
own file with a one-year immutable cache. Component-specific controllers are
|
||||||
|
about 18% of it, so splitting them out saves 3–4 kB gzipped on a first visit
|
||||||
|
and nothing after that. That is a poor return for lazy-loading complexity.
|
||||||
|
|
||||||
|
Hydration is not a bottleneck either: 21 scopes across 4,325 elements rehydrate
|
||||||
|
in 1.5 ms, and the shared document observer cost 0.9 ms across three seconds of
|
||||||
|
the busiest activity in the library.
|
||||||
|
|
||||||
|
## Known framework defects
|
||||||
|
|
||||||
|
- **A component tag nested inside another component slot is dropped**, leaving
|
||||||
|
only its children.
|
||||||
|
- **Component props and slot content render once** and do not track page state,
|
||||||
|
so the controlled-component pattern does not work.
|
||||||
|
- **i18n text is not server-rendered.** Nav links ship as empty spans and are
|
||||||
|
filled by the client, so navigation is blank until the runtime loads.
|
||||||
@@ -2,39 +2,39 @@
|
|||||||
"schemaVersion": 1,
|
"schemaVersion": 1,
|
||||||
"releaseLine": "0.8",
|
"releaseLine": "0.8",
|
||||||
"artifacts": {
|
"artifacts": {
|
||||||
"packages/ui/components/Accordion.wrn": "e74433d405767edd50e58237ac3986e08e14a893450d712f69679c8361485734",
|
"packages/ui/components/Accordion.wrn": "2b2e756a2197052bbcaf7499d01ec4b68b53a3acaf4524b7ca6424b71ba2e9a3",
|
||||||
"packages/ui/components/AdvancedDatePicker.wrn": "b9b5b08e9464544837a5400bbf9a2cb25724fac037fe196a219b42e5841ad672",
|
"packages/ui/components/AdvancedDatePicker.wrn": "b9b5b08e9464544837a5400bbf9a2cb25724fac037fe196a219b42e5841ad672",
|
||||||
"packages/ui/components/AdvancedRangeSlider.wrn": "e78b5cf825503d0cd306c6e490d71317ee3db1844882d13b500df1f7f1c408e1",
|
"packages/ui/components/AdvancedRangeSlider.wrn": "e78b5cf825503d0cd306c6e490d71317ee3db1844882d13b500df1f7f1c408e1",
|
||||||
"packages/ui/components/AdvancedSelect.wrn": "29d43f8019a3e0e98af7cf12440f41523665535a39a973441b4faea78e67114a",
|
"packages/ui/components/AdvancedSelect.wrn": "29d43f8019a3e0e98af7cf12440f41523665535a39a973441b4faea78e67114a",
|
||||||
"packages/ui/components/AnnouncementBar.wrn": "5946ef5eb646f7414056f59d9cfe14680aa3c935acc9a1ca6528dc53b23caa48",
|
"packages/ui/components/AnnouncementBar.wrn": "903bfd9421a7350c923ace3315cedc5763fe3e6b7b54b660a0f26281d46a8754",
|
||||||
"packages/ui/components/AuthForm.wrn": "496d240090269e69679e01cda3b071c012ec4e925a7c01ae883d25e359e381e1",
|
"packages/ui/components/AuthForm.wrn": "496d240090269e69679e01cda3b071c012ec4e925a7c01ae883d25e359e381e1",
|
||||||
"packages/ui/components/AuthSplitLayout.wrn": "72b82495dd14d40a2d594ccdcf3adc925d1567c155750fb1072347b8845aab7b",
|
"packages/ui/components/AuthSplitLayout.wrn": "72b82495dd14d40a2d594ccdcf3adc925d1567c155750fb1072347b8845aab7b",
|
||||||
"packages/ui/components/AvatarGroup.wrn": "9c583f567213f8e1ad4506a7d2abc3fb462d11679fd2196d3828030f28a28964",
|
"packages/ui/components/AvatarGroup.wrn": "66f3d211b7658ca5193c750d0ccb3e392185038d8960d3206f6e8a249e10214e",
|
||||||
"packages/ui/components/BackToTop.wrn": "b12c56ec8b7aabad68cbdc47f4b3237e2c21a61398f0aa51f9add6229b7357cd",
|
"packages/ui/components/BackToTop.wrn": "b12c56ec8b7aabad68cbdc47f4b3237e2c21a61398f0aa51f9add6229b7357cd",
|
||||||
"packages/ui/components/Badge.wrn": "6b55b4d85100d605cf168857aec1dc57da62c1f6a0a5cd6dd877023f24b189cc",
|
"packages/ui/components/Badge.wrn": "e96cdcf182ff9834509464bb2fa4c0b041748d3f7671aa46ab489bae6f3d98ae",
|
||||||
"packages/ui/components/Blockquote.wrn": "6016dd4450de7cbf5c3cb413599baa2e502321e8eedef54439a0df6d0aae8bcb",
|
"packages/ui/components/Blockquote.wrn": "6016dd4450de7cbf5c3cb413599baa2e502321e8eedef54439a0df6d0aae8bcb",
|
||||||
"packages/ui/components/Breadcrumb.wrn": "df27101d41cf018d55b6909e0399286a4661637140e341c8624615051d485142",
|
"packages/ui/components/Breadcrumb.wrn": "14732e91468f5793ee5da8599f8e40d84ec51c93d660fb0c0056b956ec707850",
|
||||||
"packages/ui/components/ButtonGroup.wrn": "0d97fbeed531d1d8ef4b59531923b47b34100d0de71d7bf524b02c668920b3d8",
|
"packages/ui/components/ButtonGroup.wrn": "0d97fbeed531d1d8ef4b59531923b47b34100d0de71d7bf524b02c668920b3d8",
|
||||||
"packages/ui/components/CTASection.wrn": "2d2241d4f1018cfd2f8ea1ddd5fa8c8fcb8d1bbb2d4e4498cb9f39ff47a3801c",
|
"packages/ui/components/CTASection.wrn": "2d2241d4f1018cfd2f8ea1ddd5fa8c8fcb8d1bbb2d4e4498cb9f39ff47a3801c",
|
||||||
"packages/ui/components/Card.wrn": "4370df341235819b8a968a3f812209c2e6c29e4471d06578aaa5b577fb6e2dc8",
|
"packages/ui/components/Card.wrn": "457bc546e0b227692ac96ec8f413823463d3cfe9194b6f4847c21a5beee5e8a4",
|
||||||
"packages/ui/components/Chart.wrn": "841def6b024720bd24898975a1434a1cb39c89e1272d42db431d35d27c98c553",
|
"packages/ui/components/Chart.wrn": "841def6b024720bd24898975a1434a1cb39c89e1272d42db431d35d27c98c553",
|
||||||
"packages/ui/components/ChatBubble.wrn": "0da2bc86830ac712481559bd2fe7214d26f25101f2e8c2e4629e25c004388b52",
|
"packages/ui/components/ChatBubble.wrn": "0da2bc86830ac712481559bd2fe7214d26f25101f2e8c2e4629e25c004388b52",
|
||||||
"packages/ui/components/Checkbox.wrn": "45e6046e3ad4acb1c1805b51fd5bf0b95b346d3d53973ededc5e43ea2fd91f70",
|
"packages/ui/components/Checkbox.wrn": "45e6046e3ad4acb1c1805b51fd5bf0b95b346d3d53973ededc5e43ea2fd91f70",
|
||||||
"packages/ui/components/Clipboard.wrn": "bb8651c7e44517db827603d0c0e546b6891093d7e6589c0b6e45d91b6187591b",
|
"packages/ui/components/Clipboard.wrn": "bb8651c7e44517db827603d0c0e546b6891093d7e6589c0b6e45d91b6187591b",
|
||||||
"packages/ui/components/Collapse.wrn": "c537239831c6938f3c39be0ca3ae8ba928c2490e21cfe5853c10f7221a4678ca",
|
"packages/ui/components/Collapse.wrn": "c537239831c6938f3c39be0ca3ae8ba928c2490e21cfe5853c10f7221a4678ca",
|
||||||
"packages/ui/components/ColorPicker.wrn": "6940b7ae48f1358008b8c3ae6dc7da31f96a1aefadeef18252568b2cda0b5cbf",
|
"packages/ui/components/ColorPicker.wrn": "6940b7ae48f1358008b8c3ae6dc7da31f96a1aefadeef18252568b2cda0b5cbf",
|
||||||
"packages/ui/components/Columns.wrn": "449a427c2f4dd846b5239b73efe5b8d15ad4f20fa28598802a5eb57c33332391",
|
"packages/ui/components/Columns.wrn": "e01496aa53025444cc51671efcce40d6d24d86775b2cbb1ee0def1862bb6315d",
|
||||||
"packages/ui/components/Combobox.wrn": "62a7d861b0e536ceb088cea3552c59acbafaea5184101e3651dc8f4976b99dbc",
|
"packages/ui/components/Combobox.wrn": "62a7d861b0e536ceb088cea3552c59acbafaea5184101e3651dc8f4976b99dbc",
|
||||||
"packages/ui/components/Confetti.wrn": "22d687beefd5047055f65e806b4e39f81e18887532ec18d439ac364a044b230a",
|
"packages/ui/components/Confetti.wrn": "22d687beefd5047055f65e806b4e39f81e18887532ec18d439ac364a044b230a",
|
||||||
"packages/ui/components/Container.wrn": "be8fce140043eced8b78c8dd14ff85ace4ed2d91671251641ef83e0fe4da8f2a",
|
"packages/ui/components/Container.wrn": "4a0acbb896f4c11714e3925d912b10ef9aeedfa904b4ad8561aa2cbd9a0fdca0",
|
||||||
"packages/ui/components/ContextMenu.wrn": "2e011e9cb1c09a3a2344ed3fa29dcc74331cd39f838535d8aee4b249dceef0ce",
|
"packages/ui/components/ContextMenu.wrn": "2e011e9cb1c09a3a2344ed3fa29dcc74331cd39f838535d8aee4b249dceef0ce",
|
||||||
"packages/ui/components/CopyMarkup.wrn": "8d57a7d72e02c126f855a181fc36e1b969edb90f683dce6b6ffe546d49d2b29b",
|
"packages/ui/components/CopyMarkup.wrn": "8d57a7d72e02c126f855a181fc36e1b969edb90f683dce6b6ffe546d49d2b29b",
|
||||||
"packages/ui/components/CustomScrollbar.wrn": "4c1f7758b9cd47e20ecf922403e12b5b15b8127a2744383c6bd280ee20e5fdd1",
|
"packages/ui/components/CustomScrollbar.wrn": "fedb2ab06cc2cf9499c130590945ca6971a3edfb60407b6658ef7756e4be9823",
|
||||||
"packages/ui/components/DataMap.wrn": "65552d73ecd1a148427dbb10d611f9352ca36bd490f595ab1e1a47e173445ba1",
|
"packages/ui/components/DataMap.wrn": "65552d73ecd1a148427dbb10d611f9352ca36bd490f595ab1e1a47e173445ba1",
|
||||||
"packages/ui/components/DataTable.wrn": "5a76e50e8559c724aaf01ec954958ac640c99758d44f1eef8e6eb1cb6dc4f862",
|
"packages/ui/components/DataTable.wrn": "5a76e50e8559c724aaf01ec954958ac640c99758d44f1eef8e6eb1cb6dc4f862",
|
||||||
"packages/ui/components/DatePicker.wrn": "18b07e59c27c2720bf960e9c04ad70d9e422ddcf0817fede74e71899811bb387",
|
"packages/ui/components/DatePicker.wrn": "18b07e59c27c2720bf960e9c04ad70d9e422ddcf0817fede74e71899811bb387",
|
||||||
"packages/ui/components/DeviceFrame.wrn": "a881cf2cc1f859b43cc3c7a1e1ca0fb40cea7a9e530ab5bdcb985aa9592d11c0",
|
"packages/ui/components/DeviceFrame.wrn": "a881cf2cc1f859b43cc3c7a1e1ca0fb40cea7a9e530ab5bdcb985aa9592d11c0",
|
||||||
"packages/ui/components/Divider.wrn": "e377f8005249cf4f6c51dd4d04ff9c6a70a3f4e3a79d2c02a8ab601754c8553a",
|
"packages/ui/components/Divider.wrn": "f5cc449611022b3d3eedf982ae48f6b1a289db7855cc9b6ea0248dcda807ffb3",
|
||||||
"packages/ui/components/DragAndDrop.wrn": "9a403ce9ed20d36211d8916911871875c9c7d0952a7de1a21a433eaa0b3c3324",
|
"packages/ui/components/DragAndDrop.wrn": "9a403ce9ed20d36211d8916911871875c9c7d0952a7de1a21a433eaa0b3c3324",
|
||||||
"packages/ui/components/Drawer.wrn": "04a77a69edfad6793b5ab60981a719f11061984c087d0d61663566e322649fef",
|
"packages/ui/components/Drawer.wrn": "04a77a69edfad6793b5ab60981a719f11061984c087d0d61663566e322649fef",
|
||||||
"packages/ui/components/Dropdown.wrn": "c61b46ae6e54f6aacac9f4ed422f6c659deea9a637fd944645acd37bf270b01d",
|
"packages/ui/components/Dropdown.wrn": "c61b46ae6e54f6aacac9f4ed422f6c659deea9a637fd944645acd37bf270b01d",
|
||||||
@@ -44,24 +44,24 @@
|
|||||||
"packages/ui/components/FileInput.wrn": "8b63811deb90a03763620bedf0d5d3c7d05a20b8ae34292eaface9b756b32ecd",
|
"packages/ui/components/FileInput.wrn": "8b63811deb90a03763620bedf0d5d3c7d05a20b8ae34292eaface9b756b32ecd",
|
||||||
"packages/ui/components/FileUpload.wrn": "3346d8978e134c3a1e6bc742201a3fbb0cffb89da40da6fcd856a2adbb971393",
|
"packages/ui/components/FileUpload.wrn": "3346d8978e134c3a1e6bc742201a3fbb0cffb89da40da6fcd856a2adbb971393",
|
||||||
"packages/ui/components/FileUploadProgress.wrn": "83bcc8558c70fbe0e0670642f65998abd222c235f1031be46bd7c65e6b5c5154",
|
"packages/ui/components/FileUploadProgress.wrn": "83bcc8558c70fbe0e0670642f65998abd222c235f1031be46bd7c65e6b5c5154",
|
||||||
"packages/ui/components/Footer.wrn": "a5dfaa5f9548b7fdd4b556c63428e0ea8d22e5e776a5714d76619999438cf618",
|
"packages/ui/components/Footer.wrn": "d9075d2206af75a1ec4317d7974d47311889400699260e990d672780f43f40bf",
|
||||||
"packages/ui/components/Grid.wrn": "b5546b899c509c1f3e8f5edad801bc59acf9fe3008a627f0e4476cd61b5b672e",
|
"packages/ui/components/Grid.wrn": "d089d8657298b4d33993ba4bf7b581f816c65db513d8e48cf1fdd18da19e05a8",
|
||||||
"packages/ui/components/Hero.wrn": "e4e39dcd59c273192c7e4136f6583279e20b0956bcba4cfbc3f6e01a1fade152",
|
"packages/ui/components/Hero.wrn": "e4e39dcd59c273192c7e4136f6583279e20b0956bcba4cfbc3f6e01a1fade152",
|
||||||
"packages/ui/components/HeroActions.wrn": "c5720efe2ce7f6c114eb2ea4ccc3e8102a1099078ba23fd13770eddeb6aec640",
|
"packages/ui/components/HeroActions.wrn": "c5720efe2ce7f6c114eb2ea4ccc3e8102a1099078ba23fd13770eddeb6aec640",
|
||||||
"packages/ui/components/Image.wrn": "4294358e2eddf06ae4384217dbff7693b609c16bf6549f54d6ad27df74d7ae27",
|
"packages/ui/components/Image.wrn": "8113441bf90ab0d1d8618d477125ad339021f39e853db89d656c72c492e7a20b",
|
||||||
"packages/ui/components/Input.wrn": "9ad394eed60f1b05bbd2ccd50dc2de7b78245c52c87afd46055d772c38b7b0c9",
|
"packages/ui/components/Input.wrn": "9ad394eed60f1b05bbd2ccd50dc2de7b78245c52c87afd46055d772c38b7b0c9",
|
||||||
"packages/ui/components/InputGroup.wrn": "0e23ea541a60e893c9d9e6f95113911ee459468d8d6105bf03aeb55395359123",
|
"packages/ui/components/InputGroup.wrn": "0e23ea541a60e893c9d9e6f95113911ee459468d8d6105bf03aeb55395359123",
|
||||||
"packages/ui/components/InputNumber.wrn": "a0aa4f4566bf54ffbef54c99648eab05b5f9870be6ea07639a4ecf3930afb631",
|
"packages/ui/components/InputNumber.wrn": "26936385e9f01ec888a1df61719991aa7a2782305328b02c939d3c2c94e3e8e0",
|
||||||
"packages/ui/components/Kbd.wrn": "d51fa614b36f971f885410785b481c2e6900b2416e6e7c8868dfda1ebd5f3b4c",
|
"packages/ui/components/Kbd.wrn": "5afaabbb15902bd8fb82cb4155cf6cbfff55600927b54d564d27e2dd8b752386",
|
||||||
"packages/ui/components/LayoutSplitter.wrn": "dac5a80acb76bf58dfd25233c68190c67d1aa1b3b0d4250a0957ea40912cf722",
|
"packages/ui/components/LayoutSplitter.wrn": "6bd6812e364420ed5d3439862116c58d0b011b298679005795bdccdbb7455066",
|
||||||
"packages/ui/components/LegendIndicator.wrn": "6a7607b27a17196f899132eb952203a1073e4077365a94935f485e700cbac665",
|
"packages/ui/components/LegendIndicator.wrn": "6a7607b27a17196f899132eb952203a1073e4077365a94935f485e700cbac665",
|
||||||
"packages/ui/components/Link.wrn": "935ac24e8ebd067860dc9709ea9121710315ad6e02ce95cd5e982ae4d5978a02",
|
"packages/ui/components/Link.wrn": "b986abcc66bc0b1c6296f3ff4e560812e35d89cc680d5251d7a3883e68c1d053",
|
||||||
"packages/ui/components/List.wrn": "02f960a8e82fa049aac477bac9c1d9371394c86d9c47513138f61bffc79dc7d8",
|
"packages/ui/components/List.wrn": "8cf4505ff6a079feb3b77822d7ed6977a70393dd1e6267f94e75234d3ac215d6",
|
||||||
"packages/ui/components/ListGroup.wrn": "37e2ec61ceab20ed020a834da03208c493702b41abcf586816e29f2e50d8ee11",
|
"packages/ui/components/ListGroup.wrn": "37e2ec61ceab20ed020a834da03208c493702b41abcf586816e29f2e50d8ee11",
|
||||||
"packages/ui/components/Map.wrn": "7b8a0d5412a464fd7cab8977d816542c506d8c5dab8230a3c984c2caee407c91",
|
"packages/ui/components/Map.wrn": "990656db93e1acd73a301a4addaf353afa14430805366d2e5f124b831044afbe",
|
||||||
"packages/ui/components/MarketingSectionHeader.wrn": "7d6ffcc01a9331474475ea57ca58598be757abd9428b66bdfaf6f3603c5b145b",
|
"packages/ui/components/MarketingSectionHeader.wrn": "7d6ffcc01a9331474475ea57ca58598be757abd9428b66bdfaf6f3603c5b145b",
|
||||||
"packages/ui/components/Marquee.wrn": "b2b35eedf3297ba12ab3776385a9f3eab001027648d87a2a1968f576eee6c025",
|
"packages/ui/components/Marquee.wrn": "3395235807aea43ac10c4d562706e510dac2a32786b4a5d5d73927989ede68df",
|
||||||
"packages/ui/components/MegaMenu.wrn": "48f4ced485df0e8de5217630c8bdcec0b2317bf04e6b279399f2c93d98d56995",
|
"packages/ui/components/MegaMenu.wrn": "8a9a9b348ca1c5e182914ff55d981a91f47a49c52ef5e5efd8e4cb6e56361a43",
|
||||||
"packages/ui/components/MetricCard.wrn": "6451182739298691908f68258c0250cce2a78b0dc27c97115579ece30d7d9f92",
|
"packages/ui/components/MetricCard.wrn": "6451182739298691908f68258c0250cce2a78b0dc27c97115579ece30d7d9f92",
|
||||||
"packages/ui/components/MetricGrid.wrn": "6018a98c10628ed240ed236ed916c0ff60994d192c3aadafd10bc876be0f9364",
|
"packages/ui/components/MetricGrid.wrn": "6018a98c10628ed240ed236ed916c0ff60994d192c3aadafd10bc876be0f9364",
|
||||||
"packages/ui/components/Modal.wrn": "59d4ae9d6dd2700692d9edecfe53ee868e9f864363a4885961d1813cb2bee51f",
|
"packages/ui/components/Modal.wrn": "59d4ae9d6dd2700692d9edecfe53ee868e9f864363a4885961d1813cb2bee51f",
|
||||||
@@ -73,43 +73,43 @@
|
|||||||
"packages/ui/components/Popover.wrn": "167f6c476cf3114ac5062ecf7739bddd9b5a81b1d209396a3675067dad1577b2",
|
"packages/ui/components/Popover.wrn": "167f6c476cf3114ac5062ecf7739bddd9b5a81b1d209396a3675067dad1577b2",
|
||||||
"packages/ui/components/PortalDashboard.wrn": "037d4300b59c7d60543abc7d4aba5c738efc143e9b61abc48aad0ddfcfe6845b",
|
"packages/ui/components/PortalDashboard.wrn": "037d4300b59c7d60543abc7d4aba5c738efc143e9b61abc48aad0ddfcfe6845b",
|
||||||
"packages/ui/components/PreferenceSwitcher.wrn": "2cc186d4dcb6580b4b152e3a265d9ed5ad210d3fdc76330b9092db21894465f0",
|
"packages/ui/components/PreferenceSwitcher.wrn": "2cc186d4dcb6580b4b152e3a265d9ed5ad210d3fdc76330b9092db21894465f0",
|
||||||
"packages/ui/components/PublicPageShell.wrn": "507baad0e83dc05c24db42b8af8bd45b18f4e32e418843d77ec906428c687199",
|
"packages/ui/components/PublicPageShell.wrn": "369b74f65e27227311a2ed73e9ca56c8b60908100d6840a798e8ba5f2c8b1040",
|
||||||
"packages/ui/components/Radio.wrn": "0b2d38a5aee3e859280e4590fa1d509d789cc2239082054872fa342817735f1b",
|
"packages/ui/components/Radio.wrn": "0b2d38a5aee3e859280e4590fa1d509d789cc2239082054872fa342817735f1b",
|
||||||
"packages/ui/components/RangeSlider.wrn": "21eb7a5df0ee2cb5e78f628eb920265998eb9f1a4933d4e5c57db0323fd66b41",
|
"packages/ui/components/RangeSlider.wrn": "21eb7a5df0ee2cb5e78f628eb920265998eb9f1a4933d4e5c57db0323fd66b41",
|
||||||
"packages/ui/components/Rating.wrn": "a2d74dc748fc7d98892684c760518b87fa65411b1102e3611252b87245b3ffcb",
|
"packages/ui/components/Rating.wrn": "a2d74dc748fc7d98892684c760518b87fa65411b1102e3611252b87245b3ffcb",
|
||||||
"packages/ui/components/Scrollspy.wrn": "76d1c17580c8d460f1222ce97585bdcac9779141f2f30d5460c84ff9f75413d8",
|
"packages/ui/components/Scrollspy.wrn": "76d1c17580c8d460f1222ce97585bdcac9779141f2f30d5460c84ff9f75413d8",
|
||||||
"packages/ui/components/SearchBox.wrn": "315f54f1feaaa47a815d1e2d7a35b492f09fbfadfc6d37228e1009e19e0652ad",
|
"packages/ui/components/SearchBox.wrn": "4a07358530ffb197d80d816b6ee4335a20812b6bee1e66a845c4075305bee6f7",
|
||||||
"packages/ui/components/Section.wrn": "21485de07d8bb986837a65c61c5dd01ba6c2f3d4e37d58c154a584c7b58de0ed",
|
"packages/ui/components/Section.wrn": "33eb8a82a2102229c2b1f64cec497e9e8e70b67adab8dbe396be860fccbb699c",
|
||||||
"packages/ui/components/SectionHeader.wrn": "512cb96636ee1f0540a0f4b4c75603fc0fe7536e7ed7ed7dc82173a16f48a4d3",
|
"packages/ui/components/SectionHeader.wrn": "8eecf2ea7a93139512260e3d46ca2a1afeb341b8bd46b7c30baa6e2c75e25d10",
|
||||||
"packages/ui/components/Select.wrn": "7f046bb11b7c2470dae26d91a4b2261c66a40ae054d0e04c69b6748912d1e204",
|
"packages/ui/components/Select.wrn": "7f046bb11b7c2470dae26d91a4b2261c66a40ae054d0e04c69b6748912d1e204",
|
||||||
"packages/ui/components/Sidebar.wrn": "03f1bbce75ca6d50ed940e62df39c539610e89eadd2064fe24abc7d5470f98bf",
|
"packages/ui/components/Sidebar.wrn": "03f1bbce75ca6d50ed940e62df39c539610e89eadd2064fe24abc7d5470f98bf",
|
||||||
"packages/ui/components/SplitHero.wrn": "70e843565ff869bcf413b11b6d9830b2e2bd229863a00904596f71e2dff0e76d",
|
"packages/ui/components/SplitHero.wrn": "70e843565ff869bcf413b11b6d9830b2e2bd229863a00904596f71e2dff0e76d",
|
||||||
"packages/ui/components/StatsBar.wrn": "c7d1df3895f25b6d3a2e1012a18b97592c7f33e65418b880d486f20c2d490686",
|
"packages/ui/components/StatsBar.wrn": "c7d1df3895f25b6d3a2e1012a18b97592c7f33e65418b880d486f20c2d490686",
|
||||||
"packages/ui/components/Stepper.wrn": "09f216a44f888421091bd1bce760a076927500a573550d5b2b10c4f27f608e92",
|
"packages/ui/components/Stepper.wrn": "df9093e4222ef3250963a8c6fbfec74477242735d23eabe896c29731c54fc14d",
|
||||||
"packages/ui/components/StrongPassword.wrn": "c7c5ef26ece6170dd7db9882f0dc98cb2e4607f1e5d43eb3fd39e5d15bbd3a2e",
|
"packages/ui/components/StrongPassword.wrn": "c7c5ef26ece6170dd7db9882f0dc98cb2e4607f1e5d43eb3fd39e5d15bbd3a2e",
|
||||||
"packages/ui/components/StyledIcon.wrn": "4a4504e357dee9dd0418edbe85fc90b824ccdb3752123a2125da95b77bf0b336",
|
"packages/ui/components/StyledIcon.wrn": "4a4504e357dee9dd0418edbe85fc90b824ccdb3752123a2125da95b77bf0b336",
|
||||||
"packages/ui/components/Switch.wrn": "ccb74599fab72b0d68b09a7f1f90b7732cb2f9cbed67a84219e897575ce30c28",
|
"packages/ui/components/Switch.wrn": "ccb74599fab72b0d68b09a7f1f90b7732cb2f9cbed67a84219e897575ce30c28",
|
||||||
"packages/ui/components/Tabs.wrn": "4fa0c0854700532960043290700d7cf99663ec41692068101f0aae4c2b1a1181",
|
"packages/ui/components/Tabs.wrn": "e38336d28876caa4e97da32a569749e3803b030284a85ce9f35fa788e51cc5b0",
|
||||||
"packages/ui/components/TextLink.wrn": "30782039293eb36d63b7b3a4f32a71a47177a3a68c7e90184be7cf7b4385eb19",
|
"packages/ui/components/TextLink.wrn": "30782039293eb36d63b7b3a4f32a71a47177a3a68c7e90184be7cf7b4385eb19",
|
||||||
"packages/ui/components/Textarea.wrn": "ddf0b4f124b2cf0c0ab3d820d3ac0085f7c20466e977231949be264cd0cee8cf",
|
"packages/ui/components/Textarea.wrn": "ddf0b4f124b2cf0c0ab3d820d3ac0085f7c20466e977231949be264cd0cee8cf",
|
||||||
"packages/ui/components/TimePicker.wrn": "2e8e7a90f6b6069a07e7ffd2725ba1e1031e84d55a4f1254025befbb314fa695",
|
"packages/ui/components/TimePicker.wrn": "2e8e7a90f6b6069a07e7ffd2725ba1e1031e84d55a4f1254025befbb314fa695",
|
||||||
"packages/ui/components/Timeline.wrn": "5708c656eefd12f31c93490075ee482bf527059028844bd58cdcddc88461e2b5",
|
"packages/ui/components/Timeline.wrn": "aec123bf69f6bfa41c3564e4eac18b2a245214dc6905ebd0bf5b69f7c2736ae6",
|
||||||
"packages/ui/components/Toast.wrn": "f37c584d1c1a66401deb53d915c8ee0c70aaf7baa1d3c297fa74c5bdb914dd1d",
|
"packages/ui/components/Toast.wrn": "f37c584d1c1a66401deb53d915c8ee0c70aaf7baa1d3c297fa74c5bdb914dd1d",
|
||||||
"packages/ui/components/ToastNotifications.wrn": "33ff76b2a0a129ff896baea8979b4be97f7ec4471a92a2da970403a5c46e8b03",
|
"packages/ui/components/ToastNotifications.wrn": "33ff76b2a0a129ff896baea8979b4be97f7ec4471a92a2da970403a5c46e8b03",
|
||||||
"packages/ui/components/Toaster.wrn": "7481ecddde9ed5bf1f448d45a78da7ee0009f84963814bf681735db4e5ab75f9",
|
"packages/ui/components/Toaster.wrn": "7481ecddde9ed5bf1f448d45a78da7ee0009f84963814bf681735db4e5ab75f9",
|
||||||
"packages/ui/components/ToggleCount.wrn": "70a75b2bdcc89103f8ca300ee6d21cd61baf8c6a4aeade9b68d1dc529f77064b",
|
"packages/ui/components/ToggleCount.wrn": "17710fb37fc6953911acec4e80cd95c1202836e9b958ae4ce34c9a9639edae95",
|
||||||
"packages/ui/components/TogglePassword.wrn": "405a85cbfa3d0ff0185b52d2805fba88497a5f25501f01b2438ed3a28591a38d",
|
"packages/ui/components/TogglePassword.wrn": "405a85cbfa3d0ff0185b52d2805fba88497a5f25501f01b2438ed3a28591a38d",
|
||||||
"packages/ui/components/Tooltip.wrn": "e6c8c14a75062d04a2e64245df1a40e67785240573c73bae4b0b32e76ef822bc",
|
"packages/ui/components/Tooltip.wrn": "e6c8c14a75062d04a2e64245df1a40e67785240573c73bae4b0b32e76ef822bc",
|
||||||
"packages/ui/components/TreeView.wrn": "1791a10135595b17b5c746af9e0476e8520d516ba46d64c79dc4efe0af2b500d",
|
"packages/ui/components/TreeView.wrn": "1791a10135595b17b5c746af9e0476e8520d516ba46d64c79dc4efe0af2b500d",
|
||||||
"packages/ui/components/Typography.wrn": "a667e800e11d23da74b00047bd9c560a65a5920e5394f58f66a6e0b32572ce8e",
|
"packages/ui/components/Typography.wrn": "1b4d1b91dee0ff522d27c566becc3bc49bd9ec979ae6334e6a15fca5d88eccac",
|
||||||
"packages/ui/components/WysiwygEditor.wrn": "636e60b9f9be7a5807cca7ad20e0b0f370ee1ec6c1ecba5d0a577726cc86bc98",
|
"packages/ui/components/WysiwygEditor.wrn": "636e60b9f9be7a5807cca7ad20e0b0f370ee1ec6c1ecba5d0a577726cc86bc98",
|
||||||
"packages/ui/components/alert.wrn": "a6020b3fbf02481f76cea4cfa563a7165c7ccc2920492f6f6b79e98cbf2cf0fa",
|
"packages/ui/components/alert.wrn": "3f4c4c90c2b5a00a13d0fa1e7e48e4898869dd27a50ff412a51d7bcc87a0baac",
|
||||||
"packages/ui/components/avatar.wrn": "571b70790aff28a5b7d6adbf0196e77ece1ce153a95b384148cb2bb5f74ab2e9",
|
"packages/ui/components/avatar.wrn": "571b70790aff28a5b7d6adbf0196e77ece1ce153a95b384148cb2bb5f74ab2e9",
|
||||||
"packages/ui/components/button.wrn": "647af3918142fd9151e46555345532980633cc3677ec26d0940c253ea789bc31",
|
"packages/ui/components/button.wrn": "647af3918142fd9151e46555345532980633cc3677ec26d0940c253ea789bc31",
|
||||||
"packages/ui/components/carousel.wrn": "37bdde82de59e90cf02c9fed0ee11f5ddd2979246932701dad9412c4fd358a6a",
|
"packages/ui/components/carousel.wrn": "37bdde82de59e90cf02c9fed0ee11f5ddd2979246932701dad9412c4fd358a6a",
|
||||||
"packages/ui/components/progress.wrn": "ba6f4dfcc00f04f34e9533be675bb4a6200c3cdcd7d03fc597377e48520fdec7",
|
"packages/ui/components/progress.wrn": "ba6f4dfcc00f04f34e9533be675bb4a6200c3cdcd7d03fc597377e48520fdec7",
|
||||||
"packages/ui/components/skeleton.wrn": "ceec8af147b8be08155500e378393ac7c72d819da61b62191c076c80e943d5a9",
|
"packages/ui/components/skeleton.wrn": "ceec8af147b8be08155500e378393ac7c72d819da61b62191c076c80e943d5a9",
|
||||||
"packages/ui/components/spinner.wrn": "abc4ee3ede2e019289257e9009eee012c880a85839cc220fac6dbe1b780caf52",
|
"packages/ui/components/spinner.wrn": "abc4ee3ede2e019289257e9009eee012c880a85839cc220fac6dbe1b780caf52",
|
||||||
"packages/ui/ui.css": "f71641efb0c98b673af70c10dbcea8e693de258ce8620b4f84c64553ea70204e"
|
"packages/ui/ui.css": "3138b86f269b6f7e67922ef2c56918444d562b11f4ae6f1fab98b63805cd78dc"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "wrnexus",
|
"name": "wrnexus",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "wrnexus",
|
"name": "wrnexus",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"license": "SEE LICENSE IN LICENSE",
|
"license": "SEE LICENSE IN LICENSE",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"vscode-languageclient": "^10.1.0"
|
"vscode-languageclient": "^10.1.0"
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"name": "wrnexus",
|
"name": "wrnexus",
|
||||||
"displayName": "WRNexus Language Support",
|
"displayName": "WRNexus Language Support",
|
||||||
"description": "Complete WRNexus v0.8.3 language support for typed imports, props, state, outputs, runtime functions, stores, diagnostics, formatting, navigation, and migration assistance.",
|
"description": "Complete WRNexus v0.8.3 language support for typed imports, props, state, outputs, runtime functions, stores, diagnostics, formatting, navigation, and migration assistance.",
|
||||||
"version": "0.8.5",
|
"version": "0.8.6",
|
||||||
"publisher": "wrnexus",
|
"publisher": "wrnexus",
|
||||||
"private": true,
|
"private": true,
|
||||||
"license": "SEE LICENSE IN LICENSE",
|
"license": "SEE LICENSE IN LICENSE",
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// WRN editor extension source hash: 6afaf7958331407986761b491ad81d56458dcb162f56369a4cc29f86ff95d981
|
// WRN editor extension source hash: 6165420f37af57e441086efeb6b25528f72e77a39abb2c76ca5bc8748dd90c2f
|
||||||
// WRN editor extension generator hash: 456d1d614e44e5fb1f19b784176c09cf2ade9b64ef73a17934c2698150b62728
|
// WRN editor extension generator hash: 456d1d614e44e5fb1f19b784176c09cf2ade9b64ef73a17934c2698150b62728
|
||||||
"use strict";
|
"use strict";
|
||||||
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
// WRN editor language server source hash: c4362f7edf117e0c403c9bce9435bc02ae0febd963edb4af9a18d2d74d87eb47
|
// WRN editor language server source hash: 65a5536efbc7c9fee15040559bb48afe78c4686fc5e7341ffc941cc7113c8556
|
||||||
// WRN editor language server generator hash: f593a44aaf05495b789ce7a3086bee1eebb951b884d41c0e017bbcfe5f547e72
|
// WRN editor language server generator hash: f593a44aaf05495b789ce7a3086bee1eebb951b884d41c0e017bbcfe5f547e72
|
||||||
// @bun @bun-cjs
|
// @bun @bun-cjs
|
||||||
(function(exports, require, module, __filename, __dirname) {var __create = Object.create;
|
(function(exports, require, module, __filename, __dirname) {var __create = Object.create;
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ component PublicLayout {
|
|||||||
<a href="/chat">{t:nav.chat}</a>
|
<a href="/chat">{t:nav.chat}</a>
|
||||||
<a href="/dashboard">{t:nav.dashboard}</a>
|
<a href="/dashboard">{t:nav.dashboard}</a>
|
||||||
<a href="/about">{t:nav.about}</a>
|
<a href="/about">{t:nav.about}</a>
|
||||||
|
<a href="/navigation">{t:nav.navigation}</a>
|
||||||
|
<a href="/layout">{t:nav.layout}</a>
|
||||||
<button type="button" data-wire-theme-toggle aria-label="Toggle color theme">Theme</button>
|
<button type="button" data-wire-theme-toggle aria-label="Toggle color theme">Theme</button>
|
||||||
<button class="wire-btn wire-btn--ghost wire-btn--sm" data-wire-lang-set="en">EN</button>
|
<button class="wire-btn wire-btn--ghost wire-btn--sm" data-wire-lang-set="en">EN</button>
|
||||||
<button class="wire-btn wire-btn--ghost wire-btn--sm" data-wire-lang-set="es">ES</button>
|
<button class="wire-btn wire-btn--ghost wire-btn--sm" data-wire-lang-set="es">ES</button>
|
||||||
|
|||||||
@@ -4,7 +4,9 @@
|
|||||||
"ui": "UI",
|
"ui": "UI",
|
||||||
"chat": "Chat",
|
"chat": "Chat",
|
||||||
"dashboard": "Dashboard",
|
"dashboard": "Dashboard",
|
||||||
"about": "About"
|
"about": "About",
|
||||||
|
"navigation": "Navigation",
|
||||||
|
"layout": "Layout"
|
||||||
},
|
},
|
||||||
"home": {
|
"home": {
|
||||||
"title": "Hello from WrNexus",
|
"title": "Hello from WrNexus",
|
||||||
|
|||||||
@@ -4,7 +4,9 @@
|
|||||||
"ui": "UI",
|
"ui": "UI",
|
||||||
"chat": "Chat",
|
"chat": "Chat",
|
||||||
"dashboard": "Panel",
|
"dashboard": "Panel",
|
||||||
"about": "Acerca de"
|
"about": "Acerca de",
|
||||||
|
"navigation": "Navegación",
|
||||||
|
"layout": "Diseño"
|
||||||
},
|
},
|
||||||
"home": {
|
"home": {
|
||||||
"title": "Hola desde WrNexus",
|
"title": "Hola desde WrNexus",
|
||||||
|
|||||||
@@ -0,0 +1,211 @@
|
|||||||
|
// Layout tour. Route: /layout
|
||||||
|
//
|
||||||
|
// One page built out of the layout set, rather than showing each piece alone:
|
||||||
|
//
|
||||||
|
// PublicPageShell the outer shell, holding the page background
|
||||||
|
// Section each band down the page, with its own spacing and tint
|
||||||
|
// SectionHeader the eyebrow, heading and description of each band
|
||||||
|
// Container the reading width
|
||||||
|
// Grid the card deck, including an auto-fit track
|
||||||
|
// Columns the coarse two-way split
|
||||||
|
// LayoutSplitter a resizable pane, by drag or by arrow key
|
||||||
|
// CustomScrollbar a themed scrolling region
|
||||||
|
// Divider the rules between bands
|
||||||
|
// Typography the prose column
|
||||||
|
// Image, Link, Kbd the smaller pieces inside it
|
||||||
|
//
|
||||||
|
// CustomScrollbar sits beside the splitter rather than inside a pane of it: a
|
||||||
|
// component tag nested in another component slot is dropped, and only its
|
||||||
|
// children survive.
|
||||||
|
//
|
||||||
|
// The splitter does not report into a status line here. It emits a sizeChange
|
||||||
|
// output and the component does fire it, but a parent binding on the tag is
|
||||||
|
// not invoked, so wiring one up would show something that never updates.
|
||||||
|
page LayoutTour {
|
||||||
|
layout = "public"
|
||||||
|
|
||||||
|
seo {
|
||||||
|
title = "Layout tour"
|
||||||
|
description = "Every layout component working together on one page."
|
||||||
|
}
|
||||||
|
|
||||||
|
view {
|
||||||
|
<PublicPageShell background="default" minHeight="dvh" fullWidth={true}>
|
||||||
|
<Section spacing="lg" variant="soft" borderBottom={true}>
|
||||||
|
<Container maxWidth="lg" columns={1}>
|
||||||
|
<SectionHeader
|
||||||
|
eyebrow="Layout"
|
||||||
|
title="Composing a page"
|
||||||
|
description="Every band on this page is a Section. The width you are reading at is a Container, and the pieces inside are the rest of the layout set."
|
||||||
|
align="center"
|
||||||
|
maxWidth="2xl"
|
||||||
|
/>
|
||||||
|
</Container>
|
||||||
|
</Section>
|
||||||
|
|
||||||
|
<Section spacing="lg">
|
||||||
|
<Container maxWidth="lg" columns={1}>
|
||||||
|
<SectionHeader
|
||||||
|
eyebrow="Grid"
|
||||||
|
title="Card decks"
|
||||||
|
description="A fixed column count collapses at each breakpoint. Pass minItemWidth instead and the browser decides the count, reflowing continuously."
|
||||||
|
headingLevel={3}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Divider />
|
||||||
|
|
||||||
|
<Grid columns={3} gap="md">
|
||||||
|
<div class="tour-card">
|
||||||
|
<h4>Fixed columns</h4>
|
||||||
|
<p>Three tracks on a wide screen, two on a tablet, one on a phone.</p>
|
||||||
|
</div>
|
||||||
|
<div class="tour-card">
|
||||||
|
<h4>Themed</h4>
|
||||||
|
<p>Every surface here is a theme token, so light and dark both work.</p>
|
||||||
|
</div>
|
||||||
|
<div class="tour-card">
|
||||||
|
<h4>No Tailwind</h4>
|
||||||
|
<p>These components carry their own styles and no longer need it.</p>
|
||||||
|
</div>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Divider label="auto fit" />
|
||||||
|
|
||||||
|
<Grid minItemWidth="12rem" gap="sm">
|
||||||
|
<div class="tour-card tour-card--compact"><h4>One</h4></div>
|
||||||
|
<div class="tour-card tour-card--compact"><h4>Two</h4></div>
|
||||||
|
<div class="tour-card tour-card--compact"><h4>Three</h4></div>
|
||||||
|
<div class="tour-card tour-card--compact"><h4>Four</h4></div>
|
||||||
|
<div class="tour-card tour-card--compact"><h4>Five</h4></div>
|
||||||
|
</Grid>
|
||||||
|
</Container>
|
||||||
|
</Section>
|
||||||
|
|
||||||
|
<Section spacing="lg" variant="soft" borderTop={true} borderBottom={true}>
|
||||||
|
<Container maxWidth="lg" columns={1}>
|
||||||
|
<SectionHeader
|
||||||
|
eyebrow="Split"
|
||||||
|
title="Columns and panes"
|
||||||
|
description="Columns is the coarse split of a page. LayoutSplitter is the one the reader can move."
|
||||||
|
headingLevel={3}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Columns columns={2} gap="lg">
|
||||||
|
<Typography maxWidth="full">
|
||||||
|
<h4>Prose</h4>
|
||||||
|
<p>
|
||||||
|
Typography caps the measure so a line never runs too long to
|
||||||
|
follow. Inside it you get the smaller pieces: a
|
||||||
|
<Link href="/navigation" label="link" /> to somewhere else, and
|
||||||
|
<Kbd label="Ctrl" /> <Kbd label="K" /> for a shortcut.
|
||||||
|
</p>
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
<Image src="" alt="Placeholder artwork" size="video" rounded={true} />
|
||||||
|
</Columns>
|
||||||
|
</Container>
|
||||||
|
</Section>
|
||||||
|
|
||||||
|
<Section spacing="lg">
|
||||||
|
<Container maxWidth="lg" columns={1}>
|
||||||
|
<SectionHeader
|
||||||
|
eyebrow="Interactive"
|
||||||
|
title="Resize and scroll"
|
||||||
|
description="The splitter resolves its size in the runtime and reports it here. The scrolling region themes its own scrollbar."
|
||||||
|
headingLevel={3}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<p class="tour-status">
|
||||||
|
Drag the divider, or focus it and use the arrow keys. Home and End
|
||||||
|
go to the bounds. The live value is on the handle itself, as
|
||||||
|
aria-valuenow, which is what a screen reader announces.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<LayoutSplitter size={45} minSize={20} step={5} label="Resize the panes">
|
||||||
|
<div data-slot="start">
|
||||||
|
<div class="tour-pane">
|
||||||
|
<h4>Start pane</h4>
|
||||||
|
<p>Drag the divider, or focus it and use the arrow keys. Home and End go to the bounds.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div data-slot="end">
|
||||||
|
<div class="tour-pane">
|
||||||
|
<h4>End pane</h4>
|
||||||
|
<p>The size is resolved in the runtime and written onto the container, so the panes are plain grid tracks.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</LayoutSplitter>
|
||||||
|
|
||||||
|
<Divider label="scrolling" />
|
||||||
|
|
||||||
|
<CustomScrollbar maxHeight="12rem" thickness={10}>
|
||||||
|
<div class="tour-scroll">
|
||||||
|
<p>This region scrolls, and its scrollbar follows the theme.</p>
|
||||||
|
<p>Scrollbar appearance is CSS rather than script.</p>
|
||||||
|
<p>scrollbar-width and scrollbar-color are the standard properties.</p>
|
||||||
|
<p>The webkit rules cover the engines that still need them.</p>
|
||||||
|
<p>Enough lines here that the region actually overflows.</p>
|
||||||
|
<p>Otherwise there would be no scrollbar to look at.</p>
|
||||||
|
<p>Which is the mistake the showcase demo made first time.</p>
|
||||||
|
</div>
|
||||||
|
</CustomScrollbar>
|
||||||
|
</Container>
|
||||||
|
</Section>
|
||||||
|
</PublicPageShell>
|
||||||
|
}
|
||||||
|
|
||||||
|
style {
|
||||||
|
.tour-card {
|
||||||
|
padding: 1rem;
|
||||||
|
border: 1px solid var(--wire-color-border);
|
||||||
|
border-radius: var(--wire-radius-md);
|
||||||
|
background: var(--wire-color-surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tour-card h4,
|
||||||
|
.tour-pane h4 {
|
||||||
|
margin: 0 0 0.35rem;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tour-card p,
|
||||||
|
.tour-pane p,
|
||||||
|
.tour-scroll p {
|
||||||
|
margin: 0;
|
||||||
|
color: var(--wire-color-text-muted);
|
||||||
|
font-size: 0.86rem;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tour-card--compact {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tour-status {
|
||||||
|
margin: 0 0 0.75rem;
|
||||||
|
padding: 0.5rem 0.75rem;
|
||||||
|
border: 1px solid var(--wire-color-border);
|
||||||
|
border-radius: var(--wire-radius-sm);
|
||||||
|
background: var(--wire-color-surface-soft);
|
||||||
|
color: var(--wire-color-text-muted);
|
||||||
|
font-size: 0.82rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tour-pane {
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tour-scroll {
|
||||||
|
display: grid;
|
||||||
|
gap: 0.6rem;
|
||||||
|
padding: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The splitter panes need a floor or they collapse to their text. */
|
||||||
|
.tour-pane,
|
||||||
|
.tour-scroll {
|
||||||
|
min-height: 8rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,438 @@
|
|||||||
|
// Navigation tour. Route: /navigation
|
||||||
|
//
|
||||||
|
// One page that wires every navigation component together the way a real
|
||||||
|
// console would, rather than showing each in isolation:
|
||||||
|
//
|
||||||
|
// Navbar the top bar, with a dropdown built from nested children
|
||||||
|
// MegaMenu a wide product panel beside it
|
||||||
|
// Breadcrumb the trail under the bar
|
||||||
|
// Sidebar the left rail, which becomes a Drawer on a phone
|
||||||
|
// Tabs the main content, backed by a tab query parameter
|
||||||
|
// Stepper a wizard inside one tab, gated on a checkbox
|
||||||
|
// Pagination under the list in another tab
|
||||||
|
// Scrollspy a contents rail that follows the reader down the article
|
||||||
|
// Nav the secondary links in the footer
|
||||||
|
//
|
||||||
|
// Object props are held in state and bound. Passing one inline as an
|
||||||
|
// attribute would put a brace at the start of the value, which the compiler
|
||||||
|
// reads as an interpolation.
|
||||||
|
page NavigationTour {
|
||||||
|
layout = "public"
|
||||||
|
|
||||||
|
seo {
|
||||||
|
title = "Navigation tour"
|
||||||
|
description = "Every navigation component working together in one shell."
|
||||||
|
}
|
||||||
|
|
||||||
|
state brand = { label: "Acme", description: "Console", href: "/navigation" }
|
||||||
|
|
||||||
|
state topLinks = [
|
||||||
|
{ label: "Overview", href: "/navigation", value: "overview" },
|
||||||
|
{
|
||||||
|
label: "Workspace",
|
||||||
|
value: "workspace",
|
||||||
|
columns: 2,
|
||||||
|
description: "Everything your team touches.",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
label: "Projects",
|
||||||
|
children: [
|
||||||
|
{ label: "Active", href: "/navigation", description: "In flight right now." },
|
||||||
|
{ label: "Archived", href: "/navigation", description: "Kept for the record." }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "People",
|
||||||
|
children: [
|
||||||
|
{ label: "Members", href: "/navigation", description: "Who can sign in." },
|
||||||
|
{ label: "Roles", href: "/navigation", description: "What they may do." }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{ label: "Reports", href: "/navigation", value: "reports" }
|
||||||
|
]
|
||||||
|
|
||||||
|
state topActions = [
|
||||||
|
{ label: "Docs", href: "/about", variant: "link" },
|
||||||
|
{ label: "New project", href: "/navigation", variant: "primary" }
|
||||||
|
]
|
||||||
|
|
||||||
|
state megaColumns = [
|
||||||
|
{
|
||||||
|
heading: "Platform",
|
||||||
|
items: [
|
||||||
|
{ label: "Runtime", href: "/navigation", description: "The browser half.", icon: "icon-[lucide--cpu]" },
|
||||||
|
{ label: "Compiler", href: "/navigation", description: "WRN to JavaScript.", icon: "icon-[lucide--hammer]" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
heading: "Tooling",
|
||||||
|
items: [
|
||||||
|
{ label: "CLI", href: "/navigation", description: "Scaffold and deploy.", icon: "icon-[lucide--terminal]" },
|
||||||
|
{ label: "Editor", href: "/navigation", description: "Language server.", icon: "icon-[lucide--code]" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
state crumbs = [
|
||||||
|
{ label: "Home", href: "/" },
|
||||||
|
{ label: "Console", href: "/navigation" },
|
||||||
|
{ label: "Navigation tour" }
|
||||||
|
]
|
||||||
|
|
||||||
|
state sideItems = [
|
||||||
|
{ label: "Overview", href: "#overview", value: "overview", icon: "icon-[lucide--gauge]" },
|
||||||
|
{
|
||||||
|
heading: "Build",
|
||||||
|
items: [
|
||||||
|
{ label: "Projects", href: "#projects", value: "projects", badge: "4" },
|
||||||
|
{
|
||||||
|
label: "Environments",
|
||||||
|
value: "envs",
|
||||||
|
items: [
|
||||||
|
{ label: "Production", href: "#projects", value: "prod" },
|
||||||
|
{ label: "Staging", href: "#projects", value: "staging" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
heading: "Account",
|
||||||
|
items: [{ label: "Settings", href: "#settings", value: "settings", icon: "icon-[lucide--settings]" }]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
state contentTabs = [
|
||||||
|
{ label: "Article", value: "article", title: "Release notes" },
|
||||||
|
{ label: "Wizard", value: "wizard", title: "Create a project" },
|
||||||
|
{ label: "Members", value: "members", title: "Who can sign in" }
|
||||||
|
]
|
||||||
|
|
||||||
|
state spyLinks = [
|
||||||
|
{ label: "Overview", href: "#overview" },
|
||||||
|
{ label: "Projects", href: "#projects" },
|
||||||
|
{ label: "Settings", href: "#settings" }
|
||||||
|
]
|
||||||
|
|
||||||
|
state wizardSteps = [
|
||||||
|
{ label: "Details", title: "Name the project", content: "Pick something the team will recognise." },
|
||||||
|
{ label: "Access", title: "Who can see it", content: "Invite people now or later." },
|
||||||
|
{ label: "Review", title: "Check and create", content: "Nothing is created until you finish." }
|
||||||
|
]
|
||||||
|
|
||||||
|
state footerLinks = [
|
||||||
|
{ label: "Status", href: "/navigation", value: "status" },
|
||||||
|
{ label: "Changelog", href: "/navigation", value: "changelog" },
|
||||||
|
{ label: "Support", href: "/about", value: "support" }
|
||||||
|
]
|
||||||
|
|
||||||
|
state members = [
|
||||||
|
"A. Okafor", "R. Silva", "M. Chen", "J. Dubois", "P. Novak",
|
||||||
|
"T. Ahmed", "L. Rossi", "K. Bauer", "S. Haddad", "N. Ito"
|
||||||
|
]
|
||||||
|
|
||||||
|
// Tabs reports the selection and this page owns what is shown. Slot content
|
||||||
|
// and component props are rendered once and do not track page state, so
|
||||||
|
// anything that has to react lives out here in page scope.
|
||||||
|
state section = "article"
|
||||||
|
state sideActive = "overview"
|
||||||
|
state wizardStep = 0
|
||||||
|
// Not named page: that is the page keyword and shadows the runtime binding.
|
||||||
|
state currentPage = 1
|
||||||
|
state pageSize = 4
|
||||||
|
state lastEvent = "Nothing yet. Interact with any control."
|
||||||
|
|
||||||
|
functions {
|
||||||
|
client function onSideSelect(payload) {
|
||||||
|
sideActive = payload.value || ""
|
||||||
|
lastEvent = "Sidebar select: " + (payload.value || "(none)")
|
||||||
|
}
|
||||||
|
|
||||||
|
client function onTabChange(payload) {
|
||||||
|
section = payload.value
|
||||||
|
lastEvent = "Tab change: " + payload.value
|
||||||
|
}
|
||||||
|
|
||||||
|
// The stepper never validates anything itself. This page owns the
|
||||||
|
// checkbox, so it decides when the step may advance.
|
||||||
|
client function onWizardChange(payload) {
|
||||||
|
wizardStep = payload.index
|
||||||
|
lastEvent = "Wizard step: " + (payload.index + 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
client function onWizardFinish() {
|
||||||
|
lastEvent = "Wizard finished. A real app would create the project here."
|
||||||
|
}
|
||||||
|
|
||||||
|
client function onWizardSkip(payload) {
|
||||||
|
wizardStep = payload.index
|
||||||
|
lastEvent = "Wizard skipped to step " + (payload.index + 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
client function onPageChange(payload) {
|
||||||
|
currentPage = payload.page
|
||||||
|
lastEvent = "Page " + payload.page
|
||||||
|
}
|
||||||
|
|
||||||
|
client function onSpyChange(payload) {
|
||||||
|
lastEvent = "Reading: " + payload.label
|
||||||
|
}
|
||||||
|
|
||||||
|
client function onMegaSelect(payload) {
|
||||||
|
lastEvent = "Mega menu: " + payload.value
|
||||||
|
}
|
||||||
|
|
||||||
|
client function onNavSelect(payload) {
|
||||||
|
lastEvent = "Footer nav: " + payload.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
view {
|
||||||
|
<div class="tour">
|
||||||
|
<Navbar
|
||||||
|
brand={brand}
|
||||||
|
items={topLinks}
|
||||||
|
actions={topActions}
|
||||||
|
active="overview"
|
||||||
|
label="Primary navigation"
|
||||||
|
mobileLabel="Toggle navigation"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div class="tour__toolbar">
|
||||||
|
<MegaMenu
|
||||||
|
label="Products"
|
||||||
|
icon="icon-[lucide--box]"
|
||||||
|
columns={megaColumns}
|
||||||
|
footer="Not sure where to start? Talk to us."
|
||||||
|
@select="onMegaSelect(payload)"
|
||||||
|
/>
|
||||||
|
<Breadcrumb items={crumbs} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="tour__shell">
|
||||||
|
<aside class="tour__rail">
|
||||||
|
<Sidebar
|
||||||
|
items={sideItems}
|
||||||
|
active={sideActive}
|
||||||
|
label="Console"
|
||||||
|
mobileLabel="Open navigation"
|
||||||
|
drawerTitle="Console"
|
||||||
|
@select="onSideSelect(payload)"
|
||||||
|
/>
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
<main class="tour__main">
|
||||||
|
<p class="tour__status" role="status">{lastEvent}</p>
|
||||||
|
|
||||||
|
<Tabs
|
||||||
|
items={contentTabs}
|
||||||
|
active="article"
|
||||||
|
mode="url"
|
||||||
|
param="tab"
|
||||||
|
label="Console sections"
|
||||||
|
@change="onTabChange(payload)"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<section class="tour__panel" data-show="section === 'article'">
|
||||||
|
<section id="overview" class="tour__section">
|
||||||
|
<h3>Overview</h3>
|
||||||
|
<p>
|
||||||
|
Scroll this column and the contents rail on the right follows along.
|
||||||
|
The runtime observes these sections against the viewport and moves
|
||||||
|
aria-current to the matching link.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="projects" class="tour__section">
|
||||||
|
<h3>Projects</h3>
|
||||||
|
<p>
|
||||||
|
The rail on the left is the Sidebar. Below the tablet breakpoint it
|
||||||
|
collapses behind a launcher and opens as a Drawer, which is where the
|
||||||
|
focus trap and the body scroll lock come from.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="settings" class="tour__section">
|
||||||
|
<h3>Settings</h3>
|
||||||
|
<p>
|
||||||
|
The tab you are reading is mirrored into the URL. Switch tabs and the
|
||||||
|
address bar follows, then use the browser back button.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="tour__panel" data-show="section === 'wizard'">
|
||||||
|
<Stepper
|
||||||
|
steps={wizardSteps}
|
||||||
|
active={wizardStep}
|
||||||
|
showPanel={true}
|
||||||
|
controls={true}
|
||||||
|
allowSkip={true}
|
||||||
|
nextDisabled={false}
|
||||||
|
backLabel="Back"
|
||||||
|
nextLabel="Next"
|
||||||
|
skipLabel="Skip"
|
||||||
|
finishLabel="Create project"
|
||||||
|
label="Create a project"
|
||||||
|
@change="onWizardChange(payload)"
|
||||||
|
@skip="onWizardSkip(payload)"
|
||||||
|
@finish="onWizardFinish()"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<p class="tour__note">
|
||||||
|
Back, Skip and Next each emit an output, shown in the status line
|
||||||
|
above, and Next becomes Create project on the last step. The marker
|
||||||
|
does not advance here: active is a component prop, and props are
|
||||||
|
rendered once rather than tracking page state. Set nextDisabled to
|
||||||
|
hold Next while a form is incomplete.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="tour__panel" data-show="section === 'members'">
|
||||||
|
<p class="tour__note">
|
||||||
|
Showing page {currentPage} of 3. Pagination reports the requested
|
||||||
|
page through its change output and the page decides what to do with
|
||||||
|
it; the counter above is bound to that state. Re-slicing the list
|
||||||
|
itself would need the list re-rendered, which an each block does not
|
||||||
|
do when state changes.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<ul class="tour__members">
|
||||||
|
{#each members as person}
|
||||||
|
<li>{person}</li>
|
||||||
|
{/each}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<Pagination
|
||||||
|
page={currentPage}
|
||||||
|
pageSize={pageSize}
|
||||||
|
total={members.length}
|
||||||
|
variant="numbered"
|
||||||
|
@change="onPageChange(payload)"
|
||||||
|
/>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<aside class="tour__toc">
|
||||||
|
<Scrollspy
|
||||||
|
items={spyLinks}
|
||||||
|
heading="On this page"
|
||||||
|
active="#overview"
|
||||||
|
@change="onSpyChange(payload)"
|
||||||
|
/>
|
||||||
|
</aside>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<footer class="tour__footer">
|
||||||
|
<Nav
|
||||||
|
items={footerLinks}
|
||||||
|
active="status"
|
||||||
|
label="Secondary"
|
||||||
|
collapsible={false}
|
||||||
|
@select="onNavSelect(payload)"
|
||||||
|
/>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
style {
|
||||||
|
.tour {
|
||||||
|
display: grid;
|
||||||
|
gap: 1rem;
|
||||||
|
padding-bottom: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tour__toolbar {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Three columns: the rail, the reading column and the contents. The middle
|
||||||
|
* column carries min-width 0 so a wide table or code block inside a tab
|
||||||
|
* cannot push the whole shell sideways.
|
||||||
|
*/
|
||||||
|
.tour__shell {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 15rem minmax(0, 1fr) 12rem;
|
||||||
|
gap: 1.5rem;
|
||||||
|
align-items: start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tour__main {
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tour__rail,
|
||||||
|
.tour__toc {
|
||||||
|
position: sticky;
|
||||||
|
top: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tour__status {
|
||||||
|
margin: 0 0 0.75rem;
|
||||||
|
padding: 0.5rem 0.75rem;
|
||||||
|
border: 1px solid var(--wire-color-border);
|
||||||
|
border-radius: var(--wire-radius-sm);
|
||||||
|
background: var(--wire-color-surface-soft);
|
||||||
|
color: var(--wire-color-text-muted);
|
||||||
|
font-size: 0.82rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tall enough that scrolling actually moves between sections. */
|
||||||
|
.tour__section {
|
||||||
|
min-height: 60vh;
|
||||||
|
padding-top: 0.5rem;
|
||||||
|
scroll-margin-top: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tour__section h3 {
|
||||||
|
margin: 0 0 0.4rem;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tour__section p {
|
||||||
|
margin: 0;
|
||||||
|
max-width: 46rem;
|
||||||
|
color: var(--wire-color-text-muted);
|
||||||
|
line-height: 1.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.tour__members {
|
||||||
|
display: grid;
|
||||||
|
gap: 0.35rem;
|
||||||
|
margin: 0 0 1rem;
|
||||||
|
padding: 0;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tour__members li {
|
||||||
|
padding: 0.5rem 0.75rem;
|
||||||
|
border: 1px solid var(--wire-color-border);
|
||||||
|
border-radius: var(--wire-radius-sm);
|
||||||
|
font-size: 0.88rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tour__footer {
|
||||||
|
padding-top: 1rem;
|
||||||
|
border-top: 1px solid var(--wire-color-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The rails fold away first; the reading column is what matters. */
|
||||||
|
@media (max-width: 1023px) {
|
||||||
|
.tour__shell {
|
||||||
|
grid-template-columns: minmax(0, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tour__rail,
|
||||||
|
.tour__toc {
|
||||||
|
position: static;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,8 +10,10 @@ export interface Routes {
|
|||||||
"/dashboard": Record<string, never>;
|
"/dashboard": Record<string, never>;
|
||||||
"/hello": Record<string, never>;
|
"/hello": Record<string, never>;
|
||||||
"/language-tools": Record<string, never>;
|
"/language-tools": Record<string, never>;
|
||||||
|
"/layout": Record<string, never>;
|
||||||
"/login": Record<string, never>;
|
"/login": Record<string, never>;
|
||||||
"/modal": Record<string, never>;
|
"/modal": Record<string, never>;
|
||||||
|
"/navigation": Record<string, never>;
|
||||||
"/partial-static": Record<string, never>;
|
"/partial-static": Record<string, never>;
|
||||||
"/platform-showcase": Record<string, never>;
|
"/platform-showcase": Record<string, never>;
|
||||||
"/reactive": Record<string, never>;
|
"/reactive": Record<string, never>;
|
||||||
@@ -30,8 +32,10 @@ export interface RouteNames {
|
|||||||
"dashboard": "/dashboard";
|
"dashboard": "/dashboard";
|
||||||
"hello": "/hello";
|
"hello": "/hello";
|
||||||
"language.tools": "/language-tools";
|
"language.tools": "/language-tools";
|
||||||
|
"layout": "/layout";
|
||||||
"login": "/login";
|
"login": "/login";
|
||||||
"modal": "/modal";
|
"modal": "/modal";
|
||||||
|
"navigation": "/navigation";
|
||||||
"partial.static": "/partial-static";
|
"partial.static": "/partial-static";
|
||||||
"platform.showcase": "/platform-showcase";
|
"platform.showcase": "/platform-showcase";
|
||||||
"reactive": "/reactive";
|
"reactive": "/reactive";
|
||||||
@@ -119,8 +123,10 @@ export function route<N extends RouteName>(
|
|||||||
"dashboard": "/dashboard",
|
"dashboard": "/dashboard",
|
||||||
"hello": "/hello",
|
"hello": "/hello",
|
||||||
"language.tools": "/language-tools",
|
"language.tools": "/language-tools",
|
||||||
|
"layout": "/layout",
|
||||||
"login": "/login",
|
"login": "/login",
|
||||||
"modal": "/modal",
|
"modal": "/modal",
|
||||||
|
"navigation": "/navigation",
|
||||||
"partial.static": "/partial-static",
|
"partial.static": "/partial-static",
|
||||||
"platform.showcase": "/platform-showcase",
|
"platform.showcase": "/platform-showcase",
|
||||||
"reactive": "/reactive",
|
"reactive": "/reactive",
|
||||||
|
|||||||
@@ -13,12 +13,21 @@
|
|||||||
|
|
||||||
/* --- App theme layered on top of Tailwind's utilities & preflight --- */
|
/* --- App theme layered on top of Tailwind's utilities & preflight --- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The app palette is derived from the theme tokens rather than fixed.
|
||||||
|
*
|
||||||
|
* These used to be hardcoded dark values. Wire UI surfaces follow the theme,
|
||||||
|
* so switching to light turned the cards light while this text stayed light
|
||||||
|
* too -- the sign-in form rendered at a contrast of about 1.1 and was
|
||||||
|
* unreadable. Anything an app hardcodes here has to be themed as well, or it
|
||||||
|
* only ever looks right in one mode.
|
||||||
|
*/
|
||||||
:root {
|
:root {
|
||||||
--bg: #0b1020;
|
--bg: var(--wire-color-bg);
|
||||||
--surface: #141a30;
|
--surface: var(--wire-color-surface);
|
||||||
--text: #e7ecff;
|
--text: var(--wire-color-text);
|
||||||
--muted: #9aa6d0;
|
--muted: var(--wire-color-text-muted);
|
||||||
--brand: #6c8cff;
|
--brand: var(--wire-color-primary);
|
||||||
--radius: 10px;
|
--radius: 10px;
|
||||||
--maxw: 720px;
|
--maxw: 720px;
|
||||||
}
|
}
|
||||||
@@ -36,7 +45,12 @@ body {
|
|||||||
Roboto,
|
Roboto,
|
||||||
sans-serif;
|
sans-serif;
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
background: radial-gradient(1200px 600px at 50% -10%, #1b2750 0%, var(--bg) 60%);
|
/* Tinted from the primary token so the wash follows the theme too. */
|
||||||
|
background: radial-gradient(
|
||||||
|
1200px 600px at 50% -10%,
|
||||||
|
color-mix(in srgb, var(--wire-color-primary) 18%, var(--bg)) 0%,
|
||||||
|
var(--bg) 60%
|
||||||
|
);
|
||||||
background-color: var(--bg);
|
background-color: var(--bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ page ContainerDetail {
|
|||||||
state playground_columns = Number(ctx.url.searchParams.get("pg_columns") ?? "2")
|
state playground_columns = Number(ctx.url.searchParams.get("pg_columns") ?? "2")
|
||||||
state playground_gap = ctx.url.searchParams.get("pg_gap") ?? "md"
|
state playground_gap = ctx.url.searchParams.get("pg_gap") ?? "md"
|
||||||
state playground_maxWidth = ctx.url.searchParams.get("pg_maxWidth") ?? "xl"
|
state playground_maxWidth = ctx.url.searchParams.get("pg_maxWidth") ?? "xl"
|
||||||
|
state playground_centered = (ctx.url.searchParams.get("pg_centered") ?? "true") === "true"
|
||||||
state playground_class = ctx.url.searchParams.get("pg_class") ?? "showcase-instance showcase-instance--1"
|
state playground_class = ctx.url.searchParams.get("pg_class") ?? "showcase-instance showcase-instance--1"
|
||||||
seo {
|
seo {
|
||||||
title = "Container"
|
title = "Container"
|
||||||
@@ -20,7 +21,7 @@ page ContainerDetail {
|
|||||||
<span class="showcase-eyebrow">Layout component</span>
|
<span class="showcase-eyebrow">Layout component</span>
|
||||||
<h1>Container</h1>
|
<h1>Container</h1>
|
||||||
<p>Constrain and align page content with responsive gutters and compact, wide, or full width options.</p>
|
<p>Constrain and align page content with responsive gutters and compact, wide, or full width options.</p>
|
||||||
<div class="detail-badges"><span>6 props</span><span>1 slots</span><span>0 outputs</span><span>Theme ready</span><span>Responsive</span></div>
|
<div class="detail-badges"><span>7 props</span><span>1 slots</span><span>0 outputs</span><span>Theme ready</span><span>Responsive</span></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="detail-hero-icon"><span class="icon-[lucide--component] size-10" aria-hidden="true"></span></div>
|
<div class="detail-hero-icon"><span class="icon-[lucide--component] size-10" aria-hidden="true"></span></div>
|
||||||
</header>
|
</header>
|
||||||
@@ -29,7 +30,7 @@ page ContainerDetail {
|
|||||||
<div class="playground-workbench">
|
<div class="playground-workbench">
|
||||||
<div class="playground-preview">
|
<div class="playground-preview">
|
||||||
<div class="demo-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
|
<div class="demo-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
|
||||||
<div class="playground-preview-source" data-playground-preview><Container size='{playground_size}' color='{playground_color}' columns='{playground_columns}' gap='{playground_gap}' maxWidth='{playground_maxWidth}' class='{playground_class}'><div class="showcase-content-block">Centered container content</div></Container></div>
|
<div class="playground-preview-source" data-playground-preview><Container size='{playground_size}' color='{playground_color}' columns='{playground_columns}' gap='{playground_gap}' maxWidth='{playground_maxWidth}' centered='{playground_centered}' class='{playground_class}'><div class="showcase-content-block">Centered container content</div></Container></div>
|
||||||
<section class="playground-code" aria-label="Current component code">
|
<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>
|
<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><Container>
|
<pre><code data-playground-code><Container>
|
||||||
@@ -40,8 +41,8 @@ page ContainerDetail {
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
<form class="playground-controls" data-playground-form>
|
<form class="playground-controls" data-playground-form>
|
||||||
<header><div><span>Component props</span><strong>6 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>7 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-container-size"><span><strong>size</strong><small>string</small></span><select id="playground-container-size" name="pg_size"><option value="default" selected>default</option><option value="compact">compact</option><option value="spacious">spacious</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-container-color"><span><strong>color</strong><small>string</small></span><select id="playground-container-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-container-columns"><span><strong>columns</strong><small>number</small></span><input id="playground-container-columns" name="pg_columns" type="number" value="2" /></label><label class="playground-field" for="playground-container-gap"><span><strong>gap</strong><small>string</small></span><select id="playground-container-gap" name="pg_gap"><option value="md" selected>md</option><option value="none">none</option><option value="xs">xs</option><option value="sm">sm</option><option value="lg">lg</option><option value="xl">xl</option><option value="2xl">2xl</option></select></label><label class="playground-field" for="playground-container-maxWidth"><span><strong>max Width</strong><small>string</small></span><select id="playground-container-maxWidth" name="pg_maxWidth"><option value="xl" selected>xl</option><option value="compact">compact</option><option value="lg">lg</option><option value="wide">wide</option><option value="2xl">2xl</option><option value="full">full</option></select></label><label class="playground-field" for="playground-container-class"><span><strong>class</strong><small>string</small></span><input id="playground-container-class" name="pg_class" type="text" value="showcase-instance showcase-instance--1" /></label></div>
|
<div class="playground-fields"><label class="playground-field" for="playground-container-size"><span><strong>size</strong><small>string</small></span><select id="playground-container-size" name="pg_size"><option value="default" selected>default</option><option value="compact">compact</option><option value="spacious">spacious</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-container-color"><span><strong>color</strong><small>string</small></span><select id="playground-container-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-container-columns"><span><strong>columns</strong><small>number</small></span><input id="playground-container-columns" name="pg_columns" type="number" value="2" /></label><label class="playground-field" for="playground-container-gap"><span><strong>gap</strong><small>string</small></span><select id="playground-container-gap" name="pg_gap"><option value="md" selected>md</option><option value="none">none</option><option value="xs">xs</option><option value="sm">sm</option><option value="lg">lg</option><option value="xl">xl</option><option value="2xl">2xl</option></select></label><label class="playground-field" for="playground-container-maxWidth"><span><strong>max Width</strong><small>string</small></span><select id="playground-container-maxWidth" name="pg_maxWidth"><option value="xl" selected>xl</option><option value="compact">compact</option><option value="lg">lg</option><option value="wide">wide</option><option value="2xl">2xl</option><option value="full">full</option></select></label><label class="playground-toggle" for="playground-container-centered"><span><strong>centered</strong><small>boolean</small></span><input id="playground-container-centered" name="pg_centered" type="checkbox" value="true" checked data-playground-boolean /><i aria-hidden="true"></i></label><label class="playground-field" for="playground-container-class"><span><strong>class</strong><small>string</small></span><input id="playground-container-class" name="pg_class" type="text" value="showcase-instance showcase-instance--1" /></label></div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -57,7 +58,7 @@ page ContainerDetail {
|
|||||||
<div id="container-demo-1" class="demo-canvas demo-canvas--1">
|
<div id="container-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-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
|
||||||
|
|
||||||
<div class="demo-render"><Container size="default" columns="2" maxWidth="xl" class="showcase-instance showcase-instance--1"><div class="showcase-content-block">Centered container content</div></Container></div>
|
<div class="demo-render"><Container size="default" columns="2" maxWidth="xl" centered="true" class="showcase-instance showcase-instance--1"><div class="showcase-content-block">Centered container content</div></Container></div>
|
||||||
</div>
|
</div>
|
||||||
<section class="demo-code" aria-label="Standard content container usage">
|
<section class="demo-code" aria-label="Standard content container usage">
|
||||||
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
|
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
|
||||||
@@ -76,7 +77,7 @@ page ContainerDetail {
|
|||||||
<div id="container-demo-2" class="demo-canvas demo-canvas--2">
|
<div id="container-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-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
|
||||||
|
|
||||||
<div class="demo-render"><Container size="compact" columns="2" maxWidth="compact" class="showcase-instance showcase-instance--2"><div class="showcase-content-block">Compact readable content</div></Container></div>
|
<div class="demo-render"><Container size="compact" columns="2" maxWidth="compact" centered="true" class="showcase-instance showcase-instance--2"><div class="showcase-content-block">Compact readable content</div></Container></div>
|
||||||
</div>
|
</div>
|
||||||
<section class="demo-code" aria-label="Compact reading container usage">
|
<section class="demo-code" aria-label="Compact reading container usage">
|
||||||
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
|
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
|
||||||
@@ -97,7 +98,7 @@ page ContainerDetail {
|
|||||||
<div id="container-demo-3" class="demo-canvas demo-canvas--3">
|
<div id="container-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-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
|
||||||
|
|
||||||
<div class="demo-render"><Container size="spacious" columns="2" maxWidth="full" class="showcase-instance showcase-instance--3"><div class="showcase-content-block">Full-width dashboard content</div></Container></div>
|
<div class="demo-render"><Container size="spacious" columns="2" maxWidth="full" centered="true" class="showcase-instance showcase-instance--3"><div class="showcase-content-block">Full-width dashboard content</div></Container></div>
|
||||||
</div>
|
</div>
|
||||||
<section class="demo-code" aria-label="Full-width layout container usage">
|
<section class="demo-code" aria-label="Full-width layout container usage">
|
||||||
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
|
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
|
||||||
@@ -110,7 +111,7 @@ page ContainerDetail {
|
|||||||
</div>
|
</div>
|
||||||
</article></div></section>
|
</article></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>columns</code></td><td>number</td><td><code>2</code></td><td>No</td></tr><tr><td><code>gap</code></td><td>string</td><td><code>"md"</code></td><td>No</td></tr><tr><td><code>maxWidth</code></td><td>string</td><td><code>"xl"</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>columns</code></td><td>number</td><td><code>2</code></td><td>No</td></tr><tr><td><code>gap</code></td><td>string</td><td><code>"md"</code></td><td>No</td></tr><tr><td><code>maxWidth</code></td><td>string</td><td><code>"xl"</code></td><td>No</td></tr><tr><td><code>centered</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>
|
</main>
|
||||||
<aside class="detail-aside">
|
<aside class="detail-aside">
|
||||||
<div class="detail-toc"><strong>On this page</strong><a href="#playground">Playground</a><a href="#container-demo-1">Standard content container</a><a href="#container-demo-2">Compact reading container</a><a href="#container-demo-3">Full-width layout container</a><a href="#api">Props API</a></div>
|
<div class="detail-toc"><strong>On this page</strong><a href="#playground">Playground</a><a href="#container-demo-1">Standard content container</a><a href="#container-demo-2">Compact reading container</a><a href="#container-demo-3">Full-width layout container</a><a href="#api">Props API</a></div>
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
// Generated by scripts/generate-showcase.mjs. Do not edit directly.
|
// Generated by scripts/generate-showcase.mjs. Do not edit directly.
|
||||||
page CustomScrollbarDetail {
|
page CustomScrollbarDetail {
|
||||||
layout = "showcase"
|
layout = "showcase"
|
||||||
state playground_size = ctx.url.searchParams.get("pg_size") ?? "default"
|
|
||||||
state playground_color = ctx.url.searchParams.get("pg_color") ?? "primary"
|
state playground_color = ctx.url.searchParams.get("pg_color") ?? "primary"
|
||||||
state playground_columns = Number(ctx.url.searchParams.get("pg_columns") ?? "2")
|
state playground_size = ctx.url.searchParams.get("pg_size") ?? "default"
|
||||||
state playground_gap = ctx.url.searchParams.get("pg_gap") ?? "md"
|
state playground_axis = ctx.url.searchParams.get("pg_axis") ?? "vertical"
|
||||||
state playground_maxWidth = ctx.url.searchParams.get("pg_maxWidth") ?? "xl"
|
state playground_thickness = Number(ctx.url.searchParams.get("pg_thickness") ?? "8")
|
||||||
|
state playground_maxHeight = ctx.url.searchParams.get("pg_maxHeight") ?? "20rem"
|
||||||
|
state playground_radius = ctx.url.searchParams.get("pg_radius") ?? "999px"
|
||||||
state playground_class = ctx.url.searchParams.get("pg_class") ?? "showcase-instance showcase-instance--1"
|
state playground_class = ctx.url.searchParams.get("pg_class") ?? "showcase-instance showcase-instance--1"
|
||||||
seo {
|
seo {
|
||||||
title = "Custom Scrollbar"
|
title = "Custom Scrollbar"
|
||||||
@@ -20,26 +21,26 @@ page CustomScrollbarDetail {
|
|||||||
<span class="showcase-eyebrow">Layout component</span>
|
<span class="showcase-eyebrow">Layout component</span>
|
||||||
<h1>Custom Scrollbar</h1>
|
<h1>Custom Scrollbar</h1>
|
||||||
<p>Theme-aware, responsive custom scrollbar component.</p>
|
<p>Theme-aware, responsive custom scrollbar component.</p>
|
||||||
<div class="detail-badges"><span>6 props</span><span>1 slots</span><span>1 outputs</span><span>Theme ready</span><span>Responsive</span></div>
|
<div class="detail-badges"><span>7 props</span><span>1 slots</span><span>0 outputs</span><span>Theme ready</span><span>Responsive</span></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="detail-hero-icon"><span class="icon-[lucide--component] size-10" aria-hidden="true"></span></div>
|
<div class="detail-hero-icon"><span class="icon-[lucide--component] size-10" aria-hidden="true"></span></div>
|
||||||
</header>
|
</header>
|
||||||
<section id="playground" class="detail-section playground-section" data-playground data-playground-component="CustomScrollbar" data-playground-public-tag="true" data-playground-has-slot="true" data-playground-events="scroll">
|
<section id="playground" class="detail-section playground-section" data-playground data-playground-component="CustomScrollbar" data-playground-public-tag="true" data-playground-has-slot="true" data-playground-events="">
|
||||||
<div class="detail-section-heading"><span>Interactive playground</span><h2>Configure Custom Scrollbar</h2><p>Change any prop and inspect the server-rendered component immediately.</p></div>
|
<div class="detail-section-heading"><span>Interactive playground</span><h2>Configure Custom Scrollbar</h2><p>Change any prop and inspect the server-rendered component immediately.</p></div>
|
||||||
<div class="playground-workbench">
|
<div class="playground-workbench">
|
||||||
<div class="playground-preview">
|
<div class="playground-preview">
|
||||||
<div class="demo-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
|
<div class="demo-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
|
||||||
<div class="playground-preview-source" data-playground-preview><CustomScrollbar size='{playground_size}' color='{playground_color}' columns='{playground_columns}' gap='{playground_gap}' maxWidth='{playground_maxWidth}' class='{playground_class}' /></div>
|
<div class="playground-preview-source" data-playground-preview><CustomScrollbar color='{playground_color}' size='{playground_size}' axis='{playground_axis}' thickness='{playground_thickness}' maxHeight='{playground_maxHeight}' radius='{playground_radius}' class='{playground_class}'><div class="showcase-scroll-demo"><p>Line 1. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 2. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 3. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 4. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 5. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 6. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 7. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 8. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 9. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 10. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 11. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 12. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p></div></CustomScrollbar></div>
|
||||||
<section class="playground-code" aria-label="Current component code">
|
<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>
|
<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><CustomScrollbar /></code></pre>
|
<pre><code data-playground-code><CustomScrollbar /></code></pre>
|
||||||
</section>
|
</section>
|
||||||
<div class="playground-status" data-playground-status aria-live="polite"></div>
|
<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>
|
</div>
|
||||||
<form class="playground-controls" data-playground-form>
|
<form class="playground-controls" data-playground-form>
|
||||||
<header><div><span>Component props</span><strong>6 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>7 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-custom-scrollbar-size"><span><strong>size</strong><small>string</small></span><select id="playground-custom-scrollbar-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-custom-scrollbar-color"><span><strong>color</strong><small>string</small></span><select id="playground-custom-scrollbar-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-custom-scrollbar-columns"><span><strong>columns</strong><small>number</small></span><input id="playground-custom-scrollbar-columns" name="pg_columns" type="number" value="2" /></label><label class="playground-field" for="playground-custom-scrollbar-gap"><span><strong>gap</strong><small>string</small></span><select id="playground-custom-scrollbar-gap" name="pg_gap"><option value="md" selected>md</option><option value="none">none</option><option value="xs">xs</option><option value="sm">sm</option><option value="lg">lg</option><option value="xl">xl</option><option value="2xl">2xl</option></select></label><label class="playground-field" for="playground-custom-scrollbar-maxWidth"><span><strong>max Width</strong><small>string</small></span><select id="playground-custom-scrollbar-maxWidth" name="pg_maxWidth"><option value="xl" selected>xl</option><option value="compact">compact</option><option value="lg">lg</option><option value="wide">wide</option><option value="2xl">2xl</option><option value="full">full</option></select></label><label class="playground-field" for="playground-custom-scrollbar-class"><span><strong>class</strong><small>string</small></span><input id="playground-custom-scrollbar-class" name="pg_class" type="text" value="showcase-instance showcase-instance--1" /></label></div>
|
<div class="playground-fields"><label class="playground-field" for="playground-custom-scrollbar-color"><span><strong>color</strong><small>string</small></span><select id="playground-custom-scrollbar-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-custom-scrollbar-size"><span><strong>size</strong><small>string</small></span><select id="playground-custom-scrollbar-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-custom-scrollbar-axis"><span><strong>axis</strong><small>string</small></span><input id="playground-custom-scrollbar-axis" name="pg_axis" type="text" value="vertical" /></label><label class="playground-field" for="playground-custom-scrollbar-thickness"><span><strong>thickness</strong><small>number</small></span><input id="playground-custom-scrollbar-thickness" name="pg_thickness" type="number" value="8" /></label><label class="playground-field" for="playground-custom-scrollbar-maxHeight"><span><strong>max Height</strong><small>string</small></span><input id="playground-custom-scrollbar-maxHeight" name="pg_maxHeight" type="text" value="20rem" /></label><label class="playground-field" for="playground-custom-scrollbar-radius"><span><strong>radius</strong><small>string</small></span><input id="playground-custom-scrollbar-radius" name="pg_radius" type="text" value="999px" /></label><label class="playground-field" for="playground-custom-scrollbar-class"><span><strong>class</strong><small>string</small></span><input id="playground-custom-scrollbar-class" name="pg_class" type="text" value="showcase-instance showcase-instance--1" /></label></div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -48,72 +49,54 @@ page CustomScrollbarDetail {
|
|||||||
<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">
|
<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">
|
<article class="demo-case">
|
||||||
<header class="demo-case-header">
|
<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>
|
<div><span class="demo-case-eyebrow">Recommended</span><h2>Themed scrolling region</h2><p>Scrollbar appearance is CSS rather than script: scrollbar-width and scrollbar-color are the standard properties, with webkit rules for the engines that still need them. The thumb follows the component colour.</p></div>
|
||||||
<span class="demo-case-number">01</span>
|
<span class="demo-case-number">01</span>
|
||||||
</header>
|
</header>
|
||||||
<div class="demo-workbench">
|
<div class="demo-workbench">
|
||||||
<div id="custom-scrollbar-demo-1" class="demo-canvas demo-canvas--1">
|
<div id="custom-scrollbar-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-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
|
||||||
|
|
||||||
<div class="demo-render"><CustomScrollbar size="default" columns="2" class="showcase-instance showcase-instance--1" /></div>
|
<div class="demo-render"><CustomScrollbar size="default" axis="vertical" thickness="8" maxHeight="14rem" radius="999px" class="showcase-instance showcase-instance--1"><div class="showcase-scroll-demo"><p>Line 1. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 2. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 3. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 4. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 5. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 6. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 7. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 8. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 9. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 10. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 11. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 12. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p></div></CustomScrollbar></div>
|
||||||
</div>
|
</div>
|
||||||
<section class="demo-code" aria-label="Production default usage">
|
<section class="demo-code" aria-label="Themed scrolling region usage">
|
||||||
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
|
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
|
||||||
<pre><code><CustomScrollbar /></code></pre>
|
<pre><code><CustomScrollbar
|
||||||
|
maxHeight="14rem">
|
||||||
|
<div class="showcase-scroll-demo"><p>Line 1. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 2. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 3. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 4. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 5. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 6. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 7. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 8. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 9. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 10. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 11. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 12. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p></div>
|
||||||
|
</CustomScrollbar></code></pre>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
<article class="demo-case">
|
<article class="demo-case">
|
||||||
<header class="demo-case-header">
|
<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>
|
<div><span class="demo-case-eyebrow">Advanced</span><h2>Horizontal, thicker track</h2><p>A horizontal region with a heavier track. thickness is clamped, since it arrives as an attribute and a scrollbar wider than its content helps nobody.</p></div>
|
||||||
<span class="demo-case-number">02</span>
|
<span class="demo-case-number">02</span>
|
||||||
</header>
|
</header>
|
||||||
<div class="demo-workbench">
|
<div class="demo-workbench">
|
||||||
<div id="custom-scrollbar-demo-2" class="demo-canvas demo-canvas--2">
|
<div id="custom-scrollbar-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-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
|
||||||
|
|
||||||
<div class="demo-render"><CustomScrollbar size="sm" columns="2" class="showcase-instance showcase-instance--2" /></div>
|
<div class="demo-render"><CustomScrollbar color="info" size="sm" axis="horizontal" thickness="14" maxHeight="8rem" radius="4px" class="showcase-instance showcase-instance--2"><div class="showcase-scroll-demo showcase-scroll-demo--wide"><span>Column 1</span><span>Column 2</span><span>Column 3</span><span>Column 4</span><span>Column 5</span><span>Column 6</span><span>Column 7</span><span>Column 8</span><span>Column 9</span><span>Column 10</span><span>Column 11</span><span>Column 12</span><span>Column 13</span><span>Column 14</span></div></CustomScrollbar></div>
|
||||||
</div>
|
</div>
|
||||||
<section class="demo-code" aria-label="Compact application usage">
|
<section class="demo-code" aria-label="Horizontal, thicker track usage">
|
||||||
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
|
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
|
||||||
<pre><code><CustomScrollbar
|
<pre><code><CustomScrollbar
|
||||||
|
color="info"
|
||||||
size="sm"
|
size="sm"
|
||||||
/></code></pre>
|
axis="horizontal"
|
||||||
</section>
|
thickness="14"
|
||||||
</div>
|
maxHeight="8rem"
|
||||||
</article>
|
radius="4px">
|
||||||
<article class="demo-case">
|
<div class="showcase-scroll-demo showcase-scroll-demo--wide"><span>Column 1</span><span>Column 2</span><span>Column 3</span><span>Column 4</span><span>Column 5</span><span>Column 6</span><span>Column 7</span><span>Column 8</span><span>Column 9</span><span>Column 10</span><span>Column 11</span><span>Column 12</span><span>Column 13</span><span>Column 14</span></div>
|
||||||
<header class="demo-case-header">
|
</CustomScrollbar></code></pre>
|
||||||
<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="custom-scrollbar-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"><CustomScrollbar size="lg" columns="2" 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><CustomScrollbar
|
|
||||||
size="lg"
|
|
||||||
/></code></pre>
|
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</article></div></section>
|
</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>@scroll</code><span>Fires when the component emits the scroll 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><CustomScrollbar
|
|
||||||
@scroll='console.log(payload)'
|
|
||||||
/></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>{</span> registerOutputHandler <span>}</span> from "@wrnexus/csr/outputs"
|
|
||||||
|
|
||||||
const component = document.querySelector("[data-ui-component=\"CustomScrollbar\"], [data-component=\"CustomScrollbar\"]")
|
<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>color</code></td><td>string</td><td><code>"primary"</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>axis</code></td><td>string</td><td><code>"vertical"</code></td><td>No</td></tr><tr><td><code>thickness</code></td><td>number</td><td><code>8</code></td><td>No</td></tr><tr><td><code>maxHeight</code></td><td>string</td><td><code>"20rem"</code></td><td>No</td></tr><tr><td><code>radius</code></td><td>string</td><td><code>"999px"</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>
|
||||||
|
|
||||||
if (component) registerOutputHandler(component, "scroll", (payload) => <span>{</span>
|
|
||||||
console.log("scroll", payload)
|
|
||||||
<span>}</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>columns</code></td><td>number</td><td><code>2</code></td><td>No</td></tr><tr><td><code>gap</code></td><td>string</td><td><code>"md"</code></td><td>No</td></tr><tr><td><code>maxWidth</code></td><td>string</td><td><code>"xl"</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>
|
</main>
|
||||||
<aside class="detail-aside">
|
<aside class="detail-aside">
|
||||||
<div class="detail-toc"><strong>On this page</strong><a href="#playground">Playground</a><a href="#custom-scrollbar-demo-1">Production default</a><a href="#custom-scrollbar-demo-2">Compact application</a><a href="#custom-scrollbar-demo-3">Rich configuration</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="#custom-scrollbar-demo-1">Themed scrolling region</a><a href="#custom-scrollbar-demo-2">Horizontal, thicker track</a><a href="#api">Props API</a></div>
|
||||||
</aside>
|
</aside>
|
||||||
</div>
|
</div>
|
||||||
<nav class="detail-pagination">
|
<nav class="detail-pagination">
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ page DividerDetail {
|
|||||||
state playground_color = ctx.url.searchParams.get("pg_color") ?? "primary"
|
state playground_color = ctx.url.searchParams.get("pg_color") ?? "primary"
|
||||||
state playground_label = ctx.url.searchParams.get("pg_label") ?? "Divider"
|
state playground_label = ctx.url.searchParams.get("pg_label") ?? "Divider"
|
||||||
state playground_orientation = ctx.url.searchParams.get("pg_orientation") ?? "horizontal"
|
state playground_orientation = ctx.url.searchParams.get("pg_orientation") ?? "horizontal"
|
||||||
|
state playground_variant = ctx.url.searchParams.get("pg_variant") ?? "solid"
|
||||||
state playground_class = ctx.url.searchParams.get("pg_class") ?? "showcase-instance showcase-instance--1"
|
state playground_class = ctx.url.searchParams.get("pg_class") ?? "showcase-instance showcase-instance--1"
|
||||||
seo {
|
seo {
|
||||||
title = "Divider"
|
title = "Divider"
|
||||||
@@ -19,7 +20,7 @@ page DividerDetail {
|
|||||||
<span class="showcase-eyebrow">Layout component</span>
|
<span class="showcase-eyebrow">Layout component</span>
|
||||||
<h1>Divider</h1>
|
<h1>Divider</h1>
|
||||||
<p>Separate related horizontal or vertical content with optional labels, sizes, and semantic colors.</p>
|
<p>Separate related horizontal or vertical content with optional labels, sizes, and semantic colors.</p>
|
||||||
<div class="detail-badges"><span>5 props</span><span>0 slots</span><span>0 outputs</span><span>Theme ready</span><span>Responsive</span></div>
|
<div class="detail-badges"><span>6 props</span><span>0 slots</span><span>0 outputs</span><span>Theme ready</span><span>Responsive</span></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="detail-hero-icon"><span class="icon-[lucide--component] size-10" aria-hidden="true"></span></div>
|
<div class="detail-hero-icon"><span class="icon-[lucide--component] size-10" aria-hidden="true"></span></div>
|
||||||
</header>
|
</header>
|
||||||
@@ -28,7 +29,7 @@ page DividerDetail {
|
|||||||
<div class="playground-workbench">
|
<div class="playground-workbench">
|
||||||
<div class="playground-preview">
|
<div class="playground-preview">
|
||||||
<div class="demo-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
|
<div class="demo-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
|
||||||
<div class="playground-preview-source" data-playground-preview><Divider size='{playground_size}' color='{playground_color}' label='{playground_label}' orientation='{playground_orientation}' class='{playground_class}' /></div>
|
<div class="playground-preview-source" data-playground-preview><Divider size='{playground_size}' color='{playground_color}' label='{playground_label}' orientation='{playground_orientation}' variant='{playground_variant}' class='{playground_class}' /></div>
|
||||||
<section class="playground-code" aria-label="Current component code">
|
<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>
|
<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><Divider
|
<pre><code data-playground-code><Divider
|
||||||
@@ -39,8 +40,8 @@ page DividerDetail {
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
<form class="playground-controls" data-playground-form>
|
<form class="playground-controls" data-playground-form>
|
||||||
<header><div><span>Component props</span><strong>5 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>6 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-divider-size"><span><strong>size</strong><small>string</small></span><select id="playground-divider-size" name="pg_size"><option value="default" selected>default</option><option value="sm">sm</option><option value="lg">lg</option><option value="xs">xs</option><option value="md">md</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-divider-color"><span><strong>color</strong><small>string</small></span><select id="playground-divider-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-divider-label"><span><strong>label</strong><small>string</small></span><input id="playground-divider-label" name="pg_label" type="text" value="Divider" /></label><label class="playground-field" for="playground-divider-orientation"><span><strong>orientation</strong><small>string</small></span><select id="playground-divider-orientation" name="pg_orientation"><option value="horizontal" selected>horizontal</option><option value="vertical">vertical</option></select></label><label class="playground-field" for="playground-divider-class"><span><strong>class</strong><small>string</small></span><input id="playground-divider-class" name="pg_class" type="text" value="showcase-instance showcase-instance--1" /></label></div>
|
<div class="playground-fields"><label class="playground-field" for="playground-divider-size"><span><strong>size</strong><small>string</small></span><select id="playground-divider-size" name="pg_size"><option value="default" selected>default</option><option value="sm">sm</option><option value="lg">lg</option><option value="xs">xs</option><option value="md">md</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-divider-color"><span><strong>color</strong><small>string</small></span><select id="playground-divider-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-divider-label"><span><strong>label</strong><small>string</small></span><input id="playground-divider-label" name="pg_label" type="text" value="Divider" /></label><label class="playground-field" for="playground-divider-orientation"><span><strong>orientation</strong><small>string</small></span><select id="playground-divider-orientation" name="pg_orientation"><option value="horizontal" selected>horizontal</option><option value="vertical">vertical</option></select></label><label class="playground-field" for="playground-divider-variant"><span><strong>variant</strong><small>string</small></span><input id="playground-divider-variant" name="pg_variant" type="text" value="solid" /></label><label class="playground-field" for="playground-divider-class"><span><strong>class</strong><small>string</small></span><input id="playground-divider-class" name="pg_class" type="text" value="showcase-instance showcase-instance--1" /></label></div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -56,7 +57,7 @@ page DividerDetail {
|
|||||||
<div id="divider-demo-1" class="demo-canvas demo-canvas--1">
|
<div id="divider-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-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
|
||||||
|
|
||||||
<div class="demo-render"><Divider size="default" label="Related information" orientation="horizontal" class="showcase-instance showcase-instance--1" /></div>
|
<div class="demo-render"><Divider size="default" label="Related information" orientation="horizontal" variant="solid" class="showcase-instance showcase-instance--1" /></div>
|
||||||
</div>
|
</div>
|
||||||
<section class="demo-code" aria-label="Horizontal section divider usage">
|
<section class="demo-code" aria-label="Horizontal section divider usage">
|
||||||
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
|
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
|
||||||
@@ -75,12 +76,13 @@ page DividerDetail {
|
|||||||
<div id="divider-demo-2" class="demo-canvas demo-canvas--2">
|
<div id="divider-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-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
|
||||||
|
|
||||||
<div class="demo-render"><Divider size="sm" label="" orientation="horizontal" class="showcase-instance showcase-instance--2" /></div>
|
<div class="demo-render"><Divider size="sm" label="" orientation="horizontal" variant="secondary" class="showcase-instance showcase-instance--2" /></div>
|
||||||
</div>
|
</div>
|
||||||
<section class="demo-code" aria-label="Minimal unlabeled divider usage">
|
<section class="demo-code" aria-label="Minimal unlabeled divider usage">
|
||||||
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
|
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
|
||||||
<pre><code><Divider
|
<pre><code><Divider
|
||||||
size="sm"
|
size="sm"
|
||||||
|
variant="secondary"
|
||||||
/></code></pre>
|
/></code></pre>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
@@ -94,7 +96,7 @@ page DividerDetail {
|
|||||||
<div id="divider-demo-3" class="demo-canvas demo-canvas--3">
|
<div id="divider-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-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
|
||||||
|
|
||||||
<div class="demo-render"><Divider size="lg" color="info" label="Actions" orientation="vertical" class="showcase-instance showcase-instance--3" /></div>
|
<div class="demo-render"><Divider size="lg" color="info" label="Actions" orientation="vertical" variant="success" class="showcase-instance showcase-instance--3" /></div>
|
||||||
</div>
|
</div>
|
||||||
<section class="demo-code" aria-label="Vertical toolbar divider usage">
|
<section class="demo-code" aria-label="Vertical toolbar divider usage">
|
||||||
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
|
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
|
||||||
@@ -103,12 +105,13 @@ page DividerDetail {
|
|||||||
color="info"
|
color="info"
|
||||||
label="Actions"
|
label="Actions"
|
||||||
orientation="vertical"
|
orientation="vertical"
|
||||||
|
variant="success"
|
||||||
/></code></pre>
|
/></code></pre>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</article></div></section>
|
</article></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>label</code></td><td>string</td><td><code>""</code></td><td>No</td></tr><tr><td><code>orientation</code></td><td>string</td><td><code>"horizontal"</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>label</code></td><td>string</td><td><code>""</code></td><td>No</td></tr><tr><td><code>orientation</code></td><td>string</td><td><code>"horizontal"</code></td><td>No</td></tr><tr><td><code>variant</code></td><td>string</td><td><code>"solid"</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>
|
</main>
|
||||||
<aside class="detail-aside">
|
<aside class="detail-aside">
|
||||||
<div class="detail-toc"><strong>On this page</strong><a href="#playground">Playground</a><a href="#divider-demo-1">Horizontal section divider</a><a href="#divider-demo-2">Minimal unlabeled divider</a><a href="#divider-demo-3">Vertical toolbar divider</a><a href="#api">Props API</a></div>
|
<div class="detail-toc"><strong>On this page</strong><a href="#playground">Playground</a><a href="#divider-demo-1">Horizontal section divider</a><a href="#divider-demo-2">Minimal unlabeled divider</a><a href="#divider-demo-3">Vertical toolbar divider</a><a href="#api">Props API</a></div>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ page GridDetail {
|
|||||||
state playground_columns = Number(ctx.url.searchParams.get("pg_columns") ?? "2")
|
state playground_columns = Number(ctx.url.searchParams.get("pg_columns") ?? "2")
|
||||||
state playground_gap = ctx.url.searchParams.get("pg_gap") ?? "md"
|
state playground_gap = ctx.url.searchParams.get("pg_gap") ?? "md"
|
||||||
state playground_maxWidth = ctx.url.searchParams.get("pg_maxWidth") ?? "xl"
|
state playground_maxWidth = ctx.url.searchParams.get("pg_maxWidth") ?? "xl"
|
||||||
|
state playground_minItemWidth = ctx.url.searchParams.get("pg_minItemWidth") ?? ""
|
||||||
state playground_class = ctx.url.searchParams.get("pg_class") ?? "showcase-instance showcase-instance--1"
|
state playground_class = ctx.url.searchParams.get("pg_class") ?? "showcase-instance showcase-instance--1"
|
||||||
seo {
|
seo {
|
||||||
title = "Grid"
|
title = "Grid"
|
||||||
@@ -20,7 +21,7 @@ page GridDetail {
|
|||||||
<span class="showcase-eyebrow">Layout component</span>
|
<span class="showcase-eyebrow">Layout component</span>
|
||||||
<h1>Grid</h1>
|
<h1>Grid</h1>
|
||||||
<p>Arrange arbitrary content in a responsive configurable CSS grid with stable columns, gaps, alignment, and width.</p>
|
<p>Arrange arbitrary content in a responsive configurable CSS grid with stable columns, gaps, alignment, and width.</p>
|
||||||
<div class="detail-badges"><span>6 props</span><span>1 slots</span><span>0 outputs</span><span>Theme ready</span><span>Responsive</span></div>
|
<div class="detail-badges"><span>7 props</span><span>1 slots</span><span>0 outputs</span><span>Theme ready</span><span>Responsive</span></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="detail-hero-icon"><span class="icon-[lucide--component] size-10" aria-hidden="true"></span></div>
|
<div class="detail-hero-icon"><span class="icon-[lucide--component] size-10" aria-hidden="true"></span></div>
|
||||||
</header>
|
</header>
|
||||||
@@ -29,7 +30,7 @@ page GridDetail {
|
|||||||
<div class="playground-workbench">
|
<div class="playground-workbench">
|
||||||
<div class="playground-preview">
|
<div class="playground-preview">
|
||||||
<div class="demo-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
|
<div class="demo-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
|
||||||
<div class="playground-preview-source" data-playground-preview><Grid size='{playground_size}' color='{playground_color}' columns='{playground_columns}' gap='{playground_gap}' maxWidth='{playground_maxWidth}' class='{playground_class}'><div class="showcase-grid-items"><span>One</span><span>Two</span><span>Three</span></div></Grid></div>
|
<div class="playground-preview-source" data-playground-preview><Grid size='{playground_size}' color='{playground_color}' columns='{playground_columns}' gap='{playground_gap}' maxWidth='{playground_maxWidth}' minItemWidth='{playground_minItemWidth}' class='{playground_class}'><div class="showcase-grid-items"><span>One</span><span>Two</span><span>Three</span></div></Grid></div>
|
||||||
<section class="playground-code" aria-label="Current component code">
|
<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>
|
<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><Grid /></code></pre>
|
<pre><code data-playground-code><Grid /></code></pre>
|
||||||
@@ -38,8 +39,8 @@ page GridDetail {
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
<form class="playground-controls" data-playground-form>
|
<form class="playground-controls" data-playground-form>
|
||||||
<header><div><span>Component props</span><strong>6 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>7 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-grid-size"><span><strong>size</strong><small>string</small></span><select id="playground-grid-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-grid-color"><span><strong>color</strong><small>string</small></span><select id="playground-grid-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-grid-columns"><span><strong>columns</strong><small>number</small></span><input id="playground-grid-columns" name="pg_columns" type="number" value="2" /></label><label class="playground-field" for="playground-grid-gap"><span><strong>gap</strong><small>string</small></span><select id="playground-grid-gap" name="pg_gap"><option value="md" selected>md</option><option value="none">none</option><option value="sm">sm</option><option value="lg">lg</option><option value="xl">xl</option><option value="xs">xs</option><option value="2xl">2xl</option></select></label><label class="playground-field" for="playground-grid-maxWidth"><span><strong>max Width</strong><small>string</small></span><select id="playground-grid-maxWidth" name="pg_maxWidth"><option value="xl" selected>xl</option><option value="compact">compact</option><option value="lg">lg</option><option value="wide">wide</option><option value="2xl">2xl</option><option value="full">full</option></select></label><label class="playground-field" for="playground-grid-class"><span><strong>class</strong><small>string</small></span><input id="playground-grid-class" name="pg_class" type="text" value="showcase-instance showcase-instance--1" /></label></div>
|
<div class="playground-fields"><label class="playground-field" for="playground-grid-size"><span><strong>size</strong><small>string</small></span><select id="playground-grid-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-grid-color"><span><strong>color</strong><small>string</small></span><select id="playground-grid-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-grid-columns"><span><strong>columns</strong><small>number</small></span><input id="playground-grid-columns" name="pg_columns" type="number" value="2" /></label><label class="playground-field" for="playground-grid-gap"><span><strong>gap</strong><small>string</small></span><select id="playground-grid-gap" name="pg_gap"><option value="md" selected>md</option><option value="none">none</option><option value="sm">sm</option><option value="lg">lg</option><option value="xl">xl</option><option value="xs">xs</option><option value="2xl">2xl</option></select></label><label class="playground-field" for="playground-grid-maxWidth"><span><strong>max Width</strong><small>string</small></span><select id="playground-grid-maxWidth" name="pg_maxWidth"><option value="xl" selected>xl</option><option value="compact">compact</option><option value="lg">lg</option><option value="wide">wide</option><option value="2xl">2xl</option><option value="full">full</option></select></label><label class="playground-field" for="playground-grid-minItemWidth"><span><strong>min Item Width</strong><small>string</small></span><input id="playground-grid-minItemWidth" name="pg_minItemWidth" type="text" value="" /></label><label class="playground-field" for="playground-grid-class"><span><strong>class</strong><small>string</small></span><input id="playground-grid-class" name="pg_class" type="text" value="showcase-instance showcase-instance--1" /></label></div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -112,7 +113,7 @@ page GridDetail {
|
|||||||
</div>
|
</div>
|
||||||
</article></div></section>
|
</article></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>columns</code></td><td>number</td><td><code>2</code></td><td>No</td></tr><tr><td><code>gap</code></td><td>string</td><td><code>"md"</code></td><td>No</td></tr><tr><td><code>maxWidth</code></td><td>string</td><td><code>"xl"</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>columns</code></td><td>number</td><td><code>2</code></td><td>No</td></tr><tr><td><code>gap</code></td><td>string</td><td><code>"md"</code></td><td>No</td></tr><tr><td><code>maxWidth</code></td><td>string</td><td><code>"xl"</code></td><td>No</td></tr><tr><td><code>minItemWidth</code></td><td>string</td><td><code>""</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>
|
</main>
|
||||||
<aside class="detail-aside">
|
<aside class="detail-aside">
|
||||||
<div class="detail-toc"><strong>On this page</strong><a href="#playground">Playground</a><a href="#grid-demo-1">Responsive three-column grid</a><a href="#grid-demo-2">Dense four-column grid</a><a href="#grid-demo-3">Full-width two-column grid</a><a href="#api">Props API</a></div>
|
<div class="detail-toc"><strong>On this page</strong><a href="#playground">Playground</a><a href="#grid-demo-1">Responsive three-column grid</a><a href="#grid-demo-2">Dense four-column grid</a><a href="#grid-demo-3">Full-width two-column grid</a><a href="#api">Props API</a></div>
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ page ImageDetail {
|
|||||||
state playground_width = ctx.url.searchParams.get("pg_width") ?? ""
|
state playground_width = ctx.url.searchParams.get("pg_width") ?? ""
|
||||||
state playground_height = ctx.url.searchParams.get("pg_height") ?? ""
|
state playground_height = ctx.url.searchParams.get("pg_height") ?? ""
|
||||||
state playground_loading = ctx.url.searchParams.get("pg_loading") ?? "lazy"
|
state playground_loading = ctx.url.searchParams.get("pg_loading") ?? "lazy"
|
||||||
|
state playground_fit = ctx.url.searchParams.get("pg_fit") ?? "cover"
|
||||||
state playground_rounded = (ctx.url.searchParams.get("pg_rounded") ?? "false") === "true"
|
state playground_rounded = (ctx.url.searchParams.get("pg_rounded") ?? "false") === "true"
|
||||||
state playground_class = ctx.url.searchParams.get("pg_class") ?? "showcase-instance showcase-instance--1"
|
state playground_class = ctx.url.searchParams.get("pg_class") ?? "showcase-instance showcase-instance--1"
|
||||||
seo {
|
seo {
|
||||||
@@ -23,7 +24,7 @@ page ImageDetail {
|
|||||||
<span class="showcase-eyebrow">Layout component</span>
|
<span class="showcase-eyebrow">Layout component</span>
|
||||||
<h1>Image</h1>
|
<h1>Image</h1>
|
||||||
<p>Render a responsive image with explicit dimensions, loading behavior, alternative text, sizing, and rounded treatment.</p>
|
<p>Render a responsive image with explicit dimensions, loading behavior, alternative text, sizing, and rounded treatment.</p>
|
||||||
<div class="detail-badges"><span>9 props</span><span>1 slots</span><span>0 outputs</span><span>Theme ready</span><span>Responsive</span></div>
|
<div class="detail-badges"><span>10 props</span><span>1 slots</span><span>0 outputs</span><span>Theme ready</span><span>Responsive</span></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="detail-hero-icon"><span class="icon-[lucide--component] size-10" aria-hidden="true"></span></div>
|
<div class="detail-hero-icon"><span class="icon-[lucide--component] size-10" aria-hidden="true"></span></div>
|
||||||
</header>
|
</header>
|
||||||
@@ -32,7 +33,7 @@ page ImageDetail {
|
|||||||
<div class="playground-workbench">
|
<div class="playground-workbench">
|
||||||
<div class="playground-preview">
|
<div class="playground-preview">
|
||||||
<div class="demo-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
|
<div class="demo-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
|
||||||
<div class="playground-preview-source" data-playground-preview><Image size='{playground_size}' color='{playground_color}' src='{playground_src}' alt='{playground_alt}' width='{playground_width}' height='{playground_height}' loading='{playground_loading}' rounded='{playground_rounded}' class='{playground_class}' /></div>
|
<div class="playground-preview-source" data-playground-preview><Image size='{playground_size}' color='{playground_color}' src='{playground_src}' alt='{playground_alt}' width='{playground_width}' height='{playground_height}' loading='{playground_loading}' fit='{playground_fit}' rounded='{playground_rounded}' class='{playground_class}' /></div>
|
||||||
<section class="playground-code" aria-label="Current component code">
|
<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>
|
<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><Image /></code></pre>
|
<pre><code data-playground-code><Image /></code></pre>
|
||||||
@@ -41,8 +42,8 @@ page ImageDetail {
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
<form class="playground-controls" data-playground-form>
|
<form class="playground-controls" data-playground-form>
|
||||||
<header><div><span>Component props</span><strong>9 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>10 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-image-size"><span><strong>size</strong><small>string</small></span><select id="playground-image-size" name="pg_size"><option value="default" selected>default</option><option value="sm">sm</option><option value="lg">lg</option><option value="xs">xs</option><option value="md">md</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-image-color"><span><strong>color</strong><small>string</small></span><select id="playground-image-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-image-src"><span><strong>src</strong><small>string</small></span><input id="playground-image-src" name="pg_src" type="text" value="" /></label><label class="playground-field" for="playground-image-alt"><span><strong>alt</strong><small>string</small></span><input id="playground-image-alt" name="pg_alt" type="text" value="" /></label><label class="playground-field" for="playground-image-width"><span><strong>width</strong><small>string</small></span><select id="playground-image-width" name="pg_width"><option value="" selected>Auto / default</option><option value="default">default</option><option value="compact">compact</option><option value="wide">wide</option><option value="full">full</option></select></label><label class="playground-field" for="playground-image-height"><span><strong>height</strong><small>string</small></span><input id="playground-image-height" name="pg_height" type="text" value="" /></label><label class="playground-field" for="playground-image-loading"><span><strong>loading</strong><small>string</small></span><select id="playground-image-loading" name="pg_loading"><option value="lazy" selected>lazy</option><option value="eager">eager</option></select></label><label class="playground-toggle" for="playground-image-rounded"><span><strong>rounded</strong><small>boolean</small></span><input id="playground-image-rounded" name="pg_rounded" type="checkbox" value="true" data-playground-boolean /><i aria-hidden="true"></i></label><label class="playground-field" for="playground-image-class"><span><strong>class</strong><small>string</small></span><input id="playground-image-class" name="pg_class" type="text" value="showcase-instance showcase-instance--1" /></label></div>
|
<div class="playground-fields"><label class="playground-field" for="playground-image-size"><span><strong>size</strong><small>string</small></span><select id="playground-image-size" name="pg_size"><option value="default" selected>default</option><option value="sm">sm</option><option value="lg">lg</option><option value="xs">xs</option><option value="md">md</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-image-color"><span><strong>color</strong><small>string</small></span><select id="playground-image-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-image-src"><span><strong>src</strong><small>string</small></span><input id="playground-image-src" name="pg_src" type="text" value="" /></label><label class="playground-field" for="playground-image-alt"><span><strong>alt</strong><small>string</small></span><input id="playground-image-alt" name="pg_alt" type="text" value="" /></label><label class="playground-field" for="playground-image-width"><span><strong>width</strong><small>string</small></span><select id="playground-image-width" name="pg_width"><option value="" selected>Auto / default</option><option value="default">default</option><option value="compact">compact</option><option value="wide">wide</option><option value="full">full</option></select></label><label class="playground-field" for="playground-image-height"><span><strong>height</strong><small>string</small></span><input id="playground-image-height" name="pg_height" type="text" value="" /></label><label class="playground-field" for="playground-image-loading"><span><strong>loading</strong><small>string</small></span><select id="playground-image-loading" name="pg_loading"><option value="lazy" selected>lazy</option><option value="eager">eager</option></select></label><label class="playground-field" for="playground-image-fit"><span><strong>fit</strong><small>string</small></span><input id="playground-image-fit" name="pg_fit" type="text" value="cover" /></label><label class="playground-toggle" for="playground-image-rounded"><span><strong>rounded</strong><small>boolean</small></span><input id="playground-image-rounded" name="pg_rounded" type="checkbox" value="true" data-playground-boolean /><i aria-hidden="true"></i></label><label class="playground-field" for="playground-image-class"><span><strong>class</strong><small>string</small></span><input id="playground-image-class" name="pg_class" type="text" value="showcase-instance showcase-instance--1" /></label></div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -121,7 +122,7 @@ page ImageDetail {
|
|||||||
</div>
|
</div>
|
||||||
</article></div></section>
|
</article></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>src</code></td><td>string</td><td><code>""</code></td><td>No</td></tr><tr><td><code>alt</code></td><td>string</td><td><code>""</code></td><td>No</td></tr><tr><td><code>width</code></td><td>string</td><td><code>""</code></td><td>No</td></tr><tr><td><code>height</code></td><td>string</td><td><code>""</code></td><td>No</td></tr><tr><td><code>loading</code></td><td>string</td><td><code>"lazy"</code></td><td>No</td></tr><tr><td><code>rounded</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>src</code></td><td>string</td><td><code>""</code></td><td>No</td></tr><tr><td><code>alt</code></td><td>string</td><td><code>""</code></td><td>No</td></tr><tr><td><code>width</code></td><td>string</td><td><code>""</code></td><td>No</td></tr><tr><td><code>height</code></td><td>string</td><td><code>""</code></td><td>No</td></tr><tr><td><code>loading</code></td><td>string</td><td><code>"lazy"</code></td><td>No</td></tr><tr><td><code>fit</code></td><td>string</td><td><code>"cover"</code></td><td>No</td></tr><tr><td><code>rounded</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>
|
</main>
|
||||||
<aside class="detail-aside">
|
<aside class="detail-aside">
|
||||||
<div class="detail-toc"><strong>On this page</strong><a href="#playground">Playground</a><a href="#image-demo-1">Responsive content image</a><a href="#image-demo-2">Rounded thumbnail</a><a href="#image-demo-3">Eager hero image</a><a href="#api">Props API</a></div>
|
<div class="detail-toc"><strong>On this page</strong><a href="#playground">Playground</a><a href="#image-demo-1">Responsive content image</a><a href="#image-demo-2">Rounded thumbnail</a><a href="#image-demo-3">Eager hero image</a><a href="#api">Props API</a></div>
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ page KbdDetail {
|
|||||||
</div>
|
</div>
|
||||||
</article></div></section>
|
</article></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>label</code></td><td>string</td><td><code>"⌘ K"</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>label</code></td><td>string</td><td><code>"K"</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>
|
</main>
|
||||||
<aside class="detail-aside">
|
<aside class="detail-aside">
|
||||||
<div class="detail-toc"><strong>On this page</strong><a href="#playground">Playground</a><a href="#kbd-demo-1">Production default</a><a href="#kbd-demo-2">Compact application</a><a href="#kbd-demo-3">Rich configuration</a><a href="#api">Props API</a></div>
|
<div class="detail-toc"><strong>On this page</strong><a href="#playground">Playground</a><a href="#kbd-demo-1">Production default</a><a href="#kbd-demo-2">Compact application</a><a href="#kbd-demo-3">Rich configuration</a><a href="#api">Props API</a></div>
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
// Generated by scripts/generate-showcase.mjs. Do not edit directly.
|
// Generated by scripts/generate-showcase.mjs. Do not edit directly.
|
||||||
page LayoutSplitterDetail {
|
page LayoutSplitterDetail {
|
||||||
layout = "showcase"
|
layout = "showcase"
|
||||||
state playground_size = ctx.url.searchParams.get("pg_size") ?? "default"
|
|
||||||
state playground_color = ctx.url.searchParams.get("pg_color") ?? "primary"
|
state playground_color = ctx.url.searchParams.get("pg_color") ?? "primary"
|
||||||
state playground_columns = Number(ctx.url.searchParams.get("pg_columns") ?? "2")
|
state playground_size = Number(ctx.url.searchParams.get("pg_size") ?? "50")
|
||||||
state playground_gap = ctx.url.searchParams.get("pg_gap") ?? "md"
|
state playground_orientation = ctx.url.searchParams.get("pg_orientation") ?? "horizontal"
|
||||||
state playground_maxWidth = ctx.url.searchParams.get("pg_maxWidth") ?? "xl"
|
state playground_minSize = Number(ctx.url.searchParams.get("pg_minSize") ?? "15")
|
||||||
|
state playground_step = Number(ctx.url.searchParams.get("pg_step") ?? "5")
|
||||||
|
state playground_label = ctx.url.searchParams.get("pg_label") ?? "Layout Splitter"
|
||||||
state playground_class = ctx.url.searchParams.get("pg_class") ?? "showcase-instance showcase-instance--1"
|
state playground_class = ctx.url.searchParams.get("pg_class") ?? "showcase-instance showcase-instance--1"
|
||||||
seo {
|
seo {
|
||||||
title = "Layout Splitter"
|
title = "Layout Splitter"
|
||||||
@@ -20,26 +21,34 @@ page LayoutSplitterDetail {
|
|||||||
<span class="showcase-eyebrow">Layout component</span>
|
<span class="showcase-eyebrow">Layout component</span>
|
||||||
<h1>Layout Splitter</h1>
|
<h1>Layout Splitter</h1>
|
||||||
<p>Theme-aware, responsive layout splitter component.</p>
|
<p>Theme-aware, responsive layout splitter component.</p>
|
||||||
<div class="detail-badges"><span>6 props</span><span>1 slots</span><span>3 outputs</span><span>Theme ready</span><span>Responsive</span></div>
|
<div class="detail-badges"><span>7 props</span><span>3 slots</span><span>1 outputs</span><span>Theme ready</span><span>Responsive</span></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="detail-hero-icon"><span class="icon-[lucide--component] size-10" aria-hidden="true"></span></div>
|
<div class="detail-hero-icon"><span class="icon-[lucide--component] size-10" aria-hidden="true"></span></div>
|
||||||
</header>
|
</header>
|
||||||
<section id="playground" class="detail-section playground-section" data-playground data-playground-component="LayoutSplitter" data-playground-public-tag="true" data-playground-has-slot="true" data-playground-events="resizeStart,resize,resizeEnd">
|
<section id="playground" class="detail-section playground-section" data-playground data-playground-component="LayoutSplitter" data-playground-public-tag="true" data-playground-has-slot="true" data-playground-events="sizeChange">
|
||||||
<div class="detail-section-heading"><span>Interactive playground</span><h2>Configure Layout Splitter</h2><p>Change any prop and inspect the server-rendered component immediately.</p></div>
|
<div class="detail-section-heading"><span>Interactive playground</span><h2>Configure Layout Splitter</h2><p>Change any prop and inspect the server-rendered component immediately.</p></div>
|
||||||
<div class="playground-workbench">
|
<div class="playground-workbench">
|
||||||
<div class="playground-preview">
|
<div class="playground-preview">
|
||||||
<div class="demo-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
|
<div class="demo-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
|
||||||
<div class="playground-preview-source" data-playground-preview><LayoutSplitter size='{playground_size}' color='{playground_color}' columns='{playground_columns}' gap='{playground_gap}' maxWidth='{playground_maxWidth}' class='{playground_class}' /></div>
|
<div class="playground-preview-source" data-playground-preview><LayoutSplitter color='{playground_color}' size='{playground_size}' orientation='{playground_orientation}' minSize='{playground_minSize}' step='{playground_step}' label='{playground_label}' class='{playground_class}' /></div>
|
||||||
<section class="playground-code" aria-label="Current component code">
|
<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>
|
<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><LayoutSplitter /></code></pre>
|
<pre><code data-playground-code><LayoutSplitter
|
||||||
|
label="Layout Splitter">
|
||||||
|
<div data-slot="start">
|
||||||
|
<div class="showcase-slot">start slot</div>
|
||||||
|
</div>
|
||||||
|
<div data-slot="end">
|
||||||
|
<div class="showcase-slot">end slot</div>
|
||||||
|
</div>
|
||||||
|
</LayoutSplitter></code></pre>
|
||||||
</section>
|
</section>
|
||||||
<div class="playground-status" data-playground-status aria-live="polite"></div>
|
<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 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>
|
</div>
|
||||||
<form class="playground-controls" data-playground-form>
|
<form class="playground-controls" data-playground-form>
|
||||||
<header><div><span>Component props</span><strong>6 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>7 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-layout-splitter-size"><span><strong>size</strong><small>string</small></span><select id="playground-layout-splitter-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-layout-splitter-color"><span><strong>color</strong><small>string</small></span><select id="playground-layout-splitter-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-layout-splitter-columns"><span><strong>columns</strong><small>number</small></span><input id="playground-layout-splitter-columns" name="pg_columns" type="number" value="2" /></label><label class="playground-field" for="playground-layout-splitter-gap"><span><strong>gap</strong><small>string</small></span><select id="playground-layout-splitter-gap" name="pg_gap"><option value="md" selected>md</option><option value="none">none</option><option value="xs">xs</option><option value="sm">sm</option><option value="lg">lg</option><option value="xl">xl</option><option value="2xl">2xl</option></select></label><label class="playground-field" for="playground-layout-splitter-maxWidth"><span><strong>max Width</strong><small>string</small></span><select id="playground-layout-splitter-maxWidth" name="pg_maxWidth"><option value="xl" selected>xl</option><option value="compact">compact</option><option value="lg">lg</option><option value="wide">wide</option><option value="2xl">2xl</option><option value="full">full</option></select></label><label class="playground-field" for="playground-layout-splitter-class"><span><strong>class</strong><small>string</small></span><input id="playground-layout-splitter-class" name="pg_class" type="text" value="showcase-instance showcase-instance--1" /></label></div>
|
<div class="playground-fields"><label class="playground-field" for="playground-layout-splitter-color"><span><strong>color</strong><small>string</small></span><select id="playground-layout-splitter-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-layout-splitter-size"><span><strong>size</strong><small>number</small></span><input id="playground-layout-splitter-size" name="pg_size" type="number" value="50" /></label><label class="playground-field" for="playground-layout-splitter-orientation"><span><strong>orientation</strong><small>string</small></span><select id="playground-layout-splitter-orientation" name="pg_orientation"><option value="horizontal" selected>horizontal</option><option value="vertical">vertical</option></select></label><label class="playground-field" for="playground-layout-splitter-minSize"><span><strong>min Size</strong><small>number</small></span><input id="playground-layout-splitter-minSize" name="pg_minSize" type="number" value="15" /></label><label class="playground-field" for="playground-layout-splitter-step"><span><strong>step</strong><small>number</small></span><input id="playground-layout-splitter-step" name="pg_step" type="number" value="5" /></label><label class="playground-field" for="playground-layout-splitter-label"><span><strong>label</strong><small>string</small></span><input id="playground-layout-splitter-label" name="pg_label" type="text" value="Layout Splitter" /></label><label class="playground-field" for="playground-layout-splitter-class"><span><strong>class</strong><small>string</small></span><input id="playground-layout-splitter-class" name="pg_class" type="text" value="showcase-instance showcase-instance--1" /></label></div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -48,82 +57,72 @@ page LayoutSplitterDetail {
|
|||||||
<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">
|
<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">
|
<article class="demo-case">
|
||||||
<header class="demo-case-header">
|
<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>
|
<div><span class="demo-case-eyebrow">Recommended</span><h2>Drag or arrow the divider</h2><p>Two panes with a movable divider. Drag it, or focus it and use the arrow keys; Home and End go to the bounds. The size is resolved in the runtime and written onto the container as a custom property, because a pointermove fires far too often to route through a client function.</p></div>
|
||||||
<span class="demo-case-number">01</span>
|
<span class="demo-case-number">01</span>
|
||||||
</header>
|
</header>
|
||||||
<div class="demo-workbench">
|
<div class="demo-workbench">
|
||||||
<div id="layout-splitter-demo-1" class="demo-canvas demo-canvas--1">
|
<div id="layout-splitter-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-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
|
||||||
|
|
||||||
<div class="demo-render"><LayoutSplitter size="default" columns="2" class="showcase-instance showcase-instance--1" /></div>
|
<div class="demo-render"><LayoutSplitter size="40" orientation="horizontal" minSize="20" step="5" label="Resize panels" class="showcase-instance showcase-instance--1" /></div>
|
||||||
</div>
|
</div>
|
||||||
<section class="demo-code" aria-label="Production default usage">
|
<section class="demo-code" aria-label="Drag or arrow the divider usage">
|
||||||
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
|
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
|
||||||
<pre><code><LayoutSplitter /></code></pre>
|
<pre><code><LayoutSplitter
|
||||||
|
size="40"
|
||||||
|
minSize="20">
|
||||||
|
<div data-slot="start">
|
||||||
|
<div class="showcase-slot">start slot</div>
|
||||||
|
</div>
|
||||||
|
<div data-slot="end">
|
||||||
|
<div class="showcase-slot">end slot</div>
|
||||||
|
</div>
|
||||||
|
</LayoutSplitter></code></pre>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
<article class="demo-case">
|
<article class="demo-case">
|
||||||
<header class="demo-case-header">
|
<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>
|
<div><span class="demo-case-eyebrow">Advanced</span><h2>Stacked panes</h2><p>Vertical orientation splits top from bottom and switches the arrow keys to up and down. Below the small breakpoint both orientations stack, because two panes side by side stop making sense on a phone.</p></div>
|
||||||
<span class="demo-case-number">02</span>
|
<span class="demo-case-number">02</span>
|
||||||
</header>
|
</header>
|
||||||
<div class="demo-workbench">
|
<div class="demo-workbench">
|
||||||
<div id="layout-splitter-demo-2" class="demo-canvas demo-canvas--2">
|
<div id="layout-splitter-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-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
|
||||||
|
|
||||||
<div class="demo-render"><LayoutSplitter size="sm" columns="2" class="showcase-instance showcase-instance--2" /></div>
|
<div class="demo-render"><LayoutSplitter size="60" orientation="vertical" minSize="25" step="10" label="Resize rows" class="showcase-instance showcase-instance--2" /></div>
|
||||||
</div>
|
</div>
|
||||||
<section class="demo-code" aria-label="Compact application usage">
|
<section class="demo-code" aria-label="Stacked panes usage">
|
||||||
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
|
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
|
||||||
<pre><code><LayoutSplitter
|
<pre><code><LayoutSplitter
|
||||||
size="sm"
|
size="60"
|
||||||
/></code></pre>
|
orientation="vertical"
|
||||||
</section>
|
minSize="25"
|
||||||
</div>
|
step="10"
|
||||||
</article>
|
label="Resize rows">
|
||||||
<article class="demo-case">
|
<div data-slot="start">
|
||||||
<header class="demo-case-header">
|
<div class="showcase-slot">start slot</div>
|
||||||
<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>
|
</div>
|
||||||
<span class="demo-case-number">03</span>
|
<div data-slot="end">
|
||||||
</header>
|
<div class="showcase-slot">end slot</div>
|
||||||
<div class="demo-workbench">
|
</div>
|
||||||
<div id="layout-splitter-demo-3" class="demo-canvas demo-canvas--3">
|
</LayoutSplitter></code></pre>
|
||||||
<div class="demo-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
|
|
||||||
|
|
||||||
<div class="demo-render"><LayoutSplitter size="lg" columns="2" 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><LayoutSplitter
|
|
||||||
size="lg"
|
|
||||||
/></code></pre>
|
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</article></div></section>
|
</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>@resizeStart</code><span>Fires when the component emits the resizeStart event.</span></div><div><code>@resize</code><span>Fires when the component emits the resize event.</span></div><div><code>@resizeEnd</code><span>Fires when the component emits the resizeEnd 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><LayoutSplitter
|
<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>@sizeChange</code><span>Fires when the component emits the sizeChange 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><LayoutSplitter
|
||||||
@resizeStart='console.log(payload)'
|
@sizeChange='console.log(payload)'
|
||||||
@resize='console.log(payload)'
|
|
||||||
@resizeEnd='console.log(payload)'
|
|
||||||
/></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>{</span> registerOutputHandler <span>}</span> from "@wrnexus/csr/outputs"
|
/></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>{</span> registerOutputHandler <span>}</span> from "@wrnexus/csr/outputs"
|
||||||
|
|
||||||
const component = document.querySelector("[data-ui-component=\"LayoutSplitter\"], [data-component=\"LayoutSplitter\"]")
|
const component = document.querySelector("[data-ui-component=\"LayoutSplitter\"], [data-component=\"LayoutSplitter\"]")
|
||||||
|
|
||||||
if (component) registerOutputHandler(component, "resizeStart", (payload) => <span>{</span>
|
if (component) registerOutputHandler(component, "sizeChange", (payload) => <span>{</span>
|
||||||
console.log("resizeStart", payload)
|
console.log("sizeChange", payload)
|
||||||
<span>}</span>)
|
|
||||||
|
|
||||||
if (component) registerOutputHandler(component, "resize", (payload) => <span>{</span>
|
|
||||||
console.log("resize", payload)
|
|
||||||
<span>}</span>)
|
|
||||||
|
|
||||||
if (component) registerOutputHandler(component, "resizeEnd", (payload) => <span>{</span>
|
|
||||||
console.log("resizeEnd", payload)
|
|
||||||
<span>}</span>)</code></pre></section></div></div></section>
|
<span>}</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>columns</code></td><td>number</td><td><code>2</code></td><td>No</td></tr><tr><td><code>gap</code></td><td>string</td><td><code>"md"</code></td><td>No</td></tr><tr><td><code>maxWidth</code></td><td>string</td><td><code>"xl"</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>color</code></td><td>string</td><td><code>"primary"</code></td><td>No</td></tr><tr><td><code>size</code></td><td>number</td><td><code>50</code></td><td>No</td></tr><tr><td><code>orientation</code></td><td>string</td><td><code>"horizontal"</code></td><td>No</td></tr><tr><td><code>minSize</code></td><td>number</td><td><code>15</code></td><td>No</td></tr><tr><td><code>step</code></td><td>number</td><td><code>5</code></td><td>No</td></tr><tr><td><code>label</code></td><td>string</td><td><code>"Resize panels"</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>
|
</main>
|
||||||
<aside class="detail-aside">
|
<aside class="detail-aside">
|
||||||
<div class="detail-toc"><strong>On this page</strong><a href="#playground">Playground</a><a href="#layout-splitter-demo-1">Production default</a><a href="#layout-splitter-demo-2">Compact application</a><a href="#layout-splitter-demo-3">Rich configuration</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="#layout-splitter-demo-1">Drag or arrow the divider</a><a href="#layout-splitter-demo-2">Stacked panes</a><a href="#events">Outputs</a><a href="#api">Props API</a></div>
|
||||||
</aside>
|
</aside>
|
||||||
</div>
|
</div>
|
||||||
<nav class="detail-pagination">
|
<nav class="detail-pagination">
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ page LinkDetail {
|
|||||||
state playground_href = ctx.url.searchParams.get("pg_href") ?? "#link-demo"
|
state playground_href = ctx.url.searchParams.get("pg_href") ?? "#link-demo"
|
||||||
state playground_target = ctx.url.searchParams.get("pg_target") ?? ""
|
state playground_target = ctx.url.searchParams.get("pg_target") ?? ""
|
||||||
state playground_rel = ctx.url.searchParams.get("pg_rel") ?? ""
|
state playground_rel = ctx.url.searchParams.get("pg_rel") ?? ""
|
||||||
|
state playground_underline = ctx.url.searchParams.get("pg_underline") ?? "hover"
|
||||||
state playground_external = (ctx.url.searchParams.get("pg_external") ?? "false") === "true"
|
state playground_external = (ctx.url.searchParams.get("pg_external") ?? "false") === "true"
|
||||||
state playground_class = ctx.url.searchParams.get("pg_class") ?? "showcase-instance showcase-instance--1"
|
state playground_class = ctx.url.searchParams.get("pg_class") ?? "showcase-instance showcase-instance--1"
|
||||||
seo {
|
seo {
|
||||||
@@ -22,7 +23,7 @@ page LinkDetail {
|
|||||||
<span class="showcase-eyebrow">Layout component</span>
|
<span class="showcase-eyebrow">Layout component</span>
|
||||||
<h1>Link</h1>
|
<h1>Link</h1>
|
||||||
<p>Render an accessible internal or external link with target, relation, size, color, and public focus or click events.</p>
|
<p>Render an accessible internal or external link with target, relation, size, color, and public focus or click events.</p>
|
||||||
<div class="detail-badges"><span>8 props</span><span>1 slots</span><span>0 outputs</span><span>Theme ready</span><span>Responsive</span></div>
|
<div class="detail-badges"><span>9 props</span><span>1 slots</span><span>0 outputs</span><span>Theme ready</span><span>Responsive</span></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="detail-hero-icon"><span class="icon-[lucide--component] size-10" aria-hidden="true"></span></div>
|
<div class="detail-hero-icon"><span class="icon-[lucide--component] size-10" aria-hidden="true"></span></div>
|
||||||
</header>
|
</header>
|
||||||
@@ -31,7 +32,7 @@ page LinkDetail {
|
|||||||
<div class="playground-workbench">
|
<div class="playground-workbench">
|
||||||
<div class="playground-preview">
|
<div class="playground-preview">
|
||||||
<div class="demo-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
|
<div class="demo-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
|
||||||
<div class="playground-preview-source" data-playground-preview><Link size='{playground_size}' color='{playground_color}' label='{playground_label}' href='{playground_href}' target='{playground_target}' rel='{playground_rel}' external='{playground_external}' class='{playground_class}' /></div>
|
<div class="playground-preview-source" data-playground-preview><Link size='{playground_size}' color='{playground_color}' label='{playground_label}' href='{playground_href}' target='{playground_target}' rel='{playground_rel}' underline='{playground_underline}' external='{playground_external}' class='{playground_class}' /></div>
|
||||||
<section class="playground-code" aria-label="Current component code">
|
<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>
|
<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><Link
|
<pre><code data-playground-code><Link
|
||||||
@@ -42,8 +43,8 @@ page LinkDetail {
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
<form class="playground-controls" data-playground-form>
|
<form class="playground-controls" data-playground-form>
|
||||||
<header><div><span>Component props</span><strong>8 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>9 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-link-size"><span><strong>size</strong><small>string</small></span><select id="playground-link-size" name="pg_size"><option value="default" selected>default</option><option value="sm">sm</option><option value="lg">lg</option><option value="xs">xs</option><option value="md">md</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-link-color"><span><strong>color</strong><small>string</small></span><select id="playground-link-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-link-label"><span><strong>label</strong><small>string</small></span><input id="playground-link-label" name="pg_label" type="text" value="Link" /></label><label class="playground-field" for="playground-link-href"><span><strong>href</strong><small>string</small></span><input id="playground-link-href" name="pg_href" type="text" value="#link-demo" /></label><label class="playground-field" for="playground-link-target"><span><strong>target</strong><small>string</small></span><select id="playground-link-target" name="pg_target"><option value="" selected>Auto / default</option><option value="_self">_self</option><option value="_blank">_blank</option><option value="_parent">_parent</option><option value="_top">_top</option></select></label><label class="playground-field" for="playground-link-rel"><span><strong>rel</strong><small>string</small></span><input id="playground-link-rel" name="pg_rel" type="text" value="" /></label><label class="playground-toggle" for="playground-link-external"><span><strong>external</strong><small>boolean</small></span><input id="playground-link-external" name="pg_external" type="checkbox" value="true" data-playground-boolean /><i aria-hidden="true"></i></label><label class="playground-field" for="playground-link-class"><span><strong>class</strong><small>string</small></span><input id="playground-link-class" name="pg_class" type="text" value="showcase-instance showcase-instance--1" /></label></div>
|
<div class="playground-fields"><label class="playground-field" for="playground-link-size"><span><strong>size</strong><small>string</small></span><select id="playground-link-size" name="pg_size"><option value="default" selected>default</option><option value="sm">sm</option><option value="lg">lg</option><option value="xs">xs</option><option value="md">md</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-link-color"><span><strong>color</strong><small>string</small></span><select id="playground-link-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-link-label"><span><strong>label</strong><small>string</small></span><input id="playground-link-label" name="pg_label" type="text" value="Link" /></label><label class="playground-field" for="playground-link-href"><span><strong>href</strong><small>string</small></span><input id="playground-link-href" name="pg_href" type="text" value="#link-demo" /></label><label class="playground-field" for="playground-link-target"><span><strong>target</strong><small>string</small></span><select id="playground-link-target" name="pg_target"><option value="" selected>Auto / default</option><option value="_self">_self</option><option value="_blank">_blank</option><option value="_parent">_parent</option><option value="_top">_top</option></select></label><label class="playground-field" for="playground-link-rel"><span><strong>rel</strong><small>string</small></span><input id="playground-link-rel" name="pg_rel" type="text" value="" /></label><label class="playground-field" for="playground-link-underline"><span><strong>underline</strong><small>string</small></span><input id="playground-link-underline" name="pg_underline" type="text" value="hover" /></label><label class="playground-toggle" for="playground-link-external"><span><strong>external</strong><small>boolean</small></span><input id="playground-link-external" name="pg_external" type="checkbox" value="true" data-playground-boolean /><i aria-hidden="true"></i></label><label class="playground-field" for="playground-link-class"><span><strong>class</strong><small>string</small></span><input id="playground-link-class" name="pg_class" type="text" value="showcase-instance showcase-instance--1" /></label></div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -116,7 +117,7 @@ page LinkDetail {
|
|||||||
</div>
|
</div>
|
||||||
</article></div></section>
|
</article></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>label</code></td><td>string</td><td><code>"Link"</code></td><td>No</td></tr><tr><td><code>href</code></td><td>string</td><td><code>"#"</code></td><td>No</td></tr><tr><td><code>target</code></td><td>string</td><td><code>""</code></td><td>No</td></tr><tr><td><code>rel</code></td><td>string</td><td><code>""</code></td><td>No</td></tr><tr><td><code>external</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>label</code></td><td>string</td><td><code>"Link"</code></td><td>No</td></tr><tr><td><code>href</code></td><td>string</td><td><code>"#"</code></td><td>No</td></tr><tr><td><code>target</code></td><td>string</td><td><code>""</code></td><td>No</td></tr><tr><td><code>rel</code></td><td>string</td><td><code>""</code></td><td>No</td></tr><tr><td><code>underline</code></td><td>string</td><td><code>"hover"</code></td><td>No</td></tr><tr><td><code>external</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>
|
</main>
|
||||||
<aside class="detail-aside">
|
<aside class="detail-aside">
|
||||||
<div class="detail-toc"><strong>On this page</strong><a href="#playground">Playground</a><a href="#link-demo-1">Standard navigation link</a><a href="#link-demo-2">External resource link</a><a href="#link-demo-3">Large emphasized link</a><a href="#api">Props API</a></div>
|
<div class="detail-toc"><strong>On this page</strong><a href="#playground">Playground</a><a href="#link-demo-1">Standard navigation link</a><a href="#link-demo-2">External resource link</a><a href="#link-demo-3">Large emphasized link</a><a href="#api">Props API</a></div>
|
||||||
|
|||||||
@@ -14,6 +14,9 @@ page NavbarDetail {
|
|||||||
state playground_maxWidth = ctx.url.searchParams.get("pg_maxWidth") ?? "full"
|
state playground_maxWidth = ctx.url.searchParams.get("pg_maxWidth") ?? "full"
|
||||||
state playground_mobileLabel = ctx.url.searchParams.get("pg_mobileLabel") ?? "Navbar"
|
state playground_mobileLabel = ctx.url.searchParams.get("pg_mobileLabel") ?? "Navbar"
|
||||||
state playground_class = ctx.url.searchParams.get("pg_class") ?? "showcase-instance showcase-instance--1"
|
state playground_class = ctx.url.searchParams.get("pg_class") ?? "showcase-instance showcase-instance--1"
|
||||||
|
state demo_obj_0 = JSON.parse("{\"label\":\"Northwind\",\"description\":\"Console\",\"href\":\"/\"}")
|
||||||
|
state demo_obj_1 = JSON.parse("{\"label\":\"Northwind\",\"icon\":\"icon-[lucide--box]\",\"href\":\"/\"}")
|
||||||
|
state demo_obj_2 = JSON.parse("{\"label\":\"Acme\",\"href\":\"/\"}")
|
||||||
seo {
|
seo {
|
||||||
title = "Navbar"
|
title = "Navbar"
|
||||||
description = "Theme-aware, responsive navbar component."
|
description = "Theme-aware, responsive navbar component."
|
||||||
@@ -600,289 +603,54 @@ page NavbarDetail {
|
|||||||
<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">
|
<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">
|
<article class="demo-case">
|
||||||
<header class="demo-case-header">
|
<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>
|
<div><span class="demo-case-eyebrow">Recommended</span><h2>Brand, links and actions</h2><p>The everyday shape: a brand, a row of links with the current page marked, and calls to action on the right. Arrow keys move along the menu bar.</p></div>
|
||||||
<span class="demo-case-number">01</span>
|
<span class="demo-case-number">01</span>
|
||||||
</header>
|
</header>
|
||||||
<div class="demo-workbench">
|
<div class="demo-workbench">
|
||||||
<div id="navbar-demo-1" class="demo-canvas demo-canvas--1">
|
<div id="navbar-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-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
|
||||||
|
|
||||||
<div class="demo-render"><Navbar size="default" label="Navbar" topbarLabel="Navbar" brand='({"id":"navbar-0-1","key":"navbar-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":"#navbar-demo","actionHref":"#navbar-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"]})' items='[{"id":"navbar-0-1","key":"navbar-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":"#navbar-demo","actionHref":"#navbar-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":"navbar-0-2","key":"navbar-0-2","value":"secondary","label":"Additional option","title":"Supporting example","description":"A clean default configuration for everyday product interfaces.","text":"Another configurable message.","href":"#navbar-demo","actionHref":"#navbar-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"]}]' actions='[{"id":"navbar-0-1","key":"navbar-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":"#navbar-demo","actionHref":"#navbar-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":"navbar-0-2","key":"navbar-0-2","value":"secondary","label":"Additional option","title":"Supporting example","description":"A clean default configuration for everyday product interfaces.","text":"Another configurable message.","href":"#navbar-demo","actionHref":"#navbar-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"]}]' sticky="false" openOnHover="false" mobileLabel="Navbar" class="showcase-instance showcase-instance--1" /></div>
|
<div class="demo-render"><Navbar size="default" label="Primary navigation" topbarLabel="Navbar" brand='{demo_obj_0}' items='[{"label":"Overview","href":"/","value":"overview"},{"label":"Projects","href":"/projects","value":"projects"},{"label":"Reports","href":"/reports","value":"reports"}]' actions='[{"label":"Sign in","href":"/login","variant":"link"},{"label":"Start free","href":"/signup","variant":"primary"}]' active="projects" sticky="false" openOnHover="false" mobileLabel="Navbar" class="showcase-instance showcase-instance--1" /></div>
|
||||||
</div>
|
</div>
|
||||||
<section class="demo-code" aria-label="Production default usage">
|
<section class="demo-code" aria-label="Brand, links and actions usage">
|
||||||
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
|
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
|
||||||
<pre><code><Navbar
|
<pre><code><Navbar
|
||||||
label="Navbar"
|
|
||||||
topbarLabel="Navbar"
|
topbarLabel="Navbar"
|
||||||
brand='<span>{</span>
|
brand='<span>{</span>
|
||||||
"id": "navbar-0-1",
|
"label": "Northwind",
|
||||||
"key": "navbar-0-1",
|
"description": "Console",
|
||||||
"value": "primary",
|
"href": "/"
|
||||||
"label": "Primary workflow",
|
|
||||||
"title": "Primary workflow",
|
|
||||||
"description": "A clean default configuration for everyday product interfaces.",
|
|
||||||
"text": "A configurable sample message.",
|
|
||||||
"href": "#navbar-demo",
|
|
||||||
"actionHref": "#navbar-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": [
|
|
||||||
<span>{</span>
|
|
||||||
"label": "Nested option A",
|
|
||||||
"value": "nested-a"
|
|
||||||
<span>}</span>,
|
|
||||||
<span>{</span>
|
|
||||||
"label": "Nested option B",
|
|
||||||
"value": "nested-b"
|
|
||||||
<span>}</span>
|
|
||||||
],
|
|
||||||
"links": [
|
|
||||||
<span>{</span>
|
|
||||||
"label": "Documentation",
|
|
||||||
"href": "#documentation"
|
|
||||||
<span>}</span>,
|
|
||||||
<span>{</span>
|
|
||||||
"label": "API reference",
|
|
||||||
"href": "#api-reference"
|
|
||||||
<span>}</span>
|
|
||||||
],
|
|
||||||
"values": [
|
|
||||||
"Included",
|
|
||||||
"Standard"
|
|
||||||
]
|
|
||||||
<span>}</span>'
|
<span>}</span>'
|
||||||
items='[
|
items='[
|
||||||
<span>{</span>
|
<span>{</span>
|
||||||
"id": "navbar-0-1",
|
"label": "Overview",
|
||||||
"key": "navbar-0-1",
|
"href": "/",
|
||||||
"value": "primary",
|
"value": "overview"
|
||||||
"label": "Primary workflow",
|
|
||||||
"title": "Primary workflow",
|
|
||||||
"description": "A clean default configuration for everyday product interfaces.",
|
|
||||||
"text": "A configurable sample message.",
|
|
||||||
"href": "#navbar-demo",
|
|
||||||
"actionHref": "#navbar-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": [
|
|
||||||
<span>{</span>
|
|
||||||
"label": "Nested option A",
|
|
||||||
"value": "nested-a"
|
|
||||||
<span>}</span>,
|
<span>}</span>,
|
||||||
<span>{</span>
|
<span>{</span>
|
||||||
"label": "Nested option B",
|
"label": "Projects",
|
||||||
"value": "nested-b"
|
"href": "/projects",
|
||||||
<span>}</span>
|
"value": "projects"
|
||||||
],
|
|
||||||
"links": [
|
|
||||||
<span>{</span>
|
|
||||||
"label": "Documentation",
|
|
||||||
"href": "#documentation"
|
|
||||||
<span>}</span>,
|
<span>}</span>,
|
||||||
<span>{</span>
|
<span>{</span>
|
||||||
"label": "API reference",
|
"label": "Reports",
|
||||||
"href": "#api-reference"
|
"href": "/reports",
|
||||||
<span>}</span>
|
"value": "reports"
|
||||||
],
|
|
||||||
"values": [
|
|
||||||
"Included",
|
|
||||||
"Standard"
|
|
||||||
]
|
|
||||||
<span>}</span>,
|
|
||||||
<span>{</span>
|
|
||||||
"id": "navbar-0-2",
|
|
||||||
"key": "navbar-0-2",
|
|
||||||
"value": "secondary",
|
|
||||||
"label": "Additional option",
|
|
||||||
"title": "Supporting example",
|
|
||||||
"description": "A clean default configuration for everyday product interfaces.",
|
|
||||||
"text": "Another configurable message.",
|
|
||||||
"href": "#navbar-demo",
|
|
||||||
"actionHref": "#navbar-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": [
|
|
||||||
<span>{</span>
|
|
||||||
"label": "Nested option A",
|
|
||||||
"value": "nested-a"
|
|
||||||
<span>}</span>,
|
|
||||||
<span>{</span>
|
|
||||||
"label": "Nested option B",
|
|
||||||
"value": "nested-b"
|
|
||||||
<span>}</span>
|
|
||||||
],
|
|
||||||
"links": [
|
|
||||||
<span>{</span>
|
|
||||||
"label": "Documentation",
|
|
||||||
"href": "#documentation"
|
|
||||||
<span>}</span>,
|
|
||||||
<span>{</span>
|
|
||||||
"label": "API reference",
|
|
||||||
"href": "#api-reference"
|
|
||||||
<span>}</span>
|
|
||||||
],
|
|
||||||
"values": [
|
|
||||||
"Included",
|
|
||||||
"Standard"
|
|
||||||
]
|
|
||||||
<span>}</span>
|
<span>}</span>
|
||||||
]'
|
]'
|
||||||
actions='[
|
actions='[
|
||||||
<span>{</span>
|
<span>{</span>
|
||||||
"id": "navbar-0-1",
|
"label": "Sign in",
|
||||||
"key": "navbar-0-1",
|
"href": "/login",
|
||||||
"value": "primary",
|
"variant": "link"
|
||||||
"label": "Primary workflow",
|
|
||||||
"title": "Primary workflow",
|
|
||||||
"description": "A clean default configuration for everyday product interfaces.",
|
|
||||||
"text": "A configurable sample message.",
|
|
||||||
"href": "#navbar-demo",
|
|
||||||
"actionHref": "#navbar-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": [
|
|
||||||
<span>{</span>
|
|
||||||
"label": "Nested option A",
|
|
||||||
"value": "nested-a"
|
|
||||||
<span>}</span>,
|
<span>}</span>,
|
||||||
<span>{</span>
|
<span>{</span>
|
||||||
"label": "Nested option B",
|
"label": "Start free",
|
||||||
"value": "nested-b"
|
"href": "/signup",
|
||||||
<span>}</span>
|
"variant": "primary"
|
||||||
],
|
|
||||||
"links": [
|
|
||||||
<span>{</span>
|
|
||||||
"label": "Documentation",
|
|
||||||
"href": "#documentation"
|
|
||||||
<span>}</span>,
|
|
||||||
<span>{</span>
|
|
||||||
"label": "API reference",
|
|
||||||
"href": "#api-reference"
|
|
||||||
<span>}</span>
|
|
||||||
],
|
|
||||||
"values": [
|
|
||||||
"Included",
|
|
||||||
"Standard"
|
|
||||||
]
|
|
||||||
<span>}</span>,
|
|
||||||
<span>{</span>
|
|
||||||
"id": "navbar-0-2",
|
|
||||||
"key": "navbar-0-2",
|
|
||||||
"value": "secondary",
|
|
||||||
"label": "Additional option",
|
|
||||||
"title": "Supporting example",
|
|
||||||
"description": "A clean default configuration for everyday product interfaces.",
|
|
||||||
"text": "Another configurable message.",
|
|
||||||
"href": "#navbar-demo",
|
|
||||||
"actionHref": "#navbar-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": [
|
|
||||||
<span>{</span>
|
|
||||||
"label": "Nested option A",
|
|
||||||
"value": "nested-a"
|
|
||||||
<span>}</span>,
|
|
||||||
<span>{</span>
|
|
||||||
"label": "Nested option B",
|
|
||||||
"value": "nested-b"
|
|
||||||
<span>}</span>
|
|
||||||
],
|
|
||||||
"links": [
|
|
||||||
<span>{</span>
|
|
||||||
"label": "Documentation",
|
|
||||||
"href": "#documentation"
|
|
||||||
<span>}</span>,
|
|
||||||
<span>{</span>
|
|
||||||
"label": "API reference",
|
|
||||||
"href": "#api-reference"
|
|
||||||
<span>}</span>
|
|
||||||
],
|
|
||||||
"values": [
|
|
||||||
"Included",
|
|
||||||
"Standard"
|
|
||||||
]
|
|
||||||
<span>}</span>
|
<span>}</span>
|
||||||
]'
|
]'
|
||||||
|
active="projects"
|
||||||
mobileLabel="Navbar">
|
mobileLabel="Navbar">
|
||||||
<div data-slot="topbar">
|
<div data-slot="topbar">
|
||||||
<div class="showcase-slot">topbar slot</div>
|
<div class="showcase-slot">topbar slot</div>
|
||||||
@@ -896,290 +664,86 @@ page NavbarDetail {
|
|||||||
</article>
|
</article>
|
||||||
<article class="demo-case">
|
<article class="demo-case">
|
||||||
<header class="demo-case-header">
|
<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>
|
<div><span class="demo-case-eyebrow">Advanced</span><h2>Dropdown and mega panel</h2><p>An item carrying children opens a panel built from native details and summary, so it is keyboard operable without any extra script. Give a child its own children to get a titled column inside the panel.</p></div>
|
||||||
<span class="demo-case-number">02</span>
|
<span class="demo-case-number">02</span>
|
||||||
</header>
|
</header>
|
||||||
<div class="demo-workbench">
|
<div class="demo-workbench">
|
||||||
<div id="navbar-demo-2" class="demo-canvas demo-canvas--2">
|
<div id="navbar-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-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
|
||||||
|
|
||||||
<div class="demo-render"><Navbar size="sm" label="Compact example" topbarLabel="Compact example" brand='({"id":"navbar-1-1","key":"navbar-1-1","value":"primary","label":"Secondary workflow","title":"Secondary workflow","description":"A compact configuration designed for dense application layouts.","text":"A configurable sample message.","href":"#navbar-demo","actionHref":"#navbar-demo","actionLabel":"View details","icon":"icon-[lucide--zap]","iconClass":"icon-[lucide--zap]","variant":"secondary","status":"Active","time":"10:15","current":true,"selected":true,"checked":true,"disabled":false,"outgoing":false,"open":true,"number":1,"count":24,"percentage":48,"color":"#0284c7","target":"_self","ariaLabel":"Open secondary 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"]})' items='[{"id":"navbar-1-1","key":"navbar-1-1","value":"primary","label":"Secondary workflow","title":"Secondary workflow","description":"A compact configuration designed for dense application layouts.","text":"A configurable sample message.","href":"#navbar-demo","actionHref":"#navbar-demo","actionLabel":"View details","icon":"icon-[lucide--zap]","iconClass":"icon-[lucide--zap]","variant":"secondary","status":"Active","time":"10:15","current":true,"selected":true,"checked":true,"disabled":false,"outgoing":false,"open":true,"number":1,"count":24,"percentage":48,"color":"#0284c7","target":"_self","ariaLabel":"Open secondary 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":"navbar-1-2","key":"navbar-1-2","value":"secondary","label":"Additional option","title":"Supporting example","description":"A compact configuration designed for dense application layouts.","text":"Another configurable message.","href":"#navbar-demo","actionHref":"#navbar-demo","actionLabel":"View details","icon":"icon-[lucide--zap]","iconClass":"icon-[lucide--zap]","variant":"secondary","status":"Active","time":"10:15","current":false,"selected":false,"checked":false,"disabled":false,"outgoing":true,"open":true,"number":2,"count":48,"percentage":48,"color":"#0284c7","target":"_self","ariaLabel":"Open secondary 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"]}]' actions='[{"id":"navbar-1-1","key":"navbar-1-1","value":"primary","label":"Secondary workflow","title":"Secondary workflow","description":"A compact configuration designed for dense application layouts.","text":"A configurable sample message.","href":"#navbar-demo","actionHref":"#navbar-demo","actionLabel":"View details","icon":"icon-[lucide--zap]","iconClass":"icon-[lucide--zap]","variant":"secondary","status":"Active","time":"10:15","current":true,"selected":true,"checked":true,"disabled":false,"outgoing":false,"open":true,"number":1,"count":24,"percentage":48,"color":"#0284c7","target":"_self","ariaLabel":"Open secondary 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":"navbar-1-2","key":"navbar-1-2","value":"secondary","label":"Additional option","title":"Supporting example","description":"A compact configuration designed for dense application layouts.","text":"Another configurable message.","href":"#navbar-demo","actionHref":"#navbar-demo","actionLabel":"View details","icon":"icon-[lucide--zap]","iconClass":"icon-[lucide--zap]","variant":"secondary","status":"Active","time":"10:15","current":false,"selected":false,"checked":false,"disabled":false,"outgoing":true,"open":true,"number":2,"count":48,"percentage":48,"color":"#0284c7","target":"_self","ariaLabel":"Open secondary 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"]}]' sticky="false" openOnHover="false" mobileLabel="Compact example" class="showcase-instance showcase-instance--2" /></div>
|
<div class="demo-render"><Navbar size="sm" label="Compact example" topbarLabel="Compact example" brand='{demo_obj_1}' items='[{"label":"Overview","href":"/","value":"overview"},{"label":"Products","value":"products","columns":2,"description":"Everything in the platform.","children":[{"label":"Platform","children":[{"label":"Runtime","href":"/runtime","description":"The browser half.","icon":"icon-[lucide--cpu]"},{"label":"Compiler","href":"/compiler","description":"WRN to JavaScript.","icon":"icon-[lucide--hammer]"}]},{"label":"Tooling","children":[{"label":"CLI","href":"/cli","description":"Scaffold and deploy."},{"label":"Editor","href":"/editor","description":"Language server."}]}]},{"label":"Pricing","href":"/pricing","value":"pricing"}]' actions='[{"label":"Book a demo","href":"/demo","variant":"primary"}]' active="overview" sticky="false" openOnHover="false" mobileLabel="Compact example" class="showcase-instance showcase-instance--2" /></div>
|
||||||
</div>
|
</div>
|
||||||
<section class="demo-code" aria-label="Compact application usage">
|
<section class="demo-code" aria-label="Dropdown and mega panel usage">
|
||||||
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
|
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
|
||||||
<pre><code><Navbar
|
<pre><code><Navbar
|
||||||
size="sm"
|
size="sm"
|
||||||
label="Compact example"
|
label="Compact example"
|
||||||
topbarLabel="Compact example"
|
topbarLabel="Compact example"
|
||||||
brand='<span>{</span>
|
brand='<span>{</span>
|
||||||
"id": "navbar-1-1",
|
"label": "Northwind",
|
||||||
"key": "navbar-1-1",
|
"icon": "icon-[lucide--box]",
|
||||||
"value": "primary",
|
"href": "/"
|
||||||
"label": "Secondary workflow",
|
|
||||||
"title": "Secondary workflow",
|
|
||||||
"description": "A compact configuration designed for dense application layouts.",
|
|
||||||
"text": "A configurable sample message.",
|
|
||||||
"href": "#navbar-demo",
|
|
||||||
"actionHref": "#navbar-demo",
|
|
||||||
"actionLabel": "View details",
|
|
||||||
"icon": "icon-[lucide--zap]",
|
|
||||||
"iconClass": "icon-[lucide--zap]",
|
|
||||||
"variant": "secondary",
|
|
||||||
"status": "Active",
|
|
||||||
"time": "10:15",
|
|
||||||
"current": true,
|
|
||||||
"selected": true,
|
|
||||||
"checked": true,
|
|
||||||
"disabled": false,
|
|
||||||
"outgoing": false,
|
|
||||||
"open": true,
|
|
||||||
"number": 1,
|
|
||||||
"count": 24,
|
|
||||||
"percentage": 48,
|
|
||||||
"color": "#0284c7",
|
|
||||||
"target": "_self",
|
|
||||||
"ariaLabel": "Open secondary workflow 1",
|
|
||||||
"items": [
|
|
||||||
<span>{</span>
|
|
||||||
"label": "Nested option A",
|
|
||||||
"value": "nested-a"
|
|
||||||
<span>}</span>,
|
|
||||||
<span>{</span>
|
|
||||||
"label": "Nested option B",
|
|
||||||
"value": "nested-b"
|
|
||||||
<span>}</span>
|
|
||||||
],
|
|
||||||
"links": [
|
|
||||||
<span>{</span>
|
|
||||||
"label": "Documentation",
|
|
||||||
"href": "#documentation"
|
|
||||||
<span>}</span>,
|
|
||||||
<span>{</span>
|
|
||||||
"label": "API reference",
|
|
||||||
"href": "#api-reference"
|
|
||||||
<span>}</span>
|
|
||||||
],
|
|
||||||
"values": [
|
|
||||||
"Included",
|
|
||||||
"Standard"
|
|
||||||
]
|
|
||||||
<span>}</span>'
|
<span>}</span>'
|
||||||
items='[
|
items='[
|
||||||
<span>{</span>
|
<span>{</span>
|
||||||
"id": "navbar-1-1",
|
"label": "Overview",
|
||||||
"key": "navbar-1-1",
|
"href": "/",
|
||||||
"value": "primary",
|
"value": "overview"
|
||||||
"label": "Secondary workflow",
|
|
||||||
"title": "Secondary workflow",
|
|
||||||
"description": "A compact configuration designed for dense application layouts.",
|
|
||||||
"text": "A configurable sample message.",
|
|
||||||
"href": "#navbar-demo",
|
|
||||||
"actionHref": "#navbar-demo",
|
|
||||||
"actionLabel": "View details",
|
|
||||||
"icon": "icon-[lucide--zap]",
|
|
||||||
"iconClass": "icon-[lucide--zap]",
|
|
||||||
"variant": "secondary",
|
|
||||||
"status": "Active",
|
|
||||||
"time": "10:15",
|
|
||||||
"current": true,
|
|
||||||
"selected": true,
|
|
||||||
"checked": true,
|
|
||||||
"disabled": false,
|
|
||||||
"outgoing": false,
|
|
||||||
"open": true,
|
|
||||||
"number": 1,
|
|
||||||
"count": 24,
|
|
||||||
"percentage": 48,
|
|
||||||
"color": "#0284c7",
|
|
||||||
"target": "_self",
|
|
||||||
"ariaLabel": "Open secondary workflow 1",
|
|
||||||
"items": [
|
|
||||||
<span>{</span>
|
|
||||||
"label": "Nested option A",
|
|
||||||
"value": "nested-a"
|
|
||||||
<span>}</span>,
|
<span>}</span>,
|
||||||
<span>{</span>
|
<span>{</span>
|
||||||
"label": "Nested option B",
|
"label": "Products",
|
||||||
"value": "nested-b"
|
"value": "products",
|
||||||
<span>}</span>
|
"columns": 2,
|
||||||
],
|
"description": "Everything in the platform.",
|
||||||
"links": [
|
"children": [
|
||||||
<span>{</span>
|
<span>{</span>
|
||||||
"label": "Documentation",
|
"label": "Platform",
|
||||||
"href": "#documentation"
|
"children": [
|
||||||
|
<span>{</span>
|
||||||
|
"label": "Runtime",
|
||||||
|
"href": "/runtime",
|
||||||
|
"description": "The browser half.",
|
||||||
|
"icon": "icon-[lucide--cpu]"
|
||||||
<span>}</span>,
|
<span>}</span>,
|
||||||
<span>{</span>
|
<span>{</span>
|
||||||
"label": "API reference",
|
"label": "Compiler",
|
||||||
"href": "#api-reference"
|
"href": "/compiler",
|
||||||
|
"description": "WRN to JavaScript.",
|
||||||
|
"icon": "icon-[lucide--hammer]"
|
||||||
<span>}</span>
|
<span>}</span>
|
||||||
],
|
|
||||||
"values": [
|
|
||||||
"Included",
|
|
||||||
"Standard"
|
|
||||||
]
|
]
|
||||||
<span>}</span>,
|
<span>}</span>,
|
||||||
<span>{</span>
|
<span>{</span>
|
||||||
"id": "navbar-1-2",
|
"label": "Tooling",
|
||||||
"key": "navbar-1-2",
|
"children": [
|
||||||
"value": "secondary",
|
|
||||||
"label": "Additional option",
|
|
||||||
"title": "Supporting example",
|
|
||||||
"description": "A compact configuration designed for dense application layouts.",
|
|
||||||
"text": "Another configurable message.",
|
|
||||||
"href": "#navbar-demo",
|
|
||||||
"actionHref": "#navbar-demo",
|
|
||||||
"actionLabel": "View details",
|
|
||||||
"icon": "icon-[lucide--zap]",
|
|
||||||
"iconClass": "icon-[lucide--zap]",
|
|
||||||
"variant": "secondary",
|
|
||||||
"status": "Active",
|
|
||||||
"time": "10:15",
|
|
||||||
"current": false,
|
|
||||||
"selected": false,
|
|
||||||
"checked": false,
|
|
||||||
"disabled": false,
|
|
||||||
"outgoing": true,
|
|
||||||
"open": true,
|
|
||||||
"number": 2,
|
|
||||||
"count": 48,
|
|
||||||
"percentage": 48,
|
|
||||||
"color": "#0284c7",
|
|
||||||
"target": "_self",
|
|
||||||
"ariaLabel": "Open secondary workflow 2",
|
|
||||||
"items": [
|
|
||||||
<span>{</span>
|
<span>{</span>
|
||||||
"label": "Nested option A",
|
"label": "CLI",
|
||||||
"value": "nested-a"
|
"href": "/cli",
|
||||||
|
"description": "Scaffold and deploy."
|
||||||
<span>}</span>,
|
<span>}</span>,
|
||||||
<span>{</span>
|
<span>{</span>
|
||||||
"label": "Nested option B",
|
"label": "Editor",
|
||||||
"value": "nested-b"
|
"href": "/editor",
|
||||||
|
"description": "Language server."
|
||||||
<span>}</span>
|
<span>}</span>
|
||||||
],
|
|
||||||
"links": [
|
|
||||||
<span>{</span>
|
|
||||||
"label": "Documentation",
|
|
||||||
"href": "#documentation"
|
|
||||||
<span>}</span>,
|
|
||||||
<span>{</span>
|
|
||||||
"label": "API reference",
|
|
||||||
"href": "#api-reference"
|
|
||||||
<span>}</span>
|
|
||||||
],
|
|
||||||
"values": [
|
|
||||||
"Included",
|
|
||||||
"Standard"
|
|
||||||
]
|
]
|
||||||
<span>}</span>
|
<span>}</span>
|
||||||
|
]
|
||||||
|
<span>}</span>,
|
||||||
|
<span>{</span>
|
||||||
|
"label": "Pricing",
|
||||||
|
"href": "/pricing",
|
||||||
|
"value": "pricing"
|
||||||
|
<span>}</span>
|
||||||
]'
|
]'
|
||||||
actions='[
|
actions='[
|
||||||
<span>{</span>
|
<span>{</span>
|
||||||
"id": "navbar-1-1",
|
"label": "Book a demo",
|
||||||
"key": "navbar-1-1",
|
"href": "/demo",
|
||||||
"value": "primary",
|
"variant": "primary"
|
||||||
"label": "Secondary workflow",
|
|
||||||
"title": "Secondary workflow",
|
|
||||||
"description": "A compact configuration designed for dense application layouts.",
|
|
||||||
"text": "A configurable sample message.",
|
|
||||||
"href": "#navbar-demo",
|
|
||||||
"actionHref": "#navbar-demo",
|
|
||||||
"actionLabel": "View details",
|
|
||||||
"icon": "icon-[lucide--zap]",
|
|
||||||
"iconClass": "icon-[lucide--zap]",
|
|
||||||
"variant": "secondary",
|
|
||||||
"status": "Active",
|
|
||||||
"time": "10:15",
|
|
||||||
"current": true,
|
|
||||||
"selected": true,
|
|
||||||
"checked": true,
|
|
||||||
"disabled": false,
|
|
||||||
"outgoing": false,
|
|
||||||
"open": true,
|
|
||||||
"number": 1,
|
|
||||||
"count": 24,
|
|
||||||
"percentage": 48,
|
|
||||||
"color": "#0284c7",
|
|
||||||
"target": "_self",
|
|
||||||
"ariaLabel": "Open secondary workflow 1",
|
|
||||||
"items": [
|
|
||||||
<span>{</span>
|
|
||||||
"label": "Nested option A",
|
|
||||||
"value": "nested-a"
|
|
||||||
<span>}</span>,
|
|
||||||
<span>{</span>
|
|
||||||
"label": "Nested option B",
|
|
||||||
"value": "nested-b"
|
|
||||||
<span>}</span>
|
|
||||||
],
|
|
||||||
"links": [
|
|
||||||
<span>{</span>
|
|
||||||
"label": "Documentation",
|
|
||||||
"href": "#documentation"
|
|
||||||
<span>}</span>,
|
|
||||||
<span>{</span>
|
|
||||||
"label": "API reference",
|
|
||||||
"href": "#api-reference"
|
|
||||||
<span>}</span>
|
|
||||||
],
|
|
||||||
"values": [
|
|
||||||
"Included",
|
|
||||||
"Standard"
|
|
||||||
]
|
|
||||||
<span>}</span>,
|
|
||||||
<span>{</span>
|
|
||||||
"id": "navbar-1-2",
|
|
||||||
"key": "navbar-1-2",
|
|
||||||
"value": "secondary",
|
|
||||||
"label": "Additional option",
|
|
||||||
"title": "Supporting example",
|
|
||||||
"description": "A compact configuration designed for dense application layouts.",
|
|
||||||
"text": "Another configurable message.",
|
|
||||||
"href": "#navbar-demo",
|
|
||||||
"actionHref": "#navbar-demo",
|
|
||||||
"actionLabel": "View details",
|
|
||||||
"icon": "icon-[lucide--zap]",
|
|
||||||
"iconClass": "icon-[lucide--zap]",
|
|
||||||
"variant": "secondary",
|
|
||||||
"status": "Active",
|
|
||||||
"time": "10:15",
|
|
||||||
"current": false,
|
|
||||||
"selected": false,
|
|
||||||
"checked": false,
|
|
||||||
"disabled": false,
|
|
||||||
"outgoing": true,
|
|
||||||
"open": true,
|
|
||||||
"number": 2,
|
|
||||||
"count": 48,
|
|
||||||
"percentage": 48,
|
|
||||||
"color": "#0284c7",
|
|
||||||
"target": "_self",
|
|
||||||
"ariaLabel": "Open secondary workflow 2",
|
|
||||||
"items": [
|
|
||||||
<span>{</span>
|
|
||||||
"label": "Nested option A",
|
|
||||||
"value": "nested-a"
|
|
||||||
<span>}</span>,
|
|
||||||
<span>{</span>
|
|
||||||
"label": "Nested option B",
|
|
||||||
"value": "nested-b"
|
|
||||||
<span>}</span>
|
|
||||||
],
|
|
||||||
"links": [
|
|
||||||
<span>{</span>
|
|
||||||
"label": "Documentation",
|
|
||||||
"href": "#documentation"
|
|
||||||
<span>}</span>,
|
|
||||||
<span>{</span>
|
|
||||||
"label": "API reference",
|
|
||||||
"href": "#api-reference"
|
|
||||||
<span>}</span>
|
|
||||||
],
|
|
||||||
"values": [
|
|
||||||
"Included",
|
|
||||||
"Standard"
|
|
||||||
]
|
|
||||||
<span>}</span>
|
<span>}</span>
|
||||||
]'
|
]'
|
||||||
|
active="overview"
|
||||||
mobileLabel="Compact example">
|
mobileLabel="Compact example">
|
||||||
<div data-slot="topbar">
|
<div data-slot="topbar">
|
||||||
<div class="showcase-slot">topbar slot</div>
|
<div class="showcase-slot">topbar slot</div>
|
||||||
@@ -1193,291 +757,46 @@ page NavbarDetail {
|
|||||||
</article>
|
</article>
|
||||||
<article class="demo-case">
|
<article class="demo-case">
|
||||||
<header class="demo-case-header">
|
<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>
|
<div><span class="demo-case-eyebrow">Compact</span><h2>Sticky and compact</h2><p>Sticky keeps the bar pinned while the page scrolls. The toggle appears below the tablet breakpoint and the links collapse behind it.</p></div>
|
||||||
<span class="demo-case-number">03</span>
|
<span class="demo-case-number">03</span>
|
||||||
</header>
|
</header>
|
||||||
<div class="demo-workbench">
|
<div class="demo-workbench">
|
||||||
<div id="navbar-demo-3" class="demo-canvas demo-canvas--3">
|
<div id="navbar-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-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
|
||||||
|
|
||||||
<div class="demo-render"><Navbar size="lg" label="Advanced example" topbarLabel="Advanced example" brand='({"id":"navbar-2-1","key":"navbar-2-1","value":"primary","label":"Advanced workflow","title":"Advanced workflow","description":"A richer configuration with more supporting information and actions.","text":"A configurable sample message.","href":"#navbar-demo","actionHref":"#navbar-demo","actionLabel":"Explore workflow","icon":"icon-[lucide--circle-check]","iconClass":"icon-[lucide--circle-check]","variant":"success","status":"Complete","time":"11:45","current":true,"selected":true,"checked":true,"disabled":false,"outgoing":false,"open":true,"number":1,"count":32,"percentage":91,"color":"#059669","target":"_self","ariaLabel":"Open advanced 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","Unlimited"]})' items='[{"id":"navbar-2-1","key":"navbar-2-1","value":"primary","label":"Advanced workflow","title":"Advanced workflow","description":"A richer configuration with more supporting information and actions.","text":"A configurable sample message.","href":"#navbar-demo","actionHref":"#navbar-demo","actionLabel":"Explore workflow","icon":"icon-[lucide--circle-check]","iconClass":"icon-[lucide--circle-check]","variant":"success","status":"Complete","time":"11:45","current":true,"selected":true,"checked":true,"disabled":false,"outgoing":false,"open":true,"number":1,"count":32,"percentage":91,"color":"#059669","target":"_self","ariaLabel":"Open advanced 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","Unlimited"]},{"id":"navbar-2-2","key":"navbar-2-2","value":"secondary","label":"Additional option","title":"Supporting example","description":"A richer configuration with more supporting information and actions.","text":"Another configurable message.","href":"#navbar-demo","actionHref":"#navbar-demo","actionLabel":"Explore workflow","icon":"icon-[lucide--circle-check]","iconClass":"icon-[lucide--circle-check]","variant":"success","status":"Complete","time":"11:45","current":false,"selected":false,"checked":false,"disabled":true,"outgoing":true,"open":true,"number":2,"count":64,"percentage":91,"color":"#059669","target":"_self","ariaLabel":"Open advanced 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","Unlimited"]}]' actions='[{"id":"navbar-2-1","key":"navbar-2-1","value":"primary","label":"Advanced workflow","title":"Advanced workflow","description":"A richer configuration with more supporting information and actions.","text":"A configurable sample message.","href":"#navbar-demo","actionHref":"#navbar-demo","actionLabel":"Explore workflow","icon":"icon-[lucide--circle-check]","iconClass":"icon-[lucide--circle-check]","variant":"success","status":"Complete","time":"11:45","current":true,"selected":true,"checked":true,"disabled":false,"outgoing":false,"open":true,"number":1,"count":32,"percentage":91,"color":"#059669","target":"_self","ariaLabel":"Open advanced 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","Unlimited"]},{"id":"navbar-2-2","key":"navbar-2-2","value":"secondary","label":"Additional option","title":"Supporting example","description":"A richer configuration with more supporting information and actions.","text":"Another configurable message.","href":"#navbar-demo","actionHref":"#navbar-demo","actionLabel":"Explore workflow","icon":"icon-[lucide--circle-check]","iconClass":"icon-[lucide--circle-check]","variant":"success","status":"Complete","time":"11:45","current":false,"selected":false,"checked":false,"disabled":true,"outgoing":true,"open":true,"number":2,"count":64,"percentage":91,"color":"#059669","target":"_self","ariaLabel":"Open advanced 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","Unlimited"]}]' sticky="false" openOnHover="false" mobileLabel="Advanced example" class="showcase-instance showcase-instance--3" /></div>
|
<div class="demo-render"><Navbar size="sm" label="Advanced example" topbarLabel="Advanced example" brand='{demo_obj_2}' items='[{"label":"Docs","href":"/docs","value":"docs"},{"label":"Support","href":"/support","value":"support"}]' actions='[{"label":"Dashboard","href":"/app","variant":"primary"}]' active="docs" sticky="true" openOnHover="false" mobileLabel="Toggle navigation" class="showcase-instance showcase-instance--3" /></div>
|
||||||
</div>
|
</div>
|
||||||
<section class="demo-code" aria-label="Rich configuration usage">
|
<section class="demo-code" aria-label="Sticky and compact usage">
|
||||||
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
|
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
|
||||||
<pre><code><Navbar
|
<pre><code><Navbar
|
||||||
size="lg"
|
size="sm"
|
||||||
label="Advanced example"
|
label="Advanced example"
|
||||||
topbarLabel="Advanced example"
|
topbarLabel="Advanced example"
|
||||||
brand='<span>{</span>
|
brand='<span>{</span>
|
||||||
"id": "navbar-2-1",
|
"label": "Acme",
|
||||||
"key": "navbar-2-1",
|
"href": "/"
|
||||||
"value": "primary",
|
|
||||||
"label": "Advanced workflow",
|
|
||||||
"title": "Advanced workflow",
|
|
||||||
"description": "A richer configuration with more supporting information and actions.",
|
|
||||||
"text": "A configurable sample message.",
|
|
||||||
"href": "#navbar-demo",
|
|
||||||
"actionHref": "#navbar-demo",
|
|
||||||
"actionLabel": "Explore workflow",
|
|
||||||
"icon": "icon-[lucide--circle-check]",
|
|
||||||
"iconClass": "icon-[lucide--circle-check]",
|
|
||||||
"variant": "success",
|
|
||||||
"status": "Complete",
|
|
||||||
"time": "11:45",
|
|
||||||
"current": true,
|
|
||||||
"selected": true,
|
|
||||||
"checked": true,
|
|
||||||
"disabled": false,
|
|
||||||
"outgoing": false,
|
|
||||||
"open": true,
|
|
||||||
"number": 1,
|
|
||||||
"count": 32,
|
|
||||||
"percentage": 91,
|
|
||||||
"color": "#059669",
|
|
||||||
"target": "_self",
|
|
||||||
"ariaLabel": "Open advanced workflow 1",
|
|
||||||
"items": [
|
|
||||||
<span>{</span>
|
|
||||||
"label": "Nested option A",
|
|
||||||
"value": "nested-a"
|
|
||||||
<span>}</span>,
|
|
||||||
<span>{</span>
|
|
||||||
"label": "Nested option B",
|
|
||||||
"value": "nested-b"
|
|
||||||
<span>}</span>
|
|
||||||
],
|
|
||||||
"links": [
|
|
||||||
<span>{</span>
|
|
||||||
"label": "Documentation",
|
|
||||||
"href": "#documentation"
|
|
||||||
<span>}</span>,
|
|
||||||
<span>{</span>
|
|
||||||
"label": "API reference",
|
|
||||||
"href": "#api-reference"
|
|
||||||
<span>}</span>
|
|
||||||
],
|
|
||||||
"values": [
|
|
||||||
"Included",
|
|
||||||
"Unlimited"
|
|
||||||
]
|
|
||||||
<span>}</span>'
|
<span>}</span>'
|
||||||
items='[
|
items='[
|
||||||
<span>{</span>
|
<span>{</span>
|
||||||
"id": "navbar-2-1",
|
"label": "Docs",
|
||||||
"key": "navbar-2-1",
|
"href": "/docs",
|
||||||
"value": "primary",
|
"value": "docs"
|
||||||
"label": "Advanced workflow",
|
|
||||||
"title": "Advanced workflow",
|
|
||||||
"description": "A richer configuration with more supporting information and actions.",
|
|
||||||
"text": "A configurable sample message.",
|
|
||||||
"href": "#navbar-demo",
|
|
||||||
"actionHref": "#navbar-demo",
|
|
||||||
"actionLabel": "Explore workflow",
|
|
||||||
"icon": "icon-[lucide--circle-check]",
|
|
||||||
"iconClass": "icon-[lucide--circle-check]",
|
|
||||||
"variant": "success",
|
|
||||||
"status": "Complete",
|
|
||||||
"time": "11:45",
|
|
||||||
"current": true,
|
|
||||||
"selected": true,
|
|
||||||
"checked": true,
|
|
||||||
"disabled": false,
|
|
||||||
"outgoing": false,
|
|
||||||
"open": true,
|
|
||||||
"number": 1,
|
|
||||||
"count": 32,
|
|
||||||
"percentage": 91,
|
|
||||||
"color": "#059669",
|
|
||||||
"target": "_self",
|
|
||||||
"ariaLabel": "Open advanced workflow 1",
|
|
||||||
"items": [
|
|
||||||
<span>{</span>
|
|
||||||
"label": "Nested option A",
|
|
||||||
"value": "nested-a"
|
|
||||||
<span>}</span>,
|
<span>}</span>,
|
||||||
<span>{</span>
|
<span>{</span>
|
||||||
"label": "Nested option B",
|
"label": "Support",
|
||||||
"value": "nested-b"
|
"href": "/support",
|
||||||
<span>}</span>
|
"value": "support"
|
||||||
],
|
|
||||||
"links": [
|
|
||||||
<span>{</span>
|
|
||||||
"label": "Documentation",
|
|
||||||
"href": "#documentation"
|
|
||||||
<span>}</span>,
|
|
||||||
<span>{</span>
|
|
||||||
"label": "API reference",
|
|
||||||
"href": "#api-reference"
|
|
||||||
<span>}</span>
|
|
||||||
],
|
|
||||||
"values": [
|
|
||||||
"Included",
|
|
||||||
"Unlimited"
|
|
||||||
]
|
|
||||||
<span>}</span>,
|
|
||||||
<span>{</span>
|
|
||||||
"id": "navbar-2-2",
|
|
||||||
"key": "navbar-2-2",
|
|
||||||
"value": "secondary",
|
|
||||||
"label": "Additional option",
|
|
||||||
"title": "Supporting example",
|
|
||||||
"description": "A richer configuration with more supporting information and actions.",
|
|
||||||
"text": "Another configurable message.",
|
|
||||||
"href": "#navbar-demo",
|
|
||||||
"actionHref": "#navbar-demo",
|
|
||||||
"actionLabel": "Explore workflow",
|
|
||||||
"icon": "icon-[lucide--circle-check]",
|
|
||||||
"iconClass": "icon-[lucide--circle-check]",
|
|
||||||
"variant": "success",
|
|
||||||
"status": "Complete",
|
|
||||||
"time": "11:45",
|
|
||||||
"current": false,
|
|
||||||
"selected": false,
|
|
||||||
"checked": false,
|
|
||||||
"disabled": true,
|
|
||||||
"outgoing": true,
|
|
||||||
"open": true,
|
|
||||||
"number": 2,
|
|
||||||
"count": 64,
|
|
||||||
"percentage": 91,
|
|
||||||
"color": "#059669",
|
|
||||||
"target": "_self",
|
|
||||||
"ariaLabel": "Open advanced workflow 2",
|
|
||||||
"items": [
|
|
||||||
<span>{</span>
|
|
||||||
"label": "Nested option A",
|
|
||||||
"value": "nested-a"
|
|
||||||
<span>}</span>,
|
|
||||||
<span>{</span>
|
|
||||||
"label": "Nested option B",
|
|
||||||
"value": "nested-b"
|
|
||||||
<span>}</span>
|
|
||||||
],
|
|
||||||
"links": [
|
|
||||||
<span>{</span>
|
|
||||||
"label": "Documentation",
|
|
||||||
"href": "#documentation"
|
|
||||||
<span>}</span>,
|
|
||||||
<span>{</span>
|
|
||||||
"label": "API reference",
|
|
||||||
"href": "#api-reference"
|
|
||||||
<span>}</span>
|
|
||||||
],
|
|
||||||
"values": [
|
|
||||||
"Included",
|
|
||||||
"Unlimited"
|
|
||||||
]
|
|
||||||
<span>}</span>
|
<span>}</span>
|
||||||
]'
|
]'
|
||||||
actions='[
|
actions='[
|
||||||
<span>{</span>
|
<span>{</span>
|
||||||
"id": "navbar-2-1",
|
"label": "Dashboard",
|
||||||
"key": "navbar-2-1",
|
"href": "/app",
|
||||||
"value": "primary",
|
"variant": "primary"
|
||||||
"label": "Advanced workflow",
|
|
||||||
"title": "Advanced workflow",
|
|
||||||
"description": "A richer configuration with more supporting information and actions.",
|
|
||||||
"text": "A configurable sample message.",
|
|
||||||
"href": "#navbar-demo",
|
|
||||||
"actionHref": "#navbar-demo",
|
|
||||||
"actionLabel": "Explore workflow",
|
|
||||||
"icon": "icon-[lucide--circle-check]",
|
|
||||||
"iconClass": "icon-[lucide--circle-check]",
|
|
||||||
"variant": "success",
|
|
||||||
"status": "Complete",
|
|
||||||
"time": "11:45",
|
|
||||||
"current": true,
|
|
||||||
"selected": true,
|
|
||||||
"checked": true,
|
|
||||||
"disabled": false,
|
|
||||||
"outgoing": false,
|
|
||||||
"open": true,
|
|
||||||
"number": 1,
|
|
||||||
"count": 32,
|
|
||||||
"percentage": 91,
|
|
||||||
"color": "#059669",
|
|
||||||
"target": "_self",
|
|
||||||
"ariaLabel": "Open advanced workflow 1",
|
|
||||||
"items": [
|
|
||||||
<span>{</span>
|
|
||||||
"label": "Nested option A",
|
|
||||||
"value": "nested-a"
|
|
||||||
<span>}</span>,
|
|
||||||
<span>{</span>
|
|
||||||
"label": "Nested option B",
|
|
||||||
"value": "nested-b"
|
|
||||||
<span>}</span>
|
|
||||||
],
|
|
||||||
"links": [
|
|
||||||
<span>{</span>
|
|
||||||
"label": "Documentation",
|
|
||||||
"href": "#documentation"
|
|
||||||
<span>}</span>,
|
|
||||||
<span>{</span>
|
|
||||||
"label": "API reference",
|
|
||||||
"href": "#api-reference"
|
|
||||||
<span>}</span>
|
|
||||||
],
|
|
||||||
"values": [
|
|
||||||
"Included",
|
|
||||||
"Unlimited"
|
|
||||||
]
|
|
||||||
<span>}</span>,
|
|
||||||
<span>{</span>
|
|
||||||
"id": "navbar-2-2",
|
|
||||||
"key": "navbar-2-2",
|
|
||||||
"value": "secondary",
|
|
||||||
"label": "Additional option",
|
|
||||||
"title": "Supporting example",
|
|
||||||
"description": "A richer configuration with more supporting information and actions.",
|
|
||||||
"text": "Another configurable message.",
|
|
||||||
"href": "#navbar-demo",
|
|
||||||
"actionHref": "#navbar-demo",
|
|
||||||
"actionLabel": "Explore workflow",
|
|
||||||
"icon": "icon-[lucide--circle-check]",
|
|
||||||
"iconClass": "icon-[lucide--circle-check]",
|
|
||||||
"variant": "success",
|
|
||||||
"status": "Complete",
|
|
||||||
"time": "11:45",
|
|
||||||
"current": false,
|
|
||||||
"selected": false,
|
|
||||||
"checked": false,
|
|
||||||
"disabled": true,
|
|
||||||
"outgoing": true,
|
|
||||||
"open": true,
|
|
||||||
"number": 2,
|
|
||||||
"count": 64,
|
|
||||||
"percentage": 91,
|
|
||||||
"color": "#059669",
|
|
||||||
"target": "_self",
|
|
||||||
"ariaLabel": "Open advanced workflow 2",
|
|
||||||
"items": [
|
|
||||||
<span>{</span>
|
|
||||||
"label": "Nested option A",
|
|
||||||
"value": "nested-a"
|
|
||||||
<span>}</span>,
|
|
||||||
<span>{</span>
|
|
||||||
"label": "Nested option B",
|
|
||||||
"value": "nested-b"
|
|
||||||
<span>}</span>
|
|
||||||
],
|
|
||||||
"links": [
|
|
||||||
<span>{</span>
|
|
||||||
"label": "Documentation",
|
|
||||||
"href": "#documentation"
|
|
||||||
<span>}</span>,
|
|
||||||
<span>{</span>
|
|
||||||
"label": "API reference",
|
|
||||||
"href": "#api-reference"
|
|
||||||
<span>}</span>
|
|
||||||
],
|
|
||||||
"values": [
|
|
||||||
"Included",
|
|
||||||
"Unlimited"
|
|
||||||
]
|
|
||||||
<span>}</span>
|
<span>}</span>
|
||||||
]'
|
]'
|
||||||
mobileLabel="Advanced example">
|
active="docs"
|
||||||
|
sticky="true">
|
||||||
<div data-slot="topbar">
|
<div data-slot="topbar">
|
||||||
<div class="showcase-slot">topbar slot</div>
|
<div class="showcase-slot">topbar slot</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -1520,7 +839,7 @@ if (component) registerOutputHandler(component, "action", (payload) => <span>
|
|||||||
<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>label</code></td><td>string</td><td><code>"Primary navigation"</code></td><td>No</td></tr><tr><td><code>topbarLabel</code></td><td>string</td><td><code>"Utility navigation"</code></td><td>No</td></tr><tr><td><code>brand</code></td><td>Record<string, unknown></td><td><code><span>{</span><span>}</span></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>actions</code></td><td>unknown[]</td><td><code>[]</code></td><td>No</td></tr><tr><td><code>active</code></td><td>string</td><td><code>""</code></td><td>No</td></tr><tr><td><code>sticky</code></td><td>boolean</td><td><code>false</code></td><td>No</td></tr><tr><td><code>openOnHover</code></td><td>boolean</td><td><code>false</code></td><td>No</td></tr><tr><td><code>maxWidth</code></td><td>string</td><td><code>"full"</code></td><td>No</td></tr><tr><td><code>mobileLabel</code></td><td>string</td><td><code>"Toggle navigation"</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>label</code></td><td>string</td><td><code>"Primary navigation"</code></td><td>No</td></tr><tr><td><code>topbarLabel</code></td><td>string</td><td><code>"Utility navigation"</code></td><td>No</td></tr><tr><td><code>brand</code></td><td>Record<string, unknown></td><td><code><span>{</span><span>}</span></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>actions</code></td><td>unknown[]</td><td><code>[]</code></td><td>No</td></tr><tr><td><code>active</code></td><td>string</td><td><code>""</code></td><td>No</td></tr><tr><td><code>sticky</code></td><td>boolean</td><td><code>false</code></td><td>No</td></tr><tr><td><code>openOnHover</code></td><td>boolean</td><td><code>false</code></td><td>No</td></tr><tr><td><code>maxWidth</code></td><td>string</td><td><code>"full"</code></td><td>No</td></tr><tr><td><code>mobileLabel</code></td><td>string</td><td><code>"Toggle navigation"</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>
|
</main>
|
||||||
<aside class="detail-aside">
|
<aside class="detail-aside">
|
||||||
<div class="detail-toc"><strong>On this page</strong><a href="#playground">Playground</a><a href="#navbar-demo-1">Production default</a><a href="#navbar-demo-2">Compact application</a><a href="#navbar-demo-3">Rich configuration</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="#navbar-demo-1">Brand, links and actions</a><a href="#navbar-demo-2">Dropdown and mega panel</a><a href="#navbar-demo-3">Sticky and compact</a><a href="#events">Outputs</a><a href="#api">Props API</a></div>
|
||||||
</aside>
|
</aside>
|
||||||
</div>
|
</div>
|
||||||
<nav class="detail-pagination">
|
<nav class="detail-pagination">
|
||||||
|
|||||||
@@ -266,16 +266,16 @@ page ScrollspyDetail {
|
|||||||
<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">
|
<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">
|
<article class="demo-case">
|
||||||
<header class="demo-case-header">
|
<header class="demo-case-header">
|
||||||
<div><span class="demo-case-eyebrow">Recommended</span><h2>Table of contents</h2><p>Each href points at an element on the page. The runtime observes those elements and moves aria-current to the link for whichever one is in view, so the marker follows the reader without any component state.</p></div>
|
<div><span class="demo-case-eyebrow">Recommended</span><h2>Follows the reader</h2><p>Scroll the page and the marker moves to whichever section is in view. The sections below are real page content, because the runtime observes against the viewport -- a table of contents inside a small scrolling box would have nothing to react to.</p></div>
|
||||||
<span class="demo-case-number">01</span>
|
<span class="demo-case-number">01</span>
|
||||||
</header>
|
</header>
|
||||||
<div class="demo-workbench">
|
<div class="demo-workbench">
|
||||||
<div id="scrollspy-demo-1" class="demo-canvas demo-canvas--1">
|
<div id="scrollspy-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-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
|
||||||
|
|
||||||
<div class="demo-render"><Scrollspy size="default" items='[{"label":"Overview","href":"#overview"},{"label":"Installation","href":"#installation"},{"label":"Usage","href":"#usage"},{"label":"API","href":"#api"}]' active="#overview" label="Scrollspy" heading="On this page" class="showcase-instance showcase-instance--1" /></div>
|
<div class="demo-render"><div class="showcase-spy-doc"><section id="overview" class="showcase-spy-section"><h3>Overview</h3><p>Scroll this page and watch the marker in the list move. The runtime observes these sections against the viewport, so the current link follows whatever you are reading.</p></section><section id="installation" class="showcase-spy-section"><h3>Installation</h3><p>Each link points at one of these ids. Nothing is wired up by hand -- the component only renders the links, and the runtime moves aria-current.</p></section><section id="usage" class="showcase-spy-section"><h3>Usage</h3><p>The active link is marked with aria-current="location", which is what a screen reader announces, and styled through data-active.</p></section><section id="api" class="showcase-spy-section"><h3>API</h3><p>Clicking a link jumps to its section and marks it immediately, so the control responds even before the scroll settles.</p></section></div><Scrollspy size="default" items='[{"label":"Overview","href":"#overview"},{"label":"Installation","href":"#installation"},{"label":"Usage","href":"#usage"},{"label":"API","href":"#api"}]' active="#overview" label="Scrollspy" heading="On this page" class="showcase-instance showcase-instance--1" /></div>
|
||||||
</div>
|
</div>
|
||||||
<section class="demo-code" aria-label="Table of contents usage">
|
<section class="demo-code" aria-label="Follows the reader usage">
|
||||||
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
|
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
|
||||||
<pre><code><Scrollspy
|
<pre><code><Scrollspy
|
||||||
items='[
|
items='[
|
||||||
@@ -312,7 +312,7 @@ page ScrollspyDetail {
|
|||||||
<div id="scrollspy-demo-2" class="demo-canvas demo-canvas--2">
|
<div id="scrollspy-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-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
|
||||||
|
|
||||||
<div class="demo-render"><Scrollspy size="sm" items='[{"label":"Getting started","href":"#getting-started"},{"label":"Configuration","href":"#configuration"},{"label":"Troubleshooting","href":"#troubleshooting"}]' active="#configuration" label="Compact example" heading="Sections" class="showcase-instance showcase-instance--2" /></div>
|
<div class="demo-render"><Scrollspy size="sm" items='[{"label":"Overview","href":"#overview"},{"label":"Installation","href":"#installation"},{"label":"Usage","href":"#usage"}]' active="#installation" label="Compact example" heading="Sections" class="showcase-instance showcase-instance--2" /></div>
|
||||||
</div>
|
</div>
|
||||||
<section class="demo-code" aria-label="Compact rail usage">
|
<section class="demo-code" aria-label="Compact rail usage">
|
||||||
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
|
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
|
||||||
@@ -320,19 +320,19 @@ page ScrollspyDetail {
|
|||||||
size="sm"
|
size="sm"
|
||||||
items='[
|
items='[
|
||||||
<span>{</span>
|
<span>{</span>
|
||||||
"label": "Getting started",
|
"label": "Overview",
|
||||||
"href": "#getting-started"
|
"href": "#overview"
|
||||||
<span>}</span>,
|
<span>}</span>,
|
||||||
<span>{</span>
|
<span>{</span>
|
||||||
"label": "Configuration",
|
"label": "Installation",
|
||||||
"href": "#configuration"
|
"href": "#installation"
|
||||||
<span>}</span>,
|
<span>}</span>,
|
||||||
<span>{</span>
|
<span>{</span>
|
||||||
"label": "Troubleshooting",
|
"label": "Usage",
|
||||||
"href": "#troubleshooting"
|
"href": "#usage"
|
||||||
<span>}</span>
|
<span>}</span>
|
||||||
]'
|
]'
|
||||||
active="#configuration"
|
active="#installation"
|
||||||
label="Compact example"
|
label="Compact example"
|
||||||
heading="Sections"
|
heading="Sections"
|
||||||
/></code></pre>
|
/></code></pre>
|
||||||
@@ -351,7 +351,7 @@ if (component) registerOutputHandler(component, "change", (payload) => <span>
|
|||||||
<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>color</code></td><td>string</td><td><code>"primary"</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>items</code></td><td>unknown[]</td><td><code>[]</code></td><td>No</td></tr><tr><td><code>active</code></td><td>string</td><td><code>""</code></td><td>No</td></tr><tr><td><code>label</code></td><td>string</td><td><code>"On this page"</code></td><td>No</td></tr><tr><td><code>heading</code></td><td>string</td><td><code>""</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>color</code></td><td>string</td><td><code>"primary"</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>items</code></td><td>unknown[]</td><td><code>[]</code></td><td>No</td></tr><tr><td><code>active</code></td><td>string</td><td><code>""</code></td><td>No</td></tr><tr><td><code>label</code></td><td>string</td><td><code>"On this page"</code></td><td>No</td></tr><tr><td><code>heading</code></td><td>string</td><td><code>""</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>
|
</main>
|
||||||
<aside class="detail-aside">
|
<aside class="detail-aside">
|
||||||
<div class="detail-toc"><strong>On this page</strong><a href="#playground">Playground</a><a href="#scrollspy-demo-1">Table of contents</a><a href="#scrollspy-demo-2">Compact rail</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="#scrollspy-demo-1">Follows the reader</a><a href="#scrollspy-demo-2">Compact rail</a><a href="#events">Outputs</a><a href="#api">Props API</a></div>
|
||||||
</aside>
|
</aside>
|
||||||
</div>
|
</div>
|
||||||
<nav class="detail-pagination">
|
<nav class="detail-pagination">
|
||||||
|
|||||||
@@ -8,6 +8,14 @@ page StepperDetail {
|
|||||||
state playground_orientation = ctx.url.searchParams.get("pg_orientation") ?? "horizontal"
|
state playground_orientation = ctx.url.searchParams.get("pg_orientation") ?? "horizontal"
|
||||||
state playground_clickable = (ctx.url.searchParams.get("pg_clickable") ?? "false") === "true"
|
state playground_clickable = (ctx.url.searchParams.get("pg_clickable") ?? "false") === "true"
|
||||||
state playground_label = ctx.url.searchParams.get("pg_label") ?? "Stepper"
|
state playground_label = ctx.url.searchParams.get("pg_label") ?? "Stepper"
|
||||||
|
state playground_showPanel = (ctx.url.searchParams.get("pg_showPanel") ?? "true") === "true"
|
||||||
|
state playground_controls = (ctx.url.searchParams.get("pg_controls") ?? "false") === "true"
|
||||||
|
state playground_allowSkip = (ctx.url.searchParams.get("pg_allowSkip") ?? "false") === "true"
|
||||||
|
state playground_nextDisabled = (ctx.url.searchParams.get("pg_nextDisabled") ?? "false") === "true"
|
||||||
|
state playground_backLabel = ctx.url.searchParams.get("pg_backLabel") ?? "Stepper"
|
||||||
|
state playground_nextLabel = ctx.url.searchParams.get("pg_nextLabel") ?? "Stepper"
|
||||||
|
state playground_skipLabel = ctx.url.searchParams.get("pg_skipLabel") ?? "Stepper"
|
||||||
|
state playground_finishLabel = ctx.url.searchParams.get("pg_finishLabel") ?? "Stepper"
|
||||||
state playground_class = ctx.url.searchParams.get("pg_class") ?? "showcase-instance showcase-instance--1"
|
state playground_class = ctx.url.searchParams.get("pg_class") ?? "showcase-instance showcase-instance--1"
|
||||||
seo {
|
seo {
|
||||||
title = "Stepper"
|
title = "Stepper"
|
||||||
@@ -22,16 +30,16 @@ page StepperDetail {
|
|||||||
<span class="showcase-eyebrow">Navigation component</span>
|
<span class="showcase-eyebrow">Navigation component</span>
|
||||||
<h1>Stepper</h1>
|
<h1>Stepper</h1>
|
||||||
<p>Theme-aware, responsive stepper component.</p>
|
<p>Theme-aware, responsive stepper component.</p>
|
||||||
<div class="detail-badges"><span>8 props</span><span>2 slots</span><span>1 outputs</span><span>Theme ready</span><span>Responsive</span></div>
|
<div class="detail-badges"><span>16 props</span><span>3 slots</span><span>5 outputs</span><span>Theme ready</span><span>Responsive</span></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="detail-hero-icon"><span class="icon-[lucide--component] size-10" aria-hidden="true"></span></div>
|
<div class="detail-hero-icon"><span class="icon-[lucide--component] size-10" aria-hidden="true"></span></div>
|
||||||
</header>
|
</header>
|
||||||
<section id="playground" class="detail-section playground-section" data-playground data-playground-component="Stepper" data-playground-public-tag="true" data-playground-has-slot="true" data-playground-events="change">
|
<section id="playground" class="detail-section playground-section" data-playground data-playground-component="Stepper" data-playground-public-tag="true" data-playground-has-slot="true" data-playground-events="change,back,next,skip,finish">
|
||||||
<div class="detail-section-heading"><span>Interactive playground</span><h2>Configure Stepper</h2><p>Change any prop and inspect the server-rendered component immediately.</p></div>
|
<div class="detail-section-heading"><span>Interactive playground</span><h2>Configure Stepper</h2><p>Change any prop and inspect the server-rendered component immediately.</p></div>
|
||||||
<div class="playground-workbench">
|
<div class="playground-workbench">
|
||||||
<div class="playground-preview">
|
<div class="playground-preview">
|
||||||
<div class="demo-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
|
<div class="demo-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
|
||||||
<div class="playground-preview-source" data-playground-preview><Stepper color='{playground_color}' size='{playground_size}' steps='{playground_steps}' active='{playground_active}' orientation='{playground_orientation}' clickable='{playground_clickable}' label='{playground_label}' class='{playground_class}' /></div>
|
<div class="playground-preview-source" data-playground-preview><Stepper color='{playground_color}' size='{playground_size}' steps='{playground_steps}' active='{playground_active}' orientation='{playground_orientation}' clickable='{playground_clickable}' label='{playground_label}' showPanel='{playground_showPanel}' controls='{playground_controls}' allowSkip='{playground_allowSkip}' nextDisabled='{playground_nextDisabled}' backLabel='{playground_backLabel}' nextLabel='{playground_nextLabel}' skipLabel='{playground_skipLabel}' finishLabel='{playground_finishLabel}' class='{playground_class}' /></div>
|
||||||
<section class="playground-code" aria-label="Current component code">
|
<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>
|
<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><Stepper
|
<pre><code data-playground-code><Stepper
|
||||||
@@ -143,17 +151,25 @@ page StepperDetail {
|
|||||||
]
|
]
|
||||||
<span>}</span>
|
<span>}</span>
|
||||||
]'
|
]'
|
||||||
label="Stepper">
|
label="Stepper"
|
||||||
|
showPanel="true"
|
||||||
|
backLabel="Stepper"
|
||||||
|
nextLabel="Stepper"
|
||||||
|
skipLabel="Stepper"
|
||||||
|
finishLabel="Stepper">
|
||||||
<div data-slot="step-<span>{</span>index<span>}</span>">
|
<div data-slot="step-<span>{</span>index<span>}</span>">
|
||||||
<div class="showcase-slot">step-<span>{</span>index<span>}</span> slot</div>
|
<div class="showcase-slot">step-<span>{</span>index<span>}</span> slot</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div data-slot="panel-<span>{</span>index<span>}</span>">
|
||||||
|
<div class="showcase-slot">panel-<span>{</span>index<span>}</span> slot</div>
|
||||||
|
</div>
|
||||||
</Stepper></code></pre>
|
</Stepper></code></pre>
|
||||||
</section>
|
</section>
|
||||||
<div class="playground-status" data-playground-status aria-live="polite"></div>
|
<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 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>
|
</div>
|
||||||
<form class="playground-controls" data-playground-form>
|
<form class="playground-controls" data-playground-form>
|
||||||
<header><div><span>Component props</span><strong>8 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>16 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-stepper-color"><span><strong>color</strong><small>string</small></span><select id="playground-stepper-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-stepper-size"><span><strong>size</strong><small>string</small></span><select id="playground-stepper-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-stepper-steps"><span><strong>steps</strong><small>unknown[]</small></span><textarea id="playground-stepper-steps" name="pg_steps" rows="5" spellcheck="false" data-playground-json>[
|
<div class="playground-fields"><label class="playground-field" for="playground-stepper-color"><span><strong>color</strong><small>string</small></span><select id="playground-stepper-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-stepper-size"><span><strong>size</strong><small>string</small></span><select id="playground-stepper-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-stepper-steps"><span><strong>steps</strong><small>unknown[]</small></span><textarea id="playground-stepper-steps" name="pg_steps" rows="5" spellcheck="false" data-playground-json>[
|
||||||
{
|
{
|
||||||
"id": "stepper-0-1",
|
"id": "stepper-0-1",
|
||||||
@@ -261,7 +277,7 @@ page StepperDetail {
|
|||||||
"Standard"
|
"Standard"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]</textarea><em data-playground-error></em></label><label class="playground-field" for="playground-stepper-active"><span><strong>active</strong><small>number</small></span><input id="playground-stepper-active" name="pg_active" type="number" value="0" /></label><label class="playground-field" for="playground-stepper-orientation"><span><strong>orientation</strong><small>string</small></span><select id="playground-stepper-orientation" name="pg_orientation"><option value="horizontal" selected>horizontal</option><option value="vertical">vertical</option></select></label><label class="playground-toggle" for="playground-stepper-clickable"><span><strong>clickable</strong><small>boolean</small></span><input id="playground-stepper-clickable" name="pg_clickable" type="checkbox" value="true" data-playground-boolean /><i aria-hidden="true"></i></label><label class="playground-field" for="playground-stepper-label"><span><strong>label</strong><small>string</small></span><input id="playground-stepper-label" name="pg_label" type="text" value="Stepper" /></label><label class="playground-field" for="playground-stepper-class"><span><strong>class</strong><small>string</small></span><input id="playground-stepper-class" name="pg_class" type="text" value="showcase-instance showcase-instance--1" /></label></div>
|
]</textarea><em data-playground-error></em></label><label class="playground-field" for="playground-stepper-active"><span><strong>active</strong><small>number</small></span><input id="playground-stepper-active" name="pg_active" type="number" value="0" /></label><label class="playground-field" for="playground-stepper-orientation"><span><strong>orientation</strong><small>string</small></span><select id="playground-stepper-orientation" name="pg_orientation"><option value="horizontal" selected>horizontal</option><option value="vertical">vertical</option></select></label><label class="playground-toggle" for="playground-stepper-clickable"><span><strong>clickable</strong><small>boolean</small></span><input id="playground-stepper-clickable" name="pg_clickable" type="checkbox" value="true" data-playground-boolean /><i aria-hidden="true"></i></label><label class="playground-field" for="playground-stepper-label"><span><strong>label</strong><small>string</small></span><input id="playground-stepper-label" name="pg_label" type="text" value="Stepper" /></label><label class="playground-toggle" for="playground-stepper-showPanel"><span><strong>show Panel</strong><small>boolean</small></span><input id="playground-stepper-showPanel" name="pg_showPanel" type="checkbox" value="true" checked data-playground-boolean /><i aria-hidden="true"></i></label><label class="playground-toggle" for="playground-stepper-controls"><span><strong>controls</strong><small>boolean</small></span><input id="playground-stepper-controls" name="pg_controls" type="checkbox" value="true" data-playground-boolean /><i aria-hidden="true"></i></label><label class="playground-toggle" for="playground-stepper-allowSkip"><span><strong>allow Skip</strong><small>boolean</small></span><input id="playground-stepper-allowSkip" name="pg_allowSkip" type="checkbox" value="true" data-playground-boolean /><i aria-hidden="true"></i></label><label class="playground-toggle" for="playground-stepper-nextDisabled"><span><strong>next Disabled</strong><small>boolean</small></span><input id="playground-stepper-nextDisabled" name="pg_nextDisabled" type="checkbox" value="true" data-playground-boolean /><i aria-hidden="true"></i></label><label class="playground-field" for="playground-stepper-backLabel"><span><strong>back Label</strong><small>string</small></span><input id="playground-stepper-backLabel" name="pg_backLabel" type="text" value="Stepper" /></label><label class="playground-field" for="playground-stepper-nextLabel"><span><strong>next Label</strong><small>string</small></span><input id="playground-stepper-nextLabel" name="pg_nextLabel" type="text" value="Stepper" /></label><label class="playground-field" for="playground-stepper-skipLabel"><span><strong>skip Label</strong><small>string</small></span><input id="playground-stepper-skipLabel" name="pg_skipLabel" type="text" value="Stepper" /></label><label class="playground-field" for="playground-stepper-finishLabel"><span><strong>finish Label</strong><small>string</small></span><input id="playground-stepper-finishLabel" name="pg_finishLabel" type="text" value="Stepper" /></label><label class="playground-field" for="playground-stepper-class"><span><strong>class</strong><small>string</small></span><input id="playground-stepper-class" name="pg_class" type="text" value="showcase-instance showcase-instance--1" /></label></div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -277,7 +293,7 @@ page StepperDetail {
|
|||||||
<div id="stepper-demo-1" class="demo-canvas demo-canvas--1">
|
<div id="stepper-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-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
|
||||||
|
|
||||||
<div class="demo-render"><Stepper size="default" steps='[{"label":"Account","description":"Your details"},{"label":"Billing","description":"Payment method"},{"label":"Confirm","description":"Review and submit"}]' active="1" clickable="false" label="Stepper" class="showcase-instance showcase-instance--1" /></div>
|
<div class="demo-render"><Stepper size="default" steps='[{"label":"Account","description":"Your details"},{"label":"Billing","description":"Payment method"},{"label":"Confirm","description":"Review and submit"}]' active="1" clickable="false" label="Stepper" showPanel="false" controls="false" allowSkip="false" nextDisabled="false" backLabel="Back" nextLabel="Next" skipLabel="Skip" finishLabel="Finish" class="showcase-instance showcase-instance--1" /></div>
|
||||||
</div>
|
</div>
|
||||||
<section class="demo-code" aria-label="Horizontal progress usage">
|
<section class="demo-code" aria-label="Horizontal progress usage">
|
||||||
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
|
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
|
||||||
@@ -301,6 +317,9 @@ page StepperDetail {
|
|||||||
<div data-slot="step-<span>{</span>index<span>}</span>">
|
<div data-slot="step-<span>{</span>index<span>}</span>">
|
||||||
<div class="showcase-slot">step-<span>{</span>index<span>}</span> slot</div>
|
<div class="showcase-slot">step-<span>{</span>index<span>}</span> slot</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div data-slot="panel-<span>{</span>index<span>}</span>">
|
||||||
|
<div class="showcase-slot">panel-<span>{</span>index<span>}</span> slot</div>
|
||||||
|
</div>
|
||||||
</Stepper></code></pre>
|
</Stepper></code></pre>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
@@ -314,7 +333,7 @@ page StepperDetail {
|
|||||||
<div id="stepper-demo-2" class="demo-canvas demo-canvas--2">
|
<div id="stepper-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-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
|
||||||
|
|
||||||
<div class="demo-render"><Stepper size="sm" steps='[{"label":"Cloned","icon":"icon-[lucide--git-branch]"},{"label":"Built","icon":"icon-[lucide--hammer]"},{"label":"Deployed","icon":"icon-[lucide--rocket]"}]' active="2" orientation="vertical" clickable="false" label="Compact example" class="showcase-instance showcase-instance--2" /></div>
|
<div class="demo-render"><Stepper size="sm" steps='[{"label":"Cloned","icon":"icon-[lucide--git-branch]"},{"label":"Built","icon":"icon-[lucide--hammer]"},{"label":"Deployed","icon":"icon-[lucide--rocket]"}]' active="2" orientation="vertical" clickable="false" label="Compact example" showPanel="false" controls="false" allowSkip="false" nextDisabled="false" backLabel="Back" nextLabel="Next" skipLabel="Skip" finishLabel="Finish" class="showcase-instance showcase-instance--2" /></div>
|
||||||
</div>
|
</div>
|
||||||
<section class="demo-code" aria-label="Vertical with icons usage">
|
<section class="demo-code" aria-label="Vertical with icons usage">
|
||||||
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
|
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
|
||||||
@@ -340,6 +359,97 @@ page StepperDetail {
|
|||||||
<div data-slot="step-<span>{</span>index<span>}</span>">
|
<div data-slot="step-<span>{</span>index<span>}</span>">
|
||||||
<div class="showcase-slot">step-<span>{</span>index<span>}</span> slot</div>
|
<div class="showcase-slot">step-<span>{</span>index<span>}</span> slot</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div data-slot="panel-<span>{</span>index<span>}</span>">
|
||||||
|
<div class="showcase-slot">panel-<span>{</span>index<span>}</span> slot</div>
|
||||||
|
</div>
|
||||||
|
</Stepper></code></pre>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
<article class="demo-case">
|
||||||
|
<header class="demo-case-header">
|
||||||
|
<div><span class="demo-case-eyebrow">Advanced</span><h2>Wizard with content and controls</h2><p>showPanel renders each step body and shows only the active one, the same contract Tabs uses. controls adds Back, Skip and Next, which becomes Finish on the last step.</p></div>
|
||||||
|
<span class="demo-case-number">03</span>
|
||||||
|
</header>
|
||||||
|
<div class="demo-workbench">
|
||||||
|
<div id="stepper-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"><Stepper size="lg" steps='[{"label":"Account","title":"Your details","content":"Name, email and a password."},{"label":"Billing","title":"How you pay","content":"Card or invoice."},{"label":"Confirm","title":"Review","content":"Check everything before submitting."}]' active="1" clickable="false" label="Advanced example" showPanel="true" controls="true" allowSkip="true" nextDisabled="false" backLabel="Back" nextLabel="Next" skipLabel="Skip" finishLabel="Finish" class="showcase-instance showcase-instance--3" /></div>
|
||||||
|
</div>
|
||||||
|
<section class="demo-code" aria-label="Wizard with content and controls usage">
|
||||||
|
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
|
||||||
|
<pre><code><Stepper
|
||||||
|
size="lg"
|
||||||
|
steps='[
|
||||||
|
<span>{</span>
|
||||||
|
"label": "Account",
|
||||||
|
"title": "Your details",
|
||||||
|
"content": "Name, email and a password."
|
||||||
|
<span>}</span>,
|
||||||
|
<span>{</span>
|
||||||
|
"label": "Billing",
|
||||||
|
"title": "How you pay",
|
||||||
|
"content": "Card or invoice."
|
||||||
|
<span>}</span>,
|
||||||
|
<span>{</span>
|
||||||
|
"label": "Confirm",
|
||||||
|
"title": "Review",
|
||||||
|
"content": "Check everything before submitting."
|
||||||
|
<span>}</span>
|
||||||
|
]'
|
||||||
|
active="1"
|
||||||
|
label="Advanced example"
|
||||||
|
showPanel="true"
|
||||||
|
controls="true"
|
||||||
|
allowSkip="true">
|
||||||
|
<div data-slot="step-<span>{</span>index<span>}</span>">
|
||||||
|
<div class="showcase-slot">step-<span>{</span>index<span>}</span> slot</div>
|
||||||
|
</div>
|
||||||
|
<div data-slot="panel-<span>{</span>index<span>}</span>">
|
||||||
|
<div class="showcase-slot">panel-<span>{</span>index<span>}</span> slot</div>
|
||||||
|
</div>
|
||||||
|
</Stepper></code></pre>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
<article class="demo-case">
|
||||||
|
<header class="demo-case-header">
|
||||||
|
<div><span class="demo-case-eyebrow">Advanced</span><h2>Held until the step is valid</h2><p>The same wizard with nextDisabled set. The component never validates anything itself: the page owns the form, sets this while the step is incomplete, and clears it once the step passes.</p></div>
|
||||||
|
<span class="demo-case-number">04</span>
|
||||||
|
</header>
|
||||||
|
<div class="demo-workbench">
|
||||||
|
<div id="stepper-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"><Stepper size="lg" steps='[{"label":"Account","title":"Your details","content":"This step is not complete yet."},{"label":"Billing","title":"How you pay","content":"Card or invoice."}]' active="0" clickable="false" label="Advanced example" showPanel="true" controls="true" allowSkip="false" nextDisabled="true" backLabel="Back" nextLabel="Next" skipLabel="Skip" finishLabel="Finish" class="showcase-instance showcase-instance--4" /></div>
|
||||||
|
</div>
|
||||||
|
<section class="demo-code" aria-label="Held until the step is valid usage">
|
||||||
|
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
|
||||||
|
<pre><code><Stepper
|
||||||
|
size="lg"
|
||||||
|
steps='[
|
||||||
|
<span>{</span>
|
||||||
|
"label": "Account",
|
||||||
|
"title": "Your details",
|
||||||
|
"content": "This step is not complete yet."
|
||||||
|
<span>}</span>,
|
||||||
|
<span>{</span>
|
||||||
|
"label": "Billing",
|
||||||
|
"title": "How you pay",
|
||||||
|
"content": "Card or invoice."
|
||||||
|
<span>}</span>
|
||||||
|
]'
|
||||||
|
label="Advanced example"
|
||||||
|
showPanel="true"
|
||||||
|
controls="true"
|
||||||
|
nextDisabled="true">
|
||||||
|
<div data-slot="step-<span>{</span>index<span>}</span>">
|
||||||
|
<div class="showcase-slot">step-<span>{</span>index<span>}</span> slot</div>
|
||||||
|
</div>
|
||||||
|
<div data-slot="panel-<span>{</span>index<span>}</span>">
|
||||||
|
<div class="showcase-slot">panel-<span>{</span>index<span>}</span> slot</div>
|
||||||
|
</div>
|
||||||
</Stepper></code></pre>
|
</Stepper></code></pre>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
@@ -347,13 +457,13 @@ page StepperDetail {
|
|||||||
<article class="demo-case">
|
<article class="demo-case">
|
||||||
<header class="demo-case-header">
|
<header class="demo-case-header">
|
||||||
<div><span class="demo-case-eyebrow">Advanced</span><h2>Clickable steps</h2><p>With clickable the steps emit a change output and take arrow-key roving focus. Without it the stepper is read-only and stays out of the tab order.</p></div>
|
<div><span class="demo-case-eyebrow">Advanced</span><h2>Clickable steps</h2><p>With clickable the steps emit a change output and take arrow-key roving focus. Without it the stepper is read-only and stays out of the tab order.</p></div>
|
||||||
<span class="demo-case-number">03</span>
|
<span class="demo-case-number">05</span>
|
||||||
</header>
|
</header>
|
||||||
<div class="demo-workbench">
|
<div class="demo-workbench">
|
||||||
<div id="stepper-demo-3" class="demo-canvas demo-canvas--3">
|
<div id="stepper-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-browser-chrome"><span></span><span></span><span></span><small>Live preview</small></div>
|
||||||
|
|
||||||
<div class="demo-render"><Stepper size="lg" steps='[{"label":"One"},{"label":"Two"},{"label":"Three"}]' active="0" clickable="true" label="Advanced example" class="showcase-instance showcase-instance--3" /></div>
|
<div class="demo-render"><Stepper size="lg" steps='[{"label":"One"},{"label":"Two"},{"label":"Three"}]' active="0" clickable="true" label="Advanced example" showPanel="false" controls="false" allowSkip="false" nextDisabled="false" backLabel="Back" nextLabel="Next" skipLabel="Skip" finishLabel="Finish" class="showcase-instance showcase-instance--5" /></div>
|
||||||
</div>
|
</div>
|
||||||
<section class="demo-code" aria-label="Clickable steps usage">
|
<section class="demo-code" aria-label="Clickable steps usage">
|
||||||
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
|
<header><span><span class="icon-[lucide--code-2] size-4" aria-hidden="true"></span>Component usage</span><small>.wrn</small></header>
|
||||||
@@ -375,23 +485,46 @@ page StepperDetail {
|
|||||||
<div data-slot="step-<span>{</span>index<span>}</span>">
|
<div data-slot="step-<span>{</span>index<span>}</span>">
|
||||||
<div class="showcase-slot">step-<span>{</span>index<span>}</span> slot</div>
|
<div class="showcase-slot">step-<span>{</span>index<span>}</span> slot</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div data-slot="panel-<span>{</span>index<span>}</span>">
|
||||||
|
<div class="showcase-slot">panel-<span>{</span>index<span>}</span> slot</div>
|
||||||
|
</div>
|
||||||
</Stepper></code></pre>
|
</Stepper></code></pre>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</article></div></section>
|
</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>@change</code><span>Fires when the component's committed value or selection changes.</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><Stepper
|
<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>@change</code><span>Fires when the component's committed value or selection changes.</span></div><div><code>@back</code><span>Fires when the component emits the back event.</span></div><div><code>@next</code><span>Fires when the component emits the next event.</span></div><div><code>@skip</code><span>Fires when the component emits the skip event.</span></div><div><code>@finish</code><span>Fires when the component emits the finish 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><Stepper
|
||||||
@change='console.log(payload)'
|
@change='console.log(payload)'
|
||||||
|
@back='console.log(payload)'
|
||||||
|
@next='console.log(payload)'
|
||||||
|
@skip='console.log(payload)'
|
||||||
|
@finish='console.log(payload)'
|
||||||
/></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>{</span> registerOutputHandler <span>}</span> from "@wrnexus/csr/outputs"
|
/></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>{</span> registerOutputHandler <span>}</span> from "@wrnexus/csr/outputs"
|
||||||
|
|
||||||
const component = document.querySelector("[data-ui-component=\"Stepper\"], [data-component=\"Stepper\"]")
|
const component = document.querySelector("[data-ui-component=\"Stepper\"], [data-component=\"Stepper\"]")
|
||||||
|
|
||||||
if (component) registerOutputHandler(component, "change", (payload) => <span>{</span>
|
if (component) registerOutputHandler(component, "change", (payload) => <span>{</span>
|
||||||
console.log("change", payload)
|
console.log("change", payload)
|
||||||
|
<span>}</span>)
|
||||||
|
|
||||||
|
if (component) registerOutputHandler(component, "back", (payload) => <span>{</span>
|
||||||
|
console.log("back", payload)
|
||||||
|
<span>}</span>)
|
||||||
|
|
||||||
|
if (component) registerOutputHandler(component, "next", (payload) => <span>{</span>
|
||||||
|
console.log("next", payload)
|
||||||
|
<span>}</span>)
|
||||||
|
|
||||||
|
if (component) registerOutputHandler(component, "skip", (payload) => <span>{</span>
|
||||||
|
console.log("skip", payload)
|
||||||
|
<span>}</span>)
|
||||||
|
|
||||||
|
if (component) registerOutputHandler(component, "finish", (payload) => <span>{</span>
|
||||||
|
console.log("finish", payload)
|
||||||
<span>}</span>)</code></pre></section></div></div></section>
|
<span>}</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>color</code></td><td>string</td><td><code>"primary"</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>steps</code></td><td>unknown[]</td><td><code>[]</code></td><td>No</td></tr><tr><td><code>active</code></td><td>number</td><td><code>0</code></td><td>No</td></tr><tr><td><code>orientation</code></td><td>string</td><td><code>"horizontal"</code></td><td>No</td></tr><tr><td><code>clickable</code></td><td>boolean</td><td><code>false</code></td><td>No</td></tr><tr><td><code>label</code></td><td>string</td><td><code>"Progress"</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>color</code></td><td>string</td><td><code>"primary"</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>steps</code></td><td>unknown[]</td><td><code>[]</code></td><td>No</td></tr><tr><td><code>active</code></td><td>number</td><td><code>0</code></td><td>No</td></tr><tr><td><code>orientation</code></td><td>string</td><td><code>"horizontal"</code></td><td>No</td></tr><tr><td><code>clickable</code></td><td>boolean</td><td><code>false</code></td><td>No</td></tr><tr><td><code>label</code></td><td>string</td><td><code>"Progress"</code></td><td>No</td></tr><tr><td><code>showPanel</code></td><td>boolean</td><td><code>false</code></td><td>No</td></tr><tr><td><code>controls</code></td><td>boolean</td><td><code>false</code></td><td>No</td></tr><tr><td><code>allowSkip</code></td><td>boolean</td><td><code>false</code></td><td>No</td></tr><tr><td><code>nextDisabled</code></td><td>boolean</td><td><code>false</code></td><td>No</td></tr><tr><td><code>backLabel</code></td><td>string</td><td><code>"Back"</code></td><td>No</td></tr><tr><td><code>nextLabel</code></td><td>string</td><td><code>"Next"</code></td><td>No</td></tr><tr><td><code>skipLabel</code></td><td>string</td><td><code>"Skip"</code></td><td>No</td></tr><tr><td><code>finishLabel</code></td><td>string</td><td><code>"Finish"</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>
|
</main>
|
||||||
<aside class="detail-aside">
|
<aside class="detail-aside">
|
||||||
<div class="detail-toc"><strong>On this page</strong><a href="#playground">Playground</a><a href="#stepper-demo-1">Horizontal progress</a><a href="#stepper-demo-2">Vertical with icons</a><a href="#stepper-demo-3">Clickable steps</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="#stepper-demo-1">Horizontal progress</a><a href="#stepper-demo-2">Vertical with icons</a><a href="#stepper-demo-3">Wizard with content and controls</a><a href="#stepper-demo-4">Held until the step is valid</a><a href="#stepper-demo-5">Clickable steps</a><a href="#events">Outputs</a><a href="#api">Props API</a></div>
|
||||||
</aside>
|
</aside>
|
||||||
</div>
|
</div>
|
||||||
<nav class="detail-pagination">
|
<nav class="detail-pagination">
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ page ComponentShowcase {
|
|||||||
<div class="showcase-stat"><strong>0</strong><span>Duplicate implementations</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>
|
<div class="showcase-stat"><strong>11</strong><span>Focused categories</span></div>
|
||||||
</section>
|
</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="/advanced-forms"><span class="home-category-index">01</span><div><strong>Advanced Forms</strong><p>8 components · 112 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="/base"><span class="home-category-index">02</span><div><strong>Base</strong><p>27 components · 86 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="/core"><span class="home-category-index">03</span><div><strong>Core</strong><p>5 components · 13 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="/data"><span class="home-category-index">04</span><div><strong>Data</strong><p>3 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--1" href="/forms"><span class="home-category-index">05</span><div><strong>Forms</strong><p>12 components · 36 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="/integrations"><span class="home-category-index">06</span><div><strong>Integrations</strong><p>11 components · 33 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="/layout"><span class="home-category-index">07</span><div><strong>Layout</strong><p>15 components · 45 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="/marketing"><span class="home-category-index">08</span><div><strong>Marketing</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="/navigation"><span class="home-category-index">09</span><div><strong>Navigation</strong><p>10 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="/overlays"><span class="home-category-index">010</span><div><strong>Overlays</strong><p>6 components · 18 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="/tables"><span class="home-category-index">011</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></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="/advanced-forms"><span class="home-category-index">01</span><div><strong>Advanced Forms</strong><p>8 components · 112 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="/base"><span class="home-category-index">02</span><div><strong>Base</strong><p>27 components · 86 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="/core"><span class="home-category-index">03</span><div><strong>Core</strong><p>5 components · 13 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="/data"><span class="home-category-index">04</span><div><strong>Data</strong><p>3 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--1" href="/forms"><span class="home-category-index">05</span><div><strong>Forms</strong><p>12 components · 36 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="/integrations"><span class="home-category-index">06</span><div><strong>Integrations</strong><p>11 components · 33 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="/layout"><span class="home-category-index">07</span><div><strong>Layout</strong><p>15 components · 43 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="/marketing"><span class="home-category-index">08</span><div><strong>Marketing</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="/navigation"><span class="home-category-index">09</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--2" href="/overlays"><span class="home-category-index">010</span><div><strong>Overlays</strong><p>6 components · 18 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="/tables"><span class="home-category-index">011</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></div></section>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ page LayoutShowcase {
|
|||||||
<span class="showcase-eyebrow">Component category</span>
|
<span class="showcase-eyebrow">Component category</span>
|
||||||
<h1 class="showcase-title">Layout</h1>
|
<h1 class="showcase-title">Layout</h1>
|
||||||
<p class="showcase-description">15 unique, responsive, theme-aware components. Open a component to inspect multiple live configurations and its complete props API.</p>
|
<p class="showcase-description">15 unique, responsive, theme-aware components. Open a component to inspect multiple live configurations and its complete props API.</p>
|
||||||
<div class="category-meta"><span>15 components</span><span>Multiple use cases</span><span>45 live configurations</span></div>
|
<div class="category-meta"><span>15 components</span><span>Multiple use cases</span><span>43 live configurations</span></div>
|
||||||
</header>
|
</header>
|
||||||
<div class="catalog-grid">
|
<div class="catalog-grid">
|
||||||
<article class="catalog-card" data-interactive-preview="false">
|
<article class="catalog-card" data-interactive-preview="false">
|
||||||
@@ -26,31 +26,31 @@ page LayoutShowcase {
|
|||||||
<article class="catalog-card" data-interactive-preview="false">
|
<article class="catalog-card" data-interactive-preview="false">
|
||||||
<div class="catalog-card-preview">
|
<div class="catalog-card-preview">
|
||||||
<div class="catalog-card-glow" aria-hidden="true"></div>
|
<div class="catalog-card-glow" aria-hidden="true"></div>
|
||||||
<div class="catalog-card-stage"><Container size="default" columns="2" maxWidth="xl" class="showcase-instance showcase-instance--1"><div class="showcase-content-block">Centered container content</div></Container></div>
|
<div class="catalog-card-stage"><Container size="default" columns="2" maxWidth="xl" centered="true" class="showcase-instance showcase-instance--1"><div class="showcase-content-block">Centered container content</div></Container></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="catalog-card-body">
|
<div class="catalog-card-body">
|
||||||
<div><span class="catalog-card-category">Layout</span><h2>Container</h2><p>Constrain and align page content with responsive gutters and compact, wide, or full width options.</p></div>
|
<div><span class="catalog-card-category">Layout</span><h2>Container</h2><p>Constrain and align page content with responsive gutters and compact, wide, or full width options.</p></div>
|
||||||
<div class="catalog-card-footer"><span>6 props · 1 slots</span><a href="/components/container">Explore component <span aria-hidden="true">→</span></a></div>
|
<div class="catalog-card-footer"><span>7 props · 1 slots</span><a href="/components/container">Explore component <span aria-hidden="true">→</span></a></div>
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
<article class="catalog-card" data-interactive-preview="false">
|
<article class="catalog-card" data-interactive-preview="false">
|
||||||
<div class="catalog-card-preview">
|
<div class="catalog-card-preview">
|
||||||
<div class="catalog-card-glow" aria-hidden="true"></div>
|
<div class="catalog-card-glow" aria-hidden="true"></div>
|
||||||
<div class="catalog-card-stage"><CustomScrollbar size="default" columns="2" class="showcase-instance showcase-instance--1" /></div>
|
<div class="catalog-card-stage"><CustomScrollbar size="default" axis="vertical" thickness="8" maxHeight="14rem" radius="999px" class="showcase-instance showcase-instance--1"><div class="showcase-scroll-demo"><p>Line 1. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 2. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 3. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 4. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 5. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 6. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 7. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 8. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 9. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 10. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 11. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 12. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p></div></CustomScrollbar></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="catalog-card-body">
|
<div class="catalog-card-body">
|
||||||
<div><span class="catalog-card-category">Layout</span><h2>Custom Scrollbar</h2><p>Theme-aware, responsive custom scrollbar component.</p></div>
|
<div><span class="catalog-card-category">Layout</span><h2>Custom Scrollbar</h2><p>Theme-aware, responsive custom scrollbar component.</p></div>
|
||||||
<div class="catalog-card-footer"><span>6 props · 1 slots</span><a href="/components/custom-scrollbar">Explore component <span aria-hidden="true">→</span></a></div>
|
<div class="catalog-card-footer"><span>7 props · 1 slots</span><a href="/components/custom-scrollbar">Explore component <span aria-hidden="true">→</span></a></div>
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
<article class="catalog-card" data-interactive-preview="false">
|
<article class="catalog-card" data-interactive-preview="false">
|
||||||
<div class="catalog-card-preview">
|
<div class="catalog-card-preview">
|
||||||
<div class="catalog-card-glow" aria-hidden="true"></div>
|
<div class="catalog-card-glow" aria-hidden="true"></div>
|
||||||
<div class="catalog-card-stage"><Divider size="default" label="Related information" orientation="horizontal" class="showcase-instance showcase-instance--1" /></div>
|
<div class="catalog-card-stage"><Divider size="default" label="Related information" orientation="horizontal" variant="solid" class="showcase-instance showcase-instance--1" /></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="catalog-card-body">
|
<div class="catalog-card-body">
|
||||||
<div><span class="catalog-card-category">Layout</span><h2>Divider</h2><p>Separate related horizontal or vertical content with optional labels, sizes, and semantic colors.</p></div>
|
<div><span class="catalog-card-category">Layout</span><h2>Divider</h2><p>Separate related horizontal or vertical content with optional labels, sizes, and semantic colors.</p></div>
|
||||||
<div class="catalog-card-footer"><span>5 props · 0 slots</span><a href="/components/divider">Explore component <span aria-hidden="true">→</span></a></div>
|
<div class="catalog-card-footer"><span>6 props · 0 slots</span><a href="/components/divider">Explore component <span aria-hidden="true">→</span></a></div>
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
<article class="catalog-card" data-interactive-preview="false">
|
<article class="catalog-card" data-interactive-preview="false">
|
||||||
@@ -80,7 +80,7 @@ page LayoutShowcase {
|
|||||||
</div>
|
</div>
|
||||||
<div class="catalog-card-body">
|
<div class="catalog-card-body">
|
||||||
<div><span class="catalog-card-category">Layout</span><h2>Grid</h2><p>Arrange arbitrary content in a responsive configurable CSS grid with stable columns, gaps, alignment, and width.</p></div>
|
<div><span class="catalog-card-category">Layout</span><h2>Grid</h2><p>Arrange arbitrary content in a responsive configurable CSS grid with stable columns, gaps, alignment, and width.</p></div>
|
||||||
<div class="catalog-card-footer"><span>6 props · 1 slots</span><a href="/components/grid">Explore component <span aria-hidden="true">→</span></a></div>
|
<div class="catalog-card-footer"><span>7 props · 1 slots</span><a href="/components/grid">Explore component <span aria-hidden="true">→</span></a></div>
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
<article class="catalog-card" data-interactive-preview="false">
|
<article class="catalog-card" data-interactive-preview="false">
|
||||||
@@ -90,7 +90,7 @@ page LayoutShowcase {
|
|||||||
</div>
|
</div>
|
||||||
<div class="catalog-card-body">
|
<div class="catalog-card-body">
|
||||||
<div><span class="catalog-card-category">Layout</span><h2>Image</h2><p>Render a responsive image with explicit dimensions, loading behavior, alternative text, sizing, and rounded treatment.</p></div>
|
<div><span class="catalog-card-category">Layout</span><h2>Image</h2><p>Render a responsive image with explicit dimensions, loading behavior, alternative text, sizing, and rounded treatment.</p></div>
|
||||||
<div class="catalog-card-footer"><span>9 props · 1 slots</span><a href="/components/image">Explore component <span aria-hidden="true">→</span></a></div>
|
<div class="catalog-card-footer"><span>10 props · 1 slots</span><a href="/components/image">Explore component <span aria-hidden="true">→</span></a></div>
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
<article class="catalog-card" data-interactive-preview="false">
|
<article class="catalog-card" data-interactive-preview="false">
|
||||||
@@ -106,11 +106,11 @@ page LayoutShowcase {
|
|||||||
<article class="catalog-card" data-interactive-preview="false">
|
<article class="catalog-card" data-interactive-preview="false">
|
||||||
<div class="catalog-card-preview">
|
<div class="catalog-card-preview">
|
||||||
<div class="catalog-card-glow" aria-hidden="true"></div>
|
<div class="catalog-card-glow" aria-hidden="true"></div>
|
||||||
<div class="catalog-card-stage"><LayoutSplitter size="default" columns="2" class="showcase-instance showcase-instance--1" /></div>
|
<div class="catalog-card-stage"><LayoutSplitter size="40" orientation="horizontal" minSize="20" step="5" label="Resize panels" class="showcase-instance showcase-instance--1" /></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="catalog-card-body">
|
<div class="catalog-card-body">
|
||||||
<div><span class="catalog-card-category">Layout</span><h2>Layout Splitter</h2><p>Theme-aware, responsive layout splitter component.</p></div>
|
<div><span class="catalog-card-category">Layout</span><h2>Layout Splitter</h2><p>Theme-aware, responsive layout splitter component.</p></div>
|
||||||
<div class="catalog-card-footer"><span>6 props · 1 slots</span><a href="/components/layout-splitter">Explore component <span aria-hidden="true">→</span></a></div>
|
<div class="catalog-card-footer"><span>7 props · 3 slots</span><a href="/components/layout-splitter">Explore component <span aria-hidden="true">→</span></a></div>
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
<article class="catalog-card" data-interactive-preview="false">
|
<article class="catalog-card" data-interactive-preview="false">
|
||||||
@@ -120,7 +120,7 @@ page LayoutShowcase {
|
|||||||
</div>
|
</div>
|
||||||
<div class="catalog-card-body">
|
<div class="catalog-card-body">
|
||||||
<div><span class="catalog-card-category">Layout</span><h2>Link</h2><p>Render an accessible internal or external link with target, relation, size, color, and public focus or click events.</p></div>
|
<div><span class="catalog-card-category">Layout</span><h2>Link</h2><p>Render an accessible internal or external link with target, relation, size, color, and public focus or click events.</p></div>
|
||||||
<div class="catalog-card-footer"><span>8 props · 1 slots</span><a href="/components/link">Explore component <span aria-hidden="true">→</span></a></div>
|
<div class="catalog-card-footer"><span>9 props · 1 slots</span><a href="/components/link">Explore component <span aria-hidden="true">→</span></a></div>
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
<article class="catalog-card" data-interactive-preview="false">
|
<article class="catalog-card" data-interactive-preview="false">
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ page NavigationShowcase {
|
|||||||
<span class="showcase-eyebrow">Component category</span>
|
<span class="showcase-eyebrow">Component category</span>
|
||||||
<h1 class="showcase-title">Navigation</h1>
|
<h1 class="showcase-title">Navigation</h1>
|
||||||
<p class="showcase-description">10 unique, responsive, theme-aware components. Open a component to inspect multiple live configurations and its complete props API.</p>
|
<p class="showcase-description">10 unique, responsive, theme-aware components. Open a component to inspect multiple live configurations and its complete props API.</p>
|
||||||
<div class="category-meta"><span>10 components</span><span>Multiple use cases</span><span>28 live configurations</span></div>
|
<div class="category-meta"><span>10 components</span><span>Multiple use cases</span><span>30 live configurations</span></div>
|
||||||
</header>
|
</header>
|
||||||
<div class="catalog-grid">
|
<div class="catalog-grid">
|
||||||
<article class="catalog-card" data-interactive-preview="false">
|
<article class="catalog-card" data-interactive-preview="false">
|
||||||
@@ -56,7 +56,7 @@ page NavigationShowcase {
|
|||||||
<article class="catalog-card" data-interactive-preview="false">
|
<article class="catalog-card" data-interactive-preview="false">
|
||||||
<div class="catalog-card-preview">
|
<div class="catalog-card-preview">
|
||||||
<div class="catalog-card-glow" aria-hidden="true"></div>
|
<div class="catalog-card-glow" aria-hidden="true"></div>
|
||||||
<div class="catalog-card-stage"><Navbar size="default" label="Navbar" topbarLabel="Navbar" brand='({"id":"navbar-0-1","key":"navbar-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":"#navbar-demo","actionHref":"#navbar-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"]})' items='[{"id":"navbar-0-1","key":"navbar-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":"#navbar-demo","actionHref":"#navbar-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":"navbar-0-2","key":"navbar-0-2","value":"secondary","label":"Additional option","title":"Supporting example","description":"A clean default configuration for everyday product interfaces.","text":"Another configurable message.","href":"#navbar-demo","actionHref":"#navbar-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"]}]' actions='[{"id":"navbar-0-1","key":"navbar-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":"#navbar-demo","actionHref":"#navbar-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":"navbar-0-2","key":"navbar-0-2","value":"secondary","label":"Additional option","title":"Supporting example","description":"A clean default configuration for everyday product interfaces.","text":"Another configurable message.","href":"#navbar-demo","actionHref":"#navbar-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"]}]' sticky="false" openOnHover="false" mobileLabel="Navbar" class="showcase-instance showcase-instance--1" /></div>
|
<div class="catalog-card-stage"><Navbar size="default" label="Primary navigation" topbarLabel="Navbar" brand='{demo_obj_0}' items='[{"label":"Overview","href":"/","value":"overview"},{"label":"Projects","href":"/projects","value":"projects"},{"label":"Reports","href":"/reports","value":"reports"}]' actions='[{"label":"Sign in","href":"/login","variant":"link"},{"label":"Start free","href":"/signup","variant":"primary"}]' active="projects" sticky="false" openOnHover="false" mobileLabel="Navbar" class="showcase-instance showcase-instance--1" /></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="catalog-card-body">
|
<div class="catalog-card-body">
|
||||||
<div><span class="catalog-card-category">Navigation</span><h2>Navbar</h2><p>Theme-aware, responsive navbar component.</p></div>
|
<div><span class="catalog-card-category">Navigation</span><h2>Navbar</h2><p>Theme-aware, responsive navbar component.</p></div>
|
||||||
@@ -96,11 +96,11 @@ page NavigationShowcase {
|
|||||||
<article class="catalog-card" data-interactive-preview="false">
|
<article class="catalog-card" data-interactive-preview="false">
|
||||||
<div class="catalog-card-preview">
|
<div class="catalog-card-preview">
|
||||||
<div class="catalog-card-glow" aria-hidden="true"></div>
|
<div class="catalog-card-glow" aria-hidden="true"></div>
|
||||||
<div class="catalog-card-stage"><Stepper size="default" steps='[{"label":"Account","description":"Your details"},{"label":"Billing","description":"Payment method"},{"label":"Confirm","description":"Review and submit"}]' active="1" clickable="false" label="Stepper" class="showcase-instance showcase-instance--1" /></div>
|
<div class="catalog-card-stage"><Stepper size="default" steps='[{"label":"Account","description":"Your details"},{"label":"Billing","description":"Payment method"},{"label":"Confirm","description":"Review and submit"}]' active="1" clickable="false" label="Stepper" showPanel="false" controls="false" allowSkip="false" nextDisabled="false" backLabel="Back" nextLabel="Next" skipLabel="Skip" finishLabel="Finish" class="showcase-instance showcase-instance--1" /></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="catalog-card-body">
|
<div class="catalog-card-body">
|
||||||
<div><span class="catalog-card-category">Navigation</span><h2>Stepper</h2><p>Theme-aware, responsive stepper component.</p></div>
|
<div><span class="catalog-card-category">Navigation</span><h2>Stepper</h2><p>Theme-aware, responsive stepper component.</p></div>
|
||||||
<div class="catalog-card-footer"><span>8 props · 2 slots</span><a href="/components/stepper">Explore component <span aria-hidden="true">→</span></a></div>
|
<div class="catalog-card-footer"><span>16 props · 3 slots</span><a href="/components/stepper">Explore component <span aria-hidden="true">→</span></a></div>
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
<article class="catalog-card" data-interactive-preview="false">
|
<article class="catalog-card" data-interactive-preview="false">
|
||||||
|
|||||||
@@ -2925,3 +2925,66 @@ body {
|
|||||||
.demo-canvas:has([data-ui-component="Tooltip"], [data-ui-component="Popover"]) .demo-render {
|
.demo-canvas:has([data-ui-component="Tooltip"], [data-ui-component="Popover"]) .demo-render {
|
||||||
padding-block: 5rem;
|
padding-block: 5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Scrollspy demo sections.
|
||||||
|
*
|
||||||
|
* Real page-flow content on purpose: the runtime observes sections against the
|
||||||
|
* viewport, so a table of contents inside a small scrolling box would have
|
||||||
|
* nothing to react to and the demo could not be tested at all.
|
||||||
|
*/
|
||||||
|
.showcase-spy-doc {
|
||||||
|
display: grid;
|
||||||
|
gap: 0.75rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.showcase-spy-section {
|
||||||
|
min-height: 42vh;
|
||||||
|
padding: 1rem;
|
||||||
|
border: 1px solid var(--wire-color-border);
|
||||||
|
border-radius: var(--wire-radius-md);
|
||||||
|
background: var(--wire-color-surface-soft);
|
||||||
|
scroll-margin-top: 5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.showcase-spy-section h3 {
|
||||||
|
margin: 0 0 0.4rem;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.showcase-spy-section p {
|
||||||
|
margin: 0;
|
||||||
|
color: var(--wire-color-text-muted);
|
||||||
|
font-size: 0.86rem;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CustomScrollbar demo content. A scrolling region shows nothing at all unless
|
||||||
|
* its content overflows, so the demo has to supply enough of it.
|
||||||
|
*/
|
||||||
|
.showcase-scroll-demo {
|
||||||
|
display: grid;
|
||||||
|
gap: 0.5rem;
|
||||||
|
padding: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.showcase-scroll-demo p {
|
||||||
|
margin: 0;
|
||||||
|
color: var(--wire-color-text-muted);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.showcase-scroll-demo--wide {
|
||||||
|
grid-auto-flow: column;
|
||||||
|
grid-auto-columns: 9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.showcase-scroll-demo--wide span {
|
||||||
|
padding: 0.75rem;
|
||||||
|
border: 1px solid var(--wire-color-border);
|
||||||
|
border-radius: var(--wire-radius-sm);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
}
|
||||||
|
|||||||
@@ -424,16 +424,42 @@ function sampleValue(prop, component, variation) {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Object props are hoisted into page state rather than written inline.
|
||||||
|
*
|
||||||
|
* A bare {...} attribute is read by the compiler as an interpolation, and
|
||||||
|
* escaping the braces does not help either: prop coercion runs JSON.parse on
|
||||||
|
* the raw attribute, which never sees the entities decoded, so the mount threw
|
||||||
|
* and the demo silently rendered nothing. Binding to state is what the
|
||||||
|
* playground already does, and it is the only form that survives both.
|
||||||
|
*
|
||||||
|
* Arrays start with [ and are unambiguous, so they stay inline.
|
||||||
|
*/
|
||||||
|
const hoistedObjects = [];
|
||||||
|
|
||||||
|
function resetHoistedObjects() {
|
||||||
|
hoistedObjects.length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function hoistObjectProp(value) {
|
||||||
|
const name = `demo_obj_${hoistedObjects.length}`;
|
||||||
|
// JSON.parse, not a bare object literal: the parser reads a leading brace
|
||||||
|
// as the start of a block and rejects the rest of the page.
|
||||||
|
const json = JSON.stringify(JSON.stringify(value));
|
||||||
|
hoistedObjects.push(` state ${name} = JSON.parse(${json})`);
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
function hoistedObjectStates() {
|
||||||
|
if (!hoistedObjects.length) return "";
|
||||||
|
// playgroundStates has no trailing newline, so lead with one.
|
||||||
|
return "\n" + hoistedObjects.join("\n");
|
||||||
|
}
|
||||||
|
|
||||||
function wrnAttribute(name, value) {
|
function wrnAttribute(name, value) {
|
||||||
if (typeof value === "object" && value !== null) {
|
if (typeof value === "object" && value !== null) {
|
||||||
const expression = JSON.stringify(value).replaceAll("'", "\\u0027");
|
if (!Array.isArray(value)) return `${name}='{${hoistObjectProp(value)}}'`;
|
||||||
/*
|
return `${name}='${JSON.stringify(value).replaceAll("'", "\\u0027")}'`;
|
||||||
* An object literal has to be parenthesised. A bare {...} at the start of
|
|
||||||
* an attribute is read as an interpolation, so the compiler tried to parse
|
|
||||||
* the JSON as JavaScript and stopped at the first colon. Arrays start with
|
|
||||||
* [ and were never affected, which is why only object props broke.
|
|
||||||
*/
|
|
||||||
return `${name}='${Array.isArray(value) ? expression : `(${expression})`}'`;
|
|
||||||
}
|
}
|
||||||
return `${name}="${escapeAttribute(String(value))}"`;
|
return `${name}="${escapeAttribute(String(value))}"`;
|
||||||
}
|
}
|
||||||
@@ -1475,6 +1501,8 @@ function eventDocumentation(component) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function detailPage(component, categoryComponents) {
|
function detailPage(component, categoryComponents) {
|
||||||
|
// Names are per page; without this they accumulate across the whole run.
|
||||||
|
resetHoistedObjects();
|
||||||
const index = categoryComponents.findIndex((item) => item.name === component.name);
|
const index = categoryComponents.findIndex((item) => item.name === component.name);
|
||||||
const previous = categoryComponents[index - 1];
|
const previous = categoryComponents[index - 1];
|
||||||
const next = categoryComponents[index + 1];
|
const next = categoryComponents[index + 1];
|
||||||
@@ -1552,7 +1580,7 @@ function detailPage(component, categoryComponents) {
|
|||||||
return `// Generated by scripts/generate-showcase.mjs. Do not edit directly.
|
return `// Generated by scripts/generate-showcase.mjs. Do not edit directly.
|
||||||
page ${component.name.replace(/[^A-Za-z0-9_]/g, "")}Detail {
|
page ${component.name.replace(/[^A-Za-z0-9_]/g, "")}Detail {
|
||||||
layout = "showcase"
|
layout = "showcase"
|
||||||
${playgroundStates(component)}
|
${playgroundStates(component)}${hoistedObjectStates()}
|
||||||
seo {
|
seo {
|
||||||
title = "${escapeAttribute(displayName(component.name))}"
|
title = "${escapeAttribute(displayName(component.name))}"
|
||||||
description = "${escapeAttribute(component.purpose)}"
|
description = "${escapeAttribute(component.purpose)}"
|
||||||
|
|||||||
@@ -253,12 +253,133 @@ const DATATABLE_ROWS =
|
|||||||
'[{"id": 1, "name": "Northwind", "plan": "Scale", "owner": "A. Okafor", "seats": 6, "status": "Active", "statusHtml": "<span class=\\"showcase-pill showcase-pill--success\\">Active</span>"}, {"id": 2, "name": "Acme Industrial", "plan": "Team", "owner": "R. Silva", "seats": 13, "status": "Trial", "statusHtml": "<span class=\\"showcase-pill showcase-pill--info\\">Trial</span>"}, {"id": 3, "name": "Globex", "plan": "Enterprise", "owner": "M. Chen", "seats": 20, "status": "Past due", "statusHtml": "<span class=\\"showcase-pill showcase-pill--danger\\">Past due</span>"}, {"id": 4, "name": "Initech", "plan": "Starter", "owner": "J. Dubois", "seats": 27, "status": "Active", "statusHtml": "<span class=\\"showcase-pill showcase-pill--success\\">Active</span>"}, {"id": 5, "name": "Umbrella", "plan": "Scale", "owner": "P. Novak", "seats": 34, "status": "Trial", "statusHtml": "<span class=\\"showcase-pill showcase-pill--info\\">Trial</span>"}, {"id": 6, "name": "Stark Labs", "plan": "Team", "owner": "A. Okafor", "seats": 41, "status": "Past due", "statusHtml": "<span class=\\"showcase-pill showcase-pill--danger\\">Past due</span>"}, {"id": 7, "name": "Wayne Foods", "plan": "Enterprise", "owner": "R. Silva", "seats": 48, "status": "Active", "statusHtml": "<span class=\\"showcase-pill showcase-pill--success\\">Active</span>"}, {"id": 8, "name": "Soylent", "plan": "Starter", "owner": "M. Chen", "seats": 55, "status": "Trial", "statusHtml": "<span class=\\"showcase-pill showcase-pill--info\\">Trial</span>"}, {"id": 9, "name": "Hooli", "plan": "Scale", "owner": "J. Dubois", "seats": 62, "status": "Past due", "statusHtml": "<span class=\\"showcase-pill showcase-pill--danger\\">Past due</span>"}, {"id": 10, "name": "Vehement", "plan": "Team", "owner": "P. Novak", "seats": 69, "status": "Active", "statusHtml": "<span class=\\"showcase-pill showcase-pill--success\\">Active</span>"}, {"id": 11, "name": "Massive Dynamic", "plan": "Enterprise", "owner": "A. Okafor", "seats": 76, "status": "Trial", "statusHtml": "<span class=\\"showcase-pill showcase-pill--info\\">Trial</span>"}, {"id": 12, "name": "Cyberdyne", "plan": "Starter", "owner": "R. Silva", "seats": 83, "status": "Past due", "statusHtml": "<span class=\\"showcase-pill showcase-pill--danger\\">Past due</span>"}, {"id": 13, "name": "Tyrell", "plan": "Scale", "owner": "M. Chen", "seats": 90, "status": "Active", "statusHtml": "<span class=\\"showcase-pill showcase-pill--success\\">Active</span>"}, {"id": 14, "name": "Aperture", "plan": "Team", "owner": "J. Dubois", "seats": 97, "status": "Trial", "statusHtml": "<span class=\\"showcase-pill showcase-pill--info\\">Trial</span>"}, {"id": 15, "name": "Black Mesa", "plan": "Enterprise", "owner": "P. Novak", "seats": 104, "status": "Past due", "statusHtml": "<span class=\\"showcase-pill showcase-pill--danger\\">Past due</span>"}]';
|
'[{"id": 1, "name": "Northwind", "plan": "Scale", "owner": "A. Okafor", "seats": 6, "status": "Active", "statusHtml": "<span class=\\"showcase-pill showcase-pill--success\\">Active</span>"}, {"id": 2, "name": "Acme Industrial", "plan": "Team", "owner": "R. Silva", "seats": 13, "status": "Trial", "statusHtml": "<span class=\\"showcase-pill showcase-pill--info\\">Trial</span>"}, {"id": 3, "name": "Globex", "plan": "Enterprise", "owner": "M. Chen", "seats": 20, "status": "Past due", "statusHtml": "<span class=\\"showcase-pill showcase-pill--danger\\">Past due</span>"}, {"id": 4, "name": "Initech", "plan": "Starter", "owner": "J. Dubois", "seats": 27, "status": "Active", "statusHtml": "<span class=\\"showcase-pill showcase-pill--success\\">Active</span>"}, {"id": 5, "name": "Umbrella", "plan": "Scale", "owner": "P. Novak", "seats": 34, "status": "Trial", "statusHtml": "<span class=\\"showcase-pill showcase-pill--info\\">Trial</span>"}, {"id": 6, "name": "Stark Labs", "plan": "Team", "owner": "A. Okafor", "seats": 41, "status": "Past due", "statusHtml": "<span class=\\"showcase-pill showcase-pill--danger\\">Past due</span>"}, {"id": 7, "name": "Wayne Foods", "plan": "Enterprise", "owner": "R. Silva", "seats": 48, "status": "Active", "statusHtml": "<span class=\\"showcase-pill showcase-pill--success\\">Active</span>"}, {"id": 8, "name": "Soylent", "plan": "Starter", "owner": "M. Chen", "seats": 55, "status": "Trial", "statusHtml": "<span class=\\"showcase-pill showcase-pill--info\\">Trial</span>"}, {"id": 9, "name": "Hooli", "plan": "Scale", "owner": "J. Dubois", "seats": 62, "status": "Past due", "statusHtml": "<span class=\\"showcase-pill showcase-pill--danger\\">Past due</span>"}, {"id": 10, "name": "Vehement", "plan": "Team", "owner": "P. Novak", "seats": 69, "status": "Active", "statusHtml": "<span class=\\"showcase-pill showcase-pill--success\\">Active</span>"}, {"id": 11, "name": "Massive Dynamic", "plan": "Enterprise", "owner": "A. Okafor", "seats": 76, "status": "Trial", "statusHtml": "<span class=\\"showcase-pill showcase-pill--info\\">Trial</span>"}, {"id": 12, "name": "Cyberdyne", "plan": "Starter", "owner": "R. Silva", "seats": 83, "status": "Past due", "statusHtml": "<span class=\\"showcase-pill showcase-pill--danger\\">Past due</span>"}, {"id": 13, "name": "Tyrell", "plan": "Scale", "owner": "M. Chen", "seats": 90, "status": "Active", "statusHtml": "<span class=\\"showcase-pill showcase-pill--success\\">Active</span>"}, {"id": 14, "name": "Aperture", "plan": "Team", "owner": "J. Dubois", "seats": 97, "status": "Trial", "statusHtml": "<span class=\\"showcase-pill showcase-pill--info\\">Trial</span>"}, {"id": 15, "name": "Black Mesa", "plan": "Enterprise", "owner": "P. Novak", "seats": 104, "status": "Past due", "statusHtml": "<span class=\\"showcase-pill showcase-pill--danger\\">Past due</span>"}]';
|
||||||
|
|
||||||
export const componentProfiles = {
|
export const componentProfiles = {
|
||||||
Scrollspy: {
|
Navbar: {
|
||||||
demos: [
|
demos: [
|
||||||
standard(
|
standard(
|
||||||
"Table of contents",
|
"Brand, links and actions",
|
||||||
"Each href points at an element on the page. The runtime observes those elements and moves aria-current to the link for whichever one is in view, so the marker follows the reader without any component state.",
|
"The everyday shape: a brand, a row of links with the current page marked, and calls to action on the right. Arrow keys move along the menu bar.",
|
||||||
{
|
{
|
||||||
|
brand: { label: "Northwind", description: "Console", href: "/" },
|
||||||
|
items: [
|
||||||
|
{ label: "Overview", href: "/", value: "overview" },
|
||||||
|
{ label: "Projects", href: "/projects", value: "projects" },
|
||||||
|
{ label: "Reports", href: "/reports", value: "reports" },
|
||||||
|
],
|
||||||
|
actions: [
|
||||||
|
{ label: "Sign in", href: "/login", variant: "link" },
|
||||||
|
{ label: "Start free", href: "/signup", variant: "primary" },
|
||||||
|
],
|
||||||
|
active: "projects",
|
||||||
|
label: "Primary navigation",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
advanced(
|
||||||
|
"Dropdown and mega panel",
|
||||||
|
"An item carrying children opens a panel built from native details and summary, so it is keyboard operable without any extra script. Give a child its own children to get a titled column inside the panel.",
|
||||||
|
{
|
||||||
|
brand: { label: "Northwind", icon: "icon-[lucide--box]", href: "/" },
|
||||||
|
items: [
|
||||||
|
{ label: "Overview", href: "/", value: "overview" },
|
||||||
|
{
|
||||||
|
label: "Products",
|
||||||
|
value: "products",
|
||||||
|
columns: 2,
|
||||||
|
description: "Everything in the platform.",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
label: "Platform",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
label: "Runtime",
|
||||||
|
href: "/runtime",
|
||||||
|
description: "The browser half.",
|
||||||
|
icon: "icon-[lucide--cpu]",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Compiler",
|
||||||
|
href: "/compiler",
|
||||||
|
description: "WRN to JavaScript.",
|
||||||
|
icon: "icon-[lucide--hammer]",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Tooling",
|
||||||
|
children: [
|
||||||
|
{ label: "CLI", href: "/cli", description: "Scaffold and deploy." },
|
||||||
|
{ label: "Editor", href: "/editor", description: "Language server." },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{ label: "Pricing", href: "/pricing", value: "pricing" },
|
||||||
|
],
|
||||||
|
actions: [{ label: "Book a demo", href: "/demo", variant: "primary" }],
|
||||||
|
active: "overview",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
compact(
|
||||||
|
"Sticky and compact",
|
||||||
|
"Sticky keeps the bar pinned while the page scrolls. The toggle appears below the tablet breakpoint and the links collapse behind it.",
|
||||||
|
{
|
||||||
|
brand: { label: "Acme", href: "/" },
|
||||||
|
items: [
|
||||||
|
{ label: "Docs", href: "/docs", value: "docs" },
|
||||||
|
{ label: "Support", href: "/support", value: "support" },
|
||||||
|
],
|
||||||
|
actions: [{ label: "Dashboard", href: "/app", variant: "primary" }],
|
||||||
|
active: "docs",
|
||||||
|
sticky: true,
|
||||||
|
size: "sm",
|
||||||
|
mobileLabel: "Toggle navigation",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
LayoutSplitter: {
|
||||||
|
demos: [
|
||||||
|
standard(
|
||||||
|
"Drag or arrow the divider",
|
||||||
|
"Two panes with a movable divider. Drag it, or focus it and use the arrow keys; Home and End go to the bounds. The size is resolved in the runtime and written onto the container as a custom property, because a pointermove fires far too often to route through a client function.",
|
||||||
|
{ size: 40, minSize: 20, step: 5, orientation: "horizontal", label: "Resize panels" },
|
||||||
|
),
|
||||||
|
advanced(
|
||||||
|
"Stacked panes",
|
||||||
|
"Vertical orientation splits top from bottom and switches the arrow keys to up and down. Below the small breakpoint both orientations stack, because two panes side by side stop making sense on a phone.",
|
||||||
|
{ size: 60, minSize: 25, step: 10, orientation: "vertical", label: "Resize rows" },
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
CustomScrollbar: {
|
||||||
|
demos: [
|
||||||
|
standard(
|
||||||
|
"Themed scrolling region",
|
||||||
|
"Scrollbar appearance is CSS rather than script: scrollbar-width and scrollbar-color are the standard properties, with webkit rules for the engines that still need them. The thumb follows the component colour.",
|
||||||
|
{ axis: "vertical", thickness: 8, maxHeight: "14rem", radius: "999px" },
|
||||||
|
{
|
||||||
|
default: `<div class="showcase-scroll-demo"><p>Line 1. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 2. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 3. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 4. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 5. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 6. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 7. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 8. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 9. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 10. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 11. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p><p>Line 12. A scrolling region only shows its scrollbar when the content actually overflows, so this demo ships enough of it.</p></div>`,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
advanced(
|
||||||
|
"Horizontal, thicker track",
|
||||||
|
"A horizontal region with a heavier track. thickness is clamped, since it arrives as an attribute and a scrollbar wider than its content helps nobody.",
|
||||||
|
{ axis: "horizontal", thickness: 14, maxHeight: "8rem", radius: "4px", color: "info" },
|
||||||
|
{
|
||||||
|
default: `<div class="showcase-scroll-demo showcase-scroll-demo--wide"><span>Column 1</span><span>Column 2</span><span>Column 3</span><span>Column 4</span><span>Column 5</span><span>Column 6</span><span>Column 7</span><span>Column 8</span><span>Column 9</span><span>Column 10</span><span>Column 11</span><span>Column 12</span><span>Column 13</span><span>Column 14</span></div>`,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
Scrollspy: {
|
||||||
|
demos: [
|
||||||
|
{
|
||||||
|
eyebrow: "Recommended",
|
||||||
|
title: "Follows the reader",
|
||||||
|
description:
|
||||||
|
"Scroll the page and the marker moves to whichever section is in view. The sections below are real page content, because the runtime observes against the viewport -- a table of contents inside a small scrolling box would have nothing to react to.",
|
||||||
|
before:
|
||||||
|
'<div class="showcase-spy-doc"><section id="overview" class="showcase-spy-section"><h3>Overview</h3><p>Scroll this page and watch the marker in the list move. The runtime observes these sections against the viewport, so the current link follows whatever you are reading.</p></section><section id="installation" class="showcase-spy-section"><h3>Installation</h3><p>Each link points at one of these ids. Nothing is wired up by hand -- the component only renders the links, and the runtime moves aria-current.</p></section><section id="usage" class="showcase-spy-section"><h3>Usage</h3><p>The active link is marked with aria-current="location", which is what a screen reader announces, and styled through data-active.</p></section><section id="api" class="showcase-spy-section"><h3>API</h3><p>Clicking a link jumps to its section and marks it immediately, so the control responds even before the scroll settles.</p></section></div>',
|
||||||
|
props: {
|
||||||
heading: "On this page",
|
heading: "On this page",
|
||||||
items: [
|
items: [
|
||||||
{ label: "Overview", href: "#overview" },
|
{ label: "Overview", href: "#overview" },
|
||||||
@@ -268,7 +389,8 @@ export const componentProfiles = {
|
|||||||
],
|
],
|
||||||
active: "#overview",
|
active: "#overview",
|
||||||
},
|
},
|
||||||
),
|
slots: {},
|
||||||
|
},
|
||||||
advanced(
|
advanced(
|
||||||
"Compact rail",
|
"Compact rail",
|
||||||
"On a phone the rail becomes a horizontal strip that scrolls, so a long contents list costs one line rather than a screenful.",
|
"On a phone the rail becomes a horizontal strip that scrolls, so a long contents list costs one line rather than a screenful.",
|
||||||
@@ -276,11 +398,11 @@ export const componentProfiles = {
|
|||||||
heading: "Sections",
|
heading: "Sections",
|
||||||
size: "sm",
|
size: "sm",
|
||||||
items: [
|
items: [
|
||||||
{ label: "Getting started", href: "#getting-started" },
|
{ label: "Overview", href: "#overview" },
|
||||||
{ label: "Configuration", href: "#configuration" },
|
{ label: "Installation", href: "#installation" },
|
||||||
{ label: "Troubleshooting", href: "#troubleshooting" },
|
{ label: "Usage", href: "#usage" },
|
||||||
],
|
],
|
||||||
active: "#configuration",
|
active: "#installation",
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -470,6 +592,15 @@ export const componentProfiles = {
|
|||||||
{ label: "Confirm", description: "Review and submit" },
|
{ label: "Confirm", description: "Review and submit" },
|
||||||
],
|
],
|
||||||
active: 1,
|
active: 1,
|
||||||
|
clickable: false,
|
||||||
|
showPanel: false,
|
||||||
|
controls: false,
|
||||||
|
allowSkip: false,
|
||||||
|
nextDisabled: false,
|
||||||
|
backLabel: "Back",
|
||||||
|
nextLabel: "Next",
|
||||||
|
skipLabel: "Skip",
|
||||||
|
finishLabel: "Finish",
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
standard(
|
standard(
|
||||||
@@ -483,6 +614,56 @@ export const componentProfiles = {
|
|||||||
],
|
],
|
||||||
active: 2,
|
active: 2,
|
||||||
orientation: "vertical",
|
orientation: "vertical",
|
||||||
|
clickable: false,
|
||||||
|
showPanel: false,
|
||||||
|
controls: false,
|
||||||
|
allowSkip: false,
|
||||||
|
nextDisabled: false,
|
||||||
|
backLabel: "Back",
|
||||||
|
nextLabel: "Next",
|
||||||
|
skipLabel: "Skip",
|
||||||
|
finishLabel: "Finish",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
advanced(
|
||||||
|
"Wizard with content and controls",
|
||||||
|
"showPanel renders each step body and shows only the active one, the same contract Tabs uses. controls adds Back, Skip and Next, which becomes Finish on the last step.",
|
||||||
|
{
|
||||||
|
steps: [
|
||||||
|
{ label: "Account", title: "Your details", content: "Name, email and a password." },
|
||||||
|
{ label: "Billing", title: "How you pay", content: "Card or invoice." },
|
||||||
|
{ label: "Confirm", title: "Review", content: "Check everything before submitting." },
|
||||||
|
],
|
||||||
|
active: 1,
|
||||||
|
clickable: false,
|
||||||
|
showPanel: true,
|
||||||
|
controls: true,
|
||||||
|
allowSkip: true,
|
||||||
|
nextDisabled: false,
|
||||||
|
backLabel: "Back",
|
||||||
|
nextLabel: "Next",
|
||||||
|
skipLabel: "Skip",
|
||||||
|
finishLabel: "Finish",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
advanced(
|
||||||
|
"Held until the step is valid",
|
||||||
|
"The same wizard with nextDisabled set. The component never validates anything itself: the page owns the form, sets this while the step is incomplete, and clears it once the step passes.",
|
||||||
|
{
|
||||||
|
steps: [
|
||||||
|
{ label: "Account", title: "Your details", content: "This step is not complete yet." },
|
||||||
|
{ label: "Billing", title: "How you pay", content: "Card or invoice." },
|
||||||
|
],
|
||||||
|
active: 0,
|
||||||
|
clickable: false,
|
||||||
|
showPanel: true,
|
||||||
|
controls: true,
|
||||||
|
allowSkip: false,
|
||||||
|
nextDisabled: true,
|
||||||
|
backLabel: "Back",
|
||||||
|
nextLabel: "Next",
|
||||||
|
skipLabel: "Skip",
|
||||||
|
finishLabel: "Finish",
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
advanced(
|
advanced(
|
||||||
@@ -492,6 +673,14 @@ export const componentProfiles = {
|
|||||||
steps: [{ label: "One" }, { label: "Two" }, { label: "Three" }],
|
steps: [{ label: "One" }, { label: "Two" }, { label: "Three" }],
|
||||||
active: 0,
|
active: 0,
|
||||||
clickable: true,
|
clickable: true,
|
||||||
|
showPanel: false,
|
||||||
|
controls: false,
|
||||||
|
allowSkip: false,
|
||||||
|
nextDisabled: false,
|
||||||
|
backLabel: "Back",
|
||||||
|
nextLabel: "Next",
|
||||||
|
skipLabel: "Skip",
|
||||||
|
finishLabel: "Finish",
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -358,7 +358,7 @@
|
|||||||
"category": "layout",
|
"category": "layout",
|
||||||
"purpose": "Constrain and align page content with responsive gutters and compact, wide, or full width options.",
|
"purpose": "Constrain and align page content with responsive gutters and compact, wide, or full width options.",
|
||||||
"demoCount": 3,
|
"demoCount": 3,
|
||||||
"propCount": 6,
|
"propCount": 7,
|
||||||
"slots": ["default"],
|
"slots": ["default"],
|
||||||
"events": [],
|
"events": [],
|
||||||
"profiled": true
|
"profiled": true
|
||||||
@@ -393,11 +393,11 @@
|
|||||||
"slug": "custom-scrollbar",
|
"slug": "custom-scrollbar",
|
||||||
"category": "layout",
|
"category": "layout",
|
||||||
"purpose": "Theme-aware, responsive custom scrollbar component.",
|
"purpose": "Theme-aware, responsive custom scrollbar component.",
|
||||||
"demoCount": 3,
|
"demoCount": 2,
|
||||||
"propCount": 6,
|
"propCount": 7,
|
||||||
"slots": ["default"],
|
"slots": ["default"],
|
||||||
"events": ["scroll"],
|
"events": [],
|
||||||
"profiled": false
|
"profiled": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "DataMap",
|
"name": "DataMap",
|
||||||
@@ -463,7 +463,7 @@
|
|||||||
"category": "layout",
|
"category": "layout",
|
||||||
"purpose": "Separate related horizontal or vertical content with optional labels, sizes, and semantic colors.",
|
"purpose": "Separate related horizontal or vertical content with optional labels, sizes, and semantic colors.",
|
||||||
"demoCount": 3,
|
"demoCount": 3,
|
||||||
"propCount": 5,
|
"propCount": 6,
|
||||||
"slots": [],
|
"slots": [],
|
||||||
"events": [],
|
"events": [],
|
||||||
"profiled": true
|
"profiled": true
|
||||||
@@ -595,7 +595,7 @@
|
|||||||
"category": "layout",
|
"category": "layout",
|
||||||
"purpose": "Arrange arbitrary content in a responsive configurable CSS grid with stable columns, gaps, alignment, and width.",
|
"purpose": "Arrange arbitrary content in a responsive configurable CSS grid with stable columns, gaps, alignment, and width.",
|
||||||
"demoCount": 3,
|
"demoCount": 3,
|
||||||
"propCount": 6,
|
"propCount": 7,
|
||||||
"slots": ["default"],
|
"slots": ["default"],
|
||||||
"events": [],
|
"events": [],
|
||||||
"profiled": true
|
"profiled": true
|
||||||
@@ -631,7 +631,7 @@
|
|||||||
"category": "layout",
|
"category": "layout",
|
||||||
"purpose": "Render a responsive image with explicit dimensions, loading behavior, alternative text, sizing, and rounded treatment.",
|
"purpose": "Render a responsive image with explicit dimensions, loading behavior, alternative text, sizing, and rounded treatment.",
|
||||||
"demoCount": 3,
|
"demoCount": 3,
|
||||||
"propCount": 9,
|
"propCount": 10,
|
||||||
"slots": ["default"],
|
"slots": ["default"],
|
||||||
"events": [],
|
"events": [],
|
||||||
"profiled": true
|
"profiled": true
|
||||||
@@ -690,11 +690,11 @@
|
|||||||
"slug": "layout-splitter",
|
"slug": "layout-splitter",
|
||||||
"category": "layout",
|
"category": "layout",
|
||||||
"purpose": "Theme-aware, responsive layout splitter component.",
|
"purpose": "Theme-aware, responsive layout splitter component.",
|
||||||
"demoCount": 3,
|
"demoCount": 2,
|
||||||
"propCount": 6,
|
"propCount": 7,
|
||||||
"slots": ["default"],
|
"slots": ["start", "end", "default"],
|
||||||
"events": ["resizeStart", "resize", "resizeEnd"],
|
"events": ["sizeChange"],
|
||||||
"profiled": false
|
"profiled": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "LegendIndicator",
|
"name": "LegendIndicator",
|
||||||
@@ -715,7 +715,7 @@
|
|||||||
"category": "layout",
|
"category": "layout",
|
||||||
"purpose": "Render an accessible internal or external link with target, relation, size, color, and public focus or click events.",
|
"purpose": "Render an accessible internal or external link with target, relation, size, color, and public focus or click events.",
|
||||||
"demoCount": 3,
|
"demoCount": 3,
|
||||||
"propCount": 8,
|
"propCount": 9,
|
||||||
"slots": ["default"],
|
"slots": ["default"],
|
||||||
"events": [],
|
"events": [],
|
||||||
"profiled": true
|
"profiled": true
|
||||||
@@ -850,7 +850,7 @@
|
|||||||
"propCount": 13,
|
"propCount": 13,
|
||||||
"slots": ["topbar", "actions"],
|
"slots": ["topbar", "actions"],
|
||||||
"events": ["toggle", "open", "close", "select", "action"],
|
"events": ["toggle", "open", "close", "select", "action"],
|
||||||
"profiled": false
|
"profiled": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "PageHeader",
|
"name": "PageHeader",
|
||||||
@@ -1110,10 +1110,10 @@
|
|||||||
"slug": "stepper",
|
"slug": "stepper",
|
||||||
"category": "navigation",
|
"category": "navigation",
|
||||||
"purpose": "Theme-aware, responsive stepper component.",
|
"purpose": "Theme-aware, responsive stepper component.",
|
||||||
"demoCount": 3,
|
"demoCount": 5,
|
||||||
"propCount": 8,
|
"propCount": 16,
|
||||||
"slots": ["step-{index}", "default"],
|
"slots": ["step-{index}", "panel-{index}", "default"],
|
||||||
"events": ["change"],
|
"events": ["change", "back", "next", "skip", "finish"],
|
||||||
"profiled": true
|
"profiled": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user