diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a546a10..387695a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,42 +2,54 @@ name: CI on: push: - branches: [ main ] + branches: [main] pull_request: - branches: [ main ] + branches: [main] workflow_dispatch: jobs: lint-and-build: runs-on: ubuntu-24.04 - + strategy: matrix: node-version: [20, 22, 24] - + + env: + SAVE_PNG_PATH: ${{ github.workspace }}/renders + steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4 - with: - node-version: ${{ matrix.node-version }} - cache: 'npm' - - - name: Install dependencies - run: npm ci - - - name: Run ESLint - run: npm run lint - - - name: Build Storybook - run: npm run storybook:build - - - name: Upload Storybook build artifacts - uses: actions/upload-artifact@v4 - if: matrix.node-version == 20 - with: - name: storybook-build - path: storybook-static/ - retention-days: 30 + - name: Checkout code + uses: actions/checkout@v4 + + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Run ESLint + run: npm run lint + + - name: Run tests + run: npm run test + + - name: Build Storybook + run: npm run storybook:build + + - name: Upload Storybook build artifacts + uses: actions/upload-artifact@v4 + if: matrix.node-version == 20 + with: + name: storybook-build + path: storybook-static/ + + - name: Upload element renders + uses: actions/upload-artifact@v4 + if: matrix.node-version == 20 + with: + name: element-renders + path: renders/ diff --git a/.gitignore b/.gitignore index b051aef..58ee62b 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ build storybook-static custom-elements.json .DS_Store +renders/*.png diff --git a/package-lock.json b/package-lock.json index 970dd35..58fa1b1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@wokwi/elements", - "version": "1.8.1", + "version": "1.9.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@wokwi/elements", - "version": "1.8.1", + "version": "1.9.0", "license": "MIT", "dependencies": { "@types/react": ">=16", @@ -15,6 +15,7 @@ "devDependencies": { "@babel/core": "^7.15.0", "@babel/runtime": "^7.15.3", + "@lit-labs/ssr": "^3.3.1", "@rollup/plugin-commonjs": "^28.0.6", "@rollup/plugin-node-resolve": "^16.0.1", "@storybook/addon-docs": "9.1.1", @@ -35,8 +36,10 @@ "react-is": "^16.13.1", "rimraf": "^3.0.2", "rollup": "^4.46.2", + "sharp": "^0.34.3", "terser": "^5.43.1", "typescript": "^5.9.0", + "vitest": "^3.2.4", "web-component-analyzer": "^2.0.0" }, "engines": { @@ -366,6 +369,25 @@ "node": ">=6.9.0" } }, + "node_modules/@emnapi/runtime": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.5.tgz", + "integrity": "sha512-++LApOtY0pEEz1zrd9vy1/zXVaVJJ/EbAF3u0fXIzPJEDtnITsBGbbK0EkM72amhl/R5b+5xx0Y/QhcVOpuulg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime/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", + "optional": true + }, "node_modules/@esbuild/win32-x64": { "version": "0.25.8", "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.8.tgz", @@ -379,7 +401,6 @@ "os": [ "win32" ], - "peer": true, "engines": { "node": ">=18" } @@ -543,167 +564,659 @@ "dev": true, "license": "BSD-3-Clause" }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.3.tgz", + "integrity": "sha512-ryFMfvxxpQRsgZJqBd4wsttYQbCxsJksrv9Lw/v798JcQ8+w84mBWuXwl+TT0WJ/WrYOLaYpwQXi3sA9nTIaIg==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - }, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=6.0.0" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.2.0" } }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "node_modules/@img/sharp-darwin-x64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.3.tgz", + "integrity": "sha512-yHpJYynROAj12TA6qil58hmPmAwxKKC7reUqtGLzsOHfP7/rniNGTL8tjWX6L3CTV4+5P4ypcS7Pp+7OB+8ihA==", + "cpu": [ + "x64" + ], "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=6.0.0" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.2.0" } }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.0.tgz", + "integrity": "sha512-sBZmpwmxqwlqG9ueWFXtockhsxefaV6O84BMOrhtg/YqbTaRdqDE7hxraVE3y6gVM4eExmfzW4a8el9ArLeEiQ==", + "cpu": [ + "arm64" + ], "dev": true, - "engines": { - "node": ">=6.0.0" + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.10", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.10.tgz", - "integrity": "sha512-0pPkgz9dY+bijgistcTTJ5mR+ocqRXLuhXHYdzoMmmoJ2C9S46RCm2GMUbatPEUK9Yjy26IrAy8D/M00lLkv+Q==", + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.0.tgz", + "integrity": "sha512-M64XVuL94OgiNHa5/m2YvEQI5q2cl9d/wk0qFTDVXcYzi43lxuiFTftMR1tOnFQovVXNZJ5TURSDK2pNe9Yzqg==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz", - "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==", + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.0.tgz", + "integrity": "sha512-mWd2uWvDtL/nvIzThLq3fr2nnGfyr/XMXlq8ZJ9WMR6PXijHlC3ksp0IpuhK6bougvQrchUAfzRLnbsen0Cqvw==", + "cpu": [ + "arm" + ], "dev": true, - "license": "MIT" + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.0.tgz", + "integrity": "sha512-RXwd0CgG+uPRX5YYrkzKyalt2OJYRiJQ8ED/fi1tq9WQW2jsQIn0tqrlR5l5dr/rjqq6AHAxURhj2DVjyQWSOA==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@lit-labs/ssr-dom-shim": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.4.0.tgz", - "integrity": "sha512-ficsEARKnmmW5njugNYKipTm4SFnbik7CXtoencDZzmzo/dQ+2Q0bgkzJuoJP20Aj0F+izzJjOqsnkd6F/o1bw==", - "license": "BSD-3-Clause" - }, - "node_modules/@lit/reactive-element": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.1.1.tgz", - "integrity": "sha512-N+dm5PAYdQ8e6UlywyyrgI2t++wFGXfHx+dSJ1oBrg6FAxUj40jId++EaRm80MKX5JnlH1sBsyZ5h0bcZKemCg==", - "license": "BSD-3-Clause", - "dependencies": { - "@lit-labs/ssr-dom-shim": "^1.4.0" + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.0.tgz", + "integrity": "sha512-Xod/7KaDDHkYu2phxxfeEPXfVXFKx70EAFZ0qyUdOjCcxbjqyJOEUpDe6RIyaunGxT34Anf9ue/wuWOqBW2WcQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@mdx-js/react": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.1.0.tgz", - "integrity": "sha512-QjHtSaoameoalGnKDT3FoIl4+9RwyTmo9ZJGBdLOks/YOiWHoRDI3PUwEzOE7kEmGcV3AFcp9K6dYu9rEuKLAQ==", + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.0.tgz", + "integrity": "sha512-eMKfzDxLGT8mnmPJTNMcjfO33fLiTDsrMlUVcp6b96ETbnJmd4uvZxVJSKPQfS+odwfVaGifhsB07J1LynFehw==", + "cpu": [ + "s390x" + ], "dev": true, - "license": "MIT", - "dependencies": { - "@types/mdx": "^2.0.0" - }, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - }, - "peerDependencies": { - "@types/react": ">=16", - "react": ">=16" + "url": "https://opencollective.com/libvips" } }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.0.tgz", + "integrity": "sha512-ZW3FPWIc7K1sH9E3nxIGB3y3dZkpJlMnkk7z5tu1nSkBoCgw2nSRTFHI5pB/3CQaJM0pdzMF3paf9ckKMSE9Tg==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.0.tgz", + "integrity": "sha512-UG+LqQJbf5VJ8NWJ5Z3tdIe/HXjuIdo4JeVNADXBFuG7z9zjoegpzzGIyV5zQKi4zaJjnAd2+g2nna8TZvuW9Q==", + "cpu": [ + "arm64" + ], "dev": true, - "engines": { - "node": ">= 8" + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.0.tgz", + "integrity": "sha512-SRYOLR7CXPgNze8akZwjoGBoN1ThNZoqpOgfnOxmWsklTGVfJiGJoC/Lod7aNMGA1jSsKWM1+HRX43OP6p9+6Q==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@pkgr/core": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz", - "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==", + "node_modules/@img/sharp-linux-arm": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.3.tgz", + "integrity": "sha512-oBK9l+h6KBN0i3dC8rYntLiVfW8D8wH+NPNT3O/WBHeW0OQWCjfWksLUaPidsrDKpJgXp3G3/hkmhptAW0I3+A==", + "cpu": [ + "arm" + ], "dev": true, - "license": "MIT", + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, "funding": { - "url": "https://opencollective.com/pkgr" + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.2.0" } }, - "node_modules/@rollup/plugin-commonjs": { - "version": "28.0.6", - "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-28.0.6.tgz", - "integrity": "sha512-XSQB1K7FUU5QP+3lOQmVCE3I0FcbbNvmNT4VJSj93iUjayaARrTQeoRdiYQoftAJBLrR9t2agwAd3ekaTgHNlw==", + "node_modules/@img/sharp-linux-arm64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.3.tgz", + "integrity": "sha512-QdrKe3EvQrqwkDrtuTIjI0bu6YEJHTgEeqdzI3uWJOH6G1O8Nl1iEeVYRGdj1h5I21CqxSvQp1Yv7xeU3ZewbA==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "@rollup/pluginutils": "^5.0.1", - "commondir": "^1.0.1", - "estree-walker": "^2.0.2", - "fdir": "^6.2.0", - "is-reference": "1.2.1", - "magic-string": "^0.30.3", - "picomatch": "^4.0.2" - }, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=16.0.0 || 14 >= 14.17" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, - "peerDependencies": { - "rollup": "^2.68.0||^3.0.0||^4.0.0" + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.2.0" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.3.tgz", + "integrity": "sha512-GLtbLQMCNC5nxuImPR2+RgrviwKwVql28FWZIW1zWruy6zLgA5/x2ZXk3mxj58X/tszVF69KK0Is83V8YgWhLA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.2.0" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.3.tgz", + "integrity": "sha512-3gahT+A6c4cdc2edhsLHmIOXMb17ltffJlxR0aC2VPZfwKoTGZec6u5GrFgdR7ciJSsHT27BD3TIuGcuRT0KmQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.2.0" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.3.tgz", + "integrity": "sha512-8kYso8d806ypnSq3/Ly0QEw90V5ZoHh10yH0HnrzOCr6DKAPI6QVHvwleqMkVQ0m+fc7EH8ah0BB0QPuWY6zJQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.2.0" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.3.tgz", + "integrity": "sha512-vAjbHDlr4izEiXM1OTggpCcPg9tn4YriK5vAjowJsHwdBIdx0fYRsURkxLG2RLm9gyBq66gwtWI8Gx0/ov+JKQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.2.0" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.3.tgz", + "integrity": "sha512-gCWUn9547K5bwvOn9l5XGAEjVTTRji4aPTqLzGXHvIr6bIDZKNTA34seMPgM0WmSf+RYBH411VavCejp3PkOeQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.2.0" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.3.tgz", + "integrity": "sha512-+CyRcpagHMGteySaWos8IbnXcHgfDn7pO2fiC2slJxvNq9gDipYBN42/RagzctVRKgxATmfqOSulgZv5e1RdMg==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.4.4" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.3.tgz", + "integrity": "sha512-MjnHPnbqMXNC2UgeLJtX4XqoVHHlZNd+nPt1kRPmj63wURegwBhZlApELdtxM2OIZDRv/DFtLcNhVbd1z8GYXQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.3.tgz", + "integrity": "sha512-xuCdhH44WxuXgOM714hn4amodJMZl3OEvf0GVTm0BEyMeA2to+8HEdRPShH0SLYptJY1uBw+SCFP9WVQi1Q/cw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.3.tgz", + "integrity": "sha512-OWwz05d++TxzLEv4VnsTz5CmZ6mI6S05sfQGEMrNrQcOEERbX46332IvE7pO/EUiw7jUrrS40z/M7kPyjfl04g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.10.tgz", + "integrity": "sha512-0pPkgz9dY+bijgistcTTJ5mR+ocqRXLuhXHYdzoMmmoJ2C9S46RCm2GMUbatPEUK9Yjy26IrAy8D/M00lLkv+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz", + "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@lit-labs/ssr": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@lit-labs/ssr/-/ssr-3.3.1.tgz", + "integrity": "sha512-JlF1PempxvzrGEpRFrF+Ki0MHzR3HA51SK8Zv0cFpW9p0bPW4k0FeCwrElCu371UEpXF7RcaE2wgYaE1az0XKg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@lit-labs/ssr-client": "^1.1.7", + "@lit-labs/ssr-dom-shim": "^1.3.0", + "@lit/reactive-element": "^2.0.4", + "@parse5/tools": "^0.3.0", + "@types/node": "^16.0.0", + "enhanced-resolve": "^5.10.0", + "lit": "^3.1.2", + "lit-element": "^4.0.4", + "lit-html": "^3.1.2", + "node-fetch": "^3.2.8", + "parse5": "^7.1.1" + }, + "engines": { + "node": ">=13.9.0" + } + }, + "node_modules/@lit-labs/ssr-client": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@lit-labs/ssr-client/-/ssr-client-1.1.7.tgz", + "integrity": "sha512-VvqhY/iif3FHrlhkzEPsuX/7h/NqnfxLwVf0p8ghNIlKegRyRqgeaJevZ57s/u/LiFyKgqksRP5n+LmNvpxN+A==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@lit/reactive-element": "^2.0.4", + "lit": "^3.1.2", + "lit-html": "^3.1.2" + } + }, + "node_modules/@lit-labs/ssr-dom-shim": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.4.0.tgz", + "integrity": "sha512-ficsEARKnmmW5njugNYKipTm4SFnbik7CXtoencDZzmzo/dQ+2Q0bgkzJuoJP20Aj0F+izzJjOqsnkd6F/o1bw==", + "license": "BSD-3-Clause" + }, + "node_modules/@lit-labs/ssr/node_modules/@types/node": { + "version": "16.18.126", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.126.tgz", + "integrity": "sha512-OTcgaiwfGFBKacvfwuHzzn1KLxH/er8mluiy8/uM3sGXHaRe73RrSIj01jow9t4kJEW633Ov+cOexXeiApTyAw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@lit/reactive-element": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.1.1.tgz", + "integrity": "sha512-N+dm5PAYdQ8e6UlywyyrgI2t++wFGXfHx+dSJ1oBrg6FAxUj40jId++EaRm80MKX5JnlH1sBsyZ5h0bcZKemCg==", + "license": "BSD-3-Clause", + "dependencies": { + "@lit-labs/ssr-dom-shim": "^1.4.0" + } + }, + "node_modules/@mdx-js/react": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.1.0.tgz", + "integrity": "sha512-QjHtSaoameoalGnKDT3FoIl4+9RwyTmo9ZJGBdLOks/YOiWHoRDI3PUwEzOE7kEmGcV3AFcp9K6dYu9rEuKLAQ==", + "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/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@parse5/tools": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@parse5/tools/-/tools-0.3.0.tgz", + "integrity": "sha512-zxRyTHkqb7WQMV8kTNBKWb1BeOFUKXBXTBWuxg9H9hfvQB3IwP6Iw2U75Ia5eyRxPNltmY7E8YAlz6zWwUnjKg==", + "dev": true, + "license": "MIT", + "dependencies": { + "parse5": "^7.0.0" + } + }, + "node_modules/@pkgr/core": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz", + "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/pkgr" + } + }, + "node_modules/@rollup/plugin-commonjs": { + "version": "28.0.6", + "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-28.0.6.tgz", + "integrity": "sha512-XSQB1K7FUU5QP+3lOQmVCE3I0FcbbNvmNT4VJSj93iUjayaARrTQeoRdiYQoftAJBLrR9t2agwAd3ekaTgHNlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "commondir": "^1.0.1", + "estree-walker": "^2.0.2", + "fdir": "^6.2.0", + "is-reference": "1.2.1", + "magic-string": "^0.30.3", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=16.0.0 || 14 >= 14.17" + }, + "peerDependencies": { + "rollup": "^2.68.0||^3.0.0||^4.0.0" }, "peerDependenciesMeta": { "rollup": { @@ -1227,18 +1740,6 @@ "vite": "^5.0.0 || ^6.0.0 || ^7.0.0" } }, - "node_modules/@storybook/web-components-vite/node_modules/@types/node": { - "version": "24.2.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.2.1.tgz", - "integrity": "sha512-DRh5K+ka5eJic8CjH7td8QpYEV6Zo10gfRkjHCO3weqZHWDtAaSTFtl4+VMqOJ4N5jcuhZ9/l+yy8rVgw7BQeQ==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "undici-types": "~7.10.0" - } - }, "node_modules/@storybook/web-components-vite/node_modules/fdir": { "version": "6.4.6", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", @@ -1440,7 +1941,6 @@ "integrity": "sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/deep-eql": "*" } @@ -1450,8 +1950,7 @@ "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@types/eslint": { "version": "9.6.1", @@ -1499,11 +1998,15 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "14.18.63", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.63.tgz", - "integrity": "sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ==", + "version": "24.2.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.2.1.tgz", + "integrity": "sha512-DRh5K+ka5eJic8CjH7td8QpYEV6Zo10gfRkjHCO3weqZHWDtAaSTFtl4+VMqOJ4N5jcuhZ9/l+yy8rVgw7BQeQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true, + "dependencies": { + "undici-types": "~7.10.0" + } }, "node_modules/@types/parse-json": { "version": "4.0.0", @@ -1811,7 +2314,6 @@ "integrity": "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/chai": "^5.2.2", "@vitest/spy": "3.2.4", @@ -1829,7 +2331,6 @@ "integrity": "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "tinyrainbow": "^2.0.0" }, @@ -1837,13 +2338,42 @@ "url": "https://opencollective.com/vitest" } }, + "node_modules/@vitest/runner": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.4.tgz", + "integrity": "sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "3.2.4", + "pathe": "^2.0.3", + "strip-literal": "^3.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.4.tgz", + "integrity": "sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "3.2.4", + "magic-string": "^0.30.17", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, "node_modules/@vitest/spy": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.4.tgz", "integrity": "sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "tinyspy": "^4.0.3" }, @@ -1857,7 +2387,6 @@ "integrity": "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@vitest/pretty-format": "3.2.4", "loupe": "^3.1.4", @@ -2212,7 +2741,6 @@ "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" } @@ -2417,6 +2945,16 @@ "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", "dev": true }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -2463,7 +3001,6 @@ "integrity": "sha512-5nFxhUrX0PqtyogoYOA8IPswy5sZFTOsBFl/9bNsmDLgsxYTzSZQJDPppDnZPTQbzSEm0hqGjWPzRemQCYbD6A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "assertion-error": "^2.0.1", "check-error": "^2.1.1", @@ -2553,7 +3090,6 @@ "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">= 16" } @@ -2683,6 +3219,20 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/color": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1", + "color-string": "^1.9.0" + }, + "engines": { + "node": ">=12.5.0" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -2703,6 +3253,17 @@ "dev": true, "license": "MIT" }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, "node_modules/colorette": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.3.0.tgz", @@ -2775,13 +3336,24 @@ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.8.tgz", "integrity": "sha512-jXKhWqXPmlUeoQnF/EhTtTl4C9SnrxSH/jZUih3jmO6lBKr99rP3/+FmrMj4EFpOXzMtXHAZkd3x0E6h6Fgflw==" }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", "dev": true, + "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -2804,7 +3376,6 @@ "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6" } @@ -2848,6 +3419,16 @@ "node": ">=6" } }, + "node_modules/detect-libc": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", + "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, "node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -2920,7 +3501,6 @@ "integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -2950,6 +3530,19 @@ "node": ">=6" } }, + "node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -2960,11 +3553,11 @@ } }, "node_modules/es-module-lexer": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.2.tgz", - "integrity": "sha512-l60ETUTmLqbVbVHv1J4/qj+M8nq7AwMzEcg3kmJDt9dCNrTk+yHcYFf/Kw75pMDwd9mPcIGCG5LcS20SxYRzFA==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", "dev": true, - "peer": true + "license": "MIT" }, "node_modules/esbuild": { "version": "0.25.8", @@ -2973,7 +3566,6 @@ "dev": true, "hasInstallScript": true, "license": "MIT", - "peer": true, "bin": { "esbuild": "bin/esbuild" }, @@ -3507,6 +4099,16 @@ "node": ">=10.17.0" } }, + "node_modules/expect-type": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.2.tgz", + "integrity": "sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -3576,6 +4178,30 @@ "reusify": "^1.0.4" } }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -3665,6 +4291,19 @@ "integrity": "sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA==", "dev": true }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, "node_modules/front-matter": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/front-matter/-/front-matter-4.0.2.tgz", @@ -3897,6 +4536,13 @@ "hygen": "dist/bin.js" } }, + "node_modules/hygen/node_modules/@types/node": { + "version": "14.18.63", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.63.tgz", + "integrity": "sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ==", + "dev": true, + "license": "MIT" + }, "node_modules/hygen/node_modules/yargs-parser": { "version": "20.2.9", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", @@ -4580,8 +5226,7 @@ "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.0.tgz", "integrity": "sha512-2NCfZcT5VGVNX9mSZIxLRkEAegDGBpuQZBy13desuHeVORmBDyAET4TkJr4SjqQy3A8JDofMN6LpkK8Xcm/dlw==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/lower-case": { "version": "1.1.4", @@ -4704,10 +5349,11 @@ } }, "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "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", @@ -4721,7 +5367,6 @@ } ], "license": "MIT", - "peer": true, "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -4751,6 +5396,46 @@ "lower-case": "^1.1.1" } }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "deprecated": "Use your platform's native DOMException instead", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, "node_modules/node-releases": { "version": "2.0.19", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", @@ -4937,6 +5622,19 @@ "node": ">=8" } }, + "node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, "node_modules/pascal-case": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-2.0.1.tgz", @@ -4998,13 +5696,19 @@ "node": ">=8" } }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, "node_modules/pathval": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz", "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">= 14.16" } @@ -5057,7 +5761,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -5539,6 +6242,49 @@ "randombytes": "^2.1.0" } }, + "node_modules/sharp": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.3.tgz", + "integrity": "sha512-eX2IQ6nFohW4DbvHIOLRB3MHFpYqaqvXd3Tp5e/T/dSH83fxaNJQRvDMhASmkNTsNTVF2/OOopzRCt7xokgPfg==", + "dev": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "color": "^4.2.3", + "detect-libc": "^2.0.4", + "semver": "^7.7.2" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.34.3", + "@img/sharp-darwin-x64": "0.34.3", + "@img/sharp-libvips-darwin-arm64": "1.2.0", + "@img/sharp-libvips-darwin-x64": "1.2.0", + "@img/sharp-libvips-linux-arm": "1.2.0", + "@img/sharp-libvips-linux-arm64": "1.2.0", + "@img/sharp-libvips-linux-ppc64": "1.2.0", + "@img/sharp-libvips-linux-s390x": "1.2.0", + "@img/sharp-libvips-linux-x64": "1.2.0", + "@img/sharp-libvips-linuxmusl-arm64": "1.2.0", + "@img/sharp-libvips-linuxmusl-x64": "1.2.0", + "@img/sharp-linux-arm": "0.34.3", + "@img/sharp-linux-arm64": "0.34.3", + "@img/sharp-linux-ppc64": "0.34.3", + "@img/sharp-linux-s390x": "0.34.3", + "@img/sharp-linux-x64": "0.34.3", + "@img/sharp-linuxmusl-arm64": "0.34.3", + "@img/sharp-linuxmusl-x64": "0.34.3", + "@img/sharp-wasm32": "0.34.3", + "@img/sharp-win32-arm64": "0.34.3", + "@img/sharp-win32-ia32": "0.34.3", + "@img/sharp-win32-x64": "0.34.3" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -5560,12 +6306,36 @@ "node": ">=8" } }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "node_modules/simple-swizzle/node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", + "dev": true, + "license": "MIT" + }, "node_modules/slice-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", @@ -5623,7 +6393,6 @@ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true, "license": "BSD-3-Clause", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -5653,6 +6422,20 @@ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/std-env": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.9.0.tgz", + "integrity": "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==", + "dev": true, + "license": "MIT" + }, "node_modules/storybook": { "version": "9.1.1", "resolved": "https://registry.npmjs.org/storybook/-/storybook-9.1.1.tgz", @@ -5808,13 +6591,33 @@ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, "license": "MIT", - "engines": { - "node": ">=8" + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-literal": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-3.0.0.tgz", + "integrity": "sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA==", + "dev": true, + "license": "MIT", + "dependencies": { + "js-tokens": "^9.0.1" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/antfu" } }, + "node_modules/strip-literal/node_modules/js-tokens": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz", + "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==", + "dev": true, + "license": "MIT" + }, "node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -5876,7 +6679,6 @@ "integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6" } @@ -5955,13 +6757,26 @@ "dev": true, "license": "MIT" }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", + "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", + "dev": true, + "license": "MIT" + }, "node_modules/tinyglobby": { "version": "0.2.14", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" @@ -5979,7 +6794,6 @@ "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", "dev": true, "license": "MIT", - "peer": true, "peerDependencies": { "picomatch": "^3 || ^4" }, @@ -5995,7 +6809,6 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -6003,13 +6816,22 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/tinypool": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", + "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.0.0 || >=20.0.0" + } + }, "node_modules/tinyrainbow": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz", "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=14.0.0" } @@ -6020,7 +6842,6 @@ "integrity": "sha512-t2T/WLB2WRgZ9EpE4jgPJ9w+i66UZfDc8wHh0xrwiRNN+UwH98GIJkTeZqX9rg0i0ptwzqW+uYeIF0T4F8LR7A==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=14.0.0" } @@ -6094,117 +6915,485 @@ "prelude-ls": "^1.2.1" }, "engines": { - "node": ">= 0.8.0" + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/typescript": { + "version": "5.9.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", + "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz", + "integrity": "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "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/update-browserslist-db": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/upper-case": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", + "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=", + "dev": true + }, + "node_modules/upper-case-first": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-1.1.2.tgz", + "integrity": "sha1-XXm+3P8UQZUY/S7bCgUHybaFkRU=", + "dev": true, + "dependencies": { + "upper-case": "^1.1.1" + } + }, + "node_modules/uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/vite-node": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.2.4.tgz", + "integrity": "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.4.1", + "es-module-lexer": "^1.7.0", + "pathe": "^2.0.3", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vite-node/node_modules/fdir": { + "version": "6.4.6", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", + "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/vite-node/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", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/vite-node/node_modules/vite": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.2.tgz", + "integrity": "sha512-J0SQBPlQiEXAF7tajiH+rUooJPo0l8KQgyg4/aMunNtrOa7bwuZJsJbDWzeljqQpgftxuq5yNJxQ91O9ts29UQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.4.6", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.14" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "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/vite-node/node_modules/yaml": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz", + "integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==", + "dev": true, + "license": "ISC", + "optional": true, + "peer": true, + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" } }, - "node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "node_modules/vitest": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.4.tgz", + "integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==", "dev": true, + "license": "MIT", + "dependencies": { + "@types/chai": "^5.2.2", + "@vitest/expect": "3.2.4", + "@vitest/mocker": "3.2.4", + "@vitest/pretty-format": "^3.2.4", + "@vitest/runner": "3.2.4", + "@vitest/snapshot": "3.2.4", + "@vitest/spy": "3.2.4", + "@vitest/utils": "3.2.4", + "chai": "^5.2.0", + "debug": "^4.4.1", + "expect-type": "^1.2.1", + "magic-string": "^0.30.17", + "pathe": "^2.0.3", + "picomatch": "^4.0.2", + "std-env": "^3.9.0", + "tinybench": "^2.9.0", + "tinyexec": "^0.3.2", + "tinyglobby": "^0.2.14", + "tinypool": "^1.1.1", + "tinyrainbow": "^2.0.0", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0", + "vite-node": "3.2.4", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, "engines": { - "node": ">=8" + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/debug": "^4.1.12", + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "@vitest/browser": "3.2.4", + "@vitest/ui": "3.2.4", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/debug": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } } }, - "node_modules/typescript": { - "version": "5.9.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", - "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", + "node_modules/vitest/node_modules/@vitest/mocker": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.4.tgz", + "integrity": "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==", "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" + "license": "MIT", + "dependencies": { + "@vitest/spy": "3.2.4", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.17" }, - "engines": { - "node": ">=14.17" + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } } }, - "node_modules/undici-types": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz", - "integrity": "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==", + "node_modules/vitest/node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", "dev": true, "license": "MIT", - "optional": true, - "peer": true + "dependencies": { + "@types/estree": "^1.0.0" + } }, - "node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "node_modules/vitest/node_modules/fdir": { + "version": "6.4.6", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", + "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", "dev": true, - "engines": { - "node": ">= 10.0.0" + "license": "MIT", + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } } }, - "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==", + "node_modules/vitest/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", - "dependencies": { - "acorn": "^8.14.0", - "webpack-virtual-modules": "^0.6.2" - }, "engines": { - "node": ">=14.0.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/update-browserslist-db": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", - "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "node_modules/vitest/node_modules/vite": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.2.tgz", + "integrity": "sha512-J0SQBPlQiEXAF7tajiH+rUooJPo0l8KQgyg4/aMunNtrOa7bwuZJsJbDWzeljqQpgftxuq5yNJxQ91O9ts29UQ==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], "license": "MIT", "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" + "esbuild": "^0.25.0", + "fdir": "^6.4.6", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.14" }, "bin": { - "update-browserslist-db": "cli.js" + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" }, "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/upper-case": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", - "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=", - "dev": true - }, - "node_modules/upper-case-first": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-1.1.2.tgz", - "integrity": "sha1-XXm+3P8UQZUY/S7bCgUHybaFkRU=", - "dev": true, - "dependencies": { - "upper-case": "^1.1.1" + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "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/uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "node_modules/vitest/node_modules/yaml": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz", + "integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==", "dev": true, - "dependencies": { - "punycode": "^2.1.0" + "license": "ISC", + "optional": true, + "peer": true, + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" } }, "node_modules/vscode-json-languageservice": { @@ -6278,6 +7467,16 @@ "node": ">=14.17" } }, + "node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, "node_modules/webpack": { "version": "5.101.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.101.0.tgz", @@ -6389,6 +7588,23 @@ "node": ">= 8" } }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", diff --git a/package.json b/package.json index c3d67ff..5a2c67f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@wokwi/elements", - "version": "1.8.1", + "version": "1.9.0", "main": "dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/esm/index.d.ts", @@ -16,6 +16,7 @@ "devDependencies": { "@babel/core": "^7.15.0", "@babel/runtime": "^7.15.3", + "@lit-labs/ssr": "^3.3.1", "@rollup/plugin-commonjs": "^28.0.6", "@rollup/plugin-node-resolve": "^16.0.1", "@storybook/addon-docs": "9.1.1", @@ -36,8 +37,10 @@ "react-is": "^16.13.1", "rimraf": "^3.0.2", "rollup": "^4.46.2", + "sharp": "^0.34.3", "terser": "^5.43.1", "typescript": "^5.9.0", + "vitest": "^3.2.4", "web-component-analyzer": "^2.0.0" }, "dependencies": { @@ -46,7 +49,8 @@ }, "scripts": { "build": "rimraf dist && tsc --sourceMap false && tsc -m esnext --outDir dist/esm --sourceMap false && rollup -c rollup.config.mjs && terser -c -m -o dist/wokwi-elements.bundle.min.js dist/wokwi-elements.bundle.js", - "test": "npm run lint", + "test": "vitest run", + "test:watch": "vitest", "lint": "eslint src/**/*.ts", "prepare": "husky install && npm run build", "analyze-components": "web-component-analyzer analyze src/*-element.ts --outFile custom-elements.json", diff --git a/src/7segment-element.spec.ts b/src/7segment-element.spec.ts new file mode 100644 index 0000000..84c0507 --- /dev/null +++ b/src/7segment-element.spec.ts @@ -0,0 +1,10 @@ +import { describe, it } from 'vitest'; +import { SevenSegmentElement } from './7segment-element'; +import { renderToPng, savePng } from './utils/test-utils'; + +describe('SevenSegmentElement', () => { + it('should render to svg', async () => { + const pngData = await renderToPng(new SevenSegmentElement(), SevenSegmentElement.styles); + await savePng('wokwi-7segment', pngData); + }); +}); diff --git a/src/analog-joystick-element.spec.ts b/src/analog-joystick-element.spec.ts new file mode 100644 index 0000000..1d60678 --- /dev/null +++ b/src/analog-joystick-element.spec.ts @@ -0,0 +1,10 @@ +import { describe, it } from 'vitest'; +import { AnalogJoystickElement } from './analog-joystick-element'; +import { renderToPng, savePng } from './utils/test-utils'; + +describe('AnalogJoystickElement', () => { + it('should render to svg', async () => { + const pngData = await renderToPng(new AnalogJoystickElement(), AnalogJoystickElement.styles); + await savePng('wokwi-analog-joystick', pngData); + }); +}); diff --git a/src/arduino-mega-element.spec.ts b/src/arduino-mega-element.spec.ts new file mode 100644 index 0000000..c37889f --- /dev/null +++ b/src/arduino-mega-element.spec.ts @@ -0,0 +1,10 @@ +import { describe, it } from 'vitest'; +import { ArduinoMegaElement } from './arduino-mega-element'; +import { renderToPng, savePng } from './utils/test-utils'; + +describe('ArduinoMegaElement', () => { + it('should render to svg', async () => { + const pngData = await renderToPng(new ArduinoMegaElement(), ArduinoMegaElement.styles); + await savePng('wokwi-arduino-mega', pngData); + }); +}); diff --git a/src/arduino-nano-element.spec.ts b/src/arduino-nano-element.spec.ts new file mode 100644 index 0000000..7157e12 --- /dev/null +++ b/src/arduino-nano-element.spec.ts @@ -0,0 +1,10 @@ +import { describe, it } from 'vitest'; +import { ArduinoNanoElement } from './arduino-nano-element'; +import { renderToPng, savePng } from './utils/test-utils'; + +describe('ArduinoNanoElement', () => { + it('should render to svg', async () => { + const pngData = await renderToPng(new ArduinoNanoElement(), ArduinoNanoElement.styles); + await savePng('wokwi-arduino-nano', pngData); + }); +}); diff --git a/src/arduino-uno-element.spec.ts b/src/arduino-uno-element.spec.ts new file mode 100644 index 0000000..7c50c55 --- /dev/null +++ b/src/arduino-uno-element.spec.ts @@ -0,0 +1,10 @@ +import { describe, it } from 'vitest'; +import { ArduinoUnoElement } from './arduino-uno-element'; +import { renderToPng, savePng } from './utils/test-utils'; + +describe('ArduinoUnoElement', () => { + it('should render to svg', async () => { + const pngData = await renderToPng(new ArduinoUnoElement(), ArduinoUnoElement.styles); + await savePng('wokwi-arduino-uno', pngData); + }); +}); diff --git a/src/biaxial-stepper-element.spec.ts b/src/biaxial-stepper-element.spec.ts new file mode 100644 index 0000000..b92c931 --- /dev/null +++ b/src/biaxial-stepper-element.spec.ts @@ -0,0 +1,10 @@ +import { describe, it } from 'vitest'; +import { BiaxialStepperElement } from './biaxial-stepper-element'; +import { renderToPng, savePng } from './utils/test-utils'; + +describe('BiaxialStepperElement', () => { + it('should render to svg', async () => { + const pngData = await renderToPng(new BiaxialStepperElement()); + await savePng('wokwi-biaxial-stepper', pngData); + }); +}); diff --git a/src/big-sound-sensor-element.spec.ts b/src/big-sound-sensor-element.spec.ts new file mode 100644 index 0000000..706cd7d --- /dev/null +++ b/src/big-sound-sensor-element.spec.ts @@ -0,0 +1,10 @@ +import { describe, it } from 'vitest'; +import { BigSoundSensorElement } from './big-sound-sensor-element'; +import { renderToPng, savePng } from './utils/test-utils'; + +describe('BigSoundSensorElement', () => { + it('should render to svg', async () => { + const pngData = await renderToPng(new BigSoundSensorElement()); + await savePng('wokwi-big-sound-sensor', pngData); + }); +}); diff --git a/src/buzzer-element.spec.ts b/src/buzzer-element.spec.ts new file mode 100644 index 0000000..fec23c8 --- /dev/null +++ b/src/buzzer-element.spec.ts @@ -0,0 +1,10 @@ +import { describe, it } from 'vitest'; +import { BuzzerElement } from './buzzer-element'; +import { renderToPng, savePng } from './utils/test-utils'; + +describe('BuzzerElement', () => { + it('should render to svg', async () => { + const pngData = await renderToPng(new BuzzerElement(), BuzzerElement.styles); + await savePng('wokwi-buzzer', pngData); + }); +}); diff --git a/src/buzzer-element.ts b/src/buzzer-element.ts index 3897bd3..14a0b0f 100644 --- a/src/buzzer-element.ts +++ b/src/buzzer-element.ts @@ -66,6 +66,41 @@ export class BuzzerElement extends LitElement { `; } + renderSVG() { + return html` + + + + + + + + + + + `; + } + render() { const buzzerOn = this.hasSignal; return html` @@ -82,39 +117,7 @@ export class BuzzerElement extends LitElement { d="M8 0c-5 0-6 1-6 1v4.09c-.15-.05-.33-.09-.5-.09-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5v-3.97c.73-.23 1.99-.44 4-.5v2.06c-.15-.05-.33-.09-.5-.09-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5v-5.5z" /> - - - - - - - - - - - - - + ${this.renderSVG()} `; } diff --git a/src/dht22-element.spec.ts b/src/dht22-element.spec.ts new file mode 100644 index 0000000..aab1182 --- /dev/null +++ b/src/dht22-element.spec.ts @@ -0,0 +1,10 @@ +import { describe, it } from 'vitest'; +import { DHT22Element } from './dht22-element'; +import { renderToPng, savePng } from './utils/test-utils'; + +describe('DHT22Element', () => { + it('should render to svg', async () => { + const pngData = await renderToPng(new DHT22Element()); + await savePng('wokwi-dht22', pngData); + }); +}); diff --git a/src/dip-switch-8-element.spec.ts b/src/dip-switch-8-element.spec.ts new file mode 100644 index 0000000..0a39033 --- /dev/null +++ b/src/dip-switch-8-element.spec.ts @@ -0,0 +1,10 @@ +import { describe, it } from 'vitest'; +import { DipSwitch8Element } from './dip-switch-8-element'; +import { renderToPng, savePng } from './utils/test-utils'; + +describe('DipSwitch8Element', () => { + it('should render to svg', async () => { + const pngData = await renderToPng(new DipSwitch8Element()); + await savePng('wokwi-dip-switch-8', pngData); + }); +}); diff --git a/src/ds1307-element.spec.ts b/src/ds1307-element.spec.ts new file mode 100644 index 0000000..a4b40e4 --- /dev/null +++ b/src/ds1307-element.spec.ts @@ -0,0 +1,10 @@ +import { describe, it } from 'vitest'; +import { Ds1307Element } from './ds1307-element'; +import { renderToPng, savePng } from './utils/test-utils'; + +describe('Ds1307Element', () => { + it('should render to svg', async () => { + const pngData = await renderToPng(new Ds1307Element()); + await savePng('wokwi-ds1307', pngData); + }); +}); diff --git a/src/esp32-devkit-v1-element.spec.ts b/src/esp32-devkit-v1-element.spec.ts new file mode 100644 index 0000000..9425168 --- /dev/null +++ b/src/esp32-devkit-v1-element.spec.ts @@ -0,0 +1,10 @@ +import { describe, it } from 'vitest'; +import { ESP32DevkitV1Element } from './esp32-devkit-v1-element'; +import { renderToPng, savePng } from './utils/test-utils'; + +describe('ESP32DevkitV1Element', () => { + it('should render to svg', async () => { + const pngData = await renderToPng(new ESP32DevkitV1Element()); + await savePng('wokwi-esp32-devkit-v1', pngData); + }); +}); diff --git a/src/flame-sensor-element.spec.ts b/src/flame-sensor-element.spec.ts new file mode 100644 index 0000000..c8344ee --- /dev/null +++ b/src/flame-sensor-element.spec.ts @@ -0,0 +1,10 @@ +import { describe, it } from 'vitest'; +import { FlameSensorElement } from './flame-sensor-element'; +import { renderToPng, savePng } from './utils/test-utils'; + +describe('FlameSensorElement', () => { + it('should render to svg', async () => { + const pngData = await renderToPng(new FlameSensorElement()); + await savePng('wokwi-flame-sensor', pngData); + }); +}); diff --git a/src/franzininho-element.spec.ts b/src/franzininho-element.spec.ts new file mode 100644 index 0000000..42325de --- /dev/null +++ b/src/franzininho-element.spec.ts @@ -0,0 +1,10 @@ +import { describe, it } from 'vitest'; +import { FranzininhoElement } from './franzininho-element'; +import { renderToPng, savePng } from './utils/test-utils'; + +describe('FranzininhoElement', () => { + it('should render to svg', async () => { + const pngData = await renderToPng(new FranzininhoElement(), FranzininhoElement.styles); + await savePng('wokwi-franzininho', pngData); + }); +}); diff --git a/src/gas-sensor-element.spec.ts b/src/gas-sensor-element.spec.ts new file mode 100644 index 0000000..cb4787e --- /dev/null +++ b/src/gas-sensor-element.spec.ts @@ -0,0 +1,10 @@ +import { describe, it } from 'vitest'; +import { GasSensorElement } from './gas-sensor-element'; +import { renderToPng, savePng } from './utils/test-utils'; + +describe('GasSensorElement', () => { + it('should render to svg', async () => { + const pngData = await renderToPng(new GasSensorElement()); + await savePng('wokwi-gas-sensor', pngData); + }); +}); diff --git a/src/hc-sr04-element.spec.ts b/src/hc-sr04-element.spec.ts new file mode 100644 index 0000000..e617751 --- /dev/null +++ b/src/hc-sr04-element.spec.ts @@ -0,0 +1,10 @@ +import { describe, it } from 'vitest'; +import { HCSR04Element } from './hc-sr04-element'; +import { renderToPng, savePng } from './utils/test-utils'; + +describe('HCSR04Element', () => { + it('should render to svg', async () => { + const pngData = await renderToPng(new HCSR04Element()); + await savePng('wokwi-hc-sr04', pngData); + }); +}); diff --git a/src/heart-beat-sensor-element.spec.ts b/src/heart-beat-sensor-element.spec.ts new file mode 100644 index 0000000..7e18eaf --- /dev/null +++ b/src/heart-beat-sensor-element.spec.ts @@ -0,0 +1,10 @@ +import { describe, it } from 'vitest'; +import { HeartBeatSensorElement } from './heart-beat-sensor-element'; +import { renderToPng, savePng } from './utils/test-utils'; + +describe('HeartBeatSensorElement', () => { + it('should render to svg', async () => { + const pngData = await renderToPng(new HeartBeatSensorElement()); + await savePng('wokwi-heart-beat-sensor', pngData); + }); +}); diff --git a/src/hx711-element.spec.ts b/src/hx711-element.spec.ts new file mode 100644 index 0000000..5aec5df --- /dev/null +++ b/src/hx711-element.spec.ts @@ -0,0 +1,10 @@ +import { describe, it } from 'vitest'; +import { HX711Element } from './hx711-element'; +import { renderToPng, savePng } from './utils/test-utils'; + +describe('HX711Element', () => { + it('should render to svg', async () => { + const pngData = await renderToPng(new HX711Element(), HX711Element.styles); + await savePng('wokwi-hx711', pngData); + }); +}); diff --git a/src/hx711-element.ts b/src/hx711-element.ts index 5e5fa8d..57e39ec 100644 --- a/src/hx711-element.ts +++ b/src/hx711-element.ts @@ -1,4 +1,4 @@ -import { html, LitElement, svg } from 'lit'; +import { css, html, LitElement, svg } from 'lit'; import { customElement, property } from 'lit/decorators.js'; import { ElementPin, GND, VCC } from './pin'; @@ -26,6 +26,14 @@ export class HX711Element extends LitElement { } } + static get styles() { + return css` + text { + user-select: none; + } + `; + } + renderSensor() { switch (this.type) { case 'gauge': @@ -227,11 +235,6 @@ export class HX711Element extends LitElement { render() { const { width, height } = this.dimension; return html` - { + it('should render to svg', async () => { + const pngData = await renderToPng(new ILI9341Element(), ILI9341Element.styles); + await savePng('wokwi-ili9341', pngData); + }); +}); diff --git a/src/ili9341-element.ts b/src/ili9341-element.ts index 9717d08..2766e98 100644 --- a/src/ili9341-element.ts +++ b/src/ili9341-element.ts @@ -51,6 +51,70 @@ export class ILI9341Element extends LitElement { this.dispatchEvent(new CustomEvent('canvas-ready')); } + renderSVG() { + return html` + + + + + + + + + + + + + + + + + + + + + + + 1 + 9 + ILI9341 + + `; + } + render() { const { screenWidth, screenHeight, flipHorizontal, flipVertical } = this; const flip = flipHorizontal || flipVertical; @@ -59,67 +123,7 @@ export class ILI9341Element extends LitElement { const canvasStyle = flip ? `transform: scaleX(${scaleX}) scaleY(${scaleY});` : ''; return html`
- - - - - - - - - - - - - - - - - - - - - - - - 1 - 9 - ILI9341 - - + ${this.renderSVG()} { + it('should render to svg', async () => { + const pngData = await renderToPng(new IRReceiverElement()); + await savePng('wokwi-ir-receiver', pngData); + }); +}); diff --git a/src/ir-remote-element.spec.ts b/src/ir-remote-element.spec.ts new file mode 100644 index 0000000..deb1d86 --- /dev/null +++ b/src/ir-remote-element.spec.ts @@ -0,0 +1,10 @@ +import { describe, it } from 'vitest'; +import { IRRemoteElement } from './ir-remote-element'; +import { renderToPng, savePng } from './utils/test-utils'; + +describe('IRRemoteElement', () => { + it('should render to svg', async () => { + const pngData = await renderToPng(new IRRemoteElement(), IRRemoteElement.styles); + await savePng('wokwi-ir-remote', pngData); + }); +}); diff --git a/src/ks2e-m-dc5-element.spec.ts b/src/ks2e-m-dc5-element.spec.ts new file mode 100644 index 0000000..7c4a574 --- /dev/null +++ b/src/ks2e-m-dc5-element.spec.ts @@ -0,0 +1,10 @@ +import { describe, it } from 'vitest'; +import { KS2EMDC5Element } from './ks2e-m-dc5-element'; +import { renderToPng, savePng } from './utils/test-utils'; + +describe('KS2EMDC5Element', () => { + it('should render to svg', async () => { + const pngData = await renderToPng(new KS2EMDC5Element()); + await savePng('wokwi-ks2e-m-dc5', pngData); + }); +}); diff --git a/src/ky-040-element.spec.ts b/src/ky-040-element.spec.ts new file mode 100644 index 0000000..8e716a8 --- /dev/null +++ b/src/ky-040-element.spec.ts @@ -0,0 +1,10 @@ +import { describe, it } from 'vitest'; +import { KY040Element } from './ky-040-element'; +import { renderToPng, savePng } from './utils/test-utils'; + +describe('KY040Element', () => { + it('should render to svg', async () => { + const pngData = await renderToPng(new KY040Element(), KY040Element.styles); + await savePng('wokwi-ky-040', pngData); + }); +}); diff --git a/src/lcd1602-element.spec.ts b/src/lcd1602-element.spec.ts new file mode 100644 index 0000000..177ac7d --- /dev/null +++ b/src/lcd1602-element.spec.ts @@ -0,0 +1,10 @@ +import { describe, it } from 'vitest'; +import { LCD1602Element } from './lcd1602-element'; +import { renderToPng, savePng } from './utils/test-utils'; + +describe('LCD1602Element', () => { + it('should render to svg', async () => { + const pngData = await renderToPng(new LCD1602Element(), LCD1602Element.styles); + await savePng('wokwi-lcd1602', pngData); + }); +}); diff --git a/src/lcd1602-element.stories.ts b/src/lcd1602-element.stories.ts index 96d5105..d16198d 100644 --- a/src/lcd1602-element.stories.ts +++ b/src/lcd1602-element.stories.ts @@ -16,6 +16,7 @@ interface LCD1602Args { cursorY: number; pins: string; text: string; + screenOnly: boolean; } const meta: Meta = { @@ -31,6 +32,7 @@ const meta: Meta = { color: 'black', cursor: false, pins: 'full', + screenOnly: false, } satisfies LCD1602Args, parameters: { docs: { @@ -55,6 +57,7 @@ const Template = (args: LCD1602Args) => html` .color=${args.color} .background=${args.background} .pins=${args.pins} + .screenOnly=${args.screenOnly} > `; @@ -119,3 +122,9 @@ NoPins.args = { text: 'Look ma! I got no pins', pins: 'none', }; + +export const ScreenOnly: Story = Template.bind({}); +ScreenOnly.args = { + text: 'Screen Only', + screenOnly: true, +}; diff --git a/src/lcd1602-element.ts b/src/lcd1602-element.ts index eadd942..a650b4b 100644 --- a/src/lcd1602-element.ts +++ b/src/lcd1602-element.ts @@ -24,6 +24,7 @@ export class LCD1602Element extends LitElement { @property() cursorY = 0; @property() backlight = true; @property() pins: 'full' | 'i2c' | 'none' = 'full'; + @property() screenOnly = false; protected numCols = 16; protected numRows = 2; @@ -221,8 +222,14 @@ export class LCD1602Element extends LitElement { background in backgroundColors ? backgroundColors[background] : backgroundColors; const panelWidth = cols * 3.5125; - const width = panelWidth + 23.8; - const height = panelHeight + 24.5; + const width = this.screenOnly ? panelWidth : panelWidth + 23.8; + const height = this.screenOnly ? panelHeight : panelHeight + 24.5; + + const panelX = 12.45; + const panelY = 12.55; + const viewBox = this.screenOnly + ? `${panelX} ${panelY} ${panelWidth} ${panelHeight}` + : `0 0 ${width} ${height}`; // Dimensions according to: // https://www.winstar.com.tw/products/character-lcd-display-module/16x2-lcd.html @@ -231,7 +238,7 @@ export class LCD1602Element extends LitElement { width="${width}mm" height="${height}mm" version="1.1" - viewBox="0 0 ${width} ${height}" + viewBox="${viewBox}" style="font-size: 1.5px; font-family: monospace" xmlns="http://www.w3.org/2000/svg" > @@ -277,13 +284,17 @@ export class LCD1602Element extends LitElement { ${pins === 'i2c' ? this.renderI2CPins() : null} ${pins === 'full' ? this.renderPins(panelHeight) : null} - + ${this.renderCursor()} `; diff --git a/src/lcd2004-element.stories.ts b/src/lcd2004-element.stories.ts index 6ae056a..e1f5b3c 100644 --- a/src/lcd2004-element.stories.ts +++ b/src/lcd2004-element.stories.ts @@ -20,3 +20,6 @@ export const BlueBackground = () => export const I2cPins = () => html``; I2cPins.storyName = 'I2C Pins'; + +export const ScreenOnly = () => + html``; diff --git a/src/led-bar-graph-element.spec.ts b/src/led-bar-graph-element.spec.ts new file mode 100644 index 0000000..dd51400 --- /dev/null +++ b/src/led-bar-graph-element.spec.ts @@ -0,0 +1,10 @@ +import { describe, it } from 'vitest'; +import { LedBarGraphElement } from './led-bar-graph-element'; +import { renderToPng, savePng } from './utils/test-utils'; + +describe('LedBarGraphElement', () => { + it('should render to svg', async () => { + const pngData = await renderToPng(new LedBarGraphElement()); + await savePng('wokwi-led-bar-graph', pngData); + }); +}); diff --git a/src/led-element.spec.ts b/src/led-element.spec.ts new file mode 100644 index 0000000..a59fad4 --- /dev/null +++ b/src/led-element.spec.ts @@ -0,0 +1,10 @@ +import { describe, it } from 'vitest'; +import { LEDElement } from './led-element'; +import { renderToPng, savePng } from './utils/test-utils'; + +describe('LEDElement', () => { + it('should render to svg', async () => { + const pngData = await renderToPng(new LEDElement(), LEDElement.styles); + await savePng('wokwi-led', pngData); + }); +}); diff --git a/src/led-element.ts b/src/led-element.ts index f73b5ae..4bd8f13 100644 --- a/src/led-element.ts +++ b/src/led-element.ts @@ -61,109 +61,113 @@ export class LEDElement extends LitElement { super.update(changedProperties); } - render() { + renderSVG() { const { color, lightColor, flip } = this; const lightColorActual = lightColor || lightColors[color?.toLowerCase()] || color; const opacity = this.brightness ? 0.3 + this.brightness * 0.7 : 0; const lightOn = this.value && this.brightness > Number.EPSILON; const xScale = flip ? -1 : 1; + return html` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + `; + } + + render() { return html`
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ${this.renderSVG()} ${this.label}
`; diff --git a/src/led-ring-element.spec.ts b/src/led-ring-element.spec.ts new file mode 100644 index 0000000..0f20ddf --- /dev/null +++ b/src/led-ring-element.spec.ts @@ -0,0 +1,10 @@ +import { describe, it } from 'vitest'; +import { LEDRingElement } from './led-ring-element'; +import { renderToPng, savePng } from './utils/test-utils'; + +describe('LEDRingElement', () => { + it('should render to svg', async () => { + const pngData = await renderToPng(new LEDRingElement()); + await savePng('wokwi-led-ring', pngData); + }); +}); diff --git a/src/membrane-keypad-element.spec.ts b/src/membrane-keypad-element.spec.ts new file mode 100644 index 0000000..68a7ab2 --- /dev/null +++ b/src/membrane-keypad-element.spec.ts @@ -0,0 +1,10 @@ +import { describe, it } from 'vitest'; +import { MembraneKeypadElement } from './membrane-keypad-element'; +import { renderToPng, savePng } from './utils/test-utils'; + +describe('MembraneKeypadElement', () => { + it('should render to svg', async () => { + const pngData = await renderToPng(new MembraneKeypadElement(), MembraneKeypadElement.styles); + await savePng('wokwi-membrane-keypad', pngData); + }); +}); diff --git a/src/membrane-keypad-element.ts b/src/membrane-keypad-element.ts index 26f6710..5b6380b 100644 --- a/src/membrane-keypad-element.ts +++ b/src/membrane-keypad-element.ts @@ -1,4 +1,4 @@ -import { html, LitElement, svg } from 'lit'; +import { css, html, LitElement, svg } from 'lit'; import { customElement, property } from 'lit/decorators.js'; import { pinsFemalePattern } from './patterns/pins-female'; import { ElementPin } from './pin'; @@ -61,6 +61,51 @@ export class MembraneKeypadElement extends LitElement { } } + static get styles() { + return css` + text { + fill: #dfe2e5; + user-select: none; + } + + g[tabindex] { + cursor: pointer; + } + + g[tabindex]:focus, + g[tabindex]:active { + stroke: white; + outline: none; + } + + .blue-key:focus, + .red-key:focus { + filter: url(#shadow); + } + + .blue-key:active, + .blue-key.pressed { + fill: #4e50d7; + } + + .red-key:active, + .red-key.pressed { + fill: #ab040b; + } + + g[tabindex]:focus text { + stroke: none; + } + + g[tabindex]:active text, + .blue-key.pressed text, + .red-key.pressed text { + fill: white; + stroke: none; + } + `; + } + update(changedProperties: Map) { if (changedProperties.has('columns')) { this.dispatchEvent(new CustomEvent('pininfo-change')); @@ -92,7 +137,7 @@ export class MembraneKeypadElement extends LitElement { @keyup=${(e: KeyboardEvent) => SPACE_KEYS.includes(e.key) && this.up(text, e.currentTarget as SVGElement)} > - + ${text} `; } @@ -107,49 +152,6 @@ export class MembraneKeypadElement extends LitElement { const height = 76 + (connector ? 15 : 0); return html` - - this.keyStrokeUp(e.key)} > - diff --git a/src/microsd-card-element.spec.ts b/src/microsd-card-element.spec.ts new file mode 100644 index 0000000..6e27b24 --- /dev/null +++ b/src/microsd-card-element.spec.ts @@ -0,0 +1,10 @@ +import { describe, it } from 'vitest'; +import { MicrosdCardElement } from './microsd-card-element'; +import { renderToPng, savePng } from './utils/test-utils'; + +describe('MicrosdCardElement', () => { + it('should render to svg', async () => { + const pngData = await renderToPng(new MicrosdCardElement()); + await savePng('wokwi-microsd-card', pngData); + }); +}); diff --git a/src/mpu6050-element.spec.ts b/src/mpu6050-element.spec.ts new file mode 100644 index 0000000..eb48842 --- /dev/null +++ b/src/mpu6050-element.spec.ts @@ -0,0 +1,10 @@ +import { describe, it } from 'vitest'; +import { MPU6050Element } from './mpu6050-element'; +import { renderToPng, savePng } from './utils/test-utils'; + +describe('MPU6050Element', () => { + it('should render to svg', async () => { + const pngData = await renderToPng(new MPU6050Element()); + await savePng('wokwi-mpu6050', pngData); + }); +}); diff --git a/src/nano-rp2040-connect-element.spec.ts b/src/nano-rp2040-connect-element.spec.ts new file mode 100644 index 0000000..aedd2de --- /dev/null +++ b/src/nano-rp2040-connect-element.spec.ts @@ -0,0 +1,10 @@ +import { describe, it } from 'vitest'; +import { NanoRP2040ConnectElement } from './nano-rp2040-connect-element'; +import { renderToPng, savePng } from './utils/test-utils'; + +describe('NanoRP2040ConnectElement', () => { + it('should render to svg', async () => { + const pngData = await renderToPng(new NanoRP2040ConnectElement()); + await savePng('wokwi-nano-rp2040-connect', pngData); + }); +}); diff --git a/src/neopixel-element.spec.ts b/src/neopixel-element.spec.ts new file mode 100644 index 0000000..8dce8cd --- /dev/null +++ b/src/neopixel-element.spec.ts @@ -0,0 +1,10 @@ +import { describe, it } from 'vitest'; +import { NeoPixelElement } from './neopixel-element'; +import { renderToPng, savePng } from './utils/test-utils'; + +describe('NeoPixelElement', () => { + it('should render to svg', async () => { + const pngData = await renderToPng(new NeoPixelElement()); + await savePng('wokwi-neopixel', pngData); + }); +}); diff --git a/src/neopixel-matrix-element.spec.ts b/src/neopixel-matrix-element.spec.ts new file mode 100644 index 0000000..4f363fe --- /dev/null +++ b/src/neopixel-matrix-element.spec.ts @@ -0,0 +1,10 @@ +import { describe, it } from 'vitest'; +import { NeopixelMatrixElement } from './neopixel-matrix-element'; +import { renderToPng, savePng } from './utils/test-utils'; + +describe('NeopixelMatrixElement', () => { + it('should render to svg', async () => { + const pngData = await renderToPng(new NeopixelMatrixElement(), NeopixelMatrixElement.styles); + await savePng('wokwi-neopixel-matrix', pngData); + }); +}); diff --git a/src/ntc-temperature-sensor-element.spec.ts b/src/ntc-temperature-sensor-element.spec.ts new file mode 100644 index 0000000..5fff0eb --- /dev/null +++ b/src/ntc-temperature-sensor-element.spec.ts @@ -0,0 +1,10 @@ +import { describe, it } from 'vitest'; +import { NTCTemperatureSensorElement } from './ntc-temperature-sensor-element'; +import { renderToPng, savePng } from './utils/test-utils'; + +describe('NTCTemperatureSensorElement', () => { + it('should render to svg', async () => { + const pngData = await renderToPng(new NTCTemperatureSensorElement()); + await savePng('wokwi-ntc-temperature-sensor', pngData); + }); +}); diff --git a/src/photoresistor-sensor-element.spec.ts b/src/photoresistor-sensor-element.spec.ts new file mode 100644 index 0000000..f33acfc --- /dev/null +++ b/src/photoresistor-sensor-element.spec.ts @@ -0,0 +1,10 @@ +import { describe, it } from 'vitest'; +import { PhotoresistorSensorElement } from './photoresistor-sensor-element'; +import { renderToPng, savePng } from './utils/test-utils'; + +describe('PhotoresistorSensorElement', () => { + it('should render to svg', async () => { + const pngData = await renderToPng(new PhotoresistorSensorElement()); + await savePng('wokwi-photoresistor-sensor', pngData); + }); +}); diff --git a/src/pir-motion-sensor-element.spec.ts b/src/pir-motion-sensor-element.spec.ts new file mode 100644 index 0000000..af2f557 --- /dev/null +++ b/src/pir-motion-sensor-element.spec.ts @@ -0,0 +1,10 @@ +import { describe, it } from 'vitest'; +import { PIRMotionSensorElement } from './pir-motion-sensor-element'; +import { renderToPng, savePng } from './utils/test-utils'; + +describe('PIRMotionSensorElement', () => { + it('should render to svg', async () => { + const pngData = await renderToPng(new PIRMotionSensorElement()); + await savePng('wokwi-pir-motion-sensor', pngData); + }); +}); diff --git a/src/potentiometer-element.spec.ts b/src/potentiometer-element.spec.ts new file mode 100644 index 0000000..372b6ce --- /dev/null +++ b/src/potentiometer-element.spec.ts @@ -0,0 +1,10 @@ +import { describe, it } from 'vitest'; +import { PotentiometerElement } from './potentiometer-element'; +import { renderToPng, savePng } from './utils/test-utils'; + +describe('PotentiometerElement', () => { + it('should render to svg', async () => { + const pngData = await renderToPng(new PotentiometerElement(), PotentiometerElement.styles); + await savePng('wokwi-potentiometer', pngData); + }); +}); diff --git a/src/potentiometer-element.ts b/src/potentiometer-element.ts index 65a790d..03f0f6c 100644 --- a/src/potentiometer-element.ts +++ b/src/potentiometer-element.ts @@ -66,10 +66,77 @@ export class PotentiometerElement extends LitElement { return (value - min) / (max - min); } - render() { + renderSVG() { const percent = clamp(0, 1, this.percentFromMinMax(this.value, this.min, this.max)); const knobDeg = (this.endDegree - this.startDegree) * percent + this.startDegree; + return html` + + + + + + + + + + + GND + SIG + VCC + + + + + + + + + + + + + + + + `; + } + + render() { return html` - - - - - - - - - - - - GND - SIG - VCC - - - - - - - - - - - - - - - - + ${this.renderSVG()} `; } diff --git a/src/pushbutton-6mm-element.spec.ts b/src/pushbutton-6mm-element.spec.ts new file mode 100644 index 0000000..b01fbc8 --- /dev/null +++ b/src/pushbutton-6mm-element.spec.ts @@ -0,0 +1,10 @@ +import { describe, it } from 'vitest'; +import { Pushbutton6mmElement } from './pushbutton-6mm-element'; +import { renderToPng, savePng } from './utils/test-utils'; + +describe('Pushbutton6mmElement', () => { + it('should render to svg', async () => { + const pngData = await renderToPng(new Pushbutton6mmElement(), Pushbutton6mmElement.styles); + await savePng('wokwi-pushbutton-6mm', pngData); + }); +}); diff --git a/src/pushbutton-6mm-element.ts b/src/pushbutton-6mm-element.ts index 50fed5d..c9cdab4 100644 --- a/src/pushbutton-6mm-element.ts +++ b/src/pushbutton-6mm-element.ts @@ -66,133 +66,98 @@ export class Pushbutton6mmElement extends LitElement { `; } - render() { - const { color, label, uniqueId, xray } = this; + renderSVG() { + const { color, uniqueId, xray } = this; const buttonFill = this.pressed ? `url(#grad-down-${uniqueId})` : `url(#grad-up-${uniqueId})`; - return html` - `; + } + + render() { + const { color, label } = this; + + return html` + ${this.label} `; diff --git a/src/pushbutton-element.spec.ts b/src/pushbutton-element.spec.ts new file mode 100644 index 0000000..09bff9e --- /dev/null +++ b/src/pushbutton-element.spec.ts @@ -0,0 +1,10 @@ +import { describe, it } from 'vitest'; +import { PushbuttonElement } from './pushbutton-element'; +import { renderToPng, savePng } from './utils/test-utils'; + +describe('PushbuttonElement', () => { + it('should render to svg', async () => { + const pngData = await renderToPng(new PushbuttonElement(), PushbuttonElement.styles); + await savePng('wokwi-pushbutton', pngData); + }); +}); diff --git a/src/pushbutton-element.ts b/src/pushbutton-element.ts index 90a40aa..8881ddb 100644 --- a/src/pushbutton-element.ts +++ b/src/pushbutton-element.ts @@ -68,9 +68,97 @@ export class PushbuttonElement extends LitElement { `; } - render() { - const { color, label, uniqueId, xray } = this; + renderSVG() { + const { color, uniqueId, xray } = this; const buttonFill = this.pressed ? `url(#grad-down-${uniqueId})` : `url(#grad-up-${uniqueId})`; + return html` + + + + + + + + + + + + + + + + + ${xray + ? svg` + + + ` + : ''} + + + + + + + + + + + + + + + + + + `; + } + + render() { + const { color, label } = this; return html` ${this.label} `; diff --git a/src/resistor-element.spec.ts b/src/resistor-element.spec.ts new file mode 100644 index 0000000..13f9ced --- /dev/null +++ b/src/resistor-element.spec.ts @@ -0,0 +1,10 @@ +import { describe, it } from 'vitest'; +import { ResistorElement } from './resistor-element'; +import { renderToPng, savePng } from './utils/test-utils'; + +describe('ResistorElement', () => { + it('should render to svg', async () => { + const pngData = await renderToPng(new ResistorElement(), ResistorElement.styles); + await savePng('wokwi-resistor', pngData); + }); +}); diff --git a/src/rgb-led-element.spec.ts b/src/rgb-led-element.spec.ts new file mode 100644 index 0000000..845dcdb --- /dev/null +++ b/src/rgb-led-element.spec.ts @@ -0,0 +1,10 @@ +import { describe, it } from 'vitest'; +import { RGBLedElement } from './rgb-led-element'; +import { renderToPng, savePng } from './utils/test-utils'; + +describe('RGBLedElement', () => { + it('should render to svg', async () => { + const pngData = await renderToPng(new RGBLedElement()); + await savePng('wokwi-rgb-led', pngData); + }); +}); diff --git a/src/rotary-dialer-element.spec.ts b/src/rotary-dialer-element.spec.ts new file mode 100644 index 0000000..0392cfa --- /dev/null +++ b/src/rotary-dialer-element.spec.ts @@ -0,0 +1,10 @@ +import { describe, it } from 'vitest'; +import { RotaryDialerElement } from './rotary-dialer-element'; +import { renderToPng, savePng } from './utils/test-utils'; + +describe('RotaryDialerElement', () => { + it('should render to svg', async () => { + const pngData = await renderToPng(new RotaryDialerElement(), RotaryDialerElement.styles); + await savePng('wokwi-rotary-dialer', pngData); + }); +}); diff --git a/src/rotary-dialer-element.ts b/src/rotary-dialer-element.ts index 64023c1..caac801 100644 --- a/src/rotary-dialer-element.ts +++ b/src/rotary-dialer-element.ts @@ -86,6 +86,71 @@ export class RotaryDialerElement extends LitElement { inputEl?.focus(); } + renderSVG() { + return html` + + + + + + + + + + + + + + this.dial(0)} x="129" y="243">0 + this.dial(9)} x="78" y="230">9 + this.dial(8)} x="40" y="194">8 + this.dial(7)} x="28" y="145">7 + this.dial(6)} x="35" y="97">6 + this.dial(5)} x="72" y="58">5 + this.dial(4)} x="117" y="41">4 + this.dial(3)} x="168" y="47">3 + this.dial(2)} x="210" y="79">2 + this.dial(1)} x="230" y="126">1 + + + `; + } + render() { return html` - - - - - - - - - - - - - - - this.dial(0)} x="129" y="243">0 - this.dial(9)} x="78" y="230">9 - this.dial(8)} x="40" y="194">8 - this.dial(7)} x="28" y="145">7 - this.dial(6)} x="35" y="97">6 - this.dial(5)} x="72" y="58">5 - this.dial(4)} x="117" y="41">4 - this.dial(3)} x="168" y="47">3 - this.dial(2)} x="210" y="79">2 - this.dial(1)} x="230" y="126">1 - - - + ${this.renderSVG()} `; } } diff --git a/src/servo-element.spec.ts b/src/servo-element.spec.ts new file mode 100644 index 0000000..304b658 --- /dev/null +++ b/src/servo-element.spec.ts @@ -0,0 +1,10 @@ +import { describe, it } from 'vitest'; +import { ServoElement } from './servo-element'; +import { renderToPng, savePng } from './utils/test-utils'; + +describe('ServoElement', () => { + it('should render to svg', async () => { + const pngData = await renderToPng(new ServoElement()); + await savePng('wokwi-servo', pngData); + }); +}); diff --git a/src/slide-potentiometer-element.spec.ts b/src/slide-potentiometer-element.spec.ts new file mode 100644 index 0000000..a01756f --- /dev/null +++ b/src/slide-potentiometer-element.spec.ts @@ -0,0 +1,13 @@ +import { describe, it } from 'vitest'; +import { SlidePotentiometerElement } from './slide-potentiometer-element'; +import { renderToPng, savePng } from './utils/test-utils'; + +describe('SlidePotentiometerElement', () => { + it('should render to svg', async () => { + const pngData = await renderToPng( + new SlidePotentiometerElement(), + SlidePotentiometerElement.styles, + ); + await savePng('wokwi-slide-potentiometer', pngData); + }); +}); diff --git a/src/slide-potentiometer-element.ts b/src/slide-potentiometer-element.ts index 6f81e4e..0fee518 100644 --- a/src/slide-potentiometer-element.ts +++ b/src/slide-potentiometer-element.ts @@ -54,13 +54,122 @@ export class SlidePotentiometerElement extends LitElement { super.update(changedProperties); } - render() { + renderSVG() { const { value, min: minValue, max: maxValue, travelLength } = this; // Tip is centered by default const tipBaseOffsetX = -15; const tipMovementX = (value / (maxValue - minValue)) * travelLength; const tipOffsetX = tipMovementX + tipBaseOffsetX; + return html` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + `; + } + + render() { return html` - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ${this.renderSVG()} `; } diff --git a/src/slide-switch-element.spec.ts b/src/slide-switch-element.spec.ts new file mode 100644 index 0000000..e286739 --- /dev/null +++ b/src/slide-switch-element.spec.ts @@ -0,0 +1,10 @@ +import { describe, it } from 'vitest'; +import { SlideSwitchElement } from './slide-switch-element'; +import { renderToPng, savePng } from './utils/test-utils'; + +describe('SlideSwitchElement', () => { + it('should render to svg', async () => { + const pngData = await renderToPng(new SlideSwitchElement(), SlideSwitchElement.styles); + await savePng('wokwi-slide-switch', pngData); + }); +}); diff --git a/src/slide-switch-element.ts b/src/slide-switch-element.ts index aa87d4f..220356b 100644 --- a/src/slide-switch-element.ts +++ b/src/slide-switch-element.ts @@ -48,6 +48,46 @@ export class SlideSwitchElement extends LitElement { this.dispatchEvent(new InputEvent('input', { detail: this.value })); } + renderSVG() { + return html` + + + + + + + + + + + + + + + + + `; + } + render() { const { value } = this; return html` @@ -58,43 +98,7 @@ export class SlideSwitchElement extends LitElement { .checked=${value} @input="${(e: InputEvent) => this.onValueChange(e.target as HTMLInputElement)}" /> - - - - - - - - - - - - - - - - - - + ${this.renderSVG()} `; } } diff --git a/src/small-sound-sensor-element.spec.ts b/src/small-sound-sensor-element.spec.ts new file mode 100644 index 0000000..a1eda4b --- /dev/null +++ b/src/small-sound-sensor-element.spec.ts @@ -0,0 +1,10 @@ +import { describe, it } from 'vitest'; +import { SmallSoundSensorElement } from './small-sound-sensor-element'; +import { renderToPng, savePng } from './utils/test-utils'; + +describe('SmallSoundSensorElement', () => { + it('should render to svg', async () => { + const pngData = await renderToPng(new SmallSoundSensorElement()); + await savePng('wokwi-small-sound-sensor', pngData); + }); +}); diff --git a/src/ssd1306-element.spec.ts b/src/ssd1306-element.spec.ts new file mode 100644 index 0000000..f25a75a --- /dev/null +++ b/src/ssd1306-element.spec.ts @@ -0,0 +1,31 @@ +import { describe, it } from 'vitest'; +import { SSD1306Element } from './ssd1306-element'; +import { renderToPng, savePng } from './utils/test-utils'; + +class MockImageData { + colorSpace = 'srgb' as const; + width: number; + height: number; + data: Uint8ClampedArray; + + constructor(data: Uint8ClampedArray | number, width: number, height: number = 0) { + if (typeof data === 'number') { + this.width = data; + this.height = width; + this.data = new Uint8ClampedArray(this.width * height * 4); + } else { + this.width = width; + this.height = height; + this.data = data; + } + } +} + +describe('SSD1306Element', () => { + it('should render to svg', async () => { + global.ImageData = MockImageData as typeof ImageData; + + const pngData = await renderToPng(new SSD1306Element(), SSD1306Element.styles); + await savePng('wokwi-ssd1306', pngData); + }); +}); diff --git a/src/ssd1306-element.ts b/src/ssd1306-element.ts index c66c0ca..3fa5067 100644 --- a/src/ssd1306-element.ts +++ b/src/ssd1306-element.ts @@ -80,60 +80,65 @@ export class SSD1306Element extends LitElement { } } - render() { + renderSVG() { const { width, height, screenWidth, screenHeight } = this; + return html` + + + + + + + + + + + + + + + Data + SA0 + CS + Vin + C1k + DC + Rst + 3v3 + Gnd + + + + + + + + + + + + + + + + + `; + } + + render() { + const { screenWidth, screenHeight } = this; return html`
- - - - - - - - - - - - - - - - Data - SA0 - CS - Vin - C1k - DC - Rst - 3v3 - Gnd - - - - - - - - - - - - - - - - - + ${this.renderSVG()}
`; } diff --git a/src/stepper-motor-element.spec.ts b/src/stepper-motor-element.spec.ts new file mode 100644 index 0000000..e24c744 --- /dev/null +++ b/src/stepper-motor-element.spec.ts @@ -0,0 +1,10 @@ +import { describe, it } from 'vitest'; +import { StepperMotorElement } from './stepper-motor-element'; +import { renderToPng, savePng } from './utils/test-utils'; + +describe('StepperMotorElement', () => { + it('should render to svg', async () => { + const pngData = await renderToPng(new StepperMotorElement()); + await savePng('wokwi-stepper-motor', pngData); + }); +}); diff --git a/src/tilt-switch-element.spec.ts b/src/tilt-switch-element.spec.ts new file mode 100644 index 0000000..b5ccd99 --- /dev/null +++ b/src/tilt-switch-element.spec.ts @@ -0,0 +1,10 @@ +import { describe, it } from 'vitest'; +import { TiltSwitchElement } from './tilt-switch-element'; +import { renderToPng, savePng } from './utils/test-utils'; + +describe('TiltSwitchElement', () => { + it('should render to svg', async () => { + const pngData = await renderToPng(new TiltSwitchElement()); + await savePng('wokwi-tilt-switch', pngData); + }); +}); diff --git a/src/utils/test-utils.ts b/src/utils/test-utils.ts new file mode 100644 index 0000000..094ec3b --- /dev/null +++ b/src/utils/test-utils.ts @@ -0,0 +1,43 @@ +import { render } from '@lit-labs/ssr'; +import { collectResult } from '@lit-labs/ssr/lib/render-result'; +import { writeFile, mkdir } from 'fs/promises'; +import { CSSResult, TemplateResult } from 'lit'; +import { join } from 'path'; +import sharp from 'sharp'; + +export interface IRenderable { + render(): TemplateResult; + renderSVG?(): TemplateResult; +} + +export function removeLitComments(svg: string) { + return svg.replace(//g, ''); +} + +async function getSavePath() { + const path = process.env.SAVE_PNG_PATH; + if (!path) { + return; + } + mkdir(path, { recursive: true }); + return path; +} + +export async function renderToPng(element: IRenderable, styles?: CSSResult) { + const rendered = element.renderSVG ? element.renderSVG() : element.render(); + const svgData = await collectResult(render(rendered)); + const svgStyles = styles ? removeLitComments(await collectResult(render(styles))) : undefined; + return await sharp(Buffer.from(svgData), { + svg: { stylesheet: svgStyles }, + }) + .png() + .toBuffer(); +} + +export async function savePng(name: string, pngData: Buffer) { + const path = await getSavePath(); + if (!path) { + return; + } + await writeFile(join(path, `${name}.png`), pngData); +}