diff --git a/conformance-storybook/.gitignore b/conformance-storybook/.gitignore new file mode 100644 index 000000000..ad5eab083 --- /dev/null +++ b/conformance-storybook/.gitignore @@ -0,0 +1,2 @@ +storybook-static/ +node_modules/ diff --git a/conformance-storybook/.storybook/main.ts b/conformance-storybook/.storybook/main.ts new file mode 100644 index 000000000..fa52bac51 --- /dev/null +++ b/conformance-storybook/.storybook/main.ts @@ -0,0 +1,12 @@ +import type { StorybookConfig } from "@storybook/web-components-vite"; + +const config: StorybookConfig = { + stories: ["../stories/**/*.stories.ts", "../stories/generated/**/*.stories.ts"], + framework: "@storybook/web-components-vite", + addons: ["@storybook/addon-essentials"], + viteFinal: async (config) => { + return config; + }, +}; + +export default config; diff --git a/conformance-storybook/.storybook/preview.ts b/conformance-storybook/.storybook/preview.ts new file mode 100644 index 000000000..0e1adde69 --- /dev/null +++ b/conformance-storybook/.storybook/preview.ts @@ -0,0 +1,14 @@ +import type { Preview } from "@storybook/web-components"; + +const preview: Preview = { + parameters: { + controls: { + matchers: { + color: /(background|color)$/i, + date: /Date$/i, + }, + }, + }, +}; + +export default preview; diff --git a/conformance-storybook/package-lock.json b/conformance-storybook/package-lock.json new file mode 100644 index 000000000..083347222 --- /dev/null +++ b/conformance-storybook/package-lock.json @@ -0,0 +1,2658 @@ +{ + "name": "a2ui-conformance-storybook", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "a2ui-conformance-storybook", + "version": "0.1.0", + "dependencies": { + "@a2ui/lit": "file:../renderers/lit", + "@a2ui/web_core": "file:../renderers/web_core", + "@lit-labs/signals": "^0.1.3", + "@lit/context": "^1.1.4", + "lit": "^3.3.1" + }, + "devDependencies": { + "@storybook/addon-essentials": "^8.6.14", + "@storybook/blocks": "^8.6.14", + "@storybook/web-components": "^8.6.14", + "@storybook/web-components-vite": "^8.6.14", + "storybook": "^8.6.14", + "typescript": "^5.8.3" + } + }, + "../renderers/lit": { + "name": "@a2ui/lit", + "version": "0.8.1", + "license": "Apache-2.0", + "dependencies": { + "@a2ui/web_core": "file:../web_core", + "@lit-labs/signals": "^0.1.3", + "@lit/context": "^1.1.4", + "lit": "^3.3.1", + "markdown-it": "^14.1.0", + "signal-utils": "^0.21.1" + }, + "devDependencies": { + "@types/markdown-it": "^14.1.2", + "@types/node": "^24.10.1", + "google-artifactregistry-auth": "^3.5.0", + "typescript": "^5.8.3", + "wireit": "^0.15.0-pre.2" + } + }, + "../renderers/web_core": { + "name": "@a2ui/web_core", + "version": "0.8.2", + "license": "Apache-2.0", + "devDependencies": { + "@types/node": "^24.10.1", + "typescript": "^5.8.3", + "wireit": "^0.15.0-pre.2" + } + }, + "node_modules/@a2ui/lit": { + "resolved": "../renderers/lit", + "link": true + }, + "node_modules/@a2ui/web_core": { + "resolved": "../renderers/web_core", + "link": true + }, + "node_modules/@babel/runtime": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz", + "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@lit-labs/signals": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@lit-labs/signals/-/signals-0.1.3.tgz", + "integrity": "sha512-P0yWgH5blwVyEwBg+WFspLzeu1i0ypJP1QB0l1Omr9qZLIPsUu0p4Fy2jshOg7oQyha5n163K3GJGeUhQQ682Q==", + "license": "BSD-3-Clause", + "dependencies": { + "lit": "^2.0.0 || ^3.0.0", + "signal-polyfill": "^0.2.0" + } + }, + "node_modules/@lit-labs/ssr-dom-shim": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.5.1.tgz", + "integrity": "sha512-Aou5UdlSpr5whQe8AA/bZG0jMj96CoJIWbGfZ91qieWu5AWUMKw8VR/pAkQkJYvBNhmCcWnZlyyk5oze8JIqYA==", + "license": "BSD-3-Clause" + }, + "node_modules/@lit/context": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@lit/context/-/context-1.1.6.tgz", + "integrity": "sha512-M26qDE6UkQbZA2mQ3RjJ3Gzd8TxP+/0obMgE5HfkfLhEEyYE3Bui4A5XHiGPjy0MUGAyxB3QgVuw2ciS0kHn6A==", + "license": "BSD-3-Clause", + "dependencies": { + "@lit/reactive-element": "^1.6.2 || ^2.1.0" + } + }, + "node_modules/@lit/reactive-element": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.1.2.tgz", + "integrity": "sha512-pbCDiVMnne1lYUIaYNN5wrwQXDtHaYtg7YEFPeW+hws6U47WeFvISGUWekPGKWOP1ygrs0ef0o1VJMk1exos5A==", + "license": "BSD-3-Clause", + "dependencies": { + "@lit-labs/ssr-dom-shim": "^1.5.0" + } + }, + "node_modules/@mdx-js/react": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.1.1.tgz", + "integrity": "sha512-f++rKLQgUVYDAtECQ6fn/is15GkEH9+nZPM3MS0RcxVqoTfawHvDlSCH7JbMhAM6uJ32v3eXLvLmLvjGu7PTQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdx": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "@types/react": ">=16", + "react": ">=16" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz", + "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "peer": true + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz", + "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "peer": true + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz", + "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "peer": true + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz", + "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "peer": true + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz", + "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "peer": true + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz", + "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz", + "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz", + "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz", + "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz", + "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz", + "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz", + "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz", + "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz", + "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz", + "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz", + "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz", + "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz", + "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz", + "integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz", + "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "peer": true + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz", + "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "peer": true + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz", + "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "peer": true + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz", + "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "peer": true + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz", + "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "peer": true + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz", + "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "peer": true + }, + "node_modules/@storybook/addon-actions": { + "version": "8.6.14", + "resolved": "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-8.6.14.tgz", + "integrity": "sha512-mDQxylxGGCQSK7tJPkD144J8jWh9IU9ziJMHfB84PKpI/V5ZgqMDnpr2bssTrUaGDqU5e1/z8KcRF+Melhs9pQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@storybook/global": "^5.0.0", + "@types/uuid": "^9.0.1", + "dequal": "^2.0.2", + "polished": "^4.2.2", + "uuid": "^9.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.6.14" + } + }, + "node_modules/@storybook/addon-backgrounds": { + "version": "8.6.14", + "resolved": "https://registry.npmjs.org/@storybook/addon-backgrounds/-/addon-backgrounds-8.6.14.tgz", + "integrity": "sha512-l9xS8qWe5n4tvMwth09QxH2PmJbCctEvBAc1tjjRasAfrd69f7/uFK4WhwJAstzBTNgTc8VXI4w8ZR97i1sFbg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@storybook/global": "^5.0.0", + "memoizerific": "^1.11.3", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.6.14" + } + }, + "node_modules/@storybook/addon-controls": { + "version": "8.6.14", + "resolved": "https://registry.npmjs.org/@storybook/addon-controls/-/addon-controls-8.6.14.tgz", + "integrity": "sha512-IiQpkNJdiRyA4Mq9mzjZlvQugL/aE7hNgVxBBGPiIZG6wb6Ht9hNnBYpap5ZXXFKV9p2qVI0FZK445ONmAa+Cw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@storybook/global": "^5.0.0", + "dequal": "^2.0.2", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.6.14" + } + }, + "node_modules/@storybook/addon-docs": { + "version": "8.6.14", + "resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-8.6.14.tgz", + "integrity": "sha512-Obpd0OhAF99JyU5pp5ci17YmpcQtMNgqW2pTXV8jAiiipWpwO++hNDeQmLmlSXB399XjtRDOcDVkoc7rc6JzdQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@mdx-js/react": "^3.0.0", + "@storybook/blocks": "8.6.14", + "@storybook/csf-plugin": "8.6.14", + "@storybook/react-dom-shim": "8.6.14", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.6.14" + } + }, + "node_modules/@storybook/addon-essentials": { + "version": "8.6.14", + "resolved": "https://registry.npmjs.org/@storybook/addon-essentials/-/addon-essentials-8.6.14.tgz", + "integrity": "sha512-5ZZSHNaW9mXMOFkoPyc3QkoNGdJHETZydI62/OASR0lmPlJ1065TNigEo5dJddmZNn0/3bkE8eKMAzLnO5eIdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@storybook/addon-actions": "8.6.14", + "@storybook/addon-backgrounds": "8.6.14", + "@storybook/addon-controls": "8.6.14", + "@storybook/addon-docs": "8.6.14", + "@storybook/addon-highlight": "8.6.14", + "@storybook/addon-measure": "8.6.14", + "@storybook/addon-outline": "8.6.14", + "@storybook/addon-toolbars": "8.6.14", + "@storybook/addon-viewport": "8.6.14", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.6.14" + } + }, + "node_modules/@storybook/addon-highlight": { + "version": "8.6.14", + "resolved": "https://registry.npmjs.org/@storybook/addon-highlight/-/addon-highlight-8.6.14.tgz", + "integrity": "sha512-4H19OJlapkofiE9tM6K/vsepf4ir9jMm9T+zw5L85blJZxhKZIbJ6FO0TCG9PDc4iPt3L6+aq5B0X29s9zicNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@storybook/global": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.6.14" + } + }, + "node_modules/@storybook/addon-measure": { + "version": "8.6.14", + "resolved": "https://registry.npmjs.org/@storybook/addon-measure/-/addon-measure-8.6.14.tgz", + "integrity": "sha512-1Tlyb72NX8aAqm6I6OICsUuGOP6hgnXcuFlXucyhKomPa6j3Eu2vKu561t/f0oGtAK2nO93Z70kVaEh5X+vaGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@storybook/global": "^5.0.0", + "tiny-invariant": "^1.3.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.6.14" + } + }, + "node_modules/@storybook/addon-outline": { + "version": "8.6.14", + "resolved": "https://registry.npmjs.org/@storybook/addon-outline/-/addon-outline-8.6.14.tgz", + "integrity": "sha512-CW857JvN6OxGWElqjlzJO2S69DHf+xO3WsEfT5mT3ZtIjmsvRDukdWfDU9bIYUFyA2lFvYjncBGjbK+I91XR7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@storybook/global": "^5.0.0", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.6.14" + } + }, + "node_modules/@storybook/addon-toolbars": { + "version": "8.6.14", + "resolved": "https://registry.npmjs.org/@storybook/addon-toolbars/-/addon-toolbars-8.6.14.tgz", + "integrity": "sha512-W/wEXT8h3VyZTVfWK/84BAcjAxTdtRiAkT2KAN0nbSHxxB5KEM1MjKpKu2upyzzMa3EywITqbfy4dP6lpkVTwQ==", + "dev": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.6.14" + } + }, + "node_modules/@storybook/addon-viewport": { + "version": "8.6.14", + "resolved": "https://registry.npmjs.org/@storybook/addon-viewport/-/addon-viewport-8.6.14.tgz", + "integrity": "sha512-gNzVQbMqRC+/4uQTPI2ZrWuRHGquTMZpdgB9DrD88VTEjNudP+J6r8myLfr2VvGksBbUMHkGHMXHuIhrBEnXYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "memoizerific": "^1.11.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.6.14" + } + }, + "node_modules/@storybook/blocks": { + "version": "8.6.14", + "resolved": "https://registry.npmjs.org/@storybook/blocks/-/blocks-8.6.14.tgz", + "integrity": "sha512-rBMHAfA39AGHgkrDze4RmsnQTMw1ND5fGWobr9pDcJdnDKWQWNRD7Nrlxj0gFlN3n4D9lEZhWGdFrCbku7FVAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@storybook/icons": "^1.2.12", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "storybook": "^8.6.14" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/@storybook/builder-vite": { + "version": "8.6.17", + "resolved": "https://registry.npmjs.org/@storybook/builder-vite/-/builder-vite-8.6.17.tgz", + "integrity": "sha512-ZqFaLUKlRNaU4ovEa5R6D5YTbft1CUcNHLhzpmL9JWInEh4PrUkxiLD/jjB6fiYLcRpSpcs2DF+O/Jh2GDWemA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@storybook/csf-plugin": "8.6.17", + "browser-assert": "^1.2.1", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.6.17", + "vite": "^4.0.0 || ^5.0.0 || ^6.0.0" + } + }, + "node_modules/@storybook/builder-vite/node_modules/@storybook/csf-plugin": { + "version": "8.6.17", + "resolved": "https://registry.npmjs.org/@storybook/csf-plugin/-/csf-plugin-8.6.17.tgz", + "integrity": "sha512-ouvF/izbKclZxpfnRUkyC5ZVDU7QA0cHhjQnXTDT4F8b0uciQUDw1LosDZy5MXf03BeIDdyBAtzd/ym3wzd+kw==", + "dev": true, + "license": "MIT", + "dependencies": { + "unplugin": "^1.3.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.6.17" + } + }, + "node_modules/@storybook/components": { + "version": "8.6.17", + "resolved": "https://registry.npmjs.org/@storybook/components/-/components-8.6.17.tgz", + "integrity": "sha512-0b8xkkuPCNbM8LTOzyfxuo2KdJCHIfu3+QxWBFllXap0eYNHwVeSxE5KERQ/bk2GDCiRzaUbwH9PeLorxOzJJQ==", + "dev": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0" + } + }, + "node_modules/@storybook/core": { + "version": "8.6.17", + "resolved": "https://registry.npmjs.org/@storybook/core/-/core-8.6.17.tgz", + "integrity": "sha512-lndZDYIvUddWk54HmgYwE4h2B0JtWt8ztIRAzHRt6ReZZ9QQbmM5b85Qpa+ng4dyQEKc2JAtYD3Du7RRFcpHlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@storybook/theming": "8.6.17", + "better-opn": "^3.0.2", + "browser-assert": "^1.2.1", + "esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 || ^0.25.0", + "esbuild-register": "^3.5.0", + "jsdoc-type-pratt-parser": "^4.0.0", + "process": "^0.11.10", + "recast": "^0.23.5", + "semver": "^7.6.2", + "util": "^0.12.5", + "ws": "^8.2.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "prettier": "^2 || ^3" + }, + "peerDependenciesMeta": { + "prettier": { + "optional": true + } + } + }, + "node_modules/@storybook/csf-plugin": { + "version": "8.6.14", + "resolved": "https://registry.npmjs.org/@storybook/csf-plugin/-/csf-plugin-8.6.14.tgz", + "integrity": "sha512-dErtc9teAuN+eelN8FojzFE635xlq9cNGGGEu0WEmMUQ4iJ8pingvBO1N8X3scz4Ry7KnxX++NNf3J3gpxS8qQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "unplugin": "^1.3.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.6.14" + } + }, + "node_modules/@storybook/global": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@storybook/global/-/global-5.0.0.tgz", + "integrity": "sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@storybook/icons": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@storybook/icons/-/icons-1.6.0.tgz", + "integrity": "sha512-hcFZIjW8yQz8O8//2WTIXylm5Xsgc+lW9ISLgUk1xGmptIJQRdlhVIXCpSyLrQaaRiyhQRaVg7l3BD9S216BHw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta" + } + }, + "node_modules/@storybook/manager-api": { + "version": "8.6.17", + "resolved": "https://registry.npmjs.org/@storybook/manager-api/-/manager-api-8.6.17.tgz", + "integrity": "sha512-sPJytvClNrw5GgKcPletMTxDOAYcTRA8VRt9E+ncKvPSYHtPDqLfGTgWajXmt0hRsiBUN5bOgLS9bmNjNQWhrw==", + "dev": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0" + } + }, + "node_modules/@storybook/preview-api": { + "version": "8.6.17", + "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-8.6.17.tgz", + "integrity": "sha512-vpTCTkw11wXerYnlG5Q0y4SbFqG9O6GhR0hlYgCn3Z9kcHlNjK/xuwd3h4CvwNXxRNWZGT8qYYCLn5gSSrX6fA==", + "dev": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0" + } + }, + "node_modules/@storybook/react-dom-shim": { + "version": "8.6.14", + "resolved": "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-8.6.14.tgz", + "integrity": "sha512-0hixr3dOy3f3M+HBofp3jtMQMS+sqzjKNgl7Arfuj3fvjmyXOks/yGjDImySR4imPtEllvPZfhiQNlejheaInw==", + "dev": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "storybook": "^8.6.14" + } + }, + "node_modules/@storybook/theming": { + "version": "8.6.17", + "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-8.6.17.tgz", + "integrity": "sha512-IttFvRqozpuzN5MlQEWGOzUA2rZg86688Dyv1d+bjpYcFHtY1X4XyTCGwv1BPTaTsB959oM8R2yoNYWQkABbBA==", + "dev": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0" + } + }, + "node_modules/@storybook/web-components": { + "version": "8.6.17", + "resolved": "https://registry.npmjs.org/@storybook/web-components/-/web-components-8.6.17.tgz", + "integrity": "sha512-nOff5VrXpul7ZEd/iA8UFEPO6+u3Mypd4CmW771u03TWxz+Evc8FmGV99uw63LyQCcb3UkueOPc2M8kpO3meqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@storybook/components": "8.6.17", + "@storybook/global": "^5.0.0", + "@storybook/manager-api": "8.6.17", + "@storybook/preview-api": "8.6.17", + "@storybook/theming": "8.6.17", + "tiny-invariant": "^1.3.1", + "ts-dedent": "^2.0.0" + }, + "engines": { + "node": ">=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "lit": "^2.0.0 || ^3.0.0", + "storybook": "^8.6.17" + } + }, + "node_modules/@storybook/web-components-vite": { + "version": "8.6.17", + "resolved": "https://registry.npmjs.org/@storybook/web-components-vite/-/web-components-vite-8.6.17.tgz", + "integrity": "sha512-6wIRmfyGM/I8TZ/2MKTvt2KQeFiKyCEZUHP006lDfasy7pFI9Sj+KyBXTFqI4WwdB+i+F6PlOW3SJmTqSykGjA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@storybook/builder-vite": "8.6.17", + "@storybook/web-components": "8.6.17", + "magic-string": "^0.30.0" + }, + "engines": { + "node": ">=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.6.17" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@types/mdx": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.13.tgz", + "integrity": "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "19.2.14", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", + "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "csstype": "^3.2.2" + } + }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "license": "MIT" + }, + "node_modules/@types/uuid": { + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", + "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", + "dev": true, + "license": "MIT" + }, + "node_modules/acorn": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ast-types": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz", + "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/better-opn": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/better-opn/-/better-opn-3.0.2.tgz", + "integrity": "sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "open": "^8.0.4" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/browser-assert": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/browser-assert/-/browser-assert-1.2.1.tgz", + "integrity": "sha512-nfulgvOR6S4gt9UKCeGJOuSGBPGiFT6oQ/2UBnvTY/5aQ1PnksW72fhZkM30DzoRRv2WpwZf1vHHEr3mtuXIWQ==", + "dev": true + }, + "node_modules/call-bind": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.12", + "@esbuild/android-arm": "0.25.12", + "@esbuild/android-arm64": "0.25.12", + "@esbuild/android-x64": "0.25.12", + "@esbuild/darwin-arm64": "0.25.12", + "@esbuild/darwin-x64": "0.25.12", + "@esbuild/freebsd-arm64": "0.25.12", + "@esbuild/freebsd-x64": "0.25.12", + "@esbuild/linux-arm": "0.25.12", + "@esbuild/linux-arm64": "0.25.12", + "@esbuild/linux-ia32": "0.25.12", + "@esbuild/linux-loong64": "0.25.12", + "@esbuild/linux-mips64el": "0.25.12", + "@esbuild/linux-ppc64": "0.25.12", + "@esbuild/linux-riscv64": "0.25.12", + "@esbuild/linux-s390x": "0.25.12", + "@esbuild/linux-x64": "0.25.12", + "@esbuild/netbsd-arm64": "0.25.12", + "@esbuild/netbsd-x64": "0.25.12", + "@esbuild/openbsd-arm64": "0.25.12", + "@esbuild/openbsd-x64": "0.25.12", + "@esbuild/openharmony-arm64": "0.25.12", + "@esbuild/sunos-x64": "0.25.12", + "@esbuild/win32-arm64": "0.25.12", + "@esbuild/win32-ia32": "0.25.12", + "@esbuild/win32-x64": "0.25.12" + } + }, + "node_modules/esbuild-register": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/esbuild-register/-/esbuild-register-3.6.0.tgz", + "integrity": "sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.4" + }, + "peerDependencies": { + "esbuild": ">=0.12 <1" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/is-arguments": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz", + "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true, + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jsdoc-type-pratt-parser": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.8.0.tgz", + "integrity": "sha512-iZ8Bdb84lWRuGHamRXFyML07r21pcwBrLkHEuHgEY5UbCouBwv7ECknDRKzsQIXMiqpPymqtIf8TC/shYKB5rw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/lit": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/lit/-/lit-3.3.2.tgz", + "integrity": "sha512-NF9zbsP79l4ao2SNrH3NkfmFgN/hBYSQo90saIVI1o5GpjAdCPVstVzO1MrLOakHoEhYkrtRjPK6Ob521aoYWQ==", + "license": "BSD-3-Clause", + "dependencies": { + "@lit/reactive-element": "^2.1.0", + "lit-element": "^4.2.0", + "lit-html": "^3.3.0" + } + }, + "node_modules/lit-element": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-4.2.2.tgz", + "integrity": "sha512-aFKhNToWxoyhkNDmWZwEva2SlQia+jfG0fjIWV//YeTaWrVnOxD89dPKfigCUspXFmjzOEUQpOkejH5Ly6sG0w==", + "license": "BSD-3-Clause", + "dependencies": { + "@lit-labs/ssr-dom-shim": "^1.5.0", + "@lit/reactive-element": "^2.1.0", + "lit-html": "^3.3.0" + } + }, + "node_modules/lit-html": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-3.3.2.tgz", + "integrity": "sha512-Qy9hU88zcmaxBXcc10ZpdK7cOLXvXpRoBxERdtqV9QOrfpMZZ6pSYP91LhpPtap3sFMUiL7Tw2RImbe0Al2/kw==", + "license": "BSD-3-Clause", + "dependencies": { + "@types/trusted-types": "^2.0.2" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/map-or-similar": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/map-or-similar/-/map-or-similar-1.5.0.tgz", + "integrity": "sha512-0aF7ZmVon1igznGI4VS30yugpduQW3y3GkcgGJOp7d8x8QrizhigUxjI/m2UojsXXto+jLAH3KSz+xOJTiORjg==", + "dev": true, + "license": "MIT" + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/memoizerific": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/memoizerific/-/memoizerific-1.11.3.tgz", + "integrity": "sha512-/EuHYwAPdLtXwAwSZkh/Gutery6pD2KYd44oQLhAvQp/50mpyduZh8Q7PYHXTCJ+wuXxt7oij2LXyIJOOYFPog==", + "dev": true, + "license": "MIT", + "dependencies": { + "map-or-similar": "^1.5.0" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "peer": true, + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC", + "peer": true + }, + "node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/polished": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/polished/-/polished-4.3.1.tgz", + "integrity": "sha512-OBatVyC/N7SCW/FaDHrSd+vn0o5cS855TOmYi4OkdWUMSJCET/xip//ch8xGUvtr3i44X9LVyWwQlRMTN3pwSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.17.8" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/react": { + "version": "19.2.4", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", + "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.2.4", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz", + "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.4" + } + }, + "node_modules/recast": { + "version": "0.23.11", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.11.tgz", + "integrity": "sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ast-types": "^0.16.1", + "esprima": "~4.0.0", + "source-map": "~0.6.1", + "tiny-invariant": "^1.3.3", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/rollup": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz", + "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.59.0", + "@rollup/rollup-android-arm64": "4.59.0", + "@rollup/rollup-darwin-arm64": "4.59.0", + "@rollup/rollup-darwin-x64": "4.59.0", + "@rollup/rollup-freebsd-arm64": "4.59.0", + "@rollup/rollup-freebsd-x64": "4.59.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", + "@rollup/rollup-linux-arm-musleabihf": "4.59.0", + "@rollup/rollup-linux-arm64-gnu": "4.59.0", + "@rollup/rollup-linux-arm64-musl": "4.59.0", + "@rollup/rollup-linux-loong64-gnu": "4.59.0", + "@rollup/rollup-linux-loong64-musl": "4.59.0", + "@rollup/rollup-linux-ppc64-gnu": "4.59.0", + "@rollup/rollup-linux-ppc64-musl": "4.59.0", + "@rollup/rollup-linux-riscv64-gnu": "4.59.0", + "@rollup/rollup-linux-riscv64-musl": "4.59.0", + "@rollup/rollup-linux-s390x-gnu": "4.59.0", + "@rollup/rollup-linux-x64-gnu": "4.59.0", + "@rollup/rollup-linux-x64-musl": "4.59.0", + "@rollup/rollup-openbsd-x64": "4.59.0", + "@rollup/rollup-openharmony-arm64": "4.59.0", + "@rollup/rollup-win32-arm64-msvc": "4.59.0", + "@rollup/rollup-win32-ia32-msvc": "4.59.0", + "@rollup/rollup-win32-x64-gnu": "4.59.0", + "@rollup/rollup-win32-x64-msvc": "4.59.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/signal-polyfill": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/signal-polyfill/-/signal-polyfill-0.2.2.tgz", + "integrity": "sha512-p63Y4Er5/eMQ9RHg0M0Y64NlsQKpiu6MDdhBXpyywRuWiPywhJTpKJ1iB5K2hJEbFZ0BnDS7ZkJ+0AfTuL37Rg==", + "license": "Apache-2.0" + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/storybook": { + "version": "8.6.17", + "resolved": "https://registry.npmjs.org/storybook/-/storybook-8.6.17.tgz", + "integrity": "sha512-krR/l680A6qVnkGiK9p8jY0ucX3+kFCs2f4zw+S3w2Cdq8EiM/tFebPcX2V4S3z2UsO0v0dwAJOJNpzbFPdmVg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@storybook/core": "8.6.17" + }, + "bin": { + "getstorybook": "bin/index.cjs", + "sb": "bin/index.cjs", + "storybook": "bin/index.cjs" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "prettier": "^2 || ^3" + }, + "peerDependenciesMeta": { + "prettier": { + "optional": true + } + } + }, + "node_modules/tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/ts-dedent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", + "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.10" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/unplugin": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.16.1.tgz", + "integrity": "sha512-4/u/j4FrCKdi17jaxuJA0jClGxB1AvU2hw/IuayPc4ay1XGaJs/rbb4v5WKwAjNifjmXK9PIFyuPiaK8azyR9w==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.14.0", + "webpack-virtual-modules": "^0.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, + "node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/vite": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz", + "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.4.4", + "picomatch": "^4.0.2", + "postcss": "^8.5.3", + "rollup": "^4.34.9", + "tinyglobby": "^0.2.13" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "jiti": ">=1.21.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/webpack-virtual-modules": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz", + "integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/which-typed-array": { + "version": "1.1.20", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.20.tgz", + "integrity": "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ws": { + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz", + "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + } + } +} diff --git a/conformance-storybook/package.json b/conformance-storybook/package.json new file mode 100644 index 000000000..abde460a5 --- /dev/null +++ b/conformance-storybook/package.json @@ -0,0 +1,26 @@ +{ + "name": "a2ui-conformance-storybook", + "private": true, + "version": "0.1.0", + "type": "module", + "scripts": { + "generate": "node scripts/generate-stories.mjs", + "storybook": "node scripts/generate-stories.mjs && storybook dev -p 6006", + "build-storybook": "node scripts/generate-stories.mjs && storybook build" + }, + "dependencies": { + "@a2ui/lit": "file:../renderers/lit", + "@a2ui/web_core": "file:../renderers/web_core", + "lit": "^3.3.1", + "@lit-labs/signals": "^0.1.3", + "@lit/context": "^1.1.4" + }, + "devDependencies": { + "@storybook/web-components": "^8.6.14", + "@storybook/web-components-vite": "^8.6.14", + "@storybook/addon-essentials": "^8.6.14", + "@storybook/blocks": "^8.6.14", + "storybook": "^8.6.14", + "typescript": "^5.8.3" + } +} diff --git a/conformance-storybook/scripts/generate-stories.mjs b/conformance-storybook/scripts/generate-stories.mjs new file mode 100644 index 000000000..2c45b666f --- /dev/null +++ b/conformance-storybook/scripts/generate-stories.mjs @@ -0,0 +1,70 @@ +#!/usr/bin/env node +/** + * Build-time story generator. + * Reads fixture JSON files and generates Storybook CSF3 .stories.ts files. + * Run before `storybook build`. + */ +import { readFileSync, writeFileSync, mkdirSync, readdirSync } from "fs"; +import { join, dirname } from "path"; +import { fileURLToPath } from "url"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const root = join(__dirname, ".."); +const fixturesDir = join(root, "stories", "fixtures"); +const outDir = join(root, "stories", "generated"); + +// Read manifest +const manifest = JSON.parse(readFileSync(join(fixturesDir, "manifest.json"), "utf-8")); + +mkdirSync(outDir, { recursive: true }); + +function sanitizeName(name) { + // Convert to valid JS identifier: "Primary Button" → "PrimaryButton" + return name.replace(/[^a-zA-Z0-9]/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, ""); +} + +let totalStories = 0; + +for (const entry of manifest.fixtures) { + const fixture = JSON.parse(readFileSync(join(fixturesDir, entry.file), "utf-8")); + const category = entry.category; + const baseName = entry.file.replace(".json", ""); + + let code = `// AUTO-GENERATED — do not edit. Run: node scripts/generate-stories.mjs +import type { Meta, StoryObj } from "@storybook/web-components"; +import { renderA2UI } from "../helpers/a2ui-story-wrapper.js"; +import { translateToV08 } from "../helpers/version-adapter.js"; +import type { V010Message } from "../helpers/version-adapter.js"; + +const meta: Meta = { title: "Generated/${category}" }; +export default meta; + +`; + + for (const scenario of fixture.scenarios) { + const exportName = sanitizeName(scenario.name) + "_v08_Lit"; + const messagesJson = JSON.stringify(scenario.messages, null, 2); + + // Determine surface ID for rendering + let surfaceId = null; + for (const msg of scenario.messages) { + if (msg.createSurface) { + surfaceId = msg.createSurface.surfaceId; + break; + } + } + + code += `const ${sanitizeName(scenario.name)}_messages: V010Message[] = ${messagesJson};\n\n`; + code += `export const ${exportName}: StoryObj = {\n`; + code += ` name: "${scenario.name} [v0.8 Lit]",\n`; + code += ` render: () => renderA2UI(translateToV08(${sanitizeName(scenario.name)}_messages)${surfaceId ? `, "${surfaceId}"` : ""}),\n`; + code += `};\n\n`; + totalStories++; + } + + const outFile = join(outDir, `${baseName}.stories.ts`); + writeFileSync(outFile, code); + console.log(` ✓ ${outFile} (${fixture.scenarios.length} stories)`); +} + +console.log(`\nGenerated ${totalStories} stories from ${manifest.fixtures.length} fixture files.`); diff --git a/conformance-storybook/stories/AudioPlayer.stories.ts b/conformance-storybook/stories/AudioPlayer.stories.ts new file mode 100644 index 000000000..e9a5f4d68 --- /dev/null +++ b/conformance-storybook/stories/AudioPlayer.stories.ts @@ -0,0 +1,11 @@ +import type { Meta, StoryObj } from "@storybook/web-components"; +import { renderA2UI, simpleComponent } from "./helpers/a2ui-story-wrapper.js"; + +const meta: Meta = { title: "Components/AudioPlayer" }; +export default meta; + +export const Basic: StoryObj = { + render: () => renderA2UI(simpleComponent("audio-basic", [ + { id: "a1", component: "AudioPlayer", url: "https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3", title: "Sample Audio" }, + ])), +}; diff --git a/conformance-storybook/stories/Button.stories.ts b/conformance-storybook/stories/Button.stories.ts new file mode 100644 index 000000000..af0d61f3f --- /dev/null +++ b/conformance-storybook/stories/Button.stories.ts @@ -0,0 +1,33 @@ +import type { Meta, StoryObj } from "@storybook/web-components"; +import { renderA2UI, simpleComponent } from "./helpers/a2ui-story-wrapper.js"; + +const meta: Meta = { title: "Components/Button" }; +export default meta; + +export const Primary: StoryObj = { + render: () => renderA2UI(simpleComponent("btn-primary", [ + { id: "btn", component: { Button: { child: "txt", primary: true, action: { name: "click" } } } }, + { id: "txt", component: { Text: { text: { literalString: "Primary Button" } } } }, + ])), +}; + +export const Outlined: StoryObj = { + render: () => renderA2UI(simpleComponent("btn-outlined", [ + { id: "btn", component: { Button: { child: "txt", outlined: true, action: { name: "click" } } } }, + { id: "txt", component: { Text: { text: { literalString: "Outlined Button" } } } }, + ])), +}; + +export const TextVariant: StoryObj = { + render: () => renderA2UI(simpleComponent("btn-text", [ + { id: "btn", component: { Button: { child: "txt", action: { name: "click" } } } }, + { id: "txt", component: { Text: { text: { literalString: "Text Button" } } } }, + ])), +}; + +export const IconButton: StoryObj = { + render: () => renderA2UI(simpleComponent("btn-icon", [ + { id: "btn", component: { Button: { child: "ico", variant: "icon", action: { name: "click" } } } }, + { id: "ico", component: { Icon: { name: { literalString: "favorite" } } } }, + ])), +}; diff --git a/conformance-storybook/stories/Card.stories.ts b/conformance-storybook/stories/Card.stories.ts new file mode 100644 index 000000000..5e0295a5a --- /dev/null +++ b/conformance-storybook/stories/Card.stories.ts @@ -0,0 +1,24 @@ +import type { Meta, StoryObj } from "@storybook/web-components"; +import { renderA2UI, simpleComponent } from "./helpers/a2ui-story-wrapper.js"; + +const meta: Meta = { title: "Components/Card" }; +export default meta; + +export const Basic: StoryObj = { + render: () => renderA2UI(simpleComponent("card-basic", [ + { id: "card1", component: "Card", child: "col1" }, + { id: "col1", component: "Column", children: ["t1", "t2"] }, + { id: "t1", component: "Text", text: "Card Title", variant: "h3" }, + { id: "t2", component: "Text", text: "Card body content goes here.", variant: "body" }, + ])), +}; + +export const WithHeader: StoryObj = { + render: () => renderA2UI(simpleComponent("card-header", [ + { id: "card1", component: "Card", child: "content", header: "header_row" }, + { id: "header_row", component: "Row", children: ["header_icon", "header_text"], align: "center" }, + { id: "header_icon", component: "Icon", name: "info" }, + { id: "header_text", component: "Text", text: "Card Header", variant: "h4" }, + { id: "content", component: "Text", text: "This card has a header section.", variant: "body" }, + ])), +}; diff --git a/conformance-storybook/stories/CheckBox.stories.ts b/conformance-storybook/stories/CheckBox.stories.ts new file mode 100644 index 000000000..7cd88bee2 --- /dev/null +++ b/conformance-storybook/stories/CheckBox.stories.ts @@ -0,0 +1,17 @@ +import type { Meta, StoryObj } from "@storybook/web-components"; +import { renderA2UI, componentWithData } from "./helpers/a2ui-story-wrapper.js"; + +const meta: Meta = { title: "Components/CheckBox" }; +export default meta; + +export const Unchecked: StoryObj = { + render: () => renderA2UI(componentWithData("cb-off", [ + { id: "cb1", component: "CheckBox", label: "Accept terms", value: { path: "/form/terms" } }, + ], "/form", { terms: false })), +}; + +export const Checked: StoryObj = { + render: () => renderA2UI(componentWithData("cb-on", [ + { id: "cb1", component: "CheckBox", label: "Subscribe to newsletter", value: { path: "/form/sub" } }, + ], "/form", { sub: true })), +}; diff --git a/conformance-storybook/stories/Column.stories.ts b/conformance-storybook/stories/Column.stories.ts new file mode 100644 index 000000000..5a184f95f --- /dev/null +++ b/conformance-storybook/stories/Column.stories.ts @@ -0,0 +1,23 @@ +import type { Meta, StoryObj } from "@storybook/web-components"; +import { renderA2UI, simpleComponent } from "./helpers/a2ui-story-wrapper.js"; + +const meta: Meta = { title: "Components/Column" }; +export default meta; + +export const Basic: StoryObj = { + render: () => renderA2UI(simpleComponent("col-basic", [ + { id: "col1", component: "Column", children: ["t1", "t2", "t3"] }, + { id: "t1", component: "Text", text: "First item", variant: "body" }, + { id: "t2", component: "Text", text: "Second item", variant: "body" }, + { id: "t3", component: "Text", text: "Third item", variant: "body" }, + ])), +}; + +export const WithAlignment: StoryObj = { + render: () => renderA2UI(simpleComponent("col-align", [ + { id: "col1", component: "Column", children: ["t1", "t2", "t3"], align: "center", justify: "center" }, + { id: "t1", component: "Text", text: "Centered", variant: "h3" }, + { id: "t2", component: "Text", text: "Column", variant: "body" }, + { id: "t3", component: "Text", text: "Items", variant: "body" }, + ])), +}; diff --git a/conformance-storybook/stories/ContactForm.stories.ts b/conformance-storybook/stories/ContactForm.stories.ts new file mode 100644 index 000000000..9cb459f9b --- /dev/null +++ b/conformance-storybook/stories/ContactForm.stories.ts @@ -0,0 +1,83 @@ +import type { Meta, StoryObj } from "@storybook/web-components"; +import { renderA2UI } from "./helpers/a2ui-story-wrapper.js"; +import type { A2UIMessage } from "./helpers/a2ui-story-wrapper.js"; + +const meta: Meta = { title: "Integration/Contact Form" }; +export default meta; + +// From specification/v0_10/test/cases/contact_form_example.jsonl +// Adapted to v0.8 (MultipleChoice instead of ChoicePicker, no checks) +const contactFormMessages: A2UIMessage[] = [ + { + version: "v0.8", + createSurface: { surfaceId: "contact_form_1" }, + }, + { + version: "v0.8", + updateComponents: { + surfaceId: "contact_form_1", + components: [ + { id: "root", component: "Card", child: "form_container" }, + { + id: "form_container", component: "Column", + children: ["header_row", "name_row", "email_group", "phone_group", "pref_group", "divider_1", "newsletter_checkbox", "submit_button"], + justify: "start", align: "stretch", + }, + { id: "header_row", component: "Row", children: ["header_icon", "header_text"], align: "center" }, + { id: "header_icon", component: "Icon", name: "mail" }, + { id: "header_text", component: "Text", text: "# Contact Us", variant: "h2" }, + { id: "name_row", component: "Row", children: ["first_name_group", "last_name_group"], justify: "spaceBetween" }, + { id: "first_name_group", component: "Column", children: ["first_name_label", "first_name_field"], weight: 1 }, + { id: "first_name_label", component: "Text", text: "First Name", variant: "caption" }, + { id: "first_name_field", component: "TextField", label: "First Name", value: { path: "/contact/firstName" }, variant: "shortText" }, + { id: "last_name_group", component: "Column", children: ["last_name_label", "last_name_field"], weight: 1 }, + { id: "last_name_label", component: "Text", text: "Last Name", variant: "caption" }, + { id: "last_name_field", component: "TextField", label: "Last Name", value: { path: "/contact/lastName" }, variant: "shortText" }, + { id: "email_group", component: "Column", children: ["email_label", "email_field"] }, + { id: "email_label", component: "Text", text: "Email Address", variant: "caption" }, + { id: "email_field", component: "TextField", label: "Email", value: { path: "/contact/email" }, variant: "shortText" }, + { id: "phone_group", component: "Column", children: ["phone_label", "phone_field"] }, + { id: "phone_label", component: "Text", text: "Phone Number", variant: "caption" }, + { id: "phone_field", component: "TextField", label: "Phone", value: { path: "/contact/phone" }, variant: "shortText" }, + { id: "pref_group", component: "Column", children: ["pref_label", "pref_picker"] }, + { id: "pref_label", component: "Text", text: "Preferred Contact Method", variant: "caption" }, + { + id: "pref_picker", component: "MultipleChoice", variant: "mutuallyExclusive", + options: [ + { label: "Email", value: "email" }, + { label: "Phone", value: "phone" }, + { label: "SMS", value: "sms" }, + ], + value: { path: "/contact/preference" }, + }, + { id: "divider_1", component: "Divider", axis: "horizontal" }, + { id: "newsletter_checkbox", component: "CheckBox", label: "Subscribe to our newsletter", value: { path: "/contact/subscribe" } }, + { id: "submit_button", component: "Button", child: "submit_button_label", variant: "primary", action: { event: { name: "submitContactForm" } } }, + { id: "submit_button_label", component: "Text", text: "Send Message" }, + ], + }, + }, + { + version: "v0.8", + updateDataModel: { + surfaceId: "contact_form_1", + path: "/contact", + value: { + firstName: "John", + lastName: "Doe", + email: "john.doe@example.com", + phone: "1234567890", + preference: ["email"], + subscribe: true, + }, + }, + }, +]; + +export const FilledForm: StoryObj = { + render: () => renderA2UI(contactFormMessages, "contact_form_1"), +}; + +export const EmptyForm: StoryObj = { + render: () => renderA2UI(contactFormMessages.slice(0, 2), "contact_form_1"), +}; diff --git a/conformance-storybook/stories/DateTimeInput.stories.ts b/conformance-storybook/stories/DateTimeInput.stories.ts new file mode 100644 index 000000000..5024a4307 --- /dev/null +++ b/conformance-storybook/stories/DateTimeInput.stories.ts @@ -0,0 +1,23 @@ +import type { Meta, StoryObj } from "@storybook/web-components"; +import { renderA2UI, componentWithData } from "./helpers/a2ui-story-wrapper.js"; + +const meta: Meta = { title: "Components/DateTimeInput" }; +export default meta; + +export const DatePicker: StoryObj = { + render: () => renderA2UI(componentWithData("dt-date", [ + { id: "dt1", component: "DateTimeInput", label: "Birth Date", variant: "date", value: { path: "/form/dob" } }, + ], "/form", { dob: "1990-01-15" })), +}; + +export const TimePicker: StoryObj = { + render: () => renderA2UI(componentWithData("dt-time", [ + { id: "dt1", component: "DateTimeInput", label: "Meeting Time", variant: "time", value: { path: "/form/time" } }, + ], "/form", { time: "14:30" })), +}; + +export const DateTimePicker: StoryObj = { + render: () => renderA2UI(componentWithData("dt-both", [ + { id: "dt1", component: "DateTimeInput", label: "Event Start", variant: "dateTime", value: { path: "/form/start" } }, + ], "/form", { start: "2026-03-01T09:00" })), +}; diff --git a/conformance-storybook/stories/Divider.stories.ts b/conformance-storybook/stories/Divider.stories.ts new file mode 100644 index 000000000..c5bdfd878 --- /dev/null +++ b/conformance-storybook/stories/Divider.stories.ts @@ -0,0 +1,14 @@ +import type { Meta, StoryObj } from "@storybook/web-components"; +import { renderA2UI, simpleComponent } from "./helpers/a2ui-story-wrapper.js"; + +const meta: Meta = { title: "Components/Divider" }; +export default meta; + +export const Horizontal: StoryObj = { + render: () => renderA2UI(simpleComponent("divider-h", [ + { id: "col1", component: "Column", children: ["t1", "d1", "t2"] }, + { id: "t1", component: "Text", text: "Above the divider", variant: "body" }, + { id: "d1", component: "Divider", axis: "horizontal" }, + { id: "t2", component: "Text", text: "Below the divider", variant: "body" }, + ])), +}; diff --git a/conformance-storybook/stories/Icon.stories.ts b/conformance-storybook/stories/Icon.stories.ts new file mode 100644 index 000000000..56a8aacc0 --- /dev/null +++ b/conformance-storybook/stories/Icon.stories.ts @@ -0,0 +1,21 @@ +import type { Meta, StoryObj } from "@storybook/web-components"; +import { renderA2UI, simpleComponent } from "./helpers/a2ui-story-wrapper.js"; + +const meta: Meta = { title: "Components/Icon" }; +export default meta; + +export const MaterialIcon: StoryObj = { + render: () => renderA2UI(simpleComponent("icon-material", [ + { id: "i1", component: "Icon", name: "home" }, + ])), +}; + +export const MultipleIcons: StoryObj = { + render: () => renderA2UI(simpleComponent("icon-multi", [ + { id: "row1", component: "Row", children: ["i1", "i2", "i3", "i4"] }, + { id: "i1", component: "Icon", name: "home" }, + { id: "i2", component: "Icon", name: "settings" }, + { id: "i3", component: "Icon", name: "mail" }, + { id: "i4", component: "Icon", name: "search" }, + ])), +}; diff --git a/conformance-storybook/stories/Image.stories.ts b/conformance-storybook/stories/Image.stories.ts new file mode 100644 index 000000000..a5f6cb057 --- /dev/null +++ b/conformance-storybook/stories/Image.stories.ts @@ -0,0 +1,17 @@ +import type { Meta, StoryObj } from "@storybook/web-components"; +import { renderA2UI, simpleComponent } from "./helpers/a2ui-story-wrapper.js"; + +const meta: Meta = { title: "Components/Image" }; +export default meta; + +export const Basic: StoryObj = { + render: () => renderA2UI(simpleComponent("image-basic", [ + { id: "img1", component: "Image", url: "https://picsum.photos/400/300", alt: "Sample image" }, + ])), +}; + +export const WithFit: StoryObj = { + render: () => renderA2UI(simpleComponent("image-fit", [ + { id: "img1", component: "Image", url: "https://picsum.photos/800/400", alt: "Cover image", fit: "cover" }, + ])), +}; diff --git a/conformance-storybook/stories/List.stories.ts b/conformance-storybook/stories/List.stories.ts new file mode 100644 index 000000000..2e8ea408e --- /dev/null +++ b/conformance-storybook/stories/List.stories.ts @@ -0,0 +1,24 @@ +import type { Meta, StoryObj } from "@storybook/web-components"; +import { renderA2UI, simpleComponent } from "./helpers/a2ui-story-wrapper.js"; + +const meta: Meta = { title: "Components/List" }; +export default meta; + +export const Basic: StoryObj = { + render: () => renderA2UI(simpleComponent("list-basic", [ + { id: "list1", component: "List", children: ["item1", "item2", "item3"] }, + { id: "item1", component: "Text", text: "Item 1", variant: "body" }, + { id: "item2", component: "Text", text: "Item 2", variant: "body" }, + { id: "item3", component: "Text", text: "Item 3", variant: "body" }, + ])), +}; + +export const WithCards: StoryObj = { + render: () => renderA2UI(simpleComponent("list-cards", [ + { id: "list1", component: "List", children: ["card1", "card2"] }, + { id: "card1", component: "Card", child: "t1" }, + { id: "t1", component: "Text", text: "Card in a list", variant: "body" }, + { id: "card2", component: "Card", child: "t2" }, + { id: "t2", component: "Text", text: "Another card", variant: "body" }, + ])), +}; diff --git a/conformance-storybook/stories/Modal.stories.ts b/conformance-storybook/stories/Modal.stories.ts new file mode 100644 index 000000000..e1c6f6280 --- /dev/null +++ b/conformance-storybook/stories/Modal.stories.ts @@ -0,0 +1,15 @@ +import type { Meta, StoryObj } from "@storybook/web-components"; +import { renderA2UI, simpleComponent } from "./helpers/a2ui-story-wrapper.js"; + +const meta: Meta = { title: "Components/Modal" }; +export default meta; + +export const Basic: StoryObj = { + render: () => renderA2UI(simpleComponent("modal-basic", [ + { id: "modal1", component: { Modal: { + child: "modal-content", + title: { literalString: "Dialog Title" }, + }}}, + { id: "modal-content", component: { Text: { text: { literalString: "This is modal content. Click the entry point to open." } } } }, + ])), +}; diff --git a/conformance-storybook/stories/MultipleChoice.stories.ts b/conformance-storybook/stories/MultipleChoice.stories.ts new file mode 100644 index 000000000..e073a5be6 --- /dev/null +++ b/conformance-storybook/stories/MultipleChoice.stories.ts @@ -0,0 +1,45 @@ +import type { Meta, StoryObj } from "@storybook/web-components"; +import { renderA2UI, simpleComponent } from "./helpers/a2ui-story-wrapper.js"; + +const meta: Meta = { title: "Components/ChoicePicker (MultipleChoice)" }; +export default meta; + +export const MutuallyExclusive: StoryObj = { + render: () => renderA2UI(simpleComponent("mc-exclusive", [ + { id: "mc1", component: { MultipleChoice: { + selections: { path: "/pref" }, + options: [ + { label: { literalString: "Email" }, value: "email" }, + { label: { literalString: "Phone" }, value: "phone" }, + { label: { literalString: "SMS" }, value: "sms" }, + ], + }}}, + ])), +}; + +export const MultiSelect: StoryObj = { + render: () => renderA2UI(simpleComponent("mc-multi", [ + { id: "mc1", component: { MultipleChoice: { + selections: { path: "/langs" }, + options: [ + { label: { literalString: "JavaScript" }, value: "js" }, + { label: { literalString: "Python" }, value: "py" }, + { label: { literalString: "Rust" }, value: "rs" }, + ], + }}}, + ])), +}; + +export const Chips: StoryObj = { + render: () => renderA2UI(simpleComponent("mc-chips", [ + { id: "mc1", component: { MultipleChoice: { + selections: { path: "/size" }, + variant: "chips", + options: [ + { label: { literalString: "Small" }, value: "s" }, + { label: { literalString: "Medium" }, value: "m" }, + { label: { literalString: "Large" }, value: "l" }, + ], + }}}, + ])), +}; diff --git a/conformance-storybook/stories/Row.stories.ts b/conformance-storybook/stories/Row.stories.ts new file mode 100644 index 000000000..caa8b26b2 --- /dev/null +++ b/conformance-storybook/stories/Row.stories.ts @@ -0,0 +1,22 @@ +import type { Meta, StoryObj } from "@storybook/web-components"; +import { renderA2UI, simpleComponent } from "./helpers/a2ui-story-wrapper.js"; + +const meta: Meta = { title: "Components/Row" }; +export default meta; + +export const Basic: StoryObj = { + render: () => renderA2UI(simpleComponent("row-basic", [ + { id: "row1", component: "Row", children: ["t1", "t2", "t3"] }, + { id: "t1", component: "Text", text: "Left", variant: "body" }, + { id: "t2", component: "Text", text: "Center", variant: "body" }, + { id: "t3", component: "Text", text: "Right", variant: "body" }, + ])), +}; + +export const SpaceBetween: StoryObj = { + render: () => renderA2UI(simpleComponent("row-space", [ + { id: "row1", component: "Row", children: ["t1", "t2"], justify: "spaceBetween" }, + { id: "t1", component: "Text", text: "Start", variant: "body" }, + { id: "t2", component: "Text", text: "End", variant: "body" }, + ])), +}; diff --git a/conformance-storybook/stories/Slider.stories.ts b/conformance-storybook/stories/Slider.stories.ts new file mode 100644 index 000000000..3d8285380 --- /dev/null +++ b/conformance-storybook/stories/Slider.stories.ts @@ -0,0 +1,17 @@ +import type { Meta, StoryObj } from "@storybook/web-components"; +import { renderA2UI, componentWithData } from "./helpers/a2ui-story-wrapper.js"; + +const meta: Meta = { title: "Components/Slider" }; +export default meta; + +export const Basic: StoryObj = { + render: () => renderA2UI(componentWithData("slider-basic", [ + { id: "s1", component: "Slider", label: "Volume", min: 0, max: 100, step: 1, value: { path: "/form/vol" } }, + ], "/form", { vol: 50 })), +}; + +export const WithRange: StoryObj = { + render: () => renderA2UI(componentWithData("slider-range", [ + { id: "s1", component: "Slider", label: "Temperature (°F)", min: 60, max: 90, step: 1, value: { path: "/form/temp" } }, + ], "/form", { temp: 72 })), +}; diff --git a/conformance-storybook/stories/Tabs.stories.ts b/conformance-storybook/stories/Tabs.stories.ts new file mode 100644 index 000000000..0194f7892 --- /dev/null +++ b/conformance-storybook/stories/Tabs.stories.ts @@ -0,0 +1,20 @@ +import type { Meta, StoryObj } from "@storybook/web-components"; +import { renderA2UI, simpleComponent } from "./helpers/a2ui-story-wrapper.js"; + +const meta: Meta = { title: "Components/Tabs" }; +export default meta; + +export const Basic: StoryObj = { + render: () => renderA2UI(simpleComponent("tabs-basic", [ + { id: "tabs1", component: { Tabs: { + tabItems: [ + { title: { literalString: "Tab 1" }, child: "content1" }, + { title: { literalString: "Tab 2" }, child: "content2" }, + { title: { literalString: "Tab 3" }, child: "content3" }, + ], + }}}, + { id: "content1", component: { Text: { text: { literalString: "Content of Tab 1" } } } }, + { id: "content2", component: { Text: { text: { literalString: "Content of Tab 2" } } } }, + { id: "content3", component: { Text: { text: { literalString: "Content of Tab 3" } } } }, + ])), +}; diff --git a/conformance-storybook/stories/Text.stories.ts b/conformance-storybook/stories/Text.stories.ts new file mode 100644 index 000000000..d94650db2 --- /dev/null +++ b/conformance-storybook/stories/Text.stories.ts @@ -0,0 +1,37 @@ +import type { Meta, StoryObj } from "@storybook/web-components"; +import { renderA2UI, simpleComponent } from "./helpers/a2ui-story-wrapper.js"; + +const meta: Meta = { + title: "Components/Text", +}; +export default meta; + +export const Heading1: StoryObj = { + render: () => renderA2UI(simpleComponent("text-h1", [ + { id: "t1", component: "Text", text: "Hello World", variant: "h1" }, + ])), +}; + +export const Heading2: StoryObj = { + render: () => renderA2UI(simpleComponent("text-h2", [ + { id: "t1", component: "Text", text: "Heading 2", variant: "h2" }, + ])), +}; + +export const Heading3: StoryObj = { + render: () => renderA2UI(simpleComponent("text-h3", [ + { id: "t1", component: "Text", text: "Heading 3", variant: "h3" }, + ])), +}; + +export const Body: StoryObj = { + render: () => renderA2UI(simpleComponent("text-body", [ + { id: "t1", component: "Text", text: "This is body text with **markdown** support.", variant: "body" }, + ])), +}; + +export const Caption: StoryObj = { + render: () => renderA2UI(simpleComponent("text-caption", [ + { id: "t1", component: "Text", text: "Caption text", variant: "caption" }, + ])), +}; diff --git a/conformance-storybook/stories/TextField.stories.ts b/conformance-storybook/stories/TextField.stories.ts new file mode 100644 index 000000000..5bdf7c363 --- /dev/null +++ b/conformance-storybook/stories/TextField.stories.ts @@ -0,0 +1,17 @@ +import type { Meta, StoryObj } from "@storybook/web-components"; +import { renderA2UI, componentWithData } from "./helpers/a2ui-story-wrapper.js"; + +const meta: Meta = { title: "Components/TextField" }; +export default meta; + +export const ShortText: StoryObj = { + render: () => renderA2UI(componentWithData("tf-short", [ + { id: "tf1", component: "TextField", label: "Name", value: { path: "/form/name" }, variant: "shortText" }, + ], "/form", { name: "John Doe" })), +}; + +export const LongText: StoryObj = { + render: () => renderA2UI(componentWithData("tf-long", [ + { id: "tf1", component: "TextField", label: "Description", value: { path: "/form/desc" }, variant: "longText" }, + ], "/form", { desc: "A longer description..." })), +}; diff --git a/conformance-storybook/stories/Video.stories.ts b/conformance-storybook/stories/Video.stories.ts new file mode 100644 index 000000000..5c45f0ca9 --- /dev/null +++ b/conformance-storybook/stories/Video.stories.ts @@ -0,0 +1,11 @@ +import type { Meta, StoryObj } from "@storybook/web-components"; +import { renderA2UI, simpleComponent } from "./helpers/a2ui-story-wrapper.js"; + +const meta: Meta = { title: "Components/Video" }; +export default meta; + +export const Basic: StoryObj = { + render: () => renderA2UI(simpleComponent("video-basic", [ + { id: "v1", component: "Video", url: "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4" }, + ])), +}; diff --git a/conformance-storybook/stories/fixtures/button-variants.json b/conformance-storybook/stories/fixtures/button-variants.json new file mode 100644 index 000000000..76731096d --- /dev/null +++ b/conformance-storybook/stories/fixtures/button-variants.json @@ -0,0 +1,46 @@ +{ + "name": "Button Variants", + "description": "All button variant types", + "scenarios": [ + { + "name": "Primary", + "messages": [ + { "createSurface": { "surfaceId": "s1", "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" } }, + { "updateComponents": { "surfaceId": "s1", "components": [ + { "id": "root", "component": "Button", "child": "txt1", "variant": "primary", "action": { "event": { "name": "click" } } }, + { "id": "txt1", "component": "Text", "text": "Primary Button" } + ]}} + ] + }, + { + "name": "Outlined", + "messages": [ + { "createSurface": { "surfaceId": "s1", "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" } }, + { "updateComponents": { "surfaceId": "s1", "components": [ + { "id": "root", "component": "Button", "child": "txt1", "variant": "outlined", "action": { "event": { "name": "click" } } }, + { "id": "txt1", "component": "Text", "text": "Outlined Button" } + ]}} + ] + }, + { + "name": "Text", + "messages": [ + { "createSurface": { "surfaceId": "s1", "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" } }, + { "updateComponents": { "surfaceId": "s1", "components": [ + { "id": "root", "component": "Button", "child": "txt1", "variant": "text", "action": { "event": { "name": "click" } } }, + { "id": "txt1", "component": "Text", "text": "Text Button" } + ]}} + ] + }, + { + "name": "Icon", + "messages": [ + { "createSurface": { "surfaceId": "s1", "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" } }, + { "updateComponents": { "surfaceId": "s1", "components": [ + { "id": "root", "component": "Button", "child": "ico1", "variant": "icon", "action": { "event": { "name": "click" } } }, + { "id": "ico1", "component": "Icon", "name": "favorite" } + ]}} + ] + } + ] +} diff --git a/conformance-storybook/stories/fixtures/card-layouts.json b/conformance-storybook/stories/fixtures/card-layouts.json new file mode 100644 index 000000000..0e0924b4e --- /dev/null +++ b/conformance-storybook/stories/fixtures/card-layouts.json @@ -0,0 +1,42 @@ +{ + "name": "Card Layouts", + "description": "Card component with various layouts", + "scenarios": [ + { + "name": "Simple Card", + "messages": [ + { "createSurface": { "surfaceId": "s1", "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" } }, + { "updateComponents": { "surfaceId": "s1", "components": [ + { "id": "root", "component": "Card", "child": "txt1" }, + { "id": "txt1", "component": "Text", "text": "Simple card content" } + ]}} + ] + }, + { + "name": "Card with Header", + "messages": [ + { "createSurface": { "surfaceId": "s1", "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" } }, + { "updateComponents": { "surfaceId": "s1", "components": [ + { "id": "root", "component": "Card", "child": "col1" }, + { "id": "col1", "component": "Column", "children": ["header", "divider", "body"] }, + { "id": "header", "component": "Text", "text": "Card Title", "variant": "h2" }, + { "id": "divider", "component": "Divider", "axis": "horizontal" }, + { "id": "body", "component": "Text", "text": "Card body content goes here." } + ]}} + ] + }, + { + "name": "Nested Cards", + "messages": [ + { "createSurface": { "surfaceId": "s1", "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" } }, + { "updateComponents": { "surfaceId": "s1", "components": [ + { "id": "root", "component": "Card", "child": "col1" }, + { "id": "col1", "component": "Column", "children": ["title", "inner_card"] }, + { "id": "title", "component": "Text", "text": "Outer Card", "variant": "h2" }, + { "id": "inner_card", "component": "Card", "child": "inner_txt" }, + { "id": "inner_txt", "component": "Text", "text": "Inner card content" } + ]}} + ] + } + ] +} diff --git a/conformance-storybook/stories/fixtures/contact-form.json b/conformance-storybook/stories/fixtures/contact-form.json new file mode 100644 index 000000000..477c333d6 --- /dev/null +++ b/conformance-storybook/stories/fixtures/contact-form.json @@ -0,0 +1,84 @@ +{ + "name": "Contact Form", + "description": "Full integration test from spec test cases", + "scenarios": [ + { + "name": "Filled Form", + "messages": [ + { "createSurface": { "surfaceId": "contact_form_1", "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" } }, + { "updateComponents": { "surfaceId": "contact_form_1", "components": [ + { "id": "root", "component": "Card", "child": "form_container" }, + { "id": "form_container", "component": "Column", "children": ["header_row", "name_row", "email_group", "phone_group", "pref_group", "divider_1", "newsletter_checkbox", "submit_button"], "justify": "start", "align": "stretch" }, + { "id": "header_row", "component": "Row", "children": ["header_icon", "header_text"], "align": "center" }, + { "id": "header_icon", "component": "Icon", "name": "mail" }, + { "id": "header_text", "component": "Text", "text": "# Contact Us", "variant": "h2" }, + { "id": "name_row", "component": "Row", "children": ["first_name_group", "last_name_group"], "justify": "spaceBetween" }, + { "id": "first_name_group", "component": "Column", "children": ["first_name_label", "first_name_field"], "weight": 1 }, + { "id": "first_name_label", "component": "Text", "text": "First Name", "variant": "caption" }, + { "id": "first_name_field", "component": "TextField", "label": "First Name", "value": { "path": "/contact/firstName" }, "variant": "shortText" }, + { "id": "last_name_group", "component": "Column", "children": ["last_name_label", "last_name_field"], "weight": 1 }, + { "id": "last_name_label", "component": "Text", "text": "Last Name", "variant": "caption" }, + { "id": "last_name_field", "component": "TextField", "label": "Last Name", "value": { "path": "/contact/lastName" }, "variant": "shortText" }, + { "id": "email_group", "component": "Column", "children": ["email_label", "email_field"] }, + { "id": "email_label", "component": "Text", "text": "Email Address", "variant": "caption" }, + { "id": "email_field", "component": "TextField", "label": "Email", "value": { "path": "/contact/email" }, "variant": "shortText" }, + { "id": "phone_group", "component": "Column", "children": ["phone_label", "phone_field"] }, + { "id": "phone_label", "component": "Text", "text": "Phone Number", "variant": "caption" }, + { "id": "phone_field", "component": "TextField", "label": "Phone", "value": { "path": "/contact/phone" }, "variant": "shortText" }, + { "id": "pref_group", "component": "Column", "children": ["pref_label", "pref_picker"] }, + { "id": "pref_label", "component": "Text", "text": "Preferred Contact Method", "variant": "caption" }, + { "id": "pref_picker", "component": "ChoicePicker", "variant": "mutuallyExclusive", "options": [ + { "label": "Email", "value": "email" }, + { "label": "Phone", "value": "phone" }, + { "label": "SMS", "value": "sms" } + ], "value": { "path": "/contact/preference" } }, + { "id": "divider_1", "component": "Divider", "axis": "horizontal" }, + { "id": "newsletter_checkbox", "component": "CheckBox", "label": "Subscribe to our newsletter", "value": { "path": "/contact/subscribe" } }, + { "id": "submit_button", "component": "Button", "child": "submit_button_label", "variant": "primary", "action": { "event": { "name": "submitContactForm" } } }, + { "id": "submit_button_label", "component": "Text", "text": "Send Message" } + ]}}, + { "updateDataModel": { "surfaceId": "contact_form_1", "path": "/contact", "value": { + "firstName": "John", "lastName": "Doe", "email": "john.doe@example.com", + "phone": "1234567890", "preference": ["email"], "subscribe": true + }}} + ] + }, + { + "name": "Empty Form", + "messages": [ + { "createSurface": { "surfaceId": "contact_form_1", "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" } }, + { "updateComponents": { "surfaceId": "contact_form_1", "components": [ + { "id": "root", "component": "Card", "child": "form_container" }, + { "id": "form_container", "component": "Column", "children": ["header_row", "name_row", "email_group", "phone_group", "pref_group", "divider_1", "newsletter_checkbox", "submit_button"], "justify": "start", "align": "stretch" }, + { "id": "header_row", "component": "Row", "children": ["header_icon", "header_text"], "align": "center" }, + { "id": "header_icon", "component": "Icon", "name": "mail" }, + { "id": "header_text", "component": "Text", "text": "# Contact Us", "variant": "h2" }, + { "id": "name_row", "component": "Row", "children": ["first_name_group", "last_name_group"], "justify": "spaceBetween" }, + { "id": "first_name_group", "component": "Column", "children": ["first_name_label", "first_name_field"], "weight": 1 }, + { "id": "first_name_label", "component": "Text", "text": "First Name", "variant": "caption" }, + { "id": "first_name_field", "component": "TextField", "label": "First Name", "value": { "path": "/contact/firstName" }, "variant": "shortText" }, + { "id": "last_name_group", "component": "Column", "children": ["last_name_label", "last_name_field"], "weight": 1 }, + { "id": "last_name_label", "component": "Text", "text": "Last Name", "variant": "caption" }, + { "id": "last_name_field", "component": "TextField", "label": "Last Name", "value": { "path": "/contact/lastName" }, "variant": "shortText" }, + { "id": "email_group", "component": "Column", "children": ["email_label", "email_field"] }, + { "id": "email_label", "component": "Text", "text": "Email Address", "variant": "caption" }, + { "id": "email_field", "component": "TextField", "label": "Email", "value": { "path": "/contact/email" }, "variant": "shortText" }, + { "id": "phone_group", "component": "Column", "children": ["phone_label", "phone_field"] }, + { "id": "phone_label", "component": "Text", "text": "Phone Number", "variant": "caption" }, + { "id": "phone_field", "component": "TextField", "label": "Phone", "value": { "path": "/contact/phone" }, "variant": "shortText" }, + { "id": "pref_group", "component": "Column", "children": ["pref_label", "pref_picker"] }, + { "id": "pref_label", "component": "Text", "text": "Preferred Contact Method", "variant": "caption" }, + { "id": "pref_picker", "component": "ChoicePicker", "variant": "mutuallyExclusive", "options": [ + { "label": "Email", "value": "email" }, + { "label": "Phone", "value": "phone" }, + { "label": "SMS", "value": "sms" } + ], "value": { "path": "/contact/preference" } }, + { "id": "divider_1", "component": "Divider", "axis": "horizontal" }, + { "id": "newsletter_checkbox", "component": "CheckBox", "label": "Subscribe to our newsletter", "value": { "path": "/contact/subscribe" } }, + { "id": "submit_button", "component": "Button", "child": "submit_button_label", "variant": "primary", "action": { "event": { "name": "submitContactForm" } } }, + { "id": "submit_button_label", "component": "Text", "text": "Send Message" } + ]}} + ] + } + ] +} diff --git a/conformance-storybook/stories/fixtures/form-inputs.json b/conformance-storybook/stories/fixtures/form-inputs.json new file mode 100644 index 000000000..17deacc87 --- /dev/null +++ b/conformance-storybook/stories/fixtures/form-inputs.json @@ -0,0 +1,128 @@ +{ + "name": "Form Inputs", + "description": "TextField, CheckBox, Slider, DateTimeInput, ChoicePicker", + "scenarios": [ + { + "name": "TextField Short", + "messages": [ + { "createSurface": { "surfaceId": "s1", "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" } }, + { "updateComponents": { "surfaceId": "s1", "components": [ + { "id": "root", "component": "TextField", "label": "Name", "value": { "path": "/name" }, "variant": "shortText" } + ]}} + ] + }, + { + "name": "TextField Long", + "messages": [ + { "createSurface": { "surfaceId": "s1", "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" } }, + { "updateComponents": { "surfaceId": "s1", "components": [ + { "id": "root", "component": "TextField", "label": "Description", "value": { "path": "/desc" }, "variant": "longText" } + ]}} + ] + }, + { + "name": "CheckBox Unchecked", + "messages": [ + { "createSurface": { "surfaceId": "s1", "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" } }, + { "updateComponents": { "surfaceId": "s1", "components": [ + { "id": "root", "component": "CheckBox", "label": "Accept terms", "value": { "path": "/terms" } } + ]}} + ] + }, + { + "name": "CheckBox Checked", + "messages": [ + { "createSurface": { "surfaceId": "s1", "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" } }, + { "updateComponents": { "surfaceId": "s1", "components": [ + { "id": "root", "component": "CheckBox", "label": "Accept terms", "value": { "path": "/terms" } } + ]}}, + { "updateDataModel": { "surfaceId": "s1", "path": "/terms", "value": true } } + ] + }, + { + "name": "Slider Basic", + "messages": [ + { "createSurface": { "surfaceId": "s1", "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" } }, + { "updateComponents": { "surfaceId": "s1", "components": [ + { "id": "root", "component": "Slider", "label": "Volume", "value": { "path": "/volume" } } + ]}} + ] + }, + { + "name": "Slider Custom Range", + "messages": [ + { "createSurface": { "surfaceId": "s1", "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" } }, + { "updateComponents": { "surfaceId": "s1", "components": [ + { "id": "root", "component": "Slider", "label": "Temperature", "value": { "path": "/temp" }, "min": 0, "max": 100, "step": 5 } + ]}}, + { "updateDataModel": { "surfaceId": "s1", "path": "/temp", "value": 50 } } + ] + }, + { + "name": "DateTimeInput Date", + "messages": [ + { "createSurface": { "surfaceId": "s1", "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" } }, + { "updateComponents": { "surfaceId": "s1", "components": [ + { "id": "root", "component": "DateTimeInput", "label": "Birthday", "value": { "path": "/birthday" }, "variant": "date" } + ]}} + ] + }, + { + "name": "DateTimeInput Time", + "messages": [ + { "createSurface": { "surfaceId": "s1", "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" } }, + { "updateComponents": { "surfaceId": "s1", "components": [ + { "id": "root", "component": "DateTimeInput", "label": "Alarm", "value": { "path": "/alarm" }, "variant": "time" } + ]}} + ] + }, + { + "name": "DateTimeInput DateTime", + "messages": [ + { "createSurface": { "surfaceId": "s1", "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" } }, + { "updateComponents": { "surfaceId": "s1", "components": [ + { "id": "root", "component": "DateTimeInput", "label": "Meeting", "value": { "path": "/meeting" }, "variant": "dateTime" } + ]}} + ] + }, + { + "name": "ChoicePicker MutuallyExclusive", + "messages": [ + { "createSurface": { "surfaceId": "s1", "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" } }, + { "updateComponents": { "surfaceId": "s1", "components": [ + { "id": "root", "component": "ChoicePicker", "variant": "mutuallyExclusive", "options": [ + { "label": "Option A", "value": "a" }, + { "label": "Option B", "value": "b" }, + { "label": "Option C", "value": "c" } + ], "value": { "path": "/choice" } } + ]}} + ] + }, + { + "name": "ChoicePicker MultiSelect", + "messages": [ + { "createSurface": { "surfaceId": "s1", "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" } }, + { "updateComponents": { "surfaceId": "s1", "components": [ + { "id": "root", "component": "ChoicePicker", "variant": "multiSelect", "options": [ + { "label": "Red", "value": "red" }, + { "label": "Blue", "value": "blue" }, + { "label": "Green", "value": "green" } + ], "value": { "path": "/colors" } } + ]}} + ] + }, + { + "name": "ChoicePicker Chips", + "messages": [ + { "createSurface": { "surfaceId": "s1", "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" } }, + { "updateComponents": { "surfaceId": "s1", "components": [ + { "id": "root", "component": "ChoicePicker", "variant": "chips", "options": [ + { "label": "Small", "value": "s" }, + { "label": "Medium", "value": "m" }, + { "label": "Large", "value": "l" } + ], "value": { "path": "/size" } } + ]}} + ] + } + ] +} diff --git a/conformance-storybook/stories/fixtures/interactive.json b/conformance-storybook/stories/fixtures/interactive.json new file mode 100644 index 000000000..31add3d6d --- /dev/null +++ b/conformance-storybook/stories/fixtures/interactive.json @@ -0,0 +1,44 @@ +{ + "name": "Interactive Components", + "description": "Modal and List", + "scenarios": [ + { + "name": "Modal with Content", + "messages": [ + { "createSurface": { "surfaceId": "s1", "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" } }, + { "updateComponents": { "surfaceId": "s1", "components": [ + { "id": "root", "component": "Modal", "child": "content", "title": "Example Modal" }, + { "id": "content", "component": "Column", "children": ["msg", "btn1"] }, + { "id": "msg", "component": "Text", "text": "This is modal content." }, + { "id": "btn1", "component": "Button", "child": "btn_txt", "variant": "primary", "action": { "event": { "name": "close" } } }, + { "id": "btn_txt", "component": "Text", "text": "Close" } + ]}} + ] + }, + { + "name": "List Basic", + "messages": [ + { "createSurface": { "surfaceId": "s1", "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" } }, + { "updateComponents": { "surfaceId": "s1", "components": [ + { "id": "root", "component": "List", "children": ["item1", "item2", "item3"] }, + { "id": "item1", "component": "Text", "text": "Item 1" }, + { "id": "item2", "component": "Text", "text": "Item 2" }, + { "id": "item3", "component": "Text", "text": "Item 3" } + ]}} + ] + }, + { + "name": "List with Cards", + "messages": [ + { "createSurface": { "surfaceId": "s1", "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" } }, + { "updateComponents": { "surfaceId": "s1", "components": [ + { "id": "root", "component": "List", "children": ["card1", "card2"] }, + { "id": "card1", "component": "Card", "child": "c1txt" }, + { "id": "c1txt", "component": "Text", "text": "Card Item 1" }, + { "id": "card2", "component": "Card", "child": "c2txt" }, + { "id": "c2txt", "component": "Text", "text": "Card Item 2" } + ]}} + ] + } + ] +} diff --git a/conformance-storybook/stories/fixtures/layout.json b/conformance-storybook/stories/fixtures/layout.json new file mode 100644 index 000000000..dc96d0376 --- /dev/null +++ b/conformance-storybook/stories/fixtures/layout.json @@ -0,0 +1,76 @@ +{ + "name": "Layout Components", + "description": "Row, Column, Divider, and Tabs", + "scenarios": [ + { + "name": "Row Basic", + "messages": [ + { "createSurface": { "surfaceId": "s1", "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" } }, + { "updateComponents": { "surfaceId": "s1", "components": [ + { "id": "root", "component": "Row", "children": ["t1", "t2", "t3"] }, + { "id": "t1", "component": "Text", "text": "Left" }, + { "id": "t2", "component": "Text", "text": "Center" }, + { "id": "t3", "component": "Text", "text": "Right" } + ]}} + ] + }, + { + "name": "Row SpaceBetween", + "messages": [ + { "createSurface": { "surfaceId": "s1", "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" } }, + { "updateComponents": { "surfaceId": "s1", "components": [ + { "id": "root", "component": "Row", "children": ["t1", "t2"], "justify": "spaceBetween" }, + { "id": "t1", "component": "Text", "text": "Left" }, + { "id": "t2", "component": "Text", "text": "Right" } + ]}} + ] + }, + { + "name": "Column Basic", + "messages": [ + { "createSurface": { "surfaceId": "s1", "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" } }, + { "updateComponents": { "surfaceId": "s1", "components": [ + { "id": "root", "component": "Column", "children": ["t1", "t2", "t3"] }, + { "id": "t1", "component": "Text", "text": "First" }, + { "id": "t2", "component": "Text", "text": "Second" }, + { "id": "t3", "component": "Text", "text": "Third" } + ]}} + ] + }, + { + "name": "Column Aligned Center", + "messages": [ + { "createSurface": { "surfaceId": "s1", "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" } }, + { "updateComponents": { "surfaceId": "s1", "components": [ + { "id": "root", "component": "Column", "children": ["t1", "t2"], "align": "center" }, + { "id": "t1", "component": "Text", "text": "Centered" }, + { "id": "t2", "component": "Text", "text": "Content" } + ]}} + ] + }, + { + "name": "Divider", + "messages": [ + { "createSurface": { "surfaceId": "s1", "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" } }, + { "updateComponents": { "surfaceId": "s1", "components": [ + { "id": "root", "component": "Column", "children": ["t1", "div1", "t2"] }, + { "id": "t1", "component": "Text", "text": "Above divider" }, + { "id": "div1", "component": "Divider", "axis": "horizontal" }, + { "id": "t2", "component": "Text", "text": "Below divider" } + ]}} + ] + }, + { + "name": "Tabs", + "messages": [ + { "createSurface": { "surfaceId": "s1", "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" } }, + { "updateComponents": { "surfaceId": "s1", "components": [ + { "id": "root", "component": "Tabs", "children": ["tab1", "tab2", "tab3"], "labels": ["Tab A", "Tab B", "Tab C"] }, + { "id": "tab1", "component": "Text", "text": "Content of Tab A" }, + { "id": "tab2", "component": "Text", "text": "Content of Tab B" }, + { "id": "tab3", "component": "Text", "text": "Content of Tab C" } + ]}} + ] + } + ] +} diff --git a/conformance-storybook/stories/fixtures/manifest.json b/conformance-storybook/stories/fixtures/manifest.json new file mode 100644 index 000000000..88d16b861 --- /dev/null +++ b/conformance-storybook/stories/fixtures/manifest.json @@ -0,0 +1,16 @@ +{ + "fixtures": [ + { "file": "text-variants.json", "category": "Components/Text" }, + { "file": "button-variants.json", "category": "Components/Button" }, + { "file": "card-layouts.json", "category": "Components/Card" }, + { "file": "layout.json", "category": "Components/Layout" }, + { "file": "form-inputs.json", "category": "Components/Form Inputs" }, + { "file": "media.json", "category": "Components/Media" }, + { "file": "interactive.json", "category": "Components/Interactive" }, + { "file": "contact-form.json", "category": "Integration/Contact Form" } + ], + "renderers": [ + { "id": "lit-v08", "label": "v0.8 Lit", "translate": "v08" } + ], + "versions": ["v0.8", "v0.10"] +} diff --git a/conformance-storybook/stories/fixtures/media.json b/conformance-storybook/stories/fixtures/media.json new file mode 100644 index 000000000..230f59f96 --- /dev/null +++ b/conformance-storybook/stories/fixtures/media.json @@ -0,0 +1,64 @@ +{ + "name": "Media Components", + "description": "Image, Video, AudioPlayer, Icon", + "scenarios": [ + { + "name": "Image Basic", + "messages": [ + { "createSurface": { "surfaceId": "s1", "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" } }, + { "updateComponents": { "surfaceId": "s1", "components": [ + { "id": "root", "component": "Image", "url": "https://picsum.photos/400/300", "alt": "Sample image" } + ]}} + ] + }, + { + "name": "Image Cover Fit", + "messages": [ + { "createSurface": { "surfaceId": "s1", "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" } }, + { "updateComponents": { "surfaceId": "s1", "components": [ + { "id": "root", "component": "Image", "url": "https://picsum.photos/800/400", "alt": "Wide image", "fit": "cover" } + ]}} + ] + }, + { + "name": "Icon Single", + "messages": [ + { "createSurface": { "surfaceId": "s1", "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" } }, + { "updateComponents": { "surfaceId": "s1", "components": [ + { "id": "root", "component": "Icon", "name": "favorite" } + ]}} + ] + }, + { + "name": "Icon Row", + "messages": [ + { "createSurface": { "surfaceId": "s1", "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" } }, + { "updateComponents": { "surfaceId": "s1", "components": [ + { "id": "root", "component": "Row", "children": ["i1", "i2", "i3", "i4"] }, + { "id": "i1", "component": "Icon", "name": "home" }, + { "id": "i2", "component": "Icon", "name": "settings" }, + { "id": "i3", "component": "Icon", "name": "favorite" }, + { "id": "i4", "component": "Icon", "name": "search" } + ]}} + ] + }, + { + "name": "Video Basic", + "messages": [ + { "createSurface": { "surfaceId": "s1", "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" } }, + { "updateComponents": { "surfaceId": "s1", "components": [ + { "id": "root", "component": "Video", "url": "https://www.w3schools.com/html/mov_bbb.mp4" } + ]}} + ] + }, + { + "name": "AudioPlayer Basic", + "messages": [ + { "createSurface": { "surfaceId": "s1", "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" } }, + { "updateComponents": { "surfaceId": "s1", "components": [ + { "id": "root", "component": "AudioPlayer", "url": "https://www.w3schools.com/html/horse.mp3", "title": "Horse Sound" } + ]}} + ] + } + ] +} diff --git a/conformance-storybook/stories/fixtures/text-variants.json b/conformance-storybook/stories/fixtures/text-variants.json new file mode 100644 index 000000000..46e9bb392 --- /dev/null +++ b/conformance-storybook/stories/fixtures/text-variants.json @@ -0,0 +1,51 @@ +{ + "name": "Text Variants", + "description": "All text variant types", + "scenarios": [ + { + "name": "Heading 1", + "messages": [ + { "createSurface": { "surfaceId": "s1", "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" } }, + { "updateComponents": { "surfaceId": "s1", "components": [ + { "id": "root", "component": "Text", "text": "Heading 1", "variant": "h1" } + ]}} + ] + }, + { + "name": "Heading 2", + "messages": [ + { "createSurface": { "surfaceId": "s1", "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" } }, + { "updateComponents": { "surfaceId": "s1", "components": [ + { "id": "root", "component": "Text", "text": "Heading 2", "variant": "h2" } + ]}} + ] + }, + { + "name": "Heading 3", + "messages": [ + { "createSurface": { "surfaceId": "s1", "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" } }, + { "updateComponents": { "surfaceId": "s1", "components": [ + { "id": "root", "component": "Text", "text": "Heading 3", "variant": "h3" } + ]}} + ] + }, + { + "name": "Body", + "messages": [ + { "createSurface": { "surfaceId": "s1", "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" } }, + { "updateComponents": { "surfaceId": "s1", "components": [ + { "id": "root", "component": "Text", "text": "This is body text with normal styling.", "variant": "body" } + ]}} + ] + }, + { + "name": "Caption", + "messages": [ + { "createSurface": { "surfaceId": "s1", "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" } }, + { "updateComponents": { "surfaceId": "s1", "components": [ + { "id": "root", "component": "Text", "text": "Caption text", "variant": "caption" } + ]}} + ] + } + ] +} diff --git a/conformance-storybook/stories/generated/button-variants.stories.ts b/conformance-storybook/stories/generated/button-variants.stories.ts new file mode 100644 index 000000000..60c16f3bc --- /dev/null +++ b/conformance-storybook/stories/generated/button-variants.stories.ts @@ -0,0 +1,157 @@ +// AUTO-GENERATED — do not edit. Run: node scripts/generate-stories.mjs +import type { Meta, StoryObj } from "@storybook/web-components"; +import { renderA2UI } from "../helpers/a2ui-story-wrapper.js"; +import { translateToV08 } from "../helpers/version-adapter.js"; +import type { V010Message } from "../helpers/version-adapter.js"; + +const meta: Meta = { title: "Generated/Components/Button" }; +export default meta; + +const Primary_messages: V010Message[] = [ + { + "createSurface": { + "surfaceId": "s1", + "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" + } + }, + { + "updateComponents": { + "surfaceId": "s1", + "components": [ + { + "id": "root", + "component": "Button", + "child": "txt1", + "variant": "primary", + "action": { + "event": { + "name": "click" + } + } + }, + { + "id": "txt1", + "component": "Text", + "text": "Primary Button" + } + ] + } + } +]; + +export const Primary_v08_Lit: StoryObj = { + name: "Primary [v0.8 Lit]", + render: () => renderA2UI(translateToV08(Primary_messages), "s1"), +}; + +const Outlined_messages: V010Message[] = [ + { + "createSurface": { + "surfaceId": "s1", + "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" + } + }, + { + "updateComponents": { + "surfaceId": "s1", + "components": [ + { + "id": "root", + "component": "Button", + "child": "txt1", + "variant": "outlined", + "action": { + "event": { + "name": "click" + } + } + }, + { + "id": "txt1", + "component": "Text", + "text": "Outlined Button" + } + ] + } + } +]; + +export const Outlined_v08_Lit: StoryObj = { + name: "Outlined [v0.8 Lit]", + render: () => renderA2UI(translateToV08(Outlined_messages), "s1"), +}; + +const Text_messages: V010Message[] = [ + { + "createSurface": { + "surfaceId": "s1", + "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" + } + }, + { + "updateComponents": { + "surfaceId": "s1", + "components": [ + { + "id": "root", + "component": "Button", + "child": "txt1", + "variant": "text", + "action": { + "event": { + "name": "click" + } + } + }, + { + "id": "txt1", + "component": "Text", + "text": "Text Button" + } + ] + } + } +]; + +export const Text_v08_Lit: StoryObj = { + name: "Text [v0.8 Lit]", + render: () => renderA2UI(translateToV08(Text_messages), "s1"), +}; + +const Icon_messages: V010Message[] = [ + { + "createSurface": { + "surfaceId": "s1", + "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" + } + }, + { + "updateComponents": { + "surfaceId": "s1", + "components": [ + { + "id": "root", + "component": "Button", + "child": "ico1", + "variant": "icon", + "action": { + "event": { + "name": "click" + } + } + }, + { + "id": "ico1", + "component": "Icon", + "name": "favorite" + } + ] + } + } +]; + +export const Icon_v08_Lit: StoryObj = { + name: "Icon [v0.8 Lit]", + render: () => renderA2UI(translateToV08(Icon_messages), "s1"), +}; + diff --git a/conformance-storybook/stories/generated/card-layouts.stories.ts b/conformance-storybook/stories/generated/card-layouts.stories.ts new file mode 100644 index 000000000..9a021b076 --- /dev/null +++ b/conformance-storybook/stories/generated/card-layouts.stories.ts @@ -0,0 +1,141 @@ +// AUTO-GENERATED — do not edit. Run: node scripts/generate-stories.mjs +import type { Meta, StoryObj } from "@storybook/web-components"; +import { renderA2UI } from "../helpers/a2ui-story-wrapper.js"; +import { translateToV08 } from "../helpers/version-adapter.js"; +import type { V010Message } from "../helpers/version-adapter.js"; + +const meta: Meta = { title: "Generated/Components/Card" }; +export default meta; + +const Simple_Card_messages: V010Message[] = [ + { + "createSurface": { + "surfaceId": "s1", + "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" + } + }, + { + "updateComponents": { + "surfaceId": "s1", + "components": [ + { + "id": "root", + "component": "Card", + "child": "txt1" + }, + { + "id": "txt1", + "component": "Text", + "text": "Simple card content" + } + ] + } + } +]; + +export const Simple_Card_v08_Lit: StoryObj = { + name: "Simple Card [v0.8 Lit]", + render: () => renderA2UI(translateToV08(Simple_Card_messages), "s1"), +}; + +const Card_with_Header_messages: V010Message[] = [ + { + "createSurface": { + "surfaceId": "s1", + "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" + } + }, + { + "updateComponents": { + "surfaceId": "s1", + "components": [ + { + "id": "root", + "component": "Card", + "child": "col1" + }, + { + "id": "col1", + "component": "Column", + "children": [ + "header", + "divider", + "body" + ] + }, + { + "id": "header", + "component": "Text", + "text": "Card Title", + "variant": "h2" + }, + { + "id": "divider", + "component": "Divider", + "axis": "horizontal" + }, + { + "id": "body", + "component": "Text", + "text": "Card body content goes here." + } + ] + } + } +]; + +export const Card_with_Header_v08_Lit: StoryObj = { + name: "Card with Header [v0.8 Lit]", + render: () => renderA2UI(translateToV08(Card_with_Header_messages), "s1"), +}; + +const Nested_Cards_messages: V010Message[] = [ + { + "createSurface": { + "surfaceId": "s1", + "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" + } + }, + { + "updateComponents": { + "surfaceId": "s1", + "components": [ + { + "id": "root", + "component": "Card", + "child": "col1" + }, + { + "id": "col1", + "component": "Column", + "children": [ + "title", + "inner_card" + ] + }, + { + "id": "title", + "component": "Text", + "text": "Outer Card", + "variant": "h2" + }, + { + "id": "inner_card", + "component": "Card", + "child": "inner_txt" + }, + { + "id": "inner_txt", + "component": "Text", + "text": "Inner card content" + } + ] + } + } +]; + +export const Nested_Cards_v08_Lit: StoryObj = { + name: "Nested Cards [v0.8 Lit]", + render: () => renderA2UI(translateToV08(Nested_Cards_messages), "s1"), +}; + diff --git a/conformance-storybook/stories/generated/contact-form.stories.ts b/conformance-storybook/stories/generated/contact-form.stories.ts new file mode 100644 index 000000000..dc0758c0b --- /dev/null +++ b/conformance-storybook/stories/generated/contact-form.stories.ts @@ -0,0 +1,485 @@ +// AUTO-GENERATED — do not edit. Run: node scripts/generate-stories.mjs +import type { Meta, StoryObj } from "@storybook/web-components"; +import { renderA2UI } from "../helpers/a2ui-story-wrapper.js"; +import { translateToV08 } from "../helpers/version-adapter.js"; +import type { V010Message } from "../helpers/version-adapter.js"; + +const meta: Meta = { title: "Generated/Integration/Contact Form" }; +export default meta; + +const Filled_Form_messages: V010Message[] = [ + { + "createSurface": { + "surfaceId": "contact_form_1", + "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" + } + }, + { + "updateComponents": { + "surfaceId": "contact_form_1", + "components": [ + { + "id": "root", + "component": "Card", + "child": "form_container" + }, + { + "id": "form_container", + "component": "Column", + "children": [ + "header_row", + "name_row", + "email_group", + "phone_group", + "pref_group", + "divider_1", + "newsletter_checkbox", + "submit_button" + ], + "justify": "start", + "align": "stretch" + }, + { + "id": "header_row", + "component": "Row", + "children": [ + "header_icon", + "header_text" + ], + "align": "center" + }, + { + "id": "header_icon", + "component": "Icon", + "name": "mail" + }, + { + "id": "header_text", + "component": "Text", + "text": "# Contact Us", + "variant": "h2" + }, + { + "id": "name_row", + "component": "Row", + "children": [ + "first_name_group", + "last_name_group" + ], + "justify": "spaceBetween" + }, + { + "id": "first_name_group", + "component": "Column", + "children": [ + "first_name_label", + "first_name_field" + ], + "weight": 1 + }, + { + "id": "first_name_label", + "component": "Text", + "text": "First Name", + "variant": "caption" + }, + { + "id": "first_name_field", + "component": "TextField", + "label": "First Name", + "value": { + "path": "/contact/firstName" + }, + "variant": "shortText" + }, + { + "id": "last_name_group", + "component": "Column", + "children": [ + "last_name_label", + "last_name_field" + ], + "weight": 1 + }, + { + "id": "last_name_label", + "component": "Text", + "text": "Last Name", + "variant": "caption" + }, + { + "id": "last_name_field", + "component": "TextField", + "label": "Last Name", + "value": { + "path": "/contact/lastName" + }, + "variant": "shortText" + }, + { + "id": "email_group", + "component": "Column", + "children": [ + "email_label", + "email_field" + ] + }, + { + "id": "email_label", + "component": "Text", + "text": "Email Address", + "variant": "caption" + }, + { + "id": "email_field", + "component": "TextField", + "label": "Email", + "value": { + "path": "/contact/email" + }, + "variant": "shortText" + }, + { + "id": "phone_group", + "component": "Column", + "children": [ + "phone_label", + "phone_field" + ] + }, + { + "id": "phone_label", + "component": "Text", + "text": "Phone Number", + "variant": "caption" + }, + { + "id": "phone_field", + "component": "TextField", + "label": "Phone", + "value": { + "path": "/contact/phone" + }, + "variant": "shortText" + }, + { + "id": "pref_group", + "component": "Column", + "children": [ + "pref_label", + "pref_picker" + ] + }, + { + "id": "pref_label", + "component": "Text", + "text": "Preferred Contact Method", + "variant": "caption" + }, + { + "id": "pref_picker", + "component": "ChoicePicker", + "variant": "mutuallyExclusive", + "options": [ + { + "label": "Email", + "value": "email" + }, + { + "label": "Phone", + "value": "phone" + }, + { + "label": "SMS", + "value": "sms" + } + ], + "value": { + "path": "/contact/preference" + } + }, + { + "id": "divider_1", + "component": "Divider", + "axis": "horizontal" + }, + { + "id": "newsletter_checkbox", + "component": "CheckBox", + "label": "Subscribe to our newsletter", + "value": { + "path": "/contact/subscribe" + } + }, + { + "id": "submit_button", + "component": "Button", + "child": "submit_button_label", + "variant": "primary", + "action": { + "event": { + "name": "submitContactForm" + } + } + }, + { + "id": "submit_button_label", + "component": "Text", + "text": "Send Message" + } + ] + } + }, + { + "updateDataModel": { + "surfaceId": "contact_form_1", + "path": "/contact", + "value": { + "firstName": "John", + "lastName": "Doe", + "email": "john.doe@example.com", + "phone": "1234567890", + "preference": [ + "email" + ], + "subscribe": true + } + } + } +]; + +export const Filled_Form_v08_Lit: StoryObj = { + name: "Filled Form [v0.8 Lit]", + render: () => renderA2UI(translateToV08(Filled_Form_messages), "contact_form_1"), +}; + +const Empty_Form_messages: V010Message[] = [ + { + "createSurface": { + "surfaceId": "contact_form_1", + "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" + } + }, + { + "updateComponents": { + "surfaceId": "contact_form_1", + "components": [ + { + "id": "root", + "component": "Card", + "child": "form_container" + }, + { + "id": "form_container", + "component": "Column", + "children": [ + "header_row", + "name_row", + "email_group", + "phone_group", + "pref_group", + "divider_1", + "newsletter_checkbox", + "submit_button" + ], + "justify": "start", + "align": "stretch" + }, + { + "id": "header_row", + "component": "Row", + "children": [ + "header_icon", + "header_text" + ], + "align": "center" + }, + { + "id": "header_icon", + "component": "Icon", + "name": "mail" + }, + { + "id": "header_text", + "component": "Text", + "text": "# Contact Us", + "variant": "h2" + }, + { + "id": "name_row", + "component": "Row", + "children": [ + "first_name_group", + "last_name_group" + ], + "justify": "spaceBetween" + }, + { + "id": "first_name_group", + "component": "Column", + "children": [ + "first_name_label", + "first_name_field" + ], + "weight": 1 + }, + { + "id": "first_name_label", + "component": "Text", + "text": "First Name", + "variant": "caption" + }, + { + "id": "first_name_field", + "component": "TextField", + "label": "First Name", + "value": { + "path": "/contact/firstName" + }, + "variant": "shortText" + }, + { + "id": "last_name_group", + "component": "Column", + "children": [ + "last_name_label", + "last_name_field" + ], + "weight": 1 + }, + { + "id": "last_name_label", + "component": "Text", + "text": "Last Name", + "variant": "caption" + }, + { + "id": "last_name_field", + "component": "TextField", + "label": "Last Name", + "value": { + "path": "/contact/lastName" + }, + "variant": "shortText" + }, + { + "id": "email_group", + "component": "Column", + "children": [ + "email_label", + "email_field" + ] + }, + { + "id": "email_label", + "component": "Text", + "text": "Email Address", + "variant": "caption" + }, + { + "id": "email_field", + "component": "TextField", + "label": "Email", + "value": { + "path": "/contact/email" + }, + "variant": "shortText" + }, + { + "id": "phone_group", + "component": "Column", + "children": [ + "phone_label", + "phone_field" + ] + }, + { + "id": "phone_label", + "component": "Text", + "text": "Phone Number", + "variant": "caption" + }, + { + "id": "phone_field", + "component": "TextField", + "label": "Phone", + "value": { + "path": "/contact/phone" + }, + "variant": "shortText" + }, + { + "id": "pref_group", + "component": "Column", + "children": [ + "pref_label", + "pref_picker" + ] + }, + { + "id": "pref_label", + "component": "Text", + "text": "Preferred Contact Method", + "variant": "caption" + }, + { + "id": "pref_picker", + "component": "ChoicePicker", + "variant": "mutuallyExclusive", + "options": [ + { + "label": "Email", + "value": "email" + }, + { + "label": "Phone", + "value": "phone" + }, + { + "label": "SMS", + "value": "sms" + } + ], + "value": { + "path": "/contact/preference" + } + }, + { + "id": "divider_1", + "component": "Divider", + "axis": "horizontal" + }, + { + "id": "newsletter_checkbox", + "component": "CheckBox", + "label": "Subscribe to our newsletter", + "value": { + "path": "/contact/subscribe" + } + }, + { + "id": "submit_button", + "component": "Button", + "child": "submit_button_label", + "variant": "primary", + "action": { + "event": { + "name": "submitContactForm" + } + } + }, + { + "id": "submit_button_label", + "component": "Text", + "text": "Send Message" + } + ] + } + } +]; + +export const Empty_Form_v08_Lit: StoryObj = { + name: "Empty Form [v0.8 Lit]", + render: () => renderA2UI(translateToV08(Empty_Form_messages), "contact_form_1"), +}; + diff --git a/conformance-storybook/stories/generated/form-inputs.stories.ts b/conformance-storybook/stories/generated/form-inputs.stories.ts new file mode 100644 index 000000000..ecb3c1054 --- /dev/null +++ b/conformance-storybook/stories/generated/form-inputs.stories.ts @@ -0,0 +1,421 @@ +// AUTO-GENERATED — do not edit. Run: node scripts/generate-stories.mjs +import type { Meta, StoryObj } from "@storybook/web-components"; +import { renderA2UI } from "../helpers/a2ui-story-wrapper.js"; +import { translateToV08 } from "../helpers/version-adapter.js"; +import type { V010Message } from "../helpers/version-adapter.js"; + +const meta: Meta = { title: "Generated/Components/Form Inputs" }; +export default meta; + +const TextField_Short_messages: V010Message[] = [ + { + "createSurface": { + "surfaceId": "s1", + "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" + } + }, + { + "updateComponents": { + "surfaceId": "s1", + "components": [ + { + "id": "root", + "component": "TextField", + "label": "Name", + "value": { + "path": "/name" + }, + "variant": "shortText" + } + ] + } + } +]; + +export const TextField_Short_v08_Lit: StoryObj = { + name: "TextField Short [v0.8 Lit]", + render: () => renderA2UI(translateToV08(TextField_Short_messages), "s1"), +}; + +const TextField_Long_messages: V010Message[] = [ + { + "createSurface": { + "surfaceId": "s1", + "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" + } + }, + { + "updateComponents": { + "surfaceId": "s1", + "components": [ + { + "id": "root", + "component": "TextField", + "label": "Description", + "value": { + "path": "/desc" + }, + "variant": "longText" + } + ] + } + } +]; + +export const TextField_Long_v08_Lit: StoryObj = { + name: "TextField Long [v0.8 Lit]", + render: () => renderA2UI(translateToV08(TextField_Long_messages), "s1"), +}; + +const CheckBox_Unchecked_messages: V010Message[] = [ + { + "createSurface": { + "surfaceId": "s1", + "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" + } + }, + { + "updateComponents": { + "surfaceId": "s1", + "components": [ + { + "id": "root", + "component": "CheckBox", + "label": "Accept terms", + "value": { + "path": "/terms" + } + } + ] + } + } +]; + +export const CheckBox_Unchecked_v08_Lit: StoryObj = { + name: "CheckBox Unchecked [v0.8 Lit]", + render: () => renderA2UI(translateToV08(CheckBox_Unchecked_messages), "s1"), +}; + +const CheckBox_Checked_messages: V010Message[] = [ + { + "createSurface": { + "surfaceId": "s1", + "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" + } + }, + { + "updateComponents": { + "surfaceId": "s1", + "components": [ + { + "id": "root", + "component": "CheckBox", + "label": "Accept terms", + "value": { + "path": "/terms" + } + } + ] + } + }, + { + "updateDataModel": { + "surfaceId": "s1", + "path": "/terms", + "value": true + } + } +]; + +export const CheckBox_Checked_v08_Lit: StoryObj = { + name: "CheckBox Checked [v0.8 Lit]", + render: () => renderA2UI(translateToV08(CheckBox_Checked_messages), "s1"), +}; + +const Slider_Basic_messages: V010Message[] = [ + { + "createSurface": { + "surfaceId": "s1", + "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" + } + }, + { + "updateComponents": { + "surfaceId": "s1", + "components": [ + { + "id": "root", + "component": "Slider", + "label": "Volume", + "value": { + "path": "/volume" + } + } + ] + } + } +]; + +export const Slider_Basic_v08_Lit: StoryObj = { + name: "Slider Basic [v0.8 Lit]", + render: () => renderA2UI(translateToV08(Slider_Basic_messages), "s1"), +}; + +const Slider_Custom_Range_messages: V010Message[] = [ + { + "createSurface": { + "surfaceId": "s1", + "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" + } + }, + { + "updateComponents": { + "surfaceId": "s1", + "components": [ + { + "id": "root", + "component": "Slider", + "label": "Temperature", + "value": { + "path": "/temp" + }, + "min": 0, + "max": 100, + "step": 5 + } + ] + } + }, + { + "updateDataModel": { + "surfaceId": "s1", + "path": "/temp", + "value": 50 + } + } +]; + +export const Slider_Custom_Range_v08_Lit: StoryObj = { + name: "Slider Custom Range [v0.8 Lit]", + render: () => renderA2UI(translateToV08(Slider_Custom_Range_messages), "s1"), +}; + +const DateTimeInput_Date_messages: V010Message[] = [ + { + "createSurface": { + "surfaceId": "s1", + "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" + } + }, + { + "updateComponents": { + "surfaceId": "s1", + "components": [ + { + "id": "root", + "component": "DateTimeInput", + "label": "Birthday", + "value": { + "path": "/birthday" + }, + "variant": "date" + } + ] + } + } +]; + +export const DateTimeInput_Date_v08_Lit: StoryObj = { + name: "DateTimeInput Date [v0.8 Lit]", + render: () => renderA2UI(translateToV08(DateTimeInput_Date_messages), "s1"), +}; + +const DateTimeInput_Time_messages: V010Message[] = [ + { + "createSurface": { + "surfaceId": "s1", + "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" + } + }, + { + "updateComponents": { + "surfaceId": "s1", + "components": [ + { + "id": "root", + "component": "DateTimeInput", + "label": "Alarm", + "value": { + "path": "/alarm" + }, + "variant": "time" + } + ] + } + } +]; + +export const DateTimeInput_Time_v08_Lit: StoryObj = { + name: "DateTimeInput Time [v0.8 Lit]", + render: () => renderA2UI(translateToV08(DateTimeInput_Time_messages), "s1"), +}; + +const DateTimeInput_DateTime_messages: V010Message[] = [ + { + "createSurface": { + "surfaceId": "s1", + "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" + } + }, + { + "updateComponents": { + "surfaceId": "s1", + "components": [ + { + "id": "root", + "component": "DateTimeInput", + "label": "Meeting", + "value": { + "path": "/meeting" + }, + "variant": "dateTime" + } + ] + } + } +]; + +export const DateTimeInput_DateTime_v08_Lit: StoryObj = { + name: "DateTimeInput DateTime [v0.8 Lit]", + render: () => renderA2UI(translateToV08(DateTimeInput_DateTime_messages), "s1"), +}; + +const ChoicePicker_MutuallyExclusive_messages: V010Message[] = [ + { + "createSurface": { + "surfaceId": "s1", + "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" + } + }, + { + "updateComponents": { + "surfaceId": "s1", + "components": [ + { + "id": "root", + "component": "ChoicePicker", + "variant": "mutuallyExclusive", + "options": [ + { + "label": "Option A", + "value": "a" + }, + { + "label": "Option B", + "value": "b" + }, + { + "label": "Option C", + "value": "c" + } + ], + "value": { + "path": "/choice" + } + } + ] + } + } +]; + +export const ChoicePicker_MutuallyExclusive_v08_Lit: StoryObj = { + name: "ChoicePicker MutuallyExclusive [v0.8 Lit]", + render: () => renderA2UI(translateToV08(ChoicePicker_MutuallyExclusive_messages), "s1"), +}; + +const ChoicePicker_MultiSelect_messages: V010Message[] = [ + { + "createSurface": { + "surfaceId": "s1", + "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" + } + }, + { + "updateComponents": { + "surfaceId": "s1", + "components": [ + { + "id": "root", + "component": "ChoicePicker", + "variant": "multiSelect", + "options": [ + { + "label": "Red", + "value": "red" + }, + { + "label": "Blue", + "value": "blue" + }, + { + "label": "Green", + "value": "green" + } + ], + "value": { + "path": "/colors" + } + } + ] + } + } +]; + +export const ChoicePicker_MultiSelect_v08_Lit: StoryObj = { + name: "ChoicePicker MultiSelect [v0.8 Lit]", + render: () => renderA2UI(translateToV08(ChoicePicker_MultiSelect_messages), "s1"), +}; + +const ChoicePicker_Chips_messages: V010Message[] = [ + { + "createSurface": { + "surfaceId": "s1", + "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" + } + }, + { + "updateComponents": { + "surfaceId": "s1", + "components": [ + { + "id": "root", + "component": "ChoicePicker", + "variant": "chips", + "options": [ + { + "label": "Small", + "value": "s" + }, + { + "label": "Medium", + "value": "m" + }, + { + "label": "Large", + "value": "l" + } + ], + "value": { + "path": "/size" + } + } + ] + } + } +]; + +export const ChoicePicker_Chips_v08_Lit: StoryObj = { + name: "ChoicePicker Chips [v0.8 Lit]", + render: () => renderA2UI(translateToV08(ChoicePicker_Chips_messages), "s1"), +}; + diff --git a/conformance-storybook/stories/generated/interactive.stories.ts b/conformance-storybook/stories/generated/interactive.stories.ts new file mode 100644 index 000000000..4e00b2ad1 --- /dev/null +++ b/conformance-storybook/stories/generated/interactive.stories.ts @@ -0,0 +1,159 @@ +// AUTO-GENERATED — do not edit. Run: node scripts/generate-stories.mjs +import type { Meta, StoryObj } from "@storybook/web-components"; +import { renderA2UI } from "../helpers/a2ui-story-wrapper.js"; +import { translateToV08 } from "../helpers/version-adapter.js"; +import type { V010Message } from "../helpers/version-adapter.js"; + +const meta: Meta = { title: "Generated/Components/Interactive" }; +export default meta; + +const Modal_with_Content_messages: V010Message[] = [ + { + "createSurface": { + "surfaceId": "s1", + "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" + } + }, + { + "updateComponents": { + "surfaceId": "s1", + "components": [ + { + "id": "root", + "component": "Modal", + "child": "content", + "title": "Example Modal" + }, + { + "id": "content", + "component": "Column", + "children": [ + "msg", + "btn1" + ] + }, + { + "id": "msg", + "component": "Text", + "text": "This is modal content." + }, + { + "id": "btn1", + "component": "Button", + "child": "btn_txt", + "variant": "primary", + "action": { + "event": { + "name": "close" + } + } + }, + { + "id": "btn_txt", + "component": "Text", + "text": "Close" + } + ] + } + } +]; + +export const Modal_with_Content_v08_Lit: StoryObj = { + name: "Modal with Content [v0.8 Lit]", + render: () => renderA2UI(translateToV08(Modal_with_Content_messages), "s1"), +}; + +const List_Basic_messages: V010Message[] = [ + { + "createSurface": { + "surfaceId": "s1", + "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" + } + }, + { + "updateComponents": { + "surfaceId": "s1", + "components": [ + { + "id": "root", + "component": "List", + "children": [ + "item1", + "item2", + "item3" + ] + }, + { + "id": "item1", + "component": "Text", + "text": "Item 1" + }, + { + "id": "item2", + "component": "Text", + "text": "Item 2" + }, + { + "id": "item3", + "component": "Text", + "text": "Item 3" + } + ] + } + } +]; + +export const List_Basic_v08_Lit: StoryObj = { + name: "List Basic [v0.8 Lit]", + render: () => renderA2UI(translateToV08(List_Basic_messages), "s1"), +}; + +const List_with_Cards_messages: V010Message[] = [ + { + "createSurface": { + "surfaceId": "s1", + "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" + } + }, + { + "updateComponents": { + "surfaceId": "s1", + "components": [ + { + "id": "root", + "component": "List", + "children": [ + "card1", + "card2" + ] + }, + { + "id": "card1", + "component": "Card", + "child": "c1txt" + }, + { + "id": "c1txt", + "component": "Text", + "text": "Card Item 1" + }, + { + "id": "card2", + "component": "Card", + "child": "c2txt" + }, + { + "id": "c2txt", + "component": "Text", + "text": "Card Item 2" + } + ] + } + } +]; + +export const List_with_Cards_v08_Lit: StoryObj = { + name: "List with Cards [v0.8 Lit]", + render: () => renderA2UI(translateToV08(List_with_Cards_messages), "s1"), +}; + diff --git a/conformance-storybook/stories/generated/layout.stories.ts b/conformance-storybook/stories/generated/layout.stories.ts new file mode 100644 index 000000000..761e4be8b --- /dev/null +++ b/conformance-storybook/stories/generated/layout.stories.ts @@ -0,0 +1,274 @@ +// AUTO-GENERATED — do not edit. Run: node scripts/generate-stories.mjs +import type { Meta, StoryObj } from "@storybook/web-components"; +import { renderA2UI } from "../helpers/a2ui-story-wrapper.js"; +import { translateToV08 } from "../helpers/version-adapter.js"; +import type { V010Message } from "../helpers/version-adapter.js"; + +const meta: Meta = { title: "Generated/Components/Layout" }; +export default meta; + +const Row_Basic_messages: V010Message[] = [ + { + "createSurface": { + "surfaceId": "s1", + "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" + } + }, + { + "updateComponents": { + "surfaceId": "s1", + "components": [ + { + "id": "root", + "component": "Row", + "children": [ + "t1", + "t2", + "t3" + ] + }, + { + "id": "t1", + "component": "Text", + "text": "Left" + }, + { + "id": "t2", + "component": "Text", + "text": "Center" + }, + { + "id": "t3", + "component": "Text", + "text": "Right" + } + ] + } + } +]; + +export const Row_Basic_v08_Lit: StoryObj = { + name: "Row Basic [v0.8 Lit]", + render: () => renderA2UI(translateToV08(Row_Basic_messages), "s1"), +}; + +const Row_SpaceBetween_messages: V010Message[] = [ + { + "createSurface": { + "surfaceId": "s1", + "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" + } + }, + { + "updateComponents": { + "surfaceId": "s1", + "components": [ + { + "id": "root", + "component": "Row", + "children": [ + "t1", + "t2" + ], + "justify": "spaceBetween" + }, + { + "id": "t1", + "component": "Text", + "text": "Left" + }, + { + "id": "t2", + "component": "Text", + "text": "Right" + } + ] + } + } +]; + +export const Row_SpaceBetween_v08_Lit: StoryObj = { + name: "Row SpaceBetween [v0.8 Lit]", + render: () => renderA2UI(translateToV08(Row_SpaceBetween_messages), "s1"), +}; + +const Column_Basic_messages: V010Message[] = [ + { + "createSurface": { + "surfaceId": "s1", + "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" + } + }, + { + "updateComponents": { + "surfaceId": "s1", + "components": [ + { + "id": "root", + "component": "Column", + "children": [ + "t1", + "t2", + "t3" + ] + }, + { + "id": "t1", + "component": "Text", + "text": "First" + }, + { + "id": "t2", + "component": "Text", + "text": "Second" + }, + { + "id": "t3", + "component": "Text", + "text": "Third" + } + ] + } + } +]; + +export const Column_Basic_v08_Lit: StoryObj = { + name: "Column Basic [v0.8 Lit]", + render: () => renderA2UI(translateToV08(Column_Basic_messages), "s1"), +}; + +const Column_Aligned_Center_messages: V010Message[] = [ + { + "createSurface": { + "surfaceId": "s1", + "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" + } + }, + { + "updateComponents": { + "surfaceId": "s1", + "components": [ + { + "id": "root", + "component": "Column", + "children": [ + "t1", + "t2" + ], + "align": "center" + }, + { + "id": "t1", + "component": "Text", + "text": "Centered" + }, + { + "id": "t2", + "component": "Text", + "text": "Content" + } + ] + } + } +]; + +export const Column_Aligned_Center_v08_Lit: StoryObj = { + name: "Column Aligned Center [v0.8 Lit]", + render: () => renderA2UI(translateToV08(Column_Aligned_Center_messages), "s1"), +}; + +const Divider_messages: V010Message[] = [ + { + "createSurface": { + "surfaceId": "s1", + "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" + } + }, + { + "updateComponents": { + "surfaceId": "s1", + "components": [ + { + "id": "root", + "component": "Column", + "children": [ + "t1", + "div1", + "t2" + ] + }, + { + "id": "t1", + "component": "Text", + "text": "Above divider" + }, + { + "id": "div1", + "component": "Divider", + "axis": "horizontal" + }, + { + "id": "t2", + "component": "Text", + "text": "Below divider" + } + ] + } + } +]; + +export const Divider_v08_Lit: StoryObj = { + name: "Divider [v0.8 Lit]", + render: () => renderA2UI(translateToV08(Divider_messages), "s1"), +}; + +const Tabs_messages: V010Message[] = [ + { + "createSurface": { + "surfaceId": "s1", + "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" + } + }, + { + "updateComponents": { + "surfaceId": "s1", + "components": [ + { + "id": "root", + "component": "Tabs", + "children": [ + "tab1", + "tab2", + "tab3" + ], + "labels": [ + "Tab A", + "Tab B", + "Tab C" + ] + }, + { + "id": "tab1", + "component": "Text", + "text": "Content of Tab A" + }, + { + "id": "tab2", + "component": "Text", + "text": "Content of Tab B" + }, + { + "id": "tab3", + "component": "Text", + "text": "Content of Tab C" + } + ] + } + } +]; + +export const Tabs_v08_Lit: StoryObj = { + name: "Tabs [v0.8 Lit]", + render: () => renderA2UI(translateToV08(Tabs_messages), "s1"), +}; + diff --git a/conformance-storybook/stories/generated/media.stories.ts b/conformance-storybook/stories/generated/media.stories.ts new file mode 100644 index 000000000..e6d2cb955 --- /dev/null +++ b/conformance-storybook/stories/generated/media.stories.ts @@ -0,0 +1,194 @@ +// AUTO-GENERATED — do not edit. Run: node scripts/generate-stories.mjs +import type { Meta, StoryObj } from "@storybook/web-components"; +import { renderA2UI } from "../helpers/a2ui-story-wrapper.js"; +import { translateToV08 } from "../helpers/version-adapter.js"; +import type { V010Message } from "../helpers/version-adapter.js"; + +const meta: Meta = { title: "Generated/Components/Media" }; +export default meta; + +const Image_Basic_messages: V010Message[] = [ + { + "createSurface": { + "surfaceId": "s1", + "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" + } + }, + { + "updateComponents": { + "surfaceId": "s1", + "components": [ + { + "id": "root", + "component": "Image", + "url": "https://picsum.photos/400/300", + "alt": "Sample image" + } + ] + } + } +]; + +export const Image_Basic_v08_Lit: StoryObj = { + name: "Image Basic [v0.8 Lit]", + render: () => renderA2UI(translateToV08(Image_Basic_messages), "s1"), +}; + +const Image_Cover_Fit_messages: V010Message[] = [ + { + "createSurface": { + "surfaceId": "s1", + "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" + } + }, + { + "updateComponents": { + "surfaceId": "s1", + "components": [ + { + "id": "root", + "component": "Image", + "url": "https://picsum.photos/800/400", + "alt": "Wide image", + "fit": "cover" + } + ] + } + } +]; + +export const Image_Cover_Fit_v08_Lit: StoryObj = { + name: "Image Cover Fit [v0.8 Lit]", + render: () => renderA2UI(translateToV08(Image_Cover_Fit_messages), "s1"), +}; + +const Icon_Single_messages: V010Message[] = [ + { + "createSurface": { + "surfaceId": "s1", + "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" + } + }, + { + "updateComponents": { + "surfaceId": "s1", + "components": [ + { + "id": "root", + "component": "Icon", + "name": "favorite" + } + ] + } + } +]; + +export const Icon_Single_v08_Lit: StoryObj = { + name: "Icon Single [v0.8 Lit]", + render: () => renderA2UI(translateToV08(Icon_Single_messages), "s1"), +}; + +const Icon_Row_messages: V010Message[] = [ + { + "createSurface": { + "surfaceId": "s1", + "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" + } + }, + { + "updateComponents": { + "surfaceId": "s1", + "components": [ + { + "id": "root", + "component": "Row", + "children": [ + "i1", + "i2", + "i3", + "i4" + ] + }, + { + "id": "i1", + "component": "Icon", + "name": "home" + }, + { + "id": "i2", + "component": "Icon", + "name": "settings" + }, + { + "id": "i3", + "component": "Icon", + "name": "favorite" + }, + { + "id": "i4", + "component": "Icon", + "name": "search" + } + ] + } + } +]; + +export const Icon_Row_v08_Lit: StoryObj = { + name: "Icon Row [v0.8 Lit]", + render: () => renderA2UI(translateToV08(Icon_Row_messages), "s1"), +}; + +const Video_Basic_messages: V010Message[] = [ + { + "createSurface": { + "surfaceId": "s1", + "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" + } + }, + { + "updateComponents": { + "surfaceId": "s1", + "components": [ + { + "id": "root", + "component": "Video", + "url": "https://www.w3schools.com/html/mov_bbb.mp4" + } + ] + } + } +]; + +export const Video_Basic_v08_Lit: StoryObj = { + name: "Video Basic [v0.8 Lit]", + render: () => renderA2UI(translateToV08(Video_Basic_messages), "s1"), +}; + +const AudioPlayer_Basic_messages: V010Message[] = [ + { + "createSurface": { + "surfaceId": "s1", + "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" + } + }, + { + "updateComponents": { + "surfaceId": "s1", + "components": [ + { + "id": "root", + "component": "AudioPlayer", + "url": "https://www.w3schools.com/html/horse.mp3", + "title": "Horse Sound" + } + ] + } + } +]; + +export const AudioPlayer_Basic_v08_Lit: StoryObj = { + name: "AudioPlayer Basic [v0.8 Lit]", + render: () => renderA2UI(translateToV08(AudioPlayer_Basic_messages), "s1"), +}; + diff --git a/conformance-storybook/stories/generated/text-variants.stories.ts b/conformance-storybook/stories/generated/text-variants.stories.ts new file mode 100644 index 000000000..3204b1e6a --- /dev/null +++ b/conformance-storybook/stories/generated/text-variants.stories.ts @@ -0,0 +1,144 @@ +// AUTO-GENERATED — do not edit. Run: node scripts/generate-stories.mjs +import type { Meta, StoryObj } from "@storybook/web-components"; +import { renderA2UI } from "../helpers/a2ui-story-wrapper.js"; +import { translateToV08 } from "../helpers/version-adapter.js"; +import type { V010Message } from "../helpers/version-adapter.js"; + +const meta: Meta = { title: "Generated/Components/Text" }; +export default meta; + +const Heading_1_messages: V010Message[] = [ + { + "createSurface": { + "surfaceId": "s1", + "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" + } + }, + { + "updateComponents": { + "surfaceId": "s1", + "components": [ + { + "id": "root", + "component": "Text", + "text": "Heading 1", + "variant": "h1" + } + ] + } + } +]; + +export const Heading_1_v08_Lit: StoryObj = { + name: "Heading 1 [v0.8 Lit]", + render: () => renderA2UI(translateToV08(Heading_1_messages), "s1"), +}; + +const Heading_2_messages: V010Message[] = [ + { + "createSurface": { + "surfaceId": "s1", + "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" + } + }, + { + "updateComponents": { + "surfaceId": "s1", + "components": [ + { + "id": "root", + "component": "Text", + "text": "Heading 2", + "variant": "h2" + } + ] + } + } +]; + +export const Heading_2_v08_Lit: StoryObj = { + name: "Heading 2 [v0.8 Lit]", + render: () => renderA2UI(translateToV08(Heading_2_messages), "s1"), +}; + +const Heading_3_messages: V010Message[] = [ + { + "createSurface": { + "surfaceId": "s1", + "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" + } + }, + { + "updateComponents": { + "surfaceId": "s1", + "components": [ + { + "id": "root", + "component": "Text", + "text": "Heading 3", + "variant": "h3" + } + ] + } + } +]; + +export const Heading_3_v08_Lit: StoryObj = { + name: "Heading 3 [v0.8 Lit]", + render: () => renderA2UI(translateToV08(Heading_3_messages), "s1"), +}; + +const Body_messages: V010Message[] = [ + { + "createSurface": { + "surfaceId": "s1", + "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" + } + }, + { + "updateComponents": { + "surfaceId": "s1", + "components": [ + { + "id": "root", + "component": "Text", + "text": "This is body text with normal styling.", + "variant": "body" + } + ] + } + } +]; + +export const Body_v08_Lit: StoryObj = { + name: "Body [v0.8 Lit]", + render: () => renderA2UI(translateToV08(Body_messages), "s1"), +}; + +const Caption_messages: V010Message[] = [ + { + "createSurface": { + "surfaceId": "s1", + "catalogId": "https://a2ui.org/specification/v0_10/standard_catalog.json" + } + }, + { + "updateComponents": { + "surfaceId": "s1", + "components": [ + { + "id": "root", + "component": "Text", + "text": "Caption text", + "variant": "caption" + } + ] + } + } +]; + +export const Caption_v08_Lit: StoryObj = { + name: "Caption [v0.8 Lit]", + render: () => renderA2UI(translateToV08(Caption_messages), "s1"), +}; + diff --git a/conformance-storybook/stories/helpers/a2ui-story-wrapper.ts b/conformance-storybook/stories/helpers/a2ui-story-wrapper.ts new file mode 100644 index 000000000..04679bf90 --- /dev/null +++ b/conformance-storybook/stories/helpers/a2ui-story-wrapper.ts @@ -0,0 +1,280 @@ +/** + * A2UI Story Wrapper — renders A2UI components via the Lit renderer. + * + * Based on the repo's own renderers/lit/stories/helpers/render-a2ui.ts + * but adapted for our conformance storybook. + */ +import { html, LitElement, css } from "lit"; +import { customElement, property } from "lit/decorators.js"; +import { provide } from "@lit/context"; +import { SignalWatcher } from "@lit-labs/signals"; + +// Import all UI components to register custom elements +import "@a2ui/lit/ui"; +import { v0_8 } from "@a2ui/lit"; +import * as UI from "@a2ui/lit/ui"; + +// Default theme — must match Theme type with nested keys +const e = {}; // empty class map +const defaultTheme: v0_8.Types.Theme = { + components: { + Text: { all: e, h1: e, h2: e, h3: e, h4: e, h5: e, body: e, bodySmall: e, label: e, labelSmall: e, caption: e }, + Button: e, + Card: e, + Checkbox: { container: e, element: e, label: e }, + Column: e, + Row: e, + List: { container: e, item: e }, + Tabs: { container: e, element: e, controls: { all: e, selected: e } }, + Divider: e, + Icon: e, + Image: { all: e, icon: e, avatar: e, image: e }, + Slider: { container: e, element: e, label: e }, + TextField: { container: e, element: e, label: e }, + DateTimeInput: { container: e, element: e, label: e }, + MultipleChoice: { container: e, option: e, selectedOption: e }, + Audio: e, + AudioPlayer: e, + Video: e, + Modal: { backdrop: e, element: e }, + Surface: e, + } as any, +}; + +/** + * Wrapper element that provides theme context for A2UI components. + */ +@customElement("conformance-a2ui-wrapper") +export class ConformanceA2UIWrapper extends SignalWatcher(LitElement) { + @provide({ context: UI.Context.themeContext }) + accessor theme: v0_8.Types.Theme = defaultTheme; + + @property({ attribute: false }) + accessor processor!: v0_8.Data.A2uiMessageProcessor; + + @property({ attribute: false }) + accessor surfaceId: string = "test_surface"; + + static styles = css` + :host { + display: block; + padding: 16px; + font-family: "Roboto", system-ui, sans-serif; + } + `; + + render() { + const surface = this.processor?.getSurfaces().get(this.surfaceId); + if (!surface) { + const available = this.processor ? Array.from(this.processor.getSurfaces().keys()).join(", ") : "none"; + return html`

Surface "${this.surfaceId}" not found. Available: ${available}

`; + } + + return html` + + `; + } +} + +export interface A2UIMessage { + version?: string; + beginRendering?: any; + surfaceUpdate?: any; + createSurface?: any; + updateComponents?: any; + updateDataModel?: any; + dataModelUpdate?: any; + deleteSurface?: any; +} + +/** + * Translate a single v0.10 message to v0.8 format inline. + */ +function translateMessage(msg: A2UIMessage): any { + const { version, ...rest } = msg; + + // v0.10 createSurface → v0.8 beginRendering + if (rest.createSurface) { + // Need to find root from a later updateComponents — defer, handled below + return { _createSurface: rest.createSurface }; + } + + // v0.10 updateComponents → v0.8 surfaceUpdate (with component translation) + if (rest.updateComponents) { + const comps = translateComponentArray(rest.updateComponents.components || []); + return { surfaceUpdate: { surfaceId: rest.updateComponents.surfaceId, components: comps } }; + } + + // v0.10 updateDataModel → v0.8 dataModelUpdate + if (rest.updateDataModel) { + return { dataModelUpdate: rest.updateDataModel }; + } + + return rest; +} + +/** + * Translate an array of v0.10 flat components to v0.8 nested format. + */ +function translateComponentArray(components: any[]): any[] { + return components.map(c => { + if (typeof c.component === "object") return c; // already nested + const { id, component, weight, ...props } = c; + const type = component === "ChoicePicker" ? "MultipleChoice" : component; + const compRenames: Record> = { Text: { variant: "usageHint" } }; + const renames = compRenames[type] || {}; + const STRING_PROPS = new Set(["text", "label", "hint", "name", "url", "src", "title", "placeholder", "description"]); + const p: any = {}; + for (const [k, v] of Object.entries(props)) { + const key = renames[k] || k; + if (STRING_PROPS.has(key) && typeof v === "string") { + p[key] = { literalString: v }; + } else { + p[key] = v; + } + } + // Tabs: v0.10 tabs → v0.8 tabItems + if (type === "Tabs" && p.tabs && Array.isArray(p.tabs)) { + p.tabItems = p.tabs.map((t: any) => ({ + title: typeof t.label === "string" ? { literalString: t.label } : (typeof t.title === "string" ? { literalString: t.title } : t.title || t.label), + child: t.child, + })); + delete p.tabs; + } + // MultipleChoice: options labels + selections + if (type === "MultipleChoice") { + if (p.options) { + p.options = p.options.map((o: any) => ({ + ...o, + label: typeof o.label === "string" ? { literalString: o.label } : o.label, + })); + } + if (p.value && !p.selections) { p.selections = p.value; delete p.value; } + if (!p.selections) { p.selections = []; } + } + const result: any = { id, component: { [type]: p } }; + if (weight !== undefined) result.weight = weight; + return result; + }); +} + +/** + * Render A2UI messages using the proper wrapper with theme context. + * Accepts both v0.8 and v0.10 message formats — auto-translates. + */ +export function renderA2UI(messages: A2UIMessage[], surfaceId?: string) { + const processor = v0_8.Data.createSignalA2uiMessageProcessor(); + + // Detect and translate v0.10 messages + const hasV010 = messages.some(m => m.createSurface || m.updateComponents); + + let serverMessages: any[]; + if (hasV010) { + // Two-pass: first translate, then resolve createSurface → beginRendering + const translated = messages.map(translateMessage); + serverMessages = []; + for (const msg of translated) { + if (msg._createSurface) { + // Find root from the next surfaceUpdate for this surface + const sid = msg._createSurface.surfaceId; + const nextUpdate = translated.find((m: any) => m.surfaceUpdate?.surfaceId === sid); + const comps = nextUpdate?.surfaceUpdate?.components || []; + const rootId = comps[0]?.id || "root"; + serverMessages.push({ beginRendering: { surfaceId: sid, root: rootId } }); + } else { + serverMessages.push(msg); + } + } + } else { + serverMessages = messages.map(({ version, ...rest }) => rest); + } + + processor.processMessages(serverMessages as v0_8.Types.ServerToClientMessage[]); + + const surfaces = processor.getSurfaces(); + const targetSurfaceId = surfaceId || Array.from(surfaces.keys())[0] || "test_surface"; + + return html` + + `; +} + +/** + * Helper to create v0.8 renderer messages for a simple component. + * Accepts EITHER format: + * - v0.8 nested: {id, component: {Type: {props}}} + * - v0.10 flat: {id, component: "Type", prop1: val1, ...} + * Auto-translates v0.10 → v0.8 if needed. + */ +export function simpleComponent( + surfaceId: string, + components: any[] +): A2UIMessage[] { + const translated = components.map(c => { + // Already v0.8 nested format + if (typeof c.component === "object") return c; + // v0.10 flat → v0.8 nested + const { id, component, weight, ...props } = c; + const type = component === "ChoicePicker" ? "MultipleChoice" : component; + // Property renames: v0.10 → v0.8 (component-specific) + const RENAMES: Record> = { + Text: { variant: "usageHint" }, + }; + const renames = RENAMES[type] || {}; + const p: any = {}; + for (const [k, v] of Object.entries(props)) { + const key = renames[k] || k; + // StringValue properties that need {literalString: ...} wrapping + const STRING_PROPS = new Set(["text", "label", "hint", "name", "url", "src", "title", "placeholder", "description"]); + if (STRING_PROPS.has(key) && typeof v === "string") { + p[key] = { literalString: v }; + } else { + p[key] = v; + } + } + // Component-specific translations + if (type === "Tabs" && p.tabs && Array.isArray(p.tabs)) { + // v0.10: tabs: [{label, child}] → v0.8: titles: [StringValue], children: [id] + p.titles = p.tabs.map((t: any) => typeof t.label === "string" ? { literalString: t.label } : t.label); + p.children = p.tabs.map((t: any) => t.child); + delete p.tabs; + } + if (type === "MultipleChoice" && p.options && Array.isArray(p.options)) { + p.options = p.options.map((o: any) => ({ + ...o, + label: typeof o.label === "string" ? { literalString: o.label } : o.label, + })); + } + const result: any = { id, component: { [type]: p } }; + if (weight !== undefined) result.weight = weight; + return result; + }); + const rootId = translated[0]?.id || "root"; + return [ + { beginRendering: { surfaceId, root: rootId } }, + { surfaceUpdate: { surfaceId, components: translated } }, + ]; +} + +/** + * Helper for components with data model values. + */ +export function componentWithData( + surfaceId: string, + components: any[], + dataPath: string, + dataValue: any +): A2UIMessage[] { + return [ + ...simpleComponent(surfaceId, components), + { dataModelUpdate: { surfaceId, path: dataPath, value: dataValue } }, + ]; +} diff --git a/conformance-storybook/stories/helpers/version-adapter.ts b/conformance-storybook/stories/helpers/version-adapter.ts new file mode 100644 index 000000000..9bd472f4b --- /dev/null +++ b/conformance-storybook/stories/helpers/version-adapter.ts @@ -0,0 +1,163 @@ +/** + * Version adapter: translates between A2UI spec formats. + * Fixtures are stored in v0.10 (canonical) format. + * The Lit renderer expects v0.8 format. + */ + +export interface V010Message { + createSurface?: { surfaceId: string; catalogId?: string }; + updateComponents?: { surfaceId: string; components: any[] }; + updateDataModel?: { surfaceId: string; path: string; value: any }; + deleteSurface?: { surfaceId: string }; +} + +export interface V08Message { + version: string; + beginRendering?: { surfaceId: string; root: string }; + surfaceUpdate?: { surfaceId: string; components: any[] }; + createSurface?: { surfaceId: string }; + updateComponents?: { surfaceId: string; components: any[] }; + dataModelUpdate?: { surfaceId: string; path: string; value: any }; + deleteSurface?: { surfaceId: string }; +} + +/** + * Find the root component ID from a components array. + * The root is the first component whose ID is not referenced as a child/children by any other component. + * Fallback: first component with id "root", or just the first component. + */ +function findRootId(components: any[]): string { + // Quick check for explicit "root" id + if (components.some(c => c.id === "root")) return "root"; + + // Build set of all child references + const childIds = new Set(); + for (const c of components) { + if (c.child) childIds.add(c.child); + if (c.children) for (const ch of c.children) childIds.add(ch); + } + + // Root = first component not referenced as a child + for (const c of components) { + if (!childIds.has(c.id)) return c.id; + } + + return components[0]?.id || "root"; +} + +/** + * Translate v0.10 flat component format to v0.8 nested format. + * + * v0.10: { id: "btn", component: "Button", child: "txt", variant: "primary", action: {...} } + * v0.8: { id: "btn", component: { Button: { child: "txt", variant: "primary", action: {...} } } } + * + * Also renames ChoicePicker → MultipleChoice. + */ +function translateComponents(components: any[]): any[] { + return components.map(c => { + const { id, component, weight, ...props } = c; + + // If already in v0.8 nested format (component is an object), pass through + if (typeof component === "object") { + return c; + } + + // Rename ChoicePicker → MultipleChoice + const componentType = component === "ChoicePicker" ? "MultipleChoice" : component; + + // Property renames: v0.10 → v0.8 (component-specific) + const RENAMES: Record> = { + Text: { variant: "usageHint" }, + }; + const renames = RENAMES[componentType] || {}; + // Wrap string values in literalString for text-like properties + const translatedProps: any = {}; + for (const [key, value] of Object.entries(props)) { + const k = renames[key] || key; + const STRING_PROPS = new Set(["text", "label", "hint", "name", "url", "src", "title", "placeholder", "description"]); + if (STRING_PROPS.has(k) && typeof value === "string") { + translatedProps[k] = { literalString: value }; + } else { + translatedProps[k] = value; + } + } + + // Component-specific translations + if (componentType === "Tabs" && translatedProps.tabs && Array.isArray(translatedProps.tabs)) { + translatedProps.tabItems = translatedProps.tabs.map((t: any) => ({ + title: typeof t.label === "string" ? { literalString: t.label } : (typeof t.title === "string" ? { literalString: t.title } : t.title || t.label), + child: t.child, + })); + delete translatedProps.tabs; + } + if (componentType === "MultipleChoice") { + if (translatedProps.options && Array.isArray(translatedProps.options)) { + translatedProps.options = translatedProps.options.map((o: any) => ({ + ...o, + label: typeof o.label === "string" ? { literalString: o.label } : o.label, + })); + } + if (translatedProps.value && !translatedProps.selections) { + translatedProps.selections = translatedProps.value; + delete translatedProps.value; + } + if (!translatedProps.selections) translatedProps.selections = []; + } + + const result: any = { + id, + component: { [componentType]: translatedProps }, + }; + if (weight !== undefined) result.weight = weight; + return result; + }); +} + +/** + * Translate v0.10 messages to v0.8 format for the Lit renderer. + */ +export function translateToV08(messages: V010Message[]): V08Message[] { + const result: V08Message[] = []; + + // We need to look ahead: createSurface needs root ID from the next updateComponents + for (let i = 0; i < messages.length; i++) { + const msg = messages[i]; + + if (msg.createSurface) { + // Find the root from the next updateComponents message for this surface + let rootId = "root"; + for (let j = i + 1; j < messages.length; j++) { + if (msg.createSurface && messages[j].updateComponents?.surfaceId === msg.createSurface.surfaceId) { + rootId = findRootId(messages[j].updateComponents!.components); + break; + } + } + result.push({ + version: "v0.8", + beginRendering: { surfaceId: msg.createSurface.surfaceId, root: rootId }, + }); + } else if (msg.updateComponents) { + const translated = translateComponents(msg.updateComponents.components); + result.push({ + version: "v0.8", + surfaceUpdate: { surfaceId: msg.updateComponents.surfaceId, components: translated }, + }); + } else if (msg.updateDataModel) { + result.push({ + version: "v0.8", + dataModelUpdate: { + surfaceId: msg.updateDataModel.surfaceId, + path: msg.updateDataModel.path, + value: msg.updateDataModel.value, + }, + }); + } else if (msg.deleteSurface) { + result.push({ + version: "v0.8", + deleteSurface: msg.deleteSurface, + }); + } + } + + return result; +} diff --git a/conformance-storybook/tsconfig.json b/conformance-storybook/tsconfig.json new file mode 100644 index 000000000..5d0eff4e3 --- /dev/null +++ b/conformance-storybook/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ES2022", + "moduleResolution": "bundler", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "experimentalDecorators": false, + "useDefineForClassFields": false, + "declaration": true, + "outDir": "dist", + "rootDir": ".", + "lib": ["ES2022", "DOM", "DOM.Iterable"] + }, + "include": ["stories/**/*.ts", ".storybook/**/*.ts"] +} diff --git a/testing/README.md b/testing/README.md new file mode 100644 index 000000000..cfdef4664 --- /dev/null +++ b/testing/README.md @@ -0,0 +1,42 @@ +# A2UI Cross-Renderer Testing + +Tools for verifying component coverage parity across A2UI renderers. + +## Coverage Matrix + +Compares registered component types across the v0.10 specification, Lit renderer, and Angular renderer. Catches missing components and naming mismatches. + +### Usage + +```bash +node testing/coverage-matrix.mjs +``` + +**No dependencies required** — uses only Node.js builtins (`fs`, `path`). + +### What it checks + +1. Reads the v0.10 spec's `standard_catalog.json` for the canonical component list +2. Scans the Lit renderer (`renderers/lit/src/0.8/ui/root.ts`) for registered `case` handlers +3. Scans the Angular renderer (`renderers/angular/src/lib/catalog/default.ts`) for `DEFAULT_CATALOG` entries +4. Outputs a matrix showing which components each renderer supports vs the spec +5. Exits with code 1 if any spec component is missing from a renderer + +### Current Status + +| | Spec (v0.10) | Lit (v0.8.1) | Angular (v0.8.4) | +|---|:---:|:---:|:---:| +| Components | 18 | 18 | 18 | +| Parity | — | ✅ | ✅ | + +> **Note:** Both renderers use the v0.8 name `MultipleChoice` which was renamed to `ChoicePicker` in v0.10. The script accounts for this rename. + +### CI Integration + +```yaml +# Example GitHub Actions step +- name: Check renderer coverage + run: node testing/coverage-matrix.mjs +``` + +The script exits 0 on full coverage, 1 on any missing components. diff --git a/testing/coverage-matrix-demo.svg b/testing/coverage-matrix-demo.svg new file mode 100644 index 000000000..8cce29787 --- /dev/null +++ b/testing/coverage-matrix-demo.svg @@ -0,0 +1,64 @@ + + + + + + + + + + + ╔══════════════════╦═════════╦═════════╦═══════════╦═════════╗║ Component ║ v0.10 ║ Lit ║ Angular ║ Parity ║╠══════════════════╬═════════╬═════════╬═══════════╬═════════╣║ AudioPlayer ║ ✅ ║ ✅ ║ ✅ ║ ✅ ║║ Button ║ ✅ ║ ✅ ║ ✅ ║ ✅ ║║ Card ║ ✅ ║ ✅ ║ ✅ ║ ✅ ║║ CheckBox ║ ✅ ║ ✅ ║ ✅ ║ ✅ ║║ ChoicePicker ║ ✅ ║ ❌ ║ ❌ ║ ⚠ renamed ║║ Column ║ ✅ ║ ✅ ║ ✅ ║ ✅ ║║ DateTimeInput ║ ✅ ║ ✅ ║ ✅ ║ ✅ ║ ║ Divider ║ ✅ ║ ✅ ║ ✅ ║ ✅ ║║ Icon ║ ✅ ║ ✅ ║ ✅ ║ ✅ ║║ Image ║ ✅ ║ ✅ ║ ✅ ║ ✅ ║║ List ║ ✅ ║ ✅ ║ ✅ ║ ✅ ║║ Modal ║ ✅ ║ ✅ ║ ✅ ║ ✅ ║║ MultipleChoice ║ ❌ ║ ✅ ║ ✅ ║ ⚠ v0.8 name ║║ Row ║ ✅ ║ ✅ ║ ✅ ║ ✅ ║║ Slider ║ ✅ ║ ✅ ║ ✅ ║ ✅ ║║ Tabs ║ ✅ ║ ✅ ║ ✅ ║ ✅ ║║ Text ║ ✅ ║ ✅ ║ ✅ ║ ✅ ║║ TextField ║ ✅ ║ ✅ ║ ✅ ║ ✅ ║║ Video ║ ✅ ║ ✅ ║ ✅ ║ ✅ ║╚══════════════════╩═════════╩═════════╩═══════════╩════════ ╚══════════════════╩═════════╩═════════╩═══════════╩═════════╝Spec components (v0.10): 18Lit components: 18Angular components: 18--- Naming Differences ---v0.10 "ChoicePicker" = v0.8 "MultipleChoice" (both renderers use v0.8 name)✅ PASS: All spec components covered (with ChoicePicker/MultipleChoice rename noted) + \ No newline at end of file diff --git a/testing/coverage-matrix.mjs b/testing/coverage-matrix.mjs new file mode 100644 index 000000000..1913307de --- /dev/null +++ b/testing/coverage-matrix.mjs @@ -0,0 +1,97 @@ +#!/usr/bin/env node +/** + * A2UI Cross-Renderer Component Coverage Matrix + * + * Introspects Lit and Angular renderer sources to find registered component types, + * compares against v0.10 spec, and outputs a coverage matrix. + */ + +import { readFileSync, readdirSync } from 'fs'; +import { join, dirname } from 'path'; +import { fileURLToPath } from 'url'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const repoRoot = join(__dirname, '../..'); + +// 1. Get spec components from standard_catalog.json +const catalog = JSON.parse(readFileSync(join(repoRoot, 'specification/v0_10/json/standard_catalog.json'), 'utf8')); +const specComponents = Object.keys(catalog.components).sort(); + +// 2. Get Lit components by scanning case statements in root.ts +const litRoot = readFileSync(join(repoRoot, 'renderers/lit/src/0.8/ui/root.ts'), 'utf8'); +const litComponents = [...litRoot.matchAll(/case "(\w+)":/g)].map(m => m[1]).sort(); + +// 3. Get Angular components from DEFAULT_CATALOG keys in default.ts +const angularDefault = readFileSync(join(repoRoot, 'renderers/angular/src/lib/catalog/default.ts'), 'utf8'); +const angularComponents = [...angularDefault.matchAll(/^\s+(\w+):/gm)] + .map(m => m[1]) + .filter(name => !['type', 'bindings', 'https', 'http', 'import', 'return', 'const', 'export'].includes(name) && /^[A-Z]/.test(name)) + .sort(); + +// 4. Build and display matrix +console.log('\n╔══════════════════╦═════════╦═════════╦═══════════╦═════════╗'); +console.log('║ Component ║ v0.10 ║ Lit ║ Angular ║ Parity ║'); +console.log('╠══════════════════╬═════════╬═════════╬═══════════╬═════════╣'); + +const allComponents = [...new Set([...specComponents, ...litComponents, ...angularComponents])].sort(); +let missingFromSpec = []; +let failures = []; + +for (const comp of allComponents) { + const inSpec = specComponents.includes(comp); + const inLit = litComponents.includes(comp); + const inAngular = angularComponents.includes(comp); + + // Check for rename: MultipleChoice (renderers) → ChoicePicker (spec) + const isRenamed = comp === 'MultipleChoice' || comp === 'ChoicePicker'; + + let parity; + if (comp === 'ChoicePicker') { + // Spec has ChoicePicker, renderers have MultipleChoice + const litHasMC = litComponents.includes('MultipleChoice'); + const angHasMC = angularComponents.includes('MultipleChoice'); + parity = litHasMC && angHasMC ? '⚠️ renamed' : '❌'; + } else if (comp === 'MultipleChoice') { + parity = '⚠️ v0.8 name'; + } else { + parity = (inSpec && inLit && inAngular) ? '✅' : '❌'; + } + + if (inSpec && (!inLit || !inAngular) && comp !== 'ChoicePicker') { + failures.push(comp); + } + + const pad = (s, n) => s.padEnd(n); + const mark = (b) => b ? ' ✅ ' : ' ❌ '; + + console.log(`║ ${pad(comp, 16)} ║${mark(inSpec)}║${mark(inLit)}║ ${inAngular ? '✅' : '❌'} ║ ${pad(parity, 7)} ║`); +} + +console.log('╚══════════════════╩═════════╩═════════╩═══════════╩═════════╝'); + +// Summary +console.log(`\nSpec components (v0.10): ${specComponents.length}`); +console.log(`Lit components: ${litComponents.length}`); +console.log(`Angular components: ${angularComponents.length}`); + +console.log('\n--- Naming Differences ---'); +console.log('v0.10 "ChoicePicker" = v0.8 "MultipleChoice" (both renderers use v0.8 name)'); + +// Check for spec components missing from renderers (accounting for rename) +const specMinusRename = specComponents.filter(c => c !== 'ChoicePicker'); +const litMinusRename = litComponents.map(c => c === 'MultipleChoice' ? 'ChoicePicker' : c); +const angMinusRename = angularComponents.map(c => c === 'MultipleChoice' ? 'ChoicePicker' : c); + +const missingLit = specMinusRename.filter(c => !litMinusRename.includes(c)); +const missingAngular = specMinusRename.filter(c => !angMinusRename.includes(c)); + +if (missingLit.length) console.log(`\n❌ Missing from Lit: ${missingLit.join(', ')}`); +if (missingAngular.length) console.log(`❌ Missing from Angular: ${missingAngular.join(', ')}`); + +if (missingLit.length || missingAngular.length) { + console.log('\n❌ FAIL: Not all spec components covered by renderers'); + process.exit(1); +} else { + console.log('\n✅ PASS: All spec components covered (with ChoicePicker/MultipleChoice rename noted)'); + process.exit(0); +}