Compare commits
56
Commits
f52e1d50e4
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
84e16ebc41 | ||
|
|
7993a303ac | ||
|
|
a99290a216 | ||
|
|
c648efc240 | ||
|
|
decbee2fd1 | ||
|
|
e62e7f5d27 | ||
|
|
b2c74a3a29 | ||
|
|
fe86570f45 | ||
|
|
bc1211ea8b | ||
|
|
d2e24eb089 | ||
|
|
e71885d51c | ||
|
|
138b5d0950 | ||
|
|
7e1eb899b3 | ||
|
|
3f6612cfe7 | ||
|
|
510b3ba777 | ||
|
|
1ff2c3339c | ||
|
|
027873459d | ||
|
|
d0bccfe37e | ||
|
|
120889060a | ||
|
|
26ec18c24b | ||
|
|
7658c5d499 | ||
|
|
3cb6ba1233 | ||
|
|
64db7da08d | ||
|
|
9f6552ea62 | ||
|
|
5bc391e74f | ||
|
|
3327ec0d37 | ||
|
|
ceb865f4f1 | ||
|
|
45309b3f72 | ||
|
|
8f3a13c854 | ||
|
|
eca4447dcf | ||
|
|
904bca21b2 | ||
|
|
b98d417185 | ||
|
|
7d737ec0a0 | ||
|
|
f5538ed621 | ||
|
|
d2d830e7e2 | ||
|
|
0618782355 | ||
|
|
9067e68f69 | ||
|
|
9d64ec60c4 | ||
|
|
fc1eea3939 | ||
|
|
4ec5dad60a | ||
|
|
a1a2947910 | ||
|
|
270040fb5f | ||
|
|
f9e285b182 | ||
|
|
3b402b4e36 | ||
|
|
fa535575c5 | ||
|
|
46ef4b775b | ||
|
|
7a36c1905f | ||
|
|
1a8c75a958 | ||
|
|
b3c93e9b18 | ||
|
|
613ff7ae5b | ||
|
|
e372ae571a | ||
|
|
354082ebc3 | ||
|
|
aa21bc4a18 | ||
|
|
1be482caab | ||
|
|
2d1cda0eab | ||
|
|
d26403fce2 |
@@ -19,7 +19,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: oven-sh/setup-bun@v2
|
- uses: oven-sh/setup-bun@v2
|
||||||
with:
|
with:
|
||||||
bun-version: 1.3.14
|
bun-version: 1.4.0
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 24
|
node-version: 24
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^10.0.1",
|
"@eslint/js": "^10.0.1",
|
||||||
"@types/bun": "^1.3.14",
|
"@types/bun": "^1.4.0",
|
||||||
"@types/react": "^19.2.18",
|
"@types/react": "^19.2.18",
|
||||||
"@types/react-dom": "^19.2.4",
|
"@types/react-dom": "^19.2.4",
|
||||||
"eslint": "^10.8.1",
|
"eslint": "^10.8.1",
|
||||||
@@ -133,7 +133,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^10.0.1",
|
"@eslint/js": "^10.0.1",
|
||||||
"@types/bun": "^1.3.14",
|
"@types/bun": "^1.3.14",
|
||||||
"@wrnexus/cli": "^0.8.35",
|
"@wrnexus/cli": "^0.8.36",
|
||||||
"eslint": "^10.8.1",
|
"eslint": "^10.8.1",
|
||||||
"prettier": "^3.9.6",
|
"prettier": "^3.9.6",
|
||||||
"typescript": "^6.0.3",
|
"typescript": "^6.0.3",
|
||||||
@@ -145,27 +145,27 @@
|
|||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/ai": "^0.8.9",
|
"@wrnexus/ai": "^0.8.9",
|
||||||
"@wrnexus/auth": "^0.8.11",
|
"@wrnexus/auth": "^0.8.12",
|
||||||
"@wrnexus/authz": "^0.8.9",
|
"@wrnexus/authz": "^0.8.9",
|
||||||
"@wrnexus/captcha": "^0.8.10",
|
"@wrnexus/captcha": "^0.8.11",
|
||||||
"@wrnexus/core": "^0.8.9",
|
"@wrnexus/core": "^0.8.9",
|
||||||
"@wrnexus/csr": "^0.8.21",
|
"@wrnexus/csr": "^0.8.21",
|
||||||
"@wrnexus/db": "^0.8.14",
|
"@wrnexus/db": "^0.8.15",
|
||||||
"@wrnexus/dev-server": "^0.8.32",
|
"@wrnexus/dev-server": "^0.8.33",
|
||||||
"@wrnexus/encryption": "^0.8.8",
|
"@wrnexus/encryption": "^0.8.9",
|
||||||
"@wrnexus/helpers": "^0.8.8",
|
"@wrnexus/helpers": "^0.8.8",
|
||||||
"@wrnexus/i18n": "^0.8.10",
|
"@wrnexus/i18n": "^0.8.11",
|
||||||
"@wrnexus/image": "^0.8.9",
|
"@wrnexus/image": "^0.8.10",
|
||||||
"@wrnexus/jwt": "^0.8.8",
|
"@wrnexus/jwt": "^0.8.9",
|
||||||
"@wrnexus/observability": "^0.8.8",
|
"@wrnexus/observability": "^0.8.8",
|
||||||
"@wrnexus/realtime": "^0.8.9",
|
"@wrnexus/realtime": "^0.8.10",
|
||||||
"@wrnexus/security": "^0.8.8",
|
"@wrnexus/security": "^0.8.8",
|
||||||
"@wrnexus/store": "^0.8.8",
|
"@wrnexus/store": "^0.8.8",
|
||||||
"@wrnexus/styles": "^0.8.15",
|
"@wrnexus/styles": "^0.8.15",
|
||||||
"@wrnexus/tracking": "^0.8.8",
|
"@wrnexus/tracking": "^0.8.8",
|
||||||
"@wrnexus/ui": "^0.8.19",
|
"@wrnexus/ui": "^0.8.19",
|
||||||
"@wrnexus/uploader": "^0.8.9",
|
"@wrnexus/uploader": "^0.8.10",
|
||||||
"@wrnexus/validation": "^0.8.9",
|
"@wrnexus/validation": "^0.8.10",
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^10.0.1",
|
"@eslint/js": "^10.0.1",
|
||||||
@@ -173,7 +173,7 @@
|
|||||||
"@iconify/tailwind4": "^1.2.3",
|
"@iconify/tailwind4": "^1.2.3",
|
||||||
"@tailwindcss/cli": "^4.3.3",
|
"@tailwindcss/cli": "^4.3.3",
|
||||||
"@types/bun": "^1.3.14",
|
"@types/bun": "^1.3.14",
|
||||||
"@wrnexus/cli": "^0.8.35",
|
"@wrnexus/cli": "^0.8.36",
|
||||||
"eslint": "^10.8.1",
|
"eslint": "^10.8.1",
|
||||||
"prettier": "^3.9.6",
|
"prettier": "^3.9.6",
|
||||||
"tailwindcss": "^4.3.3",
|
"tailwindcss": "^4.3.3",
|
||||||
@@ -186,27 +186,27 @@
|
|||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/ai": "^0.8.9",
|
"@wrnexus/ai": "^0.8.9",
|
||||||
"@wrnexus/auth": "^0.8.11",
|
"@wrnexus/auth": "^0.8.12",
|
||||||
"@wrnexus/authz": "^0.8.9",
|
"@wrnexus/authz": "^0.8.9",
|
||||||
"@wrnexus/captcha": "^0.8.10",
|
"@wrnexus/captcha": "^0.8.11",
|
||||||
"@wrnexus/core": "^0.8.9",
|
"@wrnexus/core": "^0.8.9",
|
||||||
"@wrnexus/csr": "^0.8.21",
|
"@wrnexus/csr": "^0.8.21",
|
||||||
"@wrnexus/db": "^0.8.14",
|
"@wrnexus/db": "^0.8.15",
|
||||||
"@wrnexus/dev-server": "^0.8.32",
|
"@wrnexus/dev-server": "^0.8.33",
|
||||||
"@wrnexus/encryption": "^0.8.8",
|
"@wrnexus/encryption": "^0.8.9",
|
||||||
"@wrnexus/helpers": "^0.8.8",
|
"@wrnexus/helpers": "^0.8.8",
|
||||||
"@wrnexus/i18n": "^0.8.10",
|
"@wrnexus/i18n": "^0.8.11",
|
||||||
"@wrnexus/image": "^0.8.9",
|
"@wrnexus/image": "^0.8.10",
|
||||||
"@wrnexus/jwt": "^0.8.8",
|
"@wrnexus/jwt": "^0.8.9",
|
||||||
"@wrnexus/observability": "^0.8.8",
|
"@wrnexus/observability": "^0.8.8",
|
||||||
"@wrnexus/realtime": "^0.8.9",
|
"@wrnexus/realtime": "^0.8.10",
|
||||||
"@wrnexus/security": "^0.8.8",
|
"@wrnexus/security": "^0.8.8",
|
||||||
"@wrnexus/store": "^0.8.8",
|
"@wrnexus/store": "^0.8.8",
|
||||||
"@wrnexus/styles": "^0.8.15",
|
"@wrnexus/styles": "^0.8.15",
|
||||||
"@wrnexus/tracking": "^0.8.8",
|
"@wrnexus/tracking": "^0.8.8",
|
||||||
"@wrnexus/ui": "^0.8.19",
|
"@wrnexus/ui": "^0.8.19",
|
||||||
"@wrnexus/uploader": "^0.8.9",
|
"@wrnexus/uploader": "^0.8.10",
|
||||||
"@wrnexus/validation": "^0.8.9",
|
"@wrnexus/validation": "^0.8.10",
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^10.0.1",
|
"@eslint/js": "^10.0.1",
|
||||||
@@ -214,7 +214,7 @@
|
|||||||
"@iconify/tailwind4": "^1.2.3",
|
"@iconify/tailwind4": "^1.2.3",
|
||||||
"@tailwindcss/cli": "^4.3.3",
|
"@tailwindcss/cli": "^4.3.3",
|
||||||
"@types/bun": "^1.3.14",
|
"@types/bun": "^1.3.14",
|
||||||
"@wrnexus/cli": "^0.8.35",
|
"@wrnexus/cli": "^0.8.36",
|
||||||
"eslint": "^10.8.1",
|
"eslint": "^10.8.1",
|
||||||
"prettier": "^3.9.6",
|
"prettier": "^3.9.6",
|
||||||
"tailwindcss": "^4.3.3",
|
"tailwindcss": "^4.3.3",
|
||||||
@@ -277,7 +277,7 @@
|
|||||||
},
|
},
|
||||||
"packages/captcha": {
|
"packages/captcha": {
|
||||||
"name": "@wrnexus/captcha",
|
"name": "@wrnexus/captcha",
|
||||||
"version": "0.8.11",
|
"version": "0.8.14",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "workspace:*",
|
"@wrnexus/core": "workspace:*",
|
||||||
"@wrnexus/plugin": "workspace:*",
|
"@wrnexus/plugin": "workspace:*",
|
||||||
@@ -292,7 +292,7 @@
|
|||||||
},
|
},
|
||||||
"packages/cli": {
|
"packages/cli": {
|
||||||
"name": "@wrnexus/cli",
|
"name": "@wrnexus/cli",
|
||||||
"version": "0.8.60",
|
"version": "0.8.64",
|
||||||
"bin": {
|
"bin": {
|
||||||
"wrnexus": "src/index.ts",
|
"wrnexus": "src/index.ts",
|
||||||
},
|
},
|
||||||
@@ -320,7 +320,7 @@
|
|||||||
},
|
},
|
||||||
"packages/compiler": {
|
"packages/compiler": {
|
||||||
"name": "@wrnexus/compiler",
|
"name": "@wrnexus/compiler",
|
||||||
"version": "0.8.21",
|
"version": "0.8.22",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/csr": "workspace:*",
|
"@wrnexus/csr": "workspace:*",
|
||||||
"@wrnexus/store": "workspace:*",
|
"@wrnexus/store": "workspace:*",
|
||||||
@@ -342,7 +342,7 @@
|
|||||||
},
|
},
|
||||||
"packages/csr": {
|
"packages/csr": {
|
||||||
"name": "@wrnexus/csr",
|
"name": "@wrnexus/csr",
|
||||||
"version": "0.8.33",
|
"version": "0.8.35",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "workspace:*",
|
"@wrnexus/core": "workspace:*",
|
||||||
},
|
},
|
||||||
@@ -357,7 +357,7 @@
|
|||||||
},
|
},
|
||||||
"packages/dev-server": {
|
"packages/dev-server": {
|
||||||
"name": "@wrnexus/dev-server",
|
"name": "@wrnexus/dev-server",
|
||||||
"version": "0.8.52",
|
"version": "0.8.56",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/authz": "workspace:*",
|
"@wrnexus/authz": "workspace:*",
|
||||||
"@wrnexus/cache": "workspace:*",
|
"@wrnexus/cache": "workspace:*",
|
||||||
@@ -372,6 +372,7 @@
|
|||||||
"@wrnexus/pubsub": "workspace:*",
|
"@wrnexus/pubsub": "workspace:*",
|
||||||
"@wrnexus/pwa": "workspace:*",
|
"@wrnexus/pwa": "workspace:*",
|
||||||
"@wrnexus/queue": "workspace:*",
|
"@wrnexus/queue": "workspace:*",
|
||||||
|
"@wrnexus/react": "workspace:*",
|
||||||
"@wrnexus/router": "workspace:*",
|
"@wrnexus/router": "workspace:*",
|
||||||
"@wrnexus/rpc": "workspace:*",
|
"@wrnexus/rpc": "workspace:*",
|
||||||
"@wrnexus/security": "workspace:*",
|
"@wrnexus/security": "workspace:*",
|
||||||
@@ -385,7 +386,7 @@
|
|||||||
},
|
},
|
||||||
"packages/dev-toolbar": {
|
"packages/dev-toolbar": {
|
||||||
"name": "@wrnexus/dev-toolbar",
|
"name": "@wrnexus/dev-toolbar",
|
||||||
"version": "0.8.13",
|
"version": "0.8.16",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bun": "^1.3.14",
|
"@types/bun": "^1.3.14",
|
||||||
"typescript": "^6.0.3",
|
"typescript": "^6.0.3",
|
||||||
@@ -654,7 +655,7 @@
|
|||||||
},
|
},
|
||||||
"packages/store": {
|
"packages/store": {
|
||||||
"name": "@wrnexus/store",
|
"name": "@wrnexus/store",
|
||||||
"version": "0.8.9",
|
"version": "0.8.12",
|
||||||
},
|
},
|
||||||
"packages/styles": {
|
"packages/styles": {
|
||||||
"name": "@wrnexus/styles",
|
"name": "@wrnexus/styles",
|
||||||
@@ -667,7 +668,7 @@
|
|||||||
},
|
},
|
||||||
"packages/syntax": {
|
"packages/syntax": {
|
||||||
"name": "@wrnexus/syntax",
|
"name": "@wrnexus/syntax",
|
||||||
"version": "0.8.13",
|
"version": "0.8.18",
|
||||||
},
|
},
|
||||||
"packages/test": {
|
"packages/test": {
|
||||||
"name": "@wrnexus/test",
|
"name": "@wrnexus/test",
|
||||||
@@ -679,7 +680,7 @@
|
|||||||
},
|
},
|
||||||
"packages/typecheck": {
|
"packages/typecheck": {
|
||||||
"name": "@wrnexus/typecheck",
|
"name": "@wrnexus/typecheck",
|
||||||
"version": "0.8.13",
|
"version": "0.8.16",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/syntax": "workspace:*",
|
"@wrnexus/syntax": "workspace:*",
|
||||||
"typescript": "^6.0.3",
|
"typescript": "^6.0.3",
|
||||||
@@ -687,14 +688,14 @@
|
|||||||
},
|
},
|
||||||
"packages/ui": {
|
"packages/ui": {
|
||||||
"name": "@wrnexus/ui",
|
"name": "@wrnexus/ui",
|
||||||
"version": "0.8.23",
|
"version": "0.8.56",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "workspace:*",
|
"@wrnexus/core": "workspace:*",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"packages/uploader": {
|
"packages/uploader": {
|
||||||
"name": "@wrnexus/uploader",
|
"name": "@wrnexus/uploader",
|
||||||
"version": "0.8.10",
|
"version": "0.8.13",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "workspace:*",
|
"@wrnexus/core": "workspace:*",
|
||||||
"@wrnexus/plugin": "workspace:*",
|
"@wrnexus/plugin": "workspace:*",
|
||||||
@@ -795,7 +796,7 @@
|
|||||||
|
|
||||||
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.28.1", "", { "os": "win32", "cpu": "x64" }, "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A=="],
|
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.28.1", "", { "os": "win32", "cpu": "x64" }, "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A=="],
|
||||||
|
|
||||||
"@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.9.1", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ=="],
|
"@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.10.1", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg=="],
|
||||||
|
|
||||||
"@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.2", "", {}, "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew=="],
|
"@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.2", "", {}, "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew=="],
|
||||||
|
|
||||||
@@ -821,7 +822,7 @@
|
|||||||
|
|
||||||
"@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="],
|
"@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="],
|
||||||
|
|
||||||
"@iconify-json/lucide": ["@iconify-json/lucide@1.2.123", "", { "dependencies": { "@iconify/types": "*" } }, "sha512-0CozmpKXEOEEhltrfT2zt+/t1hez67Y+hM2VJWoIcBKdBrb83VYuKf+b5A0QU9HfQm+RNn2GjFWlTOwi+Ss6IA=="],
|
"@iconify-json/lucide": ["@iconify-json/lucide@1.2.125", "", { "dependencies": { "@iconify/types": "*" } }, "sha512-tOCk1QKMtKnCfPAgZRHgjRkQTP7wF5IO+iPKvvp8vxGZYPkSLhx4HTV3Ng0pIZ3wNWrS6kVpHkunJ1dc19L1og=="],
|
||||||
|
|
||||||
"@iconify/tailwind4": ["@iconify/tailwind4@1.2.3", "", { "dependencies": { "@iconify/tools": "^5.0.5", "@iconify/types": "^2.0.0", "@iconify/utils": "^3.1.0" }, "peerDependencies": { "tailwindcss": ">= 4.0.0" } }, "sha512-z8SKiMHRASJKF/IY//87MF88lcB7ulxh8vlhQXXLWsBkNtOh6ese9R41MyGpQeqXdRvQVt+/fX2glQtHFjQ+MA=="],
|
"@iconify/tailwind4": ["@iconify/tailwind4@1.2.3", "", { "dependencies": { "@iconify/tools": "^5.0.5", "@iconify/types": "^2.0.0", "@iconify/utils": "^3.1.0" }, "peerDependencies": { "tailwindcss": ">= 4.0.0" } }, "sha512-z8SKiMHRASJKF/IY//87MF88lcB7ulxh8vlhQXXLWsBkNtOh6ese9R41MyGpQeqXdRvQVt+/fX2glQtHFjQ+MA=="],
|
||||||
|
|
||||||
@@ -841,6 +842,8 @@
|
|||||||
|
|
||||||
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],
|
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],
|
||||||
|
|
||||||
|
"@napi-rs/lzma-linux-x64-gnu": ["@napi-rs/lzma-linux-x64-gnu@1.5.1", "", { "os": "linux", "cpu": "x64" }, "sha512-oTXEIha4SsuXdTA4Iyskj0kpdx2yVXdhd75c2v3xGrHFfVMsbhTPZU/nMPL4sWKo4pBHm3aucLaqGlF696dTyQ=="],
|
||||||
|
|
||||||
"@noble/hashes": ["@noble/hashes@1.4.0", "", {}, "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg=="],
|
"@noble/hashes": ["@noble/hashes@1.4.0", "", {}, "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg=="],
|
||||||
|
|
||||||
"@parcel/watcher": ["@parcel/watcher@2.5.1", "", { "dependencies": { "detect-libc": "^1.0.3", "is-glob": "^4.0.3", "micromatch": "^4.0.5", "node-addon-api": "^7.0.0" }, "optionalDependencies": { "@parcel/watcher-android-arm64": "2.5.1", "@parcel/watcher-darwin-arm64": "2.5.1", "@parcel/watcher-darwin-x64": "2.5.1", "@parcel/watcher-freebsd-x64": "2.5.1", "@parcel/watcher-linux-arm-glibc": "2.5.1", "@parcel/watcher-linux-arm-musl": "2.5.1", "@parcel/watcher-linux-arm64-glibc": "2.5.1", "@parcel/watcher-linux-arm64-musl": "2.5.1", "@parcel/watcher-linux-x64-glibc": "2.5.1", "@parcel/watcher-linux-x64-musl": "2.5.1", "@parcel/watcher-win32-arm64": "2.5.1", "@parcel/watcher-win32-ia32": "2.5.1", "@parcel/watcher-win32-x64": "2.5.1" } }, "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg=="],
|
"@parcel/watcher": ["@parcel/watcher@2.5.1", "", { "dependencies": { "detect-libc": "^1.0.3", "is-glob": "^4.0.3", "micromatch": "^4.0.5", "node-addon-api": "^7.0.0" }, "optionalDependencies": { "@parcel/watcher-android-arm64": "2.5.1", "@parcel/watcher-darwin-arm64": "2.5.1", "@parcel/watcher-darwin-x64": "2.5.1", "@parcel/watcher-freebsd-x64": "2.5.1", "@parcel/watcher-linux-arm-glibc": "2.5.1", "@parcel/watcher-linux-arm-musl": "2.5.1", "@parcel/watcher-linux-arm64-glibc": "2.5.1", "@parcel/watcher-linux-arm64-musl": "2.5.1", "@parcel/watcher-linux-x64-glibc": "2.5.1", "@parcel/watcher-linux-x64-musl": "2.5.1", "@parcel/watcher-win32-arm64": "2.5.1", "@parcel/watcher-win32-ia32": "2.5.1", "@parcel/watcher-win32-x64": "2.5.1" } }, "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg=="],
|
||||||
@@ -871,79 +874,79 @@
|
|||||||
|
|
||||||
"@parcel/watcher-win32-x64": ["@parcel/watcher-win32-x64@2.5.1", "", { "os": "win32", "cpu": "x64" }, "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA=="],
|
"@parcel/watcher-win32-x64": ["@parcel/watcher-win32-x64@2.5.1", "", { "os": "win32", "cpu": "x64" }, "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA=="],
|
||||||
|
|
||||||
"@peculiar/asn1-cms": ["@peculiar/asn1-cms@2.8.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.8.0", "@peculiar/asn1-x509": "^2.8.0", "@peculiar/asn1-x509-attr": "^2.8.0", "asn1js": "^3.0.10", "tslib": "^2.8.1" } }, "sha512-NgekZOrSJFSBFLFoLfwePguAWAx7z1+f2TEsWFUMyiqqfntZ4+S/S5hzqME3q4pCA0iOsFKdwiQ35dwY24eVqA=="],
|
"@peculiar/asn1-cms": ["@peculiar/asn1-cms@2.9.4", "", { "dependencies": { "@peculiar/asn1-schema": "^2.9.4", "@peculiar/asn1-x509": "^2.9.4", "@peculiar/asn1-x509-attr": "^2.9.4", "asn1js": "^3.0.10", "tslib": "^2.8.1" } }, "sha512-cben7oxmQsUGZqotus7yt0srYdncOT6RNWcTQ77T2RFOXejYVYkXadrfePdRcrVpO9K95IRLKKglG2k38jKXuw=="],
|
||||||
|
|
||||||
"@peculiar/asn1-csr": ["@peculiar/asn1-csr@2.8.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.8.0", "@peculiar/asn1-x509": "^2.8.0", "asn1js": "^3.0.10", "tslib": "^2.8.1" } }, "sha512-akbF8+uvleHs8sejNPQxwmVFuInAg6FMNHOwMILXfP518YfFJwdR3jr6oNUPOaEJfuEhn/vkNOCIT6ASUd4mbg=="],
|
"@peculiar/asn1-csr": ["@peculiar/asn1-csr@2.9.4", "", { "dependencies": { "@peculiar/asn1-schema": "^2.9.4", "@peculiar/asn1-x509": "^2.9.4", "asn1js": "^3.0.10", "tslib": "^2.8.1" } }, "sha512-xd4YN4vpRjkDAQWVfZZkeu12IEND7DOpkqaHSIHxZl1uggUNa9Ju0QxY2jHvDAS9pP0zhRBytg8ifsnGo3V0jw=="],
|
||||||
|
|
||||||
"@peculiar/asn1-ecc": ["@peculiar/asn1-ecc@2.8.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.8.0", "@peculiar/asn1-x509": "^2.8.0", "asn1js": "^3.0.10", "tslib": "^2.8.1" } }, "sha512-ohwlk+u9Rv2NOAY1c6MfHj45ATVF8R1DUN/WCgABiRtLi2ZftlZWZX7KvpAbU8v9xPcmoILfELeEABj/rn18AQ=="],
|
"@peculiar/asn1-ecc": ["@peculiar/asn1-ecc@2.9.4", "", { "dependencies": { "@peculiar/asn1-schema": "^2.9.4", "@peculiar/asn1-x509": "^2.9.4", "asn1js": "^3.0.10", "tslib": "^2.8.1" } }, "sha512-JJXefFshRAuVAjWQo/39bkg1ywc1VaiO44S8RRC+Ykvf/u2KDmYffoDb0ZBPCR5uJy4AGKQhl8mX+Q8ShcWaXQ=="],
|
||||||
|
|
||||||
"@peculiar/asn1-pfx": ["@peculiar/asn1-pfx@2.8.0", "", { "dependencies": { "@peculiar/asn1-cms": "^2.8.0", "@peculiar/asn1-pkcs8": "^2.8.0", "@peculiar/asn1-rsa": "^2.8.0", "@peculiar/asn1-schema": "^2.8.0", "asn1js": "^3.0.10", "tslib": "^2.8.1" } }, "sha512-5yof1ytoB++RQtaFbqSUJ8pxDJtZT6vbVqZ8XoJ61ph7UjNVvfFwAilnCodqkNsAodpy13gDhoxZXw00pghnyg=="],
|
"@peculiar/asn1-pfx": ["@peculiar/asn1-pfx@2.9.4", "", { "dependencies": { "@peculiar/asn1-cms": "^2.9.4", "@peculiar/asn1-pkcs8": "^2.9.4", "@peculiar/asn1-rsa": "^2.9.4", "@peculiar/asn1-schema": "^2.9.4", "asn1js": "^3.0.10", "tslib": "^2.8.1" } }, "sha512-khuGzHTzNzk4GDlIBEILyIs6Lce0yn0ZBdoI9v93kmNncfZRhD+AQ5ODFqdhvoE8cMJF/JMTQ8yA+t1D14kqCw=="],
|
||||||
|
|
||||||
"@peculiar/asn1-pkcs8": ["@peculiar/asn1-pkcs8@2.8.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.8.0", "@peculiar/asn1-x509": "^2.8.0", "asn1js": "^3.0.10", "tslib": "^2.8.1" } }, "sha512-qAKXtLpBEw9LqhKpjw3ajZSXlBur+ipW+y2ivVBQAG6F6qRx94yO+1ZR4mvw+YaCfKSaOzLeYEzsPaBp4SJELA=="],
|
"@peculiar/asn1-pkcs8": ["@peculiar/asn1-pkcs8@2.9.4", "", { "dependencies": { "@peculiar/asn1-schema": "^2.9.4", "@peculiar/asn1-x509": "^2.9.4", "asn1js": "^3.0.10", "tslib": "^2.8.1" } }, "sha512-duRdotlUx9eDZe6QrQpQKl61RbWykCHBCkKayP8V8XdEFwlKHZ8qGGDMyS6Pye7OX7nLFttTTpRkJeet78ckwQ=="],
|
||||||
|
|
||||||
"@peculiar/asn1-pkcs9": ["@peculiar/asn1-pkcs9@2.8.0", "", { "dependencies": { "@peculiar/asn1-cms": "^2.8.0", "@peculiar/asn1-pfx": "^2.8.0", "@peculiar/asn1-pkcs8": "^2.8.0", "@peculiar/asn1-schema": "^2.8.0", "@peculiar/asn1-x509": "^2.8.0", "@peculiar/asn1-x509-attr": "^2.8.0", "asn1js": "^3.0.10", "tslib": "^2.8.1" } }, "sha512-b5nDWCnkV60+cQ141D6sVVwK9nz64R5n3zSVnklGd+ECdkW2Ol3U1a6yYFlalpSOaD557yuJB64A+q42jG7lUQ=="],
|
"@peculiar/asn1-pkcs9": ["@peculiar/asn1-pkcs9@2.9.4", "", { "dependencies": { "@peculiar/asn1-cms": "^2.9.4", "@peculiar/asn1-pfx": "^2.9.4", "@peculiar/asn1-pkcs8": "^2.9.4", "@peculiar/asn1-schema": "^2.9.4", "@peculiar/asn1-x509": "^2.9.4", "@peculiar/asn1-x509-attr": "^2.9.4", "asn1js": "^3.0.10", "tslib": "^2.8.1" } }, "sha512-kaL4cNxBpdQE2dKlyZBqz4ygCrwffO+8wfoxTEqM1Z8RadvCeELBRzcv0dzM8aY9azHMwODO5nxU65zXmhToOQ=="],
|
||||||
|
|
||||||
"@peculiar/asn1-rsa": ["@peculiar/asn1-rsa@2.8.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.8.0", "@peculiar/asn1-x509": "^2.8.0", "asn1js": "^3.0.10", "tslib": "^2.8.1" } }, "sha512-zHEUlCqB2mk7x2lxDwHHJy7hWZOPdGHVlsmITWKB5/PbQo61atbu9PJ/0r9dQNMwFzbKPXZ8uK8/91eUhRznSg=="],
|
"@peculiar/asn1-rsa": ["@peculiar/asn1-rsa@2.9.4", "", { "dependencies": { "@peculiar/asn1-schema": "^2.9.4", "@peculiar/asn1-x509": "^2.9.4", "asn1js": "^3.0.10", "tslib": "^2.8.1" } }, "sha512-pZ96eD1PptovcWQ/GSmuNFXd/7EQJNlKfDaNCyE2rx3W0v6QFelkzquVqRSRyyDXXCYD69ZXJDzZ8GhIiQzKoA=="],
|
||||||
|
|
||||||
"@peculiar/asn1-schema": ["@peculiar/asn1-schema@2.8.0", "", { "dependencies": { "@peculiar/utils": "^2.0.2", "asn1js": "^3.0.10", "tslib": "^2.8.1" } }, "sha512-7YT0U/ze0tF2QOBbE15gKZwy5tvgGyLRiRHLzhlbOpf7BT032oBSd0haZqXn5W6l26WLlu3dyxzjM+2638/z2Q=="],
|
"@peculiar/asn1-schema": ["@peculiar/asn1-schema@2.9.4", "", { "dependencies": { "@peculiar/utils": "^2.0.2", "asn1js": "^3.0.10", "tslib": "^2.8.1" } }, "sha512-GjzePcT9Iw8NzeOPf73iNS9xM+TBhd/FilAfP+RQGkTMQJTVWtytN3JHJACCjf/ABNau5S7mS3g+DcuxmRgYEg=="],
|
||||||
|
|
||||||
"@peculiar/asn1-x509": ["@peculiar/asn1-x509@2.8.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.8.0", "@peculiar/utils": "^2.0.2", "asn1js": "^3.0.10", "tslib": "^2.8.1" } }, "sha512-N0CMuhWUzsWEVq6F1q9X6+VKUnWzSW+cSVg+aPaGGwDdbFoFWTYgin5MHwXgpWd6y9COMBxnfy/Qc+Xc7F0Zwg=="],
|
"@peculiar/asn1-x509": ["@peculiar/asn1-x509@2.9.4", "", { "dependencies": { "@peculiar/asn1-schema": "^2.9.4", "@peculiar/utils": "^2.0.2", "asn1js": "^3.0.10", "tslib": "^2.8.1" } }, "sha512-CxhBo/RdEbMMob7T31ZdQjGuoyRFLVwrDzTn25bihzBasRg9kRm/0IxIPvhgQtcK/9dNcO1XQL2fuPugwELL0Q=="],
|
||||||
|
|
||||||
"@peculiar/asn1-x509-attr": ["@peculiar/asn1-x509-attr@2.8.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.8.0", "@peculiar/asn1-x509": "^2.8.0", "asn1js": "^3.0.10", "tslib": "^2.8.1" } }, "sha512-tHjkfS/qhMnmrlB2J9NhflQlQ7In3khO3CfmVrriOlpTeErY9ZIKOso1hQ5JQiyrJ7ShvqVPk7E5fQmbclkSKA=="],
|
"@peculiar/asn1-x509-attr": ["@peculiar/asn1-x509-attr@2.9.4", "", { "dependencies": { "@peculiar/asn1-schema": "^2.9.4", "@peculiar/asn1-x509": "^2.9.4", "asn1js": "^3.0.10", "tslib": "^2.8.1" } }, "sha512-ehQXbpQaQYycgu8OrvigwSPTFfVRcu0ECNYCWw+yzBp02Lw5paRqzzhUpfOgO2K38+WfFZuEz/0RPtam5g0OMg=="],
|
||||||
|
|
||||||
"@peculiar/utils": ["@peculiar/utils@2.0.3", "", { "dependencies": { "tslib": "^2.8.1" } }, "sha512-+oL3HPFRIZ1St2K50lWCXiioIgSoxzz7R1J3uF6neO2yl1sgmpgY6XXJH4BdpoDkMWznQTeYF6oWNDZLCdQ4eQ=="],
|
"@peculiar/utils": ["@peculiar/utils@2.0.3", "", { "dependencies": { "tslib": "^2.8.1" } }, "sha512-+oL3HPFRIZ1St2K50lWCXiioIgSoxzz7R1J3uF6neO2yl1sgmpgY6XXJH4BdpoDkMWznQTeYF6oWNDZLCdQ4eQ=="],
|
||||||
|
|
||||||
"@peculiar/x509": ["@peculiar/x509@1.14.3", "", { "dependencies": { "@peculiar/asn1-cms": "^2.6.0", "@peculiar/asn1-csr": "^2.6.0", "@peculiar/asn1-ecc": "^2.6.0", "@peculiar/asn1-pkcs9": "^2.6.0", "@peculiar/asn1-rsa": "^2.6.0", "@peculiar/asn1-schema": "^2.6.0", "@peculiar/asn1-x509": "^2.6.0", "pvtsutils": "^1.3.6", "reflect-metadata": "^0.2.2", "tslib": "^2.8.1", "tsyringe": "^4.10.0" } }, "sha512-C2Xj8FZ0uHWeCXXqX5B4/gVFQmtSkiuOolzAgutjTfseNOHT3pUjljDZsTSxXFGgio54bCzVFqmEOUrIVk8RDA=="],
|
"@peculiar/x509": ["@peculiar/x509@1.14.3", "", { "dependencies": { "@peculiar/asn1-cms": "^2.6.0", "@peculiar/asn1-csr": "^2.6.0", "@peculiar/asn1-ecc": "^2.6.0", "@peculiar/asn1-pkcs9": "^2.6.0", "@peculiar/asn1-rsa": "^2.6.0", "@peculiar/asn1-schema": "^2.6.0", "@peculiar/asn1-x509": "^2.6.0", "pvtsutils": "^1.3.6", "reflect-metadata": "^0.2.2", "tslib": "^2.8.1", "tsyringe": "^4.10.0" } }, "sha512-C2Xj8FZ0uHWeCXXqX5B4/gVFQmtSkiuOolzAgutjTfseNOHT3pUjljDZsTSxXFGgio54bCzVFqmEOUrIVk8RDA=="],
|
||||||
|
|
||||||
"@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.62.2", "", { "os": "android", "cpu": "arm" }, "sha512-6o7ZLZK+BeenkZCFNDXqpbjw9bD6nuWonvS/lwQJp7NoVVxm6p3qE7qQ5jGuBjiFsgvqjD8mZAU5oWxTmbOeOg=="],
|
"@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.62.5", "", { "os": "android", "cpu": "arm" }, "sha512-jfkGfTwhQpsiSckPF8r9bU3pn3vyd72NlWaO+TgEO6WPSDnUhXzrNYCHBMOYj0ACaUgjm6eERLF+XV9a6RstoA=="],
|
||||||
|
|
||||||
"@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.62.2", "", { "os": "android", "cpu": "arm64" }, "sha512-BaH7BllCACHoH1LguOU56UItGfUWjujlO65kS9LAodViaN4bwIKd7oeW/ZHJ/4ljr/7MIiENnNy3HJ0zXv8Zkw=="],
|
"@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.62.5", "", { "os": "android", "cpu": "arm64" }, "sha512-oGVqyQlxnrz9/ty89oHpU857VUHEl5/Xu4R2lS+aivCTrNnSsbiENzTnNaBsjxH0CNWGPhzHArOLFwo+oKXveA=="],
|
||||||
|
|
||||||
"@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.62.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-v39RCCvj4He82I9sFmk+M1VZ0PLM9sfsLVikjfx2hYBNALhrrOR2D3JjQA6AhlaSOgcR+RzrKY7e1+bT6SUO/A=="],
|
"@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.62.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-bW7B8xMEq8n99Q3ieEcPRGuphurdZAaFzQc9Efyyw3FL6DZO6pMy9xhdN+kBoD7Sy05xNXSr4OyPPnpkYriS/A=="],
|
||||||
|
|
||||||
"@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.62.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-yl0y2vq3S3lHeuXhEdss6TWfKW8vkujImO12tn4ZkG/4oghr09LvdYm2RElVjokTQiUvDUGXLGsYeLqUMCKpGA=="],
|
"@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.62.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-YSwBS86QeHOGlrxJ1PSOIZSkzRL/JmKeunhc+lV6M1a6En8QuVCD/T/qIA0J4Gd2Y86RIOBYrLcOUtqGh9+/1w=="],
|
||||||
|
|
||||||
"@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.62.2", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-tT4pvt4qXD+vEoezupCWi+a1F0vvDiksiHc+PxRlYTOH1I6/X4id9jPxTP+Fg+545euaFT1jJVs4CEdHZAU1vw=="],
|
"@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.62.5", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-2fST8lILgl7cKbme/1KDdPCmbXbG+gqoV3bHp19L0ypX/3akYMBVdOunPleRCwonoLnXOZ/0F+Mt/v8POFmfcQ=="],
|
||||||
|
|
||||||
"@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.62.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-6nU5F2wCW+qvCBhTn1pdIU3bzsIoF7EUwsCDRxilWGprQR6yd508YnH9+OKFCwpfS8pjZqDUmnCAr7exax0XCg=="],
|
"@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.62.5", "", { "os": "freebsd", "cpu": "x64" }, "sha512-cpIxQCP9J+EVad0a6LO1kY3ZGODlk80VlI+2I96B8xMcdHZ4pLVhfQ49JFpYqjPF91FFkQWftf57YlDcTiw9yQ=="],
|
||||||
|
|
||||||
"@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.62.2", "", { "os": "linux", "cpu": "arm" }, "sha512-n1GJHPOvpIfhi3TmrCeh6S6URt9BFCt0KQE3qvexyGCTAKpR4Lg+eWvNZEqu7epxwus/8ElT3hacYEucm49SZg=="],
|
"@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.62.5", "", { "os": "linux", "cpu": "arm" }, "sha512-r9fGh3eFs3e/udWh5ZjXQtxiYK/xoFxQaYR/cELxac/Udkl5Th+IsFm0CX3Kl9hmUH/we7EoMpjJgeQNnE0+IA=="],
|
||||||
|
|
||||||
"@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.62.2", "", { "os": "linux", "cpu": "arm" }, "sha512-JqgflS8wEB+UXV/vS1RpRbifGBeN4D5lz8D8oOFbFZw4vedvdOgCFAjfBmIMdW3yL10XpQQ0Ambepw6MXrhOnA=="],
|
"@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.62.5", "", { "os": "linux", "cpu": "arm" }, "sha512-xdvFdp7OM6KLJviJT2g/YuRSUjnZgGHk4RNgwIbN7X6cPugOucV60DdHXWzsBVCUdrGb6qSXnJQrrAKMmQuj3Q=="],
|
||||||
|
|
||||||
"@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.62.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-wnFJkogWvN4jm/hQRF2UBaeUmk20j5+DmHvoyWii2b8HJDyvz1MF2OU/6ynXt2KR63rbZLWkFpoytpdc/yBuSA=="],
|
"@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.62.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-rRqILAndyzHzP7T9NFQrq+4HFWNhqkqkKur7eiBpfLmz01PO0JKx5Vchu3YllE4YXI/Ftgq/szrDWg5GJ0mI8g=="],
|
||||||
|
|
||||||
"@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.62.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-HVu2bp0zhvJ8xHEV9+UUs7S90VadmBSY3LcIMvozbPo4AuMGDWlz3ymHLHZPX4hR67TKTt8Qp5PJ5RBg/i+RMQ=="],
|
"@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.62.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-Gf4X3qVMucayUvux6aXXPgXovocSFUC0rrffDuPI/S2nHhNMhjcZxsrAFYCOF350PRreW1XwzFj3CT/3bKsWCw=="],
|
||||||
|
|
||||||
"@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.62.2", "", { "os": "linux", "cpu": "none" }, "sha512-mQqqAV8QaoSgr9I2fKDLY2BAVvmKjWoGiu/cSYQonsLvtqwEn1E4QYfnCOcp5zoEqNhsDYin1s6jx/VJmrxlZg=="],
|
"@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.62.5", "", { "os": "linux", "cpu": "none" }, "sha512-+s5qA0TNM0qm8PK/a5gt/1Hpx+NV08uSuCncvhziIlQzT6AEV2fnUQo7eBtFTFO0nA9scauvoR2HusfXmQnO4w=="],
|
||||||
|
|
||||||
"@rollup/rollup-linux-loong64-musl": ["@rollup/rollup-linux-loong64-musl@4.62.2", "", { "os": "linux", "cpu": "none" }, "sha512-IxKLoxCQ2IWi6bT2akyDUBGsOImDKB+sPp4EsTmwFQ/fMwpCKm8uLSSgP/Kx/QYUgKis6SEZ5/Nlhup0DIA0PQ=="],
|
"@rollup/rollup-linux-loong64-musl": ["@rollup/rollup-linux-loong64-musl@4.62.5", "", { "os": "linux", "cpu": "none" }, "sha512-ybb6QvWwWJCbBWqERpc8K3pYVGIrXlG8MEQ8IIuJY6Y9KdHQxoFoNyfkAOtKn1VHu3KuLidXvwrvGR1mEjeWCw=="],
|
||||||
|
|
||||||
"@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.62.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-Mk5ha2RQSgyFfmYYLkBpPnUk8D8FriBxesO1u9O75X0mHgXL1UQcH5Itl2lurWL2tj0RxV9b9tJgipac0hRY9A=="],
|
"@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.62.5", "", { "os": "linux", "cpu": "ppc64" }, "sha512-nZb1DtnOyhCmYvsC8A2CwOkopVg+IS1+fPUa7rMOAXtNw5+lLCLLPqd6XAiNrGtoQKsbvIBOwsHnBH/3wnb4HQ=="],
|
||||||
|
|
||||||
"@rollup/rollup-linux-ppc64-musl": ["@rollup/rollup-linux-ppc64-musl@4.62.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-CjvEnqJL/0/TQ3TXX3OPIJ/kmBellrWd4heXUmHeJlTnmwjKpSJzoehLaL6Xk0ZnMHBu9dZuFADNOrtjF4v+2w=="],
|
"@rollup/rollup-linux-ppc64-musl": ["@rollup/rollup-linux-ppc64-musl@4.62.5", "", { "os": "linux", "cpu": "ppc64" }, "sha512-yMbj63Sp89ryrXLWyz+sy+fYD2HpOnMCLGbe4Oa1smclFSUukdtD/BgdiHaAetJNb74URD8U4hM+qG5KVzMEkg=="],
|
||||||
|
|
||||||
"@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.62.2", "", { "os": "linux", "cpu": "none" }, "sha512-1SiZbzwdkaDURsew/tSOrooKiYy7EQGT6m8ufavAi9NEyQb/6VuIxFXAL1fqa4iZe3g4NbNk4P7J32z2tw5Mgg=="],
|
"@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.62.5", "", { "os": "linux", "cpu": "none" }, "sha512-mhoan3OJw2kYV/e1jtIdmvUZgyBFeA6zGWsOswmR0Tg19TQbowZuR+JMLID6spbbBN7Zee2ejrgmy3+FxGrIdA=="],
|
||||||
|
|
||||||
"@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.62.2", "", { "os": "linux", "cpu": "none" }, "sha512-nQts12zJ3NQRoE6uYljOH89v7szzLDvG2JD/vsX+vGXU8w/At1GowTZ5/7qeFQ8m7L55rpR8Okugnuo5bgjy2Q=="],
|
"@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.62.5", "", { "os": "linux", "cpu": "none" }, "sha512-5ZTLmjWbb1VZdjuyhe83K/8QO0/h11midQCBP+X5OYn32ra7eOBoM0ZqtaY4nkgNsYgmdVhMYPoyVPTjUpHf3w=="],
|
||||||
|
|
||||||
"@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.62.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-E9/ll019jhPIJgpzfZoIkBGhcz+kKNgVWYRY0zr9srBdPPFVpvOKW8VaJKUbeK+eZXyQF9ltME+Kk6affeaPgg=="],
|
"@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.62.5", "", { "os": "linux", "cpu": "s390x" }, "sha512-m53kG+br6PGxOTmgBEM2DHSDs9RVjsyEbUwjJPJGTFm1grWOG8EKJggDCTb60unD4Tjby8fi7/m9XfkEWasVWg=="],
|
||||||
|
|
||||||
"@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.62.2", "", { "os": "linux", "cpu": "x64" }, "sha512-5BqxR/pshjey51iliyzTD5Xi3EN0aLmQ2lZ3lvefVV9c82BvrLo2/6OT55iifpWBufs6kdwWbuOKS841DrmK9A=="],
|
"@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.62.5", "", { "os": "linux", "cpu": "x64" }, "sha512-6RHPJR1g/uvdYU8uXBnfq3nlqyZCP82Fr6NHgfGoaIeSh0YEqnX/x6uA9MmJJbnSH7swqX4F+CkGdUF+6doiQA=="],
|
||||||
|
|
||||||
"@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.62.2", "", { "os": "linux", "cpu": "x64" }, "sha512-uNN83XxQrRAh/w0/pmAfibcwyb6YWt4gP+dpnQKPVJshAloQ785ii8CT8ZCIxkGg9opVsvAlGhFitSm6D1Jjpg=="],
|
"@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.62.5", "", { "os": "linux", "cpu": "x64" }, "sha512-xs+OXQtEXgpXT0DmA5+U3qnRZHdCST/5HRQxS8wSPZTUZN/EMWeHuSIod32LQklTBZBV9DyfncKBQ8n5V3eFdw=="],
|
||||||
|
|
||||||
"@rollup/rollup-openbsd-x64": ["@rollup/rollup-openbsd-x64@4.62.2", "", { "os": "openbsd", "cpu": "x64" }, "sha512-srjEIxSH3LRnJN6THczDHWQplqEMFiAJrTab0msUryh9kwNpkICf3Ea6q6MN/2cZwRFUNx5w+h6Hpi4QuHS6Zg=="],
|
"@rollup/rollup-openbsd-x64": ["@rollup/rollup-openbsd-x64@4.62.5", "", { "os": "openbsd", "cpu": "x64" }, "sha512-e7hD+sl3s+mcLQDZ8pbudBVsdG6r5yN4w3LqG2TJ8sQHDpblWj5lrJs/3m01Cvlxbt4x13zu5thLjgypgtkYzw=="],
|
||||||
|
|
||||||
"@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.62.2", "", { "os": "none", "cpu": "arm64" }, "sha512-8hOJnxgbyObnCm5AlRA3A931xX19xq80RjVTKgJOvEKWqJruP/Uf12IbAOaDjjEXYRewwHLfmF0YRIdK3OwKWA=="],
|
"@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.62.5", "", { "os": "none", "cpu": "arm64" }, "sha512-GiyJaCf+WpMub/17aPcKk27QMl5W6f+KhdPTjlFOn5akH5Wa/DCM9Stdx5cDfmasyKB08MqpVQ1uJE2RkkpbXg=="],
|
||||||
|
|
||||||
"@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.62.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-mmF4AY1i0hG/bLWUctUq59gtmgaSIRa3cu/A3JFRp/sCNEme2bgDEiDS22P9FbnJB8NJNF4jPJiSP5RHQpUTDg=="],
|
"@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.62.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-+OQ8U2DdoEfXl8T4Fb18AjmEwbXMerKDKCL8yCPAYhKCEEKoul7rkbeGCBFCbAlaGaa7pmtRTpkAJM2LE/i5FA=="],
|
||||||
|
|
||||||
"@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.62.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-DZgkknc6jhHrk46V25vbAM0zZkyP0nSDkJB8/dRkLTxv470dOmWDqGoEJl/9A0dFfS7yE3REOwNDxpHwSLSt0Q=="],
|
"@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.62.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-KanvAZrPKbDBFwrgiU9yEVpQoox9QPV1WZOXX7HudJQY+eSlu82CtWxDU8WtuRRvtN5EGkLczkd6Y6DTcvm9wA=="],
|
||||||
|
|
||||||
"@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.62.2", "", { "os": "win32", "cpu": "x64" }, "sha512-T6xr6ucWSFto+VGajA8YH26LdpHRuP4YLHEKAtCWvJDOlnmWcDZVCI2Jmjr+IFHDlt2zRaTAKE4tfjTaWLgJBg=="],
|
"@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.62.5", "", { "os": "win32", "cpu": "x64" }, "sha512-1aC3UEWTtRl3RK3VpDJ/Tqk1XI4SLTmXIthAq6wRWo8XiSXJNd+VprJM4/1P4+i6HIaFEFlVi9sTTziniD2tOQ=="],
|
||||||
|
|
||||||
"@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.62.2", "", { "os": "win32", "cpu": "x64" }, "sha512-BfzEnDJOt9T8M989/lA37EcJgat01wLRnoi5dQf3QzOH7jzpqTAzdDbVfRljVr5r+jzKqpbHeyOfAaXxAd0PAA=="],
|
"@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.62.5", "", { "os": "win32", "cpu": "x64" }, "sha512-/gDJaRs4gl0NPIwqCz+6PkpmhhjRAD2j6P4rSNHBzUkO3naEx2mIU0pRle1vUNRQ7mE/+8OOeXLTv/J56FKiQg=="],
|
||||||
|
|
||||||
"@tailwindcss/cli": ["@tailwindcss/cli@4.3.3", "", { "dependencies": { "@parcel/watcher": "2.5.1", "@tailwindcss/node": "4.3.3", "@tailwindcss/oxide": "4.3.3", "enhanced-resolve": "^5.24.1", "mri": "^1.2.0", "picocolors": "^1.1.1", "tailwindcss": "4.3.3" }, "bin": { "tailwindcss": "./dist/index.mjs" } }, "sha512-ZvS/n1ZHOBKcVlhkt8l5NNr1EDXk1NboYO5CYDOs6NUmvT9z6bzkwsosaJftY57T/3gWNzWMJzIXLodZC8ssdw=="],
|
"@tailwindcss/cli": ["@tailwindcss/cli@4.3.3", "", { "dependencies": { "@parcel/watcher": "2.5.1", "@tailwindcss/node": "4.3.3", "@tailwindcss/oxide": "4.3.3", "enhanced-resolve": "^5.24.1", "mri": "^1.2.0", "picocolors": "^1.1.1", "tailwindcss": "4.3.3" }, "bin": { "tailwindcss": "./dist/index.mjs" } }, "sha512-ZvS/n1ZHOBKcVlhkt8l5NNr1EDXk1NboYO5CYDOs6NUmvT9z6bzkwsosaJftY57T/3gWNzWMJzIXLodZC8ssdw=="],
|
||||||
|
|
||||||
@@ -975,7 +978,7 @@
|
|||||||
|
|
||||||
"@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.3.3", "", { "os": "win32", "cpu": "x64" }, "sha512-yJ0pwIVc/nYeGoV02WtsN8KYyLQv7kyI2wDnkezyJlGGjkd4QLwDGAwl47YpPJeuI0M0ObaXGSPjvWDPeTPggw=="],
|
"@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.3.3", "", { "os": "win32", "cpu": "x64" }, "sha512-yJ0pwIVc/nYeGoV02WtsN8KYyLQv7kyI2wDnkezyJlGGjkd4QLwDGAwl47YpPJeuI0M0ObaXGSPjvWDPeTPggw=="],
|
||||||
|
|
||||||
"@types/bun": ["@types/bun@1.3.14", "", { "dependencies": { "bun-types": "1.3.14" } }, "sha512-h1hFqFVcvAvD9j9K7ZW7vd82aSA+rTdznZa+5bwvCwqSB1jmmfLcbIWhOLx1/+boy/xmjgCs/OMUL8hRJSmnPw=="],
|
"@types/bun": ["@types/bun@1.4.0", "", { "dependencies": { "bun-types": "1.4.0" } }, "sha512-K+lZULY23vRgK/CfTjFIV+tyifaNdSMlPh9j+6mQ/cLfpOznLyAuzgV/JQysyECpkBQLVMSyvjlr2fBUSA9wFQ=="],
|
||||||
|
|
||||||
"@types/esrecurse": ["@types/esrecurse@4.3.1", "", {}, "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw=="],
|
"@types/esrecurse": ["@types/esrecurse@4.3.1", "", {}, "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw=="],
|
||||||
|
|
||||||
@@ -983,11 +986,11 @@
|
|||||||
|
|
||||||
"@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="],
|
"@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="],
|
||||||
|
|
||||||
"@types/node": ["@types/node@26.0.1", "", { "dependencies": { "undici-types": "~8.3.0" } }, "sha512-fc3KiUoBt6kie0N9bIW3E47vZsuaMf0PM2AaUpLCLT0s/LvX1nxAim6Fc049cNxODPpGm6qRAuUOB86SkRuPQw=="],
|
"@types/node": ["@types/node@26.2.0", "", { "dependencies": { "undici-types": "~8.3.0" } }, "sha512-5IviulTZeRNp2vAJ514cc/HUlY5nZ9fCbq9DMyC52BrhFZACo3nI0R7qBxhQmo/d27NFe96ur/b7Wwxklda+kg=="],
|
||||||
|
|
||||||
"@types/react": ["@types/react@19.2.18", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-AnzbBERsrLKtk2XSfTbYRLjQPdy116Sty4q+T+Bp3IC4l6jNBvreVPAHmpq9qhXQM7CXZPjLVmGMw9sy+hxQ3w=="],
|
"@types/react": ["@types/react@19.2.18", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-AnzbBERsrLKtk2XSfTbYRLjQPdy116Sty4q+T+Bp3IC4l6jNBvreVPAHmpq9qhXQM7CXZPjLVmGMw9sy+hxQ3w=="],
|
||||||
|
|
||||||
"@types/react-dom": ["@types/react-dom@19.2.4", "", { "peerDependencies": { "@types/react": "^19.2.0" } }, "sha512-Bsc+QHgp+P/F02XDzNCY9jnZNCUuLki36KT7VKrTXXLdHf+vHMNZnW1rVu5DNW/rCK+fya3DATySbLM4yhtKUw=="],
|
"@types/react-dom": ["@types/react-dom@19.2.5", "", { "peerDependencies": { "@types/react": "^19.2.0" } }, "sha512-fMPwH9v7r/pp43yUd2/Mbiex5KouJwwR3dzHkhLREUC6764VyDsqxhAxv6OFEYR1RhjOyD1naqba8ECDBe7ZQg=="],
|
||||||
|
|
||||||
"@types/whatwg-mimetype": ["@types/whatwg-mimetype@3.0.2", "", {}, "sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA=="],
|
"@types/whatwg-mimetype": ["@types/whatwg-mimetype@3.0.2", "", {}, "sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA=="],
|
||||||
|
|
||||||
@@ -1119,7 +1122,7 @@
|
|||||||
|
|
||||||
"@wrnexus/validation": ["@wrnexus/validation@workspace:packages/validation"],
|
"@wrnexus/validation": ["@wrnexus/validation@workspace:packages/validation"],
|
||||||
|
|
||||||
"acorn": ["acorn@8.17.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg=="],
|
"acorn": ["acorn@8.18.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ=="],
|
||||||
|
|
||||||
"acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="],
|
"acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="],
|
||||||
|
|
||||||
@@ -1145,7 +1148,7 @@
|
|||||||
|
|
||||||
"buffer-image-size": ["buffer-image-size@0.6.4", "", { "dependencies": { "@types/node": "*" } }, "sha512-nEh+kZOPY1w+gcCMobZ6ETUp9WfibndnosbpwB1iJk/8Gt5ZF2bhS6+B6bPYz424KtwsR6Rflc3tCz1/ghX2dQ=="],
|
"buffer-image-size": ["buffer-image-size@0.6.4", "", { "dependencies": { "@types/node": "*" } }, "sha512-nEh+kZOPY1w+gcCMobZ6ETUp9WfibndnosbpwB1iJk/8Gt5ZF2bhS6+B6bPYz424KtwsR6Rflc3tCz1/ghX2dQ=="],
|
||||||
|
|
||||||
"bun-types": ["bun-types@1.3.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-4N0ig0fEomHt5R0KCFWjovxow98rIoRwKolrYdCcknNwMekCXRnWEUvgu5soYV8QXtVsrUD8B95MBOZGPvr6KQ=="],
|
"bun-types": ["bun-types@1.4.0", "", { "dependencies": { "@types/node": "*" } }, "sha512-iIKw23BspnQQYd3prITOBxeUsxBHnwzX6YJfGMuNOZzeNcMmVqzIIVGRm1l69ogaPQmb4wB6BN8mA5bE9YuC5Q=="],
|
||||||
|
|
||||||
"bundle-require": ["bundle-require@5.1.0", "", { "dependencies": { "load-tsconfig": "^0.2.3" }, "peerDependencies": { "esbuild": ">=0.18" } }, "sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA=="],
|
"bundle-require": ["bundle-require@5.1.0", "", { "dependencies": { "load-tsconfig": "^0.2.3" }, "peerDependencies": { "esbuild": ">=0.18" } }, "sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA=="],
|
||||||
|
|
||||||
@@ -1177,7 +1180,7 @@
|
|||||||
|
|
||||||
"csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="],
|
"csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="],
|
||||||
|
|
||||||
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
|
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" }, "peerDependencies": { "supports-color": "*" }, "optionalPeers": ["supports-color"] }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
|
||||||
|
|
||||||
"deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="],
|
"deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="],
|
||||||
|
|
||||||
@@ -1199,7 +1202,7 @@
|
|||||||
|
|
||||||
"escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="],
|
"escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="],
|
||||||
|
|
||||||
"eslint": ["eslint@10.8.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.2", "@eslint/config-array": "^0.23.5", "@eslint/config-helpers": "^0.7.0", "@eslint/core": "^1.2.1", "@eslint/plugin-kit": "^0.7.2", "@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", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^9.1.2", "eslint-visitor-keys": "^5.0.1", "espree": "^11.2.0", "esquery": "^1.7.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", "minimatch": "^10.2.5", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-wqA7W2jbsC/BnV9Iv1UZpKVFkO1AdNoSmYW8NWG4HNOBbkAMvIqDZ27pI2f07dqn583NcIC44ckjAcOXDL1QbQ=="],
|
"eslint": ["eslint@10.9.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.2", "@eslint/config-array": "^0.23.5", "@eslint/config-helpers": "^0.7.0", "@eslint/core": "^1.2.1", "@eslint/plugin-kit": "^0.7.2", "@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", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^9.1.2", "eslint-visitor-keys": "^5.0.1", "espree": "^11.2.0", "esquery": "^1.7.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", "minimatch": "^10.2.5", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-5KeEOJZBfEVA47boFiBsf+6MmmJpffM7qEBg4pLla2e4nlKgdKlqCW0oSLOGsT8Wl5uCGJptLV1bkaiShj90Gw=="],
|
||||||
|
|
||||||
"eslint-scope": ["eslint-scope@9.1.2", "", { "dependencies": { "@types/esrecurse": "^4.3.1", "@types/estree": "^1.0.8", "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ=="],
|
"eslint-scope": ["eslint-scope@9.1.2", "", { "dependencies": { "@types/esrecurse": "^4.3.1", "@types/estree": "^1.0.8", "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ=="],
|
||||||
|
|
||||||
@@ -1235,7 +1238,7 @@
|
|||||||
|
|
||||||
"flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="],
|
"flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="],
|
||||||
|
|
||||||
"flatted": ["flatted@3.4.2", "", {}, "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA=="],
|
"flatted": ["flatted@3.4.4", "", {}, "sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q=="],
|
||||||
|
|
||||||
"fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
|
"fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
|
||||||
|
|
||||||
@@ -1243,7 +1246,7 @@
|
|||||||
|
|
||||||
"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.2", "", { "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-7MB+bJLkxu3SowAfBJbjW+c55kNz5tkR45gu2qzrxznezhLeN5YIlJbwUgSzlGc+qWoZ8Ykg71H5ezz69xixrw=="],
|
"happy-dom": ["happy-dom@20.11.6", "", { "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-Hldbg8AdAa5a5oDcZpjqnGitp7JB0hqWmfv/8qr+kft4vzSD8BHsbdRfzYvL/0QcbKcURC/yyoygbeDQarPvYg=="],
|
||||||
|
|
||||||
"i18n-showcase": ["i18n-showcase@workspace:examples/i18n-showcase"],
|
"i18n-showcase": ["i18n-showcase@workspace:examples/i18n-showcase"],
|
||||||
|
|
||||||
@@ -1315,7 +1318,7 @@
|
|||||||
|
|
||||||
"micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="],
|
"micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="],
|
||||||
|
|
||||||
"minimatch": ["minimatch@10.2.5", "", { "dependencies": { "brace-expansion": "^5.0.5" } }, "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg=="],
|
"minimatch": ["minimatch@10.2.6", "", { "dependencies": { "brace-expansion": "^5.0.8" } }, "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A=="],
|
||||||
|
|
||||||
"mlly": ["mlly@1.8.2", "", { "dependencies": { "acorn": "^8.16.0", "pathe": "^2.0.3", "pkg-types": "^1.3.1", "ufo": "^1.6.3" } }, "sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA=="],
|
"mlly": ["mlly@1.8.2", "", { "dependencies": { "acorn": "^8.16.0", "pathe": "^2.0.3", "pkg-types": "^1.3.1", "ufo": "^1.6.3" } }, "sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA=="],
|
||||||
|
|
||||||
@@ -1351,7 +1354,7 @@
|
|||||||
|
|
||||||
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
|
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
|
||||||
|
|
||||||
"picomatch": ["picomatch@4.0.4", "", {}, "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A=="],
|
"picomatch": ["picomatch@4.0.5", "", {}, "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A=="],
|
||||||
|
|
||||||
"pirates": ["pirates@4.0.7", "", {}, "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA=="],
|
"pirates": ["pirates@4.0.7", "", {}, "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA=="],
|
||||||
|
|
||||||
@@ -1369,7 +1372,7 @@
|
|||||||
|
|
||||||
"pvtsutils": ["pvtsutils@1.3.6", "", { "dependencies": { "tslib": "^2.8.1" } }, "sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg=="],
|
"pvtsutils": ["pvtsutils@1.3.6", "", { "dependencies": { "tslib": "^2.8.1" } }, "sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg=="],
|
||||||
|
|
||||||
"pvutils": ["pvutils@1.1.5", "", {}, "sha512-KTqnxsgGiQ6ZAzZCVlJH5eOjSnvlyEgx1m8bkRJfOhmGRqfo5KLvmAlACQkrjEtOQ4B7wF9TdSLIs9O90MX9xA=="],
|
"pvutils": ["pvutils@1.2.0", "", {}, "sha512-BbubeCEyTuQjVMakvJQ/Sxbc93F2pwmbsxONT/ZRrwU7Ua38d8unYTwXpTVLAKJ4BDuH9IGztCjQcd/N/39Dvg=="],
|
||||||
|
|
||||||
"react": ["react@19.2.8", "", {}, "sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw=="],
|
"react": ["react@19.2.8", "", {}, "sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw=="],
|
||||||
|
|
||||||
@@ -1381,9 +1384,9 @@
|
|||||||
|
|
||||||
"resolve-from": ["resolve-from@5.0.0", "", {}, "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw=="],
|
"resolve-from": ["resolve-from@5.0.0", "", {}, "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw=="],
|
||||||
|
|
||||||
"rollup": ["rollup@4.62.2", "", { "dependencies": { "@types/estree": "1.0.9" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.62.2", "@rollup/rollup-android-arm64": "4.62.2", "@rollup/rollup-darwin-arm64": "4.62.2", "@rollup/rollup-darwin-x64": "4.62.2", "@rollup/rollup-freebsd-arm64": "4.62.2", "@rollup/rollup-freebsd-x64": "4.62.2", "@rollup/rollup-linux-arm-gnueabihf": "4.62.2", "@rollup/rollup-linux-arm-musleabihf": "4.62.2", "@rollup/rollup-linux-arm64-gnu": "4.62.2", "@rollup/rollup-linux-arm64-musl": "4.62.2", "@rollup/rollup-linux-loong64-gnu": "4.62.2", "@rollup/rollup-linux-loong64-musl": "4.62.2", "@rollup/rollup-linux-ppc64-gnu": "4.62.2", "@rollup/rollup-linux-ppc64-musl": "4.62.2", "@rollup/rollup-linux-riscv64-gnu": "4.62.2", "@rollup/rollup-linux-riscv64-musl": "4.62.2", "@rollup/rollup-linux-s390x-gnu": "4.62.2", "@rollup/rollup-linux-x64-gnu": "4.62.2", "@rollup/rollup-linux-x64-musl": "4.62.2", "@rollup/rollup-openbsd-x64": "4.62.2", "@rollup/rollup-openharmony-arm64": "4.62.2", "@rollup/rollup-win32-arm64-msvc": "4.62.2", "@rollup/rollup-win32-ia32-msvc": "4.62.2", "@rollup/rollup-win32-x64-gnu": "4.62.2", "@rollup/rollup-win32-x64-msvc": "4.62.2", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-RFnrW4lhXA3s3eqHDZvN654g8OTjzRfqpIRJYczCGB6HzphckVAi/Qh4tbPUbRuDi7s1Llv8g/NspLkttY3gTA=="],
|
"rollup": ["rollup@4.62.5", "", { "dependencies": { "@types/estree": "1.0.9" }, "optionalDependencies": { "@napi-rs/lzma-linux-x64-gnu": "1.5.1", "@rollup/rollup-android-arm-eabi": "4.62.5", "@rollup/rollup-android-arm64": "4.62.5", "@rollup/rollup-darwin-arm64": "4.62.5", "@rollup/rollup-darwin-x64": "4.62.5", "@rollup/rollup-freebsd-arm64": "4.62.5", "@rollup/rollup-freebsd-x64": "4.62.5", "@rollup/rollup-linux-arm-gnueabihf": "4.62.5", "@rollup/rollup-linux-arm-musleabihf": "4.62.5", "@rollup/rollup-linux-arm64-gnu": "4.62.5", "@rollup/rollup-linux-arm64-musl": "4.62.5", "@rollup/rollup-linux-loong64-gnu": "4.62.5", "@rollup/rollup-linux-loong64-musl": "4.62.5", "@rollup/rollup-linux-ppc64-gnu": "4.62.5", "@rollup/rollup-linux-ppc64-musl": "4.62.5", "@rollup/rollup-linux-riscv64-gnu": "4.62.5", "@rollup/rollup-linux-riscv64-musl": "4.62.5", "@rollup/rollup-linux-s390x-gnu": "4.62.5", "@rollup/rollup-linux-x64-gnu": "4.62.5", "@rollup/rollup-linux-x64-musl": "4.62.5", "@rollup/rollup-openbsd-x64": "4.62.5", "@rollup/rollup-openharmony-arm64": "4.62.5", "@rollup/rollup-win32-arm64-msvc": "4.62.5", "@rollup/rollup-win32-ia32-msvc": "4.62.5", "@rollup/rollup-win32-x64-gnu": "4.62.5", "@rollup/rollup-win32-x64-msvc": "4.62.5", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-/tqMfgP7GPA3PHhCmuiS4vIjrSVhHLgY++i+dhbG462euyAj7FpM4D9uq1X3BgjlqRdpcOrYhcQtfiQLNc8tqw=="],
|
||||||
|
|
||||||
"sax": ["sax@1.6.0", "", {}, "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA=="],
|
"sax": ["sax@1.6.1", "", {}, "sha512-42tBVwLWnaQvW5zc4HbZrTuWccECCZfBi92FDuwtqxasH+JbPB3/FOKb1m222K42R4WxuxzzMsTswfzgtSu64Q=="],
|
||||||
|
|
||||||
"scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="],
|
"scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="],
|
||||||
|
|
||||||
@@ -1459,27 +1462,27 @@
|
|||||||
|
|
||||||
"wrnexus-crm-example": ["wrnexus-crm-example@workspace:examples/crm-app"],
|
"wrnexus-crm-example": ["wrnexus-crm-example@workspace:examples/crm-app"],
|
||||||
|
|
||||||
"ws": ["ws@8.21.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g=="],
|
"ws": ["ws@8.21.3", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw=="],
|
||||||
|
|
||||||
"yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="],
|
"yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="],
|
||||||
|
|
||||||
"@antfu/install-pkg/tinyexec": ["tinyexec@1.2.4", "", {}, "sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg=="],
|
"@antfu/install-pkg/tinyexec": ["tinyexec@1.3.0", "", {}, "sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ=="],
|
||||||
|
|
||||||
"@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=="],
|
||||||
|
|
||||||
"@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.3", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.3", "tslib": "^2.4.0" }, "bundled": true }, "sha512-zLpS5asjEb7lq8jYLq37N6XKaE41DIexlY1rF/z4/tIl3wo13Sqm28fRyfIsKZD+NZ8mM5RoKkpW/rBcuoSZSg=="],
|
||||||
|
|
||||||
"@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.3", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.2", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA=="],
|
"@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.3", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-ELEBe8PsLvvJ6QMr0zLt8ffvOHW/dc1m3CEzNMg7aJUv3bMaoDtw2TXyDAwkYBuroxxuHEwhRTLJSe5sya547g=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.6", "", { "dependencies": { "@tybys/wasm-util": "^0.10.3" }, "peerDependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1" }, "bundled": true }, "sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg=="],
|
"@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.2.3", "", { "dependencies": { "@tybys/wasm-util": "^0.10.3" }, "peerDependencies": { "@emnapi/core": "^1.7.1 || ^2.0.0-alpha.4", "@emnapi/runtime": "^1.7.1 || ^2.0.0-alpha.4" }, "bundled": true }, "sha512-UMduMbqO5s5zF2NkNacMT/yK5Y5QiKvWr2+50bzIIxFDwVJ2h49b+oyjaCGPhJxd2/gC2x39EHv/gHVuu36x2Q=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/@tybys/wasm-util": ["@tybys/wasm-util@0.10.3", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg=="],
|
"@tailwindcss/oxide-wasm32-wasi/@tybys/wasm-util": ["@tybys/wasm-util@0.10.3", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
"@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||||
|
|
||||||
"@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="],
|
"@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.6", "", {}, "sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw=="],
|
||||||
|
|
||||||
"csso/css-tree": ["css-tree@2.2.1", "", { "dependencies": { "mdn-data": "2.0.28", "source-map-js": "^1.0.1" } }, "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA=="],
|
"csso/css-tree": ["css-tree@2.2.1", "", { "dependencies": { "mdn-data": "2.0.28", "source-map-js": "^1.0.1" } }, "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA=="],
|
||||||
|
|
||||||
|
|||||||
+182
-2
@@ -968,6 +968,7 @@
|
|||||||
},
|
},
|
||||||
"@wrnexus/cli": {
|
"@wrnexus/cli": {
|
||||||
".": [],
|
".": [],
|
||||||
|
"./test-setup": [],
|
||||||
"./workspace": [
|
"./workspace": [
|
||||||
"ResolvedWorkspaceApp",
|
"ResolvedWorkspaceApp",
|
||||||
"ResolvedWorkspaceConfig",
|
"ResolvedWorkspaceConfig",
|
||||||
@@ -1352,6 +1353,8 @@
|
|||||||
"ActionClientError",
|
"ActionClientError",
|
||||||
"ActionClientOptions",
|
"ActionClientOptions",
|
||||||
"ActionResult",
|
"ActionResult",
|
||||||
|
"ApiClientOptions",
|
||||||
|
"ApiRequest",
|
||||||
"ClientModuleScope",
|
"ClientModuleScope",
|
||||||
"HydrationScopeApi",
|
"HydrationScopeApi",
|
||||||
"NAV_RUNTIME",
|
"NAV_RUNTIME",
|
||||||
@@ -1365,6 +1368,7 @@
|
|||||||
"callServerFunction",
|
"callServerFunction",
|
||||||
"collectRefs",
|
"collectRefs",
|
||||||
"createActionClient",
|
"createActionClient",
|
||||||
|
"createApiClient",
|
||||||
"createOutputProxy",
|
"createOutputProxy",
|
||||||
"createServerProxy",
|
"createServerProxy",
|
||||||
"getActionRuntime",
|
"getActionRuntime",
|
||||||
@@ -1375,11 +1379,13 @@
|
|||||||
"invalidateClientModule",
|
"invalidateClientModule",
|
||||||
"invokeOutput",
|
"invokeOutput",
|
||||||
"loadClientFunctions",
|
"loadClientFunctions",
|
||||||
"registerOutputHandler"
|
"registerOutputHandler",
|
||||||
|
"useFetch"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"@wrnexus/db": {
|
"@wrnexus/db": {
|
||||||
".": [
|
".": [
|
||||||
|
"AddSeedOptions",
|
||||||
"BaseType",
|
"BaseType",
|
||||||
"Column",
|
"Column",
|
||||||
"ColumnDef",
|
"ColumnDef",
|
||||||
@@ -1390,6 +1396,7 @@
|
|||||||
"Dialect",
|
"Dialect",
|
||||||
"Driver",
|
"Driver",
|
||||||
"ExecResult",
|
"ExecResult",
|
||||||
|
"LedgerOptions",
|
||||||
"Migration",
|
"Migration",
|
||||||
"MigrationRunOptions",
|
"MigrationRunOptions",
|
||||||
"MigrationSafetyIssue",
|
"MigrationSafetyIssue",
|
||||||
@@ -1406,7 +1413,13 @@
|
|||||||
"RelationOptions",
|
"RelationOptions",
|
||||||
"Repository",
|
"Repository",
|
||||||
"Row",
|
"Row",
|
||||||
|
"SeedDatabase",
|
||||||
|
"SeedRow",
|
||||||
|
"SeedStep",
|
||||||
|
"SeedUserAccount",
|
||||||
"TxHandle",
|
"TxHandle",
|
||||||
|
"UpsertSeedOptions",
|
||||||
|
"addSeedData",
|
||||||
"analyzeMigrationSafety",
|
"analyzeMigrationSafety",
|
||||||
"analyzeMigrations",
|
"analyzeMigrations",
|
||||||
"appliedMigrations",
|
"appliedMigrations",
|
||||||
@@ -1421,6 +1434,8 @@
|
|||||||
"cursorPaginate",
|
"cursorPaginate",
|
||||||
"databaseHealth",
|
"databaseHealth",
|
||||||
"databaseNames",
|
"databaseNames",
|
||||||
|
"defineLedger",
|
||||||
|
"defineSeed",
|
||||||
"exists",
|
"exists",
|
||||||
"firstOrThrow",
|
"firstOrThrow",
|
||||||
"generateQueriesFile",
|
"generateQueriesFile",
|
||||||
@@ -1438,15 +1453,20 @@
|
|||||||
"queryOperation",
|
"queryOperation",
|
||||||
"registerDb",
|
"registerDb",
|
||||||
"registerLazyDb",
|
"registerLazyDb",
|
||||||
|
"removeSeedData",
|
||||||
"resetDbPerformanceSnapshot",
|
"resetDbPerformanceSnapshot",
|
||||||
"retryTransaction",
|
"retryTransaction",
|
||||||
"rollback",
|
"rollback",
|
||||||
|
"runSeedQuery",
|
||||||
"scaffoldMigration",
|
"scaffoldMigration",
|
||||||
|
"seedIfMissing",
|
||||||
|
"seedUsers",
|
||||||
"setDb",
|
"setDb",
|
||||||
"softDeleteClause",
|
"softDeleteClause",
|
||||||
"status",
|
"status",
|
||||||
"table",
|
"table",
|
||||||
"tenantScope",
|
"tenantScope",
|
||||||
|
"upsertSeedData",
|
||||||
"v",
|
"v",
|
||||||
"withTransaction"
|
"withTransaction"
|
||||||
],
|
],
|
||||||
@@ -1647,6 +1667,7 @@
|
|||||||
"EncryptionKey",
|
"EncryptionKey",
|
||||||
"EncryptionKeyring",
|
"EncryptionKeyring",
|
||||||
"ReplayStore",
|
"ReplayStore",
|
||||||
|
"SecretResourceOptions",
|
||||||
"createEncryptedRequest",
|
"createEncryptedRequest",
|
||||||
"createKeyring",
|
"createKeyring",
|
||||||
"createMemoryReplayStore",
|
"createMemoryReplayStore",
|
||||||
@@ -1654,6 +1675,7 @@
|
|||||||
"decryptEncryptedResponse",
|
"decryptEncryptedResponse",
|
||||||
"decryptHttpBody",
|
"decryptHttpBody",
|
||||||
"decryptRequest",
|
"decryptRequest",
|
||||||
|
"defineSecretResource",
|
||||||
"deriveKey",
|
"deriveKey",
|
||||||
"encrypt",
|
"encrypt",
|
||||||
"encryptHttpBody",
|
"encryptHttpBody",
|
||||||
@@ -1687,26 +1709,39 @@
|
|||||||
"@wrnexus/helpers": {
|
"@wrnexus/helpers": {
|
||||||
".": [
|
".": [
|
||||||
"AllowedHosts",
|
"AllowedHosts",
|
||||||
|
"ApiHandler",
|
||||||
|
"HttpError",
|
||||||
"LoginRedirectOptions",
|
"LoginRedirectOptions",
|
||||||
"OriginalRequestOptions",
|
"OriginalRequestOptions",
|
||||||
"RequestContext",
|
"RequestContext",
|
||||||
|
"ResourceDefinition",
|
||||||
|
"ResourceHandlers",
|
||||||
"RetryOptions",
|
"RetryOptions",
|
||||||
"appOrigin",
|
"appOrigin",
|
||||||
"appUrl",
|
"appUrl",
|
||||||
|
"authorized",
|
||||||
"backoffDelay",
|
"backoffDelay",
|
||||||
"clamp",
|
"clamp",
|
||||||
"currentAppName",
|
"currentAppName",
|
||||||
"currentAppOrigin",
|
"currentAppOrigin",
|
||||||
|
"defineApiRoute",
|
||||||
|
"defineResource",
|
||||||
"getOriginalRequestMethod",
|
"getOriginalRequestMethod",
|
||||||
"getOriginalRequestOrigin",
|
"getOriginalRequestOrigin",
|
||||||
"getOriginalRequestPath",
|
"getOriginalRequestPath",
|
||||||
"getOriginalRequestUrl",
|
"getOriginalRequestUrl",
|
||||||
|
"json",
|
||||||
"once",
|
"once",
|
||||||
"redirectToLogin",
|
"redirectToLogin",
|
||||||
|
"requireJson",
|
||||||
|
"requireParam",
|
||||||
|
"requirePermission",
|
||||||
|
"requireUser",
|
||||||
"retry",
|
"retry",
|
||||||
"safeJsonParse",
|
"safeJsonParse",
|
||||||
"sleep",
|
"sleep",
|
||||||
"stableStringify",
|
"stableStringify",
|
||||||
|
"subjectId",
|
||||||
"withTimeout",
|
"withTimeout",
|
||||||
"workspaceAppOrigins",
|
"workspaceAppOrigins",
|
||||||
"workspaceRootDomain"
|
"workspaceRootDomain"
|
||||||
@@ -1902,6 +1937,25 @@
|
|||||||
"isApiReferenceAt"
|
"isApiReferenceAt"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"@wrnexus/mail": {
|
||||||
|
".": [
|
||||||
|
"MailDriver",
|
||||||
|
"MailMessage",
|
||||||
|
"MailOptions",
|
||||||
|
"MailSandboxDecision",
|
||||||
|
"MailTemplate",
|
||||||
|
"SealedMailCredentialsOptions",
|
||||||
|
"SealedMailDriverOptions",
|
||||||
|
"defineMail",
|
||||||
|
"defineMailTemplate",
|
||||||
|
"defineSealedMailCredentials",
|
||||||
|
"interpolateTemplate",
|
||||||
|
"mailSandboxDecision",
|
||||||
|
"queuedMail",
|
||||||
|
"sealedMailDriver",
|
||||||
|
"storedMailTemplate"
|
||||||
|
]
|
||||||
|
},
|
||||||
"@wrnexus/mcp": {
|
"@wrnexus/mcp": {
|
||||||
".": [
|
".": [
|
||||||
"McpServer",
|
"McpServer",
|
||||||
@@ -1913,6 +1967,20 @@
|
|||||||
"runMcpStdio"
|
"runMcpStdio"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"@wrnexus/metering": {
|
||||||
|
".": [
|
||||||
|
"EntitlementPlan",
|
||||||
|
"EntitlementsOptions",
|
||||||
|
"MeterKind",
|
||||||
|
"MeterOptions",
|
||||||
|
"MeterPack",
|
||||||
|
"MeterResult",
|
||||||
|
"MeterStore",
|
||||||
|
"defineEntitlements",
|
||||||
|
"defineMeter",
|
||||||
|
"definePacks"
|
||||||
|
]
|
||||||
|
},
|
||||||
"@wrnexus/mobile": {
|
"@wrnexus/mobile": {
|
||||||
".": [
|
".": [
|
||||||
"CapacitorBridge",
|
"CapacitorBridge",
|
||||||
@@ -2113,6 +2181,70 @@
|
|||||||
"traceMiddleware"
|
"traceMiddleware"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"@wrnexus/payment": {
|
||||||
|
".": [
|
||||||
|
"CreateIntentInput",
|
||||||
|
"CustomerInput",
|
||||||
|
"GatewayCapabilities",
|
||||||
|
"GatewayContractFixture",
|
||||||
|
"GatewayContractReport",
|
||||||
|
"GatewayIntent",
|
||||||
|
"GatewayMethod",
|
||||||
|
"GatewayRefund",
|
||||||
|
"GatewaySupport",
|
||||||
|
"InitializePaymentInput",
|
||||||
|
"Money",
|
||||||
|
"PayPalConfig",
|
||||||
|
"PaymentEvent",
|
||||||
|
"PaymentGateway",
|
||||||
|
"PaymentIntent",
|
||||||
|
"PaymentMethod",
|
||||||
|
"PaymentOptions",
|
||||||
|
"PaymentRefund",
|
||||||
|
"PaymentResult",
|
||||||
|
"PaymentService",
|
||||||
|
"PaymentStatus",
|
||||||
|
"PaymentStore",
|
||||||
|
"RazorpayConfig",
|
||||||
|
"RefundInput",
|
||||||
|
"SandboxOptions",
|
||||||
|
"StripeConfig",
|
||||||
|
"WebhookEvent",
|
||||||
|
"configurePayment",
|
||||||
|
"databasePaymentStore",
|
||||||
|
"defineGateway",
|
||||||
|
"definePayment",
|
||||||
|
"derivePaymentStatus",
|
||||||
|
"exerciseGatewayContract",
|
||||||
|
"getPaymentService",
|
||||||
|
"memoryPaymentStore",
|
||||||
|
"paymentPlugin",
|
||||||
|
"paypalGateway",
|
||||||
|
"razorpayGateway",
|
||||||
|
"sandboxGateway",
|
||||||
|
"signSandboxWebhook",
|
||||||
|
"stripeGateway",
|
||||||
|
"verifyGatewayContract"
|
||||||
|
],
|
||||||
|
"./adapters": [
|
||||||
|
"PayPalConfig",
|
||||||
|
"RazorpayConfig",
|
||||||
|
"SandboxOptions",
|
||||||
|
"StripeConfig",
|
||||||
|
"paypalGateway",
|
||||||
|
"razorpayGateway",
|
||||||
|
"sandboxGateway",
|
||||||
|
"signSandboxWebhook",
|
||||||
|
"stripeGateway"
|
||||||
|
],
|
||||||
|
"./plugin": [
|
||||||
|
"default",
|
||||||
|
"paymentPlugin"
|
||||||
|
],
|
||||||
|
"./runtime-webhook": [
|
||||||
|
"POST"
|
||||||
|
]
|
||||||
|
},
|
||||||
"@wrnexus/playground": {
|
"@wrnexus/playground": {
|
||||||
".": [
|
".": [
|
||||||
"PlaygroundCompilation",
|
"PlaygroundCompilation",
|
||||||
@@ -2277,21 +2409,41 @@
|
|||||||
"@wrnexus/queue": {
|
"@wrnexus/queue": {
|
||||||
".": [
|
".": [
|
||||||
"AddOptions",
|
"AddOptions",
|
||||||
|
"DefineQueueOptions",
|
||||||
|
"DefinedJob",
|
||||||
|
"DefinedJobOptions",
|
||||||
|
"DefinedJobs",
|
||||||
|
"DefinedQueue",
|
||||||
"DurableQueue",
|
"DurableQueue",
|
||||||
"DurableQueueOptions",
|
"DurableQueueOptions",
|
||||||
"Job",
|
"Job",
|
||||||
"JobContext",
|
"JobContext",
|
||||||
"JobDefinition",
|
"JobDefinition",
|
||||||
"JobHandler",
|
"JobHandler",
|
||||||
|
"JobStateMachineOptions",
|
||||||
|
"JobStatus",
|
||||||
|
"OutboxEntry",
|
||||||
|
"OutboxWriter",
|
||||||
"POSTGRES_QUEUE_SCHEMA",
|
"POSTGRES_QUEUE_SCHEMA",
|
||||||
"Queue",
|
"Queue",
|
||||||
|
"QueueAdminOptions",
|
||||||
"QueueDashboardSnapshot",
|
"QueueDashboardSnapshot",
|
||||||
|
"QueueEvent",
|
||||||
|
"QueueEventType",
|
||||||
|
"QueueHealth",
|
||||||
|
"QueueJobDefinitions",
|
||||||
|
"QueueJobRecord",
|
||||||
|
"QueueJobState",
|
||||||
"QueueOptions",
|
"QueueOptions",
|
||||||
"QueueScheduler",
|
"QueueScheduler",
|
||||||
|
"QueueStorage",
|
||||||
|
"QueueStorageConfig",
|
||||||
"QueueStore",
|
"QueueStore",
|
||||||
"RedisQueueClient",
|
"RedisQueueClient",
|
||||||
|
"SagaStep",
|
||||||
"ScheduledJob",
|
"ScheduledJob",
|
||||||
"SqlQueueClient",
|
"SqlQueueClient",
|
||||||
|
"SqliteQueueClient",
|
||||||
"SubjectJob",
|
"SubjectJob",
|
||||||
"SubjectQueue",
|
"SubjectQueue",
|
||||||
"WorkerDefinition",
|
"WorkerDefinition",
|
||||||
@@ -2303,24 +2455,46 @@
|
|||||||
"WorkflowStep",
|
"WorkflowStep",
|
||||||
"WorkflowStore",
|
"WorkflowStore",
|
||||||
"addBatch",
|
"addBatch",
|
||||||
|
"configureQueueStorage",
|
||||||
|
"configuredQueueStore",
|
||||||
"createDurableQueue",
|
"createDurableQueue",
|
||||||
"createQueue",
|
"createQueue",
|
||||||
|
"createQueueAdminHandler",
|
||||||
"createQueueScheduler",
|
"createQueueScheduler",
|
||||||
"createWorkflowEngine",
|
"createWorkflowEngine",
|
||||||
"cronToInterval",
|
"cronToInterval",
|
||||||
|
"databaseQueueStore",
|
||||||
"defineDurableWorkflow",
|
"defineDurableWorkflow",
|
||||||
"defineJob",
|
"defineJob",
|
||||||
|
"defineJobStateMachine",
|
||||||
|
"defineQueue",
|
||||||
|
"defineSaga",
|
||||||
"defineWorker",
|
"defineWorker",
|
||||||
"defineWorkflow",
|
"defineWorkflow",
|
||||||
|
"drainOutbox",
|
||||||
|
"installDatabaseQueueSchema",
|
||||||
|
"installOutboxSchema",
|
||||||
|
"installSqliteQueueSchema",
|
||||||
"memoryQueueStore",
|
"memoryQueueStore",
|
||||||
"memoryWorkflowStore",
|
"memoryWorkflowStore",
|
||||||
"postgresQueueStore",
|
"postgresQueueStore",
|
||||||
"queueDashboardSnapshot",
|
"queueDashboardSnapshot",
|
||||||
|
"queueStorageConfig",
|
||||||
"redisQueueStore",
|
"redisQueueStore",
|
||||||
"renderQueueDashboard",
|
"renderQueueDashboard",
|
||||||
"runQueueDaemon",
|
"runQueueDaemon",
|
||||||
"runWorker",
|
"runWorker",
|
||||||
"subjectQueue"
|
"sqliteQueueSchema",
|
||||||
|
"sqliteQueueStore",
|
||||||
|
"subjectQueue",
|
||||||
|
"testQueue",
|
||||||
|
"withOutbox"
|
||||||
|
],
|
||||||
|
"./sqlite": [
|
||||||
|
"SqliteQueueClient",
|
||||||
|
"installSqliteQueueSchema",
|
||||||
|
"sqliteQueueSchema",
|
||||||
|
"sqliteQueueStore"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"@wrnexus/react": {
|
"@wrnexus/react": {
|
||||||
@@ -2363,6 +2537,7 @@
|
|||||||
".": [
|
".": [
|
||||||
"AnimationTimeline",
|
"AnimationTimeline",
|
||||||
"Cleanup",
|
"Cleanup",
|
||||||
|
"FormState",
|
||||||
"HistorySignal",
|
"HistorySignal",
|
||||||
"ReactiveContext",
|
"ReactiveContext",
|
||||||
"ReactiveScope",
|
"ReactiveScope",
|
||||||
@@ -2389,6 +2564,7 @@
|
|||||||
"transition",
|
"transition",
|
||||||
"untrack",
|
"untrack",
|
||||||
"urlSignal",
|
"urlSignal",
|
||||||
|
"useForm",
|
||||||
"watch"
|
"watch"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -2916,11 +3092,14 @@
|
|||||||
".": [
|
".": [
|
||||||
"BrowserArtifactPage",
|
"BrowserArtifactPage",
|
||||||
"Deferred",
|
"Deferred",
|
||||||
|
"DetectMutationsOptions",
|
||||||
"FetchMock",
|
"FetchMock",
|
||||||
"Harness",
|
"Harness",
|
||||||
"HarnessOptions",
|
"HarnessOptions",
|
||||||
"JsonResponse",
|
"JsonResponse",
|
||||||
"MemoryCookieJar",
|
"MemoryCookieJar",
|
||||||
|
"MutationCase",
|
||||||
|
"MutationReport",
|
||||||
"TestRequestOptions",
|
"TestRequestOptions",
|
||||||
"TransactionalDatabase",
|
"TransactionalDatabase",
|
||||||
"WaitForOptions",
|
"WaitForOptions",
|
||||||
@@ -2938,6 +3117,7 @@
|
|||||||
"createTestContext",
|
"createTestContext",
|
||||||
"deferred",
|
"deferred",
|
||||||
"describe",
|
"describe",
|
||||||
|
"detectMutations",
|
||||||
"expect",
|
"expect",
|
||||||
"expectProblem",
|
"expectProblem",
|
||||||
"it",
|
"it",
|
||||||
|
|||||||
@@ -4,22 +4,22 @@
|
|||||||
"artifacts": {
|
"artifacts": {
|
||||||
"packages/ui/components/Accordion.wrn": "09251f76a2f9385e97eb67e06c0cf868e1771ac5f420647221bec5160287034b",
|
"packages/ui/components/Accordion.wrn": "09251f76a2f9385e97eb67e06c0cf868e1771ac5f420647221bec5160287034b",
|
||||||
"packages/ui/components/AdvancedSelect.wrn": "b952b894a5b35050fc2f6e43c4182101eeee05c75662e2aca4abfe61512b305b",
|
"packages/ui/components/AdvancedSelect.wrn": "b952b894a5b35050fc2f6e43c4182101eeee05c75662e2aca4abfe61512b305b",
|
||||||
"packages/ui/components/AnnouncementBar.wrn": "cb66b8d0619ee798a115b43f0ad93fda93dfb46571589e7a9f0a8d65ec3c84c9",
|
"packages/ui/components/AnnouncementBar.wrn": "5b3219db555e0fcdb94ec41dc18186ee1b7c0cf9c260469f7fb1fc43435c28c4",
|
||||||
"packages/ui/components/AuthForm.wrn": "46a3e1db1c9e69efc52473cbf2fababdcbfe7144e7571469638d2c3addd4d7f0",
|
"packages/ui/components/AuthForm.wrn": "46a3e1db1c9e69efc52473cbf2fababdcbfe7144e7571469638d2c3addd4d7f0",
|
||||||
"packages/ui/components/AuthSplitLayout.wrn": "724938921bc38cc5a0422de69c237b630f099f2df94c66977362b048e4a420a5",
|
"packages/ui/components/AuthSplitLayout.wrn": "724938921bc38cc5a0422de69c237b630f099f2df94c66977362b048e4a420a5",
|
||||||
"packages/ui/components/AvatarGroup.wrn": "30b702e06a1adff8b9bae32820206020e086a69560cbdcbadb19f04f25951f97",
|
"packages/ui/components/AvatarGroup.wrn": "30b702e06a1adff8b9bae32820206020e086a69560cbdcbadb19f04f25951f97",
|
||||||
"packages/ui/components/BackToTop.wrn": "5b760ec7941ffd8e58c5dedae1b322ee46e072e927533d7ec077b511a816e436",
|
"packages/ui/components/BackToTop.wrn": "d4b8d1fd37ff26c89b4276ce54ce6ac9581dc2ff8bbcbe160e072778bba76eab",
|
||||||
"packages/ui/components/Blockquote.wrn": "3761bf13babb6eb07ce7392258ee439ef5478064cf589eff63f945b950e00d2e",
|
"packages/ui/components/Blockquote.wrn": "3761bf13babb6eb07ce7392258ee439ef5478064cf589eff63f945b950e00d2e",
|
||||||
"packages/ui/components/Breadcrumb.wrn": "9f6c23550ebfc635c36ca8660953775170b4a471c0cd0206b9a7ba760994980a",
|
"packages/ui/components/Breadcrumb.wrn": "9f6c23550ebfc635c36ca8660953775170b4a471c0cd0206b9a7ba760994980a",
|
||||||
"packages/ui/components/ButtonGroup.wrn": "fc23565ad56bd8483fcb777d9e02ccba2f9ea476c085754d42503bb83b718f72",
|
"packages/ui/components/ButtonGroup.wrn": "fc23565ad56bd8483fcb777d9e02ccba2f9ea476c085754d42503bb83b718f72",
|
||||||
"packages/ui/components/CTASection.wrn": "d0665f2aa33eea95e6f84120f739b3dd9c8723c882138bcb1a7f80dcd7909904",
|
"packages/ui/components/CTASection.wrn": "f6872b980432d5ee9d88388250be9838ccce51bd706349b283ef472ee692b237",
|
||||||
"packages/ui/components/Card.wrn": "3cc2ff238bda279c169026a462236144ad11ec0046deef00ab00e001a07e8a4c",
|
"packages/ui/components/Card.wrn": "be8cd6a438d1ede4c284a302b76f0fbc235a2423b83a7ced21131763fecc8a90",
|
||||||
"packages/ui/components/Carousel.wrn": "e7d921f802aa19210f3f415b59b70750a2c8d78e30684ad334809741c70a6bf9",
|
"packages/ui/components/Carousel.wrn": "e7d921f802aa19210f3f415b59b70750a2c8d78e30684ad334809741c70a6bf9",
|
||||||
"packages/ui/components/Chart.wrn": "07bc01247b5a1c2b82c2ba8386b7fcdbf480efead75d52b7da04d471072c7ee4",
|
"packages/ui/components/Chart.wrn": "07bc01247b5a1c2b82c2ba8386b7fcdbf480efead75d52b7da04d471072c7ee4",
|
||||||
"packages/ui/components/ChatBubble.wrn": "d71f7d6567d76ac0eb3ecc8e2e567fec12bb3236ea05f4d0a72286abc0b7cbb1",
|
"packages/ui/components/ChatBubble.wrn": "d71f7d6567d76ac0eb3ecc8e2e567fec12bb3236ea05f4d0a72286abc0b7cbb1",
|
||||||
"packages/ui/components/Clipboard.wrn": "5a93f2bae337d7ce364229b796bac673f60dde6dc135f0969f4e106e04854d30",
|
"packages/ui/components/Clipboard.wrn": "5a93f2bae337d7ce364229b796bac673f60dde6dc135f0969f4e106e04854d30",
|
||||||
"packages/ui/components/Collapse.wrn": "26df087a61c82f1aa1749785f4c9be654c4f934859c1a47acfcb8cc67eecc75d",
|
"packages/ui/components/Collapse.wrn": "26df087a61c82f1aa1749785f4c9be654c4f934859c1a47acfcb8cc67eecc75d",
|
||||||
"packages/ui/components/ColorPicker.wrn": "557e36adbdee66d8ba9dcdc2446c13f3385a243f2766777feef8504908006c99",
|
"packages/ui/components/ColorPicker.wrn": "ccac7eb49c0f443b404004f1298fa905fde45c52b51466194920939c920348c9",
|
||||||
"packages/ui/components/Columns.wrn": "8ccd9e53f6799b09f8b996740d12e4e73ee782f6fd3e57595c6c16f788b9b812",
|
"packages/ui/components/Columns.wrn": "8ccd9e53f6799b09f8b996740d12e4e73ee782f6fd3e57595c6c16f788b9b812",
|
||||||
"packages/ui/components/Combobox.wrn": "58488dbb60e41dacbf223afdb4a05abdbec53b7f54cd79a0db659add7057b1c1",
|
"packages/ui/components/Combobox.wrn": "58488dbb60e41dacbf223afdb4a05abdbec53b7f54cd79a0db659add7057b1c1",
|
||||||
"packages/ui/components/Confetti.wrn": "0e81426a3ee8aff672385a5466cf96085c25ba17677a2fef432bcddf13f4d58e",
|
"packages/ui/components/Confetti.wrn": "0e81426a3ee8aff672385a5466cf96085c25ba17677a2fef432bcddf13f4d58e",
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
"packages/ui/components/CustomScrollbar.wrn": "2a3a2719580c21823d079c92ebb000c7a5a7d9d16e3fa9275b8fb7d4449cb437",
|
"packages/ui/components/CustomScrollbar.wrn": "2a3a2719580c21823d079c92ebb000c7a5a7d9d16e3fa9275b8fb7d4449cb437",
|
||||||
"packages/ui/components/DataMap.wrn": "338f0d0a3307289dd0387b7fe7ba631fa0b65b6be8c7b9ee3feb2203306f76a3",
|
"packages/ui/components/DataMap.wrn": "338f0d0a3307289dd0387b7fe7ba631fa0b65b6be8c7b9ee3feb2203306f76a3",
|
||||||
"packages/ui/components/DataTable.wrn": "e929fdb4e59613878a03fb6a11e09c42f773c06ca7b20e43ae16a266835f2af4",
|
"packages/ui/components/DataTable.wrn": "e929fdb4e59613878a03fb6a11e09c42f773c06ca7b20e43ae16a266835f2af4",
|
||||||
"packages/ui/components/DatePicker.wrn": "91bcfd3832d3bccc4de5402c0c06209947bde593bad4f869b4c29ee14a5c0bef",
|
"packages/ui/components/DatePicker.wrn": "cefbbb2abb57ad4c57864a0c65589592a20f9ea1695f9fc7693c3135dd82e71a",
|
||||||
"packages/ui/components/DeviceFrame.wrn": "c38d25419ee44b05d7c443cc4e854aeeb7a53a9289e374d71834de2dd2e4d979",
|
"packages/ui/components/DeviceFrame.wrn": "c38d25419ee44b05d7c443cc4e854aeeb7a53a9289e374d71834de2dd2e4d979",
|
||||||
"packages/ui/components/Divider.wrn": "bfa36cf16ccd48c996bb0b08a438f1b281ea1811049ed69fc7680925b1eba019",
|
"packages/ui/components/Divider.wrn": "bfa36cf16ccd48c996bb0b08a438f1b281ea1811049ed69fc7680925b1eba019",
|
||||||
"packages/ui/components/DragAndDrop.wrn": "84305f07d43cdb9eff1f63c19458d88b0aec013424d05a49a2cafbecedc60513",
|
"packages/ui/components/DragAndDrop.wrn": "84305f07d43cdb9eff1f63c19458d88b0aec013424d05a49a2cafbecedc60513",
|
||||||
@@ -36,15 +36,15 @@
|
|||||||
"packages/ui/components/Dropdown.wrn": "978367a9dde22448cc664d686e4dd9c579fe8ba0b2cf02d610d95a3501f8dbb0",
|
"packages/ui/components/Dropdown.wrn": "978367a9dde22448cc664d686e4dd9c579fe8ba0b2cf02d610d95a3501f8dbb0",
|
||||||
"packages/ui/components/FeatureCard.wrn": "1bc548c115f924a0c7ade4c557852757083755c60ca0ee747b150a7cca3ebced",
|
"packages/ui/components/FeatureCard.wrn": "1bc548c115f924a0c7ade4c557852757083755c60ca0ee747b150a7cca3ebced",
|
||||||
"packages/ui/components/FeatureGrid.wrn": "15b5d6f9ddb7e3697682e7247fdf3c2dd080b770335f84ba9fab2692166fe897",
|
"packages/ui/components/FeatureGrid.wrn": "15b5d6f9ddb7e3697682e7247fdf3c2dd080b770335f84ba9fab2692166fe897",
|
||||||
"packages/ui/components/FeatureIconCard.wrn": "3b4f3fa62c6729e686886a5b848e26c255766684829cec2b715967b4e73d6f07",
|
"packages/ui/components/FeatureIconCard.wrn": "5f65d64235babc3e653a5695204412202015e6f3ffadca566fc18c7f9ce70428",
|
||||||
"packages/ui/components/FileInput.wrn": "866a292a3280527bf429893469e7c50f7cf38965d8adb37b45a35ede1606d5b8",
|
"packages/ui/components/FileInput.wrn": "611047c362458a4e2513b741cc3ef43fbe54c10ddafc13775e4ff39c9de34931",
|
||||||
"packages/ui/components/FileUploadProgress.wrn": "e5da29c562a521cdd6bb50b8f4d217aa1ab981d7b2a2432af47391472f0a8034",
|
"packages/ui/components/FileUploadProgress.wrn": "ba00557afebf60e6221385d6efcf08635789328deee6e551fc53fbb71e1f413b",
|
||||||
"packages/ui/components/Footer.wrn": "f7c5a77064a09e244f689d42475c4c20143f4c8859cac451c10a50c14652db33",
|
"packages/ui/components/Footer.wrn": "e3515e05ef3ef51e6dad71d67ddfe110c80fdcf69e952aecdc7973e69d4f08c7",
|
||||||
"packages/ui/components/Grid.wrn": "83d4f5f2656d539538723f5791ba3c238901432e9d8c55c74f068d3eb5a74517",
|
"packages/ui/components/Grid.wrn": "83d4f5f2656d539538723f5791ba3c238901432e9d8c55c74f068d3eb5a74517",
|
||||||
"packages/ui/components/Hero.wrn": "345478b212701817ff57060f87982a987baf01a7179c979768e1cd4218b50900",
|
"packages/ui/components/Hero.wrn": "345478b212701817ff57060f87982a987baf01a7179c979768e1cd4218b50900",
|
||||||
"packages/ui/components/HeroActions.wrn": "67cd31400ccb6abdbbf16219267dee946b44b064b79f25276d20ceb7d6e8a790",
|
"packages/ui/components/HeroActions.wrn": "67cd31400ccb6abdbbf16219267dee946b44b064b79f25276d20ceb7d6e8a790",
|
||||||
"packages/ui/components/Image.wrn": "361179c478d7674c3b998891a366d73de9514fc6cc8786440c6c50b9ef065357",
|
"packages/ui/components/Image.wrn": "361179c478d7674c3b998891a366d73de9514fc6cc8786440c6c50b9ef065357",
|
||||||
"packages/ui/components/InputGroup.wrn": "30e9f2e4364542179180b6d6e796002d0ffe1e30305146749874697cde6629ea",
|
"packages/ui/components/InputGroup.wrn": "9e259d15207500d07ff626f09c2e2f5eaf4e471f805a7bdbec154b1a23ce0f8d",
|
||||||
"packages/ui/components/InputNumber.wrn": "069195cc483f3f7d6f305d03fbe5a821906a030376fafb6f0d969e4c95b68fd0",
|
"packages/ui/components/InputNumber.wrn": "069195cc483f3f7d6f305d03fbe5a821906a030376fafb6f0d969e4c95b68fd0",
|
||||||
"packages/ui/components/Kbd.wrn": "6b402cb93f0fa76bb978d1ba483215f70ec7214b1c5e84b568fa3e26e87ed9d9",
|
"packages/ui/components/Kbd.wrn": "6b402cb93f0fa76bb978d1ba483215f70ec7214b1c5e84b568fa3e26e87ed9d9",
|
||||||
"packages/ui/components/LayoutSplitter.wrn": "41d070e801a271552023e4392e4c0f67327c61e2e8eaee5f8b87af254b1d79c1",
|
"packages/ui/components/LayoutSplitter.wrn": "41d070e801a271552023e4392e4c0f67327c61e2e8eaee5f8b87af254b1d79c1",
|
||||||
@@ -55,38 +55,38 @@
|
|||||||
"packages/ui/components/Map.wrn": "3e6d5de5a21dd050c5c65950d6fb2f89af4024e1856a48f055b65b88fcd7b890",
|
"packages/ui/components/Map.wrn": "3e6d5de5a21dd050c5c65950d6fb2f89af4024e1856a48f055b65b88fcd7b890",
|
||||||
"packages/ui/components/MarketingSectionHeader.wrn": "39b79499b77dc1c7d34e4e5ecb45a9ddc6182f78c2a2586671c4fa07f44679ad",
|
"packages/ui/components/MarketingSectionHeader.wrn": "39b79499b77dc1c7d34e4e5ecb45a9ddc6182f78c2a2586671c4fa07f44679ad",
|
||||||
"packages/ui/components/Marquee.wrn": "81cd80732be34c8d7e4bf28b00347e1a9273166afdf66589d9f5d5774b69403b",
|
"packages/ui/components/Marquee.wrn": "81cd80732be34c8d7e4bf28b00347e1a9273166afdf66589d9f5d5774b69403b",
|
||||||
"packages/ui/components/MegaMenu.wrn": "6a6db166259f8f2bd7ac8fbb21dba6d915c4b936d87b19805caa78189f54730a",
|
"packages/ui/components/MegaMenu.wrn": "a34a84f31f7a3016cf5a607a22f8f7b2322552c550278f6e8c5e6d6cb18848a8",
|
||||||
"packages/ui/components/MetricCard.wrn": "513a6e99be3d9db46d96af9942b51331a0a048b184603e77e814506f0a52bdc5",
|
"packages/ui/components/MetricCard.wrn": "513a6e99be3d9db46d96af9942b51331a0a048b184603e77e814506f0a52bdc5",
|
||||||
"packages/ui/components/MetricGrid.wrn": "c71e53249835908833055b553e64a8ee55fdf11ac4605436a9581ebb87a0608b",
|
"packages/ui/components/MetricGrid.wrn": "1fcebf51dcbe8520fe16bda904c1ef206c25c3900438d53877492c64ea21a1a5",
|
||||||
"packages/ui/components/Modal.wrn": "7fa4b877772736f29f690e24d8742922b310397ef3083f0b78acb67a9f0d14b2",
|
"packages/ui/components/Modal.wrn": "7fa4b877772736f29f690e24d8742922b310397ef3083f0b78acb67a9f0d14b2",
|
||||||
"packages/ui/components/Nav.wrn": "c45b0ecb42250f4b3ede33c8932a025f789dda9ef48dbf332459ae458163e69a",
|
"packages/ui/components/Nav.wrn": "c45b0ecb42250f4b3ede33c8932a025f789dda9ef48dbf332459ae458163e69a",
|
||||||
"packages/ui/components/Navbar.wrn": "01903230210cd2e5e6d9325a0708f85af9623d4118e3a53f1adb770fd545425d",
|
"packages/ui/components/Navbar.wrn": "b68a824e479ce6957afc3e9710442281cdc1a8d02cd96501fe060271f54368e4",
|
||||||
"packages/ui/components/PageHeader.wrn": "321cde36ce8d521a57901033d46e8b437f42e558cca27f49ca26f7172aff1d54",
|
"packages/ui/components/PageHeader.wrn": "29a93cdca7285548b79ebe5b6421eef6dbb4d5ae8be2508fa2d681e1068ba07f",
|
||||||
"packages/ui/components/Pagination.wrn": "d54226705d4556f76ee5f0d6ae82d101ca6d006397756d547a9aa5954415ba39",
|
"packages/ui/components/Pagination.wrn": "d54226705d4556f76ee5f0d6ae82d101ca6d006397756d547a9aa5954415ba39",
|
||||||
"packages/ui/components/PinInput.wrn": "4dc398456f6392d7925db941debb484c7cb0358ecef527f696fe5ec4800a7602",
|
"packages/ui/components/PinInput.wrn": "4dc398456f6392d7925db941debb484c7cb0358ecef527f696fe5ec4800a7602",
|
||||||
"packages/ui/components/Popover.wrn": "1246b99b4236bc7109a5d1427d013bb07bbea7a2da4f821517d2545ee0b5c019",
|
"packages/ui/components/Popover.wrn": "1246b99b4236bc7109a5d1427d013bb07bbea7a2da4f821517d2545ee0b5c019",
|
||||||
"packages/ui/components/PortalDashboard.wrn": "f04171eb1f8cabef06de3c20e4694b766def3407e1e20d2c9aaebc9bb7da03ee",
|
"packages/ui/components/PortalDashboard.wrn": "f04171eb1f8cabef06de3c20e4694b766def3407e1e20d2c9aaebc9bb7da03ee",
|
||||||
"packages/ui/components/PreferenceSwitcher.wrn": "77229e15449182563ebf49159507139928eb74e799e4438e00e9aa81fd60f982",
|
"packages/ui/components/PreferenceSwitcher.wrn": "519cf911390f529fff3fd16e11fb58e79d618fe851902202dc37552ee1182395",
|
||||||
"packages/ui/components/PublicPageShell.wrn": "3d3f25c03d48f3d3d7e3c567e79cb137c7fce1867e054fd6d440fa1d2e961077",
|
"packages/ui/components/PublicPageShell.wrn": "3d3f25c03d48f3d3d7e3c567e79cb137c7fce1867e054fd6d440fa1d2e961077",
|
||||||
"packages/ui/components/RangeSlider.wrn": "bbf646c5d5a89a62986290db811d77b8f635ebcaea9ca2d334b569aa5edc785b",
|
"packages/ui/components/RangeSlider.wrn": "e8ab41782c9d6e58638f0bfccf6e3172af4ebf552189d2199cc6c96bd1652067",
|
||||||
"packages/ui/components/Rating.wrn": "902b55c64e3798f3097f09b1558d1a2372f66d4f760662de085783108ee04587",
|
"packages/ui/components/Rating.wrn": "902b55c64e3798f3097f09b1558d1a2372f66d4f760662de085783108ee04587",
|
||||||
"packages/ui/components/Scrollspy.wrn": "b9c6400ee92a7c228362610a2051f37bff1d3baba1dbacd66d58397dfda5d856",
|
"packages/ui/components/Scrollspy.wrn": "4b452fcbd524feda9c9f2c81894ee01747a51888e3b86fafb37c5d4d192a3a51",
|
||||||
"packages/ui/components/SearchBox.wrn": "3f88340e0b69c0cd552023c72bd22dc511bc00422d46060097bcf0777e683675",
|
"packages/ui/components/SearchBox.wrn": "3f88340e0b69c0cd552023c72bd22dc511bc00422d46060097bcf0777e683675",
|
||||||
"packages/ui/components/Section.wrn": "45b7a1977c25a6020d5cc8bab2ce9c80730e7ec2d51ad53e8c9f64cd9b5b64cd",
|
"packages/ui/components/Section.wrn": "78da13eb8bc1acafe8e6151cbaeed4baaac2ab860e3209f1d13c467f279d2e68",
|
||||||
"packages/ui/components/SectionHeader.wrn": "aca2df8eb35806096f5b9af466b018e5c22a19422e8665f488380da577a0ceb5",
|
"packages/ui/components/SectionHeader.wrn": "aca2df8eb35806096f5b9af466b018e5c22a19422e8665f488380da577a0ceb5",
|
||||||
"packages/ui/components/Sidebar.wrn": "e0250a973aea589a4d7dcc8b30dd01f22592bf22ba012e54a672b2a2288d8af6",
|
"packages/ui/components/Sidebar.wrn": "e0250a973aea589a4d7dcc8b30dd01f22592bf22ba012e54a672b2a2288d8af6",
|
||||||
"packages/ui/components/SplitHero.wrn": "843387dc7b920b3cf6a1b2b785b8653c281982e524479edc2638a89381ff3577",
|
"packages/ui/components/SplitHero.wrn": "7127cb869d1228522d066e028818dd9e512de8b6dd8f99e3dec500e6da5a3cb0",
|
||||||
"packages/ui/components/StatsBar.wrn": "c273bd6ca417a0a20e5e6f1214414f678741b73bedd885fea1037575fa8c5b95",
|
"packages/ui/components/StatsBar.wrn": "6fabcb4374b1e074f58ebcaba968f235c8a3409762163aea51298e2515a14435",
|
||||||
"packages/ui/components/Stepper.wrn": "7ec0902acd7cb74b44d490215b6421dae9a41731735ad1e9aec17e8bfc3fa142",
|
"packages/ui/components/Stepper.wrn": "7ec0902acd7cb74b44d490215b6421dae9a41731735ad1e9aec17e8bfc3fa142",
|
||||||
"packages/ui/components/StrongPassword.wrn": "407eabcc13affc9323a346ddba8e39c81b885a59ef7043d2bd5567d4b7553282",
|
"packages/ui/components/StrongPassword.wrn": "cc31cb080c4b4116c544b4340b8d740d08fec1b05563372b3280c50759416c87",
|
||||||
"packages/ui/components/StyledIcon.wrn": "0874f9a234b053a7c8b9c6983be5d664453a64c4576dff1a049101e249a2866d",
|
"packages/ui/components/StyledIcon.wrn": "0874f9a234b053a7c8b9c6983be5d664453a64c4576dff1a049101e249a2866d",
|
||||||
"packages/ui/components/Tabs.wrn": "f85214960e62da2fac41228deba511a50c57fd94f2830a8233b75048f6a542e9",
|
"packages/ui/components/Tabs.wrn": "f85214960e62da2fac41228deba511a50c57fd94f2830a8233b75048f6a542e9",
|
||||||
"packages/ui/components/TextLink.wrn": "9d561631c5f65a2bcdc59f5c0b166a5dd794a396f42093f2cd26388386f6f954",
|
"packages/ui/components/TextLink.wrn": "9d561631c5f65a2bcdc59f5c0b166a5dd794a396f42093f2cd26388386f6f954",
|
||||||
"packages/ui/components/TimePicker.wrn": "ec0860a4a82a042a65acf9aa81519a5c815b61e0b8080cf6f1c986d26ce7f0e8",
|
"packages/ui/components/TimePicker.wrn": "33bd7a7069b7abe858cf1617b5b950733b37a8d522469ed673cff00b4dfcad0e",
|
||||||
"packages/ui/components/Timeline.wrn": "fb553f69763840532eef1c0aafa79013f57411dc5335e7cb7e7c20c5a3753008",
|
"packages/ui/components/Timeline.wrn": "fb553f69763840532eef1c0aafa79013f57411dc5335e7cb7e7c20c5a3753008",
|
||||||
"packages/ui/components/Toaster.wrn": "5e4c9b2c1bfd5675a81a32e57684b99393ac7fe45d8420c7409a4e95d47d080c",
|
"packages/ui/components/Toaster.wrn": "5e4c9b2c1bfd5675a81a32e57684b99393ac7fe45d8420c7409a4e95d47d080c",
|
||||||
"packages/ui/components/ToggleCount.wrn": "e577195ee05ddb43cceec47145f6b90c0149f2f17055733d58911fcd02de2c7f",
|
"packages/ui/components/ToggleCount.wrn": "e577195ee05ddb43cceec47145f6b90c0149f2f17055733d58911fcd02de2c7f",
|
||||||
"packages/ui/components/TogglePassword.wrn": "6bd4d9fa82b0c8e80178430d5a42b1b3ec9725fb62be158585f68af9338c901a",
|
"packages/ui/components/TogglePassword.wrn": "caa58479e5c8b1e3e504181a56a7d6bcf71d0a230010733710961c31e1cc58ab",
|
||||||
"packages/ui/components/TreeView.wrn": "f54d8495730203b923629bcfb167d5ca41236af0101ea2723d33354413555b4b",
|
"packages/ui/components/TreeView.wrn": "f54d8495730203b923629bcfb167d5ca41236af0101ea2723d33354413555b4b",
|
||||||
"packages/ui/components/Typography.wrn": "9676af57f2a937b21f45512e0a290b5bee4a16267fbf404850297d29645d88b5",
|
"packages/ui/components/Typography.wrn": "9676af57f2a937b21f45512e0a290b5bee4a16267fbf404850297d29645d88b5",
|
||||||
"packages/ui/components/WysiwygEditor.wrn": "a858ebd4e6e2672463ba57d4d049176ca1cc98dac32ab3df3638d6a9cdcd0f2d",
|
"packages/ui/components/WysiwygEditor.wrn": "a858ebd4e6e2672463ba57d4d049176ca1cc98dac32ab3df3638d6a9cdcd0f2d",
|
||||||
@@ -94,15 +94,15 @@
|
|||||||
"packages/ui/components/avatar.wrn": "8bc705e459b13c7f063c57e1506ce540e50fa8ef9020ae85b6e8b6a3579fc5dc",
|
"packages/ui/components/avatar.wrn": "8bc705e459b13c7f063c57e1506ce540e50fa8ef9020ae85b6e8b6a3579fc5dc",
|
||||||
"packages/ui/components/badge.wrn": "e44e33633fb34e897696cd9290f210108e35a3e2dc3b2a4a367411f45c69a1e1",
|
"packages/ui/components/badge.wrn": "e44e33633fb34e897696cd9290f210108e35a3e2dc3b2a4a367411f45c69a1e1",
|
||||||
"packages/ui/components/button.wrn": "65570c58cb2547f1e17cd158eec7cf7b1ffc721e6976c6486c9df564627b1219",
|
"packages/ui/components/button.wrn": "65570c58cb2547f1e17cd158eec7cf7b1ffc721e6976c6486c9df564627b1219",
|
||||||
"packages/ui/components/checkbox.wrn": "18046396b75d0b9c6bb2bdb09dbff1846c84fb07490f390a25ca7b5367fd2ef4",
|
"packages/ui/components/checkbox.wrn": "da735354b57f33946591e1bd018b521ff709bae1325e2317735824673188377a",
|
||||||
"packages/ui/components/input.wrn": "e4c14527f009b610b4aa96d8d7b7d5ac3ca1ffd34237bab348ee9dc4ddc55847",
|
"packages/ui/components/input.wrn": "2f17353cbf0711ca50a935ae03ee9ee53594d7e35eb73f5df573fadb7958fac2",
|
||||||
"packages/ui/components/progress.wrn": "6307a90585197d7aab19a8710b2430f5d4ed27ce77e9b90b1414ea0eed876492",
|
"packages/ui/components/progress.wrn": "6307a90585197d7aab19a8710b2430f5d4ed27ce77e9b90b1414ea0eed876492",
|
||||||
"packages/ui/components/radio.wrn": "09425a78358de5bbd2f47482f313e80065135335b969ce5ccdd5c7cc3ea5232c",
|
"packages/ui/components/radio.wrn": "df8e562324b6d99f5a157b0971d63bd715daa0cf6189e7b0d4df04d6f0411388",
|
||||||
"packages/ui/components/select.wrn": "1d8d47a74d5ab9ed58d0ba11f46910897233b96652d17f5962f5dda60bd4cf8a",
|
"packages/ui/components/select.wrn": "747321d6292b8052e44e8014e87ce25f4b56d8e07f86f1061e0ed0cec7651356",
|
||||||
"packages/ui/components/skeleton.wrn": "4fc5e0846eeefd7830c038e1789be995c4f9d833aa913ff079eb4863baa65648",
|
"packages/ui/components/skeleton.wrn": "4fc5e0846eeefd7830c038e1789be995c4f9d833aa913ff079eb4863baa65648",
|
||||||
"packages/ui/components/spinner.wrn": "2322645da7ef53f7c06035ff071d9a2f6ffe2901ff9338daed84037369367105",
|
"packages/ui/components/spinner.wrn": "2322645da7ef53f7c06035ff071d9a2f6ffe2901ff9338daed84037369367105",
|
||||||
"packages/ui/components/switch.wrn": "874504e4828e9db6a570d78984c4d3a76d0ceb39d70baa877649cb3798c82c85",
|
"packages/ui/components/switch.wrn": "243f521431ffb644089df7f629bace0c07094638dfdd27e75b2017efa9cbba4f",
|
||||||
"packages/ui/components/textarea.wrn": "9870d37664471a103d44435a3977bf40b087a743acd76ee4d77df9b56cccbb2b",
|
"packages/ui/components/textarea.wrn": "aa3a75214e998a0b57c50e416476d6f85fa0313aaf97262f2f9222150c6c9e26",
|
||||||
"packages/ui/components/tooltip.wrn": "f3dfdfa5cd9661fe5e95ef3580eef4c7437c069726421370c2d7328fbe7d840d",
|
"packages/ui/components/tooltip.wrn": "f3dfdfa5cd9661fe5e95ef3580eef4c7437c069726421370c2d7328fbe7d840d",
|
||||||
"packages/ui/styles/SelectStyles.wrn": "074fe0d67de4ef5e9f9cfe879beb72fd5c83352888687d3a1a4b7722c87af3ca",
|
"packages/ui/styles/SelectStyles.wrn": "074fe0d67de4ef5e9f9cfe879beb72fd5c83352888687d3a1a4b7722c87af3ca",
|
||||||
"packages/ui/ui.css": "9ea591404e9cf675bbf1003e15e9fad00327094ff217dc20733f0fc87c0f4a62"
|
"packages/ui/ui.css": "9ea591404e9cf675bbf1003e15e9fad00327094ff217dc20733f0fc87c0f4a62"
|
||||||
|
|||||||
@@ -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.9",
|
"version": "0.8.11",
|
||||||
"publisher": "wrnexus",
|
"publisher": "wrnexus",
|
||||||
"private": true,
|
"private": true,
|
||||||
"license": "SEE LICENSE IN LICENSE",
|
"license": "SEE LICENSE IN LICENSE",
|
||||||
|
|||||||
+130
-20
@@ -1,7 +1,7 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
// Generated by scripts/build-editor-compiler.mjs. Do not edit directly.
|
// Generated by scripts/build-editor-compiler.mjs. Do not edit directly.
|
||||||
// WRN editor compiler source hash: 1e7593d6b6bd1c9b8439fc34a30f9db9f7ae64f1788365a74115170aa34cd185
|
// WRN editor compiler source hash: 3d346a264807ba7b107584dc9a7b505b1d14057b2ad1aa85c5ea890f9b09c272
|
||||||
// WRN editor compiler generator hash: a54ca847c758bc98d8e353ad6d70088df31de1820f6cf9d1c3462505f563e6b8
|
// WRN editor compiler generator hash: f8c1094b47e695151205899de28cd63d574356d26ac49219c4a43db0f2391ef5
|
||||||
// Generated with TypeScript: 6.0.3
|
// Generated with TypeScript: 6.0.3
|
||||||
const __nodeRequire = require;
|
const __nodeRequire = require;
|
||||||
const __path = __nodeRequire("node:path");
|
const __path = __nodeRequire("node:path");
|
||||||
@@ -1148,6 +1148,31 @@ function componentEventAttribute(name) {
|
|||||||
}
|
}
|
||||||
return `data-wrn-out-${name}`;
|
return `data-wrn-out-${name}`;
|
||||||
}
|
}
|
||||||
|
/** Expand bind:value/bind:checked into a reactive prop plus assignment handler. */
|
||||||
|
function expandBindings(attrs) {
|
||||||
|
const output = [];
|
||||||
|
for (const attr of attrs) {
|
||||||
|
if (attr.event || !attr.name.startsWith("bind:")) {
|
||||||
|
output.push(attr);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const target = attr.name.slice("bind:".length);
|
||||||
|
if (target !== "value" && target !== "checked") {
|
||||||
|
throw new Error(`Unknown .wrn binding '${attr.name}'. Use bind:value or bind:checked.`);
|
||||||
|
}
|
||||||
|
const expression = wholeAttributeExpression(attr.value) ?? attr.value.trim();
|
||||||
|
if (!/^[A-Za-z_$][\w$]*$/.test(expression)) {
|
||||||
|
throw new Error(`${attr.name} requires a writable state name, received '${expression}'.`);
|
||||||
|
}
|
||||||
|
output.push({ name: target, value: `{${expression}}`, event: false });
|
||||||
|
output.push({
|
||||||
|
name: target === "checked" ? "change" : "input",
|
||||||
|
value: `${expression} = payload.${target}`,
|
||||||
|
event: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
function reactiveAttrValue(raw, reactive) {
|
function reactiveAttrValue(raw, reactive) {
|
||||||
let found = false;
|
let found = false;
|
||||||
const value = raw.replace(/\{([^{}]+)\}/g, (whole, inner) => {
|
const value = raw.replace(/\{([^{}]+)\}/g, (whole, inner) => {
|
||||||
@@ -1166,6 +1191,7 @@ function reactiveAttrValue(raw, reactive) {
|
|||||||
return found ? value : null;
|
return found ? value : null;
|
||||||
}
|
}
|
||||||
function renderAttrs(attrs, csrId, reactive = null, dynamicExpressions) {
|
function renderAttrs(attrs, csrId, reactive = null, dynamicExpressions) {
|
||||||
|
attrs = expandBindings(attrs);
|
||||||
let bindIndex = 0;
|
let bindIndex = 0;
|
||||||
const rendered = attrs
|
const rendered = attrs
|
||||||
.map((attr) => {
|
.map((attr) => {
|
||||||
@@ -1302,7 +1328,7 @@ function renderLoopBody(node, locals = []) {
|
|||||||
return compileIfExpr(node, locals);
|
return compileIfExpr(node, locals);
|
||||||
}
|
}
|
||||||
const componentTag = isComponentTag(node.tag);
|
const componentTag = isComponentTag(node.tag);
|
||||||
const attrs = node.attrs
|
const attrs = expandBindings(node.attrs)
|
||||||
.filter((attr) => attr.name !== "data-component")
|
.filter((attr) => attr.name !== "data-component")
|
||||||
.map((attr) => {
|
.map((attr) => {
|
||||||
const name = attr.event
|
const name = attr.event
|
||||||
@@ -1562,9 +1588,9 @@ function renderPageComponentInvocation(node, ssrBindings, csrBindings, apiBindin
|
|||||||
const island = islandMarkerFor(node);
|
const island = islandMarkerFor(node);
|
||||||
if (island)
|
if (island)
|
||||||
return island;
|
return island;
|
||||||
const attrs = node.attrs
|
const attrs = expandBindings(node.attrs)
|
||||||
.filter((attr) => attr.name !== "data-component")
|
.filter((attr) => attr.name !== "data-component")
|
||||||
.map((attr) => renderPageComponentAttr(attr, loops))
|
.map((attr) => renderPageComponentAttr(attr, loops, reactive))
|
||||||
.join("");
|
.join("");
|
||||||
const inner = node.children
|
const inner = node.children
|
||||||
.map((child) => renderNode(child, ssrBindings, csrBindings, apiBindings, loops, reactive))
|
.map((child) => renderNode(child, ssrBindings, csrBindings, apiBindings, loops, reactive))
|
||||||
@@ -1577,7 +1603,7 @@ function renderNestedComponentInvocation(node, ctx) {
|
|||||||
if (island)
|
if (island)
|
||||||
return island;
|
return island;
|
||||||
let bindIndex = 0;
|
let bindIndex = 0;
|
||||||
const attrs = node.attrs
|
const attrs = expandBindings(node.attrs)
|
||||||
.filter((attr) => attr.name !== "data-component")
|
.filter((attr) => attr.name !== "data-component")
|
||||||
.map((attr) => {
|
.map((attr) => {
|
||||||
const spread = /^\{\.\.\.([A-Za-z_$][\w$]*)\}$/.exec(attr.name);
|
const spread = /^\{\.\.\.([A-Za-z_$][\w$]*)\}$/.exec(attr.name);
|
||||||
@@ -2446,6 +2472,8 @@ ${exposed
|
|||||||
${declarations}
|
${declarations}
|
||||||
${visible.length
|
${visible.length
|
||||||
? ` const __values = await Promise.all([${visible.map((entry) => `__load_${entry.name}()`).join(", ")}]);
|
? ` const __values = await Promise.all([${visible.map((entry) => `__load_${entry.name}()`).join(", ")}]);
|
||||||
|
const __response = __values.find((value) => value instanceof Response);
|
||||||
|
if (__response) return __response;
|
||||||
return { ${visible.map((entry, index) => `${JSON.stringify(entry.name)}: __values[${index}]`).join(", ")} };`
|
return { ${visible.map((entry, index) => `${JSON.stringify(entry.name)}: __values[${index}]`).join(", ")} };`
|
||||||
: ""}
|
: ""}
|
||||||
}`;
|
}`;
|
||||||
@@ -2765,7 +2793,7 @@ function renderClientControlTemplate(nodes) {
|
|||||||
}
|
}
|
||||||
const componentTag = isComponentTag(node.tag);
|
const componentTag = isComponentTag(node.tag);
|
||||||
let bindIndex = 0;
|
let bindIndex = 0;
|
||||||
const attrs = node.attrs
|
const attrs = expandBindings(node.attrs)
|
||||||
.map((attribute) => {
|
.map((attribute) => {
|
||||||
const name = attribute.event
|
const name = attribute.event
|
||||||
? componentTag
|
? componentTag
|
||||||
@@ -2803,19 +2831,21 @@ function encodeClientControl(value) {
|
|||||||
}
|
}
|
||||||
function renderComponentIfNode(node, ctx) {
|
function renderComponentIfNode(node, ctx) {
|
||||||
let expression = "``";
|
let expression = "``";
|
||||||
|
const clientBranches = [];
|
||||||
for (let index = node.branches.length - 1; index >= 0; index--) {
|
for (let index = node.branches.length - 1; index >= 0; index--) {
|
||||||
const branch = node.branches[index];
|
const branch = node.branches[index];
|
||||||
const body = branch.body.map((child) => renderComponentNode(child, ctx)).join("");
|
const body = branch.body.map((child) => renderComponentNode(child, ctx)).join("");
|
||||||
const bodyExpression = "`" + body + "`";
|
const bodyExpression = "`" + body + "`";
|
||||||
|
clientBranches.unshift(`{ cond: ${branch.cond === null ? "null" : JSON.stringify(branch.cond)}, body: ${bodyExpression} }`);
|
||||||
expression =
|
expression =
|
||||||
branch.cond === null
|
branch.cond === null
|
||||||
? bodyExpression
|
? bodyExpression
|
||||||
: `(${ctx.resolveExpr(branch.cond)}) ? ${bodyExpression} : ${expression}`;
|
: `(${ctx.resolveExpr(branch.cond)}) ? ${bodyExpression} : ${expression}`;
|
||||||
}
|
}
|
||||||
const definition = encodeClientControl(node.branches.map((branch) => ({
|
// Render all branches on the server into an inert, encoded definition.
|
||||||
cond: branch.cond,
|
// A branch first selected in the browser therefore contains the real nested
|
||||||
body: renderClientControlTemplate(branch.body),
|
// component HTML and scope metadata, not a data-component placeholder.
|
||||||
})));
|
const definition = `\${__wrnexusEncodeControl([${clientBranches.join(",")}])}`;
|
||||||
return `<template data-wrn-if="${definition}"></template>${"${" + expression + "}"}<template data-wrn-control-end></template>`;
|
return `<template data-wrn-if="${definition}"></template>${"${" + expression + "}"}<template data-wrn-control-end></template>`;
|
||||||
}
|
}
|
||||||
function renderComponentEachNode(node, ctx) {
|
function renderComponentEachNode(node, ctx) {
|
||||||
@@ -2955,7 +2985,7 @@ function renderComponentNode(node, ctx) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
const isExplicitComponentMount = node.attrs.some((attribute) => attribute.name === "data-component");
|
const isExplicitComponentMount = node.attrs.some((attribute) => attribute.name === "data-component");
|
||||||
const attrs = node.attrs
|
const attrs = expandBindings(node.attrs)
|
||||||
.filter((a) => a.name !== "class" && !a.name.startsWith("class:"))
|
.filter((a) => a.name !== "class" && !a.name.startsWith("class:"))
|
||||||
.map((a) => {
|
.map((a) => {
|
||||||
const spread = /^\{\.\.\.([A-Za-z_$][\w$]*)\}$/.exec(a.name);
|
const spread = /^\{\.\.\.([A-Za-z_$][\w$]*)\}$/.exec(a.name);
|
||||||
@@ -3413,6 +3443,9 @@ function __wrnRaw(v: unknown): string {
|
|||||||
}`);
|
}`);
|
||||||
}
|
}
|
||||||
if (needsScope) {
|
if (needsScope) {
|
||||||
|
out.push(`function __wrnexusEncodeControl(value: unknown): string {
|
||||||
|
return __WrnexusBuffer.from(JSON.stringify(value), "utf8").toString("base64");
|
||||||
|
}`);
|
||||||
out.push(`function __wrnexusSerializeScopeValue(value: unknown): string {
|
out.push(`function __wrnexusSerializeScopeValue(value: unknown): string {
|
||||||
if (value === undefined) {
|
if (value === undefined) {
|
||||||
return "undefined";
|
return "undefined";
|
||||||
@@ -3495,7 +3528,7 @@ function __wrnProp(v) {
|
|||||||
const value = v !== null && typeof v === "object" ? JSON.stringify(v) : String(v == null ? "" : v);
|
const value = v !== null && typeof v === "object" ? JSON.stringify(v) : String(v == null ? "" : v);
|
||||||
return __wrnAttr(value);
|
return __wrnAttr(value);
|
||||||
}
|
}
|
||||||
function renderPageComponentAttr(attr, dynamicExpressions) {
|
function renderPageComponentAttr(attr, dynamicExpressions, _reactive) {
|
||||||
if (attr.event) {
|
if (attr.event) {
|
||||||
return ` ${componentEventAttribute(attr.name)}="${attrEscape(attr.value)}"`;
|
return ` ${componentEventAttribute(attr.name)}="${attrEscape(attr.value)}"`;
|
||||||
}
|
}
|
||||||
@@ -3508,7 +3541,11 @@ function renderPageComponentAttr(attr, dynamicExpressions) {
|
|||||||
}
|
}
|
||||||
dynamicExpressions.push(`\${__wrnexusPropAttr(${expression})}`);
|
dynamicExpressions.push(`\${__wrnexusPropAttr(${expression})}`);
|
||||||
const marker = `\x00WRNEACH${dynamicExpressions.length - 1}\x00`;
|
const marker = `\x00WRNEACH${dynamicExpressions.length - 1}\x00`;
|
||||||
return ` ${attr.name}="${marker}"`;
|
// The mount disappears during SSR. Preserve every dynamic component prop
|
||||||
|
// as a parent-owned binding; server-only expressions simply fail closed in
|
||||||
|
// the browser, while page state can continue driving the mounted child.
|
||||||
|
const binding = ` data-wrn-prop-bind-${dynamicExpressions.length - 1}="${attrEscape(JSON.stringify([attr.name, attr.value]))}"`;
|
||||||
|
return ` ${attr.name}="${marker}"${binding}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
@@ -4030,6 +4067,7 @@ function islandNamesFrom(imports) {
|
|||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
exports.NativeCompileError = void 0;
|
exports.NativeCompileError = void 0;
|
||||||
exports.generateNative = generateNative;
|
exports.generateNative = generateNative;
|
||||||
|
const syntax_1 = require("@wrnexus/syntax");
|
||||||
class NativeCompileError extends Error {
|
class NativeCompileError extends Error {
|
||||||
constructor(message) {
|
constructor(message) {
|
||||||
super(message);
|
super(message);
|
||||||
@@ -4095,12 +4133,12 @@ function expression(value) {
|
|||||||
function textJsx(value) {
|
function textJsx(value) {
|
||||||
const pieces = [];
|
const pieces = [];
|
||||||
let last = 0;
|
let last = 0;
|
||||||
for (const match of value.matchAll(/\{([^{}]+)\}/g)) {
|
for (const segment of (0, syntax_1.extractInterpolations)(value)) {
|
||||||
if (match.index > last)
|
if (segment.start > last)
|
||||||
pieces.push(value.slice(last, match.index));
|
pieces.push(value.slice(last, segment.start));
|
||||||
const expr = match[1].trim();
|
const expr = segment.expression;
|
||||||
pieces.push(expr.startsWith("t:") ? `{${JSON.stringify(expr.slice(2).trim())}}` : `{${expr}}`);
|
pieces.push(expr.startsWith("t:") ? `{${JSON.stringify(expr.slice(2).trim())}}` : `{${expr}}`);
|
||||||
last = match.index + match[0].length;
|
last = segment.end;
|
||||||
}
|
}
|
||||||
pieces.push(value.slice(last));
|
pieces.push(value.slice(last));
|
||||||
return pieces.join("").replace(/([<>])/g, (char) => (char === "<" ? "<" : ">"));
|
return pieces.join("").replace(/([<>])/g, (char) => (char === "<" ? "<" : ">"));
|
||||||
@@ -6190,6 +6228,26 @@ function expandStructuredStateDeclarations(lines, unit) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
function formatStructuredPropDeclaration(value, unit, depth, printWidth) {
|
||||||
|
const match = /^([A-Za-z_$][\w$]*\??\s*(?::\s*[^=]+?)?\s*=\s*)([\[{][\s\S]*)$/.exec(value);
|
||||||
|
if (!match)
|
||||||
|
return null;
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(match[2].trim());
|
||||||
|
const compact = JSON.stringify(parsed);
|
||||||
|
const indentation = unit.repeat(depth);
|
||||||
|
if (indentation.length + match[1].length + compact.length <= printWidth)
|
||||||
|
return null;
|
||||||
|
const jsonLines = JSON.stringify(parsed, null, unit).split("\n");
|
||||||
|
return [
|
||||||
|
`${indentation}${match[1]}${jsonLines[0]}`,
|
||||||
|
...jsonLines.slice(1).map((jsonLine) => `${indentation}${jsonLine}`),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
function formatWrnPass(source, options = {}) {
|
function formatWrnPass(source, options = {}) {
|
||||||
const unit = options.insertSpaces === false ? "\t" : " ".repeat(options.tabSize ?? 4);
|
const unit = options.insertSpaces === false ? "\t" : " ".repeat(options.tabSize ?? 4);
|
||||||
const printWidth = options.printWidth ?? 100;
|
const printWidth = options.printWidth ?? 100;
|
||||||
@@ -6245,6 +6303,12 @@ function formatWrnPass(source, options = {}) {
|
|||||||
index += 1;
|
index += 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
const structuredProp = formatStructuredPropDeclaration(value, unit, codeDepth + htmlDepth + controlDepth, printWidth);
|
||||||
|
if (structuredProp) {
|
||||||
|
output.push(...structuredProp);
|
||||||
|
index += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
const leadingClosingBraces = countLeadingClosingBraces(value);
|
const leadingClosingBraces = countLeadingClosingBraces(value);
|
||||||
const closesControlBlock = isControlBlockClose(value);
|
const closesControlBlock = isControlBlockClose(value);
|
||||||
const continuesControlBlock = isControlBlockMiddle(value);
|
const continuesControlBlock = isControlBlockMiddle(value);
|
||||||
@@ -6325,7 +6389,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|||||||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
||||||
};
|
};
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
exports.stripRuntimeFunctionModifiers = exports.parseStructuredImports = exports.parseStoreLifecycle = exports.parseStateDeclarations = exports.parseRuntimeFunctions = exports.parsePersist = exports.parseOutputs = exports.parseComputedDeclarations = exports.supportsSyntaxFeature = exports.diagnosticSummary = exports.sliceSource = exports.createSourceRange = exports.WRN_SYNTAX_FEATURES = exports.WRN_SYNTAX_VERSION = exports.positionAt = exports.isRuntimeTarget = exports.isHydrationStrategy = exports.formatDiagnostic = exports.diagnosticFromError = exports.diagnose = exports.containsReadonlyPropMutation = exports.classifyParseError = exports.assertValidAst = exports.validateTypedInitializer = exports.runtimeTypeOf = exports.inferredRuntimeType = exports.eraseFunctionTypes = exports.VOID_ELEMENTS = exports.ParseError = exports.parseHtmlView = exports.parse = exports.formatWrn = exports.skipLiteralOrComment = exports.LexError = exports.Lexer = void 0;
|
exports.stripRuntimeFunctionModifiers = exports.parseStructuredImports = exports.parseStoreLifecycle = exports.parseStateDeclarations = exports.parseRuntimeFunctions = exports.parsePersist = exports.parseOutputs = exports.parseComputedDeclarations = exports.supportsSyntaxFeature = exports.diagnosticSummary = exports.sliceSource = exports.createSourceRange = exports.WRN_SYNTAX_FEATURES = exports.WRN_SYNTAX_VERSION = exports.positionAt = exports.isRuntimeTarget = exports.isHydrationStrategy = exports.formatDiagnostic = exports.diagnosticFromError = exports.diagnose = exports.containsReadonlyPropMutation = exports.classifyParseError = exports.assertValidAst = exports.validateTypedInitializer = exports.runtimeTypeOf = exports.inferredRuntimeType = exports.eraseFunctionTypes = exports.extractInterpolations = exports.VOID_ELEMENTS = exports.ParseError = exports.parseHtmlView = exports.parse = exports.formatWrn = exports.skipLiteralOrComment = exports.LexError = exports.Lexer = void 0;
|
||||||
var tokenizer_ts_1 = require("./tokenizer.js");
|
var tokenizer_ts_1 = require("./tokenizer.js");
|
||||||
Object.defineProperty(exports, "Lexer", { enumerable: true, get: function () { return tokenizer_ts_1.Lexer; } });
|
Object.defineProperty(exports, "Lexer", { enumerable: true, get: function () { return tokenizer_ts_1.Lexer; } });
|
||||||
Object.defineProperty(exports, "LexError", { enumerable: true, get: function () { return tokenizer_ts_1.LexError; } });
|
Object.defineProperty(exports, "LexError", { enumerable: true, get: function () { return tokenizer_ts_1.LexError; } });
|
||||||
@@ -6337,6 +6401,8 @@ Object.defineProperty(exports, "parse", { enumerable: true, get: function () { r
|
|||||||
Object.defineProperty(exports, "parseHtmlView", { enumerable: true, get: function () { return parser_ts_1.parseHtmlView; } });
|
Object.defineProperty(exports, "parseHtmlView", { enumerable: true, get: function () { return parser_ts_1.parseHtmlView; } });
|
||||||
Object.defineProperty(exports, "ParseError", { enumerable: true, get: function () { return parser_ts_1.ParseError; } });
|
Object.defineProperty(exports, "ParseError", { enumerable: true, get: function () { return parser_ts_1.ParseError; } });
|
||||||
Object.defineProperty(exports, "VOID_ELEMENTS", { enumerable: true, get: function () { return parser_ts_1.VOID_ELEMENTS; } });
|
Object.defineProperty(exports, "VOID_ELEMENTS", { enumerable: true, get: function () { return parser_ts_1.VOID_ELEMENTS; } });
|
||||||
|
var interpolation_ts_1 = require("./interpolation.js");
|
||||||
|
Object.defineProperty(exports, "extractInterpolations", { enumerable: true, get: function () { return interpolation_ts_1.extractInterpolations; } });
|
||||||
var types_ts_1 = require("./types.js");
|
var types_ts_1 = require("./types.js");
|
||||||
Object.defineProperty(exports, "eraseFunctionTypes", { enumerable: true, get: function () { return types_ts_1.eraseFunctionTypes; } });
|
Object.defineProperty(exports, "eraseFunctionTypes", { enumerable: true, get: function () { return types_ts_1.eraseFunctionTypes; } });
|
||||||
Object.defineProperty(exports, "inferredRuntimeType", { enumerable: true, get: function () { return types_ts_1.inferredRuntimeType; } });
|
Object.defineProperty(exports, "inferredRuntimeType", { enumerable: true, get: function () { return types_ts_1.inferredRuntimeType; } });
|
||||||
@@ -6370,6 +6436,50 @@ Object.defineProperty(exports, "parseStoreLifecycle", { enumerable: true, get: f
|
|||||||
Object.defineProperty(exports, "parseStructuredImports", { enumerable: true, get: function () { return v060_ts_1.parseStructuredImports; } });
|
Object.defineProperty(exports, "parseStructuredImports", { enumerable: true, get: function () { return v060_ts_1.parseStructuredImports; } });
|
||||||
Object.defineProperty(exports, "stripRuntimeFunctionModifiers", { enumerable: true, get: function () { return v060_ts_1.stripRuntimeFunctionModifiers; } });
|
Object.defineProperty(exports, "stripRuntimeFunctionModifiers", { enumerable: true, get: function () { return v060_ts_1.stripRuntimeFunctionModifiers; } });
|
||||||
|
|
||||||
|
},
|
||||||
|
"packages/syntax/src/interpolation.ts": function (module, exports, require, __filename, __dirname) {
|
||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.extractInterpolations = extractInterpolations;
|
||||||
|
/** Extract top-level `{...}` expressions while preserving nested object/array literals. */
|
||||||
|
function extractInterpolations(value) {
|
||||||
|
const segments = [];
|
||||||
|
let index = 0;
|
||||||
|
while (index < value.length) {
|
||||||
|
if (value[index] !== "{") {
|
||||||
|
index++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const start = index++;
|
||||||
|
let depth = 1;
|
||||||
|
let quote = null;
|
||||||
|
while (index < value.length && depth > 0) {
|
||||||
|
const char = value[index];
|
||||||
|
if (quote) {
|
||||||
|
if (char === "\\" && index + 1 < value.length)
|
||||||
|
index += 2;
|
||||||
|
else {
|
||||||
|
if (char === quote)
|
||||||
|
quote = null;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (char === '"' || char === "'" || char === "`")
|
||||||
|
quote = char;
|
||||||
|
else if (char === "{")
|
||||||
|
depth++;
|
||||||
|
else if (char === "}")
|
||||||
|
depth--;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
if (depth === 0) {
|
||||||
|
segments.push({ expression: value.slice(start + 1, index - 1).trim(), start, end: index });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return segments;
|
||||||
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
"packages/syntax/src/parser.ts": function (module, exports, require, __filename, __dirname) {
|
"packages/syntax/src/parser.ts": function (module, exports, require, __filename, __dirname) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
// WRN editor language server source hash: 3c6060ff9db332cf1dc01a467d795fb2d002300400072a4b87437c48d61ab7f9
|
// WRN editor language server source hash: 5258b3e76cec47df752d4bb886fbd57a3f3c4af9ca9b6b2bf6742c8d78025ff1
|
||||||
// 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;
|
||||||
@@ -23,12 +23,14 @@ var __toESM = (mod, isNodeMode, target) => {
|
|||||||
}
|
}
|
||||||
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
||||||
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
||||||
for (let key of __getOwnPropNames(mod))
|
if (mod && typeof mod === "object" || typeof mod === "function") {
|
||||||
if (!__hasOwnProp.call(to, key))
|
for (let key of __getOwnPropNames(mod))
|
||||||
__defProp(to, key, {
|
if (!__hasOwnProp.call(to, key))
|
||||||
get: __accessProp.bind(mod, key),
|
__defProp(to, key, {
|
||||||
enumerable: true
|
get: __accessProp.bind(mod, key),
|
||||||
});
|
enumerable: true
|
||||||
|
});
|
||||||
|
}
|
||||||
if (canCache)
|
if (canCache)
|
||||||
cache.set(mod, to);
|
cache.set(mod, to);
|
||||||
return to;
|
return to;
|
||||||
@@ -66,7 +68,7 @@ var __export = (target, all) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/typescript.js
|
// node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/typescript.js
|
||||||
var require_typescript = __commonJS((exports2, module2) => {
|
var require_typescript = __commonJS(function(exports2, module2) {
|
||||||
var __dirname = "E:\\WireJS\\node_modules\\.bun\\typescript@6.0.3\\node_modules\\typescript\\lib", __filename = "E:\\WireJS\\node_modules\\.bun\\typescript@6.0.3\\node_modules\\typescript\\lib\\typescript.js";
|
var __dirname = "E:\\WireJS\\node_modules\\.bun\\typescript@6.0.3\\node_modules\\typescript\\lib", __filename = "E:\\WireJS\\node_modules\\.bun\\typescript@6.0.3\\node_modules\\typescript\\lib\\typescript.js";
|
||||||
/*! *****************************************************************************
|
/*! *****************************************************************************
|
||||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
@@ -169514,7 +169516,7 @@ Additional information: BADCLIENT: Bad error code, ${badCode} not found in range
|
|||||||
});
|
});
|
||||||
|
|
||||||
// node_modules/.bun/@vscode+l10n@0.0.18/node_modules/@vscode/l10n/dist/main.js
|
// node_modules/.bun/@vscode+l10n@0.0.18/node_modules/@vscode/l10n/dist/main.js
|
||||||
var require_main = __commonJS((exports2, module2) => {
|
var require_main = __commonJS(function(exports2, module2) {
|
||||||
var __defProp2 = Object.defineProperty;
|
var __defProp2 = Object.defineProperty;
|
||||||
var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor;
|
var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor;
|
||||||
var __getOwnPropNames2 = Object.getOwnPropertyNames;
|
var __getOwnPropNames2 = Object.getOwnPropertyNames;
|
||||||
@@ -169658,9 +169660,9 @@ var require_main = __commonJS((exports2, module2) => {
|
|||||||
// packages/language-server/src/server.ts
|
// packages/language-server/src/server.ts
|
||||||
var exports_server = {};
|
var exports_server = {};
|
||||||
__export(exports_server, {
|
__export(exports_server, {
|
||||||
isApiReferenceAt: () => isApiReferenceAt,
|
apiCallCompletions: () => apiCallCompletions,
|
||||||
apiCallHover: () => apiCallHover,
|
apiCallHover: () => apiCallHover,
|
||||||
apiCallCompletions: () => apiCallCompletions
|
isApiReferenceAt: () => isApiReferenceAt
|
||||||
});
|
});
|
||||||
module.exports = __toCommonJS(exports_server);
|
module.exports = __toCommonJS(exports_server);
|
||||||
|
|
||||||
@@ -170720,6 +170722,26 @@ function expandStructuredStateDeclarations(lines, unit) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
function formatStructuredPropDeclaration(value, unit, depth, printWidth) {
|
||||||
|
const match = /^([A-Za-z_$][\w$]*\??\s*(?::\s*[^=]+?)?\s*=\s*)([\[{][\s\S]*)$/.exec(value);
|
||||||
|
if (!match)
|
||||||
|
return null;
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(match[2].trim());
|
||||||
|
const compact = JSON.stringify(parsed);
|
||||||
|
const indentation = unit.repeat(depth);
|
||||||
|
if (indentation.length + match[1].length + compact.length <= printWidth)
|
||||||
|
return null;
|
||||||
|
const jsonLines = JSON.stringify(parsed, null, unit).split(`
|
||||||
|
`);
|
||||||
|
return [
|
||||||
|
`${indentation}${match[1]}${jsonLines[0]}`,
|
||||||
|
...jsonLines.slice(1).map((jsonLine) => `${indentation}${jsonLine}`)
|
||||||
|
];
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
function formatWrnPass(source, options = {}) {
|
function formatWrnPass(source, options = {}) {
|
||||||
const unit = options.insertSpaces === false ? "\t" : " ".repeat(options.tabSize ?? 4);
|
const unit = options.insertSpaces === false ? "\t" : " ".repeat(options.tabSize ?? 4);
|
||||||
const printWidth = options.printWidth ?? 100;
|
const printWidth = options.printWidth ?? 100;
|
||||||
@@ -170776,6 +170798,12 @@ function formatWrnPass(source, options = {}) {
|
|||||||
index += 1;
|
index += 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
const structuredProp = formatStructuredPropDeclaration(value, unit, codeDepth + htmlDepth + controlDepth, printWidth);
|
||||||
|
if (structuredProp) {
|
||||||
|
output.push(...structuredProp);
|
||||||
|
index += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
const leadingClosingBraces = countLeadingClosingBraces(value);
|
const leadingClosingBraces = countLeadingClosingBraces(value);
|
||||||
const closesControlBlock = isControlBlockClose(value);
|
const closesControlBlock = isControlBlockClose(value);
|
||||||
const continuesControlBlock = isControlBlockMiddle(value);
|
const continuesControlBlock = isControlBlockMiddle(value);
|
||||||
@@ -172391,6 +172419,44 @@ function parseHtmlView(src, pos) {
|
|||||||
const nodes = parseNodeList("root");
|
const nodes = parseNodeList("root");
|
||||||
return { nodes, endPos: i };
|
return { nodes, endPos: i };
|
||||||
}
|
}
|
||||||
|
// packages/syntax/src/interpolation.ts
|
||||||
|
function extractInterpolations(value) {
|
||||||
|
const segments = [];
|
||||||
|
let index = 0;
|
||||||
|
while (index < value.length) {
|
||||||
|
if (value[index] !== "{") {
|
||||||
|
index++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const start = index++;
|
||||||
|
let depth = 1;
|
||||||
|
let quote = null;
|
||||||
|
while (index < value.length && depth > 0) {
|
||||||
|
const char = value[index];
|
||||||
|
if (quote) {
|
||||||
|
if (char === "\\" && index + 1 < value.length)
|
||||||
|
index += 2;
|
||||||
|
else {
|
||||||
|
if (char === quote)
|
||||||
|
quote = null;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (char === '"' || char === "'" || char === "`")
|
||||||
|
quote = char;
|
||||||
|
else if (char === "{")
|
||||||
|
depth++;
|
||||||
|
else if (char === "}")
|
||||||
|
depth--;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
if (depth === 0) {
|
||||||
|
segments.push({ expression: value.slice(start + 1, index - 1).trim(), start, end: index });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return segments;
|
||||||
|
}
|
||||||
// packages/syntax/src/diagnostics.ts
|
// packages/syntax/src/diagnostics.ts
|
||||||
function stripAsciiControlAndSpace(value) {
|
function stripAsciiControlAndSpace(value) {
|
||||||
let result = "";
|
let result = "";
|
||||||
@@ -172988,7 +173054,7 @@ function runtimeNamespace(runtime) {
|
|||||||
return `__wrn_${runtime}`;
|
return `__wrn_${runtime}`;
|
||||||
}
|
}
|
||||||
function functionDeclaration(fn) {
|
function functionDeclaration(fn) {
|
||||||
const params = fn.parameters.map((param) => `${param.name}${param.optional ? "?" : ""}${param.valueType ? `: ${param.valueType}` : param.name === "event" ? ": CustomEvent<any> & { target: HTMLElement }" : ": any"}${param.default ? ` = ${param.default}` : ""}`).join(", ");
|
const params = fn.parameters.map((param) => `${param.name}${param.optional ? "?" : ""}${param.valueType ? `: ${param.valueType}` : param.name === "event" ? ": Event & { target: HTMLElement }" : ": any"}${param.default ? ` = ${param.default}` : ""}`).join(", ");
|
||||||
return `export ${fn.async ? "async " : ""}function ${fn.name}(${params})${fn.returnType ? `: ${fn.returnType}` : ""} {${fn.body}}`;
|
return `export ${fn.async ? "async " : ""}function ${fn.name}(${params})${fn.returnType ? `: ${fn.returnType}` : ""} {${fn.body}}`;
|
||||||
}
|
}
|
||||||
function retainedImports(ast) {
|
function retainedImports(ast) {
|
||||||
@@ -173048,6 +173114,27 @@ var RESERVED_BINDING_NAMES = new Set([
|
|||||||
function safeBindingName(name) {
|
function safeBindingName(name) {
|
||||||
return /^[A-Za-z_$][\w$]*$/.test(name) && !RESERVED_BINDING_NAMES.has(name);
|
return /^[A-Za-z_$][\w$]*$/.test(name) && !RESERVED_BINDING_NAMES.has(name);
|
||||||
}
|
}
|
||||||
|
function safeViewExpression(expression, reservedProps) {
|
||||||
|
if (!reservedProps.size)
|
||||||
|
return expression;
|
||||||
|
const scanner = import_typescript.default.createScanner(import_typescript.default.ScriptTarget.Latest, false, import_typescript.default.LanguageVariant.Standard, expression);
|
||||||
|
let result = "";
|
||||||
|
let copied = 0;
|
||||||
|
for (let token = scanner.scan();token !== import_typescript.default.SyntaxKind.EndOfFileToken; token = scanner.scan()) {
|
||||||
|
const start = scanner.getTokenPos();
|
||||||
|
const end = scanner.getTextPos();
|
||||||
|
const text = scanner.getTokenText();
|
||||||
|
if (!reservedProps.has(text))
|
||||||
|
continue;
|
||||||
|
const previous = expression.slice(0, start).trimEnd().at(-1);
|
||||||
|
const following = expression.slice(end).trimStart().at(0);
|
||||||
|
if (previous === "." || following === ":")
|
||||||
|
continue;
|
||||||
|
result += expression.slice(copied, start) + `props.${text}`;
|
||||||
|
copied = end;
|
||||||
|
}
|
||||||
|
return result + expression.slice(copied);
|
||||||
|
}
|
||||||
function virtualTypeScriptModule(source, filePath = "component.wrn", appRoot = findAppRoot(filePath)) {
|
function virtualTypeScriptModule(source, filePath = "component.wrn", appRoot = findAppRoot(filePath)) {
|
||||||
const ast = parse(source);
|
const ast = parse(source);
|
||||||
const chunks = [];
|
const chunks = [];
|
||||||
@@ -173103,6 +173190,8 @@ function virtualTypeScriptModule(source, filePath = "component.wrn", appRoot = f
|
|||||||
append(`declare const api: { ${apiType} };`);
|
append(`declare const api: { ${apiType} };`);
|
||||||
append(`declare const props: Readonly<${ast.name}Props>;`);
|
append(`declare const props: Readonly<${ast.name}Props>;`);
|
||||||
append("declare const refs: Record<string, Element | null>;");
|
append("declare const refs: Record<string, Element | null>;");
|
||||||
|
append("declare const toast: ((message: string, options?: Record<string, unknown>) => unknown) & { success(message: string, options?: Record<string, unknown>): unknown; error(message: string, options?: Record<string, unknown>): unknown; danger(message: string, options?: Record<string, unknown>): unknown; warning(message: string, options?: Record<string, unknown>): unknown; info(message: string, options?: Record<string, unknown>): unknown; dismiss(id: string | number): void; clear(): void };");
|
||||||
|
append("declare function useFetch(path: string, method?: string | { method?: string; query?: unknown; params?: unknown; body?: unknown; data?: unknown }, input?: unknown): Promise<any>;");
|
||||||
append(ast.kind === "global-store" || ast.kind === "page-store" ? storeContract(ast) : componentContract(ast));
|
append(ast.kind === "global-store" || ast.kind === "page-store" ? storeContract(ast) : componentContract(ast));
|
||||||
append(importedWrnDeclarations(ast, filePath, appRoot));
|
append(importedWrnDeclarations(ast, filePath, appRoot));
|
||||||
const sharedNames = new Set(ast.runtimeFunctions.filter((fn) => fn.runtime === "shared").map((fn) => fn.name));
|
const sharedNames = new Set(ast.runtimeFunctions.filter((fn) => fn.runtime === "shared").map((fn) => fn.name));
|
||||||
@@ -173119,6 +173208,53 @@ ${sharedAliases}`);
|
|||||||
append(functionDeclaration(fn), fn.source);
|
append(functionDeclaration(fn), fn.source);
|
||||||
append("}");
|
append("}");
|
||||||
}
|
}
|
||||||
|
const viewFunctions = new Map;
|
||||||
|
for (const fn of ast.runtimeFunctions) {
|
||||||
|
if (fn.runtime !== "server")
|
||||||
|
viewFunctions.set(fn.name, fn.runtime);
|
||||||
|
}
|
||||||
|
for (const [name, runtime] of viewFunctions) {
|
||||||
|
append(`declare const ${name}: typeof ${runtimeNamespace(runtime)}.${name};`);
|
||||||
|
}
|
||||||
|
let bindingIndex = 0;
|
||||||
|
const reservedProps = new Set(ast.props.map((prop) => prop.name).filter((name) => !safeBindingName(name)));
|
||||||
|
const appendViewBindings = (nodes, locals) => {
|
||||||
|
for (const node of nodes) {
|
||||||
|
if (node.type === "element") {
|
||||||
|
for (const attr of node.attrs) {
|
||||||
|
const expressions = attr.event ? [attr.value] : extractInterpolations(attr.value).map((segment) => segment.expression);
|
||||||
|
for (const expression of expressions) {
|
||||||
|
if (!expression.trim())
|
||||||
|
continue;
|
||||||
|
const declarations = [
|
||||||
|
...[...locals].map((name) => `declare const ${name}: any;`),
|
||||||
|
...attr.event ? [
|
||||||
|
"declare const payload: any;",
|
||||||
|
"declare const event: Event & { target: HTMLElement };"
|
||||||
|
] : []
|
||||||
|
].join(" ");
|
||||||
|
append(`namespace __wrn_view_${bindingIndex++} { ${declarations} void (${safeViewExpression(expression, reservedProps)}); }`, attr.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
appendViewBindings(node.children, locals);
|
||||||
|
} else if (node.type === "if") {
|
||||||
|
for (const branch of node.branches) {
|
||||||
|
if (branch.cond)
|
||||||
|
append(`namespace __wrn_view_${bindingIndex++} { void (${safeViewExpression(branch.cond, reservedProps)}); }`, branch.cond);
|
||||||
|
appendViewBindings(branch.body, locals);
|
||||||
|
}
|
||||||
|
} else if (node.type === "each") {
|
||||||
|
append(`namespace __wrn_view_${bindingIndex++} { void (${safeViewExpression(node.list, reservedProps)}); }`, node.list);
|
||||||
|
const nested = new Set(locals);
|
||||||
|
nested.add(node.item);
|
||||||
|
if (node.index)
|
||||||
|
nested.add(node.index);
|
||||||
|
appendViewBindings(node.body, nested);
|
||||||
|
appendViewBindings(node.empty, locals);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
appendViewBindings(ast.view, new Set);
|
||||||
return {
|
return {
|
||||||
ast,
|
ast,
|
||||||
fileName: filePath.replace(/\.wrn$/i, ".wrn.ts"),
|
fileName: filePath.replace(/\.wrn$/i, ".wrn.ts"),
|
||||||
@@ -173224,7 +173360,7 @@ function componentUsageDiagnostics(source, ast, filePath, appRoot) {
|
|||||||
const shape = shapes.get(node.tag);
|
const shape = shapes.get(node.tag);
|
||||||
if (!shape)
|
if (!shape)
|
||||||
return;
|
return;
|
||||||
const attributes = new Map(node.attrs.filter((attr) => !attr.event).map((attr) => [attr.name, attr]));
|
const attributes = new Map(node.attrs.filter((attr) => !attr.event).map((attr) => [attr.name.startsWith("bind:") ? attr.name.slice(5) : attr.name, attr]));
|
||||||
const outputNames = new Set(shape.outputs.map((output) => output.name));
|
const outputNames = new Set(shape.outputs.map((output) => output.name));
|
||||||
const position = lineAt(source, `<${node.tag}`);
|
const position = lineAt(source, `<${node.tag}`);
|
||||||
for (const prop of shape.props) {
|
for (const prop of shape.props) {
|
||||||
@@ -173261,7 +173397,8 @@ function componentUsageDiagnostics(source, ast, filePath, appRoot) {
|
|||||||
}
|
}
|
||||||
if (/^(?:class|id|style|slot|data-|aria-)/.test(attr.name) || attr.name === "attrs")
|
if (/^(?:class|id|style|slot|data-|aria-)/.test(attr.name) || attr.name === "attrs")
|
||||||
continue;
|
continue;
|
||||||
const prop = known.get(attr.name);
|
const propName = attr.name.startsWith("bind:") ? attr.name.slice(5) : attr.name;
|
||||||
|
const prop = known.get(propName);
|
||||||
if (!prop) {
|
if (!prop) {
|
||||||
diagnostics.push({
|
diagnostics.push({
|
||||||
code: "WRN-COMPONENT-UNKNOWN-PROP",
|
code: "WRN-COMPONENT-UNKNOWN-PROP",
|
||||||
|
|||||||
@@ -20,6 +20,20 @@ test("preserves nested prop defaults while formatting", () => {
|
|||||||
assert.equal(formatWrn(formatted, { insertSpaces: true, tabSize: 2 }), formatted);
|
assert.equal(formatWrn(formatted, { insertSpaces: true, tabSize: 2 }), formatted);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("formats large typed JSON prop defaults with the bundled formatter", () => {
|
||||||
|
const source = `component Catalog {
|
||||||
|
props {
|
||||||
|
categories: unknown[] = [{"label":"Platform & Core","apps":[{"label":"Home","href":"/home"},{"label":"SSO","href":"/sso"}]},{"label":"Sales","apps":[{"label":"CRM","href":"/crm"}]}]
|
||||||
|
}
|
||||||
|
view { <div></div> }
|
||||||
|
}`;
|
||||||
|
const formatted = formatWrn(source, { insertSpaces: true, tabSize: 2, printWidth: 70 });
|
||||||
|
|
||||||
|
assert.match(formatted, /categories: unknown\[\] = \[\n \{/);
|
||||||
|
assert.match(formatted, /"apps": \[\n \{/);
|
||||||
|
assert.equal(formatWrn(formatted, { insertSpaces: true, tabSize: 2, printWidth: 70 }), formatted);
|
||||||
|
});
|
||||||
|
|
||||||
test("formats native JSON state values with readable indentation", () => {
|
test("formats native JSON state values with readable indentation", () => {
|
||||||
const source = `component Footer {
|
const source = `component Footer {
|
||||||
state footerItems = [{"label":"Accessibility","href":"/accessibility","value":"accessibility"},{"label":"Privacy","href":"/privacy","value":"privacy"}]
|
state footerItems = [{"label":"Accessibility","href":"/accessibility","value":"accessibility"},{"label":"Privacy","href":"/privacy","value":"privacy"}]
|
||||||
|
|||||||
+2
-2
@@ -55,7 +55,7 @@
|
|||||||
"generate:ui-visual": "node scripts/check-ui-visual-contract.mjs --write",
|
"generate:ui-visual": "node scripts/check-ui-visual-contract.mjs --write",
|
||||||
"sbom": "node scripts/generate-sbom.mjs",
|
"sbom": "node scripts/generate-sbom.mjs",
|
||||||
"benchmark:framework": "node --experimental-transform-types scripts/benchmark-framework.mjs --write",
|
"benchmark:framework": "node --experimental-transform-types scripts/benchmark-framework.mjs --write",
|
||||||
"check:production": "bun run check:workspace && bun run check:generated-types && bun run check:public-api && bun run check:ui-visual && bun run validate:0.8 && bun run security:framework && bun run security:asvs && bun run check:editor-compiler && bun run check:editor-language-server && bun run check:editor-extension && bun run check && bun run test:examples",
|
"check:production": "bun run check:workspace && bun run check:generated-types && bun run check:public-api && bun run check:ui-visual && bun run validate:0.8 && bun run security:framework && bun run security:asvs && bun run check:editor-compiler && bun run check:editor-language-server && bun run check:editor-extension && bun run check && bun run test:examples && bun run test:services && bun run test:editor",
|
||||||
"validate:staging": "node --experimental-transform-types scripts/test-package-integrity.mjs",
|
"validate:staging": "node --experimental-transform-types scripts/test-package-integrity.mjs",
|
||||||
"stage:packages": "bun run scripts/publish-packages.ts",
|
"stage:packages": "bun run scripts/publish-packages.ts",
|
||||||
"test:staged-consumers": "node scripts/test-staged-consumers.mjs",
|
"test:staged-consumers": "node scripts/test-staged-consumers.mjs",
|
||||||
@@ -70,7 +70,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^10.0.1",
|
"@eslint/js": "^10.0.1",
|
||||||
"@types/bun": "^1.3.14",
|
"@types/bun": "^1.4.0",
|
||||||
"@types/react": "^19.2.18",
|
"@types/react": "^19.2.18",
|
||||||
"@types/react-dom": "^19.2.4",
|
"@types/react-dom": "^19.2.4",
|
||||||
"eslint": "^10.8.1",
|
"eslint": "^10.8.1",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/captcha",
|
"name": "@wrnexus/captcha",
|
||||||
"version": "0.8.11",
|
"version": "0.8.14",
|
||||||
"description": "First-class CAPTCHA challenges, providers, verification guards, page gates, and WRNexusJS UI.",
|
"description": "First-class CAPTCHA challenges, providers, verification guards, page gates, and WRNexusJS UI.",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
import { describe, expect, test } from "bun:test";
|
||||||
|
import {
|
||||||
|
captchaContext,
|
||||||
|
captchaResultResponse,
|
||||||
|
captchaTokenFrom,
|
||||||
|
verifyCaptchaOrThrow,
|
||||||
|
} from "../src/helpers.ts";
|
||||||
|
|
||||||
|
describe("CAPTCHA helper boundaries", () => {
|
||||||
|
test("extracts JSON request fallbacks without consuming the caller's request", async () => {
|
||||||
|
const request = new Request("https://example.test/verify", {
|
||||||
|
method: "POST",
|
||||||
|
headers: { "content-type": "application/json" },
|
||||||
|
body: JSON.stringify({ captchaToken: 12345 }),
|
||||||
|
});
|
||||||
|
expect(await captchaTokenFrom(request)).toBe("12345");
|
||||||
|
expect(await request.json()).toEqual({ captchaToken: 12345 });
|
||||||
|
});
|
||||||
|
|
||||||
|
test("turns verification failures into stable errors and no-store responses", async () => {
|
||||||
|
const provider = {
|
||||||
|
name: "custom" as const,
|
||||||
|
client: { responseField: "captchaToken" },
|
||||||
|
verify: async () => ({
|
||||||
|
success: false as const,
|
||||||
|
code: "expired",
|
||||||
|
message: "Try again",
|
||||||
|
provider: "custom" as const,
|
||||||
|
action: "login",
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
await expect(
|
||||||
|
verifyCaptchaOrThrow(provider, { providerToken: "x", action: "login" }),
|
||||||
|
).rejects.toThrow("WRN-CAPTCHA-EXPIRED: Try again");
|
||||||
|
const response = captchaResultResponse({
|
||||||
|
success: false,
|
||||||
|
code: "invalid",
|
||||||
|
provider: "custom",
|
||||||
|
action: "login",
|
||||||
|
});
|
||||||
|
expect(response.status).toBe(403);
|
||||||
|
expect(response.headers.get("cache-control")).toBe("no-store");
|
||||||
|
expect(
|
||||||
|
captchaContext({
|
||||||
|
locals: { captcha: { success: true, provider: "custom", action: "login" } },
|
||||||
|
} as never),
|
||||||
|
).toEqual({ success: true, provider: "custom", action: "login" });
|
||||||
|
expect(captchaContext({ locals: { captcha: "forged" } } as never)).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("does not convert provider transport failures into successful verification", async () => {
|
||||||
|
const provider = {
|
||||||
|
name: "custom" as const,
|
||||||
|
client: { responseField: "captchaToken" },
|
||||||
|
verify: async () => {
|
||||||
|
throw new Error("provider timeout");
|
||||||
|
},
|
||||||
|
};
|
||||||
|
await expect(
|
||||||
|
verifyCaptchaOrThrow(provider, { providerToken: "x", action: "checkout" }),
|
||||||
|
).rejects.toThrow("provider timeout");
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/cli",
|
"name": "@wrnexus/cli",
|
||||||
"version": "0.8.60",
|
"version": "0.8.64",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"exports": {
|
"exports": {
|
||||||
|
|||||||
@@ -113,6 +113,11 @@ Update options: --dry-run previews changes; --no-verify skips post-update check/
|
|||||||
async function main(): Promise<void> {
|
async function main(): Promise<void> {
|
||||||
const [command, ...rest] = process.argv.slice(2);
|
const [command, ...rest] = process.argv.slice(2);
|
||||||
|
|
||||||
|
if (command === "--version" || command === "-v" || command === "version") {
|
||||||
|
console.log(currentCliVersion());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
notifyIfUpdateAvailable(currentCliVersion(), command);
|
notifyIfUpdateAvailable(currentCliVersion(), command);
|
||||||
|
|
||||||
switch (command) {
|
switch (command) {
|
||||||
|
|||||||
@@ -72,7 +72,9 @@ export function createTestPlan(appRoot: string, args: string[]): TestCommandPlan
|
|||||||
const watch = args.includes("--watch");
|
const watch = args.includes("--watch");
|
||||||
const profile = args.find((value) => value.startsWith("--profile="))?.slice(10) || "test";
|
const profile = args.find((value) => value.startsWith("--profile="))?.slice(10) || "test";
|
||||||
const setupSource = join(import.meta.dir, "test-setup.ts");
|
const setupSource = join(import.meta.dir, "test-setup.ts");
|
||||||
const setupModule = existsSync(setupSource) ? setupSource : join(import.meta.dir, "test-setup.js");
|
const setupModule = existsSync(setupSource)
|
||||||
|
? setupSource
|
||||||
|
: join(import.meta.dir, "test-setup.js");
|
||||||
const shard = args.find((value) => value.startsWith("--shard="))?.slice(8);
|
const shard = args.find((value) => value.startsWith("--shard="))?.slice(8);
|
||||||
const browsers = (args.find((value) => value.startsWith("--browsers="))?.slice(11) ?? "chromium")
|
const browsers = (args.find((value) => value.startsWith("--browsers="))?.slice(11) ?? "chromium")
|
||||||
.split(",")
|
.split(",")
|
||||||
|
|||||||
@@ -63,14 +63,16 @@ const execFileAsync = promisify(execFile);
|
|||||||
|
|
||||||
/** Resolve every installed WRNexus dependency independently and in parallel. */
|
/** Resolve every installed WRNexus dependency independently and in parallel. */
|
||||||
export async function latestPackageVersions(names: string[]): Promise<Map<string, string>> {
|
export async function latestPackageVersions(names: string[]): Promise<Map<string, string>> {
|
||||||
const npm = process.platform === "win32" ? "npm.cmd" : "npm";
|
|
||||||
const unique = [...new Set(names.filter((name) => name.startsWith("@wrnexus/")))];
|
const unique = [...new Set(names.filter((name) => name.startsWith("@wrnexus/")))];
|
||||||
const entries = await Promise.all(
|
const entries = await Promise.all(
|
||||||
unique.map(async (name) => {
|
unique.map(async (name) => {
|
||||||
try {
|
try {
|
||||||
const { stdout } = await execFileAsync(npm, ["view", name, "version", "--json"], {
|
const command = process.platform === "win32" ? (process.env.ComSpec ?? "cmd.exe") : "npm";
|
||||||
encoding: "utf8",
|
const args =
|
||||||
});
|
process.platform === "win32"
|
||||||
|
? ["/d", "/s", "/c", "npm", "view", name, "version", "--json"]
|
||||||
|
: ["view", name, "version", "--json"];
|
||||||
|
const { stdout } = await execFileAsync(command, args, { encoding: "utf8" });
|
||||||
const parsed = JSON.parse(stdout.trim()) as string | string[];
|
const parsed = JSON.parse(stdout.trim()) as string | string[];
|
||||||
const version = Array.isArray(parsed) ? parsed.at(-1) : parsed;
|
const version = Array.isArray(parsed) ? parsed.at(-1) : parsed;
|
||||||
return typeof version === "string" && /^\d+\.\d+\.\d+/.test(version)
|
return typeof version === "string" && /^\d+\.\d+\.\d+/.test(version)
|
||||||
@@ -1274,6 +1276,13 @@ export async function runUpdate(dir: string, args: string[]): Promise<void> {
|
|||||||
? new Map<string, string>()
|
? new Map<string, string>()
|
||||||
: await latestPackageVersions(dependencyNames);
|
: await latestPackageVersions(dependencyNames);
|
||||||
|
|
||||||
|
if (!versionArg && dependencyNames.length > 0 && packageVersions.size === 0) {
|
||||||
|
throw new Error(
|
||||||
|
`Unable to resolve any of ${new Set(dependencyNames).size} installed WRNexus package ` +
|
||||||
|
`version(s) from npm. Check the @wrnexus registry and authentication before retrying.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
console.log(`\n ⚡ wrnexus update → migrations ${target}${dryRun ? " (dry run)" : ""}`);
|
console.log(`\n ⚡ wrnexus update → migrations ${target}${dryRun ? " (dry run)" : ""}`);
|
||||||
if (!versionArg) {
|
if (!versionArg) {
|
||||||
console.log(
|
console.log(
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
import { afterEach, expect, test } from "bun:test";
|
import { afterEach, expect, test } from "bun:test";
|
||||||
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
||||||
import { tmpdir } from "node:os";
|
import { tmpdir } from "node:os";
|
||||||
import { join } from "node:path";
|
import { join, resolve } from "node:path";
|
||||||
import { compareVersions, notifyIfUpdateAvailable } from "../src/update-notifier.ts";
|
import {
|
||||||
|
compareVersions,
|
||||||
|
currentCliVersion,
|
||||||
|
notifyIfUpdateAvailable,
|
||||||
|
} from "../src/update-notifier.ts";
|
||||||
|
|
||||||
const originalCache = process.env.WRNEXUS_UPDATE_CACHE;
|
const originalCache = process.env.WRNEXUS_UPDATE_CACHE;
|
||||||
|
|
||||||
@@ -35,3 +39,21 @@ test("cached update checks suggest the exact upgrade command", () => {
|
|||||||
rmSync(root, { recursive: true, force: true });
|
rmSync(root, { recursive: true, force: true });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("--version prints the package version outside a WrNexus workspace", () => {
|
||||||
|
const root = mkdtempSync(join(tmpdir(), "wrnexus-version-"));
|
||||||
|
try {
|
||||||
|
const result = Bun.spawnSync({
|
||||||
|
cmd: [process.execPath, resolve(import.meta.dir, "../src/index.ts"), "--version"],
|
||||||
|
cwd: root,
|
||||||
|
env: { ...process.env, WRNEXUS_NO_UPDATE_CHECK: "1" },
|
||||||
|
stdout: "pipe",
|
||||||
|
stderr: "pipe",
|
||||||
|
});
|
||||||
|
expect(result.exitCode).toBe(0);
|
||||||
|
expect(result.stdout.toString().trim()).toBe(currentCliVersion());
|
||||||
|
expect(result.stderr.toString()).toBe("");
|
||||||
|
} finally {
|
||||||
|
rmSync(root, { recursive: true, force: true });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/compiler",
|
"name": "@wrnexus/compiler",
|
||||||
"version": "0.8.21",
|
"version": "0.8.22",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"exports": {
|
"exports": {
|
||||||
|
|||||||
@@ -3175,7 +3175,7 @@ function __wrnProp(v: unknown): string {
|
|||||||
function renderPageComponentAttr(
|
function renderPageComponentAttr(
|
||||||
attr: Attr,
|
attr: Attr,
|
||||||
dynamicExpressions: string[],
|
dynamicExpressions: string[],
|
||||||
reactive: PageReactive | null,
|
_reactive: PageReactive | null,
|
||||||
): string {
|
): string {
|
||||||
if (attr.event) {
|
if (attr.event) {
|
||||||
return ` ${componentEventAttribute(attr.name)}="${attrEscape(attr.value)}"`;
|
return ` ${componentEventAttribute(attr.name)}="${attrEscape(attr.value)}"`;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { Attr, PageAst, ViewNode } from "@wrnexus/syntax";
|
import { extractInterpolations, type Attr, type PageAst, type ViewNode } from "@wrnexus/syntax";
|
||||||
|
|
||||||
export class NativeCompileError extends Error {
|
export class NativeCompileError extends Error {
|
||||||
constructor(message: string) {
|
constructor(message: string) {
|
||||||
@@ -68,11 +68,11 @@ function expression(value: string): string | null {
|
|||||||
function textJsx(value: string): string {
|
function textJsx(value: string): string {
|
||||||
const pieces: string[] = [];
|
const pieces: string[] = [];
|
||||||
let last = 0;
|
let last = 0;
|
||||||
for (const match of value.matchAll(/\{([^{}]+)\}/g)) {
|
for (const segment of extractInterpolations(value)) {
|
||||||
if (match.index! > last) pieces.push(value.slice(last, match.index));
|
if (segment.start > last) pieces.push(value.slice(last, segment.start));
|
||||||
const expr = match[1]!.trim();
|
const expr = segment.expression;
|
||||||
pieces.push(expr.startsWith("t:") ? `{${JSON.stringify(expr.slice(2).trim())}}` : `{${expr}}`);
|
pieces.push(expr.startsWith("t:") ? `{${JSON.stringify(expr.slice(2).trim())}}` : `{${expr}}`);
|
||||||
last = match.index! + match[0].length;
|
last = segment.end;
|
||||||
}
|
}
|
||||||
pieces.push(value.slice(last));
|
pieces.push(value.slice(last));
|
||||||
return pieces.join("").replace(/([<>])/g, (char) => (char === "<" ? "<" : ">"));
|
return pieces.join("").replace(/([<>])/g, (char) => (char === "<" ? "<" : ">"));
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/csr",
|
"name": "@wrnexus/csr",
|
||||||
"version": "0.8.33",
|
"version": "0.8.35",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"exports": {
|
"exports": {
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ const CONTROLLER_LOADER = String.raw`
|
|||||||
if (!componentControllerPromise) {
|
if (!componentControllerPromise) {
|
||||||
componentControllerPromise = new Promise(function (resolve, reject) {
|
componentControllerPromise = new Promise(function (resolve, reject) {
|
||||||
var script = document.createElement("script");
|
var script = document.createElement("script");
|
||||||
script.src = componentControllerUrl;
|
script.src = trustedScriptURL(componentControllerUrl);
|
||||||
script.defer = true;
|
script.defer = true;
|
||||||
script.onload = resolve;
|
script.onload = resolve;
|
||||||
script.onerror = reject;
|
script.onerror = reject;
|
||||||
|
|||||||
@@ -26,6 +26,40 @@ export const REACTIVE_RUNTIME = String.raw`
|
|||||||
var behaviorObserver;
|
var behaviorObserver;
|
||||||
var clientModuleCache = new Map();
|
var clientModuleCache = new Map();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Production enables require-trusted-types-for 'script'. Every HTML write
|
||||||
|
* below uses compiler-emitted template markup (or the explicit data-html
|
||||||
|
* escape hatch), and controller URLs are generated by the framework. Route
|
||||||
|
* those known sinks through the policy allowed by the default security
|
||||||
|
* preset instead of letting the browser reject hydration midway through a
|
||||||
|
* state update.
|
||||||
|
*/
|
||||||
|
var wrnexusTrustedTypesPolicy = null;
|
||||||
|
if (window.trustedTypes && typeof window.trustedTypes.createPolicy === "function") {
|
||||||
|
try {
|
||||||
|
wrnexusTrustedTypesPolicy = window.trustedTypes.createPolicy("wrnexus", {
|
||||||
|
createHTML: function (value) { return value; },
|
||||||
|
createScriptURL: function (value) { return value; }
|
||||||
|
});
|
||||||
|
} catch (_) {
|
||||||
|
wrnexusTrustedTypesPolicy = window.trustedTypes.defaultPolicy || null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function trustedHTML(value) {
|
||||||
|
var source = value == null ? "" : String(value);
|
||||||
|
return wrnexusTrustedTypesPolicy
|
||||||
|
? wrnexusTrustedTypesPolicy.createHTML(source)
|
||||||
|
: source;
|
||||||
|
}
|
||||||
|
|
||||||
|
function trustedScriptURL(value) {
|
||||||
|
var source = value == null ? "" : String(value);
|
||||||
|
return wrnexusTrustedTypesPolicy
|
||||||
|
? wrnexusTrustedTypesPolicy.createScriptURL(source)
|
||||||
|
: source;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Two builtin chains the runtime reaches for constantly. Aliasing them is
|
* Two builtin chains the runtime reaches for constantly. Aliasing them is
|
||||||
* not only shorter: hasOwn keeps prototype keys from reading as data, and
|
* not only shorter: hasOwn keeps prototype keys from reading as data, and
|
||||||
@@ -234,8 +268,21 @@ export const REACTIVE_RUNTIME = String.raw`
|
|||||||
Array.prototype.forEach.call(rules || [], function (rule) {
|
Array.prototype.forEach.call(rules || [], function (rule) {
|
||||||
var cssText = rule.cssText || "";
|
var cssText = rule.cssText || "";
|
||||||
var match;
|
var match;
|
||||||
var pattern = /var\(\s*(--wrn-[A-Za-z0-9_-]+)/g;
|
// Only inspect declarations that can affect the current document. A
|
||||||
while ((match = pattern.exec(cssText))) referenced[match[1]] = true;
|
// component stylesheet may contain optional variants that are not
|
||||||
|
// rendered on this page, and variables with fallbacks are intentionally
|
||||||
|
// optional rather than missing theme tokens.
|
||||||
|
if (rule.selectorText) {
|
||||||
|
try {
|
||||||
|
if (!document.querySelector(rule.selectorText)) return;
|
||||||
|
} catch (_) {
|
||||||
|
// Keep inspecting selectors that the DOM implementation cannot parse.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var pattern = /var\(\s*(--wrn-[A-Za-z0-9_-]+)\s*(,)?/g;
|
||||||
|
while ((match = pattern.exec(cssText))) {
|
||||||
|
if (!match[2]) referenced[match[1]] = true;
|
||||||
|
}
|
||||||
if (rule.style) {
|
if (rule.style) {
|
||||||
Array.prototype.forEach.call(rule.style, function (property) {
|
Array.prototype.forEach.call(rule.style, function (property) {
|
||||||
if (String(property).indexOf("--wrn-") === 0) declared[property] = true;
|
if (String(property).indexOf("--wrn-") === 0) declared[property] = true;
|
||||||
@@ -1818,7 +1865,7 @@ export const REACTIVE_RUNTIME = String.raw`
|
|||||||
var next = markup == null ? "" : String(markup);
|
var next = markup == null ? "" : String(markup);
|
||||||
|
|
||||||
if (htmlNode.innerHTML !== next) {
|
if (htmlNode.innerHTML !== next) {
|
||||||
htmlNode.innerHTML = next;
|
htmlNode.innerHTML = trustedHTML(next);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
runHtml();
|
runHtml();
|
||||||
@@ -2002,7 +2049,7 @@ export const REACTIVE_RUNTIME = String.raw`
|
|||||||
}
|
}
|
||||||
|
|
||||||
function clearControlContent() {
|
function clearControlContent() {
|
||||||
if (!rangeEnd) { block.innerHTML = ""; return; }
|
if (!rangeEnd) { block.innerHTML = trustedHTML(""); return; }
|
||||||
while (block.nextSibling && block.nextSibling !== rangeEnd) {
|
while (block.nextSibling && block.nextSibling !== rangeEnd) {
|
||||||
block.parentNode.removeChild(block.nextSibling);
|
block.parentNode.removeChild(block.nextSibling);
|
||||||
}
|
}
|
||||||
@@ -2010,7 +2057,7 @@ export const REACTIVE_RUNTIME = String.raw`
|
|||||||
|
|
||||||
function appendControlContent(markup, locals) {
|
function appendControlContent(markup, locals) {
|
||||||
var template = document.createElement("template");
|
var template = document.createElement("template");
|
||||||
template.innerHTML = markup || "";
|
template.innerHTML = trustedHTML(markup || "");
|
||||||
var fragment = template.content;
|
var fragment = template.content;
|
||||||
var elements = toArray(fragment.childNodes).filter(function (node) {
|
var elements = toArray(fragment.childNodes).filter(function (node) {
|
||||||
return node.nodeType === 1;
|
return node.nodeType === 1;
|
||||||
@@ -2399,7 +2446,7 @@ export const REACTIVE_RUNTIME = String.raw`
|
|||||||
var markup = value == null ? "" : String(value);
|
var markup = value == null ? "" : String(value);
|
||||||
|
|
||||||
if (node.innerHTML !== markup) {
|
if (node.innerHTML !== markup) {
|
||||||
node.innerHTML = markup;
|
node.innerHTML = trustedHTML(markup);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -62,6 +62,13 @@ test("split runtime hydrates a controller only from the controller asset", () =>
|
|||||||
expect(win.document.activeElement).toBe(buttons[1]);
|
expect(win.document.activeElement).toBe(buttons[1]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("production hydration uses Trusted Types for HTML and controller URLs", () => {
|
||||||
|
const runtime = getReactiveRuntime();
|
||||||
|
expect(runtime).toContain('createPolicy("wrnexus"');
|
||||||
|
expect(runtime).toContain('template.innerHTML = trustedHTML(markup || "")');
|
||||||
|
expect(runtime).toContain("script.src = trustedScriptURL(componentControllerUrl)");
|
||||||
|
});
|
||||||
|
|
||||||
test("a page without controller markers does not request the controller asset", () => {
|
test("a page without controller markers does not request the controller asset", () => {
|
||||||
const win = mount(
|
const win = mount(
|
||||||
`<main data-scope="count: 1"><span>{count}</span></main>`,
|
`<main data-scope="count: 1"><span>{count}</span></main>`,
|
||||||
@@ -1081,6 +1088,38 @@ test("development runtime accepts component-local and inline wrn variables", ()
|
|||||||
expect(warnings).toHaveLength(0);
|
expect(warnings).toHaveLength(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("development runtime ignores fallback and inactive component variables", () => {
|
||||||
|
const win = new Window() as unknown as Window & Record<string, unknown>;
|
||||||
|
win.document.head.innerHTML =
|
||||||
|
`<style>.visible { color: var(--wrn-optional, red); } ` +
|
||||||
|
`.not-rendered { color: var(--wrn-inactive); }</style>`;
|
||||||
|
win.document.body.innerHTML = `<div class="visible" data-scope=""></div>`;
|
||||||
|
(globalThis as Record<string, unknown>).window = win;
|
||||||
|
(globalThis as Record<string, unknown>).document = win.document;
|
||||||
|
(globalThis as Record<string, unknown>).location = win.location;
|
||||||
|
(globalThis as Record<string, unknown>).NodeFilter = (
|
||||||
|
win as unknown as { NodeFilter: unknown }
|
||||||
|
).NodeFilter;
|
||||||
|
(globalThis as Record<string, unknown>).MutationObserver = (
|
||||||
|
win as unknown as { MutationObserver: unknown }
|
||||||
|
).MutationObserver;
|
||||||
|
(globalThis as Record<string, unknown>).CustomEvent = (
|
||||||
|
win as unknown as { CustomEvent: unknown }
|
||||||
|
).CustomEvent;
|
||||||
|
const warnings: unknown[][] = [];
|
||||||
|
const originalWarn = console.warn;
|
||||||
|
console.warn = (...args: unknown[]) => warnings.push(args);
|
||||||
|
try {
|
||||||
|
(0, eval)(getReactiveRuntime(true));
|
||||||
|
(
|
||||||
|
win as unknown as { __wrnexusHydrateScopes?: (root: unknown) => void }
|
||||||
|
).__wrnexusHydrateScopes?.(win.document);
|
||||||
|
} finally {
|
||||||
|
console.warn = originalWarn;
|
||||||
|
}
|
||||||
|
expect(warnings).toHaveLength(0);
|
||||||
|
});
|
||||||
|
|
||||||
test("production runtime strips development diagnostics", () => {
|
test("production runtime strips development diagnostics", () => {
|
||||||
const production = getReactiveRuntime();
|
const production = getReactiveRuntime();
|
||||||
expect(production).not.toContain("WRN-DEV-");
|
expect(production).not.toContain("WRN-DEV-");
|
||||||
|
|||||||
@@ -15,9 +15,17 @@ function fakeDb() {
|
|||||||
|
|
||||||
test("seed helpers parameterize object rows and removals", async () => {
|
test("seed helpers parameterize object rows and removals", async () => {
|
||||||
const { db, calls } = fakeDb();
|
const { db, calls } = fakeDb();
|
||||||
await addSeedData(db, [{ code: "free", credits: 10 }, { code: "pro", credits: 20 }], "plans", {
|
await addSeedData(
|
||||||
conflict: "ignore",
|
db,
|
||||||
});
|
[
|
||||||
|
{ code: "free", credits: 10 },
|
||||||
|
{ code: "pro", credits: 20 },
|
||||||
|
],
|
||||||
|
"plans",
|
||||||
|
{
|
||||||
|
conflict: "ignore",
|
||||||
|
},
|
||||||
|
);
|
||||||
await removeSeedData(db, { code: "free" }, "plans");
|
await removeSeedData(db, { code: "free" }, "plans");
|
||||||
expect(calls[0]).toEqual({
|
expect(calls[0]).toEqual({
|
||||||
sql: "INSERT OR IGNORE INTO plans (code, credits) VALUES (?, ?)",
|
sql: "INSERT OR IGNORE INTO plans (code, credits) VALUES (?, ?)",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/dev-server",
|
"name": "@wrnexus/dev-server",
|
||||||
"version": "0.8.52",
|
"version": "0.8.56",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"exports": {
|
"exports": {
|
||||||
@@ -25,6 +25,7 @@
|
|||||||
"@wrnexus/uploader": "workspace:*",
|
"@wrnexus/uploader": "workspace:*",
|
||||||
"@wrnexus/plugin": "workspace:*",
|
"@wrnexus/plugin": "workspace:*",
|
||||||
"@wrnexus/queue": "workspace:*",
|
"@wrnexus/queue": "workspace:*",
|
||||||
|
"@wrnexus/react": "workspace:*",
|
||||||
"@wrnexus/store": "workspace:*",
|
"@wrnexus/store": "workspace:*",
|
||||||
"@wrnexus/security": "workspace:*",
|
"@wrnexus/security": "workspace:*",
|
||||||
"@wrnexus/observability": "workspace:*",
|
"@wrnexus/observability": "workspace:*",
|
||||||
|
|||||||
@@ -367,6 +367,12 @@ export async function startServer(opts: ServeOptions): Promise<RunningServer> {
|
|||||||
externalRoutes: pluginContributions.routes,
|
externalRoutes: pluginContributions.routes,
|
||||||
middlewareFiles: pluginContributions.middleware,
|
middlewareFiles: pluginContributions.middleware,
|
||||||
});
|
});
|
||||||
|
// UI and plugin components are intentionally registered application-wide;
|
||||||
|
// using them without a source import is not an implicit-import diagnostic.
|
||||||
|
setCompileImportOptions(appRoot, {
|
||||||
|
...importConfig,
|
||||||
|
globalComponents: router.components.map((component) => component.name),
|
||||||
|
});
|
||||||
const styleEntry = opts.styleEntry ?? null;
|
const styleEntry = opts.styleEntry ?? null;
|
||||||
|
|
||||||
const devToolbarConfig = resolveDevToolbarConfig(mode, opts.devToolbar);
|
const devToolbarConfig = resolveDevToolbarConfig(mode, opts.devToolbar);
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ interface CompileImportOptions {
|
|||||||
mode: ImportMode;
|
mode: ImportMode;
|
||||||
aliases: Record<string, string>;
|
aliases: Record<string, string>;
|
||||||
autoImport: boolean;
|
autoImport: boolean;
|
||||||
|
globalComponents: Set<string>;
|
||||||
}
|
}
|
||||||
const compileImportOptions = new Map<string, CompileImportOptions>();
|
const compileImportOptions = new Map<string, CompileImportOptions>();
|
||||||
const warnedImportDiagnostics = new Set<string>();
|
const warnedImportDiagnostics = new Set<string>();
|
||||||
@@ -104,12 +105,18 @@ export function setDevCompilerPipeline(pipeline: DevCompilerPipeline | null): vo
|
|||||||
|
|
||||||
export function setCompileImportOptions(
|
export function setCompileImportOptions(
|
||||||
appRoot: string,
|
appRoot: string,
|
||||||
options: { mode?: ImportMode; aliases?: Record<string, string>; autoImport?: boolean } = {},
|
options: {
|
||||||
|
mode?: ImportMode;
|
||||||
|
aliases?: Record<string, string>;
|
||||||
|
autoImport?: boolean;
|
||||||
|
globalComponents?: Iterable<string>;
|
||||||
|
} = {},
|
||||||
): void {
|
): void {
|
||||||
compileImportOptions.set(resolve(appRoot), {
|
compileImportOptions.set(resolve(appRoot), {
|
||||||
mode: options.mode ?? "compatible",
|
mode: options.mode ?? "compatible",
|
||||||
aliases: { "@": "./app", ...(options.aliases ?? {}) },
|
aliases: { "@": "./app", ...(options.aliases ?? {}) },
|
||||||
autoImport: options.autoImport ?? true,
|
autoImport: options.autoImport ?? true,
|
||||||
|
globalComponents: new Set(options.globalComponents ?? []),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,11 +148,18 @@ function importOptionsHash(file: string): string {
|
|||||||
mode: "compatible" as const,
|
mode: "compatible" as const,
|
||||||
aliases: { "@": "./app" },
|
aliases: { "@": "./app" },
|
||||||
autoImport: true,
|
autoImport: true,
|
||||||
|
globalComponents: new Set<string>(),
|
||||||
};
|
};
|
||||||
const aliases = Object.fromEntries(
|
const aliases = Object.fromEntries(
|
||||||
Object.entries(options.aliases).sort(([left], [right]) => left.localeCompare(right)),
|
Object.entries(options.aliases).sort(([left], [right]) => left.localeCompare(right)),
|
||||||
);
|
);
|
||||||
return hashPath(JSON.stringify({ ...options, aliases }));
|
return hashPath(
|
||||||
|
JSON.stringify({
|
||||||
|
...options,
|
||||||
|
aliases,
|
||||||
|
globalComponents: [...options.globalComponents].sort(),
|
||||||
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Island bundles already built this dev session, keyed by resolved source. */
|
/** Island bundles already built this dev session, keyed by resolved source. */
|
||||||
@@ -493,7 +507,8 @@ function validateConfiguredImports(_source: string, ast: PageAst, file: string):
|
|||||||
"Transition",
|
"Transition",
|
||||||
]);
|
]);
|
||||||
const missing = [...usedComponents].filter(
|
const missing = [...usedComponents].filter(
|
||||||
(name) => !compilerBuiltins.has(name) && !imported.has(name),
|
(name) =>
|
||||||
|
!compilerBuiltins.has(name) && !options.globalComponents.has(name) && !imported.has(name),
|
||||||
);
|
);
|
||||||
if (ast.layoutIsSymbol && ast.layout && !imported.has(ast.layout)) missing.push(ast.layout);
|
if (ast.layoutIsSymbol && ast.layout && !imported.has(ast.layout)) missing.push(ast.layout);
|
||||||
if (!missing.length) return;
|
if (!missing.length) return;
|
||||||
|
|||||||
@@ -1739,6 +1739,15 @@ export function createHandlers(deps: RuntimeDeps): Handlers {
|
|||||||
// Props may carry `{t:key}` i18n markers — resolve them for the active
|
// Props may carry `{t:key}` i18n markers — resolve them for the active
|
||||||
// language before handing them to the component.
|
// language before handing them to the component.
|
||||||
const props = resolveTProps(parseComponentProps(attrStr!), translate);
|
const props = resolveTProps(parseComponentProps(attrStr!), translate);
|
||||||
|
// Client control templates retain reactive expressions (for example
|
||||||
|
// `metrics="{metrics}"`) because their parent state is not available
|
||||||
|
// while we pre-render the inert branch metadata. Do not feed those
|
||||||
|
// expression strings into typed component coercion. Rendering with the
|
||||||
|
// component defaults creates the real child boundary; the bridged prop
|
||||||
|
// binding synchronizes the live value when the branch is instantiated.
|
||||||
|
for (const [key, value] of Object.entries(props)) {
|
||||||
|
if (/^\{[\s\S]*\}$/.test(value) && !/^\{t:/.test(value)) delete props[key];
|
||||||
|
}
|
||||||
if (normalizedName === "languageswitcher" && deps.i18n) {
|
if (normalizedName === "languageswitcher" && deps.i18n) {
|
||||||
props.locales ??= JSON.stringify(
|
props.locales ??= JSON.stringify(
|
||||||
deps.i18n.langs.map((locale) => ({
|
deps.i18n.langs.map((locale) => ({
|
||||||
@@ -1777,7 +1786,10 @@ export function createHandlers(deps: RuntimeDeps): Handlers {
|
|||||||
(match) => ` ${match[1]}`,
|
(match) => ` ${match[1]}`,
|
||||||
).join("");
|
).join("");
|
||||||
const bridged = propBindings
|
const bridged = propBindings
|
||||||
? rendered.replace(/(<[A-Za-z][A-Za-z0-9-]*\b[^>]*\bdata-scope="[^"]*")/, `$1${propBindings}`)
|
? rendered.replace(
|
||||||
|
/(<[A-Za-z][A-Za-z0-9-]*\b[^>]*\bdata-scope="[^"]*")/,
|
||||||
|
`$1${propBindings}`,
|
||||||
|
)
|
||||||
: rendered;
|
: rendered;
|
||||||
result += await renderComponents(bridged, translate, language, depth + 1);
|
result += await renderComponents(bridged, translate, language, depth + 1);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -2679,7 +2691,12 @@ export function parseComponentProps(attrStr: string): Record<string, string> {
|
|||||||
const props: Record<string, string> = {};
|
const props: Record<string, string> = {};
|
||||||
for (const m of attrStr.matchAll(/([A-Za-z_][\w-]*)(?:="([^"]*)")?/g)) {
|
for (const m of attrStr.matchAll(/([A-Za-z_][\w-]*)(?:="([^"]*)")?/g)) {
|
||||||
const key = m[1]!;
|
const key = m[1]!;
|
||||||
if (key === "data-component") continue;
|
if (
|
||||||
|
key === "data-component" ||
|
||||||
|
key.startsWith("data-wrn-bind-") ||
|
||||||
|
key.startsWith("data-wrn-prop-bind-")
|
||||||
|
)
|
||||||
|
continue;
|
||||||
props[key] = decodeHtmlEntities(m[2] ?? "");
|
props[key] = decodeHtmlEntities(m[2] ?? "");
|
||||||
}
|
}
|
||||||
return props;
|
return props;
|
||||||
|
|||||||
@@ -90,6 +90,58 @@ test("a component in an initially hidden client branch is server-prepared for in
|
|||||||
expect(branches[0].body).not.toContain("data-component=");
|
expect(branches[0].body).not.toContain("data-component=");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("typed components in client branches use defaults until reactive props are available", async () => {
|
||||||
|
const root = mkdtempSync(join(tmpdir(), "wrnexus-component-reactive-branch-"));
|
||||||
|
roots.push(root);
|
||||||
|
const app = join(root, "app");
|
||||||
|
mkdirSync(join(app, "pages"), { recursive: true });
|
||||||
|
mkdirSync(join(app, "components"), { recursive: true });
|
||||||
|
writeFileSync(join(app, "pages/index.ts"), "export default () => '';\n");
|
||||||
|
writeFileSync(join(app, "components/Panel.wrn"), "component Panel { view { <section /> } }\n");
|
||||||
|
const marker = "["items","{items}"]";
|
||||||
|
const definition = Buffer.from(
|
||||||
|
JSON.stringify([
|
||||||
|
{
|
||||||
|
cond: "open",
|
||||||
|
body: `<div data-component="Panel" items="{items}" visible="{true}" data-wrn-prop-bind-0="${marker}"></div>`,
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
"utf8",
|
||||||
|
).toString("base64");
|
||||||
|
let observed: Record<string, string> | undefined;
|
||||||
|
|
||||||
|
const handlers = createHandlers({
|
||||||
|
mode: "development",
|
||||||
|
hmr: false,
|
||||||
|
router: buildRouter(app),
|
||||||
|
loadModule: async (file) =>
|
||||||
|
basename(file) === "Panel.wrn"
|
||||||
|
? {
|
||||||
|
render: (props: Record<string, string>) => {
|
||||||
|
observed = props;
|
||||||
|
return '<section data-scope="items: [], visible: false" data-wrn-scope="e30="></section>';
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
default: () =>
|
||||||
|
`<template data-wrn-if="${definition}"></template><template data-wrn-control-end></template>`,
|
||||||
|
},
|
||||||
|
getMiddleware: async () => [],
|
||||||
|
assets: { serve: async () => null },
|
||||||
|
} satisfies RuntimeDeps);
|
||||||
|
|
||||||
|
const response = await handlers.fetch(new Request("https://example.test/"), {
|
||||||
|
upgrade: () => false,
|
||||||
|
});
|
||||||
|
const html = await response!.text();
|
||||||
|
expect(observed).toEqual({});
|
||||||
|
const encoded = /data-wrn-if="([A-Za-z0-9+/=]+)"/.exec(html)?.[1];
|
||||||
|
const branches = JSON.parse(Buffer.from(encoded!, "base64").toString("utf8"));
|
||||||
|
expect(branches[0].body).toContain("<section");
|
||||||
|
expect(branches[0].body).toContain("data-wrn-prop-bind-0");
|
||||||
|
expect(branches[0].body).not.toContain("data-component=");
|
||||||
|
});
|
||||||
|
|
||||||
test("SSR carries a parent prop binding onto the rendered child scope", async () => {
|
test("SSR carries a parent prop binding onto the rendered child scope", async () => {
|
||||||
const root = mkdtempSync(join(tmpdir(), "wrnexus-component-prop-"));
|
const root = mkdtempSync(join(tmpdir(), "wrnexus-component-prop-"));
|
||||||
roots.push(root);
|
roots.push(root);
|
||||||
@@ -97,7 +149,10 @@ test("SSR carries a parent prop binding onto the rendered child scope", async ()
|
|||||||
mkdirSync(join(app, "pages"), { recursive: true });
|
mkdirSync(join(app, "pages"), { recursive: true });
|
||||||
mkdirSync(join(app, "components"), { recursive: true });
|
mkdirSync(join(app, "components"), { recursive: true });
|
||||||
writeFileSync(join(app, "pages/index.ts"), "export default () => '';\n");
|
writeFileSync(join(app, "pages/index.ts"), "export default () => '';\n");
|
||||||
writeFileSync(join(app, "components/Child.wrn"), "component Child { props { value = 0 } view { <b>{value}</b> } }\n");
|
writeFileSync(
|
||||||
|
join(app, "components/Child.wrn"),
|
||||||
|
"component Child { props { value = 0 } view { <b>{value}</b> } }\n",
|
||||||
|
);
|
||||||
const marker = "["value","{count}"]";
|
const marker = "["value","{count}"]";
|
||||||
const handlers = createHandlers({
|
const handlers = createHandlers({
|
||||||
mode: "development",
|
mode: "development",
|
||||||
@@ -106,11 +161,16 @@ test("SSR carries a parent prop binding onto the rendered child scope", async ()
|
|||||||
loadModule: async (file) =>
|
loadModule: async (file) =>
|
||||||
basename(file) === "Child.wrn"
|
basename(file) === "Child.wrn"
|
||||||
? { render: () => '<div data-scope="value: 1" data-wrn-scope="e30="><b>1</b></div>' }
|
? { render: () => '<div data-scope="value: 1" data-wrn-scope="e30="><b>1</b></div>' }
|
||||||
: { default: () => `<div data-component="Child" value="1" data-wrn-prop-bind-0="${marker}"></div>` },
|
: {
|
||||||
|
default: () =>
|
||||||
|
`<div data-component="Child" value="1" data-wrn-prop-bind-0="${marker}"></div>`,
|
||||||
|
},
|
||||||
getMiddleware: async () => [],
|
getMiddleware: async () => [],
|
||||||
assets: { serve: async () => null },
|
assets: { serve: async () => null },
|
||||||
} satisfies RuntimeDeps);
|
} satisfies RuntimeDeps);
|
||||||
const response = await handlers.fetch(new Request("https://example.test/"), { upgrade: () => false });
|
const response = await handlers.fetch(new Request("https://example.test/"), {
|
||||||
|
upgrade: () => false,
|
||||||
|
});
|
||||||
const html = await response!.text();
|
const html = await response!.text();
|
||||||
expect(html).toContain(`data-wrn-prop-bind-0="${marker}"`);
|
expect(html).toContain(`data-wrn-prop-bind-0="${marker}"`);
|
||||||
expect(html).not.toContain('data-component="Child"');
|
expect(html).not.toContain('data-component="Child"');
|
||||||
|
|||||||
@@ -71,6 +71,13 @@ test("compiler-native reactive elements do not require application imports", ()
|
|||||||
expect(() => compileWrnArtifacts(page, 5)).not.toThrow();
|
expect(() => compileWrnArtifacts(page, 5)).not.toThrow();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("globally registered plugin components do not require source imports", () => {
|
||||||
|
const { root, page } = fixture();
|
||||||
|
writeFileSync(page, "page Home { view { <SignIn /> } }");
|
||||||
|
setCompileImportOptions(root, { mode: "explicit", globalComponents: ["SignIn"] });
|
||||||
|
expect(() => compileWrnArtifacts(page, 6)).not.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
test("component examples in comments do not require imports", () => {
|
test("component examples in comments do not require imports", () => {
|
||||||
const { root, page } = fixture();
|
const { root, page } = fixture();
|
||||||
writeFileSync(
|
writeFileSync(
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/dev-toolbar",
|
"name": "@wrnexus/dev-toolbar",
|
||||||
"version": "0.8.13",
|
"version": "0.8.16",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
import { expect, test } from "bun:test";
|
||||||
|
import { createServerIssue, issueFromError } from "../../src/server/issues.ts";
|
||||||
|
|
||||||
|
test("server issues have stable fingerprints and retain actionable error context", () => {
|
||||||
|
const input = {
|
||||||
|
ruleId: "server/query",
|
||||||
|
category: "server" as const,
|
||||||
|
severity: "warning" as const,
|
||||||
|
title: "Slow query",
|
||||||
|
message: "Query exceeded budget",
|
||||||
|
pathname: "/orders",
|
||||||
|
source: { file: "app/api/orders.ts", line: 12, column: 4 },
|
||||||
|
};
|
||||||
|
const first = createServerIssue(input);
|
||||||
|
const second = createServerIssue(input);
|
||||||
|
expect(first.id).not.toBe(second.id);
|
||||||
|
expect(first.fingerprint).toBe(second.fingerprint);
|
||||||
|
expect(first.metadata?.pathname).toBe("/orders");
|
||||||
|
|
||||||
|
const error = issueFromError(new Error("database offline"), { pathname: "/orders" });
|
||||||
|
expect(error.severity).toBe("error");
|
||||||
|
expect(error.message).toBe("database offline");
|
||||||
|
expect(error.metadata?.stack).toContain("database offline");
|
||||||
|
expect(error.recommendation).toContain("stack trace");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("non-Error throws are normalized without losing caller context", () => {
|
||||||
|
const issue = issueFromError(
|
||||||
|
{ reason: "offline" },
|
||||||
|
{
|
||||||
|
ruleId: "server/dependency",
|
||||||
|
title: "Dependency failed",
|
||||||
|
pathname: "/health",
|
||||||
|
source: { file: "app/api/health.ts", line: 4 },
|
||||||
|
},
|
||||||
|
);
|
||||||
|
expect(issue.ruleId).toBe("server/dependency");
|
||||||
|
expect(issue.title).toBe("Dependency failed");
|
||||||
|
expect(issue.message).toBe("[object Object]");
|
||||||
|
expect(issue.fingerprint).toContain("app/api/health.ts:4:0");
|
||||||
|
});
|
||||||
@@ -117,7 +117,7 @@ export function defineSealedMailCredentials(options: SealedMailCredentialsOption
|
|||||||
const secret = process.env[env];
|
const secret = process.env[env];
|
||||||
if (!secret)
|
if (!secret)
|
||||||
throw new Error(`${env} is not set; it is required to seal mail credentials at rest.`);
|
throw new Error(`${env} is not set; it is required to seal mail credentials at rest.`);
|
||||||
let length = 0;
|
let length: number;
|
||||||
try {
|
try {
|
||||||
length = atob(secret).length;
|
length = atob(secret).length;
|
||||||
} catch {
|
} catch {
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
# @wrnexus/metering
|
||||||
|
|
||||||
|
Framework-native entitlement catalogs, credit packs, and usage metering for WrNexus applications.
|
||||||
|
|
||||||
|
The package keeps policy separate from persistence: applications provide a `MeterStore`, while the metering facade validates unit amounts and reports insufficient balances separately from storage faults. All amounts are positive safe integers except explicit adjustments, which may be positive or negative but never zero.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { defineEntitlements, defineMeter, definePacks } from "@wrnexus/metering";
|
||||||
|
|
||||||
|
const entitlements = defineEntitlements({
|
||||||
|
plans: () => [
|
||||||
|
{ code: "free", name: "Free", features: [], allowance: 10 },
|
||||||
|
{ code: "pro", name: "Pro", features: ["exports"], allowance: 1_000 },
|
||||||
|
],
|
||||||
|
subscriptionFor: async (subjectId) => subscriptions.planFor(subjectId),
|
||||||
|
fallback: "free",
|
||||||
|
});
|
||||||
|
|
||||||
|
const packs = definePacks([
|
||||||
|
{ code: "starter", units: 100 },
|
||||||
|
{ code: "plus", units: 500 },
|
||||||
|
]);
|
||||||
|
|
||||||
|
const meter = defineMeter({ store });
|
||||||
|
|
||||||
|
if (await entitlements.enabled("user-1", "exports")) {
|
||||||
|
const result = await meter.reserve("user-1", 1, "export report");
|
||||||
|
if (!result.ok) console.error(result.reason);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
- `defineEntitlements(options)` resolves a subject's plan, features, and allowance from a server-owned catalog, with an explicit fallback plan.
|
||||||
|
- `definePacks(entries)` creates an immutable, prototype-safe lookup of purchasable unit packs. Clients select a pack code rather than supplying an amount.
|
||||||
|
- `defineMeter(options)` exposes `balance`, `reserve`, `grant`, `purchase`, `refund`, and `adjust` operations over an application-provided store.
|
||||||
|
|
||||||
|
Meter operations return `{ ok: true }` on success or `{ ok: false, reason, fault? }` on refusal. A result with `fault: true` identifies an underlying storage error; use `onFault` for operational reporting without exposing exception-based control flow to callers.
|
||||||
@@ -37,15 +37,15 @@ function createQueue(options?: QueueOptions): Queue;
|
|||||||
|
|
||||||
#### `QueueOptions`
|
#### `QueueOptions`
|
||||||
|
|
||||||
| Option | Type | Default | Description |
|
| Option | Type | Default | Description |
|
||||||
| ------------- | ------------------------------------ | ---------- | -------------------------------------------------------- |
|
| ------------- | ------------------------------------ | ---------- | --------------------------------------------------------------------------------------- |
|
||||||
| `maxAttempts` | `number` | `3` | Default max attempts per job before it is dead-lettered. |
|
| `maxAttempts` | `number` | `3` | Default max attempts per job before it is dead-lettered. |
|
||||||
| `backoffMs` | `number` | `1000` | Base retry backoff in ms; doubles per attempt. |
|
| `backoffMs` | `number` | `1000` | Base retry backoff in ms; doubles per attempt. |
|
||||||
| `pollMs` | `number` | `250` | Poll interval used once `start()` is called (ms). |
|
| `pollMs` | `number` | `250` | Poll interval used once `start()` is called (ms). |
|
||||||
| `onFailed` | `(job: Job, error: unknown) => void` | — | Called when a job exhausts its attempts. |
|
| `onFailed` | `(job: Job, error: unknown) => void` | — | Called when a job exhausts its attempts. |
|
||||||
| `concurrency` | `number` | unlimited | Maximum jobs claimed by one `drain()` call. |
|
| `concurrency` | `number` | unlimited | Maximum jobs claimed by one `drain()` call. |
|
||||||
| `capacity` | `number` | unlimited | Optional maximum queued jobs; omitted queues never scan merely to enforce a hidden cap. |
|
| `capacity` | `number` | unlimited | Optional maximum queued jobs; omitted queues never scan merely to enforce a hidden cap. |
|
||||||
| `now` | `() => number` | `Date.now` | Clock injection for deterministic tests. |
|
| `now` | `() => number` | `Date.now` | Clock injection for deterministic tests. |
|
||||||
|
|
||||||
### `Queue`
|
### `Queue`
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/store",
|
"name": "@wrnexus/store",
|
||||||
"version": "0.8.9",
|
"version": "0.8.12",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"exports": {
|
"exports": {
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
import { expect, test } from "bun:test";
|
||||||
|
import { StoreContainer, defineStore } from "../src/index.ts";
|
||||||
|
|
||||||
|
test("memory persistence includes only approved fields and migrates old state", async () => {
|
||||||
|
const original = defineStore({
|
||||||
|
name: "preferences-migration",
|
||||||
|
kind: "global" as const,
|
||||||
|
createSharedState: () => ({ theme: "dark", secret: "initial" }),
|
||||||
|
persist: { storage: "memory" as const, version: 1, include: ["theme"] },
|
||||||
|
actions: {
|
||||||
|
setTheme: {
|
||||||
|
runtime: "client" as const,
|
||||||
|
handler: ({ state }: any, theme: string) => void (state.theme = theme),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const first = await new StoreContainer({ runtime: "client" }).use(original);
|
||||||
|
await first.actions.setTheme("light");
|
||||||
|
|
||||||
|
const migrated = defineStore({
|
||||||
|
...original,
|
||||||
|
persist: {
|
||||||
|
storage: "memory" as const,
|
||||||
|
version: 2,
|
||||||
|
include: ["theme"],
|
||||||
|
migrate: (state: any) => ({ ...state, theme: `${state.theme}-v2` }),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const second = await new StoreContainer({ runtime: "client" }).use(migrated);
|
||||||
|
expect(second.state.theme).toBe("light-v2");
|
||||||
|
expect(second.state.secret).toBe("initial");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("invalid persisted state fails closed to the store defaults", async () => {
|
||||||
|
const name = `preferences-validation-${crypto.randomUUID()}`;
|
||||||
|
const firstDefinition = defineStore({
|
||||||
|
name,
|
||||||
|
kind: "global" as const,
|
||||||
|
createSharedState: () => ({ theme: "dark" }),
|
||||||
|
persist: { storage: "memory" as const, version: 1, include: ["theme"] },
|
||||||
|
actions: {
|
||||||
|
setTheme: {
|
||||||
|
runtime: "client" as const,
|
||||||
|
handler: ({ state }: any, theme: string) => void (state.theme = theme),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const first = await new StoreContainer({ runtime: "client" }).use(firstDefinition);
|
||||||
|
await first.actions.setTheme("corrupt");
|
||||||
|
|
||||||
|
const validated = defineStore({
|
||||||
|
...firstDefinition,
|
||||||
|
persist: {
|
||||||
|
storage: "memory" as const,
|
||||||
|
version: 1,
|
||||||
|
include: ["theme"],
|
||||||
|
validate: (value: any) => (value?.theme === "light" ? value : null),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const second = await new StoreContainer({ runtime: "client" }).use(validated);
|
||||||
|
expect(second.state.theme).toBe("dark");
|
||||||
|
});
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/syntax",
|
"name": "@wrnexus/syntax",
|
||||||
"version": "0.8.13",
|
"version": "0.8.18",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"exports": {
|
"exports": {
|
||||||
|
|||||||
@@ -767,6 +767,28 @@ function expandStructuredStateDeclarations(lines, unit) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function formatStructuredPropDeclaration(value, unit, depth, printWidth) {
|
||||||
|
const match = /^([A-Za-z_$][\w$]*\??\s*(?::\s*[^=]+?)?\s*=\s*)([\[{][\s\S]*)$/.exec(
|
||||||
|
value,
|
||||||
|
);
|
||||||
|
if (!match) return null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(match[2].trim());
|
||||||
|
const compact = JSON.stringify(parsed);
|
||||||
|
const indentation = unit.repeat(depth);
|
||||||
|
if (indentation.length + match[1].length + compact.length <= printWidth) return null;
|
||||||
|
|
||||||
|
const jsonLines = JSON.stringify(parsed, null, unit).split("\n");
|
||||||
|
return [
|
||||||
|
`${indentation}${match[1]}${jsonLines[0]}`,
|
||||||
|
...jsonLines.slice(1).map((jsonLine) => `${indentation}${jsonLine}`),
|
||||||
|
];
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function formatWrnPass(source: string, options: FormatWrnOptions = {}): string {
|
function formatWrnPass(source: string, options: FormatWrnOptions = {}): string {
|
||||||
const unit = options.insertSpaces === false ? "\t" : " ".repeat(options.tabSize ?? 4);
|
const unit = options.insertSpaces === false ? "\t" : " ".repeat(options.tabSize ?? 4);
|
||||||
|
|
||||||
@@ -844,6 +866,18 @@ function formatWrnPass(source: string, options: FormatWrnOptions = {}): string {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const structuredProp = formatStructuredPropDeclaration(
|
||||||
|
value,
|
||||||
|
unit,
|
||||||
|
codeDepth + htmlDepth + controlDepth,
|
||||||
|
printWidth,
|
||||||
|
);
|
||||||
|
if (structuredProp) {
|
||||||
|
output.push(...structuredProp);
|
||||||
|
index += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const leadingClosingBraces = countLeadingClosingBraces(value);
|
const leadingClosingBraces = countLeadingClosingBraces(value);
|
||||||
|
|
||||||
const closesControlBlock = isControlBlockClose(value);
|
const closesControlBlock = isControlBlockClose(value);
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ export { Lexer, LexError, skipLiteralOrComment } from "./tokenizer.ts";
|
|||||||
export { formatWrn } from "./formatter.ts";
|
export { formatWrn } from "./formatter.ts";
|
||||||
export type { FormatWrnOptions } from "./formatter.ts";
|
export type { FormatWrnOptions } from "./formatter.ts";
|
||||||
export { parse, parseHtmlView, ParseError, VOID_ELEMENTS } from "./parser.ts";
|
export { parse, parseHtmlView, ParseError, VOID_ELEMENTS } from "./parser.ts";
|
||||||
|
export { extractInterpolations } from "./interpolation.ts";
|
||||||
|
export type { InterpolationSegment } from "./interpolation.ts";
|
||||||
export type {
|
export type {
|
||||||
ActionBlock,
|
ActionBlock,
|
||||||
ApiBlock,
|
ApiBlock,
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
export interface InterpolationSegment {
|
||||||
|
expression: string;
|
||||||
|
start: number;
|
||||||
|
end: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Extract top-level `{...}` expressions while preserving nested object/array literals. */
|
||||||
|
export function extractInterpolations(value: string): InterpolationSegment[] {
|
||||||
|
const segments: InterpolationSegment[] = [];
|
||||||
|
let index = 0;
|
||||||
|
while (index < value.length) {
|
||||||
|
if (value[index] !== "{") {
|
||||||
|
index++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const start = index++;
|
||||||
|
let depth = 1;
|
||||||
|
let quote: string | null = null;
|
||||||
|
while (index < value.length && depth > 0) {
|
||||||
|
const char = value[index]!;
|
||||||
|
if (quote) {
|
||||||
|
if (char === "\\" && index + 1 < value.length) index += 2;
|
||||||
|
else {
|
||||||
|
if (char === quote) quote = null;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (char === '"' || char === "'" || char === "`") quote = char;
|
||||||
|
else if (char === "{") depth++;
|
||||||
|
else if (char === "}") depth--;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
if (depth === 0) {
|
||||||
|
segments.push({ expression: value.slice(start + 1, index - 1).trim(), start, end: index });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return segments;
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import { expect, test } from "bun:test";
|
||||||
|
import { hasRequestSection, parseApiEntries, parseApiSections } from "../src/api-sections.ts";
|
||||||
|
|
||||||
|
test("api section scanning ignores keywords in literals, comments, and nested objects", () => {
|
||||||
|
const source = `
|
||||||
|
// request { body { forged: string } }
|
||||||
|
response {
|
||||||
|
return { label: "request { not a section }", nested: { body: true } }
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
expect(hasRequestSection(source)).toBe(false);
|
||||||
|
expect(parseApiSections(source)?.response).toContain("nested");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("api entries normalize methods and reject malformed request fields", () => {
|
||||||
|
expect(
|
||||||
|
parseApiEntries(`lookup get /users/:id {
|
||||||
|
response { return data }
|
||||||
|
}`)[0],
|
||||||
|
).toMatchObject({
|
||||||
|
name: "lookup",
|
||||||
|
method: "GET",
|
||||||
|
path: "/users/:id",
|
||||||
|
});
|
||||||
|
expect(() =>
|
||||||
|
parseApiSections("request { body { missingType } } response { return data }"),
|
||||||
|
).toThrow('Expected "name: type"');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("api entries reject truncated blocks and bare response bodies", () => {
|
||||||
|
expect(() => parseApiEntries("lookup GET /users { response { return data }")).toThrow();
|
||||||
|
expect(() => parseApiEntries("lookup GET /users { return data }")).toThrow(
|
||||||
|
'declare a "response { }" section',
|
||||||
|
);
|
||||||
|
});
|
||||||
@@ -83,3 +83,18 @@ test("preserves balanced compact sibling markup without indentation drift", () =
|
|||||||
expect(formatted).toContain('<div class="strip"><span>Page</span><b>→</b><span>API</span></div>');
|
expect(formatted).toContain('<div class="strip"><span>Page</span><b>→</b><span>API</span></div>');
|
||||||
expect(formatWrn(formatted, { tabSize: 2, printWidth: 80 })).toBe(formatted);
|
expect(formatWrn(formatted, { tabSize: 2, printWidth: 80 })).toBe(formatted);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("formats large typed JSON prop defaults and remains idempotent", () => {
|
||||||
|
const source = `component Catalog {
|
||||||
|
props {
|
||||||
|
categories: unknown[] = [{"label":"Platform & Core","value":"platform","apps":[{"label":"WRNexus Home / Business Command Center","href":"/products/home","number":"01"},{"label":"SSO & Account","href":"/products/sso","number":"02"}]},{"label":"Sales & Customer","value":"sales","apps":[{"label":"CRM","href":"/products/crm","number":"11"}]}]
|
||||||
|
}
|
||||||
|
view { <div></div> }
|
||||||
|
}`;
|
||||||
|
const formatted = formatWrn(source, options);
|
||||||
|
|
||||||
|
expect(formatted).toContain(`categories: unknown[] = [\n {\n "label": "Platform & Core"`);
|
||||||
|
expect(formatted).toContain(`"apps": [\n {`);
|
||||||
|
expect(formatWrn(formatted, options)).toBe(formatted);
|
||||||
|
expect(() => parse(formatted)).not.toThrow();
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { expect, test } from "bun:test";
|
import { expect, test } from "bun:test";
|
||||||
import { diagnose, formatDiagnostic, parse } from "../src/index.ts";
|
import { diagnose, extractInterpolations, formatDiagnostic, parse } from "../src/index.ts";
|
||||||
|
|
||||||
test("parses explicit rendering modes and the never hydration alias", () => {
|
test("parses explicit rendering modes and the never hydration alias", () => {
|
||||||
const ast = parse(`page Marketing {
|
const ast = parse(`page Marketing {
|
||||||
@@ -337,3 +337,14 @@ test("a block comment inside props is still refused with its own message", () =>
|
|||||||
`;
|
`;
|
||||||
expect(() => parse(source)).toThrow("Block comments are not allowed inside props");
|
expect(() => parse(source)).toThrow("Block comments are not allowed inside props");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("extracts nested object and array interpolation as one expression", () => {
|
||||||
|
const value = `prefix {[{ label: 'One', meta: { count: 1 } }, { label: "Two" }]} suffix`;
|
||||||
|
expect(extractInterpolations(value)).toEqual([
|
||||||
|
{
|
||||||
|
expression: `[{ label: 'One', meta: { count: 1 } }, { label: "Two" }]`,
|
||||||
|
start: 7,
|
||||||
|
end: value.length - 7,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|||||||
@@ -206,8 +206,4 @@ export type {
|
|||||||
export { withDatabaseRollback, createFactory, captureBrowserArtifacts } from "./platform.ts";
|
export { withDatabaseRollback, createFactory, captureBrowserArtifacts } from "./platform.ts";
|
||||||
export type { TransactionalDatabase, BrowserArtifactPage } from "./platform.ts";
|
export type { TransactionalDatabase, BrowserArtifactPage } from "./platform.ts";
|
||||||
export { detectMutations } from "./mutation.ts";
|
export { detectMutations } from "./mutation.ts";
|
||||||
export type {
|
export type { MutationCase, MutationReport, DetectMutationsOptions } from "./mutation.ts";
|
||||||
MutationCase,
|
|
||||||
MutationReport,
|
|
||||||
DetectMutationsOptions,
|
|
||||||
} from "./mutation.ts";
|
|
||||||
|
|||||||
@@ -43,10 +43,9 @@ export async function detectMutations<T, O>(
|
|||||||
(same ? survived : killed).push(mutation.name);
|
(same ? survived : killed).push(mutation.name);
|
||||||
}
|
}
|
||||||
if (survived.length) {
|
if (survived.length) {
|
||||||
throw Object.assign(
|
throw Object.assign(new Error(`WRN-MUTATION-SURVIVED: ${survived.join(", ")}`), {
|
||||||
new Error(`WRN-MUTATION-SURVIVED: ${survived.join(", ")}`),
|
report: { baseline, killed, survived },
|
||||||
{ report: { baseline, killed, survived } },
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return { baseline, killed, survived };
|
return { baseline, killed, survived };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/typecheck",
|
"name": "@wrnexus/typecheck",
|
||||||
"version": "0.8.13",
|
"version": "0.8.16",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"exports": {
|
"exports": {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { dirname, join, normalize, resolve } from "node:path";
|
|||||||
import ts from "typescript";
|
import ts from "typescript";
|
||||||
import {
|
import {
|
||||||
containsReadonlyPropMutation,
|
containsReadonlyPropMutation,
|
||||||
|
extractInterpolations,
|
||||||
inferredRuntimeType,
|
inferredRuntimeType,
|
||||||
parse,
|
parse,
|
||||||
runtimeTypeOf,
|
runtimeTypeOf,
|
||||||
@@ -139,7 +140,7 @@ function functionDeclaration(fn: RuntimeFunctionDecl): string {
|
|||||||
const params = fn.parameters
|
const params = fn.parameters
|
||||||
.map(
|
.map(
|
||||||
(param) =>
|
(param) =>
|
||||||
`${param.name}${param.optional ? "?" : ""}${param.valueType ? `: ${param.valueType}` : param.name === "event" ? ": CustomEvent<any> & { target: HTMLElement }" : ": any"}${param.default ? ` = ${param.default}` : ""}`,
|
`${param.name}${param.optional ? "?" : ""}${param.valueType ? `: ${param.valueType}` : param.name === "event" ? ": Event & { target: HTMLElement }" : ": any"}${param.default ? ` = ${param.default}` : ""}`,
|
||||||
)
|
)
|
||||||
.join(", ");
|
.join(", ");
|
||||||
// An omitted WRN parameter type follows JavaScript semantics. Emitting it as
|
// An omitted WRN parameter type follows JavaScript semantics. Emitting it as
|
||||||
@@ -214,6 +215,31 @@ function safeBindingName(name: string): boolean {
|
|||||||
return /^[A-Za-z_$][\w$]*$/.test(name) && !RESERVED_BINDING_NAMES.has(name);
|
return /^[A-Za-z_$][\w$]*$/.test(name) && !RESERVED_BINDING_NAMES.has(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function safeViewExpression(expression: string, reservedProps: ReadonlySet<string>): string {
|
||||||
|
if (!reservedProps.size) return expression;
|
||||||
|
const scanner = ts.createScanner(
|
||||||
|
ts.ScriptTarget.Latest,
|
||||||
|
false,
|
||||||
|
ts.LanguageVariant.Standard,
|
||||||
|
expression,
|
||||||
|
);
|
||||||
|
let result = "";
|
||||||
|
let copied = 0;
|
||||||
|
for (let token = scanner.scan(); token !== ts.SyntaxKind.EndOfFileToken; token = scanner.scan()) {
|
||||||
|
const start = scanner.getTokenPos();
|
||||||
|
const end = scanner.getTextPos();
|
||||||
|
const text = scanner.getTokenText();
|
||||||
|
if (!reservedProps.has(text)) continue;
|
||||||
|
const previous = expression.slice(0, start).trimEnd().at(-1);
|
||||||
|
const following = expression.slice(end).trimStart().at(0);
|
||||||
|
// Property access and object-literal keys are already valid TypeScript.
|
||||||
|
if (previous === "." || following === ":") continue;
|
||||||
|
result += expression.slice(copied, start) + `props.${text}`;
|
||||||
|
copied = end;
|
||||||
|
}
|
||||||
|
return result + expression.slice(copied);
|
||||||
|
}
|
||||||
|
|
||||||
export function virtualTypeScriptModule(
|
export function virtualTypeScriptModule(
|
||||||
source: string,
|
source: string,
|
||||||
filePath = "component.wrn",
|
filePath = "component.wrn",
|
||||||
@@ -307,6 +333,9 @@ export function virtualTypeScriptModule(
|
|||||||
if (ast.dataApis.length) append(`declare const api: { ${apiType} };`);
|
if (ast.dataApis.length) append(`declare const api: { ${apiType} };`);
|
||||||
append(`declare const props: Readonly<${ast.name}Props>;`);
|
append(`declare const props: Readonly<${ast.name}Props>;`);
|
||||||
append("declare const refs: Record<string, Element | null>;");
|
append("declare const refs: Record<string, Element | null>;");
|
||||||
|
append(
|
||||||
|
"declare const toast: ((message: string, options?: Record<string, unknown>) => unknown) & { success(message: string, options?: Record<string, unknown>): unknown; error(message: string, options?: Record<string, unknown>): unknown; danger(message: string, options?: Record<string, unknown>): unknown; warning(message: string, options?: Record<string, unknown>): unknown; info(message: string, options?: Record<string, unknown>): unknown; dismiss(id: string | number): void; clear(): void };",
|
||||||
|
);
|
||||||
append(
|
append(
|
||||||
"declare function useFetch(path: string, method?: string | { method?: string; query?: unknown; params?: unknown; body?: unknown; data?: unknown }, input?: unknown): Promise<any>;",
|
"declare function useFetch(path: string, method?: string | { method?: string; query?: unknown; params?: unknown; body?: unknown; data?: unknown }, input?: unknown): Promise<any>;",
|
||||||
);
|
);
|
||||||
@@ -348,21 +377,29 @@ export function virtualTypeScriptModule(
|
|||||||
// misspelled state/function name cannot silently become `undefined` at
|
// misspelled state/function name cannot silently become `undefined` at
|
||||||
// runtime. Each/handler locals mirror the browser evaluator's bindings.
|
// runtime. Each/handler locals mirror the browser evaluator's bindings.
|
||||||
let bindingIndex = 0;
|
let bindingIndex = 0;
|
||||||
|
const reservedProps = new Set(
|
||||||
|
ast.props.map((prop) => prop.name).filter((name) => !safeBindingName(name)),
|
||||||
|
);
|
||||||
const appendViewBindings = (nodes: ViewNode[], locals: Set<string>): void => {
|
const appendViewBindings = (nodes: ViewNode[], locals: Set<string>): void => {
|
||||||
for (const node of nodes) {
|
for (const node of nodes) {
|
||||||
if (node.type === "element") {
|
if (node.type === "element") {
|
||||||
for (const attr of node.attrs) {
|
for (const attr of node.attrs) {
|
||||||
const expressions = attr.event
|
const expressions = attr.event
|
||||||
? [attr.value]
|
? [attr.value]
|
||||||
: [...attr.value.matchAll(/\{([^{}]+)\}/g)].map((match) => match[1]!.trim());
|
: extractInterpolations(attr.value).map((segment) => segment.expression);
|
||||||
for (const expression of expressions) {
|
for (const expression of expressions) {
|
||||||
if (!expression.trim()) continue;
|
if (!expression.trim()) continue;
|
||||||
const declarations = [
|
const declarations = [
|
||||||
...[...locals].map((name) => `declare const ${name}: any;`),
|
...[...locals].map((name) => `declare const ${name}: any;`),
|
||||||
...(attr.event ? ["declare const payload: any;", "declare const event: Event;"] : []),
|
...(attr.event
|
||||||
|
? [
|
||||||
|
"declare const payload: any;",
|
||||||
|
"declare const event: Event & { target: HTMLElement };",
|
||||||
|
]
|
||||||
|
: []),
|
||||||
].join(" ");
|
].join(" ");
|
||||||
append(
|
append(
|
||||||
`namespace __wrn_view_${bindingIndex++} { ${declarations} void (${expression}); }`,
|
`namespace __wrn_view_${bindingIndex++} { ${declarations} void (${safeViewExpression(expression, reservedProps)}); }`,
|
||||||
attr.value,
|
attr.value,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -372,13 +409,16 @@ export function virtualTypeScriptModule(
|
|||||||
for (const branch of node.branches) {
|
for (const branch of node.branches) {
|
||||||
if (branch.cond)
|
if (branch.cond)
|
||||||
append(
|
append(
|
||||||
`namespace __wrn_view_${bindingIndex++} { void (${branch.cond}); }`,
|
`namespace __wrn_view_${bindingIndex++} { void (${safeViewExpression(branch.cond, reservedProps)}); }`,
|
||||||
branch.cond,
|
branch.cond,
|
||||||
);
|
);
|
||||||
appendViewBindings(branch.body, locals);
|
appendViewBindings(branch.body, locals);
|
||||||
}
|
}
|
||||||
} else if (node.type === "each") {
|
} else if (node.type === "each") {
|
||||||
append(`namespace __wrn_view_${bindingIndex++} { void (${node.list}); }`, node.list);
|
append(
|
||||||
|
`namespace __wrn_view_${bindingIndex++} { void (${safeViewExpression(node.list, reservedProps)}); }`,
|
||||||
|
node.list,
|
||||||
|
);
|
||||||
const nested = new Set(locals);
|
const nested = new Set(locals);
|
||||||
nested.add(node.item);
|
nested.add(node.item);
|
||||||
if (node.index) nested.add(node.index);
|
if (node.index) nested.add(node.index);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { expect, test } from "bun:test";
|
import { expect, test } from "bun:test";
|
||||||
import { mkdirSync, mkdtempSync, writeFileSync } from "node:fs";
|
import { mkdirSync, mkdtempSync } from "node:fs";
|
||||||
import { tmpdir } from "node:os";
|
import { tmpdir } from "node:os";
|
||||||
import { join } from "node:path";
|
import { join } from "node:path";
|
||||||
import { checkWrnSource } from "../src/index.ts";
|
import { checkWrnSource } from "../src/index.ts";
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { expect, test } from "bun:test";
|
import { expect, test } from "bun:test";
|
||||||
import { mkdirSync, mkdtempSync, writeFileSync } from "node:fs";
|
import { mkdirSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs";
|
||||||
import { tmpdir } from "node:os";
|
import { tmpdir } from "node:os";
|
||||||
import { join } from "node:path";
|
import { join } from "node:path";
|
||||||
import { checkWrnSource } from "../src/index.ts";
|
import { checkWrnSource } from "../src/index.ts";
|
||||||
@@ -82,6 +82,23 @@ page Home {
|
|||||||
expect(diagnostics.some((item) => item.code === "WRN-COMPONENT-PROP-TYPE")).toBe(false);
|
expect(diagnostics.some((item) => item.code === "WRN-COMPONENT-PROP-TYPE")).toBe(false);
|
||||||
expect(diagnostics.some((item) => item.code === "WRN-TYPE-1389")).toBe(false);
|
expect(diagnostics.some((item) => item.code === "WRN-TYPE-1389")).toBe(false);
|
||||||
expect(diagnostics.some((item) => item.code === "WRN-TYPE-1005")).toBe(false);
|
expect(diagnostics.some((item) => item.code === "WRN-TYPE-1005")).toBe(false);
|
||||||
|
expect(
|
||||||
|
checkWrnSource(readFileSync(componentPath, "utf8"), { appRoot: root, filePath: componentPath }),
|
||||||
|
).toEqual([]);
|
||||||
|
}, 15_000);
|
||||||
|
|
||||||
|
test("implicit DOM events satisfy untyped event handler parameters", () => {
|
||||||
|
const root = fixture();
|
||||||
|
const filePath = join(root, "app", "components", "Submit.wrn");
|
||||||
|
const diagnostics = checkWrnSource(
|
||||||
|
`component Submit {
|
||||||
|
outputs { submit(payload: { event: Event }) }
|
||||||
|
functions { client function submitForm(event) { output.submit({ event }) } }
|
||||||
|
view { <form @submit="submitForm(event)"></form> }
|
||||||
|
}`,
|
||||||
|
{ appRoot: root, filePath },
|
||||||
|
);
|
||||||
|
expect(diagnostics).toEqual([]);
|
||||||
}, 15_000);
|
}, 15_000);
|
||||||
|
|
||||||
test("does not treat UI component imports as JavaScript exports", () => {
|
test("does not treat UI component imports as JavaScript exports", () => {
|
||||||
|
|||||||
@@ -112,3 +112,32 @@ test("accepts handler payload, loop locals, and the public useFetch helper", ()
|
|||||||
);
|
);
|
||||||
expect(diagnostics.filter((diagnostic) => diagnostic.code === "WRN-TYPE-2304")).toEqual([]);
|
expect(diagnostics.filter((diagnostic) => diagnostic.code === "WRN-TYPE-2304")).toEqual([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("accepts multiline array props containing nested object literals", () => {
|
||||||
|
const root = app();
|
||||||
|
const diagnostics = checkWrnSource(
|
||||||
|
`page Contact {
|
||||||
|
view {
|
||||||
|
<div data-component="StatsBar" items="{[
|
||||||
|
{ label: 'Product catalog', value: '81', suffix: ' apps' },
|
||||||
|
{ label: 'Starting point', value: 'One workflow' }
|
||||||
|
]}"></div>
|
||||||
|
}
|
||||||
|
}`,
|
||||||
|
{ appRoot: root, filePath: join(root, "app", "pages", "contact.wrn") },
|
||||||
|
);
|
||||||
|
expect(diagnostics.filter((diagnostic) => diagnostic.code.startsWith("WRN-TYPE-"))).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("provides the toast API to view event expressions", () => {
|
||||||
|
const root = app();
|
||||||
|
const diagnostics = checkWrnSource(
|
||||||
|
`page Contact {
|
||||||
|
view {
|
||||||
|
<form @wrn:success="toast.success('Sent', { title: 'Request sent' })"></form>
|
||||||
|
}
|
||||||
|
}`,
|
||||||
|
{ appRoot: root, filePath: join(root, "app", "pages", "contact.wrn") },
|
||||||
|
);
|
||||||
|
expect(diagnostics.filter((diagnostic) => diagnostic.code.startsWith("WRN-TYPE-"))).toEqual([]);
|
||||||
|
});
|
||||||
|
|||||||
+15
-15
@@ -45,7 +45,7 @@ Secure multi-cell PIN and verification-code input with regex and paste support.
|
|||||||
Theme-aware, responsive strong password component.
|
Theme-aware, responsive strong password component.
|
||||||
|
|
||||||
- Mount: `data-component="StrongPassword"`
|
- Mount: `data-component="StrongPassword"`
|
||||||
- Props: `size: string = "default"`, `color: string = "primary"`, `label: string = "Password"`, `name: string = "password"`, `value: string = ""`, `placeholder: string = "Create a strong password"`, `autocomplete: string = "new-password"`, `minLength: number = 8`, `specialCharactersSet: string = "!@#$%^&*()_+-=[]{}|;:,.<>?"`, `requireLowercase: boolean = true`, `requireUppercase: boolean = true`, `requireNumber: boolean = true`, `requireSpecialCharacter: boolean = true`, `showRequirements: boolean = true`, `presentation: string = "inline"`, `hintText: string = "Use a unique password you do not use elsewhere."`, `emptyLabel: string = "Enter a password"`, `weakLabel: string = "Weak"`, `fairLabel: string = "Fair"`, `goodLabel: string = "Good"`, `strongLabel: string = "Strong"`, `disabled: boolean = false`, `readonly: boolean = false`, `required: boolean = false`, `invalid: boolean = false`, `validationMessage: string = ""`, `class: string = ""`
|
- Props: `size: string = "default"`, `color: string = "primary"`, `label: string = "Password"`, `name: string = "password"`, `value: string = ""`, `placeholder: string = "Create a strong password"`, `autocomplete: string = "new-password"`, `minLength: number = 8`, `specialCharactersSet: string = "!@#$%^&*()_+-=[]{}|;:,.<>?"`, `requireLowercase: boolean = true`, `requireUppercase: boolean = true`, `requireNumber: boolean = true`, `requireSpecialCharacter: boolean = true`, `showRequirements: boolean = true`, `presentation: string = "inline"`, `hintText: string = "Use a unique password you do not use elsewhere."`, `emptyLabel: string = "Enter a password"`, `weakLabel: string = "Weak"`, `fairLabel: string = "Fair"`, `goodLabel: string = "Good"`, `strongLabel: string = "Strong"`, `disabled: boolean = false`, `readonly: boolean = false`, `required: boolean = false`, `invalid: boolean = false`, `validationMessage: string = ""`, `showLabel: string = "Show password"`, `hideLabel: string = "Hide password"`, `class: string = ""`
|
||||||
- Slots: None
|
- Slots: None
|
||||||
- Outputs: `input({ value: string; score: number; maximumScore: number; percent: number; level: string })`, `change({ value: string; score: number; maximumScore: number; percent: number; level: string })`, `strength({ value: string; score: number; maximumScore: number; percent: number; level: string })`
|
- Outputs: `input({ value: string; score: number; maximumScore: number; percent: number; level: string })`, `change({ value: string; score: number; maximumScore: number; percent: number; level: string })`, `strength({ value: string; score: number; maximumScore: number; percent: number; level: string })`
|
||||||
|
|
||||||
@@ -146,7 +146,7 @@ Theme-aware, responsive button group component.
|
|||||||
Group related content in a responsive themed surface with title, description, content, and supporting slots.
|
Group related content in a responsive themed surface with title, description, content, and supporting slots.
|
||||||
|
|
||||||
- Mount: `data-component="Card"`
|
- Mount: `data-component="Card"`
|
||||||
- Props: `title: string = "Card title"`, `subtitle: string = ""`, `description: string = ""`, `header: string = ""`, `footer: string = ""`, `imageSrc: string = ""`, `imageAlt: string = ""`, `imagePosition: string = "top"`, `actionLabel: string = ""`, `actionHref: string = ""`, `headerActions: unknown[] = []`, `navigation: unknown[] = []`, `activeNav: string = ""`, `mobileNavigation: boolean = false`, `alertTitle: string = ""`, `alertDescription: string = ""`, `empty: boolean = false`, `emptyTitle: string = "No data to show"`, `emptyIcon: string = "icon-[lucide--inbox]"`, `items: unknown[] = []`, `size: string = "md"`, `color: string = "primary"`, `variant: string = "default"`, `layout: string = "vertical"`, `align: string = "left"`, `hover: string = "none"`, `scrollable: boolean = false`, `maxHeight: string = "18rem"`, `dismissible: boolean = false`, `ariaLabel: string = ""`, `class: string = ""`
|
- Props: `title: string = ""`, `icon: string = ""`, `titleKey: string = ""`, `subtitle: string = ""`, `subtitleKey: string = ""`, `description: string = ""`, `descriptionKey: string = ""`, `header: string = ""`, `footer: string = ""`, `imageSrc: string = ""`, `imageAlt: string = ""`, `imagePosition: string = "top"`, `actionLabel: string = ""`, `actionLabelKey: string = ""`, `actionHref: string = ""`, `headerActions: unknown[] = []`, `navigation: unknown[] = []`, `activeNav: string = ""`, `mobileNavigation: boolean = false`, `alertTitle: string = ""`, `alertDescription: string = ""`, `empty: boolean = false`, `emptyTitle: string = "No data to show"`, `emptyIcon: string = "icon-[lucide--inbox]"`, `items: unknown[] = []`, `size: string = "md"`, `color: string = "primary"`, `variant: string = "default"`, `layout: string = "vertical"`, `align: string = "left"`, `hover: string = "none"`, `radius: string = "default"`, `shadow: string = "default"`, `equalHeight: boolean = false`, `scrollable: boolean = false`, `maxHeight: string = "18rem"`, `dismissible: boolean = false`, `ariaLabel: string = ""`, `class: string = ""`
|
||||||
- Slots: `default`
|
- Slots: `default`
|
||||||
- Outputs: `click({ sourceEvent?: Event; [key: string]: string | number | boolean | null | object })`, `action({ sourceEvent?: Event; [key: string]: string | number | boolean | null | object })`, `navigate({ sourceEvent?: Event; [key: string]: string | number | boolean | null | object })`, `dismiss({ sourceEvent?: Event; [key: string]: string | number | boolean | null | object })`, `load({ sourceEvent?: Event; [key: string]: string | number | boolean | null | object })`, `error({ error: Error | string; sourceEvent?: Event; [key: string]: string | number | boolean | null | object } | Error | string)`
|
- Outputs: `click({ sourceEvent?: Event; [key: string]: string | number | boolean | null | object })`, `action({ sourceEvent?: Event; [key: string]: string | number | boolean | null | object })`, `navigate({ sourceEvent?: Event; [key: string]: string | number | boolean | null | object })`, `dismiss({ sourceEvent?: Event; [key: string]: string | number | boolean | null | object })`, `load({ sourceEvent?: Event; [key: string]: string | number | boolean | null | object })`, `error({ error: Error | string; sourceEvent?: Event; [key: string]: string | number | boolean | null | object } | Error | string)`
|
||||||
|
|
||||||
@@ -337,7 +337,7 @@ Reusable portal dashboard component.
|
|||||||
Reusable preference switcher component.
|
Reusable preference switcher component.
|
||||||
|
|
||||||
- Mount: `data-component="PreferenceSwitcher"`
|
- Mount: `data-component="PreferenceSwitcher"`
|
||||||
- Props: `size: string = "default"`, `color: string = "primary"`, `themeLabel: string = "Theme"`, `colorLabel: string = "Accent color"`, `languageLabel: string = "Language"`, `languages: string = [`, `colors: string = [`, `compact: boolean = true`, `class: string = ""`
|
- Props: `size: string = "default"`, `color: string = "primary"`, `themeLabel: string = "Theme"`, `colorLabel: string = "Accent color"`, `languageLabel: string = "Language"`, `languages: string = [`, `colors: string = [`, `compact: boolean = true`, `iconOnly: boolean = true`, `themeIcon: string = "icon-[lucide--sun-moon]"`, `colorIcon: string = "icon-[lucide--palette]"`, `languageIcon: string = "icon-[lucide--languages]"`, `panelPlacement: string = "bottom-end"`, `mobilePanel: string = "dropdown"`, `showCurrentLanguage: boolean = true`, `class: string = ""`
|
||||||
- Slots: None
|
- Slots: None
|
||||||
- Outputs: `theme({ sourceEvent?: Event; value: string | number | boolean | null | object; [key: string]: string | number | boolean | null | object } | string | number | boolean | null | object[])`, `color({ sourceEvent?: Event; value: string | number | boolean | null | object; [key: string]: string | number | boolean | null | object } | string | number | boolean | null | object[])`, `language({ sourceEvent?: Event; value: string | number | boolean | null | object; [key: string]: string | number | boolean | null | object } | string | number | boolean | null | object[])`
|
- Outputs: `theme({ sourceEvent?: Event; value: string | number | boolean | null | object; [key: string]: string | number | boolean | null | object } | string | number | boolean | null | object[])`, `color({ sourceEvent?: Event; value: string | number | boolean | null | object; [key: string]: string | number | boolean | null | object } | string | number | boolean | null | object[])`, `language({ sourceEvent?: Event; value: string | number | boolean | null | object; [key: string]: string | number | boolean | null | object } | string | number | boolean | null | object[])`
|
||||||
|
|
||||||
@@ -375,7 +375,7 @@ Arrange operational metrics, KPIs, public statistics, or service indicators in a
|
|||||||
Present a compact responsive strip of key facts, counts, performance indicators, or trust signals.
|
Present a compact responsive strip of key facts, counts, performance indicators, or trust signals.
|
||||||
|
|
||||||
- Mount: `data-component="StatsBar"`
|
- Mount: `data-component="StatsBar"`
|
||||||
- Props: `items: unknown[] = []`, `columns: number = 4`, `compact: boolean = true`, `dividers: boolean = true`, `icons: boolean = true`, `size: string = "default"`, `color: string = "primary"`, `variant: string = "raised"`, `maxWidth: string = "xl"`, `class: string = ""`
|
- Props: `items: unknown[] = []`, `columns: number = 4`, `compact: boolean = true`, `dividers: boolean = true`, `icons: boolean = true`, `size: string = "default"`, `color: string = "primary"`, `variant: string = "raised"`, `maxWidth: string = "xl"`, `radius: string = "default"`, `shadow: string = "default"`, `gutter: string = "md"`, `outerSpacing: string = "none"`, `mobileColumns: number = 1`, `class: string = ""`
|
||||||
- Slots: None
|
- Slots: None
|
||||||
- Outputs: None
|
- Outputs: None
|
||||||
|
|
||||||
@@ -606,7 +606,7 @@ Arrange feature cards, services, solutions, or benefits in a responsive equal-he
|
|||||||
Render structured responsive footer navigation, pre and post content, copyright content, links, and public events.
|
Render structured responsive footer navigation, pre and post content, copyright content, links, and public events.
|
||||||
|
|
||||||
- Mount: `data-component="Footer"`
|
- Mount: `data-component="Footer"`
|
||||||
- Props: `size: string = "default"`, `color: string = "primary"`, `label: string = "Footer navigation"`, `items: unknown[] = []`, `columns: number = 3`, `maxWidth: string = "compact"`, `copyright: string = ""`, `class: string = ""`
|
- Props: `size: string = "default"`, `color: string = "primary"`, `label: string = "Footer navigation"`, `items: unknown[] = []`, `columns: number = 3`, `maxWidth: string = "compact"`, `mobileColumns: number = 2`, `mobileCopyrightAlign: string = "center"`, `copyright: string = ""`, `copyrightKey: string = ""`, `translationPrefix: string = ""`, `class: string = ""`
|
||||||
- Slots: `pre-footer`, `post-footer`, `copyright-left`, `copyright-right`
|
- Slots: `pre-footer`, `post-footer`, `copyright-left`, `copyright-right`
|
||||||
- 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)`, `action({ sourceEvent?: Event; [key: string]: string | number | boolean | null | object })`
|
- 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)`, `action({ sourceEvent?: Event; [key: string]: string | number | boolean | null | object })`
|
||||||
|
|
||||||
@@ -698,7 +698,7 @@ Apply consistent readable responsive typography, widths, columns, spacing, and e
|
|||||||
Publish a responsive notice with badge, icon, supporting copy, action, dismiss behavior, and width controls.
|
Publish a responsive notice with badge, icon, supporting copy, action, dismiss behavior, and width controls.
|
||||||
|
|
||||||
- Mount: `data-component="AnnouncementBar"`
|
- Mount: `data-component="AnnouncementBar"`
|
||||||
- Props: `badge: string = ""`, `badgeIcon: string = ""`, `message: string = "Announcement"`, `description: string = ""`, `icon: string = "icon-[lucide--megaphone]"`, `actionLabel: string = ""`, `actionHref: string = ""`, `actionIcon: string = ""`, `dismissible: boolean = false`, `dismissLabel: string = "Dismiss announcement"`, `sticky: boolean = false`, `compact: boolean = false`, `size: string = "default"`, `width: string = "default"`, `color: string = "primary"`, `variant: string = "soft"`, `role: string = "status"`, `live: string = "polite"`, `class: string = ""`
|
- Props: `badge: string = ""`, `badgeIcon: string = ""`, `message: string = "Announcement"`, `description: string = ""`, `icon: string = "icon-[lucide--megaphone]"`, `actionLabel: string = ""`, `actionHref: string = ""`, `actionIcon: string = ""`, `dismissible: boolean = false`, `dismissLabel: string = "Dismiss announcement"`, `sticky: boolean = false`, `compact: boolean = false`, `flush: boolean = false`, `mobileCompact: boolean = false`, `mobileMessageLines: number = 2`, `hideBadgeOnMobile: boolean = false`, `hideDescriptionOnMobile: boolean = false`, `mobileActionSize: string = "default"`, `gutter: string = "md"`, `contentGutter: string = "md"`, `flushMobile: boolean = false`, `size: string = "default"`, `width: string = "default"`, `color: string = "primary"`, `variant: string = "soft"`, `role: string = "status"`, `live: string = "polite"`, `class: string = ""`
|
||||||
- Slots: None
|
- Slots: None
|
||||||
- Outputs: `dismiss({ sourceEvent?: Event; [key: string]: string | number | boolean | null | object })`
|
- Outputs: `dismiss({ sourceEvent?: Event; [key: string]: string | number | boolean | null | object })`
|
||||||
|
|
||||||
@@ -707,7 +707,7 @@ Publish a responsive notice with badge, icon, supporting copy, action, dismiss b
|
|||||||
Close a page or major section with conversion-focused copy, actions, and optional supporting visual content.
|
Close a page or major section with conversion-focused copy, actions, and optional supporting visual content.
|
||||||
|
|
||||||
- Mount: `data-component="CTASection"`
|
- Mount: `data-component="CTASection"`
|
||||||
- Props: `eyebrow: string = ""`, `title: string = "Ready to get started?"`, `description: string = ""`, `icon: string = ""`, `align: string = "center"`, `size: string = "default"`, `color: string = "primary"`, `variant: string = "solid"`, `primaryLabel: string = "Get started"`, `primaryHref: string = "#"`, `primaryIcon: string = ""`, `secondaryLabel: string = ""`, `secondaryHref: string = ""`, `secondaryIcon: string = ""`, `backgroundImage: string = ""`, `visualImage: string = ""`, `visualAlt: string = ""`, `visualIcon: string = ""`, `visualTitle: string = ""`, `visualDescription: string = ""`, `visualItems: unknown[] = []`, `visualPosition: string = "right"`, `maxWidth: string = "xl"`, `fullBleed: boolean = false`, `class: string = ""`
|
- Props: `eyebrow: string = ""`, `title: string = "Ready to get started?"`, `description: string = ""`, `icon: string = ""`, `align: string = "center"`, `size: string = "default"`, `color: string = "primary"`, `variant: string = "solid"`, `spacing: string = "none"`, `radius: string = "default"`, `titleMaxWidth: string = ""`, `contentPadding: string = "default"`, `mobilePadding: string = "default"`, `mobileActions: string = "stack"`, `primaryLabel: string = "Get started"`, `primaryHref: string = "#"`, `primaryIcon: string = ""`, `secondaryLabel: string = ""`, `secondaryHref: string = ""`, `secondaryIcon: string = ""`, `backgroundImage: string = ""`, `visualImage: string = ""`, `visualAlt: string = ""`, `visualIcon: string = ""`, `visualTitle: string = ""`, `visualDescription: string = ""`, `visualItems: unknown[] = []`, `visualPosition: string = "right"`, `maxWidth: string = "xl"`, `fullBleed: boolean = false`, `class: string = ""`
|
||||||
- Slots: `default`, `actions`, `visual`, `footer`
|
- Slots: `default`, `actions`, `visual`, `footer`
|
||||||
- Outputs: None
|
- Outputs: None
|
||||||
|
|
||||||
@@ -725,7 +725,7 @@ Present one linked feature or service with media, icon, badge, description, and
|
|||||||
Present a compact feature or benefit with a styled icon, title, description, badge, and optional link.
|
Present a compact feature or benefit with a styled icon, title, description, badge, and optional link.
|
||||||
|
|
||||||
- Mount: `data-component="FeatureIconCard"`
|
- Mount: `data-component="FeatureIconCard"`
|
||||||
- Props: `icon: string = "icon-[lucide--sparkles]"`, `iconSize: string = "md"`, `iconVariant: string = "soft"`, `title: string = "Feature"`, `description: string = ""`, `href: string = ""`, `actionLabel: string = "Explore"`, `badge: string = ""`, `size: string = "default"`, `color: string = "primary"`, `variant: string = "default"`, `align: string = "left"`, `hover: string = "lift"`, `class: string = ""`
|
- Props: `icon: string = "icon-[lucide--sparkles]"`, `iconSize: string = "md"`, `iconVariant: string = "soft"`, `title: string = "Feature"`, `description: string = ""`, `href: string = ""`, `actionLabel: string = "Explore"`, `badge: string = ""`, `size: string = "default"`, `color: string = "primary"`, `variant: string = "default"`, `align: string = "left"`, `hover: string = "lift"`, `radius: string = "default"`, `shadow: string = "default"`, `clickableSurface: boolean = false`, `descriptionTone: string = "default"`, `class: string = ""`
|
||||||
- Slots: `default`, `footer`
|
- Slots: `default`, `footer`
|
||||||
- Outputs: None
|
- Outputs: None
|
||||||
|
|
||||||
@@ -770,7 +770,7 @@ Introduce an internal or public page with breadcrumbs, icon, title, description,
|
|||||||
Build a responsive two-column introduction balancing descriptive content with a visual, image, or structured data panel.
|
Build a responsive two-column introduction balancing descriptive content with a visual, image, or structured data panel.
|
||||||
|
|
||||||
- Mount: `data-component="SplitHero"`
|
- Mount: `data-component="SplitHero"`
|
||||||
- Props: `eyebrow: string = ""`, `eyebrowIcon: string = "icon-[lucide--sparkles]"`, `title: string = "A better digital experience"`, `highlight: string = ""`, `description: string = ""`, `primaryLabel: string = ""`, `primaryHref: string = ""`, `primaryIcon: string = ""`, `secondaryLabel: string = ""`, `secondaryHref: string = ""`, `secondaryIcon: string = ""`, `visualPosition: string = "right"`, `reverse: boolean = false`, `ratio: string = "balanced"`, `align: string = "left"`, `size: string = "default"`, `color: string = "primary"`, `variant: string = "default"`, `maxWidth: string = "xl"`, `fullBleed: boolean = true`, `backgroundImage: string = ""`, `visualImage: string = ""`, `visualAlt: string = ""`, `visualIcon: string = ""`, `visualEyebrow: string = ""`, `visualTitle: string = ""`, `visualDescription: string = ""`, `visualItems: unknown[] = []`, `visualStyle: string = "panel"`, `trustItems: unknown[] = []`, `class: string = ""`
|
- Props: `eyebrow: string = ""`, `eyebrowIcon: string = "icon-[lucide--sparkles]"`, `title: string = "A better digital experience"`, `highlight: string = ""`, `description: string = ""`, `primaryLabel: string = ""`, `primaryHref: string = ""`, `primaryIcon: string = ""`, `secondaryLabel: string = ""`, `secondaryHref: string = ""`, `secondaryIcon: string = ""`, `visualPosition: string = "right"`, `reverse: boolean = false`, `ratio: string = "balanced"`, `align: string = "left"`, `size: string = "default"`, `color: string = "primary"`, `variant: string = "default"`, `maxWidth: string = "xl"`, `fullBleed: boolean = true`, `gutter: string = "md"`, `contentGutter: string = "md"`, `flushMobile: boolean = false`, `titleSize: string = "default"`, `titleMaxWidth: string = ""`, `descriptionWeight: string = "default"`, `mobileTitleSize: string = "default"`, `mobileStack: boolean = true`, `backgroundImage: string = ""`, `visualImage: string = ""`, `visualAlt: string = ""`, `visualIcon: string = ""`, `visualEyebrow: string = ""`, `visualTitle: string = ""`, `visualDescription: string = ""`, `visualItems: unknown[] = []`, `visualStyle: string = "panel"`, `trustItems: unknown[] = []`, `class: string = ""`
|
||||||
- Slots: `default`, `actions`, `trust`, `visual`
|
- Slots: `default`, `actions`, `trust`, `visual`
|
||||||
- Outputs: None
|
- Outputs: None
|
||||||
|
|
||||||
@@ -799,7 +799,7 @@ Provide a responsive floating control that returns long pages to the top and can
|
|||||||
Show responsive hierarchical navigation with home support, separators, current-page state, sizes, and selection events.
|
Show responsive hierarchical navigation with home support, separators, current-page state, sizes, and selection events.
|
||||||
|
|
||||||
- Mount: `data-component="Breadcrumb"`
|
- Mount: `data-component="Breadcrumb"`
|
||||||
- Props: `label: string = "Breadcrumb"`, `items: unknown[] = []`, `active: string = ""`, `separator: string = "chevron"`, `showHome: boolean = false`, `homeLabel: string = "Home"`, `homeHref: string = "/"`, `homeIcon: string = "icon-[lucide--house]"`, `size: string = "default"`, `color: string = "primary"`, `variant: string = "minimal"`, `class: string = ""`
|
- Props: `label: string = "Breadcrumb"`, `items: unknown[] = []`, `active: string = ""`, `activeIcon: string = "icon-[lucide--file-text]"`, `separator: string = "chevron"`, `showHome: boolean = false`, `homeLabel: string = "Home"`, `homeHref: string = "/"`, `homeIcon: string = "icon-[lucide--house]"`, `size: string = "default"`, `color: string = "primary"`, `variant: string = "minimal"`, `class: string = ""`
|
||||||
- Slots: None
|
- Slots: None
|
||||||
- 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)`
|
- 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)`
|
||||||
|
|
||||||
@@ -808,9 +808,9 @@ 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: `color: string = "primary"`, `size: string = "default"`, `label: string = "Menu"`, `icon: string = ""`, `columns: unknown[] = []`, `footer: string = ""`, `defaultOpen: boolean = false`, `class: string = ""`
|
- Props: `color: string = "primary"`, `size: string = "default"`, `label: string = "Menu"`, `icon: string = ""`, `columns: unknown[] = []`, `rail: unknown[] = []`, `featured: Record<string, unknown> = {}`, `variant: string = "default"`, `density: string = "default"`, `panelWidth: string = "xl"`, `panelAlign: string = "start"`, `columnCount: number = 0`, `fullWidth: boolean = false`, `openOnHover: boolean = true`, `activeCategory: string = ""`, `actionLabel: string = ""`, `actionHref: string = ""`, `actionIcon: string = "icon-[lucide--arrow-right]"`, `footer: string = ""`, `defaultOpen: boolean = false`, `class: string = ""`
|
||||||
- Slots: `default`
|
- Slots: `default`
|
||||||
- Outputs: `open({ sourceEvent: Event })`, `close({ reason: string })`, `select({ item: object; value: string })`
|
- Outputs: `open({ sourceEvent: Event })`, `close({ reason: string })`, `select({ item: object; value: string })`, `category({ item: object; value: string; index: number })`
|
||||||
|
|
||||||
### Nav
|
### Nav
|
||||||
|
|
||||||
@@ -826,8 +826,8 @@ Theme-aware, responsive nav component.
|
|||||||
Theme-aware, responsive navbar component.
|
Theme-aware, responsive navbar component.
|
||||||
|
|
||||||
- Mount: `data-component="Navbar"`
|
- Mount: `data-component="Navbar"`
|
||||||
- Props: `size: string = "default"`, `color: string = "primary"`, `label: string = "Primary navigation"`, `topbarLabel: string = "Utility navigation"`, `brand: Record<string, unknown> = {}`, `items: unknown[] = []`, `actions: unknown[] = []`, `active: string = ""`, `sticky: boolean = false`, `openOnHover: boolean = false`, `maxWidth: string = "full"`, `mobileLabel: string = "Toggle navigation"`, `class: string = ""`
|
- Props: `size: string = "default"`, `color: string = "primary"`, `label: string = "Primary navigation"`, `topbarLabel: string = "Utility navigation"`, `brand: Record<string, unknown> = {}`, `items: unknown[] = []`, `actions: unknown[] = []`, `active: string = ""`, `sticky: boolean = false`, `floating: boolean = false`, `startFloating: string = "0px"`, `openOnHover: boolean = false`, `maxWidth: string = "full"`, `mobileLabel: string = "Toggle navigation"`, `collapseAt: string = "900px"`, `mobilePanel: string = "content"`, `mobileUtilitiesPosition: string = "header"`, `gutter: string = "md"`, `contentGutter: string = "md"`, `flushMobile: boolean = false`, `translationPrefix: string = ""`, `class: string = ""`
|
||||||
- Slots: `topbar`, `actions`
|
- Slots: `topbar`, `actions`, `utilities`
|
||||||
- Outputs: `toggle({ open: boolean })`, `open({ sourceEvent?: Event; [key: string]: string | number | boolean | null | object })`, `close({ sourceEvent?: Event; [key: string]: string | number | boolean | null | object })`, `select({ item: string | number | boolean | null | object; value: string | number | boolean; level: string })`, `action({ item: string | number | boolean | null | object; value: string | number | boolean })`
|
- Outputs: `toggle({ open: boolean })`, `open({ sourceEvent?: Event; [key: string]: string | number | boolean | null | object })`, `close({ sourceEvent?: Event; [key: string]: string | number | boolean | null | object })`, `select({ item: string | number | boolean | null | object; value: string | number | boolean; level: string })`, `action({ item: string | number | boolean | null | object; value: string | number | boolean })`
|
||||||
|
|
||||||
### Pagination
|
### Pagination
|
||||||
@@ -844,7 +844,7 @@ Theme-aware, responsive pagination component.
|
|||||||
Theme-aware, responsive scrollspy component.
|
Theme-aware, responsive scrollspy component.
|
||||||
|
|
||||||
- Mount: `data-component="Scrollspy"`
|
- Mount: `data-component="Scrollspy"`
|
||||||
- Props: `color: string = "primary"`, `size: string = "default"`, `items: unknown[] = []`, `active: string = ""`, `label: string = "On this page"`, `heading: string = ""`, `class: string = ""`
|
- Props: `color: string = "primary"`, `size: string = "default"`, `items: unknown[] = []`, `active: string = ""`, `label: string = "On this page"`, `heading: string = ""`, `sticky: boolean = false`, `topOffset: string = "6rem"`, `sectionOffset: string = "7rem"`, `collapseAt: string = "800px"`, `class: string = ""`
|
||||||
- Slots: `default`
|
- Slots: `default`
|
||||||
- Outputs: `change({ href: string; label: string })`
|
- Outputs: `change({ href: string; label: string })`
|
||||||
|
|
||||||
|
|||||||
@@ -90,6 +90,62 @@ the component directory at runtime.
|
|||||||
For the full catalog, see [`COMPONENTS.md`](./COMPONENTS.md). The machine-readable
|
For the full catalog, see [`COMPONENTS.md`](./COMPONENTS.md). The machine-readable
|
||||||
equivalent is exported as `@wrnexus/ui/component-reference.json`.
|
equivalent is exported as `@wrnexus/ui/component-reference.json`.
|
||||||
|
|
||||||
|
### Typed Navbar items
|
||||||
|
|
||||||
|
Keep navigation data in a shared TypeScript module and validate it with the
|
||||||
|
package contract. `NavbarItem` is a discriminated union of `link`, `dropdown`,
|
||||||
|
and `mega`; a mega item accepts every `MegaMenu` layout option.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import type { NavbarItem } from "@wrnexus/ui";
|
||||||
|
|
||||||
|
export const navigation = [
|
||||||
|
{ type: "link", label: "Pricing", href: "/pricing" },
|
||||||
|
{
|
||||||
|
type: "dropdown",
|
||||||
|
label: "Company",
|
||||||
|
items: [
|
||||||
|
{ label: "About", href: "/about" },
|
||||||
|
{ label: "Contact", href: "/contact" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "mega",
|
||||||
|
label: "Products",
|
||||||
|
mega: {
|
||||||
|
variant: "icon-grid",
|
||||||
|
panelWidth: "2xl",
|
||||||
|
columnCount: 3,
|
||||||
|
rail: [{ label: "All products", href: "/products" }],
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
heading: "Work",
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
label: "Projects",
|
||||||
|
href: "/products/projects",
|
||||||
|
icon: "icon-[lucide--folders]",
|
||||||
|
description: "Plan and deliver work",
|
||||||
|
badge: "New",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
featured: {
|
||||||
|
title: "What's new",
|
||||||
|
actionLabel: "Explore",
|
||||||
|
actionHref: "/new",
|
||||||
|
},
|
||||||
|
actionLabel: "View all products",
|
||||||
|
actionHref: "/products",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
] satisfies NavbarItem[];
|
||||||
|
```
|
||||||
|
|
||||||
|
Importing from `@wrnexus/ui/navigation` is also supported. Existing untyped
|
||||||
|
Navbar data using `children` remains accepted at runtime for migration.
|
||||||
|
|
||||||
## API
|
## API
|
||||||
|
|
||||||
The JS module (`@wrnexus/ui`) exposes five helpers used by the build tooling to
|
The JS module (`@wrnexus/ui`) exposes five helpers used by the build tooling to
|
||||||
|
|||||||
@@ -806,6 +806,69 @@
|
|||||||
"default": "false",
|
"default": "false",
|
||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "flush",
|
||||||
|
"type": "boolean",
|
||||||
|
"required": false,
|
||||||
|
"default": "false",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mobileCompact",
|
||||||
|
"type": "boolean",
|
||||||
|
"required": false,
|
||||||
|
"default": "false",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mobileMessageLines",
|
||||||
|
"type": "number",
|
||||||
|
"required": false,
|
||||||
|
"default": "2",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "hideBadgeOnMobile",
|
||||||
|
"type": "boolean",
|
||||||
|
"required": false,
|
||||||
|
"default": "false",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "hideDescriptionOnMobile",
|
||||||
|
"type": "boolean",
|
||||||
|
"required": false,
|
||||||
|
"default": "false",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mobileActionSize",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"default\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "gutter",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"md\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "contentGutter",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"md\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "flushMobile",
|
||||||
|
"type": "boolean",
|
||||||
|
"required": false,
|
||||||
|
"default": "false",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "size",
|
"name": "size",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -2180,6 +2243,48 @@
|
|||||||
"default": "\"solid\"",
|
"default": "\"solid\"",
|
||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "spacing",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"none\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "radius",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"default\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "titleMaxWidth",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "contentPadding",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"default\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mobilePadding",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"default\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mobileActions",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"stack\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "primaryLabel",
|
"name": "primaryLabel",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -2315,7 +2420,21 @@
|
|||||||
"name": "title",
|
"name": "title",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"required": false,
|
"required": false,
|
||||||
"default": "\"Card title\"",
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "icon",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "titleKey",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -2325,6 +2444,13 @@
|
|||||||
"default": "\"\"",
|
"default": "\"\"",
|
||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "subtitleKey",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "description",
|
"name": "description",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -2332,6 +2458,13 @@
|
|||||||
"default": "\"\"",
|
"default": "\"\"",
|
||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "descriptionKey",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "header",
|
"name": "header",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -2374,6 +2507,13 @@
|
|||||||
"default": "\"\"",
|
"default": "\"\"",
|
||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "actionLabelKey",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "actionHref",
|
"name": "actionHref",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -2493,6 +2633,27 @@
|
|||||||
"default": "\"none\"",
|
"default": "\"none\"",
|
||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "radius",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"default\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "shadow",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"default\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "equalHeight",
|
||||||
|
"type": "boolean",
|
||||||
|
"required": false,
|
||||||
|
"default": "false",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "scrollable",
|
"name": "scrollable",
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
@@ -5833,6 +5994,34 @@
|
|||||||
"default": "\"lift\"",
|
"default": "\"lift\"",
|
||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "radius",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"default\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "shadow",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"default\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "clickableSurface",
|
||||||
|
"type": "boolean",
|
||||||
|
"required": false,
|
||||||
|
"default": "false",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "descriptionTone",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"default\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "class",
|
"name": "class",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -6198,6 +6387,20 @@
|
|||||||
"default": "\"compact\"",
|
"default": "\"compact\"",
|
||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "mobileColumns",
|
||||||
|
"type": "number",
|
||||||
|
"required": false,
|
||||||
|
"default": "2",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mobileCopyrightAlign",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"center\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "copyright",
|
"name": "copyright",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -6205,6 +6408,20 @@
|
|||||||
"default": "\"\"",
|
"default": "\"\"",
|
||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "copyrightKey",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "translationPrefix",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "class",
|
"name": "class",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -8128,6 +8345,97 @@
|
|||||||
"default": "[]",
|
"default": "[]",
|
||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "rail",
|
||||||
|
"type": "unknown[]",
|
||||||
|
"required": false,
|
||||||
|
"default": "[]",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "featured",
|
||||||
|
"type": "Record<string, unknown>",
|
||||||
|
"required": false,
|
||||||
|
"default": "{}",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "variant",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"default\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "density",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"default\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "panelWidth",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"xl\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "panelAlign",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"start\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "columnCount",
|
||||||
|
"type": "number",
|
||||||
|
"required": false,
|
||||||
|
"default": "0",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "fullWidth",
|
||||||
|
"type": "boolean",
|
||||||
|
"required": false,
|
||||||
|
"default": "false",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "openOnHover",
|
||||||
|
"type": "boolean",
|
||||||
|
"required": false,
|
||||||
|
"default": "true",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "activeCategory",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "actionLabel",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "actionHref",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "actionIcon",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"icon-[lucide--arrow-right]\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "footer",
|
"name": "footer",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -8163,9 +8471,13 @@
|
|||||||
{
|
{
|
||||||
"name": "select",
|
"name": "select",
|
||||||
"payloadType": "{ item: object; value: string }"
|
"payloadType": "{ item: object; value: string }"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "category",
|
||||||
|
"payloadType": "{ item: object; value: string; index: number }"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"events": ["open", "close", "select"],
|
"events": ["open", "close", "select", "category"],
|
||||||
"source": "components/MegaMenu.wrn"
|
"source": "components/MegaMenu.wrn"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -8878,6 +9190,20 @@
|
|||||||
"default": "false",
|
"default": "false",
|
||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "floating",
|
||||||
|
"type": "boolean",
|
||||||
|
"required": false,
|
||||||
|
"default": "false",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "startFloating",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"0px\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "openOnHover",
|
"name": "openOnHover",
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
@@ -8899,6 +9225,55 @@
|
|||||||
"default": "\"Toggle navigation\"",
|
"default": "\"Toggle navigation\"",
|
||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "collapseAt",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"900px\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mobilePanel",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"content\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mobileUtilitiesPosition",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"header\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "gutter",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"md\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "contentGutter",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"md\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "flushMobile",
|
||||||
|
"type": "boolean",
|
||||||
|
"required": false,
|
||||||
|
"default": "false",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "translationPrefix",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "class",
|
"name": "class",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -8907,7 +9282,7 @@
|
|||||||
"options": []
|
"options": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"slots": ["topbar", "actions"],
|
"slots": ["topbar", "actions", "utilities"],
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"name": "toggle",
|
"name": "toggle",
|
||||||
@@ -9826,6 +10201,55 @@
|
|||||||
"default": "true",
|
"default": "true",
|
||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "iconOnly",
|
||||||
|
"type": "boolean",
|
||||||
|
"required": false,
|
||||||
|
"default": "true",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "themeIcon",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"icon-[lucide--sun-moon]\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "colorIcon",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"icon-[lucide--palette]\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "languageIcon",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"icon-[lucide--languages]\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "panelPlacement",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"bottom-end\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mobilePanel",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"dropdown\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "showCurrentLanguage",
|
||||||
|
"type": "boolean",
|
||||||
|
"required": false,
|
||||||
|
"default": "true",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "class",
|
"name": "class",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -10532,6 +10956,34 @@
|
|||||||
"default": "\"\"",
|
"default": "\"\"",
|
||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "sticky",
|
||||||
|
"type": "boolean",
|
||||||
|
"required": false,
|
||||||
|
"default": "false",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "topOffset",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"6rem\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "sectionOffset",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"7rem\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "collapseAt",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"800px\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "class",
|
"name": "class",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -11346,6 +11798,62 @@
|
|||||||
"default": "true",
|
"default": "true",
|
||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "gutter",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"md\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "contentGutter",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"md\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "flushMobile",
|
||||||
|
"type": "boolean",
|
||||||
|
"required": false,
|
||||||
|
"default": "false",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "titleSize",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"default\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "titleMaxWidth",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "descriptionWeight",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"default\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mobileTitleSize",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"default\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mobileStack",
|
||||||
|
"type": "boolean",
|
||||||
|
"required": false,
|
||||||
|
"default": "true",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "backgroundImage",
|
"name": "backgroundImage",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -11498,6 +12006,41 @@
|
|||||||
"default": "\"xl\"",
|
"default": "\"xl\"",
|
||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "radius",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"default\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "shadow",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"default\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "gutter",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"md\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "outerSpacing",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"none\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mobileColumns",
|
||||||
|
"type": "number",
|
||||||
|
"required": false,
|
||||||
|
"default": "1",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "class",
|
"name": "class",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -11844,6 +12387,20 @@
|
|||||||
"default": "\"\"",
|
"default": "\"\"",
|
||||||
"options": []
|
"options": []
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "showLabel",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"Show password\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "hideLabel",
|
||||||
|
"type": "string",
|
||||||
|
"required": false,
|
||||||
|
"default": "\"Hide password\"",
|
||||||
|
"options": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "class",
|
"name": "class",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
|||||||
@@ -16,6 +16,15 @@ badge: string = ""
|
|||||||
dismissLabel: string = "Dismiss announcement"
|
dismissLabel: string = "Dismiss announcement"
|
||||||
sticky: boolean = false
|
sticky: boolean = false
|
||||||
compact: boolean = false
|
compact: boolean = false
|
||||||
|
flush: boolean = false
|
||||||
|
mobileCompact: boolean = false
|
||||||
|
mobileMessageLines: number = 2
|
||||||
|
hideBadgeOnMobile: boolean = false
|
||||||
|
hideDescriptionOnMobile: boolean = false
|
||||||
|
mobileActionSize: string = "default"
|
||||||
|
gutter: string = "md"
|
||||||
|
contentGutter: string = "md"
|
||||||
|
flushMobile: boolean = false
|
||||||
size: string = "default"
|
size: string = "default"
|
||||||
width: string = "default"
|
width: string = "default"
|
||||||
color: string = "primary"
|
color: string = "primary"
|
||||||
@@ -36,6 +45,7 @@ badge: string = ""
|
|||||||
data-color='{color}'
|
data-color='{color}'
|
||||||
data-variant='{variant}'
|
data-variant='{variant}'
|
||||||
data-compact='{compact}'
|
data-compact='{compact}'
|
||||||
|
data-flush='{flush ? "true" : "false"}' data-mobile-compact='{mobileCompact ? "true" : "false"}' data-mobile-message-lines='{mobileMessageLines}' data-hide-badge-mobile='{hideBadgeOnMobile ? "true" : "false"}' data-hide-description-mobile='{hideDescriptionOnMobile ? "true" : "false"}' data-mobile-action-size='{mobileActionSize}' data-gutter='{gutter}' data-content-gutter='{contentGutter}' data-flush-mobile='{flushMobile ? "true" : "false"}'
|
||||||
data-sticky='{sticky}'
|
data-sticky='{sticky}'
|
||||||
data-show='{!dismissed}'
|
data-show='{!dismissed}'
|
||||||
aria-hidden='{dismissed ? "true" : "false"}'
|
aria-hidden='{dismissed ? "true" : "false"}'
|
||||||
@@ -152,9 +162,9 @@ badge: string = ""
|
|||||||
position: relative;
|
position: relative;
|
||||||
z-index: 40;
|
z-index: 40;
|
||||||
display: block;
|
display: block;
|
||||||
width: 100vw;
|
width: 100%;
|
||||||
max-width: 100vw;
|
max-width: 100%;
|
||||||
margin-inline: calc(50% - 50vw);
|
margin-inline: 0;
|
||||||
color: var(--wrn-color-text);
|
color: var(--wrn-color-text);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,6 +173,8 @@ badge: string = ""
|
|||||||
margin-inline: auto;
|
margin-inline: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.wrn-announcement[data-flush="true"] .wrn-announcement__surface { border-radius: 0; box-shadow: none; }
|
||||||
|
|
||||||
.wrn-announcement[data-width="wide"] .wrn-announcement__surface {
|
.wrn-announcement[data-width="wide"] .wrn-announcement__surface {
|
||||||
width: min(calc(100% - 2rem), 90rem);
|
width: min(calc(100% - 2rem), 90rem);
|
||||||
}
|
}
|
||||||
@@ -573,6 +585,15 @@ badge: string = ""
|
|||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 639px) {
|
@media (max-width: 639px) {
|
||||||
|
.wrn-announcement[data-mobile-compact="true"] .wrn-announcement__inner,
|
||||||
|
.wrn-announcement[data-compact="true"] .wrn-announcement__inner { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 0.65rem; }
|
||||||
|
.wrn-announcement[data-hide-badge-mobile="true"] .wrn-announcement__badge,
|
||||||
|
.wrn-announcement[data-mobile-compact="true"] .wrn-announcement__badge { display: none; }
|
||||||
|
.wrn-announcement[data-hide-description-mobile="true"] .wrn-announcement__description,
|
||||||
|
.wrn-announcement[data-mobile-compact="true"] .wrn-announcement__description { display: none; }
|
||||||
|
.wrn-announcement[data-mobile-message-lines="2"] .wrn-announcement__message { display: -webkit-box; overflow: hidden; -webkit-box-orient: vertical; -webkit-line-clamp: 2; }
|
||||||
|
.wrn-announcement[data-mobile-action-size="sm"] .wrn-announcement__action { min-height: 2.25rem; padding-inline: 0.7rem; }
|
||||||
|
.wrn-announcement[data-flush-mobile="false"] .wrn-announcement__inner { padding-inline: 1rem; }
|
||||||
.wrn-announcement__surface,
|
.wrn-announcement__surface,
|
||||||
.wrn-announcement[data-width="wide"] .wrn-announcement__surface {
|
.wrn-announcement[data-width="wide"] .wrn-announcement__surface {
|
||||||
width: calc(100% - 1rem);
|
width: calc(100% - 1rem);
|
||||||
|
|||||||
@@ -120,11 +120,11 @@ component BackToTop {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.wrn-back-to-top[data-position="right"] {
|
.wrn-back-to-top[data-position="right"] {
|
||||||
right: 1.5rem;
|
right: max(1.5rem, env(safe-area-inset-right));
|
||||||
}
|
}
|
||||||
|
|
||||||
.wrn-back-to-top[data-position="left"] {
|
.wrn-back-to-top[data-position="left"] {
|
||||||
left: 1.5rem;
|
left: max(1.5rem, env(safe-area-inset-left));
|
||||||
}
|
}
|
||||||
|
|
||||||
.wrn-back-to-top[data-position="center"] {
|
.wrn-back-to-top[data-position="center"] {
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ component Blockquote {
|
|||||||
variant: string = "default"
|
variant: string = "default"
|
||||||
quoteMark: boolean = true
|
quoteMark: boolean = true
|
||||||
italic: boolean = true
|
italic: boolean = true
|
||||||
|
maxWidth: string = "xl"
|
||||||
class: string = ""
|
class: string = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -24,6 +25,7 @@ component Blockquote {
|
|||||||
data-align="{align}"
|
data-align="{align}"
|
||||||
data-variant="{variant}"
|
data-variant="{variant}"
|
||||||
data-italic="{italic}"
|
data-italic="{italic}"
|
||||||
|
data-max-width="{maxWidth}"
|
||||||
>
|
>
|
||||||
<blockquote cite="{citationUrl}">
|
<blockquote cite="{citationUrl}">
|
||||||
{#if quoteMark}
|
{#if quoteMark}
|
||||||
@@ -73,10 +75,17 @@ component Blockquote {
|
|||||||
display: grid;
|
display: grid;
|
||||||
gap: 1.25rem;
|
gap: 1.25rem;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
max-width: var(--wrn-blockquote-max-width, 48rem);
|
||||||
color: var(--wrn-color-text);
|
color: var(--wrn-color-text);
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.wrn-next--blockquote[data-max-width="sm"] { --wrn-blockquote-max-width: 32rem; }
|
||||||
|
.wrn-next--blockquote[data-max-width="md"] { --wrn-blockquote-max-width: 40rem; }
|
||||||
|
.wrn-next--blockquote[data-max-width="lg"] { --wrn-blockquote-max-width: 48rem; }
|
||||||
|
.wrn-next--blockquote[data-max-width="xl"] { --wrn-blockquote-max-width: 64rem; }
|
||||||
|
.wrn-next--blockquote[data-max-width="full"] { --wrn-blockquote-max-width: 100%; }
|
||||||
|
|
||||||
.wrn-next--blockquote[data-size="xs"] {
|
.wrn-next--blockquote[data-size="xs"] {
|
||||||
--wrn-blockquote-font-size: 0.875rem;
|
--wrn-blockquote-font-size: 0.875rem;
|
||||||
--wrn-blockquote-mark-size: 3rem;
|
--wrn-blockquote-mark-size: 3rem;
|
||||||
@@ -189,8 +198,19 @@ component Blockquote {
|
|||||||
|
|
||||||
.wrn-next--blockquote[data-align="center"] {
|
.wrn-next--blockquote[data-align="center"] {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
margin-inline: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.wrn-next--blockquote:is([data-variant="contained"], [data-variant="spotlight"], [data-variant="card"]) {
|
||||||
|
padding: clamp(1.5rem, 4vw, 3rem);
|
||||||
|
border: 1px solid color-mix(in srgb, var(--wrn-blockquote-color) 24%, var(--wrn-color-border));
|
||||||
|
border-radius: calc(var(--wrn-radius) * 2);
|
||||||
|
background: linear-gradient(145deg, color-mix(in srgb, var(--wrn-blockquote-color) 8%, var(--wrn-color-surface-raised)), var(--wrn-color-surface-raised));
|
||||||
|
box-shadow: var(--wrn-shadow-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrn-next--blockquote[data-variant="spotlight"] > blockquote { padding-top: calc(var(--wrn-blockquote-mark-size) * 0.55); }
|
||||||
|
|
||||||
.wrn-next--blockquote[data-align="right"],
|
.wrn-next--blockquote[data-align="right"],
|
||||||
.wrn-next--blockquote[data-align="end"] {
|
.wrn-next--blockquote[data-align="end"] {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ component Breadcrumb {
|
|||||||
label: string = "Breadcrumb"
|
label: string = "Breadcrumb"
|
||||||
items: unknown[] = []
|
items: unknown[] = []
|
||||||
active: string = ""
|
active: string = ""
|
||||||
|
activeIcon: string = "icon-[lucide--file-text]"
|
||||||
separator: string = "chevron"
|
separator: string = "chevron"
|
||||||
showHome: boolean = false
|
showHome: boolean = false
|
||||||
homeLabel: string = "Home"
|
homeLabel: string = "Home"
|
||||||
@@ -61,7 +62,7 @@ label: string = "Breadcrumb"
|
|||||||
{:else if separator === "arrow"}
|
{:else if separator === "arrow"}
|
||||||
<span>→</span>
|
<span>→</span>
|
||||||
{:else}
|
{:else}
|
||||||
<span class="icon-[lucide--chevron-right] wrn-breadcrumb__separator-icon"></span>
|
<span class="wrn-breadcrumb__separator-icon">›</span>
|
||||||
{/if}
|
{/if}
|
||||||
</span>
|
</span>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -99,6 +100,30 @@ label: string = "Breadcrumb"
|
|||||||
{/if}
|
{/if}
|
||||||
</li>
|
</li>
|
||||||
{/each}
|
{/each}
|
||||||
|
|
||||||
|
{#if active && !items.some((item) => active === (item.value || item.label || item.title))}
|
||||||
|
<li class="wrn-breadcrumb__item" data-current="true">
|
||||||
|
{#if showHome || items.length > 0}
|
||||||
|
<span class="wrn-breadcrumb__separator" aria-hidden="true">
|
||||||
|
{#if separator === "slash"}
|
||||||
|
<span>/</span>
|
||||||
|
{:else if separator === "dot"}
|
||||||
|
<span>•</span>
|
||||||
|
{:else if separator === "arrow"}
|
||||||
|
<span>→</span>
|
||||||
|
{:else}
|
||||||
|
<span class="wrn-breadcrumb__separator-icon">›</span>
|
||||||
|
{/if}
|
||||||
|
</span>
|
||||||
|
{/if}
|
||||||
|
<span class="wrn-breadcrumb__current" aria-current="page">
|
||||||
|
{#if activeIcon}
|
||||||
|
<span class='{activeIcon} wrn-breadcrumb__icon' aria-hidden="true"></span>
|
||||||
|
{/if}
|
||||||
|
<span class="wrn-breadcrumb__label">{active}</span>
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
{/if}
|
||||||
</ol>
|
</ol>
|
||||||
</nav>
|
</nav>
|
||||||
}
|
}
|
||||||
@@ -207,8 +232,14 @@ label: string = "Breadcrumb"
|
|||||||
}
|
}
|
||||||
|
|
||||||
.wrn-breadcrumb__separator-icon {
|
.wrn-breadcrumb__separator-icon {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
width: 0.9rem;
|
width: 0.9rem;
|
||||||
height: 0.9rem;
|
height: 0.9rem;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wrn-breadcrumb__link,
|
.wrn-breadcrumb__link,
|
||||||
|
|||||||
@@ -8,6 +8,12 @@ component CTASection {
|
|||||||
size: string = "default"
|
size: string = "default"
|
||||||
color: string = "primary"
|
color: string = "primary"
|
||||||
variant: string = "solid"
|
variant: string = "solid"
|
||||||
|
spacing: string = "none"
|
||||||
|
radius: string = "default"
|
||||||
|
titleMaxWidth: string = ""
|
||||||
|
contentPadding: string = "default"
|
||||||
|
mobilePadding: string = "default"
|
||||||
|
mobileActions: string = "stack"
|
||||||
primaryLabel: string = "Get started"
|
primaryLabel: string = "Get started"
|
||||||
primaryHref: string = "#"
|
primaryHref: string = "#"
|
||||||
primaryIcon: string = ""
|
primaryIcon: string = ""
|
||||||
@@ -35,6 +41,9 @@ component CTASection {
|
|||||||
data-size='{size}'
|
data-size='{size}'
|
||||||
data-color='{color}'
|
data-color='{color}'
|
||||||
data-variant='{variant}'
|
data-variant='{variant}'
|
||||||
|
data-spacing='{spacing}'
|
||||||
|
data-radius='{radius}' data-content-padding='{contentPadding}' data-mobile-padding='{mobilePadding}' data-mobile-actions='{mobileActions}'
|
||||||
|
style='--wrn-cta-title-max-width: {titleMaxWidth || "18ch"}'
|
||||||
data-max-width='{maxWidth}'
|
data-max-width='{maxWidth}'
|
||||||
data-full-bleed='{fullBleed ? "true" : "false"}'
|
data-full-bleed='{fullBleed ? "true" : "false"}'
|
||||||
data-visual-position='{visualPosition}'
|
data-visual-position='{visualPosition}'
|
||||||
@@ -186,6 +195,18 @@ component CTASection {
|
|||||||
--cta-contrast: var(--wrn-color-secondary-contrast);
|
--cta-contrast: var(--wrn-color-secondary-contrast);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.wrn-cta-section[data-spacing="sm"] {
|
||||||
|
padding-block: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrn-cta-section[data-spacing="md"] {
|
||||||
|
padding-block: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrn-cta-section[data-spacing="lg"] {
|
||||||
|
padding-block: 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
.wrn-cta-section[data-color="info"] {
|
.wrn-cta-section[data-color="info"] {
|
||||||
--cta-accent: var(--wrn-color-info);
|
--cta-accent: var(--wrn-color-info);
|
||||||
--cta-accent-hover: var(--wrn-color-info-hover);
|
--cta-accent-hover: var(--wrn-color-info-hover);
|
||||||
@@ -223,6 +244,20 @@ component CTASection {
|
|||||||
margin-inline: auto;
|
margin-inline: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 640px) {
|
||||||
|
.wrn-cta-section[data-spacing="sm"] {
|
||||||
|
padding-block: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrn-cta-section[data-spacing="md"] {
|
||||||
|
padding-block: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrn-cta-section[data-spacing="lg"] {
|
||||||
|
padding-block: 2.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.wrn-cta-section[data-max-width="compact"] .wrn-cta-section__outer {
|
.wrn-cta-section[data-max-width="compact"] .wrn-cta-section__outer {
|
||||||
width: min(calc(100% - 2rem), 64rem);
|
width: min(calc(100% - 2rem), 64rem);
|
||||||
}
|
}
|
||||||
@@ -260,6 +295,8 @@ component CTASection {
|
|||||||
0 1px 0 color-mix(in srgb, white 5%, transparent) inset,
|
0 1px 0 color-mix(in srgb, white 5%, transparent) inset,
|
||||||
0 24px 70px color-mix(in srgb, black 15%, transparent);
|
0 24px 70px color-mix(in srgb, black 15%, transparent);
|
||||||
}
|
}
|
||||||
|
.wrn-cta-section[data-radius="xl"] .wrn-cta-section__surface { border-radius: 1.5rem; }
|
||||||
|
.wrn-cta-section[data-content-padding="lg"] .wrn-cta-section__surface { padding: 3.5rem clamp(1.5rem, 5vw, 4rem); }
|
||||||
|
|
||||||
.wrn-cta-section[data-size="compact"] .wrn-cta-section__surface,
|
.wrn-cta-section[data-size="compact"] .wrn-cta-section__surface,
|
||||||
.wrn-cta-section[data-size="sm"] .wrn-cta-section__surface {
|
.wrn-cta-section[data-size="sm"] .wrn-cta-section__surface {
|
||||||
@@ -401,7 +438,7 @@ component CTASection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.wrn-cta-section__title {
|
.wrn-cta-section__title {
|
||||||
max-width: 18ch;
|
max-width: var(--wrn-cta-title-max-width);
|
||||||
margin: 0.75rem 0 0;
|
margin: 0.75rem 0 0;
|
||||||
color: var(--wrn-color-text);
|
color: var(--wrn-color-text);
|
||||||
font-size: clamp(2rem, 5vw, 4rem);
|
font-size: clamp(2rem, 5vw, 4rem);
|
||||||
@@ -637,11 +674,11 @@ component CTASection {
|
|||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wrn-cta-section__footer:empty {
|
.wrn-cta-section__footer:not(:has(> *)) {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wrn-cta-section__footer:not(:empty) {
|
.wrn-cta-section__footer:has(> *) {
|
||||||
margin-top: 2rem;
|
margin-top: 2rem;
|
||||||
padding-top: 1.25rem;
|
padding-top: 1.25rem;
|
||||||
border-top: 1px solid color-mix(in srgb, currentColor 14%, transparent);
|
border-top: 1px solid color-mix(in srgb, currentColor 14%, transparent);
|
||||||
@@ -671,6 +708,8 @@ component CTASection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 639px) {
|
@media (max-width: 639px) {
|
||||||
|
.wrn-cta-section[data-mobile-padding="md"] .wrn-cta-section__surface { padding: 2.5rem 1.25rem; }
|
||||||
|
.wrn-cta-section[data-mobile-actions="inline"] .wrn-cta-section__action { width: auto; }
|
||||||
.wrn-cta-section__surface {
|
.wrn-cta-section__surface {
|
||||||
padding: 1.6rem;
|
padding: 1.6rem;
|
||||||
border-radius: 1.2rem;
|
border-radius: 1.2rem;
|
||||||
|
|||||||
@@ -9,7 +9,8 @@ component Card {
|
|||||||
}
|
}
|
||||||
|
|
||||||
props {
|
props {
|
||||||
title: string = "Card title"
|
title: string = ""
|
||||||
|
icon: string = ""
|
||||||
titleKey: string = ""
|
titleKey: string = ""
|
||||||
subtitle: string = ""
|
subtitle: string = ""
|
||||||
subtitleKey: string = ""
|
subtitleKey: string = ""
|
||||||
@@ -39,6 +40,9 @@ component Card {
|
|||||||
layout: string = "vertical"
|
layout: string = "vertical"
|
||||||
align: string = "left"
|
align: string = "left"
|
||||||
hover: string = "none"
|
hover: string = "none"
|
||||||
|
radius: string = "default"
|
||||||
|
shadow: string = "default"
|
||||||
|
equalHeight: boolean = false
|
||||||
scrollable: boolean = false
|
scrollable: boolean = false
|
||||||
maxHeight: string = "18rem"
|
maxHeight: string = "18rem"
|
||||||
dismissible: boolean = false
|
dismissible: boolean = false
|
||||||
@@ -84,6 +88,7 @@ component Card {
|
|||||||
data-layout='{layout}'
|
data-layout='{layout}'
|
||||||
data-hover='{hover}'
|
data-hover='{hover}'
|
||||||
data-align='{align}'
|
data-align='{align}'
|
||||||
|
data-radius='{radius}' data-shadow='{shadow}' data-equal-height='{equalHeight ? "true" : "false"}'
|
||||||
class='wrn-component wrn-next--card wrn-component--color-{color} wrn-component--size-{size} wrn-next--variant-{variant} {class}'
|
class='wrn-component wrn-next--card wrn-component--color-{color} wrn-component--size-{size} wrn-next--variant-{variant} {class}'
|
||||||
>
|
>
|
||||||
{#if items.length > 0}
|
{#if items.length > 0}
|
||||||
@@ -271,6 +276,7 @@ component Card {
|
|||||||
<p>{emptyTitle}</p>
|
<p>{emptyTitle}</p>
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
|
{#if icon}<span class='wrn-next__card-icon {icon}' aria-hidden="true"></span>{/if}
|
||||||
{#if description}
|
{#if description}
|
||||||
<p class="wrn-next__card-description" data-t='{descriptionKey}'>{description}</p>
|
<p class="wrn-next__card-description" data-t='{descriptionKey}'>{description}</p>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -343,6 +349,12 @@ component Card {
|
|||||||
.wrn-next--card[data-size="sm"] {
|
.wrn-next--card[data-size="sm"] {
|
||||||
--wrn-card-padding: 0.85rem;
|
--wrn-card-padding: 0.85rem;
|
||||||
}
|
}
|
||||||
|
.wrn-next--card[data-size="compact"] .wrn-next__card-body { padding: 1rem; }
|
||||||
|
.wrn-next--card[data-radius="lg"] > .wrn-next__card-panel { border-radius: 1rem; }
|
||||||
|
.wrn-next--card[data-shadow="none"] > .wrn-next__card-panel { box-shadow: none; }
|
||||||
|
.wrn-next--card[data-equal-height="true"], .wrn-next--card[data-equal-height="true"] > .wrn-next__card-panel { height: 100%; }
|
||||||
|
.wrn-next--card[data-layout="horizontal"] .wrn-next__card-body { display: grid; grid-template-columns: auto 1fr; align-items: center; gap: 0.8rem; }
|
||||||
|
.wrn-next__card-icon { display: grid; width: 2.35rem; height: 2.35rem; place-items: center; border-radius: 0.7rem; color: var(--wrn-color-primary); background: color-mix(in srgb, var(--wrn-color-primary) 12%, transparent); font-size: 1.15rem; }
|
||||||
|
|
||||||
.wrn-next--card[data-size="lg"] {
|
.wrn-next--card[data-size="lg"] {
|
||||||
--wrn-card-padding: 1.75rem;
|
--wrn-card-padding: 1.75rem;
|
||||||
|
|||||||
@@ -205,7 +205,9 @@ component ColorPicker {
|
|||||||
}
|
}
|
||||||
.wrn-next__field-heading label {
|
.wrn-next__field-heading label {
|
||||||
color: var(--wrn-color-text);
|
color: var(--wrn-color-text);
|
||||||
|
font-size: 0.8125rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
line-height: 1.35;
|
||||||
}
|
}
|
||||||
.wrn-next__field-hint,
|
.wrn-next__field-hint,
|
||||||
.wrn-next__field-help {
|
.wrn-next__field-help {
|
||||||
|
|||||||
@@ -276,7 +276,9 @@ size: string = "default"
|
|||||||
}
|
}
|
||||||
.wrn-next__field-heading label {
|
.wrn-next__field-heading label {
|
||||||
color: var(--wrn-color-text);
|
color: var(--wrn-color-text);
|
||||||
|
font-size: 0.8125rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
line-height: 1.35;
|
||||||
}
|
}
|
||||||
.wrn-next__field-hint,
|
.wrn-next__field-hint,
|
||||||
.wrn-next__field-help {
|
.wrn-next__field-help {
|
||||||
|
|||||||
@@ -15,13 +15,17 @@ component FeatureIconCard {
|
|||||||
variant: string = "default"
|
variant: string = "default"
|
||||||
align: string = "left"
|
align: string = "left"
|
||||||
hover: string = "lift"
|
hover: string = "lift"
|
||||||
|
radius: string = "default"
|
||||||
|
shadow: string = "default"
|
||||||
|
clickableSurface: boolean = false
|
||||||
|
descriptionTone: string = "default"
|
||||||
class: string = ""
|
class: string = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
view {
|
view {
|
||||||
<article
|
<article
|
||||||
data-ui-component="FeatureIconCard"
|
data-ui-component="FeatureIconCard"
|
||||||
data-size='{size}' data-variant='{variant}' data-hover='{hover}' data-align='{align}'
|
data-size='{size}' data-variant='{variant}' data-hover='{hover}' data-align='{align}' data-radius='{radius}' data-shadow='{shadow}' data-clickable-surface='{clickableSurface ? "true" : "false"}' data-description-tone='{descriptionTone}'
|
||||||
class='wrn-feature-icon-card {class}'
|
class='wrn-feature-icon-card {class}'
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
@@ -62,6 +66,11 @@ component FeatureIconCard {
|
|||||||
style {
|
style {
|
||||||
.wrn-feature-icon-card { position: relative; display: flex; height: 100%; flex-direction: column; padding: 1.5rem; border: 1px solid var(--wrn-color-border); border-radius: calc(var(--wrn-radius) * 2); background: var(--wrn-color-surface-raised); box-shadow: var(--wrn-shadow-1); transition: transform var(--wrn-motion-base), border-color var(--wrn-motion-base), box-shadow var(--wrn-motion-base); }
|
.wrn-feature-icon-card { position: relative; display: flex; height: 100%; flex-direction: column; padding: 1.5rem; border: 1px solid var(--wrn-color-border); border-radius: calc(var(--wrn-radius) * 2); background: var(--wrn-color-surface-raised); box-shadow: var(--wrn-shadow-1); transition: transform var(--wrn-motion-base), border-color var(--wrn-motion-base), box-shadow var(--wrn-motion-base); }
|
||||||
.wrn-feature-icon-card[data-size="sm"] { padding: 1.25rem; } .wrn-feature-icon-card[data-size="lg"] { padding: 2rem; }
|
.wrn-feature-icon-card[data-size="sm"] { padding: 1.25rem; } .wrn-feature-icon-card[data-size="lg"] { padding: 2rem; }
|
||||||
|
.wrn-feature-icon-card[data-size="compact"] { min-height: 0; padding: 1.25rem; }
|
||||||
|
.wrn-feature-icon-card[data-radius="lg"] { border-radius: 1rem; }
|
||||||
|
.wrn-feature-icon-card[data-shadow="sm"] { box-shadow: 0 5px 18px rgb(15 23 42 / 0.06); }
|
||||||
|
.wrn-feature-icon-card[data-description-tone="muted"] .wrn-feature-icon-card__description { color: var(--wrn-color-text-muted); font-weight: 500; }
|
||||||
|
.wrn-feature-icon-card[data-clickable-surface="true"] .wrn-feature-icon-card__action::after { position: absolute; inset: 0; content: ""; }
|
||||||
.wrn-feature-icon-card[data-variant="soft"] { background: var(--wrn-color-surface-soft); }
|
.wrn-feature-icon-card[data-variant="soft"] { background: var(--wrn-color-surface-soft); }
|
||||||
.wrn-feature-icon-card[data-variant="ghost"] { border-color: transparent; background: transparent; box-shadow: none; }
|
.wrn-feature-icon-card[data-variant="ghost"] { border-color: transparent; background: transparent; box-shadow: none; }
|
||||||
.wrn-feature-icon-card[data-hover="lift"]:hover { transform: translateY(-0.25rem); }
|
.wrn-feature-icon-card[data-hover="lift"]:hover { transform: translateY(-0.25rem); }
|
||||||
|
|||||||
@@ -230,7 +230,9 @@ size: string = "default"
|
|||||||
}
|
}
|
||||||
.wrn-next__field-heading label {
|
.wrn-next__field-heading label {
|
||||||
color: var(--wrn-color-text);
|
color: var(--wrn-color-text);
|
||||||
|
font-size: 0.8125rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
line-height: 1.35;
|
||||||
}
|
}
|
||||||
.wrn-next__field-hint,
|
.wrn-next__field-hint,
|
||||||
.wrn-next__field-help {
|
.wrn-next__field-help {
|
||||||
|
|||||||
@@ -244,7 +244,9 @@ size: string = "default"
|
|||||||
}
|
}
|
||||||
.wrn-next__field-heading label {
|
.wrn-next__field-heading label {
|
||||||
color: var(--wrn-color-text);
|
color: var(--wrn-color-text);
|
||||||
|
font-size: 0.8125rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
line-height: 1.35;
|
||||||
}
|
}
|
||||||
.wrn-next__field-hint,
|
.wrn-next__field-hint,
|
||||||
.wrn-next__field-help {
|
.wrn-next__field-help {
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ component Footer {
|
|||||||
items: unknown[] = []
|
items: unknown[] = []
|
||||||
columns: number = 3
|
columns: number = 3
|
||||||
maxWidth: string = "compact"
|
maxWidth: string = "compact"
|
||||||
|
mobileColumns: number = 2
|
||||||
|
mobileCopyrightAlign: string = "center"
|
||||||
copyright: string = ""
|
copyright: string = ""
|
||||||
copyrightKey: string = ""
|
copyrightKey: string = ""
|
||||||
translationPrefix: string = ""
|
translationPrefix: string = ""
|
||||||
@@ -36,6 +38,7 @@ component Footer {
|
|||||||
data-ui-component="Footer"
|
data-ui-component="Footer"
|
||||||
data-size='{size}'
|
data-size='{size}'
|
||||||
data-color='{color}'
|
data-color='{color}'
|
||||||
|
data-mobile-columns='{mobileColumns}' data-mobile-copyright-align='{mobileCopyrightAlign}'
|
||||||
class='wrn-footer {maxWidth === "full" ? "wrn-footer--width-full" : ""} {class}'
|
class='wrn-footer {maxWidth === "full" ? "wrn-footer--width-full" : ""} {class}'
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
@@ -531,6 +534,9 @@ component Footer {
|
|||||||
.wrn-footer__links {
|
.wrn-footer__links {
|
||||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
}
|
}
|
||||||
|
.wrn-footer[data-mobile-columns="1"] .wrn-footer__links { grid-template-columns: 1fr; }
|
||||||
|
.wrn-footer[data-mobile-columns="2"] .wrn-footer__links { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
||||||
|
.wrn-footer[data-mobile-copyright-align="start"] :is(.wrn-footer__copyright-left, .wrn-footer__copyright-right) { justify-content: flex-start; text-align: left; }
|
||||||
.wrn-footer__bottom,
|
.wrn-footer__bottom,
|
||||||
.wrn-footer__bottom--slots {
|
.wrn-footer__bottom--slots {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
|
|||||||
@@ -280,22 +280,14 @@ component Hero {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.wrn-hero[data-full-bleed="true"] {
|
.wrn-hero[data-full-bleed="true"] {
|
||||||
width: 100vw;
|
width: 100%;
|
||||||
max-width: 100vw;
|
max-width: 100%;
|
||||||
margin-inline: calc(50% - 50vw);
|
margin-inline: 0;
|
||||||
border-right-width: 0;
|
border-right-width: 0;
|
||||||
border-left-width: 0;
|
border-left-width: 0;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@supports (width: 100dvw) {
|
|
||||||
.wrn-hero[data-full-bleed="true"] {
|
|
||||||
width: 100dvw;
|
|
||||||
max-width: 100dvw;
|
|
||||||
margin-inline: calc(50% - 50dvw);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.wrn-hero[data-color="secondary"] {
|
.wrn-hero[data-color="secondary"] {
|
||||||
--wrn-hero-accent: var(--wrn-color-secondary);
|
--wrn-hero-accent: var(--wrn-color-secondary);
|
||||||
--wrn-hero-accent-soft: var(--wrn-color-secondary-soft, var(--wrn-color-primary-soft));
|
--wrn-hero-accent-soft: var(--wrn-color-secondary-soft, var(--wrn-color-primary-soft));
|
||||||
|
|||||||
@@ -243,7 +243,9 @@ component InputGroup {
|
|||||||
}
|
}
|
||||||
.wrn-next__field-heading label {
|
.wrn-next__field-heading label {
|
||||||
color: var(--wrn-color-text);
|
color: var(--wrn-color-text);
|
||||||
|
font-size: 0.8125rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
line-height: 1.35;
|
||||||
}
|
}
|
||||||
.wrn-next__field-hint,
|
.wrn-next__field-hint,
|
||||||
.wrn-next__field-help {
|
.wrn-next__field-help {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ component MegaMenu {
|
|||||||
open(payload: { sourceEvent: Event })
|
open(payload: { sourceEvent: Event })
|
||||||
close(payload: { reason: string })
|
close(payload: { reason: string })
|
||||||
select(payload: { item: object; value: string })
|
select(payload: { item: object; value: string })
|
||||||
|
category(payload: { item: object; value: string; index: number })
|
||||||
}
|
}
|
||||||
|
|
||||||
props {
|
props {
|
||||||
@@ -26,12 +27,27 @@ component MegaMenu {
|
|||||||
label: string = "Menu"
|
label: string = "Menu"
|
||||||
icon: string = ""
|
icon: string = ""
|
||||||
columns: unknown[] = []
|
columns: unknown[] = []
|
||||||
|
rail: unknown[] = []
|
||||||
|
featured: Record<string, unknown> = {}
|
||||||
|
variant: string = "default"
|
||||||
|
density: string = "default"
|
||||||
|
panelWidth: string = "xl"
|
||||||
|
panelAlign: string = "start"
|
||||||
|
columnCount: number = 0
|
||||||
|
fullWidth: boolean = false
|
||||||
|
openOnHover: boolean = true
|
||||||
|
activeCategory: string = ""
|
||||||
|
actionLabel: string = ""
|
||||||
|
actionHref: string = ""
|
||||||
|
actionIcon: string = "icon-[lucide--arrow-right]"
|
||||||
footer: string = ""
|
footer: string = ""
|
||||||
defaultOpen: boolean = false
|
defaultOpen: boolean = false
|
||||||
class: string = ""
|
class: string = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
state visible = defaultOpen
|
state visible = defaultOpen
|
||||||
|
state closeTimer = null
|
||||||
|
state selectedCategory = activeCategory
|
||||||
|
|
||||||
functions {
|
functions {
|
||||||
shared function columnList() {
|
shared function columnList() {
|
||||||
@@ -42,16 +58,66 @@ component MegaMenu {
|
|||||||
return column && Array.isArray(column.items) ? column.items : []
|
return column && Array.isArray(column.items) ? column.items : []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
shared function railList() {
|
||||||
|
return Array.isArray(rail) ? rail : []
|
||||||
|
}
|
||||||
|
|
||||||
|
shared function categoryValue(item) {
|
||||||
|
return item ? String(item.value || item.href || item.label || "") : ""
|
||||||
|
}
|
||||||
|
|
||||||
|
shared function activeCategoryIndex() {
|
||||||
|
const entries = railList()
|
||||||
|
if (!entries.length) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
if (!selectedCategory) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
for (let index = 0; index < entries.length; index += 1) {
|
||||||
|
if (categoryValue(entries[index]) === selectedCategory) {
|
||||||
|
return index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
shared function visibleColumns() {
|
||||||
|
const entries = columnList()
|
||||||
|
if (variant !== "catalog") {
|
||||||
|
return entries
|
||||||
|
}
|
||||||
|
const selected = entries[activeCategoryIndex()]
|
||||||
|
return selected ? [selected] : []
|
||||||
|
}
|
||||||
|
|
||||||
client function showPanel(sourceEvent) {
|
client function showPanel(sourceEvent) {
|
||||||
|
cancelScheduledHide()
|
||||||
visible = true
|
visible = true
|
||||||
output.open({ sourceEvent: sourceEvent })
|
output.open({ sourceEvent: sourceEvent })
|
||||||
}
|
}
|
||||||
|
|
||||||
client function hidePanel(reason) {
|
client function hidePanel(reason) {
|
||||||
|
cancelScheduledHide()
|
||||||
visible = false
|
visible = false
|
||||||
output.close({ reason: reason })
|
output.close({ reason: reason })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
client function cancelScheduledHide() {
|
||||||
|
if (closeTimer) {
|
||||||
|
window.clearTimeout(closeTimer)
|
||||||
|
closeTimer = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
client function scheduleHide() {
|
||||||
|
cancelScheduledHide()
|
||||||
|
closeTimer = window.setTimeout(function () {
|
||||||
|
closeTimer = null
|
||||||
|
hidePanel("pointer-leave")
|
||||||
|
}, 220)
|
||||||
|
}
|
||||||
|
|
||||||
client function togglePanel(sourceEvent) {
|
client function togglePanel(sourceEvent) {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
hidePanel("toggle")
|
hidePanel("toggle")
|
||||||
@@ -60,6 +126,34 @@ component MegaMenu {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
client function activatePanel(sourceEvent) {
|
||||||
|
if (openOnHover) {
|
||||||
|
showPanel(sourceEvent)
|
||||||
|
} else {
|
||||||
|
togglePanel(sourceEvent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
client function hoverPanel(sourceEvent) {
|
||||||
|
if (openOnHover) {
|
||||||
|
showPanel(sourceEvent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
client function chooseCategory(item, index, sourceEvent) {
|
||||||
|
const root = sourceEvent.currentTarget.closest(".wrn-mega")
|
||||||
|
const rail = sourceEvent.currentTarget.closest(".wrn-mega__rail")
|
||||||
|
const scrollTop = rail ? rail.scrollTop : 0
|
||||||
|
selectedCategory = categoryValue(item)
|
||||||
|
output.category({ item: item, value: selectedCategory, index: index })
|
||||||
|
window.requestAnimationFrame(function () {
|
||||||
|
const nextRail = root ? root.querySelector(".wrn-mega__rail") : null
|
||||||
|
if (nextRail) {
|
||||||
|
nextRail.scrollTop = scrollTop
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
client function handleKeydown(sourceEvent) {
|
client function handleKeydown(sourceEvent) {
|
||||||
if (sourceEvent.key === "Escape" && visible) {
|
if (sourceEvent.key === "Escape" && visible) {
|
||||||
sourceEvent.preventDefault()
|
sourceEvent.preventDefault()
|
||||||
@@ -84,20 +178,27 @@ component MegaMenu {
|
|||||||
data-color='{color}'
|
data-color='{color}'
|
||||||
data-size='{size}'
|
data-size='{size}'
|
||||||
data-open='{visible}'
|
data-open='{visible}'
|
||||||
|
data-variant='{variant}'
|
||||||
|
data-density='{density}'
|
||||||
|
data-panel-width='{panelWidth}'
|
||||||
|
data-panel-align='{panelAlign}'
|
||||||
|
data-full-width='{fullWidth ? "true" : "false"}'
|
||||||
|
data-column-count='{columnCount}'
|
||||||
@keydown='handleKeydown(event)'
|
@keydown='handleKeydown(event)'
|
||||||
@mouseleave='hidePanel("pointer-leave")'
|
@mouseenter='cancelScheduledHide()'
|
||||||
|
@mouseleave='scheduleHide()'
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="wrn-mega__trigger"
|
class="wrn-mega__trigger"
|
||||||
aria-haspopup="true"
|
aria-haspopup="true"
|
||||||
aria-expanded='{visible}'
|
aria-expanded='{visible}'
|
||||||
@click='togglePanel(event)'
|
aria-label='{label}'
|
||||||
@mouseenter='showPanel(event)'
|
@click='activatePanel(event)'
|
||||||
@focus='showPanel(event)'
|
@mouseenter='hoverPanel(event)'
|
||||||
>
|
>
|
||||||
<span class='wrn-mega__trigger-icon {icon}' data-show="icon" aria-hidden="true"></span>
|
<span class='wrn-mega__trigger-icon {icon}' data-show="icon" aria-hidden="true"></span>
|
||||||
<span class="wrn-mega__trigger-label">{label}</span>
|
<span class="wrn-mega__trigger-label" data-label='{label}' aria-hidden="true"></span>
|
||||||
<span class="wrn-mega__arrow" aria-hidden="true">›</span>
|
<span class="wrn-mega__arrow" aria-hidden="true">›</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
@@ -105,42 +206,76 @@ component MegaMenu {
|
|||||||
class="wrn-mega__panel"
|
class="wrn-mega__panel"
|
||||||
data-wrn-anchored="true"
|
data-wrn-anchored="true"
|
||||||
data-show="visible"
|
data-show="visible"
|
||||||
|
style='{visible ? "" : "display:none"}'
|
||||||
data-wrn-roving="both"
|
data-wrn-roving="both"
|
||||||
|
@mouseenter='cancelScheduledHide()'
|
||||||
>
|
>
|
||||||
<div class="wrn-mega__columns">
|
<div class="wrn-mega__layout">
|
||||||
{#each columnList() as column}
|
{#if railList().length > 0}
|
||||||
<section class="wrn-mega__column">
|
<aside class="wrn-mega__rail">
|
||||||
<h3 class="wrn-mega__heading" data-show="column.heading">{column.heading}</h3>
|
{#each railList() as item, index}
|
||||||
<ul class="wrn-mega__list">
|
{#if variant === "catalog"}
|
||||||
{#each itemsOf(column) as item}
|
<button type="button" class="wrn-mega__rail-link" data-active='{activeCategoryIndex() === index ? "true" : "false"}' aria-pressed='{activeCategoryIndex() === index ? "true" : "false"}' @click='chooseCategory(item, index, event)'>
|
||||||
<li>
|
{#if item.icon}<span class="wrn-mega__rail-icon" aria-hidden="true"><span class='{item.icon}'></span></span>{/if}
|
||||||
<a
|
<span><strong>{item.label}</strong>{#if item.description}<small>{item.description}</small>{/if}</span>
|
||||||
class="wrn-mega__link"
|
</button>
|
||||||
href='{item.href || "#"}'
|
{:else}
|
||||||
data-wrn-roving-item="true"
|
<a class="wrn-mega__rail-link" href='{item.href || "#"}' @click='choose(item)'>
|
||||||
aria-disabled='{item.disabled ? "true" : "false"}'
|
{#if item.icon}<span class="wrn-mega__rail-icon" aria-hidden="true"><span class='{item.icon}'></span></span>{/if}
|
||||||
@click='choose(item)'
|
<span><strong>{item.label}</strong>{#if item.description}<small>{item.description}</small>{/if}</span>
|
||||||
>
|
</a>
|
||||||
<span
|
{/if}
|
||||||
class='wrn-mega__link-icon {item.icon}'
|
{/each}
|
||||||
data-show="item.icon"
|
</aside>
|
||||||
aria-hidden="true"
|
{/if}
|
||||||
></span>
|
|
||||||
<span class="wrn-mega__link-body">
|
<div class="wrn-mega__columns">
|
||||||
<span class="wrn-mega__link-label">{item.label}</span>
|
{#each visibleColumns() as column}
|
||||||
<span class="wrn-mega__link-description" data-show="item.description">
|
<section class="wrn-mega__column">
|
||||||
{item.description}
|
<header class="wrn-mega__column-header">
|
||||||
|
{#if column.eyebrow}<p class="wrn-mega__eyebrow">{column.eyebrow}</p>{/if}
|
||||||
|
<h3 class="wrn-mega__heading" data-show="column.heading">{column.heading}</h3>
|
||||||
|
{#if column.description}<p class="wrn-mega__column-description">{column.description}</p>{/if}
|
||||||
|
</header>
|
||||||
|
{#if column.image}<img class="wrn-mega__column-image" src='{column.image}' alt='{column.imageAlt || ""}' loading="lazy" />{/if}
|
||||||
|
<ul class="wrn-mega__list">
|
||||||
|
{#each itemsOf(column) as item}
|
||||||
|
<li>
|
||||||
|
<a class="wrn-mega__link" href='{item.href || "#"}' data-wrn-roving-item="true" aria-disabled='{item.disabled ? "true" : "false"}' @click='choose(item)'>
|
||||||
|
{#if item.image}<img class="wrn-mega__link-image" src='{item.image}' alt="" loading="lazy" />{/if}
|
||||||
|
{#if item.icon}
|
||||||
|
<span class='wrn-mega__link-icon {item.icon}' aria-hidden="true"></span>
|
||||||
|
{:else if variant === "catalog"}
|
||||||
|
<span class="wrn-mega__link-icon wrn-mega__link-icon--fallback" aria-hidden="true">
|
||||||
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="18" height="18" x="3" y="3" rx="2"></rect><path d="M3 9h18"></path><path d="M9 21V9"></path></svg>
|
||||||
|
</span>
|
||||||
|
{/if}
|
||||||
|
<span class="wrn-mega__link-body">
|
||||||
|
{#if item.eyebrow}<span class="wrn-mega__link-eyebrow">{item.eyebrow}</span>{/if}
|
||||||
|
<span class="wrn-mega__link-label">{item.label}{#if item.badge}<span class="wrn-mega__badge">{item.badge}</span>{/if}</span>
|
||||||
|
{#if item.description}<span class="wrn-mega__link-description">{item.description}</span>{/if}
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</a>
|
||||||
</a>
|
</li>
|
||||||
</li>
|
{/each}
|
||||||
{/each}
|
</ul>
|
||||||
</ul>
|
{#if column.actionLabel}<a class="wrn-mega__column-action" href='{column.actionHref || "#"}'>{column.actionLabel}<span class="icon-[lucide--arrow-right]" aria-hidden="true"></span></a>{/if}
|
||||||
</section>
|
</section>
|
||||||
{/each}
|
{/each}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{#if featured.title || featured.image}
|
||||||
|
<aside class="wrn-mega__featured">
|
||||||
|
{#if featured.eyebrow}<p class="wrn-mega__eyebrow">{featured.eyebrow}</p>{/if}
|
||||||
|
{#if featured.image}<img src='{featured.image}' alt='{featured.imageAlt || ""}' loading="lazy" />{/if}
|
||||||
|
{#if featured.title}<strong>{featured.title}</strong>{/if}
|
||||||
|
{#if featured.description}<p>{featured.description}</p>{/if}
|
||||||
|
{#if featured.actionLabel}<a href='{featured.actionHref || "#"}'>{featured.actionLabel}<span class="icon-[lucide--arrow-right]" aria-hidden="true"></span></a>{/if}
|
||||||
|
</aside>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p class="wrn-mega__footer" data-show="footer">{footer}</p>
|
{#if footer || actionLabel}<div class="wrn-mega__footer"><span>{footer}</span>{#if actionLabel}<a href='{actionHref || "#"}'>{actionLabel}<span class='{actionIcon}' aria-hidden="true"></span></a>{/if}</div>{/if}
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -187,7 +322,7 @@ component MegaMenu {
|
|||||||
border: 1px solid transparent;
|
border: 1px solid transparent;
|
||||||
border-radius: var(--wrn-radius-sm);
|
border-radius: var(--wrn-radius-sm);
|
||||||
background: transparent;
|
background: transparent;
|
||||||
color: var(--wrn-color-text-muted);
|
color: var(--wrn-color-text);
|
||||||
font: inherit;
|
font: inherit;
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
@@ -200,6 +335,10 @@ component MegaMenu {
|
|||||||
color: var(--wrn-color-text);
|
color: var(--wrn-color-text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.wrn-mega__trigger-label::before {
|
||||||
|
content: attr(data-label);
|
||||||
|
}
|
||||||
|
|
||||||
.wrn-mega__trigger:focus-visible {
|
.wrn-mega__trigger:focus-visible {
|
||||||
outline: 2px solid var(--mega-accent);
|
outline: 2px solid var(--mega-accent);
|
||||||
outline-offset: 2px;
|
outline-offset: 2px;
|
||||||
@@ -226,29 +365,78 @@ component MegaMenu {
|
|||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 100%;
|
bottom: 100%;
|
||||||
height: 0.6rem;
|
height: 0.85rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wrn-mega__panel {
|
.wrn-mega__panel {
|
||||||
|
box-sizing: border-box;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 40;
|
z-index: 1200;
|
||||||
top: calc(100% + 0.4rem);
|
top: calc(100% + 0.4rem);
|
||||||
left: 0;
|
left: 0;
|
||||||
width: max-content;
|
width: max-content;
|
||||||
max-width: min(60rem, calc(100vw - 2rem));
|
max-width: min(60rem, calc(100vw - 2rem));
|
||||||
|
max-height: calc(100dvh - 5.5rem);
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
border: 1px solid var(--wrn-color-border);
|
border: 1px solid var(--wrn-color-border);
|
||||||
border-radius: var(--wrn-radius-lg);
|
border-radius: var(--wrn-radius-lg);
|
||||||
background: var(--wrn-color-surface);
|
background: var(--wrn-color-surface);
|
||||||
box-shadow: var(--wrn-shadow-1);
|
box-shadow: var(--wrn-shadow-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Keep SSR output closed before the reactive runtime hydrates it. */
|
||||||
|
.wrn-mega__panel[data-show="false"] { display: none; }
|
||||||
|
.wrn-mega__panel[data-show="true"] { display: flex; }
|
||||||
|
|
||||||
|
.wrn-mega[data-panel-width="lg"] .wrn-mega__panel { width: min(48rem, calc(100vw - 2rem)); }
|
||||||
|
.wrn-mega[data-panel-width="xl"] .wrn-mega__panel { width: min(72rem, calc(100vw - 2rem)); }
|
||||||
|
.wrn-mega[data-panel-width="2xl"] .wrn-mega__panel { width: min(88rem, calc(100vw - 2rem)); }
|
||||||
|
.wrn-mega[data-full-width="true"] .wrn-mega__panel { width: calc(100vw - 2rem); max-width: none; }
|
||||||
|
.wrn-mega[data-panel-align="center"] .wrn-mega__panel { left: 50%; transform: translateX(-50%); }
|
||||||
|
.wrn-mega[data-panel-align="end"] .wrn-mega__panel { right: 0; left: auto; }
|
||||||
|
|
||||||
|
.wrn-mega[data-variant="default"] .wrn-mega__panel {
|
||||||
|
width: max-content;
|
||||||
|
min-width: 15rem;
|
||||||
|
max-width: min(24rem, calc(100dvw - 2rem));
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
.wrn-mega[data-variant="default"] .wrn-mega__layout,
|
||||||
|
.wrn-mega[data-variant="default"] .wrn-mega__columns,
|
||||||
|
.wrn-mega[data-variant="default"][data-column-count] .wrn-mega__columns {
|
||||||
|
grid-template-columns: minmax(0, 1fr);
|
||||||
|
}
|
||||||
|
.wrn-mega[data-variant="default"] .wrn-mega__columns { overflow: visible; }
|
||||||
|
.wrn-mega[data-variant="default"] .wrn-mega__featured { width: auto; padding: 1rem 0 0; border-top: 1px solid var(--wrn-color-border); border-left: 0; }
|
||||||
|
|
||||||
|
.wrn-mega__layout { display: grid; min-height: 0; max-height: calc(100dvh - 8rem); flex: 1; grid-template-columns: auto minmax(0, 1fr) auto; gap: 1.25rem; overflow: hidden; }
|
||||||
|
|
||||||
.wrn-mega__columns {
|
.wrn-mega__columns {
|
||||||
display: grid;
|
display: grid;
|
||||||
|
min-height: 0;
|
||||||
grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
|
grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
|
||||||
gap: 1.25rem;
|
gap: 1.25rem;
|
||||||
|
overflow-y: auto;
|
||||||
|
overscroll-behavior: contain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.wrn-mega[data-column-count="2"] .wrn-mega__columns { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
||||||
|
.wrn-mega[data-column-count="3"] .wrn-mega__columns { grid-template-columns: repeat(3, minmax(0, 1fr)); }
|
||||||
|
.wrn-mega[data-column-count="4"] .wrn-mega__columns { grid-template-columns: repeat(4, minmax(0, 1fr)); }
|
||||||
|
.wrn-mega[data-column-count="5"] .wrn-mega__columns { grid-template-columns: repeat(5, minmax(0, 1fr)); }
|
||||||
|
|
||||||
|
.wrn-mega__rail { display: grid; min-width: 13rem; min-height: 0; padding: 0.75rem; align-content: start; gap: 0.25rem; overflow-y: auto; overscroll-behavior: contain; border-radius: var(--wrn-radius-lg); background: var(--wrn-color-surface-soft); }
|
||||||
|
.wrn-mega__rail-link { appearance: none; display: flex; width: 100%; padding: 0.65rem; align-items: flex-start; gap: 0.65rem; color: var(--wrn-color-text); border: 0; border-radius: var(--wrn-radius-sm); background: transparent; font: inherit; text-align: left; text-decoration: none; cursor: pointer; }
|
||||||
|
.wrn-mega__rail-link:hover { background: var(--wrn-color-surface); }
|
||||||
|
.wrn-mega__rail-link[data-active="true"] { color: var(--mega-accent); background: var(--wrn-color-surface); box-shadow: inset 3px 0 0 var(--mega-accent); }
|
||||||
|
.wrn-mega__rail-link > span:last-child { display: grid; gap: 0.2rem; }
|
||||||
|
.wrn-mega__rail-link strong { font-size: 0.82rem; }
|
||||||
|
.wrn-mega__rail-link small { max-width: 18ch; color: var(--wrn-color-text-muted); font-size: 0.72rem; line-height: 1.45; }
|
||||||
|
.wrn-mega__rail-icon { display: grid; width: 2.4rem; height: 2.4rem; flex: none; place-items: center; color: var(--mega-accent); border-radius: 0.7rem; background: color-mix(in srgb, var(--mega-accent) 12%, transparent); font-size: 1.15rem; }
|
||||||
|
|
||||||
.wrn-mega__column {
|
.wrn-mega__column {
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
@@ -262,6 +450,10 @@ component MegaMenu {
|
|||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.wrn-mega__eyebrow, .wrn-mega__link-eyebrow { margin: 0 0 0.35rem; color: var(--wrn-color-text-muted); font-size: 0.65rem; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; }
|
||||||
|
.wrn-mega__column-description { margin: -0.25rem 0 0.75rem; color: var(--wrn-color-text-muted); font-size: 0.75rem; line-height: 1.5; }
|
||||||
|
.wrn-mega__column-image { width: 100%; aspect-ratio: 16 / 7; margin-bottom: 0.65rem; object-fit: cover; border-radius: var(--wrn-radius-sm); }
|
||||||
|
|
||||||
.wrn-mega__list {
|
.wrn-mega__list {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 0.15rem;
|
gap: 0.15rem;
|
||||||
@@ -270,8 +462,14 @@ component MegaMenu {
|
|||||||
list-style: none;
|
list-style: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.wrn-mega__list > li {
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.wrn-mega__link {
|
.wrn-mega__link {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
min-width: 0;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
padding: 0.45rem 0.5rem;
|
padding: 0.45rem 0.5rem;
|
||||||
@@ -280,6 +478,43 @@ component MegaMenu {
|
|||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.wrn-mega__link-icon { display: grid; width: 2rem; height: 2rem; flex: none; place-items: center; color: var(--mega-accent); border-radius: 999px; background: color-mix(in srgb, var(--mega-accent) 10%, var(--wrn-color-surface-soft)); }
|
||||||
|
.wrn-mega__link-image { width: 2.4rem; height: 2.4rem; flex: none; object-fit: cover; border-radius: 0.65rem; }
|
||||||
|
.wrn-mega__badge { display: inline-flex; margin-left: 0.4rem; padding: 0.12rem 0.35rem; align-items: center; color: var(--mega-accent); border: 1px solid color-mix(in srgb, var(--mega-accent) 35%, transparent); border-radius: 999px; font-size: 0.6rem; font-weight: 700; }
|
||||||
|
.wrn-mega__column-action, .wrn-mega__featured a, .wrn-mega__footer a { display: inline-flex; margin-top: 0.7rem; align-items: center; gap: 0.35rem; color: var(--mega-accent); font-size: 0.78rem; font-weight: 700; text-decoration: none; }
|
||||||
|
|
||||||
|
.wrn-mega__featured { display: grid; width: 14rem; padding-left: 1.25rem; align-content: start; gap: 0.55rem; border-left: 1px solid var(--wrn-color-border); }
|
||||||
|
.wrn-mega__featured img { width: 100%; aspect-ratio: 16 / 9; object-fit: cover; border-radius: var(--wrn-radius-lg); }
|
||||||
|
.wrn-mega__featured strong { font-size: 0.85rem; line-height: 1.35; }
|
||||||
|
.wrn-mega__featured p { margin: 0; color: var(--wrn-color-text-muted); font-size: 0.75rem; line-height: 1.5; }
|
||||||
|
|
||||||
|
.wrn-mega[data-density="compact"] :is(.wrn-mega__panel, .wrn-mega__rail) { padding: 0.7rem; }
|
||||||
|
.wrn-mega[data-density="compact"] .wrn-mega__columns { gap: 0.65rem; }
|
||||||
|
.wrn-mega[data-variant="icon-grid"] .wrn-mega__list { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.35rem; }
|
||||||
|
.wrn-mega[data-variant="catalog"] .wrn-mega__panel { height: min(36rem, calc(100dvh - 6.5rem)); }
|
||||||
|
.wrn-mega[data-variant="catalog"] .wrn-mega__layout { grid-template-columns: minmax(14rem, 17rem) minmax(0, 1fr); gap: 0; }
|
||||||
|
.wrn-mega[data-variant="catalog"] .wrn-mega__rail { min-width: 0; padding: 0.55rem; gap: 0.3rem; border-radius: calc(var(--wrn-radius-lg) - 0.25rem); }
|
||||||
|
.wrn-mega[data-variant="catalog"] .wrn-mega__rail-link { min-height: 2.5rem; padding: 0.45rem 0.55rem; align-items: center; gap: 0.7rem; }
|
||||||
|
.wrn-mega[data-variant="catalog"] .wrn-mega__rail-link strong { font-size: 0.76rem; font-weight: 400; line-height: 1.25; }
|
||||||
|
.wrn-mega[data-variant="catalog"] .wrn-mega__rail-link[data-active="true"] strong { font-weight: 600; }
|
||||||
|
.wrn-mega[data-variant="catalog"] .wrn-mega__rail-icon { display: grid; width: 1.65rem; height: 1.65rem; flex: 0 0 1.65rem; place-items: center; color: currentColor; border: 1px solid color-mix(in srgb, currentColor 35%, transparent); border-radius: 0.45rem; background: color-mix(in srgb, currentColor 8%, transparent); opacity: 0.9; }
|
||||||
|
.wrn-mega[data-variant="catalog"] .wrn-mega__rail-icon > span { display: block; width: 0.95rem; height: 0.95rem; color: currentColor !important; font-size: 0.95rem; }
|
||||||
|
.wrn-mega[data-variant="catalog"] .wrn-mega__rail-link:hover .wrn-mega__rail-icon,
|
||||||
|
.wrn-mega[data-variant="catalog"] .wrn-mega__rail-link[data-active="true"] .wrn-mega__rail-icon { opacity: 1; }
|
||||||
|
.wrn-mega[data-variant="catalog"] .wrn-mega__columns { padding: 0.35rem 0.5rem 0.75rem 1.25rem; grid-template-columns: minmax(0, 1fr); }
|
||||||
|
.wrn-mega[data-variant="catalog"] .wrn-mega__column { display: flex; min-height: 100%; flex-direction: column; }
|
||||||
|
.wrn-mega[data-variant="catalog"] .wrn-mega__column-header { width: 100%; min-width: 0; margin: 0 0 0.85rem; padding: 0 0 0.65rem; border: 0; border-bottom: 1px solid var(--wrn-color-border); border-radius: 0; background: transparent; }
|
||||||
|
.wrn-mega[data-variant="catalog"] .wrn-mega__heading { margin: 0; color: var(--wrn-color-text-muted); font-size: 0.75rem; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; }
|
||||||
|
.wrn-mega[data-variant="catalog"] .wrn-mega__column-description { margin: 0.3rem 0 0; }
|
||||||
|
.wrn-mega[data-variant="catalog"] .wrn-mega__list { grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr)); gap: 0.3rem; }
|
||||||
|
.wrn-mega[data-variant="catalog"] .wrn-mega__link { min-height: 2.7rem; padding: 0.45rem 0.55rem; align-items: center; gap: 0.55rem; border: 1px solid transparent; background: transparent; }
|
||||||
|
.wrn-mega[data-variant="catalog"] .wrn-mega__link:hover { border-color: color-mix(in srgb, var(--mega-accent) 28%, var(--wrn-color-border)); background: color-mix(in srgb, var(--mega-accent) 7%, var(--wrn-color-surface)); transform: translateY(-1px); }
|
||||||
|
.wrn-mega[data-variant="catalog"] .wrn-mega__column-action { margin-top: auto; padding-top: 1rem; }
|
||||||
|
.wrn-mega[data-variant="dark"] .wrn-mega__panel { color: #f8fafc; border-color: #2b2b2b; background: #151515; }
|
||||||
|
.wrn-mega[data-variant="dark"] :is(.wrn-mega__heading, .wrn-mega__link, .wrn-mega__featured strong) { color: #f8fafc; }
|
||||||
|
.wrn-mega[data-variant="dark"] :is(.wrn-mega__link-description, .wrn-mega__column-description, .wrn-mega__eyebrow, .wrn-mega__featured p) { color: #a3a3a3; }
|
||||||
|
.wrn-mega[data-variant="dark"] .wrn-mega__link:hover { background: #242424; }
|
||||||
|
|
||||||
.wrn-mega__link:hover {
|
.wrn-mega__link:hover {
|
||||||
background: var(--wrn-color-surface-soft);
|
background: var(--wrn-color-surface-soft);
|
||||||
}
|
}
|
||||||
@@ -300,9 +535,15 @@ component MegaMenu {
|
|||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.wrn-mega[data-variant="catalog"] .wrn-mega__link-icon { width: 1.65rem; height: 1.65rem; flex: 0 0 1.65rem; border: 1px solid color-mix(in srgb, var(--mega-accent) 22%, var(--wrn-color-border)); border-radius: 0.45rem; font-size: 0.9rem; }
|
||||||
|
.wrn-mega[data-variant="catalog"] .wrn-mega__link-icon--fallback svg { width: 0.9rem; height: 0.9rem; }
|
||||||
|
.wrn-mega[data-variant="catalog"] .wrn-mega__link-label { font-size: 0.78rem; line-height: 1.25; }
|
||||||
|
.wrn-mega[data-variant="catalog"] .wrn-mega__link-description { font-size: 0.7rem; line-height: 1.35; }
|
||||||
|
|
||||||
.wrn-mega__link-label {
|
.wrn-mega__link-label {
|
||||||
font-size: 0.88rem;
|
font-size: 0.88rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
overflow-wrap: anywhere;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wrn-mega__link-description {
|
.wrn-mega__link-description {
|
||||||
@@ -312,8 +553,12 @@ component MegaMenu {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.wrn-mega__footer {
|
.wrn-mega__footer {
|
||||||
|
display: flex;
|
||||||
margin: 1rem 0 0;
|
margin: 1rem 0 0;
|
||||||
padding-top: 0.75rem;
|
padding-top: 0.75rem;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 1rem;
|
||||||
border-top: 1px solid var(--wrn-color-border);
|
border-top: 1px solid var(--wrn-color-border);
|
||||||
color: var(--wrn-color-text-muted);
|
color: var(--wrn-color-text-muted);
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
@@ -333,12 +578,24 @@ component MegaMenu {
|
|||||||
position: static;
|
position: static;
|
||||||
width: auto;
|
width: auto;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
|
max-height: none;
|
||||||
|
overflow: visible;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.wrn-mega__panel[data-show="false"] { display: none; }
|
||||||
|
|
||||||
.wrn-mega__columns {
|
.wrn-mega__columns {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
|
.wrn-mega__layout { max-height: none; grid-template-columns: 1fr; overflow: visible; }
|
||||||
|
.wrn-mega__rail, .wrn-mega__columns { overflow: visible; }
|
||||||
|
.wrn-mega__featured { width: auto; padding: 1rem 0 0; border-top: 1px solid var(--wrn-color-border); border-left: 0; }
|
||||||
|
.wrn-mega[data-variant="icon-grid"] .wrn-mega__list { grid-template-columns: 1fr; }
|
||||||
|
.wrn-mega[data-variant="catalog"] .wrn-mega__panel { height: auto; }
|
||||||
|
.wrn-mega[data-variant="catalog"] .wrn-mega__layout { grid-template-columns: 1fr; }
|
||||||
|
.wrn-mega[data-variant="catalog"] .wrn-mega__columns { padding: 1rem 0 0; }
|
||||||
|
.wrn-mega[data-variant="catalog"] .wrn-mega__list { grid-template-columns: 1fr; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -92,7 +92,9 @@ component MetricGrid {
|
|||||||
@action='forwardAction(item, itemIndex, event)'
|
@action='forwardAction(item, itemIndex, event)'
|
||||||
/>
|
/>
|
||||||
{:empty}
|
{:empty}
|
||||||
<slot></slot>
|
<div class="wrn-metric-grid__empty" role="status">
|
||||||
|
<slot>No metrics are available.</slot>
|
||||||
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -100,6 +102,15 @@ component MetricGrid {
|
|||||||
}
|
}
|
||||||
|
|
||||||
style {
|
style {
|
||||||
|
.wrn-metric-grid__empty {
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
padding: 1.25rem;
|
||||||
|
color: var(--wrn-color-text-muted);
|
||||||
|
background: var(--wrn-color-surface-soft);
|
||||||
|
border: 1px dashed var(--wrn-color-border);
|
||||||
|
border-radius: 0.9rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
.wrn-metric-grid__frame {
|
.wrn-metric-grid__frame {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import MegaMenu from "./MegaMenu.wrn"
|
||||||
|
|
||||||
component Navbar {
|
component Navbar {
|
||||||
outputs {
|
outputs {
|
||||||
toggle(payload: { open: boolean })
|
toggle(payload: { open: boolean })
|
||||||
@@ -17,9 +19,17 @@ size: string = "default"
|
|||||||
actions: unknown[] = []
|
actions: unknown[] = []
|
||||||
active: string = ""
|
active: string = ""
|
||||||
sticky: boolean = false
|
sticky: boolean = false
|
||||||
|
floating: boolean = false
|
||||||
|
startFloating: string = "0px"
|
||||||
openOnHover: boolean = false
|
openOnHover: boolean = false
|
||||||
maxWidth: string = "full"
|
maxWidth: string = "full"
|
||||||
mobileLabel: string = "Toggle navigation"
|
mobileLabel: string = "Toggle navigation"
|
||||||
|
collapseAt: string = "900px"
|
||||||
|
mobilePanel: string = "content"
|
||||||
|
mobileUtilitiesPosition: string = "header"
|
||||||
|
gutter: string = "md"
|
||||||
|
contentGutter: string = "md"
|
||||||
|
flushMobile: boolean = false
|
||||||
translationPrefix: string = ""
|
translationPrefix: string = ""
|
||||||
class: string = ""
|
class: string = ""
|
||||||
}
|
}
|
||||||
@@ -36,27 +46,112 @@ size: string = "default"
|
|||||||
const slug = String(source).replace(/^\/+|\/+$/g, "").replace(/[^A-Za-z0-9]+/g, "-").replace(/^-+|-+$/g, "").toLowerCase()
|
const slug = String(source).replace(/^\/+|\/+$/g, "").replace(/[^A-Za-z0-9]+/g, "-").replace(/^-+|-+$/g, "").toLowerCase()
|
||||||
return slug ? translationPrefix + "." + slug + (field === "description" ? ".description" : "") : ""
|
return slug ? translationPrefix + "." + slug + (field === "description" ? ".description" : "") : ""
|
||||||
}
|
}
|
||||||
client function toggleNavigation() {
|
shared function itemType(item) {
|
||||||
mobileOpen = !mobileOpen
|
if (item && item.type) {
|
||||||
output.toggle({ open: mobileOpen })
|
return item.type
|
||||||
output[mobileOpen ? "open" : "close"]({ source: "mobile" })
|
}
|
||||||
|
return item && ((item.items && item.items.length) || (item.children && item.children.length)) ? "dropdown" : "link"
|
||||||
}
|
}
|
||||||
|
|
||||||
client function selectItem(item, level) {
|
shared function dropdownItems(item) {
|
||||||
mobileOpen = false
|
if (!item) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
if (Array.isArray(item.items)) {
|
||||||
|
return item.items
|
||||||
|
}
|
||||||
|
return Array.isArray(item.children) ? item.children : []
|
||||||
|
}
|
||||||
|
|
||||||
|
shared function dropdownGroupItems(item) {
|
||||||
|
if (!item) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
if (Array.isArray(item.items)) {
|
||||||
|
return item.items
|
||||||
|
}
|
||||||
|
return Array.isArray(item.children) ? item.children : []
|
||||||
|
}
|
||||||
|
|
||||||
|
shared function megaData(item) {
|
||||||
|
return item && item.mega && typeof item.mega === "object" ? item.mega : item || {}
|
||||||
|
}
|
||||||
|
|
||||||
|
shared function megaColumns(item) {
|
||||||
|
const data = megaData(item)
|
||||||
|
if (Array.isArray(data.columns)) {
|
||||||
|
return data.columns
|
||||||
|
}
|
||||||
|
const legacy = dropdownItems(item)
|
||||||
|
if (!legacy.length) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
const grouped = legacy.some(function (entry) {
|
||||||
|
return dropdownGroupItems(entry).length > 0
|
||||||
|
})
|
||||||
|
if (grouped) {
|
||||||
|
return legacy.map(function (entry) {
|
||||||
|
return {
|
||||||
|
heading: entry.label || "",
|
||||||
|
description: entry.description || "",
|
||||||
|
items: dropdownGroupItems(entry)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return [{ heading: item.description || "", items: legacy }]
|
||||||
|
}
|
||||||
|
client function setMobileNavigation(open, trigger) {
|
||||||
|
const root = trigger && trigger.closest ? trigger.closest("[data-wrn-navbar]") : null
|
||||||
|
if (!root) return
|
||||||
|
const collapse = root.querySelector(".wrn-navbar__collapse")
|
||||||
|
const toggle = root.querySelector(".wrn-navbar__toggle")
|
||||||
|
if (collapse) collapse.classList.toggle("is-open", open)
|
||||||
|
if (toggle) toggle.setAttribute("aria-expanded", open ? "true" : "false")
|
||||||
|
}
|
||||||
|
|
||||||
|
client function toggleNavigation(event) {
|
||||||
|
const open = event.currentTarget.getAttribute("aria-expanded") !== "true"
|
||||||
|
setMobileNavigation(open, event.currentTarget)
|
||||||
|
output.toggle({ open: open })
|
||||||
|
output[open ? "open" : "close"]({ source: "mobile" })
|
||||||
|
}
|
||||||
|
|
||||||
|
client function selectItem(item, level, event) {
|
||||||
|
setMobileNavigation(false, event.currentTarget)
|
||||||
output.select({ item: item, value: item.value || "", level: level })
|
output.select({ item: item, value: item.value || "", level: level })
|
||||||
}
|
}
|
||||||
|
|
||||||
client function selectAction(item) {
|
client function selectAction(item, event) {
|
||||||
mobileOpen = false
|
setMobileNavigation(false, event.currentTarget)
|
||||||
output.action({ item: item, value: item.value || "" })
|
output.action({ item: item, value: item.value || "" })
|
||||||
}
|
}
|
||||||
|
|
||||||
shared function isItemActive(item) {
|
shared function isItemActive(item) {
|
||||||
if (!item) return false
|
if (!item) {
|
||||||
if (item.value && item.value === active) return true
|
return false
|
||||||
if (!item.children || !item.children.length) return false
|
}
|
||||||
return item.children.some(function (child) {
|
if (item.value && item.value === active) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (itemType(item) === "mega") {
|
||||||
|
const data = megaData(item)
|
||||||
|
const links = Array.isArray(data.rail) ? data.rail.slice() : []
|
||||||
|
megaColumns(item).forEach(function (column) {
|
||||||
|
if (column && Array.isArray(column.items)) {
|
||||||
|
column.items.forEach(function (child) {
|
||||||
|
links.push(child)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return links.some(function (child) {
|
||||||
|
return child.value && child.value === active
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const entries = dropdownItems(item)
|
||||||
|
if (!entries.length) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return entries.some(function (child) {
|
||||||
return isItemActive(child)
|
return isItemActive(child)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -70,12 +165,13 @@ size: string = "default"
|
|||||||
}
|
}
|
||||||
|
|
||||||
view {
|
view {
|
||||||
<header class="wrn-navbar wrn-navbar--width-{maxWidth} wrn-component--color-{color} wrn-component--size-{size} {sticky ? 'wrn-navbar--sticky' : ''} {class}" data-wrn-navbar data-open-on-hover="{openOnHover}">
|
<header class="wrn-navbar wrn-navbar--width-{maxWidth} wrn-component--color-{color} wrn-component--size-{size} {sticky ? 'wrn-navbar--sticky' : ''} {floating ? 'wrn-navbar--floating' : ''} {class}" style="--wrn-navbar-floating-start: {startFloating};" data-wrn-navbar data-open-on-hover="{openOnHover}" data-floating="{floating ? 'true' : 'false'}" data-collapse-at="{collapseAt}" data-mobile-panel="{mobilePanel}" data-mobile-utilities-position="{mobileUtilitiesPosition}" data-gutter="{gutter}" data-content-gutter="{contentGutter}" data-flush-mobile="{flushMobile ? 'true' : 'false'}">
|
||||||
<div class="wrn-navbar__topbar" aria-label="{topbarLabel}">
|
<div class="wrn-navbar__topbar" aria-label="{topbarLabel}">
|
||||||
<slot name="topbar" />
|
<slot name="topbar" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="wrn-navbar__main">
|
<div class="wrn-navbar__main">
|
||||||
|
{#if brand.logo || brand.icon || brand.label || brand.description}
|
||||||
<a class="wrn-navbar__brand" href="{brand.href || '/'}" aria-label="{brand.ariaLabel || brand.label || label}">
|
<a class="wrn-navbar__brand" href="{brand.href || '/'}" aria-label="{brand.ariaLabel || brand.label || label}">
|
||||||
{#if brand.logo}
|
{#if brand.logo}
|
||||||
<img class="wrn-navbar__brand-logo" src="{brand.logo}" alt="{brand.logoAlt || brand.label || ''}" width="{brand.logoWidth || ''}" height="{brand.logoHeight || ''}" />
|
<img class="wrn-navbar__brand-logo" src="{brand.logo}" alt="{brand.logoAlt || brand.label || ''}" width="{brand.logoWidth || ''}" height="{brand.logoHeight || ''}" />
|
||||||
@@ -90,15 +186,39 @@ size: string = "default"
|
|||||||
</span>
|
</span>
|
||||||
{/if}
|
{/if}
|
||||||
</a>
|
</a>
|
||||||
|
{/if}
|
||||||
<button type="button" class="wrn-navbar__toggle" aria-label="{mobileLabel}" aria-expanded="{mobileOpen}" @click="toggleNavigation()">
|
<slot name="brand" />
|
||||||
<span aria-hidden="true"></span><span aria-hidden="true"></span><span aria-hidden="true"></span>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<div class="wrn-navbar__collapse {mobileOpen ? 'is-open' : ''}">
|
<div class="wrn-navbar__collapse {mobileOpen ? 'is-open' : ''}">
|
||||||
<nav class="wrn-navbar__menus" aria-label="{label}" data-wrn-roving="horizontal">
|
<nav class="wrn-navbar__menus" aria-label="{label}" data-wrn-roving="horizontal">
|
||||||
{#each items as item}
|
{#each items as item}
|
||||||
{#if item.children && item.children.length}
|
{#if itemType(item) === "mega"}
|
||||||
|
<MegaMenu
|
||||||
|
class="wrn-navbar__mega"
|
||||||
|
data-active="{isItemActive(item) ? 'true' : 'false'}"
|
||||||
|
label="{item.label}"
|
||||||
|
icon="{item.icon || ''}"
|
||||||
|
columns={megaColumns(item)}
|
||||||
|
rail={megaData(item).rail || []}
|
||||||
|
featured={megaData(item).featured || {}}
|
||||||
|
variant="{megaData(item).variant || 'default'}"
|
||||||
|
density="{megaData(item).density || 'default'}"
|
||||||
|
panelWidth="{megaData(item).panelWidth || 'xl'}"
|
||||||
|
panelAlign="{megaData(item).panelAlign || 'start'}"
|
||||||
|
columnCount={megaData(item).columnCount || 0}
|
||||||
|
fullWidth={megaData(item).fullWidth || false}
|
||||||
|
openOnHover={openOnHover}
|
||||||
|
activeCategory="{megaData(item).activeCategory || ''}"
|
||||||
|
actionLabel="{megaData(item).actionLabel || ''}"
|
||||||
|
actionHref="{megaData(item).actionHref || ''}"
|
||||||
|
actionIcon="{megaData(item).actionIcon || 'icon-[lucide--arrow-right]'}"
|
||||||
|
footer="{megaData(item).footer || ''}"
|
||||||
|
/>
|
||||||
|
<a class="wrn-navbar__menu-link wrn-navbar__mobile-mega-link" data-wrn-roving-item="true" href="{item.href || megaData(item).actionHref || '#'}" target="{item.target || ''}" rel="{item.rel || ''}" aria-current="{isItemActive(item) ? 'page' : 'false'}" @click="selectItem(item, 1, event)">
|
||||||
|
{#if item.icon}<span class="{item.icon}" aria-hidden="true"></span>{/if}
|
||||||
|
<span data-t="{translationKey(item, 'label')}">{item.label}</span>
|
||||||
|
</a>
|
||||||
|
{:else if itemType(item) === "dropdown"}
|
||||||
<details class="wrn-navbar__dropdown wrn-navbar__dropdown--{item.type || 'dropdown'}" name="wrn-navbar-menu" @toggle="toggleDropdown(event, item)">
|
<details class="wrn-navbar__dropdown wrn-navbar__dropdown--{item.type || 'dropdown'}" name="wrn-navbar-menu" @toggle="toggleDropdown(event, item)">
|
||||||
<summary data-wrn-roving-item="true" aria-current="{isItemActive(item) ? 'page' : 'false'}">
|
<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}
|
||||||
@@ -107,19 +227,19 @@ size: string = "default"
|
|||||||
</summary>
|
</summary>
|
||||||
<div class="wrn-navbar__panel wrn-navbar__panel--columns-{item.columns || 1}">
|
<div class="wrn-navbar__panel wrn-navbar__panel--columns-{item.columns || 1}">
|
||||||
{#if item.description}<p class="wrn-navbar__panel-intro" data-t="{translationKey(item, 'description')}">{item.description}</p>{/if}
|
{#if item.description}<p class="wrn-navbar__panel-intro" data-t="{translationKey(item, 'description')}">{item.description}</p>{/if}
|
||||||
{#each item.children as child}
|
{#each dropdownItems(item) as child}
|
||||||
<div class="wrn-navbar__group">
|
<div class="wrn-navbar__group">
|
||||||
{#if child.children && child.children.length}
|
{#if dropdownGroupItems(child).length}
|
||||||
{#if child.label}<strong class="wrn-navbar__group-title" data-t="{translationKey(child, 'label')}">{child.label}</strong>{/if}
|
{#if child.label}<strong class="wrn-navbar__group-title" data-t="{translationKey(child, 'label')}">{child.label}</strong>{/if}
|
||||||
{#if child.description}<small data-t="{translationKey(child, 'description')}">{child.description}</small>{/if}
|
{#if child.description}<small data-t="{translationKey(child, 'description')}">{child.description}</small>{/if}
|
||||||
{#each child.children as nested}
|
{#each dropdownGroupItems(child) as nested}
|
||||||
<a href="{nested.href || '#'}" target="{nested.target || ''}" rel="{nested.rel || ''}" aria-current="{nested.value === active ? 'page' : 'false'}" @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, event)">
|
||||||
{#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 data-t="{translationKey(nested, 'label')}">{nested.label}</strong>{#if nested.description}<small data-t="{translationKey(nested, 'description')}">{nested.description}</small>{/if}</span>
|
<span><strong data-t="{translationKey(nested, 'label')}">{nested.label}</strong>{#if nested.description}<small data-t="{translationKey(nested, 'description')}">{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' : 'false'}" @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, event)">
|
||||||
{#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 data-t="{translationKey(child, 'label')}">{child.label}</strong>{#if child.description}<small data-t="{translationKey(child, 'description')}">{child.description}</small>{/if}</span>
|
<span><strong data-t="{translationKey(child, 'label')}">{child.label}</strong>{#if child.description}<small data-t="{translationKey(child, 'description')}">{child.description}</small>{/if}</span>
|
||||||
</a>
|
</a>
|
||||||
@@ -129,7 +249,7 @@ size: string = "default"
|
|||||||
</div>
|
</div>
|
||||||
</details>
|
</details>
|
||||||
{:else}
|
{:else}
|
||||||
<a class="wrn-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)">
|
<a class="wrn-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, event)">
|
||||||
{#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 data-t="{translationKey(item, 'label')}">{item.label}</span>
|
<span data-t="{translationKey(item, 'label')}">{item.label}</span>
|
||||||
</a>
|
</a>
|
||||||
@@ -138,15 +258,21 @@ size: string = "default"
|
|||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<div class="wrn-navbar__actions">
|
<div class="wrn-navbar__actions">
|
||||||
|
<slot name="actions" />
|
||||||
{#each actions as item}
|
{#each actions as item}
|
||||||
<a class="wrn-navbar__action wrn-navbar__action--{item.variant || 'link'}" href="{item.href || '#'}" target="{item.target || ''}" rel="{item.rel || ''}" @click="selectAction(item)">
|
<a class="wrn-navbar__action wrn-navbar__action--{item.variant || 'link'}" href="{item.href || '#'}" target="{item.target || ''}" rel="{item.rel || ''}" @click="selectAction(item, event)">
|
||||||
{#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 data-t="{translationKey(item, 'label')}">{item.label}</span>
|
<span data-t="{translationKey(item, 'label')}">{item.label}</span>
|
||||||
</a>
|
</a>
|
||||||
{/each}
|
{/each}
|
||||||
<slot name="actions" />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="wrn-navbar__utilities"><slot name="utilities" /></div>
|
||||||
|
|
||||||
|
<button type="button" class="wrn-navbar__toggle" aria-label="{mobileLabel}" aria-expanded="{mobileOpen}" @click="toggleNavigation(event)">
|
||||||
|
<span aria-hidden="true"></span><span aria-hidden="true"></span><span aria-hidden="true"></span>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
}
|
}
|
||||||
@@ -155,7 +281,7 @@ size: string = "default"
|
|||||||
/* Full application navigation */
|
/* Full application navigation */
|
||||||
.wrn-navbar {
|
.wrn-navbar {
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 40;
|
z-index: 1000;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
color: var(--wrn-color-text);
|
color: var(--wrn-color-text);
|
||||||
background: color-mix(in srgb, var(--wrn-color-surface) 96%, transparent);
|
background: color-mix(in srgb, var(--wrn-color-surface) 96%, transparent);
|
||||||
@@ -168,12 +294,19 @@ size: string = "default"
|
|||||||
backdrop-filter: blur(16px);
|
backdrop-filter: blur(16px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.wrn-navbar__topbar:empty,
|
.wrn-navbar--floating {
|
||||||
.wrn-navbar__topbar:not(:has(*)) {
|
position: sticky;
|
||||||
|
z-index: 1000;
|
||||||
|
top: var(--wrn-navbar-floating-start, 0px);
|
||||||
|
box-shadow: 0 10px 30px rgb(15 23 42 / 0.08);
|
||||||
|
backdrop-filter: blur(16px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrn-navbar__topbar:not(:has(> *)) {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wrn-navbar__topbar:not(:empty) {
|
.wrn-navbar__topbar:has(> *) {
|
||||||
display: flex;
|
display: flex;
|
||||||
min-height: 2.25rem;
|
min-height: 2.25rem;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -188,6 +321,7 @@ size: string = "default"
|
|||||||
}
|
}
|
||||||
|
|
||||||
.wrn-navbar__main {
|
.wrn-navbar__main {
|
||||||
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
min-height: 4.25rem;
|
min-height: 4.25rem;
|
||||||
width: min(100%, 90rem);
|
width: min(100%, 90rem);
|
||||||
@@ -197,6 +331,17 @@ size: string = "default"
|
|||||||
gap: 1.5rem;
|
gap: 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.wrn-navbar[data-gutter="sm"] .wrn-navbar__main { padding-inline: 1rem; }
|
||||||
|
.wrn-navbar[data-gutter="lg"] .wrn-navbar__main { padding-inline: clamp(1.5rem, 5vw, 4rem); }
|
||||||
|
|
||||||
|
.wrn-navbar__utilities {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
flex: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrn-navbar__utilities:not(:has(> *)) { display: none; }
|
||||||
|
|
||||||
.wrn-navbar--width-full .wrn-navbar__main {
|
.wrn-navbar--width-full .wrn-navbar__main {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: none;
|
max-width: none;
|
||||||
@@ -265,20 +410,59 @@ size: string = "default"
|
|||||||
.wrn-navbar__collapse {
|
.wrn-navbar__collapse {
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
justify-content: flex-end;
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wrn-navbar__menus {
|
.wrn-navbar__menus {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
left: 0;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
flex: 1;
|
pointer-events: none;
|
||||||
gap: 0.25rem;
|
gap: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.wrn-navbar__menus > * {
|
||||||
|
pointer-events: auto;
|
||||||
|
}
|
||||||
|
|
||||||
.wrn-navbar__actions {
|
.wrn-navbar__actions {
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.wrn-navbar__mega {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrn-navbar__mega .wrn-mega__trigger {
|
||||||
|
min-height: 2.75rem;
|
||||||
|
padding: 0.65rem 0.8rem;
|
||||||
|
border-radius: 0.65rem;
|
||||||
|
font-size: 0.8125rem;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrn-navbar__mega[data-full-width="true"] .wrn-mega__panel {
|
||||||
|
position: fixed;
|
||||||
|
top: calc(var(--wrn-navbar-floating-start, 0px) + 4.25rem);
|
||||||
|
right: 1rem;
|
||||||
|
left: 1rem;
|
||||||
|
width: auto;
|
||||||
|
max-width: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrn-navbar__mega[data-variant="default"][data-full-width="true"] .wrn-mega__panel {
|
||||||
|
position: absolute;
|
||||||
|
top: calc(100% + 0.4rem);
|
||||||
|
right: auto;
|
||||||
|
left: 0;
|
||||||
|
width: max-content;
|
||||||
|
min-width: 15rem;
|
||||||
|
max-width: min(24rem, calc(100dvw - 2rem));
|
||||||
|
}
|
||||||
|
|
||||||
.wrn-navbar__menu-link,
|
.wrn-navbar__menu-link,
|
||||||
.wrn-navbar__dropdown > summary,
|
.wrn-navbar__dropdown > summary,
|
||||||
.wrn-navbar__action {
|
.wrn-navbar__action {
|
||||||
@@ -295,13 +479,15 @@ size: string = "default"
|
|||||||
}
|
}
|
||||||
|
|
||||||
.wrn-navbar__menu-link:hover,
|
.wrn-navbar__menu-link:hover,
|
||||||
.wrn-navbar__dropdown > summary:hover {
|
.wrn-navbar__dropdown > summary:hover,
|
||||||
|
.wrn-navbar__mega .wrn-mega__trigger:hover {
|
||||||
color: var(--wrn-color-text);
|
color: var(--wrn-color-text);
|
||||||
background: var(--wrn-color-surface-2);
|
background: var(--wrn-color-surface-2);
|
||||||
}
|
}
|
||||||
|
|
||||||
.wrn-navbar__menu-link[aria-current="page"],
|
.wrn-navbar__menu-link[aria-current="page"],
|
||||||
.wrn-navbar__dropdown > summary[aria-current="page"] {
|
.wrn-navbar__dropdown > summary[aria-current="page"],
|
||||||
|
.wrn-navbar__mega[data-active="true"] .wrn-mega__trigger {
|
||||||
color: var(--wrn-component-color, var(--wrn-color-primary));
|
color: var(--wrn-component-color, var(--wrn-color-primary));
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
background: color-mix(
|
background: color-mix(
|
||||||
@@ -313,7 +499,8 @@ size: string = "default"
|
|||||||
}
|
}
|
||||||
|
|
||||||
.wrn-navbar__menu-link[aria-current="page"]:hover,
|
.wrn-navbar__menu-link[aria-current="page"]:hover,
|
||||||
.wrn-navbar__dropdown > summary[aria-current="page"]:hover {
|
.wrn-navbar__dropdown > summary[aria-current="page"]:hover,
|
||||||
|
.wrn-navbar__mega[data-active="true"] .wrn-mega__trigger:hover {
|
||||||
color: var(--wrn-component-color, var(--wrn-color-primary));
|
color: var(--wrn-component-color, var(--wrn-color-primary));
|
||||||
background: color-mix(
|
background: color-mix(
|
||||||
in srgb,
|
in srgb,
|
||||||
@@ -349,6 +536,7 @@ size: string = "default"
|
|||||||
|
|
||||||
.wrn-navbar__panel {
|
.wrn-navbar__panel {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
z-index: 1100;
|
||||||
top: calc(100% + 0.55rem);
|
top: calc(100% + 0.55rem);
|
||||||
left: 50%;
|
left: 50%;
|
||||||
display: grid;
|
display: grid;
|
||||||
@@ -508,7 +696,13 @@ size: string = "default"
|
|||||||
background: currentColor;
|
background: currentColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.wrn-navbar__mobile-mega-link { display: none; }
|
||||||
|
|
||||||
@media (max-width: 900px) {
|
@media (max-width: 900px) {
|
||||||
|
.wrn-navbar__main {
|
||||||
|
min-height: 3.5rem;
|
||||||
|
padding-block: 0.4rem;
|
||||||
|
}
|
||||||
.wrn-navbar--width-compact .wrn-navbar__main {
|
.wrn-navbar--width-compact .wrn-navbar__main {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
@@ -527,20 +721,39 @@ size: string = "default"
|
|||||||
background: var(--wrn-color-surface);
|
background: var(--wrn-color-surface);
|
||||||
border-bottom: 1px solid var(--wrn-color-border);
|
border-bottom: 1px solid var(--wrn-color-border);
|
||||||
box-shadow: 0 16px 32px rgb(15 23 42 / 0.12);
|
box-shadow: 0 16px 32px rgb(15 23 42 / 0.12);
|
||||||
max-height: calc(100dvh - 4rem);
|
height: auto;
|
||||||
|
max-height: calc(100dvh - 3.5rem);
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
overscroll-behavior: contain;
|
overscroll-behavior: contain;
|
||||||
}
|
}
|
||||||
|
.wrn-navbar[data-mobile-panel="sheet"] .wrn-navbar__collapse {
|
||||||
|
height: calc(100dvh - 3.5rem);
|
||||||
|
}
|
||||||
.wrn-navbar__collapse.is-open {
|
.wrn-navbar__collapse.is-open {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
.wrn-navbar:has(.wrn-navbar__collapse.is-open)::after {
|
||||||
|
position: fixed;
|
||||||
|
z-index: -1;
|
||||||
|
inset: 0;
|
||||||
|
background: rgb(15 23 42 / 0.42);
|
||||||
|
content: "";
|
||||||
|
}
|
||||||
.wrn-navbar__menus,
|
.wrn-navbar__menus,
|
||||||
.wrn-navbar__actions {
|
.wrn-navbar__actions {
|
||||||
|
position: static;
|
||||||
|
transform: none;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
.wrn-navbar__mega,
|
||||||
|
.wrn-navbar__mega .wrn-mega__trigger {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.wrn-navbar__mega { display: none; }
|
||||||
|
.wrn-navbar__mobile-mega-link { display: flex; }
|
||||||
.wrn-navbar__menu-link,
|
.wrn-navbar__menu-link,
|
||||||
.wrn-navbar__dropdown > summary,
|
.wrn-navbar__dropdown > summary,
|
||||||
.wrn-navbar__action {
|
.wrn-navbar__action {
|
||||||
@@ -557,6 +770,12 @@ size: string = "default"
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
animation: wrn-navbar-mobile-panel 180ms ease both;
|
animation: wrn-navbar-mobile-panel 180ms ease both;
|
||||||
}
|
}
|
||||||
|
.wrn-navbar__mega[data-full-width="true"] .wrn-mega__panel {
|
||||||
|
position: static;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 100%;
|
||||||
|
margin-top: 0.25rem;
|
||||||
|
}
|
||||||
.wrn-navbar__dropdown:not([open]) > .wrn-navbar__panel,
|
.wrn-navbar__dropdown:not([open]) > .wrn-navbar__panel,
|
||||||
.wrn-navbar__dropdown[open] > .wrn-navbar__panel {
|
.wrn-navbar__dropdown[open] > .wrn-navbar__panel {
|
||||||
transform: none;
|
transform: none;
|
||||||
@@ -569,7 +788,43 @@ size: string = "default"
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 1100px) and (min-width: 901px) {
|
||||||
|
.wrn-navbar[data-collapse-at="1100px"] .wrn-navbar__toggle { display: block; }
|
||||||
|
.wrn-navbar[data-collapse-at="1100px"] .wrn-navbar__collapse {
|
||||||
|
position: absolute;
|
||||||
|
top: 100%;
|
||||||
|
right: 0;
|
||||||
|
left: 0;
|
||||||
|
display: none;
|
||||||
|
max-height: calc(100dvh - 3.5rem);
|
||||||
|
padding: 0.75rem 1rem 1rem;
|
||||||
|
align-items: stretch;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow-y: auto;
|
||||||
|
background: var(--wrn-color-surface);
|
||||||
|
border-bottom: 1px solid var(--wrn-color-border);
|
||||||
|
box-shadow: 0 16px 32px rgb(15 23 42 / 0.12);
|
||||||
|
}
|
||||||
|
.wrn-navbar[data-collapse-at="1100px"] .wrn-navbar__collapse.is-open { display: flex; }
|
||||||
|
.wrn-navbar[data-collapse-at="1100px"] .wrn-navbar__menus,
|
||||||
|
.wrn-navbar[data-collapse-at="1100px"] .wrn-navbar__actions {
|
||||||
|
position: static;
|
||||||
|
transform: none;
|
||||||
|
width: 100%;
|
||||||
|
align-items: stretch;
|
||||||
|
flex: none;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
.wrn-navbar[data-collapse-at="1100px"] :is(.wrn-navbar__menu-link, .wrn-navbar__dropdown > summary, .wrn-navbar__action) { width: 100%; }
|
||||||
|
.wrn-navbar[data-collapse-at="1100px"] :is(.wrn-navbar__mega, .wrn-navbar__mega .wrn-mega__trigger) { width: 100%; }
|
||||||
|
.wrn-navbar[data-collapse-at="1100px"] .wrn-navbar__mega { display: none; }
|
||||||
|
.wrn-navbar[data-collapse-at="1100px"] .wrn-navbar__mobile-mega-link { display: flex; }
|
||||||
|
.wrn-navbar[data-collapse-at="1100px"] .wrn-navbar__panel { position: static; width: 100%; max-width: none; transform: none; }
|
||||||
|
.wrn-navbar[data-collapse-at="1100px"] .wrn-navbar__mega[data-full-width="true"] .wrn-mega__panel { position: static; width: 100%; max-width: 100%; margin-top: 0.25rem; }
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 600px) {
|
@media (max-width: 600px) {
|
||||||
|
.wrn-navbar[data-flush-mobile="false"] .wrn-navbar__main { padding-inline: 1rem; }
|
||||||
.wrn-navbar__brand-copy small {
|
.wrn-navbar__brand-copy small {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -576,6 +576,14 @@ current: true
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Compiled empty slots retain inert template markers, so :empty alone
|
||||||
|
cannot collapse their spacing in the rendered document. */
|
||||||
|
.wrn-page-header__meta:not(:has(> :not(template))),
|
||||||
|
.wrn-page-header__body:not(:has(> :not(template))),
|
||||||
|
.wrn-page-header__actions--slot-only:not(:has(> :not(template))) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
.wrn-page-header__meta {
|
.wrn-page-header__meta {
|
||||||
margin-top: 1.1rem;
|
margin-top: 1.1rem;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,13 @@ size: string = "default"
|
|||||||
{"label": "Amber", "value": "amber", "hex": "#d97706"}
|
{"label": "Amber", "value": "amber", "hex": "#d97706"}
|
||||||
]
|
]
|
||||||
compact: boolean = true
|
compact: boolean = true
|
||||||
|
iconOnly: boolean = true
|
||||||
|
themeIcon: string = "icon-[lucide--sun-moon]"
|
||||||
|
colorIcon: string = "icon-[lucide--palette]"
|
||||||
|
languageIcon: string = "icon-[lucide--languages]"
|
||||||
|
panelPlacement: string = "bottom-end"
|
||||||
|
mobilePanel: string = "dropdown"
|
||||||
|
showCurrentLanguage: boolean = true
|
||||||
class: string = ""
|
class: string = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,11 +44,11 @@ size: string = "default"
|
|||||||
}
|
}
|
||||||
|
|
||||||
view {
|
view {
|
||||||
<div class="wrn-preferences wrn-component--color-{color} wrn-component--size-{size} {compact ? 'wrn-preferences--compact' : ''} {class}" data-wrn-preferences aria-label="Display and language preferences">
|
<div class="wrn-preferences wrn-component--color-{color} wrn-component--size-{size} {compact ? 'wrn-preferences--compact' : ''} {class}" data-wrn-preferences data-icon-only="{iconOnly ? 'true' : 'false'}" data-panel-placement="{panelPlacement}" data-mobile-panel="{mobilePanel}" aria-label="Display and language preferences">
|
||||||
<details class="wrn-preferences__menu" name="wrn-preference-menu">
|
<details class="wrn-preferences__menu" name="wrn-preference-menu">
|
||||||
<summary aria-label="{themeLabel}" title="{themeLabel}">
|
<summary aria-label="{themeLabel}" title="{themeLabel}">
|
||||||
<span class="icon-[lucide--sun-moon]" aria-hidden="true"></span>
|
<span class="{themeIcon}" aria-hidden="true"></span>
|
||||||
{#if !compact}<span>{themeLabel}</span>{/if}
|
{#if !iconOnly && !compact}<span>{themeLabel}</span>{/if}
|
||||||
</summary>
|
</summary>
|
||||||
<div class="wrn-preferences__panel">
|
<div class="wrn-preferences__panel">
|
||||||
<strong>{themeLabel}</strong>
|
<strong>{themeLabel}</strong>
|
||||||
@@ -54,8 +61,8 @@ size: string = "default"
|
|||||||
|
|
||||||
<details class="wrn-preferences__menu" name="wrn-preference-menu">
|
<details class="wrn-preferences__menu" name="wrn-preference-menu">
|
||||||
<summary aria-label="{colorLabel}" title="{colorLabel}">
|
<summary aria-label="{colorLabel}" title="{colorLabel}">
|
||||||
<span class="icon-[lucide--palette]" aria-hidden="true"></span>
|
<span class="{colorIcon}" aria-hidden="true"></span>
|
||||||
{#if !compact}<span>{colorLabel}</span>{/if}
|
{#if !iconOnly && !compact}<span>{colorLabel}</span>{/if}
|
||||||
</summary>
|
</summary>
|
||||||
<div class="wrn-preferences__panel wrn-preferences__panel--colors">
|
<div class="wrn-preferences__panel wrn-preferences__panel--colors">
|
||||||
<strong>{colorLabel}</strong>
|
<strong>{colorLabel}</strong>
|
||||||
@@ -69,9 +76,9 @@ size: string = "default"
|
|||||||
|
|
||||||
<details class="wrn-preferences__menu wrn-preferences__menu--language" name="wrn-preference-menu">
|
<details class="wrn-preferences__menu wrn-preferences__menu--language" name="wrn-preference-menu">
|
||||||
<summary aria-label="{languageLabel}" title="{languageLabel}">
|
<summary aria-label="{languageLabel}" title="{languageLabel}">
|
||||||
<span class="icon-[lucide--languages]" aria-hidden="true"></span>
|
<span class="{languageIcon}" aria-hidden="true"></span>
|
||||||
<span class="wrn-preferences__current-language" aria-hidden="true">EN</span>
|
{#if showCurrentLanguage}<span class="wrn-preferences__current-language" aria-hidden="true">EN</span>{/if}
|
||||||
{#if !compact}<span>{languageLabel}</span>{/if}
|
{#if !iconOnly && !compact}<span>{languageLabel}</span>{/if}
|
||||||
</summary>
|
</summary>
|
||||||
<div class="wrn-preferences__panel wrn-preferences__panel--language">
|
<div class="wrn-preferences__panel wrn-preferences__panel--language">
|
||||||
<strong>{languageLabel}</strong>
|
<strong>{languageLabel}</strong>
|
||||||
@@ -157,6 +164,9 @@ size: string = "default"
|
|||||||
animation: wrn-component-enter 160ms ease both;
|
animation: wrn-component-enter 160ms ease both;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.wrn-preferences[data-panel-placement="bottom-start"] .wrn-preferences__panel { right: auto; left: 0; }
|
||||||
|
.wrn-preferences[data-panel-placement="bottom-center"] .wrn-preferences__panel { right: auto; left: 50%; transform: translateX(-50%); }
|
||||||
|
|
||||||
.wrn-preferences__panel > strong {
|
.wrn-preferences__panel > strong {
|
||||||
padding-inline: 0.25rem;
|
padding-inline: 0.25rem;
|
||||||
font-size: 0.7rem;
|
font-size: 0.7rem;
|
||||||
@@ -242,7 +252,7 @@ size: string = "default"
|
|||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 640px) {
|
@media (max-width: 640px) {
|
||||||
.wrn-preferences__panel {
|
.wrn-preferences[data-mobile-panel="sheet"] .wrn-preferences__panel {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: auto;
|
top: auto;
|
||||||
right: 1rem;
|
right: 1rem;
|
||||||
@@ -250,6 +260,15 @@ size: string = "default"
|
|||||||
left: 1rem;
|
left: 1rem;
|
||||||
width: auto;
|
width: auto;
|
||||||
}
|
}
|
||||||
|
.wrn-preferences[data-mobile-panel="dropdown"] .wrn-preferences__panel {
|
||||||
|
position: absolute;
|
||||||
|
top: calc(100% + 0.5rem);
|
||||||
|
right: 0;
|
||||||
|
bottom: auto;
|
||||||
|
left: auto;
|
||||||
|
width: max-content;
|
||||||
|
max-width: min(22rem, calc(100vw - 2rem));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Shared component foundation. */
|
/* Shared component foundation. */
|
||||||
|
|||||||
@@ -365,7 +365,9 @@ component RangeSlider {
|
|||||||
}
|
}
|
||||||
.wrn-next__field-heading label {
|
.wrn-next__field-heading label {
|
||||||
color: var(--wrn-color-text);
|
color: var(--wrn-color-text);
|
||||||
|
font-size: 0.8125rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
line-height: 1.35;
|
||||||
}
|
}
|
||||||
.wrn-next__field-hint,
|
.wrn-next__field-hint,
|
||||||
.wrn-next__field-help {
|
.wrn-next__field-help {
|
||||||
|
|||||||
@@ -24,6 +24,10 @@ component Scrollspy {
|
|||||||
active: string = ""
|
active: string = ""
|
||||||
label: string = "On this page"
|
label: string = "On this page"
|
||||||
heading: string = ""
|
heading: string = ""
|
||||||
|
sticky: boolean = false
|
||||||
|
topOffset: string = "6rem"
|
||||||
|
sectionOffset: string = "7rem"
|
||||||
|
collapseAt: string = "800px"
|
||||||
class: string = ""
|
class: string = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,6 +48,7 @@ component Scrollspy {
|
|||||||
class='wrn-scrollspy {class}'
|
class='wrn-scrollspy {class}'
|
||||||
data-color='{color}'
|
data-color='{color}'
|
||||||
data-size='{size}'
|
data-size='{size}'
|
||||||
|
data-sticky='{sticky ? "true" : "false"}' data-collapse-at='{collapseAt}' style='--wrn-scrollspy-top: {topOffset}; --wrn-scrollspy-section-offset: {sectionOffset};'
|
||||||
data-wrn-scrollspy="true"
|
data-wrn-scrollspy="true"
|
||||||
role="navigation"
|
role="navigation"
|
||||||
aria-label='{label}'
|
aria-label='{label}'
|
||||||
@@ -74,6 +79,12 @@ component Scrollspy {
|
|||||||
--scrollspy-accent: var(--wrn-color-primary);
|
--scrollspy-accent: var(--wrn-color-primary);
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
.wrn-scrollspy[data-sticky="true"] { position: sticky; top: var(--wrn-scrollspy-top); height: max-content; }
|
||||||
|
.wrn-scrollspy__link { scroll-margin-top: var(--wrn-scrollspy-section-offset); }
|
||||||
|
|
||||||
|
.wrn-scrollspy:not(:has(.wrn-scrollspy__item)):not(:has(slot > *)) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
.wrn-scrollspy[data-color="secondary"] {
|
.wrn-scrollspy[data-color="secondary"] {
|
||||||
--scrollspy-accent: var(--wrn-color-secondary);
|
--scrollspy-accent: var(--wrn-color-secondary);
|
||||||
@@ -148,6 +159,7 @@ component Scrollspy {
|
|||||||
* line rather than a screenful.
|
* line rather than a screenful.
|
||||||
*/
|
*/
|
||||||
@media (max-width: 767px) {
|
@media (max-width: 767px) {
|
||||||
|
.wrn-scrollspy[data-collapse-at="800px"] { position: static; }
|
||||||
.wrn-scrollspy__list {
|
.wrn-scrollspy__list {
|
||||||
grid-auto-flow: column;
|
grid-auto-flow: column;
|
||||||
grid-auto-columns: max-content;
|
grid-auto-columns: max-content;
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ component Section {
|
|||||||
padding-block: 3rem;
|
padding-block: 3rem;
|
||||||
background: var(--section-tint);
|
background: var(--section-tint);
|
||||||
color: var(--section-ink);
|
color: var(--section-ink);
|
||||||
|
scroll-margin-top: var(--wrn-sticky-header-offset, 5rem);
|
||||||
}
|
}
|
||||||
|
|
||||||
.wrn-section[data-spacing="sm"] {
|
.wrn-section[data-spacing="sm"] {
|
||||||
|
|||||||
@@ -20,6 +20,14 @@ component SplitHero {
|
|||||||
variant: string = "default"
|
variant: string = "default"
|
||||||
maxWidth: string = "xl"
|
maxWidth: string = "xl"
|
||||||
fullBleed: boolean = true
|
fullBleed: boolean = true
|
||||||
|
gutter: string = "md"
|
||||||
|
contentGutter: string = "md"
|
||||||
|
flushMobile: boolean = false
|
||||||
|
titleSize: string = "default"
|
||||||
|
titleMaxWidth: string = ""
|
||||||
|
descriptionWeight: string = "default"
|
||||||
|
mobileTitleSize: string = "default"
|
||||||
|
mobileStack: boolean = true
|
||||||
backgroundImage: string = ""
|
backgroundImage: string = ""
|
||||||
visualImage: string = ""
|
visualImage: string = ""
|
||||||
visualAlt: string = ""
|
visualAlt: string = ""
|
||||||
@@ -45,6 +53,8 @@ component SplitHero {
|
|||||||
data-variant='{variant}'
|
data-variant='{variant}'
|
||||||
data-max-width='{maxWidth}'
|
data-max-width='{maxWidth}'
|
||||||
data-full-bleed='{fullBleed ? "true" : "false"}'
|
data-full-bleed='{fullBleed ? "true" : "false"}'
|
||||||
|
data-gutter='{gutter}' data-content-gutter='{contentGutter}' data-flush-mobile='{flushMobile ? "true" : "false"}' data-title-size='{titleSize}' data-description-weight='{descriptionWeight}' data-mobile-title-size='{mobileTitleSize}' data-mobile-stack='{mobileStack ? "true" : "false"}'
|
||||||
|
style='--wrn-split-title-max-width: {titleMaxWidth || "18ch"}'
|
||||||
data-visual-style='{visualStyle}'
|
data-visual-style='{visualStyle}'
|
||||||
class='wrn-split-hero {class}'
|
class='wrn-split-hero {class}'
|
||||||
>
|
>
|
||||||
@@ -413,6 +423,7 @@ component SplitHero {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.wrn-split-hero__title {
|
.wrn-split-hero__title {
|
||||||
|
max-width: var(--wrn-split-title-max-width);
|
||||||
max-width: 15ch;
|
max-width: 15ch;
|
||||||
margin: 1.45rem 0 0;
|
margin: 1.45rem 0 0;
|
||||||
color: var(--wrn-color-text);
|
color: var(--wrn-color-text);
|
||||||
@@ -421,6 +432,8 @@ component SplitHero {
|
|||||||
line-height: 1.02;
|
line-height: 1.02;
|
||||||
letter-spacing: -0.05em;
|
letter-spacing: -0.05em;
|
||||||
}
|
}
|
||||||
|
.wrn-split-hero[data-title-size="xl"] .wrn-split-hero__title { font-size: clamp(3rem, 5.5vw, 5rem); }
|
||||||
|
.wrn-split-hero[data-description-weight="medium"] .wrn-split-hero__description { font-weight: 500; }
|
||||||
|
|
||||||
.wrn-split-hero[data-size="compact"] .wrn-split-hero__title,
|
.wrn-split-hero[data-size="compact"] .wrn-split-hero__title,
|
||||||
.wrn-split-hero[data-size="sm"] .wrn-split-hero__title {
|
.wrn-split-hero[data-size="sm"] .wrn-split-hero__title {
|
||||||
@@ -771,6 +784,7 @@ component SplitHero {
|
|||||||
.wrn-split-hero[data-ratio="content"] .wrn-split-hero__layout {
|
.wrn-split-hero[data-ratio="content"] .wrn-split-hero__layout {
|
||||||
grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
|
grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
|
||||||
}
|
}
|
||||||
|
.wrn-split-hero[data-ratio="wide-copy"] .wrn-split-hero__layout { grid-template-columns: minmax(0, 1.12fr) minmax(20rem, 0.88fr); }
|
||||||
|
|
||||||
.wrn-split-hero[data-ratio="visual"] .wrn-split-hero__layout {
|
.wrn-split-hero[data-ratio="visual"] .wrn-split-hero__layout {
|
||||||
grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
|
grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
|
||||||
@@ -786,6 +800,8 @@ component SplitHero {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 639px) {
|
@media (max-width: 639px) {
|
||||||
|
.wrn-split-hero[data-flush-mobile="false"] .wrn-split-hero__inner { width: calc(100% - 2rem); }
|
||||||
|
.wrn-split-hero[data-mobile-title-size="lg"] .wrn-split-hero__title { font-size: clamp(2.5rem, 12vw, 3.5rem); }
|
||||||
.wrn-split-hero__inner {
|
.wrn-split-hero__inner {
|
||||||
padding-block: 3.25rem;
|
padding-block: 3.25rem;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,11 @@ component StatsBar {
|
|||||||
color: string = "primary"
|
color: string = "primary"
|
||||||
variant: string = "raised"
|
variant: string = "raised"
|
||||||
maxWidth: string = "xl"
|
maxWidth: string = "xl"
|
||||||
|
radius: string = "default"
|
||||||
|
shadow: string = "default"
|
||||||
|
gutter: string = "md"
|
||||||
|
outerSpacing: string = "none"
|
||||||
|
mobileColumns: number = 1
|
||||||
class: string = ""
|
class: string = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -24,6 +29,7 @@ component StatsBar {
|
|||||||
data-color='{color}'
|
data-color='{color}'
|
||||||
data-variant='{variant}'
|
data-variant='{variant}'
|
||||||
data-max-width='{maxWidth}'
|
data-max-width='{maxWidth}'
|
||||||
|
data-radius='{radius}' data-shadow='{shadow}' data-gutter='{gutter}' data-outer-spacing='{outerSpacing}' data-mobile-columns='{mobileColumns}'
|
||||||
class='wrn-stats-bar {class}'
|
class='wrn-stats-bar {class}'
|
||||||
aria-label="Key statistics"
|
aria-label="Key statistics"
|
||||||
>
|
>
|
||||||
@@ -91,6 +97,8 @@ component StatsBar {
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</article>
|
</article>
|
||||||
|
{:empty}
|
||||||
|
<div class="wrn-stats-bar__empty" role="status">No statistics are available.</div>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -98,6 +106,15 @@ component StatsBar {
|
|||||||
}
|
}
|
||||||
|
|
||||||
style {
|
style {
|
||||||
|
.wrn-stats-bar__empty {
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
padding: 1.25rem;
|
||||||
|
color: var(--wrn-color-text-muted);
|
||||||
|
background: var(--wrn-color-surface-soft);
|
||||||
|
border: 1px dashed var(--wrn-color-border);
|
||||||
|
border-radius: 0.9rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
.wrn-stats-bar {
|
.wrn-stats-bar {
|
||||||
--stats-accent: var(--wrn-color-primary);
|
--stats-accent: var(--wrn-color-primary);
|
||||||
--stats-contrast: var(--wrn-color-primary-contrast);
|
--stats-contrast: var(--wrn-color-primary-contrast);
|
||||||
@@ -135,21 +152,43 @@ component StatsBar {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.wrn-stats-bar__inner {
|
.wrn-stats-bar__inner {
|
||||||
width: min(calc(100% - 2rem), 80rem);
|
--stats-max-width: 80rem;
|
||||||
|
--stats-gutter-width: 0rem;
|
||||||
|
|
||||||
|
width: min(
|
||||||
|
calc(100% - var(--stats-gutter-width)),
|
||||||
|
calc(var(--stats-max-width) - var(--stats-gutter-width))
|
||||||
|
);
|
||||||
margin-inline: auto;
|
margin-inline: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.wrn-stats-bar[data-gutter="sm"] .wrn-stats-bar__inner {
|
||||||
|
--stats-gutter-width: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrn-stats-bar[data-gutter="md"] .wrn-stats-bar__inner {
|
||||||
|
--stats-gutter-width: 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrn-stats-bar[data-gutter="lg"] .wrn-stats-bar__inner {
|
||||||
|
--stats-gutter-width: 6rem;
|
||||||
|
}
|
||||||
|
.wrn-stats-bar[data-outer-spacing="md"] { margin-block: 2rem; }
|
||||||
|
.wrn-stats-bar[data-radius="xl"] .wrn-stats-bar__surface { overflow: hidden; border-radius: 1.25rem; }
|
||||||
|
.wrn-stats-bar[data-shadow="sm"] .wrn-stats-bar__surface { box-shadow: 0 10px 30px rgb(15 23 42 / 0.05); }
|
||||||
|
.wrn-stats-bar[data-variant="card"] .wrn-stats-bar__surface { border: 1px solid var(--wrn-color-border); background: var(--wrn-color-surface); }
|
||||||
|
|
||||||
.wrn-stats-bar[data-max-width="compact"] .wrn-stats-bar__inner {
|
.wrn-stats-bar[data-max-width="compact"] .wrn-stats-bar__inner {
|
||||||
width: min(calc(100% - 2rem), 64rem);
|
--stats-max-width: 64rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wrn-stats-bar[data-max-width="lg"] .wrn-stats-bar__inner {
|
.wrn-stats-bar[data-max-width="lg"] .wrn-stats-bar__inner {
|
||||||
width: min(calc(100% - 2rem), 72rem);
|
--stats-max-width: 72rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wrn-stats-bar[data-max-width="wide"] .wrn-stats-bar__inner,
|
.wrn-stats-bar[data-max-width="wide"] .wrn-stats-bar__inner,
|
||||||
.wrn-stats-bar[data-max-width="2xl"] .wrn-stats-bar__inner {
|
.wrn-stats-bar[data-max-width="2xl"] .wrn-stats-bar__inner {
|
||||||
width: min(calc(100% - 2rem), 90rem);
|
--stats-max-width: 90rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wrn-stats-bar[data-max-width="full"] .wrn-stats-bar__inner {
|
.wrn-stats-bar[data-max-width="full"] .wrn-stats-bar__inner {
|
||||||
@@ -469,6 +508,10 @@ component StatsBar {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 639px) {
|
@media (max-width: 639px) {
|
||||||
|
.wrn-stats-bar[data-mobile-columns="1"] .wrn-stats-bar__surface { grid-template-columns: 1fr; }
|
||||||
|
.wrn-stats-bar[data-gutter="sm"] .wrn-stats-bar__inner,
|
||||||
|
.wrn-stats-bar[data-gutter="md"] .wrn-stats-bar__inner { --stats-gutter-width: 2rem; }
|
||||||
|
.wrn-stats-bar[data-gutter="lg"] .wrn-stats-bar__inner { --stats-gutter-width: 3rem; }
|
||||||
.wrn-stats-bar[data-max-width="full"] .wrn-stats-bar__surface {
|
.wrn-stats-bar[data-max-width="full"] .wrn-stats-bar__surface {
|
||||||
border-inline: 0;
|
border-inline: 0;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
|
|||||||
@@ -649,7 +649,9 @@ component StrongPassword {
|
|||||||
}
|
}
|
||||||
.wrn-next__field-heading label {
|
.wrn-next__field-heading label {
|
||||||
color: var(--wrn-color-text);
|
color: var(--wrn-color-text);
|
||||||
|
font-size: 0.8125rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
line-height: 1.35;
|
||||||
}
|
}
|
||||||
.wrn-next__field-hint,
|
.wrn-next__field-hint,
|
||||||
.wrn-next__field-help {
|
.wrn-next__field-help {
|
||||||
|
|||||||
@@ -41,6 +41,18 @@ component Tabs {
|
|||||||
return String(item.value || item.id || index)
|
return String(item.value || item.id || index)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
shared function tabId(item, index) {
|
||||||
|
return "wrn-tab-" + valueOf(item, index)
|
||||||
|
}
|
||||||
|
|
||||||
|
shared function panelId(item, index) {
|
||||||
|
return "wrn-panel-" + valueOf(item, index)
|
||||||
|
}
|
||||||
|
|
||||||
|
shared function panelSlot(item, index) {
|
||||||
|
return "panel-" + valueOf(item, index)
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* In url mode the query parameter is the source of truth, not local state.
|
* In url mode the query parameter is the source of truth, not local state.
|
||||||
*
|
*
|
||||||
@@ -130,8 +142,8 @@ component Tabs {
|
|||||||
role="tab"
|
role="tab"
|
||||||
data-value='{valueOf(item, index)}'
|
data-value='{valueOf(item, index)}'
|
||||||
data-wrn-roving-item="true"
|
data-wrn-roving-item="true"
|
||||||
id='wrn-tab-{valueOf(item, index)}'
|
id='{tabId(item, index)}'
|
||||||
aria-controls='wrn-panel-{valueOf(item, index)}'
|
aria-controls='{panelId(item, index)}'
|
||||||
aria-selected='{isSelected(item, index) ? "true" : "false"}'
|
aria-selected='{isSelected(item, index) ? "true" : "false"}'
|
||||||
aria-disabled='{item.disabled ? "true" : "false"}'
|
aria-disabled='{item.disabled ? "true" : "false"}'
|
||||||
@click='selectTab(item, index, event)'
|
@click='selectTab(item, index, event)'
|
||||||
@@ -148,8 +160,8 @@ component Tabs {
|
|||||||
<div
|
<div
|
||||||
class="wrn-tabs__panel"
|
class="wrn-tabs__panel"
|
||||||
role="tabpanel"
|
role="tabpanel"
|
||||||
id='wrn-panel-{valueOf(item, index)}'
|
id='{panelId(item, index)}'
|
||||||
aria-labelledby='wrn-tab-{valueOf(item, index)}'
|
aria-labelledby='{tabId(item, index)}'
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
data-show='isSelected(item, index)'
|
data-show='isSelected(item, index)'
|
||||||
>
|
>
|
||||||
@@ -158,7 +170,7 @@ component Tabs {
|
|||||||
</h3>
|
</h3>
|
||||||
<p class="wrn-tabs__description" data-show="item.description">{item.description}</p>
|
<p class="wrn-tabs__description" data-show="item.description">{item.description}</p>
|
||||||
<div class="wrn-tabs__content" data-show="item.content">{item.content}</div>
|
<div class="wrn-tabs__content" data-show="item.content">{item.content}</div>
|
||||||
<slot name="panel-{valueOf(item, index)}"></slot>
|
<slot name='{panelSlot(item, index)}'></slot>
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
<slot />
|
<slot />
|
||||||
|
|||||||
@@ -249,7 +249,9 @@ size: string = "default"
|
|||||||
}
|
}
|
||||||
.wrn-next__field-heading label {
|
.wrn-next__field-heading label {
|
||||||
color: var(--wrn-color-text);
|
color: var(--wrn-color-text);
|
||||||
|
font-size: 0.8125rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
line-height: 1.35;
|
||||||
}
|
}
|
||||||
.wrn-next__field-hint,
|
.wrn-next__field-hint,
|
||||||
.wrn-next__field-help {
|
.wrn-next__field-help {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ component Timeline {
|
|||||||
description: string = ""
|
description: string = ""
|
||||||
items: unknown[] = []
|
items: unknown[] = []
|
||||||
variant: string = "default"
|
variant: string = "default"
|
||||||
|
numbered: boolean = false
|
||||||
class: string = ""
|
class: string = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -18,6 +19,9 @@ component Timeline {
|
|||||||
data-ui-component="Timeline"
|
data-ui-component="Timeline"
|
||||||
aria-label='{title}'
|
aria-label='{title}'
|
||||||
class='wrn-timeline {class}'
|
class='wrn-timeline {class}'
|
||||||
|
data-size='{size}'
|
||||||
|
data-color='{color}'
|
||||||
|
data-variant='{variant}'
|
||||||
>
|
>
|
||||||
{#if title || description}
|
{#if title || description}
|
||||||
<header class="wrn-timeline__header">
|
<header class="wrn-timeline__header">
|
||||||
@@ -34,13 +38,18 @@ component Timeline {
|
|||||||
{#each items as item, index}
|
{#each items as item, index}
|
||||||
<li
|
<li
|
||||||
class="wrn-timeline__item"
|
class="wrn-timeline__item"
|
||||||
|
data-interactive='{item.href ? "true" : "false"}'
|
||||||
@click='output.select({ item: item, index: index })'
|
@click='output.select({ item: item, index: index })'
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
class="wrn-timeline__marker"
|
class="wrn-timeline__marker"
|
||||||
data-status='{item.status || "default"}'
|
data-status='{item.status || "default"}'
|
||||||
>
|
>
|
||||||
<span class='{item.icon || "icon-[lucide--circle]"}' aria-hidden="true"></span>
|
{#if numbered}
|
||||||
|
<span class="wrn-timeline__number" aria-hidden="true">{index + 1}</span>
|
||||||
|
{:else}
|
||||||
|
<span class='{item.icon || "icon-[lucide--circle-check]"}' aria-hidden="true"></span>
|
||||||
|
{/if}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<article
|
<article
|
||||||
@@ -81,22 +90,28 @@ component Timeline {
|
|||||||
}
|
}
|
||||||
|
|
||||||
style {
|
style {
|
||||||
.wrn-timeline { width: 100%; }
|
.wrn-timeline { --wrn-timeline-accent: var(--wrn-color-primary); width: 100%; min-width: 0; color: var(--wrn-color-text); }
|
||||||
|
.wrn-timeline[data-color="success"] { --wrn-timeline-accent: var(--wrn-color-success); }
|
||||||
|
.wrn-timeline[data-color="info"] { --wrn-timeline-accent: var(--wrn-color-info); }
|
||||||
.wrn-timeline__header { margin-bottom: 1.5rem; }
|
.wrn-timeline__header { margin-bottom: 1.5rem; }
|
||||||
.wrn-timeline__title { color: var(--wrn-color-text); font-size: 1.25rem; font-weight: 700; }
|
.wrn-timeline__title { color: var(--wrn-color-text); font-size: 1.25rem; font-weight: 700; }
|
||||||
.wrn-timeline__description { max-width: 42rem; margin-top: 0.5rem; color: var(--wrn-color-text-muted); line-height: 1.75rem; }
|
.wrn-timeline__description { max-width: 42rem; margin-top: 0.5rem; color: var(--wrn-color-text-muted); line-height: 1.75rem; }
|
||||||
.wrn-timeline__list { position: relative; margin-left: 1rem; border-left: 1px solid var(--wrn-color-border); }
|
.wrn-timeline__list { position: relative; display: grid; gap: 1rem; margin: 0; padding: 0 0 0 3rem; list-style: none; }
|
||||||
.wrn-timeline__item { position: relative; padding: 0 0 2rem 2rem; cursor: pointer; }
|
.wrn-timeline__list::before { position: absolute; inset-block: 1rem; inset-inline-start: 1rem; width: 2px; border-radius: 999px; background: color-mix(in srgb, var(--wrn-timeline-accent) 30%, var(--wrn-color-border)); content: ""; }
|
||||||
|
.wrn-timeline__item { position: relative; min-width: 0; }
|
||||||
.wrn-timeline__item:last-child { padding-bottom: 0; }
|
.wrn-timeline__item:last-child { padding-bottom: 0; }
|
||||||
.wrn-timeline__marker {
|
.wrn-timeline__marker {
|
||||||
position: absolute; top: 0; left: -1.05rem; display: flex; width: 2rem; height: 2rem;
|
position: absolute; z-index: 1; top: 1rem; inset-inline-start: -3rem; display: flex; width: 2rem; height: 2rem;
|
||||||
align-items: center; justify-content: center; border: 4px solid var(--wrn-color-background);
|
align-items: center; justify-content: center; border: 4px solid var(--wrn-color-background);
|
||||||
border-radius: 50%; color: var(--wrn-color-on-primary); background: var(--wrn-color-primary); box-shadow: var(--wrn-shadow-1);
|
border-radius: 50%; color: var(--wrn-color-on-primary); background: var(--wrn-timeline-accent); box-shadow: var(--wrn-shadow-1);
|
||||||
}
|
}
|
||||||
.wrn-timeline__marker:is([data-status="complete"], [data-status="success"]) { background: var(--wrn-color-success); }
|
.wrn-timeline__marker:is([data-status="complete"], [data-status="success"]) { background: var(--wrn-color-success); }
|
||||||
.wrn-timeline__marker:is([data-status="warning"], [data-status="pending"]) { background: var(--wrn-color-warning); }
|
.wrn-timeline__marker:is([data-status="warning"], [data-status="pending"]) { background: var(--wrn-color-warning); }
|
||||||
.wrn-timeline__marker:is([data-status="danger"], [data-status="failed"]) { background: var(--wrn-color-danger); }
|
.wrn-timeline__marker:is([data-status="danger"], [data-status="failed"]) { background: var(--wrn-color-danger); }
|
||||||
.wrn-timeline__card { padding: 1.25rem; border: 1px solid var(--wrn-color-border); border-radius: calc(var(--wrn-radius) * 1.5); background: var(--wrn-color-surface-raised); box-shadow: var(--wrn-shadow-1); }
|
.wrn-timeline__number { font-size: 0.75rem; font-weight: 800; }
|
||||||
|
.wrn-timeline__card { min-width: 0; padding: 1.25rem; border: 1px solid var(--wrn-color-border); border-radius: calc(var(--wrn-radius) * 1.5); background: var(--wrn-color-surface-raised); box-shadow: var(--wrn-shadow-1); transition: border-color 160ms ease, transform 160ms ease, box-shadow 160ms ease; }
|
||||||
|
.wrn-timeline__item[data-interactive="true"] { cursor: pointer; }
|
||||||
|
.wrn-timeline__item[data-interactive="true"]:hover .wrn-timeline__card { border-color: color-mix(in srgb, var(--wrn-timeline-accent) 45%, var(--wrn-color-border)); transform: translateY(-2px); box-shadow: var(--wrn-shadow-2); }
|
||||||
.wrn-timeline__card[data-variant="minimal"] { padding: 0; border-color: transparent; background: transparent; box-shadow: none; }
|
.wrn-timeline__card[data-variant="minimal"] { padding: 0; border-color: transparent; background: transparent; box-shadow: none; }
|
||||||
.wrn-timeline__card-header { display: flex; flex-direction: column; gap: 0.5rem; }
|
.wrn-timeline__card-header { display: flex; flex-direction: column; gap: 0.5rem; }
|
||||||
.wrn-timeline__item-title { color: var(--wrn-color-text); font-weight: 700; }
|
.wrn-timeline__item-title { color: var(--wrn-color-text); font-weight: 700; }
|
||||||
@@ -110,5 +125,11 @@ component Timeline {
|
|||||||
@media (min-width: 40rem) {
|
@media (min-width: 40rem) {
|
||||||
.wrn-timeline__card-header { flex-direction: row; align-items: flex-start; justify-content: space-between; }
|
.wrn-timeline__card-header { flex-direction: row; align-items: flex-start; justify-content: space-between; }
|
||||||
}
|
}
|
||||||
|
@media (max-width: 39.99rem) {
|
||||||
|
.wrn-timeline__list { padding-inline-start: 2.5rem; }
|
||||||
|
.wrn-timeline__list::before { inset-inline-start: 0.75rem; }
|
||||||
|
.wrn-timeline__marker { inset-inline-start: -2.5rem; }
|
||||||
|
.wrn-timeline__card { padding: 1rem; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -492,7 +492,9 @@ component TogglePassword {
|
|||||||
}
|
}
|
||||||
.wrn-next__field-heading label {
|
.wrn-next__field-heading label {
|
||||||
color: var(--wrn-color-text);
|
color: var(--wrn-color-text);
|
||||||
|
font-size: 0.8125rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
line-height: 1.35;
|
||||||
}
|
}
|
||||||
.wrn-next__field-hint,
|
.wrn-next__field-hint,
|
||||||
.wrn-next__field-help {
|
.wrn-next__field-help {
|
||||||
|
|||||||
@@ -360,7 +360,9 @@ size: string = "default"
|
|||||||
}
|
}
|
||||||
.wrn-next__field-heading label {
|
.wrn-next__field-heading label {
|
||||||
color: var(--wrn-color-text);
|
color: var(--wrn-color-text);
|
||||||
|
font-size: 0.8125rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
line-height: 1.35;
|
||||||
}
|
}
|
||||||
.wrn-next__field-hint,
|
.wrn-next__field-hint,
|
||||||
.wrn-next__field-help {
|
.wrn-next__field-help {
|
||||||
|
|||||||
@@ -315,7 +315,9 @@ component Input {
|
|||||||
}
|
}
|
||||||
.wrn-next__field-heading label {
|
.wrn-next__field-heading label {
|
||||||
color: var(--wrn-color-text);
|
color: var(--wrn-color-text);
|
||||||
|
font-size: 0.8125rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
line-height: 1.35;
|
||||||
}
|
}
|
||||||
.wrn-next__field-hint,
|
.wrn-next__field-hint,
|
||||||
.wrn-next__field-help {
|
.wrn-next__field-help {
|
||||||
|
|||||||
@@ -221,7 +221,9 @@ size: string = "default"
|
|||||||
}
|
}
|
||||||
.wrn-next__field-heading label {
|
.wrn-next__field-heading label {
|
||||||
color: var(--wrn-color-text);
|
color: var(--wrn-color-text);
|
||||||
|
font-size: 0.8125rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
line-height: 1.35;
|
||||||
}
|
}
|
||||||
.wrn-next__field-hint,
|
.wrn-next__field-hint,
|
||||||
.wrn-next__field-help {
|
.wrn-next__field-help {
|
||||||
|
|||||||
@@ -244,7 +244,9 @@ size: string = "default"
|
|||||||
}
|
}
|
||||||
.wrn-next__field-heading label {
|
.wrn-next__field-heading label {
|
||||||
color: var(--wrn-color-text);
|
color: var(--wrn-color-text);
|
||||||
|
font-size: 0.8125rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
line-height: 1.35;
|
||||||
}
|
}
|
||||||
.wrn-next__field-hint,
|
.wrn-next__field-hint,
|
||||||
.wrn-next__field-help {
|
.wrn-next__field-help {
|
||||||
|
|||||||
@@ -243,7 +243,9 @@ component Switch {
|
|||||||
}
|
}
|
||||||
.wrn-next__field-heading label {
|
.wrn-next__field-heading label {
|
||||||
color: var(--wrn-color-text);
|
color: var(--wrn-color-text);
|
||||||
|
font-size: 0.8125rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
line-height: 1.35;
|
||||||
}
|
}
|
||||||
.wrn-next__field-hint,
|
.wrn-next__field-hint,
|
||||||
.wrn-next__field-help {
|
.wrn-next__field-help {
|
||||||
|
|||||||
@@ -223,7 +223,9 @@ size: string = "default"
|
|||||||
}
|
}
|
||||||
.wrn-next__field-heading label {
|
.wrn-next__field-heading label {
|
||||||
color: var(--wrn-color-text);
|
color: var(--wrn-color-text);
|
||||||
|
font-size: 0.8125rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
line-height: 1.35;
|
||||||
}
|
}
|
||||||
.wrn-next__field-hint,
|
.wrn-next__field-hint,
|
||||||
.wrn-next__field-help {
|
.wrn-next__field-help {
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/ui",
|
"name": "@wrnexus/ui",
|
||||||
"version": "0.8.23",
|
"version": "0.8.56",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.ts",
|
".": "./src/index.ts",
|
||||||
|
"./navigation": "./src/navigation.ts",
|
||||||
"./registry": "./src/registry.ts",
|
"./registry": "./src/registry.ts",
|
||||||
"./components/*": "./components/*",
|
"./components/*": "./components/*",
|
||||||
"./component-catalog.json": "./component-catalog.json",
|
"./component-catalog.json": "./component-catalog.json",
|
||||||
|
|||||||
@@ -24,4 +24,22 @@
|
|||||||
* server-only subpath. Import from there instead if you need them.
|
* server-only subpath. Import from there instead if you need them.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export {};
|
export type {
|
||||||
|
MegaMenuColumn,
|
||||||
|
MegaMenuDensity,
|
||||||
|
MegaMenuFeatured,
|
||||||
|
MegaMenuPanelAlign,
|
||||||
|
MegaMenuPanelWidth,
|
||||||
|
MegaMenuRailItem,
|
||||||
|
MegaMenuVariant,
|
||||||
|
NavbarAction,
|
||||||
|
NavbarBrand,
|
||||||
|
NavbarDropdownGroup,
|
||||||
|
NavbarDropdownItem,
|
||||||
|
NavbarItem,
|
||||||
|
NavbarItemType,
|
||||||
|
NavbarLinkItem,
|
||||||
|
NavbarMegaMenuData,
|
||||||
|
NavbarMegaMenuItem,
|
||||||
|
NavigationLink,
|
||||||
|
} from "./navigation";
|
||||||
|
|||||||
@@ -0,0 +1,121 @@
|
|||||||
|
/** Shared, serializable navigation contracts for Navbar and application configs. */
|
||||||
|
|
||||||
|
export type NavbarItemType = "link" | "dropdown" | "mega";
|
||||||
|
export type MegaMenuVariant = "default" | "icon-grid" | "catalog" | "dark";
|
||||||
|
export type MegaMenuDensity = "compact" | "default" | "comfortable";
|
||||||
|
export type MegaMenuPanelWidth = "sm" | "md" | "lg" | "xl" | "2xl" | "full";
|
||||||
|
export type MegaMenuPanelAlign = "start" | "center" | "end";
|
||||||
|
|
||||||
|
export interface NavigationLink {
|
||||||
|
label: string;
|
||||||
|
href: string;
|
||||||
|
value?: string;
|
||||||
|
labelKey?: string;
|
||||||
|
description?: string;
|
||||||
|
descriptionKey?: string;
|
||||||
|
icon?: string;
|
||||||
|
image?: string;
|
||||||
|
imageAlt?: string;
|
||||||
|
eyebrow?: string;
|
||||||
|
badge?: string;
|
||||||
|
target?: string;
|
||||||
|
rel?: string;
|
||||||
|
disabled?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NavbarLinkItem extends NavigationLink {
|
||||||
|
type?: "link";
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NavbarDropdownGroup {
|
||||||
|
label?: string;
|
||||||
|
labelKey?: string;
|
||||||
|
description?: string;
|
||||||
|
descriptionKey?: string;
|
||||||
|
items: NavigationLink[];
|
||||||
|
/** Compatibility alias accepted by Navbar. Prefer `items`. */
|
||||||
|
children?: NavigationLink[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NavbarDropdownItem {
|
||||||
|
type: "dropdown";
|
||||||
|
label: string;
|
||||||
|
value?: string;
|
||||||
|
labelKey?: string;
|
||||||
|
description?: string;
|
||||||
|
descriptionKey?: string;
|
||||||
|
icon?: string;
|
||||||
|
columns?: number;
|
||||||
|
items: Array<NavigationLink | NavbarDropdownGroup>;
|
||||||
|
/** Compatibility alias accepted by Navbar. Prefer `items`. */
|
||||||
|
children?: Array<NavigationLink | NavbarDropdownGroup>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MegaMenuColumn {
|
||||||
|
heading?: string;
|
||||||
|
eyebrow?: string;
|
||||||
|
description?: string;
|
||||||
|
image?: string;
|
||||||
|
imageAlt?: string;
|
||||||
|
items: NavigationLink[];
|
||||||
|
actionLabel?: string;
|
||||||
|
actionHref?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MegaMenuRailItem extends NavigationLink {}
|
||||||
|
|
||||||
|
export interface MegaMenuFeatured {
|
||||||
|
eyebrow?: string;
|
||||||
|
image?: string;
|
||||||
|
imageAlt?: string;
|
||||||
|
title?: string;
|
||||||
|
description?: string;
|
||||||
|
actionLabel?: string;
|
||||||
|
actionHref?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NavbarMegaMenuData {
|
||||||
|
variant?: MegaMenuVariant;
|
||||||
|
density?: MegaMenuDensity;
|
||||||
|
panelWidth?: MegaMenuPanelWidth;
|
||||||
|
panelAlign?: MegaMenuPanelAlign;
|
||||||
|
fullWidth?: boolean;
|
||||||
|
activeCategory?: string;
|
||||||
|
columnCount?: number;
|
||||||
|
columns: MegaMenuColumn[];
|
||||||
|
rail?: MegaMenuRailItem[];
|
||||||
|
featured?: MegaMenuFeatured;
|
||||||
|
actionLabel?: string;
|
||||||
|
actionHref?: string;
|
||||||
|
actionIcon?: string;
|
||||||
|
footer?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NavbarMegaMenuItem {
|
||||||
|
type: "mega";
|
||||||
|
label: string;
|
||||||
|
value?: string;
|
||||||
|
labelKey?: string;
|
||||||
|
icon?: string;
|
||||||
|
mega: NavbarMegaMenuData;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type NavbarItem = NavbarLinkItem | NavbarDropdownItem | NavbarMegaMenuItem;
|
||||||
|
|
||||||
|
export interface NavbarAction extends NavigationLink {
|
||||||
|
variant?: "link" | "outline" | "primary";
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NavbarBrand {
|
||||||
|
label?: string;
|
||||||
|
labelKey?: string;
|
||||||
|
description?: string;
|
||||||
|
descriptionKey?: string;
|
||||||
|
href?: string;
|
||||||
|
ariaLabel?: string;
|
||||||
|
icon?: string;
|
||||||
|
logo?: string;
|
||||||
|
logoAlt?: string;
|
||||||
|
logoWidth?: number | string;
|
||||||
|
logoHeight?: number | string;
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
import { expect, test } from "bun:test";
|
||||||
|
import type { NavbarItem } from "../src/navigation";
|
||||||
|
|
||||||
|
const items = [
|
||||||
|
{ type: "link", label: "Pricing", href: "/pricing" },
|
||||||
|
{
|
||||||
|
type: "dropdown",
|
||||||
|
label: "Company",
|
||||||
|
items: [{ label: "About", href: "/about" }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "mega",
|
||||||
|
label: "Products",
|
||||||
|
mega: {
|
||||||
|
variant: "icon-grid",
|
||||||
|
density: "compact",
|
||||||
|
panelWidth: "2xl",
|
||||||
|
panelAlign: "center",
|
||||||
|
columnCount: 3,
|
||||||
|
fullWidth: true,
|
||||||
|
rail: [{ label: "All products", href: "/products", icon: "icon-products" }],
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
heading: "Work",
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
label: "Projects",
|
||||||
|
href: "/projects",
|
||||||
|
icon: "icon-projects",
|
||||||
|
description: "Plan and deliver work",
|
||||||
|
badge: "New",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
featured: {
|
||||||
|
title: "What's new",
|
||||||
|
image: "/new.png",
|
||||||
|
actionLabel: "Explore",
|
||||||
|
actionHref: "/new",
|
||||||
|
},
|
||||||
|
footer: "One connected platform",
|
||||||
|
actionLabel: "View all products",
|
||||||
|
actionHref: "/products",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
] satisfies NavbarItem[];
|
||||||
|
|
||||||
|
test("navbar item contract covers links, dropdowns, and complete mega menus", () => {
|
||||||
|
expect(items.map((item) => item.type)).toEqual(["link", "dropdown", "mega"]);
|
||||||
|
});
|
||||||
@@ -78,6 +78,28 @@ function openingTags(source: string): string[] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
describe("@wrnexus/ui redesign component pack", () => {
|
describe("@wrnexus/ui redesign component pack", () => {
|
||||||
|
test("Hero full bleed does not use scrollbar-sensitive viewport units", async () => {
|
||||||
|
const source = await readFile(join(componentsDir, "Hero.wrn"), "utf8");
|
||||||
|
expect(source).not.toContain("width: 100vw");
|
||||||
|
expect(source).not.toContain("width: 100dvw");
|
||||||
|
expect(source).toContain('.wrn-hero[data-full-bleed="true"]');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Timeline supports numbered data items without styling every row as interactive", async () => {
|
||||||
|
const source = await readFile(join(componentsDir, "Timeline.wrn"), "utf8");
|
||||||
|
expect(source).toContain("numbered: boolean = false");
|
||||||
|
expect(source).toContain("data-interactive");
|
||||||
|
expect(source).toContain('data-interactive="true"');
|
||||||
|
expect(source).toContain('.wrn-timeline__item[data-interactive="true"] { cursor: pointer; }');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Blockquote provides constrained contained presentation", async () => {
|
||||||
|
const source = await readFile(join(componentsDir, "Blockquote.wrn"), "utf8");
|
||||||
|
expect(source).toContain('maxWidth: string = "xl"');
|
||||||
|
expect(source).toContain('data-variant="spotlight"');
|
||||||
|
expect(source).toContain('data-max-width="full"');
|
||||||
|
});
|
||||||
|
|
||||||
test("contains every replacement and new component", async () => {
|
test("contains every replacement and new component", async () => {
|
||||||
const files = new Set(await readdir(componentsDir));
|
const files = new Set(await readdir(componentsDir));
|
||||||
|
|
||||||
@@ -118,6 +140,77 @@ describe("@wrnexus/ui redesign component pack", () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("Navbar only displays its utility bar when the topbar slot has rendered content", async () => {
|
||||||
|
const source = await readFile(join(componentsDir, "Navbar.wrn"), "utf8");
|
||||||
|
|
||||||
|
expect(source).toContain(".wrn-navbar__topbar:not(:has(> *))");
|
||||||
|
expect(source).toContain(".wrn-navbar__topbar:has(> *)");
|
||||||
|
expect(source).not.toContain(".wrn-navbar__topbar:not(:empty)");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Navbar renders its brand prop independently from the optional brand slot", async () => {
|
||||||
|
const source = await readFile(join(componentsDir, "Navbar.wrn"), "utf8");
|
||||||
|
|
||||||
|
expect(source).toContain('<slot name="brand" />');
|
||||||
|
expect(source).toContain("brand.logo || brand.icon || brand.label || brand.description");
|
||||||
|
expect(source.indexOf("brand.logo || brand.icon || brand.label || brand.description")).toBeLessThan(
|
||||||
|
source.indexOf('<slot name="brand" />'),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Navbar renders slotted utilities before its built-in actions", async () => {
|
||||||
|
const source = await readFile(join(componentsDir, "Navbar.wrn"), "utf8");
|
||||||
|
const actionsStart = source.indexOf('<div class="wrn-navbar__actions">');
|
||||||
|
const slotIndex = source.indexOf('<slot name="actions" />', actionsStart);
|
||||||
|
const actionsLoop = source.indexOf("{#each actions as item}", actionsStart);
|
||||||
|
|
||||||
|
expect(slotIndex).toBeGreaterThan(actionsStart);
|
||||||
|
expect(slotIndex).toBeLessThan(actionsLoop);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Navbar passes structured MegaMenu props as expressions", async () => {
|
||||||
|
const source = await readFile(join(componentsDir, "Navbar.wrn"), "utf8");
|
||||||
|
|
||||||
|
expect(source).toContain("columns={megaColumns(item)}");
|
||||||
|
expect(source).toContain("rail={megaData(item).rail || []}");
|
||||||
|
expect(source).toContain("featured={megaData(item).featured || {}}");
|
||||||
|
expect(source).toContain("fullWidth={megaData(item).fullWidth || false}");
|
||||||
|
expect(source).not.toContain('columns="{megaColumns(item)}"');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Navbar replaces mega panels with direct links in collapsed navigation", async () => {
|
||||||
|
const source = await readFile(join(componentsDir, "Navbar.wrn"), "utf8");
|
||||||
|
|
||||||
|
expect(source).toContain("wrn-navbar__mobile-mega-link");
|
||||||
|
expect(source).toContain("item.href || megaData(item).actionHref");
|
||||||
|
expect(source).toContain('.wrn-navbar__mega { display: none; }');
|
||||||
|
expect(source).toContain('.wrn-navbar__mobile-mega-link { display: flex; }');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Navbar supports in-flow floating and elevated menu panels", async () => {
|
||||||
|
const source = await readFile(join(componentsDir, "Navbar.wrn"), "utf8");
|
||||||
|
const ast = parse(source);
|
||||||
|
const defaults = new Map(ast.props.map((prop) => [prop.name, prop.default]));
|
||||||
|
|
||||||
|
expect(defaults.get("floating")).toBe("false");
|
||||||
|
expect(defaults.get("startFloating")).toBe('"0px"');
|
||||||
|
expect(source).toContain("wrn-navbar--floating");
|
||||||
|
expect(source).toContain("--wrn-navbar-floating-start");
|
||||||
|
expect(source).toContain("z-index: 1100");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("CTASection exposes responsive section spacing", async () => {
|
||||||
|
const source = await readFile(join(componentsDir, "CTASection.wrn"), "utf8");
|
||||||
|
const ast = parse(source);
|
||||||
|
const defaults = new Map(ast.props.map((prop) => [prop.name, prop.default]));
|
||||||
|
|
||||||
|
expect(defaults.get("spacing")).toBe('"none"');
|
||||||
|
expect(source).toContain("data-spacing='{spacing}'");
|
||||||
|
expect(source).toContain('.wrn-cta-section[data-spacing="sm"]');
|
||||||
|
expect(source).toContain('.wrn-cta-section[data-spacing="md"]');
|
||||||
|
expect(source).toContain('.wrn-cta-section[data-spacing="lg"]');
|
||||||
|
});
|
||||||
|
|
||||||
test("existing public defaults remain release compatible", async () => {
|
test("existing public defaults remain release compatible", async () => {
|
||||||
const expectations: Record<string, string[]> = {
|
const expectations: Record<string, string[]> = {
|
||||||
Container: [
|
Container: [
|
||||||
|
|||||||
+194
-10
@@ -32,6 +32,19 @@ test("Textarea binds its value without rendering hydration markup as user conten
|
|||||||
expect(source).not.toContain(">{value}</textarea>");
|
expect(source).not.toContain(">{value}</textarea>");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("form field labels use a stable control-label size instead of inherited heading scale", () => {
|
||||||
|
const fieldComponents = uiComponentNames().filter((name) =>
|
||||||
|
readFileSync(uiComponentPath(name), "utf8").includes(".wrn-next__field-heading label"),
|
||||||
|
);
|
||||||
|
expect(fieldComponents.length).toBeGreaterThan(0);
|
||||||
|
for (const name of fieldComponents) {
|
||||||
|
const source = readFileSync(uiComponentPath(name), "utf8");
|
||||||
|
expect(source).toMatch(
|
||||||
|
/\.wrn-next__field-heading label\s*\{[^}]*font-size: 0\.8125rem;[^}]*line-height: 1\.35;/s,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
test("global UI CSS stays below its migration ratchet", () => {
|
test("global UI CSS stays below its migration ratchet", () => {
|
||||||
const css = uiCss();
|
const css = uiCss();
|
||||||
// Component selectors belong to their owning .wrn files. Keep this asset to
|
// Component selectors belong to their owning .wrn files. Keep this asset to
|
||||||
@@ -239,7 +252,9 @@ test("navbar supports brands, nested menus, actions, utility slots, and public e
|
|||||||
expect(defaults.get("openOnHover")).toBe("false");
|
expect(defaults.get("openOnHover")).toBe("false");
|
||||||
expect(defaults.get("maxWidth")).toBe('"full"');
|
expect(defaults.get("maxWidth")).toBe('"full"');
|
||||||
expect(source).toContain("item.children");
|
expect(source).toContain("item.children");
|
||||||
expect(source).toContain("child.children");
|
expect(source).toContain("dropdownGroupItems(child)");
|
||||||
|
expect(source).toContain('itemType(item) === "mega"');
|
||||||
|
expect(source).toContain("megaData(item).featured");
|
||||||
expect(source).toContain("wrn-navbar__dropdown--{item.type || 'dropdown'}");
|
expect(source).toContain("wrn-navbar__dropdown--{item.type || 'dropdown'}");
|
||||||
const outputs = new Set(contract.outputs.map((output) => output.name));
|
const outputs = new Set(contract.outputs.map((output) => output.name));
|
||||||
for (const event of ["toggle", "open", "close", "select", "action"]) {
|
for (const event of ["toggle", "open", "close", "select", "action"]) {
|
||||||
@@ -304,13 +319,19 @@ test("navbar renders a brand, nested dropdowns, mega groups, and actions", async
|
|||||||
{
|
{
|
||||||
label: "Safety",
|
label: "Safety",
|
||||||
type: "mega",
|
type: "mega",
|
||||||
columns: 2,
|
mega: {
|
||||||
children: [
|
variant: "icon-grid",
|
||||||
{
|
columnCount: 2,
|
||||||
label: "Resources",
|
rail: [{ label: "Overview", href: "/safety" }],
|
||||||
children: [{ label: "Guidance", href: "/guidance" }],
|
columns: [
|
||||||
},
|
{
|
||||||
],
|
heading: "Resources",
|
||||||
|
items: [{ label: "Guidance", href: "/guidance", badge: "New" }],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
featured: { title: "Safety report", actionLabel: "Read report" },
|
||||||
|
actionLabel: "All safety resources",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
actions: [{ label: "Sign in", href: "/login", variant: "primary" }],
|
actions: [{ label: "Sign in", href: "/login", variant: "primary" }],
|
||||||
@@ -320,7 +341,9 @@ test("navbar renders a brand, nested dropdowns, mega groups, and actions", async
|
|||||||
expect(html).toContain("Public portal");
|
expect(html).toContain("Public portal");
|
||||||
expect(html).toContain("Reports");
|
expect(html).toContain("Reports");
|
||||||
expect(html).toContain("Guidance");
|
expect(html).toContain("Guidance");
|
||||||
expect(html).toContain("wrn-navbar__dropdown--mega");
|
expect(html).toContain("wrn-navbar__mega");
|
||||||
|
expect(html).toContain("Safety report");
|
||||||
|
expect(html).toContain("All safety resources");
|
||||||
expect(html).toContain("data-wrn-navbar");
|
expect(html).toContain("data-wrn-navbar");
|
||||||
expect(html).toContain('name="wrn-navbar-menu"');
|
expect(html).toContain('name="wrn-navbar-menu"');
|
||||||
expect(html).toContain("Sign in");
|
expect(html).toContain("Sign in");
|
||||||
@@ -2856,8 +2879,13 @@ test("tabs use wrn classes and declare real outputs instead of raw events", asyn
|
|||||||
expect(tabs).toHaveLength(2);
|
expect(tabs).toHaveLength(2);
|
||||||
expect(tabs[0]!.getAttribute("aria-selected")).toBe("true");
|
expect(tabs[0]!.getAttribute("aria-selected")).toBe("true");
|
||||||
expect(tabs[1]!.getAttribute("aria-selected")).toBe("false");
|
expect(tabs[1]!.getAttribute("aria-selected")).toBe("false");
|
||||||
|
expect(tabs[0]!.id).toBe("wrn-tab-overview");
|
||||||
|
expect(tabs[0]!.getAttribute("aria-controls")).toBe("wrn-panel-overview");
|
||||||
expect(dom.querySelector(".wrn-tabs")).not.toBeNull();
|
expect(dom.querySelector(".wrn-tabs")).not.toBeNull();
|
||||||
expect(dom.querySelectorAll('[role="tabpanel"]')).toHaveLength(2);
|
const panels = dom.querySelectorAll('[role="tabpanel"]');
|
||||||
|
expect(panels).toHaveLength(2);
|
||||||
|
expect(panels[0]!.id).toBe("wrn-panel-overview");
|
||||||
|
expect(panels[0]!.getAttribute("aria-labelledby")).toBe("wrn-tab-overview");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("tabs in url mode declare the query parameter they sync to", async () => {
|
test("tabs in url mode declare the query parameter they sync to", async () => {
|
||||||
@@ -2918,6 +2946,10 @@ test("mega menu renders column groups in an anchored panel", async () => {
|
|||||||
const trigger = dom.querySelector(".wrn-mega__trigger") as HTMLElement;
|
const trigger = dom.querySelector(".wrn-mega__trigger") as HTMLElement;
|
||||||
expect(trigger.getAttribute("aria-expanded")).toBe("false");
|
expect(trigger.getAttribute("aria-expanded")).toBe("false");
|
||||||
expect(trigger.getAttribute("aria-haspopup")).toBe("true");
|
expect(trigger.getAttribute("aria-haspopup")).toBe("true");
|
||||||
|
expect(trigger.getAttribute("aria-label")).toBe("Products");
|
||||||
|
expect(dom.querySelector(".wrn-mega__trigger-label")?.getAttribute("data-label")).toBe(
|
||||||
|
"Products",
|
||||||
|
);
|
||||||
|
|
||||||
const panel = dom.querySelector(".wrn-mega__panel") as HTMLElement;
|
const panel = dom.querySelector(".wrn-mega__panel") as HTMLElement;
|
||||||
expect(panel.getAttribute("data-wrn-anchored")).toBe("true");
|
expect(panel.getAttribute("data-wrn-anchored")).toBe("true");
|
||||||
@@ -2927,6 +2959,14 @@ test("mega menu renders column groups in an anchored panel", async () => {
|
|||||||
// Single level by design: a mega panel shows breadth flat, so there is no
|
// Single level by design: a mega panel shows breadth flat, so there is no
|
||||||
// nested submenu markup to find.
|
// nested submenu markup to find.
|
||||||
expect(source).not.toContain("wrn-mega__submenu");
|
expect(source).not.toContain("wrn-mega__submenu");
|
||||||
|
expect(source).toContain('.wrn-mega[data-variant="default"] .wrn-mega__panel');
|
||||||
|
expect(source).toContain("box-sizing: border-box");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("announcement full-width surface does not create viewport scrollbar overflow", () => {
|
||||||
|
const source = readFileSync(uiComponentPath("AnnouncementBar"), "utf8");
|
||||||
|
expect(source).not.toContain("width: 100vw");
|
||||||
|
expect(source).not.toContain("calc(50% - 50vw)");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("mega menu columns take roving focus and survive an empty column list", async () => {
|
test("mega menu columns take roving focus and survive an empty column list", async () => {
|
||||||
@@ -2938,6 +2978,76 @@ test("mega menu columns take roving focus and survive an empty column list", asy
|
|||||||
expect(dom.querySelector('[data-wrn-roving="both"]')).not.toBeNull();
|
expect(dom.querySelector('[data-wrn-roving="both"]')).not.toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("catalog mega menu renders only the active rail category", async () => {
|
||||||
|
const source = readFileSync(uiComponentPath("MegaMenu"), "utf8");
|
||||||
|
expect(source).toContain(".wrn-mega__list > li");
|
||||||
|
expect(source).toContain("overflow-wrap: anywhere;");
|
||||||
|
const html = await renderComponent(source, {
|
||||||
|
label: "Products",
|
||||||
|
variant: "catalog",
|
||||||
|
activeCategory: "sales",
|
||||||
|
rail: [
|
||||||
|
{ label: "Platform", value: "platform" },
|
||||||
|
{ label: "Sales", value: "sales" },
|
||||||
|
],
|
||||||
|
columns: [
|
||||||
|
{ heading: "Platform", items: [{ label: "Home", href: "/home" }] },
|
||||||
|
{ heading: "Sales", items: [{ label: "CRM", href: "/crm" }] },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
const dom = mountHtml(html);
|
||||||
|
|
||||||
|
expect(dom.querySelectorAll(".wrn-mega__rail-link")).toHaveLength(2);
|
||||||
|
expect(dom.querySelectorAll(".wrn-mega__column")).toHaveLength(1);
|
||||||
|
expect(dom.querySelector(".wrn-mega__heading")?.textContent).toContain("Sales");
|
||||||
|
expect(dom.querySelector('[aria-pressed="true"]')?.textContent).toContain("Sales");
|
||||||
|
expect(source).toContain("overflow-y: auto");
|
||||||
|
expect(source).not.toContain("@mouseenter='chooseCategory(item, index)'");
|
||||||
|
expect(dom.querySelector(".wrn-mega__column-header")?.textContent).toContain("Sales");
|
||||||
|
expect(dom.querySelectorAll(".wrn-mega__link-icon")).toHaveLength(1);
|
||||||
|
expect(dom.querySelector(".wrn-mega__link-icon--fallback svg")).not.toBeNull();
|
||||||
|
expect(dom.querySelectorAll(".wrn-mega__link-description")).toHaveLength(0);
|
||||||
|
expect(source).toContain("border-bottom: 1px solid var(--wrn-color-border)");
|
||||||
|
expect(source).toContain(".wrn-mega__rail-icon > span");
|
||||||
|
expect(source).toContain("color: currentColor !important");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("mega menu supports rails, icons, badges, media, featured content and footer actions", async () => {
|
||||||
|
const source = readFileSync(uiComponentPath("MegaMenu"), "utf8");
|
||||||
|
const html = await renderComponent(source, {
|
||||||
|
label: "Explore",
|
||||||
|
variant: "icon-grid",
|
||||||
|
panelWidth: "2xl",
|
||||||
|
columnCount: 3,
|
||||||
|
rail: [{ label: "Enterprise", description: "For larger teams", icon: "icon-enterprise" }],
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
heading: "Products",
|
||||||
|
description: "Choose a workspace",
|
||||||
|
image: "/products.png",
|
||||||
|
items: [{ label: "CRM", description: "Customer records", icon: "icon-crm", badge: "New" }],
|
||||||
|
actionLabel: "All products",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
featured: {
|
||||||
|
eyebrow: "What's new",
|
||||||
|
title: "Release notes",
|
||||||
|
image: "/release.png",
|
||||||
|
actionLabel: "See more",
|
||||||
|
},
|
||||||
|
footer: "One connected platform",
|
||||||
|
actionLabel: "View everything",
|
||||||
|
});
|
||||||
|
const dom = mountHtml(html);
|
||||||
|
|
||||||
|
expect(dom.querySelector(".wrn-mega")?.getAttribute("data-variant")).toBe("icon-grid");
|
||||||
|
expect(dom.querySelector(".wrn-mega__rail-link")?.textContent).toContain("Enterprise");
|
||||||
|
expect(dom.querySelector(".wrn-mega__badge")?.textContent).toContain("New");
|
||||||
|
expect(dom.querySelector(".wrn-mega__column-image")).not.toBeNull();
|
||||||
|
expect(dom.querySelector(".wrn-mega__featured")?.textContent).toContain("Release notes");
|
||||||
|
expect(dom.querySelector(".wrn-mega__footer")?.textContent).toContain("View everything");
|
||||||
|
});
|
||||||
|
|
||||||
test("sidebar renders single items, labelled groups and nested levels", async () => {
|
test("sidebar renders single items, labelled groups and nested levels", async () => {
|
||||||
const source = readFileSync(uiComponentPath("Sidebar"), "utf8");
|
const source = readFileSync(uiComponentPath("Sidebar"), "utf8");
|
||||||
const html = await renderComponent(source, {
|
const html = await renderComponent(source, {
|
||||||
@@ -3027,6 +3137,8 @@ test("navbar uses a valid aria-current and takes roving focus on its menu", asyn
|
|||||||
*/
|
*/
|
||||||
expect(source).not.toContain("? 'page' : ''");
|
expect(source).not.toContain("? 'page' : ''");
|
||||||
expect(source).toContain("data-wrn-roving");
|
expect(source).toContain("data-wrn-roving");
|
||||||
|
expect(source).toContain("pointer-events: none;");
|
||||||
|
expect(source).toContain(".wrn-navbar__menus > *");
|
||||||
|
|
||||||
const html = await renderComponent(source, {
|
const html = await renderComponent(source, {
|
||||||
label: "Main",
|
label: "Main",
|
||||||
@@ -3066,6 +3178,38 @@ test("breadcrumb marks the trail end without emitting an empty aria-current", as
|
|||||||
expect(dom.querySelectorAll(".wrn-breadcrumb__item").length).toBeGreaterThanOrEqual(3);
|
expect(dom.querySelectorAll(".wrn-breadcrumb__item").length).toBeGreaterThanOrEqual(3);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("breadcrumb renders a standalone active page with its icon", async () => {
|
||||||
|
const source = readFileSync(uiComponentPath("Breadcrumb"), "utf8");
|
||||||
|
const html = await renderComponent(source, {
|
||||||
|
showHome: true,
|
||||||
|
items: [{ label: "Products", href: "/products", icon: "icon-[lucide--blocks]" }],
|
||||||
|
active: "CRM",
|
||||||
|
activeIcon: "icon-[lucide--contact-round]",
|
||||||
|
});
|
||||||
|
expect(html).toContain("CRM");
|
||||||
|
expect(html).toContain("icon-[lucide--contact-round]");
|
||||||
|
expect(html).toMatch(/aria-current="page"/);
|
||||||
|
const dom = mountHtml(html);
|
||||||
|
expect(dom.querySelectorAll(".wrn-breadcrumb__item").length).toBe(3);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("breadcrumb default separators remain visible without generated icon CSS", async () => {
|
||||||
|
const source = readFileSync(uiComponentPath("Breadcrumb"), "utf8");
|
||||||
|
const html = await renderComponent(source, {
|
||||||
|
showHome: true,
|
||||||
|
items: [{ label: "Legal" }, { label: "Terms", current: true }],
|
||||||
|
});
|
||||||
|
expect(html).toContain("›");
|
||||||
|
expect(html).not.toContain("icon-[lucide--chevron-right]");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("stats bar desktop gutters align its surface with container content", () => {
|
||||||
|
const source = readFileSync(uiComponentPath("StatsBar"), "utf8");
|
||||||
|
expect(source).toContain("--stats-max-width: 80rem");
|
||||||
|
expect(source).toContain("--stats-gutter-width: 4rem");
|
||||||
|
expect(source).toContain("calc(var(--stats-max-width) - var(--stats-gutter-width))");
|
||||||
|
});
|
||||||
|
|
||||||
test("mega menu bridges the gap between its trigger and panel", async () => {
|
test("mega menu bridges the gap between its trigger and panel", async () => {
|
||||||
const source = readFileSync(uiComponentPath("MegaMenu"), "utf8");
|
const source = readFileSync(uiComponentPath("MegaMenu"), "utf8");
|
||||||
/*
|
/*
|
||||||
@@ -3078,6 +3222,39 @@ test("mega menu bridges the gap between its trigger and panel", async () => {
|
|||||||
expect(source).toMatch(/\.wrn-mega__panel::before \{[^}]*bottom: 100%/s);
|
expect(source).toMatch(/\.wrn-mega__panel::before \{[^}]*bottom: 100%/s);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("mega menu keeps hover activation and click activation from cancelling each other", () => {
|
||||||
|
const source = readFileSync(uiComponentPath("MegaMenu"), "utf8");
|
||||||
|
expect(source).toContain("openOnHover: boolean = true");
|
||||||
|
expect(source).toContain("@click='activatePanel(event)'");
|
||||||
|
expect(source).toContain("@mouseenter='hoverPanel(event)'");
|
||||||
|
expect(source).toContain("showPanel(sourceEvent)");
|
||||||
|
expect(source).not.toContain("function scheduleOpen");
|
||||||
|
expect(source).toContain('.wrn-mega__panel[data-show="false"] { display: none; }');
|
||||||
|
expect(source).toContain('style=\'{visible ? "" : "display:none"}\'');
|
||||||
|
expect(source).not.toContain("@focus='showPanel(event)'");
|
||||||
|
expect(source).toContain("max-height: calc(100dvh - 5.5rem)");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("mega menu gives the pointer time to cross from its trigger into a floating panel", () => {
|
||||||
|
const source = readFileSync(uiComponentPath("MegaMenu"), "utf8");
|
||||||
|
expect(source).toContain("state closeTimer = null");
|
||||||
|
expect(source).toContain("@mouseleave='scheduleHide()'");
|
||||||
|
expect(source).toContain("@mouseenter='cancelScheduledHide()'");
|
||||||
|
expect(source).toContain("}, 220)");
|
||||||
|
expect(source).not.toContain("@mouseleave='hidePanel(\"pointer-leave\")'");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("navbar pins full-width mega panels to desktop viewport gutters", () => {
|
||||||
|
const source = readFileSync(uiComponentPath("Navbar"), "utf8");
|
||||||
|
expect(source).toMatch(
|
||||||
|
/\.wrn-navbar__mega\[data-full-width="true"\] \.wrn-mega__panel \{[^}]*position: fixed/s,
|
||||||
|
);
|
||||||
|
expect(source).toMatch(/right: 1rem;\s+left: 1rem;/s);
|
||||||
|
expect(source).toMatch(
|
||||||
|
/data-collapse-at="1100px"[^}]+\.wrn-navbar__mega\[data-full-width="true"\][^}]+position: static/s,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
test("stepper shows only the active step content and offers back, next and skip", async () => {
|
test("stepper shows only the active step content and offers back, next and skip", async () => {
|
||||||
const source = readFileSync(uiComponentPath("Stepper"), "utf8");
|
const source = readFileSync(uiComponentPath("Stepper"), "utf8");
|
||||||
const html = await renderComponent(source, {
|
const html = await renderComponent(source, {
|
||||||
@@ -3213,6 +3390,13 @@ test("custom scrollbar styles the scrollbar and drops its fake output", async ()
|
|||||||
expect(style).toContain("18rem");
|
expect(style).toContain("18rem");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("page header collapses compiled empty slot markers", () => {
|
||||||
|
const source = readFileSync(uiComponentPath("PageHeader"), "utf8");
|
||||||
|
expect(source).toContain(".wrn-page-header__meta:not(:has(> :not(template)))");
|
||||||
|
expect(source).toContain(".wrn-page-header__body:not(:has(> :not(template)))");
|
||||||
|
expect(source).toContain(".wrn-page-header__actions--slot-only:not(:has(> :not(template)))");
|
||||||
|
});
|
||||||
|
|
||||||
test("layout components ship their own styles instead of Tailwind utilities", () => {
|
test("layout components ship their own styles instead of Tailwind utilities", () => {
|
||||||
/*
|
/*
|
||||||
* These were built from utility classes and class: conditionals. That works
|
* These were built from utility classes and class: conditionals. That works
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/uploader",
|
"name": "@wrnexus/uploader",
|
||||||
"version": "0.8.10",
|
"version": "0.8.13",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./src/index.ts",
|
"main": "./src/index.ts",
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
import { describe, expect, test } from "bun:test";
|
||||||
|
import {
|
||||||
|
UploadPolicyError,
|
||||||
|
createSignedFileToken,
|
||||||
|
enforceUploadPolicy,
|
||||||
|
inspectUpload,
|
||||||
|
sniffContentType,
|
||||||
|
verifySignedFileToken,
|
||||||
|
} from "../src/security.ts";
|
||||||
|
|
||||||
|
describe("upload policy hardening", () => {
|
||||||
|
test("enforces size, type, filename, and checksum independently", async () => {
|
||||||
|
const inspection = await inspectUpload("report.pdf", new Uint8Array([0x25, 0x50, 0x44, 0x46]));
|
||||||
|
const cases: Array<[Parameters<typeof enforceUploadPolicy>[1], string | undefined, string]> = [
|
||||||
|
[{ maxBytes: 3 }, undefined, "UPLOAD_TOO_LARGE"],
|
||||||
|
[{ accept: ["image/png"] }, undefined, "UPLOAD_TYPE_REJECTED"],
|
||||||
|
[{ filenamePattern: /^invoice-/ }, undefined, "UPLOAD_FILENAME_REJECTED"],
|
||||||
|
[{ requireChecksum: true }, undefined, "UPLOAD_CHECKSUM_REQUIRED"],
|
||||||
|
[{}, "0".repeat(64), "UPLOAD_CHECKSUM_MISMATCH"],
|
||||||
|
];
|
||||||
|
for (const [policy, checksum, code] of cases) {
|
||||||
|
try {
|
||||||
|
enforceUploadPolicy(inspection, policy, checksum);
|
||||||
|
throw new Error("policy unexpectedly accepted upload");
|
||||||
|
} catch (error) {
|
||||||
|
expect(error).toBeInstanceOf(UploadPolicyError);
|
||||||
|
expect((error as UploadPolicyError).code).toBe(code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
enforceUploadPolicy(
|
||||||
|
inspection,
|
||||||
|
{ maxBytes: 4, accept: ["application/pdf"] },
|
||||||
|
inspection.sha256,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("recognizes bounded signatures and rejects malformed signed-token inputs", async () => {
|
||||||
|
expect(sniffContentType(new Uint8Array([0xff, 0xd8, 0xff]))).toBe("image/jpeg");
|
||||||
|
expect(sniffContentType(new Uint8Array([0x50, 0x4b, 0x03, 0x04]))).toBe("application/zip");
|
||||||
|
expect(sniffContentType(new Uint8Array([1, 2, 3]))).toBeNull();
|
||||||
|
await expect(
|
||||||
|
createSignedFileToken({ store: "", key: "x", expiresAt: 1 }, "long-enough-secret"),
|
||||||
|
).rejects.toThrow("store");
|
||||||
|
expect(await verifySignedFileToken("not-a-token", "long-enough-secret")).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("signed file tokens reject expiry, tampering, and the wrong signing key", async () => {
|
||||||
|
const value = { store: "uploads", key: "safe/report.pdf", expiresAt: 2_000 };
|
||||||
|
const token = await createSignedFileToken(value, "long-enough-secret");
|
||||||
|
expect(await verifySignedFileToken(token, "long-enough-secret", 1_999)).toEqual(value);
|
||||||
|
expect(await verifySignedFileToken(token, "long-enough-secret", 2_000)).toBeNull();
|
||||||
|
expect(await verifySignedFileToken(`${token}x`, "long-enough-secret", 1_999)).toBeNull();
|
||||||
|
expect(await verifySignedFileToken(token, "different-long-secret", 1_999)).toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -19,7 +19,15 @@ function sha256(value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function loadTypeScript() {
|
function loadTypeScript() {
|
||||||
const candidates = [process.env.TYPESCRIPT_PATH, "typescript"].filter(Boolean);
|
// TypeScript 7's root package is the native CLI and no longer exposes the
|
||||||
|
// legacy compiler API used by the embedded editor compiler. Keep that API
|
||||||
|
// isolated behind @wrnexus/typecheck's explicit TypeScript 6 dependency
|
||||||
|
// while the workspace itself type-checks with TypeScript 7.
|
||||||
|
const candidates = [
|
||||||
|
process.env.TYPESCRIPT_PATH,
|
||||||
|
join(root, "packages", "typecheck", "node_modules", "typescript"),
|
||||||
|
"typescript",
|
||||||
|
].filter(Boolean);
|
||||||
for (const candidate of candidates) {
|
for (const candidate of candidates) {
|
||||||
try {
|
try {
|
||||||
return require(candidate);
|
return require(candidate);
|
||||||
|
|||||||
@@ -2,10 +2,15 @@ import { existsSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
|
|||||||
import console from "node:console";
|
import console from "node:console";
|
||||||
import { dirname, join, relative, resolve } from "node:path";
|
import { dirname, join, relative, resolve } from "node:path";
|
||||||
import { fileURLToPath } from "node:url";
|
import { fileURLToPath } from "node:url";
|
||||||
|
import { createRequire } from "node:module";
|
||||||
import process from "node:process";
|
import process from "node:process";
|
||||||
import ts from "typescript";
|
|
||||||
|
|
||||||
const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
||||||
|
const require = createRequire(import.meta.url);
|
||||||
|
// TypeScript 7's root package is the native CLI and no longer exposes the
|
||||||
|
// legacy compiler API. Public API extraction intentionally uses the compiler
|
||||||
|
// version embedded by @wrnexus/typecheck.
|
||||||
|
const ts = require(join(root, "packages", "typecheck", "node_modules", "typescript"));
|
||||||
const baselinePath = join(root, "docs", "public-api-0.8.json");
|
const baselinePath = join(root, "docs", "public-api-0.8.json");
|
||||||
|
|
||||||
function flattenTargets(value) {
|
function flattenTargets(value) {
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user