├── .editorconfig ├── .github └── workflows │ └── main.yaml ├── .gitignore ├── .npmrc ├── LICENSE.txt ├── README.md ├── build.mjs ├── package-lock.json ├── package.json └── src ├── app.css ├── app.tsx ├── config.ts ├── d3wave.tsx ├── index.html ├── monaco.tsx ├── proto.ts ├── pyodide.ts ├── runner.ts └── worker.ts /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | insert_final_newline = true 7 | -------------------------------------------------------------------------------- /.github/workflows/main.yaml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | pull_request: 4 | 5 | name: CI 6 | jobs: 7 | 8 | build: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Check out source code 12 | uses: actions/checkout@v4 13 | - name: Install and build 14 | run: | 15 | npm ci 16 | npm run minify 17 | - name: Upload artifact 18 | uses: actions/upload-artifact@v4 19 | with: 20 | name: dist 21 | path: dist/ 22 | 23 | deploy: 24 | needs: build 25 | if: ${{ github.repository == 'amaranth-lang/playground' && github.event_name == 'push' && github.event.ref == 'refs/heads/live' }} 26 | runs-on: ubuntu-latest 27 | steps: 28 | - name: Check out repository 29 | uses: actions/checkout@v4 30 | - name: Download artifact 31 | uses: actions/download-artifact@v4 32 | with: 33 | name: dist 34 | path: dist/ 35 | - name: Publish artifact to the main Amaranth website 36 | uses: JamesIves/github-pages-deploy-action@releases/v4 37 | with: 38 | folder: dist/ 39 | repository-name: amaranth-lang/amaranth-lang.github.io 40 | ssh-key: ${{ secrets.PAGES_DEPLOY_KEY }} 41 | branch: main 42 | target-folder: play/ 43 | 44 | deploy-dev: 45 | needs: build 46 | if: ${{ github.event_name == 'push' && github.event.ref == 'refs/heads/main' }} 47 | runs-on: ubuntu-latest 48 | permissions: 49 | contents: write 50 | steps: 51 | - name: Check out repository 52 | uses: actions/checkout@v4 53 | - name: Download artifact 54 | uses: actions/download-artifact@v4 55 | with: 56 | name: dist 57 | path: dist/ 58 | - name: Disable Jekyll 59 | run: | 60 | touch dist/.nojekyll 61 | - name: Publish artifact to gh-pages branch in this repository 62 | uses: JamesIves/github-pages-deploy-action@releases/v4 63 | with: 64 | folder: dist/ 65 | single-commit: true 66 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /dist 3 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | audit=false 2 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (C) 2024 Amaranth HDL contributors 2 | 3 | Redistribution and use in source and binary forms, with or without modification, 4 | are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this 7 | list of conditions and the following disclaimer. 8 | 2. Redistributions in binary form must reproduce the above copyright notice, 9 | this list of conditions and the following disclaimer in the documentation 10 | and/or other materials provided with the distribution. 11 | 12 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 13 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 14 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 15 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 16 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 17 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 18 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 19 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 20 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Amaranth Playground 2 | 3 | This repository contains the source code for the [Amaranth Playground][], a web application that introduces developers to the [Amaranth HDL][] with zero installation required. 4 | 5 | [amaranth playground]: https://amaranth-lang.org/play/ 6 | [amaranth hdl]: https://amaranth-lang.org/ 7 | 8 | ## Technical details 9 | 10 | This application is built on: 11 | 12 | * [TypeScript](https://typescriptlang.org/) 13 | * [React](https://react.dev) 14 | * [MUI (Joy UI)](https://mui.com/joy-ui/getting-started/) 15 | * [Monaco](https://microsoft.github.io/monaco-editor/) 16 | * [d3-wave](https://github.com/Nic30/d3-wave) 17 | * [Pyodide](https://pyodide.org/en/stable/) 18 | * [YoWASP](https://yowasp.org) 19 | * [esbuild](https://esbuild.github.io/) 20 | 21 | The amount of dependencies is intentionally kept minimal. All code processing tasks (TypeScript compilation, minification, bundling, polyfilling/transpilation, serving in development) are performed by esbuild, which is amazingly flexible and useful. 22 | 23 | ## Development 24 | 25 | Requires [Node.js](https://nodejs.org/) and [npm](https://npmjs.org/). Install them and run: 26 | 27 | ```console 28 | npm install 29 | npm run serve 30 | ``` 31 | 32 | This will start a local server at http://localhost:8010/ (or a subsequent port if this one is in use). Any modifications to the source will cause the application to be reloaded with the modifications applied. 33 | 34 | If you are using Visual Studio Code, you can also use Shift+Ctrl+B instead. 35 | 36 | ## Deployment 37 | 38 | The latest commit in the `main` branch is deployed to the `gh-pages` branch, except in the `amaranth-lang/playground` repository. (This lets you show the changes made in your fork to others without them building the application on their machine.) 39 | 40 | The latest commit in the `live` branch is deployed to the `main` branch of `amaranth-lang/amaranth-lang.github.io`, which is published at https://amaranth-lang.org/play/. To publish latest changes from the `main` branch, run `git push origin main:live`. 41 | 42 | ## License 43 | 44 | This application is released under the [two-clause BSD license](LICENSE.txt). 45 | -------------------------------------------------------------------------------- /build.mjs: -------------------------------------------------------------------------------- 1 | import * as process from 'node:process'; 2 | import * as child_process from 'node:child_process'; 3 | import * as esbuild from 'esbuild'; 4 | import metaUrlPlugin from '@chialab/esbuild-plugin-meta-url'; 5 | 6 | const gitCommit = child_process.execSync('git rev-parse HEAD', { encoding: 'utf-8' }).replace(/\n$/, ''); 7 | 8 | const mode = (process.argv[2] ?? 'build'); 9 | const options = { 10 | logLevel: 'info', 11 | plugins: [metaUrlPlugin()], 12 | bundle: true, 13 | loader: { 14 | '.html': 'copy', 15 | '.svg': 'dataurl', 16 | '.ttf': 'file', 17 | '.woff': 'file', 18 | '.woff2': 'file', 19 | '.json': 'file', 20 | '.wasm': 'file', 21 | '.asm.wasm': 'copy', 22 | '.zip': 'file', 23 | }, 24 | external: [ 25 | 'fs/promises', // @yowasp/yosys 26 | 'node-fetch', // pyodide 27 | ], 28 | define: { 29 | 'globalThis.GIT_COMMIT': `"${mode === 'minify' ? gitCommit : 'HEAD'}"`, 30 | 'globalThis.IS_PRODUCTION': (mode === 'minify' ? 'true' : 'false'), 31 | }, 32 | target: 'es2021', 33 | format: 'esm', 34 | sourcemap: 'linked', 35 | minify: (mode === 'minify'), 36 | outdir: 'dist', 37 | entryPoints: { 38 | 'index': './src/index.html', 39 | 'app': './src/app.tsx', 40 | 'app.worker': './src/worker.ts', 41 | 'editor.worker': 'monaco-editor/esm/vs/editor/editor.worker.js', 42 | 'pyodide.asm': 'pyodide/pyodide.asm.wasm', 43 | }, 44 | }; 45 | 46 | if (mode === 'build' || mode === 'minify') { 47 | await esbuild.build(options); 48 | } else if (mode === 'watch') { 49 | const context = await esbuild.context(options); 50 | await context.watch(); 51 | } else if (mode === 'serve') { 52 | const context = await esbuild.context(options); 53 | await context.rebuild(); 54 | await context.watch(); 55 | // Specifying `servedir` is necessary for files built by meta URL plugin to be accessible. 56 | await context.serve({ servedir: 'dist', port: 8010 }); 57 | } else { 58 | console.error(`Usage: ${process.argv0} [build|watch|serve|minify]`); 59 | } 60 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "amaranth-playground", 3 | "version": "0.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "amaranth-playground", 9 | "version": "0.0.0", 10 | "license": "BSD-2-Clause", 11 | "devDependencies": { 12 | "@chialab/esbuild-plugin-meta-url": "^0.18.0", 13 | "@emotion/react": "^11.11.3", 14 | "@emotion/styled": "^11.11.0", 15 | "@fontsource/inter": "^5.0.16", 16 | "@mui/icons-material": "^5.15.10", 17 | "@mui/joy": "^5.0.0-beta.28", 18 | "@types/d3": "^7.4.3", 19 | "@types/react": "^18.2.55", 20 | "@types/react-dom": "^18.2.19", 21 | "@yowasp/yosys": "release", 22 | "d3-wave": "^1.1.5", 23 | "esbuild": "^0.25.0", 24 | "monaco-editor": "^0.46.0", 25 | "pyodide": "^0.25.0", 26 | "react": "^18.0.0", 27 | "react-dom": "^18.0.0" 28 | } 29 | }, 30 | "node_modules/@babel/code-frame": { 31 | "version": "7.24.7", 32 | "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", 33 | "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", 34 | "dev": true, 35 | "dependencies": { 36 | "@babel/highlight": "^7.24.7", 37 | "picocolors": "^1.0.0" 38 | }, 39 | "engines": { 40 | "node": ">=6.9.0" 41 | } 42 | }, 43 | "node_modules/@babel/generator": { 44 | "version": "7.25.0", 45 | "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.0.tgz", 46 | "integrity": "sha512-3LEEcj3PVW8pW2R1SR1M89g/qrYk/m/mB/tLqn7dn4sbBUQyTqnlod+II2U4dqiGtUmkcnAmkMDralTFZttRiw==", 47 | "dev": true, 48 | "dependencies": { 49 | "@babel/types": "^7.25.0", 50 | "@jridgewell/gen-mapping": "^0.3.5", 51 | "@jridgewell/trace-mapping": "^0.3.25", 52 | "jsesc": "^2.5.1" 53 | }, 54 | "engines": { 55 | "node": ">=6.9.0" 56 | } 57 | }, 58 | "node_modules/@babel/helper-module-imports": { 59 | "version": "7.24.7", 60 | "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", 61 | "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", 62 | "dev": true, 63 | "dependencies": { 64 | "@babel/traverse": "^7.24.7", 65 | "@babel/types": "^7.24.7" 66 | }, 67 | "engines": { 68 | "node": ">=6.9.0" 69 | } 70 | }, 71 | "node_modules/@babel/helper-string-parser": { 72 | "version": "7.24.8", 73 | "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", 74 | "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", 75 | "dev": true, 76 | "engines": { 77 | "node": ">=6.9.0" 78 | } 79 | }, 80 | "node_modules/@babel/helper-validator-identifier": { 81 | "version": "7.24.7", 82 | "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", 83 | "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", 84 | "dev": true, 85 | "engines": { 86 | "node": ">=6.9.0" 87 | } 88 | }, 89 | "node_modules/@babel/highlight": { 90 | "version": "7.24.7", 91 | "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", 92 | "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", 93 | "dev": true, 94 | "dependencies": { 95 | "@babel/helper-validator-identifier": "^7.24.7", 96 | "chalk": "^2.4.2", 97 | "js-tokens": "^4.0.0", 98 | "picocolors": "^1.0.0" 99 | }, 100 | "engines": { 101 | "node": ">=6.9.0" 102 | } 103 | }, 104 | "node_modules/@babel/parser": { 105 | "version": "7.25.3", 106 | "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.3.tgz", 107 | "integrity": "sha512-iLTJKDbJ4hMvFPgQwwsVoxtHyWpKKPBrxkANrSYewDPaPpT5py5yeVkgPIJ7XYXhndxJpaA3PyALSXQ7u8e/Dw==", 108 | "dev": true, 109 | "dependencies": { 110 | "@babel/types": "^7.25.2" 111 | }, 112 | "bin": { 113 | "parser": "bin/babel-parser.js" 114 | }, 115 | "engines": { 116 | "node": ">=6.0.0" 117 | } 118 | }, 119 | "node_modules/@babel/runtime": { 120 | "version": "7.25.0", 121 | "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.0.tgz", 122 | "integrity": "sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw==", 123 | "dev": true, 124 | "dependencies": { 125 | "regenerator-runtime": "^0.14.0" 126 | }, 127 | "engines": { 128 | "node": ">=6.9.0" 129 | } 130 | }, 131 | "node_modules/@babel/template": { 132 | "version": "7.25.0", 133 | "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz", 134 | "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==", 135 | "dev": true, 136 | "dependencies": { 137 | "@babel/code-frame": "^7.24.7", 138 | "@babel/parser": "^7.25.0", 139 | "@babel/types": "^7.25.0" 140 | }, 141 | "engines": { 142 | "node": ">=6.9.0" 143 | } 144 | }, 145 | "node_modules/@babel/traverse": { 146 | "version": "7.25.3", 147 | "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.3.tgz", 148 | "integrity": "sha512-HefgyP1x754oGCsKmV5reSmtV7IXj/kpaE1XYY+D9G5PvKKoFfSbiS4M77MdjuwlZKDIKFCffq9rPU+H/s3ZdQ==", 149 | "dev": true, 150 | "dependencies": { 151 | "@babel/code-frame": "^7.24.7", 152 | "@babel/generator": "^7.25.0", 153 | "@babel/parser": "^7.25.3", 154 | "@babel/template": "^7.25.0", 155 | "@babel/types": "^7.25.2", 156 | "debug": "^4.3.1", 157 | "globals": "^11.1.0" 158 | }, 159 | "engines": { 160 | "node": ">=6.9.0" 161 | } 162 | }, 163 | "node_modules/@babel/types": { 164 | "version": "7.25.2", 165 | "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.2.tgz", 166 | "integrity": "sha512-YTnYtra7W9e6/oAZEHj0bJehPRUlLH9/fbpT5LfB0NhQXyALCRkRs3zH9v07IYhkgpqX6Z78FnuccZr/l4Fs4Q==", 167 | "dev": true, 168 | "dependencies": { 169 | "@babel/helper-string-parser": "^7.24.8", 170 | "@babel/helper-validator-identifier": "^7.24.7", 171 | "to-fast-properties": "^2.0.0" 172 | }, 173 | "engines": { 174 | "node": ">=6.9.0" 175 | } 176 | }, 177 | "node_modules/@chialab/esbuild-plugin-meta-url": { 178 | "version": "0.18.2", 179 | "resolved": "https://registry.npmjs.org/@chialab/esbuild-plugin-meta-url/-/esbuild-plugin-meta-url-0.18.2.tgz", 180 | "integrity": "sha512-uIRIdLvYnw5mLrTRXY0BTgeZx6ANL2/OHkWFl8FaiTYNb7cyXmwEDRE1mh6kBXPRPtGuqv6XSpNX+koEkElu4g==", 181 | "dev": true, 182 | "dependencies": { 183 | "@chialab/esbuild-rna": "^0.18.1", 184 | "@chialab/estransform": "^0.18.1", 185 | "mime-types": "^2.1.35" 186 | }, 187 | "engines": { 188 | "node": ">=18" 189 | } 190 | }, 191 | "node_modules/@chialab/esbuild-rna": { 192 | "version": "0.18.2", 193 | "resolved": "https://registry.npmjs.org/@chialab/esbuild-rna/-/esbuild-rna-0.18.2.tgz", 194 | "integrity": "sha512-ckzskez7bxstVQ4c5cxbx0DRP2teldzrcSGQl2KPh1VJGdO2ZmRrb6vNkBBD5K3dx9tgTyvskWp4dV+Fbg07Ag==", 195 | "dev": true, 196 | "dependencies": { 197 | "@chialab/estransform": "^0.18.0", 198 | "@chialab/node-resolve": "^0.18.0" 199 | }, 200 | "engines": { 201 | "node": ">=18" 202 | } 203 | }, 204 | "node_modules/@chialab/estransform": { 205 | "version": "0.18.1", 206 | "resolved": "https://registry.npmjs.org/@chialab/estransform/-/estransform-0.18.1.tgz", 207 | "integrity": "sha512-W/WmjpQL2hndD0/XfR0FcPBAUj+aLNeoAVehOjV/Q9bSnioz0GVSAXXhzp59S33ZynxJBBfn8DNiMTVNJmk4Aw==", 208 | "dev": true, 209 | "dependencies": { 210 | "@parcel/source-map": "^2.0.0" 211 | }, 212 | "engines": { 213 | "node": ">=18" 214 | } 215 | }, 216 | "node_modules/@chialab/node-resolve": { 217 | "version": "0.18.0", 218 | "resolved": "https://registry.npmjs.org/@chialab/node-resolve/-/node-resolve-0.18.0.tgz", 219 | "integrity": "sha512-eV1m70Qn9pLY9xwFmZ2FlcOzwiaUywsJ7NB/ud8VB7DouvCQtIHkQ3Om7uPX0ojXGEG1LCyO96kZkvbNTxNu0Q==", 220 | "dev": true, 221 | "engines": { 222 | "node": ">=18" 223 | } 224 | }, 225 | "node_modules/@emotion/babel-plugin": { 226 | "version": "11.12.0", 227 | "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.12.0.tgz", 228 | "integrity": "sha512-y2WQb+oP8Jqvvclh8Q55gLUyb7UFvgv7eJfsj7td5TToBrIUtPay2kMrZi4xjq9qw2vD0ZR5fSho0yqoFgX7Rw==", 229 | "dev": true, 230 | "dependencies": { 231 | "@babel/helper-module-imports": "^7.16.7", 232 | "@babel/runtime": "^7.18.3", 233 | "@emotion/hash": "^0.9.2", 234 | "@emotion/memoize": "^0.9.0", 235 | "@emotion/serialize": "^1.2.0", 236 | "babel-plugin-macros": "^3.1.0", 237 | "convert-source-map": "^1.5.0", 238 | "escape-string-regexp": "^4.0.0", 239 | "find-root": "^1.1.0", 240 | "source-map": "^0.5.7", 241 | "stylis": "4.2.0" 242 | } 243 | }, 244 | "node_modules/@emotion/cache": { 245 | "version": "11.13.1", 246 | "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.13.1.tgz", 247 | "integrity": "sha512-iqouYkuEblRcXmylXIwwOodiEK5Ifl7JcX7o6V4jI3iW4mLXX3dmt5xwBtIkJiQEXFAI+pC8X0i67yiPkH9Ucw==", 248 | "dev": true, 249 | "dependencies": { 250 | "@emotion/memoize": "^0.9.0", 251 | "@emotion/sheet": "^1.4.0", 252 | "@emotion/utils": "^1.4.0", 253 | "@emotion/weak-memoize": "^0.4.0", 254 | "stylis": "4.2.0" 255 | } 256 | }, 257 | "node_modules/@emotion/hash": { 258 | "version": "0.9.2", 259 | "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz", 260 | "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==", 261 | "dev": true 262 | }, 263 | "node_modules/@emotion/is-prop-valid": { 264 | "version": "1.3.0", 265 | "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.3.0.tgz", 266 | "integrity": "sha512-SHetuSLvJDzuNbOdtPVbq6yMMMlLoW5Q94uDqJZqy50gcmAjxFkVqmzqSGEFq9gT2iMuIeKV1PXVWmvUhuZLlQ==", 267 | "dev": true, 268 | "dependencies": { 269 | "@emotion/memoize": "^0.9.0" 270 | } 271 | }, 272 | "node_modules/@emotion/memoize": { 273 | "version": "0.9.0", 274 | "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", 275 | "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==", 276 | "dev": true 277 | }, 278 | "node_modules/@emotion/react": { 279 | "version": "11.13.0", 280 | "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.13.0.tgz", 281 | "integrity": "sha512-WkL+bw1REC2VNV1goQyfxjx1GYJkcc23CRQkXX+vZNLINyfI7o+uUn/rTGPt/xJ3bJHd5GcljgnxHf4wRw5VWQ==", 282 | "dev": true, 283 | "dependencies": { 284 | "@babel/runtime": "^7.18.3", 285 | "@emotion/babel-plugin": "^11.12.0", 286 | "@emotion/cache": "^11.13.0", 287 | "@emotion/serialize": "^1.3.0", 288 | "@emotion/use-insertion-effect-with-fallbacks": "^1.1.0", 289 | "@emotion/utils": "^1.4.0", 290 | "@emotion/weak-memoize": "^0.4.0", 291 | "hoist-non-react-statics": "^3.3.1" 292 | }, 293 | "peerDependencies": { 294 | "react": ">=16.8.0" 295 | }, 296 | "peerDependenciesMeta": { 297 | "@types/react": { 298 | "optional": true 299 | } 300 | } 301 | }, 302 | "node_modules/@emotion/serialize": { 303 | "version": "1.3.0", 304 | "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.0.tgz", 305 | "integrity": "sha512-jACuBa9SlYajnpIVXB+XOXnfJHyckDfe6fOpORIM6yhBDlqGuExvDdZYHDQGoDf3bZXGv7tNr+LpLjJqiEQ6EA==", 306 | "dev": true, 307 | "dependencies": { 308 | "@emotion/hash": "^0.9.2", 309 | "@emotion/memoize": "^0.9.0", 310 | "@emotion/unitless": "^0.9.0", 311 | "@emotion/utils": "^1.4.0", 312 | "csstype": "^3.0.2" 313 | } 314 | }, 315 | "node_modules/@emotion/sheet": { 316 | "version": "1.4.0", 317 | "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz", 318 | "integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==", 319 | "dev": true 320 | }, 321 | "node_modules/@emotion/styled": { 322 | "version": "11.13.0", 323 | "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.13.0.tgz", 324 | "integrity": "sha512-tkzkY7nQhW/zC4hztlwucpT8QEZ6eUzpXDRhww/Eej4tFfO0FxQYWRyg/c5CCXa4d/f174kqeXYjuQRnhzf6dA==", 325 | "dev": true, 326 | "dependencies": { 327 | "@babel/runtime": "^7.18.3", 328 | "@emotion/babel-plugin": "^11.12.0", 329 | "@emotion/is-prop-valid": "^1.3.0", 330 | "@emotion/serialize": "^1.3.0", 331 | "@emotion/use-insertion-effect-with-fallbacks": "^1.1.0", 332 | "@emotion/utils": "^1.4.0" 333 | }, 334 | "peerDependencies": { 335 | "@emotion/react": "^11.0.0-rc.0", 336 | "react": ">=16.8.0" 337 | }, 338 | "peerDependenciesMeta": { 339 | "@types/react": { 340 | "optional": true 341 | } 342 | } 343 | }, 344 | "node_modules/@emotion/unitless": { 345 | "version": "0.9.0", 346 | "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.9.0.tgz", 347 | "integrity": "sha512-TP6GgNZtmtFaFcsOgExdnfxLLpRDla4Q66tnenA9CktvVSdNKDvMVuUah4QvWPIpNjrWsGg3qeGo9a43QooGZQ==", 348 | "dev": true 349 | }, 350 | "node_modules/@emotion/use-insertion-effect-with-fallbacks": { 351 | "version": "1.1.0", 352 | "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.1.0.tgz", 353 | "integrity": "sha512-+wBOcIV5snwGgI2ya3u99D7/FJquOIniQT1IKyDsBmEgwvpxMNeS65Oib7OnE2d2aY+3BU4OiH+0Wchf8yk3Hw==", 354 | "dev": true, 355 | "peerDependencies": { 356 | "react": ">=16.8.0" 357 | } 358 | }, 359 | "node_modules/@emotion/utils": { 360 | "version": "1.4.0", 361 | "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.0.tgz", 362 | "integrity": "sha512-spEnrA1b6hDR/C68lC2M7m6ALPUHZC0lIY7jAS/B/9DuuO1ZP04eov8SMv/6fwRd8pzmsn2AuJEznRREWlQrlQ==", 363 | "dev": true 364 | }, 365 | "node_modules/@emotion/weak-memoize": { 366 | "version": "0.4.0", 367 | "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz", 368 | "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==", 369 | "dev": true 370 | }, 371 | "node_modules/@esbuild/aix-ppc64": { 372 | "version": "0.25.4", 373 | "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.4.tgz", 374 | "integrity": "sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q==", 375 | "cpu": [ 376 | "ppc64" 377 | ], 378 | "dev": true, 379 | "optional": true, 380 | "os": [ 381 | "aix" 382 | ], 383 | "engines": { 384 | "node": ">=18" 385 | } 386 | }, 387 | "node_modules/@esbuild/android-arm": { 388 | "version": "0.25.4", 389 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.4.tgz", 390 | "integrity": "sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ==", 391 | "cpu": [ 392 | "arm" 393 | ], 394 | "dev": true, 395 | "optional": true, 396 | "os": [ 397 | "android" 398 | ], 399 | "engines": { 400 | "node": ">=18" 401 | } 402 | }, 403 | "node_modules/@esbuild/android-arm64": { 404 | "version": "0.25.4", 405 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.4.tgz", 406 | "integrity": "sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A==", 407 | "cpu": [ 408 | "arm64" 409 | ], 410 | "dev": true, 411 | "optional": true, 412 | "os": [ 413 | "android" 414 | ], 415 | "engines": { 416 | "node": ">=18" 417 | } 418 | }, 419 | "node_modules/@esbuild/android-x64": { 420 | "version": "0.25.4", 421 | "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.4.tgz", 422 | "integrity": "sha512-TVhdVtQIFuVpIIR282btcGC2oGQoSfZfmBdTip2anCaVYcqWlZXGcdcKIUklfX2wj0JklNYgz39OBqh2cqXvcQ==", 423 | "cpu": [ 424 | "x64" 425 | ], 426 | "dev": true, 427 | "optional": true, 428 | "os": [ 429 | "android" 430 | ], 431 | "engines": { 432 | "node": ">=18" 433 | } 434 | }, 435 | "node_modules/@esbuild/darwin-arm64": { 436 | "version": "0.25.4", 437 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.4.tgz", 438 | "integrity": "sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g==", 439 | "cpu": [ 440 | "arm64" 441 | ], 442 | "dev": true, 443 | "optional": true, 444 | "os": [ 445 | "darwin" 446 | ], 447 | "engines": { 448 | "node": ">=18" 449 | } 450 | }, 451 | "node_modules/@esbuild/darwin-x64": { 452 | "version": "0.25.4", 453 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.4.tgz", 454 | "integrity": "sha512-CJsry8ZGM5VFVeyUYB3cdKpd/H69PYez4eJh1W/t38vzutdjEjtP7hB6eLKBoOdxcAlCtEYHzQ/PJ/oU9I4u0A==", 455 | "cpu": [ 456 | "x64" 457 | ], 458 | "dev": true, 459 | "optional": true, 460 | "os": [ 461 | "darwin" 462 | ], 463 | "engines": { 464 | "node": ">=18" 465 | } 466 | }, 467 | "node_modules/@esbuild/freebsd-arm64": { 468 | "version": "0.25.4", 469 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.4.tgz", 470 | "integrity": "sha512-yYq+39NlTRzU2XmoPW4l5Ifpl9fqSk0nAJYM/V/WUGPEFfek1epLHJIkTQM6bBs1swApjO5nWgvr843g6TjxuQ==", 471 | "cpu": [ 472 | "arm64" 473 | ], 474 | "dev": true, 475 | "optional": true, 476 | "os": [ 477 | "freebsd" 478 | ], 479 | "engines": { 480 | "node": ">=18" 481 | } 482 | }, 483 | "node_modules/@esbuild/freebsd-x64": { 484 | "version": "0.25.4", 485 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.4.tgz", 486 | "integrity": "sha512-0FgvOJ6UUMflsHSPLzdfDnnBBVoCDtBTVyn/MrWloUNvq/5SFmh13l3dvgRPkDihRxb77Y17MbqbCAa2strMQQ==", 487 | "cpu": [ 488 | "x64" 489 | ], 490 | "dev": true, 491 | "optional": true, 492 | "os": [ 493 | "freebsd" 494 | ], 495 | "engines": { 496 | "node": ">=18" 497 | } 498 | }, 499 | "node_modules/@esbuild/linux-arm": { 500 | "version": "0.25.4", 501 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.4.tgz", 502 | "integrity": "sha512-kro4c0P85GMfFYqW4TWOpvmF8rFShbWGnrLqlzp4X1TNWjRY3JMYUfDCtOxPKOIY8B0WC8HN51hGP4I4hz4AaQ==", 503 | "cpu": [ 504 | "arm" 505 | ], 506 | "dev": true, 507 | "optional": true, 508 | "os": [ 509 | "linux" 510 | ], 511 | "engines": { 512 | "node": ">=18" 513 | } 514 | }, 515 | "node_modules/@esbuild/linux-arm64": { 516 | "version": "0.25.4", 517 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.4.tgz", 518 | "integrity": "sha512-+89UsQTfXdmjIvZS6nUnOOLoXnkUTB9hR5QAeLrQdzOSWZvNSAXAtcRDHWtqAUtAmv7ZM1WPOOeSxDzzzMogiQ==", 519 | "cpu": [ 520 | "arm64" 521 | ], 522 | "dev": true, 523 | "optional": true, 524 | "os": [ 525 | "linux" 526 | ], 527 | "engines": { 528 | "node": ">=18" 529 | } 530 | }, 531 | "node_modules/@esbuild/linux-ia32": { 532 | "version": "0.25.4", 533 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.4.tgz", 534 | "integrity": "sha512-yTEjoapy8UP3rv8dB0ip3AfMpRbyhSN3+hY8mo/i4QXFeDxmiYbEKp3ZRjBKcOP862Ua4b1PDfwlvbuwY7hIGQ==", 535 | "cpu": [ 536 | "ia32" 537 | ], 538 | "dev": true, 539 | "optional": true, 540 | "os": [ 541 | "linux" 542 | ], 543 | "engines": { 544 | "node": ">=18" 545 | } 546 | }, 547 | "node_modules/@esbuild/linux-loong64": { 548 | "version": "0.25.4", 549 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.4.tgz", 550 | "integrity": "sha512-NeqqYkrcGzFwi6CGRGNMOjWGGSYOpqwCjS9fvaUlX5s3zwOtn1qwg1s2iE2svBe4Q/YOG1q6875lcAoQK/F4VA==", 551 | "cpu": [ 552 | "loong64" 553 | ], 554 | "dev": true, 555 | "optional": true, 556 | "os": [ 557 | "linux" 558 | ], 559 | "engines": { 560 | "node": ">=18" 561 | } 562 | }, 563 | "node_modules/@esbuild/linux-mips64el": { 564 | "version": "0.25.4", 565 | "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.4.tgz", 566 | "integrity": "sha512-IcvTlF9dtLrfL/M8WgNI/qJYBENP3ekgsHbYUIzEzq5XJzzVEV/fXY9WFPfEEXmu3ck2qJP8LG/p3Q8f7Zc2Xg==", 567 | "cpu": [ 568 | "mips64el" 569 | ], 570 | "dev": true, 571 | "optional": true, 572 | "os": [ 573 | "linux" 574 | ], 575 | "engines": { 576 | "node": ">=18" 577 | } 578 | }, 579 | "node_modules/@esbuild/linux-ppc64": { 580 | "version": "0.25.4", 581 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.4.tgz", 582 | "integrity": "sha512-HOy0aLTJTVtoTeGZh4HSXaO6M95qu4k5lJcH4gxv56iaycfz1S8GO/5Jh6X4Y1YiI0h7cRyLi+HixMR+88swag==", 583 | "cpu": [ 584 | "ppc64" 585 | ], 586 | "dev": true, 587 | "optional": true, 588 | "os": [ 589 | "linux" 590 | ], 591 | "engines": { 592 | "node": ">=18" 593 | } 594 | }, 595 | "node_modules/@esbuild/linux-riscv64": { 596 | "version": "0.25.4", 597 | "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.4.tgz", 598 | "integrity": "sha512-i8JUDAufpz9jOzo4yIShCTcXzS07vEgWzyX3NH2G7LEFVgrLEhjwL3ajFE4fZI3I4ZgiM7JH3GQ7ReObROvSUA==", 599 | "cpu": [ 600 | "riscv64" 601 | ], 602 | "dev": true, 603 | "optional": true, 604 | "os": [ 605 | "linux" 606 | ], 607 | "engines": { 608 | "node": ">=18" 609 | } 610 | }, 611 | "node_modules/@esbuild/linux-s390x": { 612 | "version": "0.25.4", 613 | "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.4.tgz", 614 | "integrity": "sha512-jFnu+6UbLlzIjPQpWCNh5QtrcNfMLjgIavnwPQAfoGx4q17ocOU9MsQ2QVvFxwQoWpZT8DvTLooTvmOQXkO51g==", 615 | "cpu": [ 616 | "s390x" 617 | ], 618 | "dev": true, 619 | "optional": true, 620 | "os": [ 621 | "linux" 622 | ], 623 | "engines": { 624 | "node": ">=18" 625 | } 626 | }, 627 | "node_modules/@esbuild/linux-x64": { 628 | "version": "0.25.4", 629 | "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.4.tgz", 630 | "integrity": "sha512-6e0cvXwzOnVWJHq+mskP8DNSrKBr1bULBvnFLpc1KY+d+irZSgZ02TGse5FsafKS5jg2e4pbvK6TPXaF/A6+CA==", 631 | "cpu": [ 632 | "x64" 633 | ], 634 | "dev": true, 635 | "optional": true, 636 | "os": [ 637 | "linux" 638 | ], 639 | "engines": { 640 | "node": ">=18" 641 | } 642 | }, 643 | "node_modules/@esbuild/netbsd-arm64": { 644 | "version": "0.25.4", 645 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.4.tgz", 646 | "integrity": "sha512-vUnkBYxZW4hL/ie91hSqaSNjulOnYXE1VSLusnvHg2u3jewJBz3YzB9+oCw8DABeVqZGg94t9tyZFoHma8gWZQ==", 647 | "cpu": [ 648 | "arm64" 649 | ], 650 | "dev": true, 651 | "optional": true, 652 | "os": [ 653 | "netbsd" 654 | ], 655 | "engines": { 656 | "node": ">=18" 657 | } 658 | }, 659 | "node_modules/@esbuild/netbsd-x64": { 660 | "version": "0.25.4", 661 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.4.tgz", 662 | "integrity": "sha512-XAg8pIQn5CzhOB8odIcAm42QsOfa98SBeKUdo4xa8OvX8LbMZqEtgeWE9P/Wxt7MlG2QqvjGths+nq48TrUiKw==", 663 | "cpu": [ 664 | "x64" 665 | ], 666 | "dev": true, 667 | "optional": true, 668 | "os": [ 669 | "netbsd" 670 | ], 671 | "engines": { 672 | "node": ">=18" 673 | } 674 | }, 675 | "node_modules/@esbuild/openbsd-arm64": { 676 | "version": "0.25.4", 677 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.4.tgz", 678 | "integrity": "sha512-Ct2WcFEANlFDtp1nVAXSNBPDxyU+j7+tId//iHXU2f/lN5AmO4zLyhDcpR5Cz1r08mVxzt3Jpyt4PmXQ1O6+7A==", 679 | "cpu": [ 680 | "arm64" 681 | ], 682 | "dev": true, 683 | "optional": true, 684 | "os": [ 685 | "openbsd" 686 | ], 687 | "engines": { 688 | "node": ">=18" 689 | } 690 | }, 691 | "node_modules/@esbuild/openbsd-x64": { 692 | "version": "0.25.4", 693 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.4.tgz", 694 | "integrity": "sha512-xAGGhyOQ9Otm1Xu8NT1ifGLnA6M3sJxZ6ixylb+vIUVzvvd6GOALpwQrYrtlPouMqd/vSbgehz6HaVk4+7Afhw==", 695 | "cpu": [ 696 | "x64" 697 | ], 698 | "dev": true, 699 | "optional": true, 700 | "os": [ 701 | "openbsd" 702 | ], 703 | "engines": { 704 | "node": ">=18" 705 | } 706 | }, 707 | "node_modules/@esbuild/sunos-x64": { 708 | "version": "0.25.4", 709 | "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.4.tgz", 710 | "integrity": "sha512-Mw+tzy4pp6wZEK0+Lwr76pWLjrtjmJyUB23tHKqEDP74R3q95luY/bXqXZeYl4NYlvwOqoRKlInQialgCKy67Q==", 711 | "cpu": [ 712 | "x64" 713 | ], 714 | "dev": true, 715 | "optional": true, 716 | "os": [ 717 | "sunos" 718 | ], 719 | "engines": { 720 | "node": ">=18" 721 | } 722 | }, 723 | "node_modules/@esbuild/win32-arm64": { 724 | "version": "0.25.4", 725 | "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.4.tgz", 726 | "integrity": "sha512-AVUP428VQTSddguz9dO9ngb+E5aScyg7nOeJDrF1HPYu555gmza3bDGMPhmVXL8svDSoqPCsCPjb265yG/kLKQ==", 727 | "cpu": [ 728 | "arm64" 729 | ], 730 | "dev": true, 731 | "optional": true, 732 | "os": [ 733 | "win32" 734 | ], 735 | "engines": { 736 | "node": ">=18" 737 | } 738 | }, 739 | "node_modules/@esbuild/win32-ia32": { 740 | "version": "0.25.4", 741 | "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.4.tgz", 742 | "integrity": "sha512-i1sW+1i+oWvQzSgfRcxxG2k4I9n3O9NRqy8U+uugaT2Dy7kLO9Y7wI72haOahxceMX8hZAzgGou1FhndRldxRg==", 743 | "cpu": [ 744 | "ia32" 745 | ], 746 | "dev": true, 747 | "optional": true, 748 | "os": [ 749 | "win32" 750 | ], 751 | "engines": { 752 | "node": ">=18" 753 | } 754 | }, 755 | "node_modules/@esbuild/win32-x64": { 756 | "version": "0.25.4", 757 | "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.4.tgz", 758 | "integrity": "sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ==", 759 | "cpu": [ 760 | "x64" 761 | ], 762 | "dev": true, 763 | "optional": true, 764 | "os": [ 765 | "win32" 766 | ], 767 | "engines": { 768 | "node": ">=18" 769 | } 770 | }, 771 | "node_modules/@floating-ui/core": { 772 | "version": "1.6.6", 773 | "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.6.tgz", 774 | "integrity": "sha512-Vkvsw6EcpMHjvZZdMkSY+djMGFbt7CRssW99Ne8tar2WLnZ/l3dbxeTShbLQj+/s35h+Qb4cmnob+EzwtjrXGQ==", 775 | "dev": true, 776 | "dependencies": { 777 | "@floating-ui/utils": "^0.2.6" 778 | } 779 | }, 780 | "node_modules/@floating-ui/dom": { 781 | "version": "1.6.9", 782 | "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.9.tgz", 783 | "integrity": "sha512-zB1PcI350t4tkm3rvUhSRKa9sT7vH5CrAbQxW+VaPYJXKAO0gsg4CTueL+6Ajp7XzAQC8CW4Jj1Wgqc0sB6oUQ==", 784 | "dev": true, 785 | "dependencies": { 786 | "@floating-ui/core": "^1.6.0", 787 | "@floating-ui/utils": "^0.2.6" 788 | } 789 | }, 790 | "node_modules/@floating-ui/react-dom": { 791 | "version": "2.1.1", 792 | "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.1.tgz", 793 | "integrity": "sha512-4h84MJt3CHrtG18mGsXuLCHMrug49d7DFkU0RMIyshRveBeyV2hmV/pDaF2Uxtu8kgq5r46llp5E5FQiR0K2Yg==", 794 | "dev": true, 795 | "dependencies": { 796 | "@floating-ui/dom": "^1.0.0" 797 | }, 798 | "peerDependencies": { 799 | "react": ">=16.8.0", 800 | "react-dom": ">=16.8.0" 801 | } 802 | }, 803 | "node_modules/@floating-ui/utils": { 804 | "version": "0.2.6", 805 | "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.6.tgz", 806 | "integrity": "sha512-0KI3zGxIUs1KDR/pjQPdJH4Z8nGBm0yJ5WRoRfdw1Kzeh45jkIfA0rmD0kBF6fKHH+xaH7g8y4jIXyAV5MGK3g==", 807 | "dev": true 808 | }, 809 | "node_modules/@fontsource/inter": { 810 | "version": "5.0.20", 811 | "resolved": "https://registry.npmjs.org/@fontsource/inter/-/inter-5.0.20.tgz", 812 | "integrity": "sha512-rtw2F7xfM7rJmmnncXnR4ADr5wXsp4GyN1O1jmQJ1PMjAK+bm620/ZkQkeOYOkGoa09OksGinOeMA+Mkt6K9PQ==", 813 | "dev": true 814 | }, 815 | "node_modules/@fortawesome/fontawesome-common-types": { 816 | "version": "0.2.36", 817 | "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.36.tgz", 818 | "integrity": "sha512-a/7BiSgobHAgBWeN7N0w+lAhInrGxksn13uK7231n2m8EDPE3BMCl9NZLTGrj9ZXfCmC6LM0QLqXidIizVQ6yg==", 819 | "dev": true, 820 | "hasInstallScript": true, 821 | "engines": { 822 | "node": ">=6" 823 | } 824 | }, 825 | "node_modules/@fortawesome/free-solid-svg-icons": { 826 | "version": "5.15.4", 827 | "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.15.4.tgz", 828 | "integrity": "sha512-JLmQfz6tdtwxoihXLg6lT78BorrFyCf59SAwBM6qV/0zXyVeDygJVb3fk+j5Qat+Yvcxp1buLTY5iDh1ZSAQ8w==", 829 | "dev": true, 830 | "hasInstallScript": true, 831 | "dependencies": { 832 | "@fortawesome/fontawesome-common-types": "^0.2.36" 833 | }, 834 | "engines": { 835 | "node": ">=6" 836 | } 837 | }, 838 | "node_modules/@jridgewell/gen-mapping": { 839 | "version": "0.3.5", 840 | "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", 841 | "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", 842 | "dev": true, 843 | "dependencies": { 844 | "@jridgewell/set-array": "^1.2.1", 845 | "@jridgewell/sourcemap-codec": "^1.4.10", 846 | "@jridgewell/trace-mapping": "^0.3.24" 847 | }, 848 | "engines": { 849 | "node": ">=6.0.0" 850 | } 851 | }, 852 | "node_modules/@jridgewell/resolve-uri": { 853 | "version": "3.1.2", 854 | "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", 855 | "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", 856 | "dev": true, 857 | "engines": { 858 | "node": ">=6.0.0" 859 | } 860 | }, 861 | "node_modules/@jridgewell/set-array": { 862 | "version": "1.2.1", 863 | "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", 864 | "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", 865 | "dev": true, 866 | "engines": { 867 | "node": ">=6.0.0" 868 | } 869 | }, 870 | "node_modules/@jridgewell/sourcemap-codec": { 871 | "version": "1.5.0", 872 | "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", 873 | "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", 874 | "dev": true 875 | }, 876 | "node_modules/@jridgewell/trace-mapping": { 877 | "version": "0.3.25", 878 | "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", 879 | "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", 880 | "dev": true, 881 | "dependencies": { 882 | "@jridgewell/resolve-uri": "^3.1.0", 883 | "@jridgewell/sourcemap-codec": "^1.4.14" 884 | } 885 | }, 886 | "node_modules/@mui/base": { 887 | "version": "5.0.0-beta.40", 888 | "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.40.tgz", 889 | "integrity": "sha512-I/lGHztkCzvwlXpjD2+SNmvNQvB4227xBXhISPjEaJUXGImOQ9f3D2Yj/T3KasSI/h0MLWy74X0J6clhPmsRbQ==", 890 | "dev": true, 891 | "dependencies": { 892 | "@babel/runtime": "^7.23.9", 893 | "@floating-ui/react-dom": "^2.0.8", 894 | "@mui/types": "^7.2.14", 895 | "@mui/utils": "^5.15.14", 896 | "@popperjs/core": "^2.11.8", 897 | "clsx": "^2.1.0", 898 | "prop-types": "^15.8.1" 899 | }, 900 | "engines": { 901 | "node": ">=12.0.0" 902 | }, 903 | "funding": { 904 | "type": "opencollective", 905 | "url": "https://opencollective.com/mui-org" 906 | }, 907 | "peerDependencies": { 908 | "@types/react": "^17.0.0 || ^18.0.0", 909 | "react": "^17.0.0 || ^18.0.0", 910 | "react-dom": "^17.0.0 || ^18.0.0" 911 | }, 912 | "peerDependenciesMeta": { 913 | "@types/react": { 914 | "optional": true 915 | } 916 | } 917 | }, 918 | "node_modules/@mui/core-downloads-tracker": { 919 | "version": "5.16.6", 920 | "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.16.6.tgz", 921 | "integrity": "sha512-kytg6LheUG42V8H/o/Ptz3olSO5kUXW9zF0ox18VnblX6bO2yif1FPItgc3ey1t5ansb1+gbe7SatntqusQupg==", 922 | "dev": true, 923 | "funding": { 924 | "type": "opencollective", 925 | "url": "https://opencollective.com/mui-org" 926 | } 927 | }, 928 | "node_modules/@mui/icons-material": { 929 | "version": "5.16.6", 930 | "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.16.6.tgz", 931 | "integrity": "sha512-ceNGjoXheH9wbIFa1JHmSc9QVjJUvh18KvHrR4/FkJCSi9HXJ+9ee1kUhCOEFfuxNF8UB6WWVrIUOUgRd70t0A==", 932 | "dev": true, 933 | "dependencies": { 934 | "@babel/runtime": "^7.23.9" 935 | }, 936 | "engines": { 937 | "node": ">=12.0.0" 938 | }, 939 | "funding": { 940 | "type": "opencollective", 941 | "url": "https://opencollective.com/mui-org" 942 | }, 943 | "peerDependencies": { 944 | "@mui/material": "^5.0.0", 945 | "@types/react": "^17.0.0 || ^18.0.0", 946 | "react": "^17.0.0 || ^18.0.0" 947 | }, 948 | "peerDependenciesMeta": { 949 | "@types/react": { 950 | "optional": true 951 | } 952 | } 953 | }, 954 | "node_modules/@mui/joy": { 955 | "version": "5.0.0-beta.48", 956 | "resolved": "https://registry.npmjs.org/@mui/joy/-/joy-5.0.0-beta.48.tgz", 957 | "integrity": "sha512-OhTvjuGl9I5IvpBr0BQyDehIW/xb2yteW6YglHJMdOb/279nItn76X1NBtPV9ImldNlBjReGwvpOXmBTTGER9w==", 958 | "dev": true, 959 | "dependencies": { 960 | "@babel/runtime": "^7.23.9", 961 | "@mui/base": "5.0.0-beta.40", 962 | "@mui/core-downloads-tracker": "^5.16.1", 963 | "@mui/system": "^5.16.1", 964 | "@mui/types": "^7.2.15", 965 | "@mui/utils": "^5.16.1", 966 | "clsx": "^2.1.0", 967 | "prop-types": "^15.8.1" 968 | }, 969 | "engines": { 970 | "node": ">=12.0.0" 971 | }, 972 | "funding": { 973 | "type": "opencollective", 974 | "url": "https://opencollective.com/mui-org" 975 | }, 976 | "peerDependencies": { 977 | "@emotion/react": "^11.5.0", 978 | "@emotion/styled": "^11.3.0", 979 | "@types/react": "^17.0.0 || ^18.0.0", 980 | "react": "^17.0.0 || ^18.0.0", 981 | "react-dom": "^17.0.0 || ^18.0.0" 982 | }, 983 | "peerDependenciesMeta": { 984 | "@emotion/react": { 985 | "optional": true 986 | }, 987 | "@emotion/styled": { 988 | "optional": true 989 | }, 990 | "@types/react": { 991 | "optional": true 992 | } 993 | } 994 | }, 995 | "node_modules/@mui/material": { 996 | "version": "5.16.6", 997 | "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.16.6.tgz", 998 | "integrity": "sha512-0LUIKBOIjiFfzzFNxXZBRAyr9UQfmTAFzbt6ziOU2FDXhorNN2o3N9/32mNJbCA8zJo2FqFU6d3dtoqUDyIEfA==", 999 | "dev": true, 1000 | "peer": true, 1001 | "dependencies": { 1002 | "@babel/runtime": "^7.23.9", 1003 | "@mui/core-downloads-tracker": "^5.16.6", 1004 | "@mui/system": "^5.16.6", 1005 | "@mui/types": "^7.2.15", 1006 | "@mui/utils": "^5.16.6", 1007 | "@popperjs/core": "^2.11.8", 1008 | "@types/react-transition-group": "^4.4.10", 1009 | "clsx": "^2.1.0", 1010 | "csstype": "^3.1.3", 1011 | "prop-types": "^15.8.1", 1012 | "react-is": "^18.3.1", 1013 | "react-transition-group": "^4.4.5" 1014 | }, 1015 | "engines": { 1016 | "node": ">=12.0.0" 1017 | }, 1018 | "funding": { 1019 | "type": "opencollective", 1020 | "url": "https://opencollective.com/mui-org" 1021 | }, 1022 | "peerDependencies": { 1023 | "@emotion/react": "^11.5.0", 1024 | "@emotion/styled": "^11.3.0", 1025 | "@types/react": "^17.0.0 || ^18.0.0", 1026 | "react": "^17.0.0 || ^18.0.0", 1027 | "react-dom": "^17.0.0 || ^18.0.0" 1028 | }, 1029 | "peerDependenciesMeta": { 1030 | "@emotion/react": { 1031 | "optional": true 1032 | }, 1033 | "@emotion/styled": { 1034 | "optional": true 1035 | }, 1036 | "@types/react": { 1037 | "optional": true 1038 | } 1039 | } 1040 | }, 1041 | "node_modules/@mui/private-theming": { 1042 | "version": "5.16.6", 1043 | "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.16.6.tgz", 1044 | "integrity": "sha512-rAk+Rh8Clg7Cd7shZhyt2HGTTE5wYKNSJ5sspf28Fqm/PZ69Er9o6KX25g03/FG2dfpg5GCwZh/xOojiTfm3hw==", 1045 | "dev": true, 1046 | "dependencies": { 1047 | "@babel/runtime": "^7.23.9", 1048 | "@mui/utils": "^5.16.6", 1049 | "prop-types": "^15.8.1" 1050 | }, 1051 | "engines": { 1052 | "node": ">=12.0.0" 1053 | }, 1054 | "funding": { 1055 | "type": "opencollective", 1056 | "url": "https://opencollective.com/mui-org" 1057 | }, 1058 | "peerDependencies": { 1059 | "@types/react": "^17.0.0 || ^18.0.0", 1060 | "react": "^17.0.0 || ^18.0.0" 1061 | }, 1062 | "peerDependenciesMeta": { 1063 | "@types/react": { 1064 | "optional": true 1065 | } 1066 | } 1067 | }, 1068 | "node_modules/@mui/styled-engine": { 1069 | "version": "5.16.6", 1070 | "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.16.6.tgz", 1071 | "integrity": "sha512-zaThmS67ZmtHSWToTiHslbI8jwrmITcN93LQaR2lKArbvS7Z3iLkwRoiikNWutx9MBs8Q6okKvbZq1RQYB3v7g==", 1072 | "dev": true, 1073 | "dependencies": { 1074 | "@babel/runtime": "^7.23.9", 1075 | "@emotion/cache": "^11.11.0", 1076 | "csstype": "^3.1.3", 1077 | "prop-types": "^15.8.1" 1078 | }, 1079 | "engines": { 1080 | "node": ">=12.0.0" 1081 | }, 1082 | "funding": { 1083 | "type": "opencollective", 1084 | "url": "https://opencollective.com/mui-org" 1085 | }, 1086 | "peerDependencies": { 1087 | "@emotion/react": "^11.4.1", 1088 | "@emotion/styled": "^11.3.0", 1089 | "react": "^17.0.0 || ^18.0.0" 1090 | }, 1091 | "peerDependenciesMeta": { 1092 | "@emotion/react": { 1093 | "optional": true 1094 | }, 1095 | "@emotion/styled": { 1096 | "optional": true 1097 | } 1098 | } 1099 | }, 1100 | "node_modules/@mui/system": { 1101 | "version": "5.16.6", 1102 | "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.16.6.tgz", 1103 | "integrity": "sha512-5xgyJjBIMPw8HIaZpfbGAaFYPwImQn7Nyh+wwKWhvkoIeDosQ1ZMVrbTclefi7G8hNmqhip04duYwYpbBFnBgw==", 1104 | "dev": true, 1105 | "dependencies": { 1106 | "@babel/runtime": "^7.23.9", 1107 | "@mui/private-theming": "^5.16.6", 1108 | "@mui/styled-engine": "^5.16.6", 1109 | "@mui/types": "^7.2.15", 1110 | "@mui/utils": "^5.16.6", 1111 | "clsx": "^2.1.0", 1112 | "csstype": "^3.1.3", 1113 | "prop-types": "^15.8.1" 1114 | }, 1115 | "engines": { 1116 | "node": ">=12.0.0" 1117 | }, 1118 | "funding": { 1119 | "type": "opencollective", 1120 | "url": "https://opencollective.com/mui-org" 1121 | }, 1122 | "peerDependencies": { 1123 | "@emotion/react": "^11.5.0", 1124 | "@emotion/styled": "^11.3.0", 1125 | "@types/react": "^17.0.0 || ^18.0.0", 1126 | "react": "^17.0.0 || ^18.0.0" 1127 | }, 1128 | "peerDependenciesMeta": { 1129 | "@emotion/react": { 1130 | "optional": true 1131 | }, 1132 | "@emotion/styled": { 1133 | "optional": true 1134 | }, 1135 | "@types/react": { 1136 | "optional": true 1137 | } 1138 | } 1139 | }, 1140 | "node_modules/@mui/types": { 1141 | "version": "7.2.15", 1142 | "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.15.tgz", 1143 | "integrity": "sha512-nbo7yPhtKJkdf9kcVOF8JZHPZTmqXjJ/tI0bdWgHg5tp9AnIN4Y7f7wm9T+0SyGYJk76+GYZ8Q5XaTYAsUHN0Q==", 1144 | "dev": true, 1145 | "peerDependencies": { 1146 | "@types/react": "^17.0.0 || ^18.0.0" 1147 | }, 1148 | "peerDependenciesMeta": { 1149 | "@types/react": { 1150 | "optional": true 1151 | } 1152 | } 1153 | }, 1154 | "node_modules/@mui/utils": { 1155 | "version": "5.16.6", 1156 | "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.16.6.tgz", 1157 | "integrity": "sha512-tWiQqlhxAt3KENNiSRL+DIn9H5xNVK6Jjf70x3PnfQPz1MPBdh7yyIcAyVBT9xiw7hP3SomRhPR7hzBMBCjqEA==", 1158 | "dev": true, 1159 | "dependencies": { 1160 | "@babel/runtime": "^7.23.9", 1161 | "@mui/types": "^7.2.15", 1162 | "@types/prop-types": "^15.7.12", 1163 | "clsx": "^2.1.1", 1164 | "prop-types": "^15.8.1", 1165 | "react-is": "^18.3.1" 1166 | }, 1167 | "engines": { 1168 | "node": ">=12.0.0" 1169 | }, 1170 | "funding": { 1171 | "type": "opencollective", 1172 | "url": "https://opencollective.com/mui-org" 1173 | }, 1174 | "peerDependencies": { 1175 | "@types/react": "^17.0.0 || ^18.0.0", 1176 | "react": "^17.0.0 || ^18.0.0" 1177 | }, 1178 | "peerDependenciesMeta": { 1179 | "@types/react": { 1180 | "optional": true 1181 | } 1182 | } 1183 | }, 1184 | "node_modules/@parcel/source-map": { 1185 | "version": "2.1.1", 1186 | "resolved": "https://registry.npmjs.org/@parcel/source-map/-/source-map-2.1.1.tgz", 1187 | "integrity": "sha512-Ejx1P/mj+kMjQb8/y5XxDUn4reGdr+WyKYloBljpppUy8gs42T+BNoEOuRYqDVdgPc6NxduzIDoJS9pOFfV5Ew==", 1188 | "dev": true, 1189 | "dependencies": { 1190 | "detect-libc": "^1.0.3" 1191 | }, 1192 | "engines": { 1193 | "node": "^12.18.3 || >=14" 1194 | } 1195 | }, 1196 | "node_modules/@popperjs/core": { 1197 | "version": "2.11.8", 1198 | "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", 1199 | "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", 1200 | "dev": true, 1201 | "funding": { 1202 | "type": "opencollective", 1203 | "url": "https://opencollective.com/popperjs" 1204 | } 1205 | }, 1206 | "node_modules/@types/d3": { 1207 | "version": "7.4.3", 1208 | "resolved": "https://registry.npmjs.org/@types/d3/-/d3-7.4.3.tgz", 1209 | "integrity": "sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==", 1210 | "dev": true, 1211 | "dependencies": { 1212 | "@types/d3-array": "*", 1213 | "@types/d3-axis": "*", 1214 | "@types/d3-brush": "*", 1215 | "@types/d3-chord": "*", 1216 | "@types/d3-color": "*", 1217 | "@types/d3-contour": "*", 1218 | "@types/d3-delaunay": "*", 1219 | "@types/d3-dispatch": "*", 1220 | "@types/d3-drag": "*", 1221 | "@types/d3-dsv": "*", 1222 | "@types/d3-ease": "*", 1223 | "@types/d3-fetch": "*", 1224 | "@types/d3-force": "*", 1225 | "@types/d3-format": "*", 1226 | "@types/d3-geo": "*", 1227 | "@types/d3-hierarchy": "*", 1228 | "@types/d3-interpolate": "*", 1229 | "@types/d3-path": "*", 1230 | "@types/d3-polygon": "*", 1231 | "@types/d3-quadtree": "*", 1232 | "@types/d3-random": "*", 1233 | "@types/d3-scale": "*", 1234 | "@types/d3-scale-chromatic": "*", 1235 | "@types/d3-selection": "*", 1236 | "@types/d3-shape": "*", 1237 | "@types/d3-time": "*", 1238 | "@types/d3-time-format": "*", 1239 | "@types/d3-timer": "*", 1240 | "@types/d3-transition": "*", 1241 | "@types/d3-zoom": "*" 1242 | } 1243 | }, 1244 | "node_modules/@types/d3-array": { 1245 | "version": "3.2.1", 1246 | "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.1.tgz", 1247 | "integrity": "sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==", 1248 | "dev": true 1249 | }, 1250 | "node_modules/@types/d3-axis": { 1251 | "version": "3.0.6", 1252 | "resolved": "https://registry.npmjs.org/@types/d3-axis/-/d3-axis-3.0.6.tgz", 1253 | "integrity": "sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==", 1254 | "dev": true, 1255 | "dependencies": { 1256 | "@types/d3-selection": "*" 1257 | } 1258 | }, 1259 | "node_modules/@types/d3-brush": { 1260 | "version": "3.0.6", 1261 | "resolved": "https://registry.npmjs.org/@types/d3-brush/-/d3-brush-3.0.6.tgz", 1262 | "integrity": "sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==", 1263 | "dev": true, 1264 | "dependencies": { 1265 | "@types/d3-selection": "*" 1266 | } 1267 | }, 1268 | "node_modules/@types/d3-chord": { 1269 | "version": "3.0.6", 1270 | "resolved": "https://registry.npmjs.org/@types/d3-chord/-/d3-chord-3.0.6.tgz", 1271 | "integrity": "sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==", 1272 | "dev": true 1273 | }, 1274 | "node_modules/@types/d3-color": { 1275 | "version": "3.1.3", 1276 | "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", 1277 | "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==", 1278 | "dev": true 1279 | }, 1280 | "node_modules/@types/d3-contour": { 1281 | "version": "3.0.6", 1282 | "resolved": "https://registry.npmjs.org/@types/d3-contour/-/d3-contour-3.0.6.tgz", 1283 | "integrity": "sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==", 1284 | "dev": true, 1285 | "dependencies": { 1286 | "@types/d3-array": "*", 1287 | "@types/geojson": "*" 1288 | } 1289 | }, 1290 | "node_modules/@types/d3-delaunay": { 1291 | "version": "6.0.4", 1292 | "resolved": "https://registry.npmjs.org/@types/d3-delaunay/-/d3-delaunay-6.0.4.tgz", 1293 | "integrity": "sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==", 1294 | "dev": true 1295 | }, 1296 | "node_modules/@types/d3-dispatch": { 1297 | "version": "3.0.6", 1298 | "resolved": "https://registry.npmjs.org/@types/d3-dispatch/-/d3-dispatch-3.0.6.tgz", 1299 | "integrity": "sha512-4fvZhzMeeuBJYZXRXrRIQnvUYfyXwYmLsdiN7XXmVNQKKw1cM8a5WdID0g1hVFZDqT9ZqZEY5pD44p24VS7iZQ==", 1300 | "dev": true 1301 | }, 1302 | "node_modules/@types/d3-drag": { 1303 | "version": "3.0.7", 1304 | "resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-3.0.7.tgz", 1305 | "integrity": "sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==", 1306 | "dev": true, 1307 | "dependencies": { 1308 | "@types/d3-selection": "*" 1309 | } 1310 | }, 1311 | "node_modules/@types/d3-dsv": { 1312 | "version": "3.0.7", 1313 | "resolved": "https://registry.npmjs.org/@types/d3-dsv/-/d3-dsv-3.0.7.tgz", 1314 | "integrity": "sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==", 1315 | "dev": true 1316 | }, 1317 | "node_modules/@types/d3-ease": { 1318 | "version": "3.0.2", 1319 | "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", 1320 | "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==", 1321 | "dev": true 1322 | }, 1323 | "node_modules/@types/d3-fetch": { 1324 | "version": "3.0.7", 1325 | "resolved": "https://registry.npmjs.org/@types/d3-fetch/-/d3-fetch-3.0.7.tgz", 1326 | "integrity": "sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==", 1327 | "dev": true, 1328 | "dependencies": { 1329 | "@types/d3-dsv": "*" 1330 | } 1331 | }, 1332 | "node_modules/@types/d3-force": { 1333 | "version": "3.0.10", 1334 | "resolved": "https://registry.npmjs.org/@types/d3-force/-/d3-force-3.0.10.tgz", 1335 | "integrity": "sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==", 1336 | "dev": true 1337 | }, 1338 | "node_modules/@types/d3-format": { 1339 | "version": "3.0.4", 1340 | "resolved": "https://registry.npmjs.org/@types/d3-format/-/d3-format-3.0.4.tgz", 1341 | "integrity": "sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==", 1342 | "dev": true 1343 | }, 1344 | "node_modules/@types/d3-geo": { 1345 | "version": "3.1.0", 1346 | "resolved": "https://registry.npmjs.org/@types/d3-geo/-/d3-geo-3.1.0.tgz", 1347 | "integrity": "sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==", 1348 | "dev": true, 1349 | "dependencies": { 1350 | "@types/geojson": "*" 1351 | } 1352 | }, 1353 | "node_modules/@types/d3-hierarchy": { 1354 | "version": "3.1.7", 1355 | "resolved": "https://registry.npmjs.org/@types/d3-hierarchy/-/d3-hierarchy-3.1.7.tgz", 1356 | "integrity": "sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==", 1357 | "dev": true 1358 | }, 1359 | "node_modules/@types/d3-interpolate": { 1360 | "version": "3.0.4", 1361 | "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", 1362 | "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", 1363 | "dev": true, 1364 | "dependencies": { 1365 | "@types/d3-color": "*" 1366 | } 1367 | }, 1368 | "node_modules/@types/d3-path": { 1369 | "version": "3.1.0", 1370 | "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.0.tgz", 1371 | "integrity": "sha512-P2dlU/q51fkOc/Gfl3Ul9kicV7l+ra934qBFXCFhrZMOL6du1TM0pm1ThYvENukyOn5h9v+yMJ9Fn5JK4QozrQ==", 1372 | "dev": true 1373 | }, 1374 | "node_modules/@types/d3-polygon": { 1375 | "version": "3.0.2", 1376 | "resolved": "https://registry.npmjs.org/@types/d3-polygon/-/d3-polygon-3.0.2.tgz", 1377 | "integrity": "sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==", 1378 | "dev": true 1379 | }, 1380 | "node_modules/@types/d3-quadtree": { 1381 | "version": "3.0.6", 1382 | "resolved": "https://registry.npmjs.org/@types/d3-quadtree/-/d3-quadtree-3.0.6.tgz", 1383 | "integrity": "sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==", 1384 | "dev": true 1385 | }, 1386 | "node_modules/@types/d3-random": { 1387 | "version": "3.0.3", 1388 | "resolved": "https://registry.npmjs.org/@types/d3-random/-/d3-random-3.0.3.tgz", 1389 | "integrity": "sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ==", 1390 | "dev": true 1391 | }, 1392 | "node_modules/@types/d3-scale": { 1393 | "version": "4.0.8", 1394 | "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.8.tgz", 1395 | "integrity": "sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ==", 1396 | "dev": true, 1397 | "dependencies": { 1398 | "@types/d3-time": "*" 1399 | } 1400 | }, 1401 | "node_modules/@types/d3-scale-chromatic": { 1402 | "version": "3.0.3", 1403 | "resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.0.3.tgz", 1404 | "integrity": "sha512-laXM4+1o5ImZv3RpFAsTRn3TEkzqkytiOY0Dz0sq5cnd1dtNlk6sHLon4OvqaiJb28T0S/TdsBI3Sjsy+keJrw==", 1405 | "dev": true 1406 | }, 1407 | "node_modules/@types/d3-selection": { 1408 | "version": "3.0.10", 1409 | "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-3.0.10.tgz", 1410 | "integrity": "sha512-cuHoUgS/V3hLdjJOLTT691+G2QoqAjCVLmr4kJXR4ha56w1Zdu8UUQ5TxLRqudgNjwXeQxKMq4j+lyf9sWuslg==", 1411 | "dev": true 1412 | }, 1413 | "node_modules/@types/d3-shape": { 1414 | "version": "3.1.6", 1415 | "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.6.tgz", 1416 | "integrity": "sha512-5KKk5aKGu2I+O6SONMYSNflgiP0WfZIQvVUMan50wHsLG1G94JlxEVnCpQARfTtzytuY0p/9PXXZb3I7giofIA==", 1417 | "dev": true, 1418 | "dependencies": { 1419 | "@types/d3-path": "*" 1420 | } 1421 | }, 1422 | "node_modules/@types/d3-time": { 1423 | "version": "3.0.3", 1424 | "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.3.tgz", 1425 | "integrity": "sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw==", 1426 | "dev": true 1427 | }, 1428 | "node_modules/@types/d3-time-format": { 1429 | "version": "4.0.3", 1430 | "resolved": "https://registry.npmjs.org/@types/d3-time-format/-/d3-time-format-4.0.3.tgz", 1431 | "integrity": "sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==", 1432 | "dev": true 1433 | }, 1434 | "node_modules/@types/d3-timer": { 1435 | "version": "3.0.2", 1436 | "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", 1437 | "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==", 1438 | "dev": true 1439 | }, 1440 | "node_modules/@types/d3-transition": { 1441 | "version": "3.0.8", 1442 | "resolved": "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-3.0.8.tgz", 1443 | "integrity": "sha512-ew63aJfQ/ms7QQ4X7pk5NxQ9fZH/z+i24ZfJ6tJSfqxJMrYLiK01EAs2/Rtw/JreGUsS3pLPNV644qXFGnoZNQ==", 1444 | "dev": true, 1445 | "dependencies": { 1446 | "@types/d3-selection": "*" 1447 | } 1448 | }, 1449 | "node_modules/@types/d3-zoom": { 1450 | "version": "3.0.8", 1451 | "resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-3.0.8.tgz", 1452 | "integrity": "sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==", 1453 | "dev": true, 1454 | "dependencies": { 1455 | "@types/d3-interpolate": "*", 1456 | "@types/d3-selection": "*" 1457 | } 1458 | }, 1459 | "node_modules/@types/geojson": { 1460 | "version": "7946.0.14", 1461 | "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.14.tgz", 1462 | "integrity": "sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg==", 1463 | "dev": true 1464 | }, 1465 | "node_modules/@types/parse-json": { 1466 | "version": "4.0.2", 1467 | "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", 1468 | "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", 1469 | "dev": true 1470 | }, 1471 | "node_modules/@types/prop-types": { 1472 | "version": "15.7.12", 1473 | "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", 1474 | "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", 1475 | "dev": true 1476 | }, 1477 | "node_modules/@types/react": { 1478 | "version": "18.3.3", 1479 | "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", 1480 | "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", 1481 | "dev": true, 1482 | "dependencies": { 1483 | "@types/prop-types": "*", 1484 | "csstype": "^3.0.2" 1485 | } 1486 | }, 1487 | "node_modules/@types/react-dom": { 1488 | "version": "18.3.0", 1489 | "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", 1490 | "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", 1491 | "dev": true, 1492 | "dependencies": { 1493 | "@types/react": "*" 1494 | } 1495 | }, 1496 | "node_modules/@types/react-transition-group": { 1497 | "version": "4.4.10", 1498 | "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.10.tgz", 1499 | "integrity": "sha512-hT/+s0VQs2ojCX823m60m5f0sL5idt9SO6Tj6Dg+rdphGPIeJbJ6CxvBYkgkGKrYeDjvIpKTR38UzmtHJOGW3Q==", 1500 | "dev": true, 1501 | "peer": true, 1502 | "dependencies": { 1503 | "@types/react": "*" 1504 | } 1505 | }, 1506 | "node_modules/@yowasp/yosys": { 1507 | "version": "0.44.759", 1508 | "resolved": "https://registry.npmjs.org/@yowasp/yosys/-/yosys-0.44.759.tgz", 1509 | "integrity": "sha512-G7ZjA40dCXeVAYi+cYYI1A0JE1j9orZO0P1NFuE14PUa2miVbCcznyK6gERaCyi6tNv1x7IYRoGAqpBl7KTKZA==", 1510 | "dev": true 1511 | }, 1512 | "node_modules/ansi-styles": { 1513 | "version": "3.2.1", 1514 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 1515 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 1516 | "dev": true, 1517 | "dependencies": { 1518 | "color-convert": "^1.9.0" 1519 | }, 1520 | "engines": { 1521 | "node": ">=4" 1522 | } 1523 | }, 1524 | "node_modules/babel-plugin-macros": { 1525 | "version": "3.1.0", 1526 | "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", 1527 | "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", 1528 | "dev": true, 1529 | "dependencies": { 1530 | "@babel/runtime": "^7.12.5", 1531 | "cosmiconfig": "^7.0.0", 1532 | "resolve": "^1.19.0" 1533 | }, 1534 | "engines": { 1535 | "node": ">=10", 1536 | "npm": ">=6" 1537 | } 1538 | }, 1539 | "node_modules/base-64": { 1540 | "version": "1.0.0", 1541 | "resolved": "https://registry.npmjs.org/base-64/-/base-64-1.0.0.tgz", 1542 | "integrity": "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==", 1543 | "dev": true 1544 | }, 1545 | "node_modules/callsites": { 1546 | "version": "3.1.0", 1547 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", 1548 | "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", 1549 | "dev": true, 1550 | "engines": { 1551 | "node": ">=6" 1552 | } 1553 | }, 1554 | "node_modules/chalk": { 1555 | "version": "2.4.2", 1556 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 1557 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 1558 | "dev": true, 1559 | "dependencies": { 1560 | "ansi-styles": "^3.2.1", 1561 | "escape-string-regexp": "^1.0.5", 1562 | "supports-color": "^5.3.0" 1563 | }, 1564 | "engines": { 1565 | "node": ">=4" 1566 | } 1567 | }, 1568 | "node_modules/chalk/node_modules/escape-string-regexp": { 1569 | "version": "1.0.5", 1570 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 1571 | "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", 1572 | "dev": true, 1573 | "engines": { 1574 | "node": ">=0.8.0" 1575 | } 1576 | }, 1577 | "node_modules/clsx": { 1578 | "version": "2.1.1", 1579 | "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", 1580 | "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", 1581 | "dev": true, 1582 | "engines": { 1583 | "node": ">=6" 1584 | } 1585 | }, 1586 | "node_modules/color-convert": { 1587 | "version": "1.9.3", 1588 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 1589 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 1590 | "dev": true, 1591 | "dependencies": { 1592 | "color-name": "1.1.3" 1593 | } 1594 | }, 1595 | "node_modules/color-name": { 1596 | "version": "1.1.3", 1597 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 1598 | "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", 1599 | "dev": true 1600 | }, 1601 | "node_modules/commander": { 1602 | "version": "2.20.3", 1603 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", 1604 | "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", 1605 | "dev": true 1606 | }, 1607 | "node_modules/convert-source-map": { 1608 | "version": "1.9.0", 1609 | "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", 1610 | "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", 1611 | "dev": true 1612 | }, 1613 | "node_modules/cosmiconfig": { 1614 | "version": "7.1.0", 1615 | "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", 1616 | "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", 1617 | "dev": true, 1618 | "dependencies": { 1619 | "@types/parse-json": "^4.0.0", 1620 | "import-fresh": "^3.2.1", 1621 | "parse-json": "^5.0.0", 1622 | "path-type": "^4.0.0", 1623 | "yaml": "^1.10.0" 1624 | }, 1625 | "engines": { 1626 | "node": ">=10" 1627 | } 1628 | }, 1629 | "node_modules/csstype": { 1630 | "version": "3.1.3", 1631 | "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", 1632 | "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", 1633 | "dev": true 1634 | }, 1635 | "node_modules/d3": { 1636 | "version": "6.7.0", 1637 | "resolved": "https://registry.npmjs.org/d3/-/d3-6.7.0.tgz", 1638 | "integrity": "sha512-hNHRhe+yCDLUG6Q2LwvR/WdNFPOJQ5VWqsJcwIYVeI401+d2/rrCjxSXkiAdIlpx7/73eApFB4Olsmh3YN7a6g==", 1639 | "dev": true, 1640 | "dependencies": { 1641 | "d3-array": "2", 1642 | "d3-axis": "2", 1643 | "d3-brush": "2", 1644 | "d3-chord": "2", 1645 | "d3-color": "2", 1646 | "d3-contour": "2", 1647 | "d3-delaunay": "5", 1648 | "d3-dispatch": "2", 1649 | "d3-drag": "2", 1650 | "d3-dsv": "2", 1651 | "d3-ease": "2", 1652 | "d3-fetch": "2", 1653 | "d3-force": "2", 1654 | "d3-format": "2", 1655 | "d3-geo": "2", 1656 | "d3-hierarchy": "2", 1657 | "d3-interpolate": "2", 1658 | "d3-path": "2", 1659 | "d3-polygon": "2", 1660 | "d3-quadtree": "2", 1661 | "d3-random": "2", 1662 | "d3-scale": "3", 1663 | "d3-scale-chromatic": "2", 1664 | "d3-selection": "2", 1665 | "d3-shape": "2", 1666 | "d3-time": "2", 1667 | "d3-time-format": "3", 1668 | "d3-timer": "2", 1669 | "d3-transition": "2", 1670 | "d3-zoom": "2" 1671 | } 1672 | }, 1673 | "node_modules/d3-array": { 1674 | "version": "2.12.1", 1675 | "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz", 1676 | "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==", 1677 | "dev": true, 1678 | "dependencies": { 1679 | "internmap": "^1.0.0" 1680 | } 1681 | }, 1682 | "node_modules/d3-axis": { 1683 | "version": "2.1.0", 1684 | "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-2.1.0.tgz", 1685 | "integrity": "sha512-z/G2TQMyuf0X3qP+Mh+2PimoJD41VOCjViJzT0BHeL/+JQAofkiWZbWxlwFGb1N8EN+Cl/CW+MUKbVzr1689Cw==", 1686 | "dev": true 1687 | }, 1688 | "node_modules/d3-brush": { 1689 | "version": "2.1.0", 1690 | "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-2.1.0.tgz", 1691 | "integrity": "sha512-cHLLAFatBATyIKqZOkk/mDHUbzne2B3ZwxkzMHvFTCZCmLaXDpZRihQSn8UNXTkGD/3lb/W2sQz0etAftmHMJQ==", 1692 | "dev": true, 1693 | "dependencies": { 1694 | "d3-dispatch": "1 - 2", 1695 | "d3-drag": "2", 1696 | "d3-interpolate": "1 - 2", 1697 | "d3-selection": "2", 1698 | "d3-transition": "2" 1699 | } 1700 | }, 1701 | "node_modules/d3-chord": { 1702 | "version": "2.0.0", 1703 | "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-2.0.0.tgz", 1704 | "integrity": "sha512-D5PZb7EDsRNdGU4SsjQyKhja8Zgu+SHZfUSO5Ls8Wsn+jsAKUUGkcshLxMg9HDFxG3KqavGWaWkJ8EpU8ojuig==", 1705 | "dev": true, 1706 | "dependencies": { 1707 | "d3-path": "1 - 2" 1708 | } 1709 | }, 1710 | "node_modules/d3-color": { 1711 | "version": "2.0.0", 1712 | "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-2.0.0.tgz", 1713 | "integrity": "sha512-SPXi0TSKPD4g9tw0NMZFnR95XVgUZiBH+uUTqQuDu1OsE2zomHU7ho0FISciaPvosimixwHFl3WHLGabv6dDgQ==", 1714 | "dev": true 1715 | }, 1716 | "node_modules/d3-contour": { 1717 | "version": "2.0.0", 1718 | "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-2.0.0.tgz", 1719 | "integrity": "sha512-9unAtvIaNk06UwqBmvsdHX7CZ+NPDZnn8TtNH1myW93pWJkhsV25JcgnYAu0Ck5Veb1DHiCv++Ic5uvJ+h50JA==", 1720 | "dev": true, 1721 | "dependencies": { 1722 | "d3-array": "2" 1723 | } 1724 | }, 1725 | "node_modules/d3-delaunay": { 1726 | "version": "5.3.0", 1727 | "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-5.3.0.tgz", 1728 | "integrity": "sha512-amALSrOllWVLaHTnDLHwMIiz0d1bBu9gZXd1FiLfXf8sHcX9jrcj81TVZOqD4UX7MgBZZ07c8GxzEgBpJqc74w==", 1729 | "dev": true, 1730 | "dependencies": { 1731 | "delaunator": "4" 1732 | } 1733 | }, 1734 | "node_modules/d3-dispatch": { 1735 | "version": "2.0.0", 1736 | "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-2.0.0.tgz", 1737 | "integrity": "sha512-S/m2VsXI7gAti2pBoLClFFTMOO1HTtT0j99AuXLoGFKO6deHDdnv6ZGTxSTTUTgO1zVcv82fCOtDjYK4EECmWA==", 1738 | "dev": true 1739 | }, 1740 | "node_modules/d3-drag": { 1741 | "version": "2.0.0", 1742 | "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-2.0.0.tgz", 1743 | "integrity": "sha512-g9y9WbMnF5uqB9qKqwIIa/921RYWzlUDv9Jl1/yONQwxbOfszAWTCm8u7HOTgJgRDXiRZN56cHT9pd24dmXs8w==", 1744 | "dev": true, 1745 | "dependencies": { 1746 | "d3-dispatch": "1 - 2", 1747 | "d3-selection": "2" 1748 | } 1749 | }, 1750 | "node_modules/d3-dsv": { 1751 | "version": "2.0.0", 1752 | "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-2.0.0.tgz", 1753 | "integrity": "sha512-E+Pn8UJYx9mViuIUkoc93gJGGYut6mSDKy2+XaPwccwkRGlR+LO97L2VCCRjQivTwLHkSnAJG7yo00BWY6QM+w==", 1754 | "dev": true, 1755 | "dependencies": { 1756 | "commander": "2", 1757 | "iconv-lite": "0.4", 1758 | "rw": "1" 1759 | }, 1760 | "bin": { 1761 | "csv2json": "bin/dsv2json", 1762 | "csv2tsv": "bin/dsv2dsv", 1763 | "dsv2dsv": "bin/dsv2dsv", 1764 | "dsv2json": "bin/dsv2json", 1765 | "json2csv": "bin/json2dsv", 1766 | "json2dsv": "bin/json2dsv", 1767 | "json2tsv": "bin/json2dsv", 1768 | "tsv2csv": "bin/dsv2dsv", 1769 | "tsv2json": "bin/dsv2json" 1770 | } 1771 | }, 1772 | "node_modules/d3-ease": { 1773 | "version": "2.0.0", 1774 | "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-2.0.0.tgz", 1775 | "integrity": "sha512-68/n9JWarxXkOWMshcT5IcjbB+agblQUaIsbnXmrzejn2O82n3p2A9R2zEB9HIEFWKFwPAEDDN8gR0VdSAyyAQ==", 1776 | "dev": true 1777 | }, 1778 | "node_modules/d3-fetch": { 1779 | "version": "2.0.0", 1780 | "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-2.0.0.tgz", 1781 | "integrity": "sha512-TkYv/hjXgCryBeNKiclrwqZH7Nb+GaOwo3Neg24ZVWA3MKB+Rd+BY84Nh6tmNEMcjUik1CSUWjXYndmeO6F7sw==", 1782 | "dev": true, 1783 | "dependencies": { 1784 | "d3-dsv": "1 - 2" 1785 | } 1786 | }, 1787 | "node_modules/d3-force": { 1788 | "version": "2.1.1", 1789 | "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-2.1.1.tgz", 1790 | "integrity": "sha512-nAuHEzBqMvpFVMf9OX75d00OxvOXdxY+xECIXjW6Gv8BRrXu6gAWbv/9XKrvfJ5i5DCokDW7RYE50LRoK092ew==", 1791 | "dev": true, 1792 | "dependencies": { 1793 | "d3-dispatch": "1 - 2", 1794 | "d3-quadtree": "1 - 2", 1795 | "d3-timer": "1 - 2" 1796 | } 1797 | }, 1798 | "node_modules/d3-format": { 1799 | "version": "2.0.0", 1800 | "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-2.0.0.tgz", 1801 | "integrity": "sha512-Ab3S6XuE/Q+flY96HXT0jOXcM4EAClYFnRGY5zsjRGNy6qCYrQsMffs7cV5Q9xejb35zxW5hf/guKw34kvIKsA==", 1802 | "dev": true 1803 | }, 1804 | "node_modules/d3-geo": { 1805 | "version": "2.0.2", 1806 | "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-2.0.2.tgz", 1807 | "integrity": "sha512-8pM1WGMLGFuhq9S+FpPURxic+gKzjluCD/CHTuUF3mXMeiCo0i6R0tO1s4+GArRFde96SLcW/kOFRjoAosPsFA==", 1808 | "dev": true, 1809 | "dependencies": { 1810 | "d3-array": "^2.5.0" 1811 | } 1812 | }, 1813 | "node_modules/d3-hierarchy": { 1814 | "version": "2.0.0", 1815 | "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-2.0.0.tgz", 1816 | "integrity": "sha512-SwIdqM3HxQX2214EG9GTjgmCc/mbSx4mQBn+DuEETubhOw6/U3fmnji4uCVrmzOydMHSO1nZle5gh6HB/wdOzw==", 1817 | "dev": true 1818 | }, 1819 | "node_modules/d3-interpolate": { 1820 | "version": "2.0.1", 1821 | "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-2.0.1.tgz", 1822 | "integrity": "sha512-c5UhwwTs/yybcmTpAVqwSFl6vrQ8JZJoT5F7xNFK9pymv5C0Ymcc9/LIJHtYIggg/yS9YHw8i8O8tgb9pupjeQ==", 1823 | "dev": true, 1824 | "dependencies": { 1825 | "d3-color": "1 - 2" 1826 | } 1827 | }, 1828 | "node_modules/d3-path": { 1829 | "version": "2.0.0", 1830 | "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-2.0.0.tgz", 1831 | "integrity": "sha512-ZwZQxKhBnv9yHaiWd6ZU4x5BtCQ7pXszEV9CU6kRgwIQVQGLMv1oiL4M+MK/n79sYzsj+gcgpPQSctJUsLN7fA==", 1832 | "dev": true 1833 | }, 1834 | "node_modules/d3-polygon": { 1835 | "version": "2.0.0", 1836 | "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-2.0.0.tgz", 1837 | "integrity": "sha512-MsexrCK38cTGermELs0cO1d79DcTsQRN7IWMJKczD/2kBjzNXxLUWP33qRF6VDpiLV/4EI4r6Gs0DAWQkE8pSQ==", 1838 | "dev": true 1839 | }, 1840 | "node_modules/d3-quadtree": { 1841 | "version": "2.0.0", 1842 | "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-2.0.0.tgz", 1843 | "integrity": "sha512-b0Ed2t1UUalJpc3qXzKi+cPGxeXRr4KU9YSlocN74aTzp6R/Ud43t79yLLqxHRWZfsvWXmbDWPpoENK1K539xw==", 1844 | "dev": true 1845 | }, 1846 | "node_modules/d3-random": { 1847 | "version": "2.2.2", 1848 | "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-2.2.2.tgz", 1849 | "integrity": "sha512-0D9P8TRj6qDAtHhRQn6EfdOtHMfsUWanl3yb/84C4DqpZ+VsgfI5iTVRNRbELCfNvRfpMr8OrqqUTQ6ANGCijw==", 1850 | "dev": true 1851 | }, 1852 | "node_modules/d3-scale": { 1853 | "version": "3.3.0", 1854 | "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-3.3.0.tgz", 1855 | "integrity": "sha512-1JGp44NQCt5d1g+Yy+GeOnZP7xHo0ii8zsQp6PGzd+C1/dl0KGsp9A7Mxwp+1D1o4unbTTxVdU/ZOIEBoeZPbQ==", 1856 | "dev": true, 1857 | "dependencies": { 1858 | "d3-array": "^2.3.0", 1859 | "d3-format": "1 - 2", 1860 | "d3-interpolate": "1.2.0 - 2", 1861 | "d3-time": "^2.1.1", 1862 | "d3-time-format": "2 - 3" 1863 | } 1864 | }, 1865 | "node_modules/d3-scale-chromatic": { 1866 | "version": "2.0.0", 1867 | "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-2.0.0.tgz", 1868 | "integrity": "sha512-LLqy7dJSL8yDy7NRmf6xSlsFZ6zYvJ4BcWFE4zBrOPnQERv9zj24ohnXKRbyi9YHnYV+HN1oEO3iFK971/gkzA==", 1869 | "dev": true, 1870 | "dependencies": { 1871 | "d3-color": "1 - 2", 1872 | "d3-interpolate": "1 - 2" 1873 | } 1874 | }, 1875 | "node_modules/d3-selection": { 1876 | "version": "2.0.0", 1877 | "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-2.0.0.tgz", 1878 | "integrity": "sha512-XoGGqhLUN/W14NmaqcO/bb1nqjDAw5WtSYb2X8wiuQWvSZUsUVYsOSkOybUrNvcBjaywBdYPy03eXHMXjk9nZA==", 1879 | "dev": true 1880 | }, 1881 | "node_modules/d3-shape": { 1882 | "version": "2.1.0", 1883 | "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-2.1.0.tgz", 1884 | "integrity": "sha512-PnjUqfM2PpskbSLTJvAzp2Wv4CZsnAgTfcVRTwW03QR3MkXF8Uo7B1y/lWkAsmbKwuecto++4NlsYcvYpXpTHA==", 1885 | "dev": true, 1886 | "dependencies": { 1887 | "d3-path": "1 - 2" 1888 | } 1889 | }, 1890 | "node_modules/d3-time": { 1891 | "version": "2.1.1", 1892 | "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-2.1.1.tgz", 1893 | "integrity": "sha512-/eIQe/eR4kCQwq7yxi7z4c6qEXf2IYGcjoWB5OOQy4Tq9Uv39/947qlDcN2TLkiTzQWzvnsuYPB9TrWaNfipKQ==", 1894 | "dev": true, 1895 | "dependencies": { 1896 | "d3-array": "2" 1897 | } 1898 | }, 1899 | "node_modules/d3-time-format": { 1900 | "version": "3.0.0", 1901 | "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-3.0.0.tgz", 1902 | "integrity": "sha512-UXJh6EKsHBTjopVqZBhFysQcoXSv/5yLONZvkQ5Kk3qbwiUYkdX17Xa1PT6U1ZWXGGfB1ey5L8dKMlFq2DO0Ag==", 1903 | "dev": true, 1904 | "dependencies": { 1905 | "d3-time": "1 - 2" 1906 | } 1907 | }, 1908 | "node_modules/d3-timer": { 1909 | "version": "2.0.0", 1910 | "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-2.0.0.tgz", 1911 | "integrity": "sha512-TO4VLh0/420Y/9dO3+f9abDEFYeCUr2WZRlxJvbp4HPTQcSylXNiL6yZa9FIUvV1yRiFufl1bszTCLDqv9PWNA==", 1912 | "dev": true 1913 | }, 1914 | "node_modules/d3-transition": { 1915 | "version": "2.0.0", 1916 | "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-2.0.0.tgz", 1917 | "integrity": "sha512-42ltAGgJesfQE3u9LuuBHNbGrI/AJjNL2OAUdclE70UE6Vy239GCBEYD38uBPoLeNsOhFStGpPI0BAOV+HMxog==", 1918 | "dev": true, 1919 | "dependencies": { 1920 | "d3-color": "1 - 2", 1921 | "d3-dispatch": "1 - 2", 1922 | "d3-ease": "1 - 2", 1923 | "d3-interpolate": "1 - 2", 1924 | "d3-timer": "1 - 2" 1925 | }, 1926 | "peerDependencies": { 1927 | "d3-selection": "2" 1928 | } 1929 | }, 1930 | "node_modules/d3-wave": { 1931 | "version": "1.1.5", 1932 | "resolved": "https://registry.npmjs.org/d3-wave/-/d3-wave-1.1.5.tgz", 1933 | "integrity": "sha512-F89EXvF9AWikScz5liFW/q30y4b6NOcL0rUYuXij1Cacx7aclIML5FMZFiH3Oan05quExPsNvABzVdX7mThggw==", 1934 | "dev": true, 1935 | "dependencies": { 1936 | "@fortawesome/free-solid-svg-icons": "^5.15.0", 1937 | "d3": "^6.5.0" 1938 | } 1939 | }, 1940 | "node_modules/d3-zoom": { 1941 | "version": "2.0.0", 1942 | "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-2.0.0.tgz", 1943 | "integrity": "sha512-fFg7aoaEm9/jf+qfstak0IYpnesZLiMX6GZvXtUSdv8RH2o4E2qeelgdU09eKS6wGuiGMfcnMI0nTIqWzRHGpw==", 1944 | "dev": true, 1945 | "dependencies": { 1946 | "d3-dispatch": "1 - 2", 1947 | "d3-drag": "2", 1948 | "d3-interpolate": "1 - 2", 1949 | "d3-selection": "2", 1950 | "d3-transition": "2" 1951 | } 1952 | }, 1953 | "node_modules/debug": { 1954 | "version": "4.3.6", 1955 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", 1956 | "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", 1957 | "dev": true, 1958 | "dependencies": { 1959 | "ms": "2.1.2" 1960 | }, 1961 | "engines": { 1962 | "node": ">=6.0" 1963 | }, 1964 | "peerDependenciesMeta": { 1965 | "supports-color": { 1966 | "optional": true 1967 | } 1968 | } 1969 | }, 1970 | "node_modules/delaunator": { 1971 | "version": "4.0.1", 1972 | "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-4.0.1.tgz", 1973 | "integrity": "sha512-WNPWi1IRKZfCt/qIDMfERkDp93+iZEmOxN2yy4Jg+Xhv8SLk2UTqqbe1sfiipn0and9QrE914/ihdx82Y/Giag==", 1974 | "dev": true 1975 | }, 1976 | "node_modules/detect-libc": { 1977 | "version": "1.0.3", 1978 | "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", 1979 | "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", 1980 | "dev": true, 1981 | "bin": { 1982 | "detect-libc": "bin/detect-libc.js" 1983 | }, 1984 | "engines": { 1985 | "node": ">=0.10" 1986 | } 1987 | }, 1988 | "node_modules/dom-helpers": { 1989 | "version": "5.2.1", 1990 | "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", 1991 | "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", 1992 | "dev": true, 1993 | "peer": true, 1994 | "dependencies": { 1995 | "@babel/runtime": "^7.8.7", 1996 | "csstype": "^3.0.2" 1997 | } 1998 | }, 1999 | "node_modules/error-ex": { 2000 | "version": "1.3.2", 2001 | "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", 2002 | "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", 2003 | "dev": true, 2004 | "dependencies": { 2005 | "is-arrayish": "^0.2.1" 2006 | } 2007 | }, 2008 | "node_modules/esbuild": { 2009 | "version": "0.25.4", 2010 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.4.tgz", 2011 | "integrity": "sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q==", 2012 | "dev": true, 2013 | "hasInstallScript": true, 2014 | "bin": { 2015 | "esbuild": "bin/esbuild" 2016 | }, 2017 | "engines": { 2018 | "node": ">=18" 2019 | }, 2020 | "optionalDependencies": { 2021 | "@esbuild/aix-ppc64": "0.25.4", 2022 | "@esbuild/android-arm": "0.25.4", 2023 | "@esbuild/android-arm64": "0.25.4", 2024 | "@esbuild/android-x64": "0.25.4", 2025 | "@esbuild/darwin-arm64": "0.25.4", 2026 | "@esbuild/darwin-x64": "0.25.4", 2027 | "@esbuild/freebsd-arm64": "0.25.4", 2028 | "@esbuild/freebsd-x64": "0.25.4", 2029 | "@esbuild/linux-arm": "0.25.4", 2030 | "@esbuild/linux-arm64": "0.25.4", 2031 | "@esbuild/linux-ia32": "0.25.4", 2032 | "@esbuild/linux-loong64": "0.25.4", 2033 | "@esbuild/linux-mips64el": "0.25.4", 2034 | "@esbuild/linux-ppc64": "0.25.4", 2035 | "@esbuild/linux-riscv64": "0.25.4", 2036 | "@esbuild/linux-s390x": "0.25.4", 2037 | "@esbuild/linux-x64": "0.25.4", 2038 | "@esbuild/netbsd-arm64": "0.25.4", 2039 | "@esbuild/netbsd-x64": "0.25.4", 2040 | "@esbuild/openbsd-arm64": "0.25.4", 2041 | "@esbuild/openbsd-x64": "0.25.4", 2042 | "@esbuild/sunos-x64": "0.25.4", 2043 | "@esbuild/win32-arm64": "0.25.4", 2044 | "@esbuild/win32-ia32": "0.25.4", 2045 | "@esbuild/win32-x64": "0.25.4" 2046 | } 2047 | }, 2048 | "node_modules/escape-string-regexp": { 2049 | "version": "4.0.0", 2050 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", 2051 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", 2052 | "dev": true, 2053 | "engines": { 2054 | "node": ">=10" 2055 | }, 2056 | "funding": { 2057 | "url": "https://github.com/sponsors/sindresorhus" 2058 | } 2059 | }, 2060 | "node_modules/find-root": { 2061 | "version": "1.1.0", 2062 | "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", 2063 | "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", 2064 | "dev": true 2065 | }, 2066 | "node_modules/function-bind": { 2067 | "version": "1.1.2", 2068 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", 2069 | "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", 2070 | "dev": true, 2071 | "funding": { 2072 | "url": "https://github.com/sponsors/ljharb" 2073 | } 2074 | }, 2075 | "node_modules/globals": { 2076 | "version": "11.12.0", 2077 | "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", 2078 | "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", 2079 | "dev": true, 2080 | "engines": { 2081 | "node": ">=4" 2082 | } 2083 | }, 2084 | "node_modules/has-flag": { 2085 | "version": "3.0.0", 2086 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 2087 | "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", 2088 | "dev": true, 2089 | "engines": { 2090 | "node": ">=4" 2091 | } 2092 | }, 2093 | "node_modules/hasown": { 2094 | "version": "2.0.2", 2095 | "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", 2096 | "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", 2097 | "dev": true, 2098 | "dependencies": { 2099 | "function-bind": "^1.1.2" 2100 | }, 2101 | "engines": { 2102 | "node": ">= 0.4" 2103 | } 2104 | }, 2105 | "node_modules/hoist-non-react-statics": { 2106 | "version": "3.3.2", 2107 | "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", 2108 | "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", 2109 | "dev": true, 2110 | "dependencies": { 2111 | "react-is": "^16.7.0" 2112 | } 2113 | }, 2114 | "node_modules/hoist-non-react-statics/node_modules/react-is": { 2115 | "version": "16.13.1", 2116 | "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", 2117 | "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", 2118 | "dev": true 2119 | }, 2120 | "node_modules/iconv-lite": { 2121 | "version": "0.4.24", 2122 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 2123 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 2124 | "dev": true, 2125 | "dependencies": { 2126 | "safer-buffer": ">= 2.1.2 < 3" 2127 | }, 2128 | "engines": { 2129 | "node": ">=0.10.0" 2130 | } 2131 | }, 2132 | "node_modules/import-fresh": { 2133 | "version": "3.3.0", 2134 | "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", 2135 | "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", 2136 | "dev": true, 2137 | "dependencies": { 2138 | "parent-module": "^1.0.0", 2139 | "resolve-from": "^4.0.0" 2140 | }, 2141 | "engines": { 2142 | "node": ">=6" 2143 | }, 2144 | "funding": { 2145 | "url": "https://github.com/sponsors/sindresorhus" 2146 | } 2147 | }, 2148 | "node_modules/internmap": { 2149 | "version": "1.0.1", 2150 | "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz", 2151 | "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==", 2152 | "dev": true 2153 | }, 2154 | "node_modules/is-arrayish": { 2155 | "version": "0.2.1", 2156 | "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", 2157 | "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", 2158 | "dev": true 2159 | }, 2160 | "node_modules/is-core-module": { 2161 | "version": "2.15.0", 2162 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.0.tgz", 2163 | "integrity": "sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA==", 2164 | "dev": true, 2165 | "dependencies": { 2166 | "hasown": "^2.0.2" 2167 | }, 2168 | "engines": { 2169 | "node": ">= 0.4" 2170 | }, 2171 | "funding": { 2172 | "url": "https://github.com/sponsors/ljharb" 2173 | } 2174 | }, 2175 | "node_modules/js-tokens": { 2176 | "version": "4.0.0", 2177 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", 2178 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", 2179 | "dev": true 2180 | }, 2181 | "node_modules/jsesc": { 2182 | "version": "2.5.2", 2183 | "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", 2184 | "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", 2185 | "dev": true, 2186 | "bin": { 2187 | "jsesc": "bin/jsesc" 2188 | }, 2189 | "engines": { 2190 | "node": ">=4" 2191 | } 2192 | }, 2193 | "node_modules/json-parse-even-better-errors": { 2194 | "version": "2.3.1", 2195 | "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", 2196 | "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", 2197 | "dev": true 2198 | }, 2199 | "node_modules/lines-and-columns": { 2200 | "version": "1.2.4", 2201 | "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", 2202 | "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", 2203 | "dev": true 2204 | }, 2205 | "node_modules/loose-envify": { 2206 | "version": "1.4.0", 2207 | "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", 2208 | "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", 2209 | "dev": true, 2210 | "dependencies": { 2211 | "js-tokens": "^3.0.0 || ^4.0.0" 2212 | }, 2213 | "bin": { 2214 | "loose-envify": "cli.js" 2215 | } 2216 | }, 2217 | "node_modules/mime-db": { 2218 | "version": "1.52.0", 2219 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 2220 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", 2221 | "dev": true, 2222 | "engines": { 2223 | "node": ">= 0.6" 2224 | } 2225 | }, 2226 | "node_modules/mime-types": { 2227 | "version": "2.1.35", 2228 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 2229 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 2230 | "dev": true, 2231 | "dependencies": { 2232 | "mime-db": "1.52.0" 2233 | }, 2234 | "engines": { 2235 | "node": ">= 0.6" 2236 | } 2237 | }, 2238 | "node_modules/monaco-editor": { 2239 | "version": "0.46.0", 2240 | "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.46.0.tgz", 2241 | "integrity": "sha512-ADwtLIIww+9FKybWscd7OCfm9odsFYHImBRI1v9AviGce55QY8raT+9ihH8jX/E/e6QVSGM+pKj4jSUSRmALNQ==", 2242 | "dev": true 2243 | }, 2244 | "node_modules/ms": { 2245 | "version": "2.1.2", 2246 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 2247 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 2248 | "dev": true 2249 | }, 2250 | "node_modules/object-assign": { 2251 | "version": "4.1.1", 2252 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 2253 | "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", 2254 | "dev": true, 2255 | "engines": { 2256 | "node": ">=0.10.0" 2257 | } 2258 | }, 2259 | "node_modules/parent-module": { 2260 | "version": "1.0.1", 2261 | "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", 2262 | "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", 2263 | "dev": true, 2264 | "dependencies": { 2265 | "callsites": "^3.0.0" 2266 | }, 2267 | "engines": { 2268 | "node": ">=6" 2269 | } 2270 | }, 2271 | "node_modules/parse-json": { 2272 | "version": "5.2.0", 2273 | "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", 2274 | "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", 2275 | "dev": true, 2276 | "dependencies": { 2277 | "@babel/code-frame": "^7.0.0", 2278 | "error-ex": "^1.3.1", 2279 | "json-parse-even-better-errors": "^2.3.0", 2280 | "lines-and-columns": "^1.1.6" 2281 | }, 2282 | "engines": { 2283 | "node": ">=8" 2284 | }, 2285 | "funding": { 2286 | "url": "https://github.com/sponsors/sindresorhus" 2287 | } 2288 | }, 2289 | "node_modules/path-parse": { 2290 | "version": "1.0.7", 2291 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", 2292 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", 2293 | "dev": true 2294 | }, 2295 | "node_modules/path-type": { 2296 | "version": "4.0.0", 2297 | "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", 2298 | "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", 2299 | "dev": true, 2300 | "engines": { 2301 | "node": ">=8" 2302 | } 2303 | }, 2304 | "node_modules/picocolors": { 2305 | "version": "1.0.1", 2306 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", 2307 | "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", 2308 | "dev": true 2309 | }, 2310 | "node_modules/prop-types": { 2311 | "version": "15.8.1", 2312 | "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", 2313 | "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", 2314 | "dev": true, 2315 | "dependencies": { 2316 | "loose-envify": "^1.4.0", 2317 | "object-assign": "^4.1.1", 2318 | "react-is": "^16.13.1" 2319 | } 2320 | }, 2321 | "node_modules/prop-types/node_modules/react-is": { 2322 | "version": "16.13.1", 2323 | "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", 2324 | "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", 2325 | "dev": true 2326 | }, 2327 | "node_modules/pyodide": { 2328 | "version": "0.25.1", 2329 | "resolved": "https://registry.npmjs.org/pyodide/-/pyodide-0.25.1.tgz", 2330 | "integrity": "sha512-y0nJ/fLA3bxD2iZRzvVTbP2O+wp4Ewm2wThfV4HF0BytQ6hsoqTJFLNY4usLOcCVBrK8TTWqFqrmsVPzHe4rsw==", 2331 | "dev": true, 2332 | "dependencies": { 2333 | "base-64": "^1.0.0", 2334 | "ws": "^8.5.0" 2335 | } 2336 | }, 2337 | "node_modules/react": { 2338 | "version": "18.3.1", 2339 | "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", 2340 | "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", 2341 | "dev": true, 2342 | "dependencies": { 2343 | "loose-envify": "^1.1.0" 2344 | }, 2345 | "engines": { 2346 | "node": ">=0.10.0" 2347 | } 2348 | }, 2349 | "node_modules/react-dom": { 2350 | "version": "18.3.1", 2351 | "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", 2352 | "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", 2353 | "dev": true, 2354 | "dependencies": { 2355 | "loose-envify": "^1.1.0", 2356 | "scheduler": "^0.23.2" 2357 | }, 2358 | "peerDependencies": { 2359 | "react": "^18.3.1" 2360 | } 2361 | }, 2362 | "node_modules/react-is": { 2363 | "version": "18.3.1", 2364 | "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", 2365 | "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", 2366 | "dev": true 2367 | }, 2368 | "node_modules/react-transition-group": { 2369 | "version": "4.4.5", 2370 | "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", 2371 | "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", 2372 | "dev": true, 2373 | "peer": true, 2374 | "dependencies": { 2375 | "@babel/runtime": "^7.5.5", 2376 | "dom-helpers": "^5.0.1", 2377 | "loose-envify": "^1.4.0", 2378 | "prop-types": "^15.6.2" 2379 | }, 2380 | "peerDependencies": { 2381 | "react": ">=16.6.0", 2382 | "react-dom": ">=16.6.0" 2383 | } 2384 | }, 2385 | "node_modules/regenerator-runtime": { 2386 | "version": "0.14.1", 2387 | "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", 2388 | "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", 2389 | "dev": true 2390 | }, 2391 | "node_modules/resolve": { 2392 | "version": "1.22.8", 2393 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", 2394 | "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", 2395 | "dev": true, 2396 | "dependencies": { 2397 | "is-core-module": "^2.13.0", 2398 | "path-parse": "^1.0.7", 2399 | "supports-preserve-symlinks-flag": "^1.0.0" 2400 | }, 2401 | "bin": { 2402 | "resolve": "bin/resolve" 2403 | }, 2404 | "funding": { 2405 | "url": "https://github.com/sponsors/ljharb" 2406 | } 2407 | }, 2408 | "node_modules/resolve-from": { 2409 | "version": "4.0.0", 2410 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", 2411 | "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", 2412 | "dev": true, 2413 | "engines": { 2414 | "node": ">=4" 2415 | } 2416 | }, 2417 | "node_modules/rw": { 2418 | "version": "1.3.3", 2419 | "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", 2420 | "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==", 2421 | "dev": true 2422 | }, 2423 | "node_modules/safer-buffer": { 2424 | "version": "2.1.2", 2425 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 2426 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", 2427 | "dev": true 2428 | }, 2429 | "node_modules/scheduler": { 2430 | "version": "0.23.2", 2431 | "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", 2432 | "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", 2433 | "dev": true, 2434 | "dependencies": { 2435 | "loose-envify": "^1.1.0" 2436 | } 2437 | }, 2438 | "node_modules/source-map": { 2439 | "version": "0.5.7", 2440 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", 2441 | "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", 2442 | "dev": true, 2443 | "engines": { 2444 | "node": ">=0.10.0" 2445 | } 2446 | }, 2447 | "node_modules/stylis": { 2448 | "version": "4.2.0", 2449 | "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", 2450 | "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==", 2451 | "dev": true 2452 | }, 2453 | "node_modules/supports-color": { 2454 | "version": "5.5.0", 2455 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 2456 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 2457 | "dev": true, 2458 | "dependencies": { 2459 | "has-flag": "^3.0.0" 2460 | }, 2461 | "engines": { 2462 | "node": ">=4" 2463 | } 2464 | }, 2465 | "node_modules/supports-preserve-symlinks-flag": { 2466 | "version": "1.0.0", 2467 | "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", 2468 | "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", 2469 | "dev": true, 2470 | "engines": { 2471 | "node": ">= 0.4" 2472 | }, 2473 | "funding": { 2474 | "url": "https://github.com/sponsors/ljharb" 2475 | } 2476 | }, 2477 | "node_modules/to-fast-properties": { 2478 | "version": "2.0.0", 2479 | "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", 2480 | "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", 2481 | "dev": true, 2482 | "engines": { 2483 | "node": ">=4" 2484 | } 2485 | }, 2486 | "node_modules/ws": { 2487 | "version": "8.18.0", 2488 | "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", 2489 | "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", 2490 | "dev": true, 2491 | "engines": { 2492 | "node": ">=10.0.0" 2493 | }, 2494 | "peerDependencies": { 2495 | "bufferutil": "^4.0.1", 2496 | "utf-8-validate": ">=5.0.2" 2497 | }, 2498 | "peerDependenciesMeta": { 2499 | "bufferutil": { 2500 | "optional": true 2501 | }, 2502 | "utf-8-validate": { 2503 | "optional": true 2504 | } 2505 | } 2506 | }, 2507 | "node_modules/yaml": { 2508 | "version": "1.10.2", 2509 | "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", 2510 | "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", 2511 | "dev": true, 2512 | "engines": { 2513 | "node": ">= 6" 2514 | } 2515 | } 2516 | } 2517 | } 2518 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "amaranth-playground", 3 | "version": "0.0.0", 4 | "description": "Playground for experimenting with and sharing short Amaranth programs on the web", 5 | "author": "Catherine ", 6 | "license": "BSD-2-Clause", 7 | "homepage": "https://github.com/amaranth-lang/playground#readme", 8 | "repository": { 9 | "type": "git", 10 | "url": "git+https://github.com/amaranth-lang/playground.git" 11 | }, 12 | "bugs": { 13 | "url": "https://github.com/amaranth-lang/playground/issues" 14 | }, 15 | "scripts": { 16 | "build": "node build.mjs build", 17 | "minify": "node build.mjs minify", 18 | "watch": "node build.mjs watch", 19 | "serve": "node build.mjs serve" 20 | }, 21 | "devDependencies": { 22 | "@chialab/esbuild-plugin-meta-url": "^0.18.0", 23 | "@emotion/react": "^11.11.3", 24 | "@emotion/styled": "^11.11.0", 25 | "@fontsource/inter": "^5.0.16", 26 | "@mui/icons-material": "^5.15.10", 27 | "@mui/joy": "^5.0.0-beta.28", 28 | "@types/d3": "^7.4.3", 29 | "@types/react": "^18.2.55", 30 | "@types/react-dom": "^18.2.19", 31 | "@yowasp/yosys": "release", 32 | "d3-wave": "^1.1.5", 33 | "esbuild": "^0.25.0", 34 | "monaco-editor": "^0.46.0", 35 | "pyodide": "^0.25.0", 36 | "react": "^18.0.0", 37 | "react-dom": "^18.0.0" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/app.css: -------------------------------------------------------------------------------- 1 | .MuiTabs-root { 2 | overflow: hidden; 3 | } 4 | 5 | .MuiTabPanel-root { 6 | overflow-y: auto; 7 | } 8 | 9 | code { 10 | border: 1px solid gray; 11 | border-radius: 3px; 12 | padding: 0px 2px; 13 | } 14 | 15 | .terminal-output { 16 | white-space: pre-wrap; 17 | font-family: monospace; 18 | } 19 | /* .terminal-stdout {} */ 20 | .terminal-stderr { color: red; } 21 | -------------------------------------------------------------------------------- /src/app.tsx: -------------------------------------------------------------------------------- 1 | import { createRoot } from 'react-dom/client'; 2 | 3 | import * as React from 'react'; 4 | import { useState, useEffect, useRef } from 'react'; 5 | 6 | import { CssVarsProvider, useColorScheme } from '@mui/joy/styles'; 7 | import CssBaseline from '@mui/joy/CssBaseline'; 8 | import '@fontsource/inter/latin-400'; 9 | 10 | import Box from '@mui/joy/Box'; 11 | import Button from '@mui/joy/Button'; 12 | import IconButton from '@mui/joy/IconButton'; 13 | import Select from '@mui/joy/Select'; 14 | import Option from '@mui/joy/Option'; 15 | import Link from '@mui/joy/Link'; 16 | import Snackbar from '@mui/joy/Snackbar'; 17 | import Alert from '@mui/joy/Alert'; 18 | import Tabs from '@mui/joy/Tabs'; 19 | import TabList from '@mui/joy/TabList'; 20 | import Tab from '@mui/joy/Tab'; 21 | import TabPanel from '@mui/joy/TabPanel'; 22 | 23 | import PlayArrowIcon from '@mui/icons-material/PlayArrow'; 24 | import ShareIcon from '@mui/icons-material/Share'; 25 | import DarkModeIcon from '@mui/icons-material/DarkMode'; 26 | import LightModeIcon from '@mui/icons-material/LightMode'; 27 | import QuestionMarkIcon from '@mui/icons-material/QuestionMark' 28 | 29 | import * as monaco from 'monaco-editor'; 30 | import { EditorState, Editor } from './monaco'; 31 | import { Viewer as WaveformViewer } from './d3wave'; 32 | import { PythonError, runner } from './runner'; 33 | import data from './config'; 34 | 35 | import './app.css'; 36 | 37 | function stealHashQuery() { 38 | const { hash } = window.location; 39 | if (hash !== '') { 40 | history.replaceState(null, '', ' '); // remove #... from URL entirely 41 | const hashQuery = hash.substring(1); 42 | try { 43 | return JSON.parse(atob(hashQuery)); 44 | } catch { 45 | try { 46 | // Legacy encoding, used 2024-02-16 to 2024-02-24. 47 | return JSON.parse(decodeURIComponent(hashQuery.replace('+', '%20'))); 48 | } catch {} 49 | } 50 | } 51 | } 52 | 53 | interface TerminalChunk { 54 | stream: 'stdout' | 'stderr'; 55 | text: string; 56 | } 57 | 58 | function TerminalOutput(key: string, output: TerminalChunk[]) { 59 | return output.map((chunk, index) => 60 | {chunk.text}); 61 | } 62 | 63 | function AppContent() { 64 | const {mode, setMode} = useColorScheme(); 65 | useEffect(() => monaco.editor.setTheme(mode === 'light' ? 'vs' : 'vs-dark'), [mode]); 66 | 67 | const query: { av?: string, s?: string } | undefined = stealHashQuery(); 68 | const [amaranthVersion, setAmaranthVersion] = useState( 69 | query?.av 70 | ?? localStorage.getItem('amaranth-playground.amaranthVersion') 71 | ?? data.amaranthVersions[0]); 72 | useEffect(() => localStorage.setItem('amaranth-playground.amaranthVersion', amaranthVersion), [amaranthVersion]); 73 | const [running, setRunning] = useState(false); 74 | const [sharingOpen, setSharingOpen] = useState(false); 75 | const [tutorialDone, setTutorialDone] = useState(localStorage.getItem('amaranth-playground.tutorialDone') !== null); 76 | useEffect(() => tutorialDone ? localStorage.setItem('amaranth-playground.tutorialDone', '') : void 0, [tutorialDone]); 77 | const [activeTab, setActiveTab] = useState(tutorialDone ? 'amaranth-source' : 'tutorial'); 78 | const [amaranthSource, setAmaranthSource] = useState( 79 | query?.s 80 | ?? localStorage.getItem('amaranth-playground.source') 81 | ?? data.demoCode[amaranthVersion]); 82 | useEffect(() => localStorage.setItem('amaranth-playground.source', amaranthSource), [amaranthSource]); 83 | const [pythonOutput, setPythonOutput] = useState(null); 84 | const [pythonOutputWasNull, setPythonOutputWasNull] = useState(true); 85 | const [waveforms, setWaveforms] = useState(null); 86 | const [outputOutOfDate, setOutputOutOfDate] = useState(false); 87 | const [productsOutOfDate, setProductsOutOfDate] = useState(false); 88 | const [rtlilProduct, setRtlilProduct] = useState(null); 89 | const [verilogProduct, setVerilogProduct] = useState(null); 90 | 91 | const amaranthSourceEditorState = useRef(new EditorState(amaranthSource, setAmaranthSource, 'python')); 92 | const rtlilProductEditorState = useRef(new EditorState(rtlilProduct, null, 'rtlil')); 93 | useEffect(() => { rtlilProductEditorState.current.text = rtlilProduct ?? ''; }, [rtlilProduct]); 94 | const verilogProductEditorState = useRef(new EditorState(verilogProduct, null, 'verilog')); 95 | useEffect(() => { verilogProductEditorState.current.text = verilogProduct ?? ''; }, [verilogProduct]); 96 | 97 | function loadDemoCode() { 98 | amaranthSourceEditorState.current.text = data.demoCode[amaranthVersion]; 99 | setActiveTab('amaranth-source'); 100 | } 101 | 102 | function setAmaranthVersionAndUpdateDemoCode(newAmaranthVersion: string) { 103 | const wasDemoCode = (amaranthSourceEditorState.current.text == data.demoCode[amaranthVersion]); 104 | setAmaranthVersion(newAmaranthVersion); 105 | if (wasDemoCode) 106 | amaranthSourceEditorState.current.text = data.demoCode[newAmaranthVersion]; 107 | } 108 | 109 | function completeTutorial() { 110 | setTutorialDone(true); 111 | setActiveTab('amaranth-source'); 112 | } 113 | 114 | const runCode = React.useCallback(async () => { 115 | if (running) 116 | return; 117 | try { 118 | setRunning(true); 119 | if (pythonOutput !== null) 120 | setPythonOutput([]); 121 | let gotRtlil = false; 122 | let gotVerilog = false; 123 | let gotWaveforms = false; 124 | await runner.runPython(amaranthSource, { 125 | packages: data.pythonPackages[amaranthVersion], 126 | onStdout: (text) => 127 | setPythonOutput(output => (output ?? []).concat([{stream: 'stdout', text }])), 128 | onStderr: (text) => 129 | setPythonOutput(output => (output ?? []).concat([{stream: 'stderr', text }])), 130 | onShowRtlil: (code) => { gotRtlil = true; setRtlilProduct(code); }, 131 | onShowVerilog: (code) => { gotVerilog = true; setVerilogProduct(code); }, 132 | onShowWaveforms: (data) => { gotWaveforms = true; setWaveforms(data); } 133 | }); 134 | if (rtlilProduct && !gotRtlil) { 135 | setRtlilProduct(null); 136 | setActiveTab(activeTab === 'rtlil-product' ? 'amaranth-source' : activeTab); 137 | } 138 | if (verilogProduct && !gotVerilog) { 139 | setVerilogProduct(null); 140 | setActiveTab(activeTab === 'verilog-product' ? 'amaranth-source' : activeTab); 141 | } 142 | if (waveforms && !gotWaveforms) { 143 | setWaveforms(null); 144 | setActiveTab(activeTab === 'waveforms-product' ? 'amaranth-source' : activeTab); 145 | } 146 | setProductsOutOfDate(false); 147 | } catch (e) { 148 | if (e instanceof PythonError) { 149 | setPythonOutput(output => (output ?? []).concat([{stream: 'stderr', text: e.message}])); 150 | setActiveTab('python-output'); 151 | } else { 152 | throw e; 153 | } 154 | } finally { 155 | setRunning(false); 156 | setOutputOutOfDate(false); 157 | } 158 | }, [amaranthSource, amaranthVersion]); 159 | 160 | function tabAndPanel({ key, title, titleStyle = {}, content }) { 161 | return [ 162 | {title}, 163 | {content} 164 | ]; 165 | } 166 | 167 | const tabsWithPanels = [ 168 | tabAndPanel({ 169 | key: 'tutorial', 170 | title: , 171 | content: 172 |

173 | Hi there! 174 |

175 |

176 | On this page, you can experiment with 177 | the Amaranth hardware definition language: 178 | run a small program, watch its output, see the waveforms a simulation generates, look 179 | at the RTL the compiler produces, and share it with friends, if you like! 180 |

181 |

182 | To switch between views, use the tab bar right above this text. The tab with 183 | the "" icon shows this tutorial. When you open this 184 | page, the only other visible tab will be "Amaranth Source", containing a demonstration 185 | program. Go ahead and open it! Then switch back to the tutorial by clicking {} 186 | . 187 | (If the demonstration program doesn't appear, or if you edited it and now 188 | want to go back, you can reload it.) 189 |

190 |

191 | The code you enter in the "Amaranth Source" tab is ordinary Python code that runs in 192 | an environment where the Amaranth Python package and its dependencies are already 193 | installed. You can write import amaranth and start experimenting without any 194 | distractions. Once you're done, click the " Run" button 195 | in the top left, or press Ctrl+Enter while the editor is focused. 196 | Go ahead and try! 197 |

198 |

199 | You will see several new tabs appear: 200 |

201 |
    202 |
  • 203 | The "Python Output" tab contains the text from the standard output and standard error 204 | streams of the Python interpreter. If you run the print() function, 205 | this tab will contain the output. Any exceptions raised by the Python code will also 206 | be shown here. 207 |
  • 208 |
  • 209 | The "Waveforms" tab visualizes how the values of signals change during the simulation. 210 | It appears only if the code includes 211 | a with amaranth_playground.show_waveforms(sim): statement. When you open 212 | the tab, the waveform viewer will display an overview of the entire simulation. 213 | You can scroll the mouse wheel to zoom, and drag the area with the waveforms with 214 | the left mouse button to move the viewport. 215 |
  • 216 |
  • 217 | The "Generated Verilog" tab shows the output of the Amaranth compiler. It appears 218 | only if the code includes a amaranth_playground.show_verilog(...) {} 219 | statement. 220 |
  • 221 |
222 |

223 | The contents of these tabs isn't automatically updated: you need to click 224 | the " Run" button every time you modify the code to see 225 | how the changes in it affect the results. 226 | Try changing something and clicking " Run" now! 227 |

228 |

229 | The code you write in the "Amaranth Source" tab is automatically saved when you change it, 230 | so if you leave this page and come back to it later, it should be exactly as you left it. 231 | However, don't rely on it to save your important code: only one copy of the code is saved, 232 | so if you open this page in several browser tabs or windows, all but one programs will be 233 | lost. 234 |

235 |

236 | If you click the " Share" button in the top right corner of 237 | this page, a popup with a link will appear right there. This link contains a copy of 238 | the source code you entered (and the Amaranth version you're using). You can bookmark it, 239 | or send it to someone else. When you click on the link, the code you're currently editing 240 | will be erased and replaced with the code contained in the link. 241 |

242 |

243 | The button with the "{mode === 'light' 244 | ? 245 | : }" icon in the top right corner switches the color 246 | theme to use a {mode === 'light' ? 'dark' : 'light'} background instead. 247 | For now, the waveform viewer always uses a dark background. 248 |

249 |

250 | Have fun! You can now mark the tutorial as complete {} 251 | and start experimenting, or continue reading if you want to know more details. If you want 252 | to see your design run on a real development board, try the YoWASP Toolchain extension for Visual Studio Code; it provides an end-to-end FPGA 255 | toolchain for the popular iCE40 and ECP5 FPGA families entirely in the browser. {} 256 | {'usb' in navigator ? <> : <>(Your browser does not support WebUSB, so you will need 257 | to use a different browser or install a flashing utility separately.)} 258 |

259 |

260 | The only functionality available in this playground that isn't a part of the Amaranth 261 | Python package or its dependencies is the amaranth_playground Python module. 262 | This built-in module provides three functions that are used to display the results of 263 | running a program in a separate tab and in the suitable format: 264 |

265 |
    266 |
  • 267 | with amaranth_playground.show_waveforms(sim): displays waveforms by 268 | calling with sim.write_vcd(vcd_file=...) internally and then converting 269 | the VCD data to a format suitable for the interactive viewer. 270 |
  • 271 |
  • 272 | amaranth_playground.show_verilog(verilog.convert(m)) displays Verilog 273 | code. This code is accepted by all FPGA and ASIC toolchains, and can be used to run 274 | Amaranth on essentially any hardware platform or RTL simulator. 275 |
  • 276 |
  • 277 | amaranth_playground.show_rtlil(rtlil.convert(m)) displays RTLIL code, the Yosys intermediate 280 | representation. This code is accepted by the open-source FPGA toolchain, and is used 281 | internally by the Amaranth compiler to produce Verilog code. Unless you are investigating 282 | a problem with the Amaranth compiler itself, the only reason to look at it is curiosity. 283 | (Which is a very good reason; try uncommenting the line with show_rtlil {} 284 | in the demonstration program and comparing the Verilog and RTLIL code side-by-side!) 285 |
  • 286 |
287 |

288 | The demonstration program includes examples of using all three functions. (Remember, 289 | you can always reload it if you changed the source.) 290 |

291 |

292 | — Catherine "whitequark" 293 |

294 |

295 | P.S.: Everything you see on this page works within your browser, and the code you enter is 296 | never sent over the network. Yes, I run Python, Amaranth, and Yosys in the browser using {} 297 | WebAssembly. How cool is that? 298 |

299 |

300 | The source code of the playground itself is {} 301 | available on GitHub. 302 |

303 |
304 | }), 305 | tabAndPanel({ 306 | key: 'amaranth-source', 307 | title: 'Amaranth Source', 308 | content: 323 | }) 324 | ]; 325 | 326 | const prevAmaranthSource = useRef(amaranthSource); 327 | useEffect(() => { 328 | if (amaranthSource != prevAmaranthSource.current) { 329 | setOutputOutOfDate(true); 330 | setProductsOutOfDate(true); 331 | } 332 | prevAmaranthSource.current = amaranthSource; 333 | }, [amaranthSource]); 334 | 335 | if (pythonOutput !== null) 336 | tabsWithPanels.push(tabAndPanel({ 337 | key: 'python-output', 338 | title: 'Python Output', 339 | titleStyle: outputOutOfDate ? { textDecoration: 'line-through' } : {}, 340 | content: 341 | 342 | {outputOutOfDate && 343 | The Python output is out of date. Run the program again to refresh it. 344 | } 345 | {TerminalOutput('python-output', pythonOutput)} 349 | 350 | })); 351 | 352 | useEffect(() => { 353 | // Open tab if we're running code for the first time, since it may not be clear that anything 354 | // has happened otherwise. 355 | if (pythonOutput !== null && pythonOutputWasNull) 356 | setActiveTab('python-output'); 357 | setPythonOutputWasNull(pythonOutput === null); 358 | }, [pythonOutput]); 359 | 360 | if (waveforms !== null) 361 | tabsWithPanels.push(tabAndPanel({ 362 | key: 'waveforms', 363 | title: 'Waveforms', 364 | titleStyle: productsOutOfDate ? { textDecoration: 'line-through' } : {}, 365 | content: 366 | 367 | {productsOutOfDate && 368 | The waveforms are out of date. Run the program again to refresh them. 369 | } 370 | 371 | 372 | 373 | 374 | })); 375 | 376 | if (rtlilProduct !== null) 377 | tabsWithPanels.push(tabAndPanel({ 378 | key: 'rtlil-product', 379 | title: 'Generated RTLIL', 380 | titleStyle: productsOutOfDate ? { textDecoration: 'line-through' } : {}, 381 | content: 382 | 383 | {productsOutOfDate && 384 | The generated RTLIL is out of date. Run the program again to refresh it. 385 | } 386 | 387 | 392 | 393 | 394 | })); 395 | 396 | if (verilogProduct !== null) 397 | tabsWithPanels.push(tabAndPanel({ 398 | key: 'verilog-product', 399 | title: 'Generated Verilog', 400 | titleStyle: productsOutOfDate ? { textDecoration: 'line-through' } : {}, 401 | content: 402 | 403 | {productsOutOfDate && 404 | The generated Verilog is out of date. Run the program again to refresh it. 405 | } 406 | 407 | 412 | 413 | 414 | })); 415 | 416 | // FIXME: populating `tabsWithPanels` this way leads to bugs 417 | 418 | return <> 419 | 427 | 432 | 433 | 443 | 444 | 454 | 455 | 459 | Open documentation 460 | 461 | 462 | {/* spacer */} 463 | 464 | 474 | 475 | setSharingOpen(false)} 479 | > 480 | 486 | Copy this link to share the source code 487 | 488 | 489 | 490 | setMode(mode === 'light' ? 'dark' : 'light')} 495 | > 496 | {mode === 'light' ? : } 497 | 498 | 499 | 500 | setActiveTab(value as string)} 504 | > 505 | {tabsWithPanels.map(([tab, _panel]) => tab)} 506 | {tabsWithPanels.map(([_tab, panel]) => panel)} 507 | 508 | 509 | ; 510 | } 511 | 512 | createRoot(document.getElementById('root')!).render( 513 | 514 | 515 | 516 | 517 | ); 518 | 519 | console.log('Build ID:', globalThis.GIT_COMMIT); 520 | 521 | // https://esbuild.github.io/api/#live-reload 522 | if (!globalThis.IS_PRODUCTION) 523 | new EventSource('/esbuild').addEventListener('change', () => location.reload()); 524 | -------------------------------------------------------------------------------- /src/config.ts: -------------------------------------------------------------------------------- 1 | const rfc3986_2_0_0 = 'https://files.pythonhosted.org/packages/ff/9a/9afaade874b2fa6c752c36f1548f718b5b83af81ed9b76628329dab81c1b/rfc3986-2.0.0-py2.py3-none-any.whl'; 2 | const jschon_0_11_1 = 'https://files.pythonhosted.org/packages/ce/b1/31f454a2ac0d23b0a47283d115f0af4abe2a1ea391f5ccb223e02d685b82/jschon-0.11.1-py3-none-any.whl'; 3 | const pyvcd_0_4_0 = 'https://files.pythonhosted.org/packages/98/8d/a0d8fb2b9611f3ae22ddc98890b346833fa2c645ad21fd282e61ccdad477/pyvcd-0.4.0-py2.py3-none-any.whl'; 4 | const amaranth_0_4_2 = 'https://files.pythonhosted.org/packages/27/1c/39881fbd48f9de91d64955f206a7f32fd912d306d18e8c5f74126ee5962f/amaranth-0.4.2-py3-none-any.whl'; 5 | const amaranth_0_4_3 = 'https://files.pythonhosted.org/packages/72/34/82f76a59f4155e26f42cf9f9d04d80befe774aa8af6d9b6e48d3e7b9f060/amaranth-0.4.3-py3-none-any.whl'; 6 | const amaranth_0_4_4 = 'https://files.pythonhosted.org/packages/ee/66/bbb766873059d8051ddb7e760de80beefd286979bc9a786e7ec4ac524336/amaranth-0.4.4-py3-none-any.whl'; 7 | const amaranth_0_4_5 = 'https://files.pythonhosted.org/packages/1a/bf/cff5c705f2f5978889e1fa0fc2a70e0fadbb9f2a51db2d3315c3bda7c3ea/amaranth-0.4.5-py3-none-any.whl'; 8 | const amaranth_0_5_0 = 'https://files.pythonhosted.org/packages/d3/34/8a21cc1765f1952eb35766cf76ec8a1b3e73f32ae78d9bf1c1a88313bdcd/amaranth-0.5.0-py3-none-any.whl'; 9 | const amaranth_0_5_1 = 'https://files.pythonhosted.org/packages/46/1c/74dc024e77038a273160dd1d70a79371142ba9ebeac4b2fb89c272ce6859/amaranth-0.5.1-py3-none-any.whl'; 10 | const amaranth_0_5_2 = 'https://files.pythonhosted.org/packages/e1/60/f787f05fe9684ce80aeb9fe23238248461ef42783e53712092ad55a97eec/amaranth-0.5.2-py3-none-any.whl'; 11 | const amaranth_0_5_3 = 'https://files.pythonhosted.org/packages/3a/8d/889014b45ecf68727d8c8c1d88d5b858f0b43a42c5b1e51fa2c875ffd4d5/amaranth-0.5.3-py3-none-any.whl'; 12 | const amaranth_0_5_4 = 'https://files.pythonhosted.org/packages/f4/c3/a7124071d8cf2dfc958a13fd6d32efb075ce203d275df8fcbb00cbe82ad7/amaranth-0.5.4-py3-none-any.whl'; 13 | const amaranth_0_5_5 = 'https://files.pythonhosted.org/packages/62/77/79407d18a2130e5bee4a94d19a71c05d36d64d7200ff01c2b024fb0ceda3/amaranth-0.5.5-py3-none-any.whl'; 14 | const pythonPackages = { 15 | 'v0.5.5': [rfc3986_2_0_0, jschon_0_11_1, pyvcd_0_4_0, amaranth_0_5_5], 16 | 'v0.5.4': [rfc3986_2_0_0, jschon_0_11_1, pyvcd_0_4_0, amaranth_0_5_4], 17 | 'v0.5.3': [rfc3986_2_0_0, jschon_0_11_1, pyvcd_0_4_0, amaranth_0_5_3], 18 | 'v0.5.2': [rfc3986_2_0_0, jschon_0_11_1, pyvcd_0_4_0, amaranth_0_5_2], 19 | 'v0.5.1': [rfc3986_2_0_0, jschon_0_11_1, pyvcd_0_4_0, amaranth_0_5_1], 20 | 'v0.5.0': [rfc3986_2_0_0, jschon_0_11_1, pyvcd_0_4_0, amaranth_0_5_0], 21 | 'v0.4.5': [pyvcd_0_4_0, amaranth_0_4_5], 22 | 'v0.4.4': [pyvcd_0_4_0, amaranth_0_4_4], 23 | 'v0.4.3': [pyvcd_0_4_0, amaranth_0_4_3], 24 | 'v0.4.2': [pyvcd_0_4_0, amaranth_0_4_2], 25 | }; 26 | 27 | const demoCode_0_4 = `\ 28 | from amaranth import * 29 | from amaranth.sim import Simulator, Tick 30 | from amaranth.back import rtlil, verilog 31 | import amaranth_playground 32 | 33 | 34 | en = Signal() 35 | count = Signal(4) 36 | m = Module() 37 | with m.If(en): 38 | m.d.sync += count.eq(count + 1) 39 | m.d.comb += en.eq(count < 5) 40 | 41 | 42 | def testbench(): 43 | for _ in range(10): 44 | yield Tick("sync") 45 | print(f"count: {yield count}") 46 | 47 | sim = Simulator(m) 48 | sim.add_clock(1e-6) 49 | sim.add_process(testbench) 50 | with amaranth_playground.show_waveforms(sim): 51 | sim.run() 52 | 53 | amaranth_playground.show_verilog(verilog.convert(m, ports=[count])) 54 | # amaranth_playground.show_rtlil(rtlil.convert(m, ports=[count])) 55 | `; 56 | const demoCode_0_5 = `\ 57 | from amaranth import * 58 | from amaranth.sim import Simulator 59 | from amaranth.back import rtlil, verilog 60 | import amaranth_playground 61 | 62 | 63 | en = Signal() 64 | count = Signal(4) 65 | m = Module() 66 | with m.If(en): 67 | m.d.sync += count.eq(count + 1) 68 | m.d.comb += en.eq(count < 5) 69 | 70 | 71 | async def testbench(ctx): 72 | for _ in range(10): 73 | await ctx.tick() 74 | print(f"count: {ctx.get(count)}") 75 | 76 | sim = Simulator(m) 77 | sim.add_clock(1e-6) 78 | sim.add_testbench(testbench) 79 | with amaranth_playground.show_waveforms(sim): 80 | sim.run() 81 | 82 | amaranth_playground.show_verilog(verilog.convert(m, ports=[count])) 83 | # amaranth_playground.show_rtlil(rtlil.convert(m, ports=[count])) 84 | `; 85 | const demoCode = { 86 | 'v0.5.5': demoCode_0_5, 87 | 'v0.5.4': demoCode_0_5, 88 | 'v0.5.3': demoCode_0_5, 89 | 'v0.5.2': demoCode_0_5, 90 | 'v0.5.1': demoCode_0_5, 91 | 'v0.5.0': demoCode_0_5, 92 | 'v0.4.5': demoCode_0_4, 93 | 'v0.4.4': demoCode_0_4, 94 | 'v0.4.3': demoCode_0_4, 95 | 'v0.4.2': demoCode_0_4, 96 | }; 97 | 98 | export default { 99 | amaranthVersions: Array.from(Object.keys(pythonPackages)), 100 | pythonPackages, 101 | demoCode, 102 | }; 103 | -------------------------------------------------------------------------------- /src/d3wave.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { useRef, useId, useEffect } from 'react'; 3 | import * as d3 from 'd3'; 4 | import { WaveGraph } from 'd3-wave'; 5 | 6 | export interface ViewerProps { 7 | data: object; 8 | } 9 | 10 | export function Viewer(props: ViewerProps) { 11 | const waveGraphRef = useRef(null); 12 | const imageRef = useRef(null); 13 | const imageId = useId(); 14 | 15 | useEffect(() => { 16 | if (waveGraphRef.current === null) 17 | waveGraphRef.current = new WaveGraph(d3.select(`[id="${imageId}"]`)); 18 | waveGraphRef.current.setSizes(); 19 | 20 | const resizeObserver = new ResizeObserver((events) => waveGraphRef.current.setSizes()); 21 | resizeObserver.observe(imageRef.current!); 22 | return () => resizeObserver.disconnect(); 23 | }, []); 24 | 25 | useEffect(() => waveGraphRef.current?.bindData(props.data), [props.data]); 26 | 27 | return ; 28 | } 29 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Play with Amaranth HDL! 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/monaco.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { Dispatch, SetStateAction, useEffect, useRef } from 'react'; 3 | import * as monaco from 'monaco-editor'; 4 | 5 | window.MonacoEnvironment = { 6 | getWorker: (moduleId, label) => 7 | new Worker('editor.worker.js', { type: 'module' }), 8 | }; 9 | 10 | export class EditorState { 11 | readonly model: monaco.editor.IModel; 12 | readonly readOnly: boolean; 13 | viewState: monaco.editor.ICodeEditorViewState | null = null; 14 | 15 | constructor(text: string | null = '', setText: ((text: string) => void) | null = null, language = 'text') { 16 | this.model = monaco.editor.createModel(text || '', language); 17 | this.readOnly = (setText === null); 18 | if (!this.readOnly) 19 | this.model.onDidChangeContent(event => setText!(this.model.getValue())); 20 | } 21 | 22 | get text(): string { 23 | return this.model.getValue(); 24 | } 25 | 26 | set text(text: string) { 27 | if (this.readOnly) 28 | this.model.setValue(text); // don't care about undo buffer, can't undo 29 | else 30 | this.model.pushEditOperations([], [{ range: this.model.getFullModelRange(), text }], () => null); 31 | } 32 | 33 | dispose() { 34 | this.model.dispose(); 35 | } 36 | } 37 | 38 | export interface EditorProps { 39 | state: EditorState, 40 | actions?: monaco.editor.IActionDescriptor[]; 41 | padding?: monaco.editor.IEditorPaddingOptions; 42 | focus?: boolean; 43 | } 44 | 45 | export function Editor({ state, actions = [], padding, focus = false }: EditorProps) { 46 | const editorRef = useRef(null); 47 | const containerRef = useRef(null); 48 | 49 | useEffect(() => { 50 | editorRef.current = monaco.editor.create(containerRef.current!, { 51 | model: state.model, 52 | readOnly: state.readOnly, 53 | padding, 54 | }); 55 | actions.forEach(action => editorRef.current?.addAction(action)); 56 | const resizeObserver = new ResizeObserver(events => editorRef.current?.layout()); 57 | resizeObserver.observe(containerRef.current!); 58 | editorRef.current.restoreViewState(state.viewState); 59 | if (focus) 60 | editorRef.current.focus(); 61 | return () => { 62 | state.viewState = editorRef.current!.saveViewState(); 63 | resizeObserver.disconnect(); 64 | editorRef.current?.dispose(); 65 | }; 66 | }, [actions]); 67 | 68 | return
; 69 | } 70 | -------------------------------------------------------------------------------- /src/proto.ts: -------------------------------------------------------------------------------- 1 | export interface LoadPackagesMessage { 2 | type: 'loadPackages', 3 | pkgs: string[] 4 | } 5 | 6 | export interface RunPythonMessage { 7 | type: 'runPython'; 8 | code: string; 9 | } 10 | 11 | export type HostToWorkerMessage = 12 | | LoadPackagesMessage 13 | | RunPythonMessage; 14 | 15 | export interface StdoutWriteMessage { 16 | type: 'stdoutWrite', 17 | text: string 18 | } 19 | 20 | export interface StderrWriteMessage { 21 | type: 'stderrWrite', 22 | text: string 23 | } 24 | 25 | export interface ShowRtlilMessage { 26 | type: 'showRtlil', 27 | code: string 28 | } 29 | 30 | export interface ShowVerilogMessage { 31 | type: 'showVerilog', 32 | code: string 33 | } 34 | 35 | export interface ShowWaveformsMessage { 36 | type: 'showWaveforms', 37 | data: object 38 | } 39 | 40 | export interface PythonDoneMessage { 41 | type: 'pythonDone'; 42 | error: string | null; 43 | } 44 | 45 | export type WorkerToHostMessage = 46 | | StdoutWriteMessage 47 | | StderrWriteMessage 48 | | ShowRtlilMessage 49 | | ShowVerilogMessage 50 | | ShowWaveformsMessage 51 | | PythonDoneMessage; 52 | -------------------------------------------------------------------------------- /src/pyodide.ts: -------------------------------------------------------------------------------- 1 | // Slightly cursed wrapper to integrate with esbuild. 2 | 3 | import 'pyodide/pyodide.asm.js'; 4 | // @ts-ignore 5 | import pyodideStdLib from 'pyodide/python_stdlib.zip'; 6 | import pyodideLockFile from 'pyodide/pyodide-lock.json'; 7 | import { loadPyodide as originalLoadPyodide } from 'pyodide'; 8 | 9 | export type { PyodideInterface } from 'pyodide'; 10 | export type { PyProxy } from 'pyodide/ffi'; 11 | 12 | export const loadPyodide: typeof originalLoadPyodide = function(options) { 13 | return originalLoadPyodide({ 14 | indexURL: '.', 15 | stdLibURL: pyodideStdLib, 16 | // @ts-ignore 17 | lockFileURL: pyodideLockFile, 18 | ...options 19 | }); 20 | } 21 | -------------------------------------------------------------------------------- /src/runner.ts: -------------------------------------------------------------------------------- 1 | import { WorkerToHostMessage } from './proto'; 2 | 3 | const workerURL = `app.worker.js?hash=${globalThis.GIT_COMMIT.substr(0, 8)}`; 4 | 5 | export class PythonError extends Error {} 6 | 7 | export class ToolRunner { 8 | #worker = new Worker(workerURL, { type: 'module' }); 9 | #packages: null | string[] = null; 10 | 11 | private initializeWorker(packages: string[]): Worker { 12 | if (JSON.stringify(this.#packages) !== JSON.stringify(packages)) { 13 | if (this.#worker !== null && this.#packages !== null) { 14 | // Terminate and re-initialize if the set of packages has changed. 15 | this.#worker.terminate(); 16 | this.#worker = new Worker(workerURL, { type: 'module' }); 17 | } 18 | this.#worker.postMessage({ type: 'loadPackages', pkgs: packages }); 19 | this.#packages = packages; 20 | } 21 | return this.#worker; 22 | } 23 | 24 | preloadPackages(packages: string[]) { 25 | this.initializeWorker(packages); 26 | } 27 | 28 | runPython(code: string, options: { 29 | packages: string[], 30 | onStdout: (text: string) => void, 31 | onStderr: (text: string) => void, 32 | onShowRtlil: (code: string) => void, 33 | onShowVerilog: (code: string) => void, 34 | onShowWaveforms: (data: object) => void, 35 | }): Promise { 36 | console.log('[Host] Running', { packages: options.packages, code }); 37 | const worker = this.initializeWorker(options.packages); 38 | return new Promise((resolve, reject) => { 39 | function onmessage(event: MessageEvent) { 40 | console.log('[Host] Received', event.data); 41 | if (event.data.type === 'stdoutWrite') { 42 | options.onStdout(event.data.text); 43 | } else if (event.data.type === 'stderrWrite') { 44 | options.onStderr(event.data.text); 45 | } else if (event.data.type === 'showRtlil') { 46 | options.onShowRtlil(event.data.code); 47 | } else if (event.data.type === 'showVerilog') { 48 | options.onShowVerilog(event.data.code); 49 | } else if (event.data.type === 'showWaveforms') { 50 | options.onShowWaveforms(event.data.data); 51 | } else if (event.data.type === 'pythonDone') { 52 | worker.removeEventListener('message', onmessage); 53 | worker.removeEventListener('error', onerror); 54 | if (event.data.error === null) 55 | resolve(); 56 | else 57 | reject(new PythonError(event.data.error)); 58 | } else { 59 | reject(new Error(`[Host] Unexpected message ${(event.data as any).type}`)); 60 | } 61 | } 62 | function onerror(event: ErrorEvent) { 63 | console.log('[Host] Failure', event.error); 64 | worker.removeEventListener('message', onmessage); 65 | reject(event.error); 66 | } 67 | worker.addEventListener('message', onmessage); 68 | worker.addEventListener('error', onerror, { once: true }); 69 | worker.postMessage({ type: 'runPython', code }); 70 | }); 71 | } 72 | } 73 | 74 | export let runner = new ToolRunner(); 75 | -------------------------------------------------------------------------------- /src/worker.ts: -------------------------------------------------------------------------------- 1 | import { loadPyodide, PyodideInterface, PyProxy } from './pyodide'; 2 | import { runYosys, Exit as YosysExit } from '@yowasp/yosys'; 3 | 4 | import { HostToWorkerMessage, WorkerToHostMessage } from './proto'; 5 | 6 | function postMessage(data: WorkerToHostMessage, transfer?: Transferable[]) { 7 | console.log('[Worker] Sending', data); 8 | self.postMessage(data, { transfer }); 9 | } 10 | 11 | function runInNewContext(pyodide: PyodideInterface, code: string) { 12 | const dict = pyodide.globals.get('dict'); 13 | const globals = dict(); 14 | try { 15 | return pyodide.runPython(code, { globals, locals: globals }); 16 | } finally { 17 | globals.destroy(); 18 | dict.destroy(); 19 | } 20 | } 21 | 22 | // Start preloading Yosys. 23 | const yosysPromise = (runYosys() as unknown as Promise).then(() => { 24 | console.log('[Worker] Preloaded Yosys'); 25 | }); 26 | 27 | // Start preloading Pyodide. 28 | let pyodidePromise = loadPyodide({ 29 | env: { 30 | HOME: '/', 31 | AMARANTH_USE_YOSYS: 'javascript', 32 | }, 33 | stdout: line => postMessage({ type: 'stdoutWrite', text: `${line}\n` }), 34 | stderr: line => postMessage({ type: 'stderrWrite', text: `${line}\n` }), 35 | jsglobals: { 36 | Object, 37 | fetch: fetch.bind(globalThis), 38 | setTimeout: setTimeout.bind(globalThis), 39 | clearTimeout: clearTimeout.bind(globalThis), 40 | runAmaranthYosys: (args: PyProxy, stdinText: string) => { 41 | let stdin = new TextEncoder().encode(stdinText); 42 | const stdout: string[] = []; 43 | const stderr: string[] = []; 44 | try { 45 | runYosys(args.toJs(), {}, { 46 | stdin: (length) => { 47 | if (stdin.length === 0) 48 | return null; 49 | let chunk = stdin.subarray(0, length); 50 | stdin = stdin.subarray(length); 51 | return chunk; 52 | }, 53 | stdout: data => data ? stdout.push(new TextDecoder().decode(data)) : null, 54 | stderr: data => data ? stderr.push(new TextDecoder().decode(data)) : null, 55 | synchronously: true, 56 | }); 57 | return [0, stdout.join(''), stderr.join('')]; 58 | } catch(e) { 59 | if (e instanceof YosysExit) { 60 | return [e.code, stdout.join(''), stderr.join('')]; 61 | } else { 62 | throw e; 63 | } 64 | } finally { 65 | args.destroy(); 66 | } 67 | } 68 | } 69 | }).then((pyodide) => { 70 | const show_waveforms = runInNewContext(pyodide, `\ 71 | import contextlib 72 | 73 | def vcd_to_d3wave(vcd_file): 74 | from vcd.reader import TokenKind, tokenize 75 | 76 | root = {"name": "design", "type": {"name": "struct"}, "children": []} 77 | scope = [root] 78 | by_id = {} 79 | time = 0 80 | for token in tokenize(open(vcd_file, "rb")): 81 | if token.kind == TokenKind.SCOPE: 82 | new_child = { 83 | "name": token.data.ident, 84 | "type": {"name": "struct"}, 85 | "children": [] 86 | } 87 | scope[-1]["children"].append(new_child) 88 | scope.append(new_child) 89 | elif token.kind == TokenKind.UPSCOPE: 90 | scope.pop() 91 | elif token.kind == TokenKind.VAR: 92 | new_child = { 93 | "name": token.data.reference, 94 | "type": {"name": token.data.type_.value, "width": token.data.size}, 95 | "data": [] 96 | } 97 | scope[-1]["children"].append(new_child) 98 | by_id[token.data.id_code] = new_child 99 | elif token.kind == TokenKind.CHANGE_TIME: 100 | time = token.data 101 | elif token.kind in (TokenKind.CHANGE_SCALAR, TokenKind.CHANGE_VECTOR): 102 | signal = by_id[token.data.id_code] 103 | value = token.data.value 104 | if isinstance(value, int): 105 | value = f"{value:0{signal['type']['width']}d}" 106 | signal["data"].append([time, value]) 107 | 108 | return (root if len(root["children"]) > 1 else root["children"][-1]) 109 | 110 | 111 | @contextlib.contextmanager 112 | def show_waveforms(sim): 113 | import amaranth_playground 114 | 115 | vcd_file = "/tmp/waveforms.vcd" 116 | with sim.write_vcd(vcd_file=vcd_file): 117 | yield 118 | 119 | amaranth_playground._show_waveforms(vcd_to_d3wave(vcd_file=vcd_file)) 120 | 121 | show_waveforms 122 | `); 123 | 124 | pyodide.registerJsModule('amaranth_playground', { 125 | show_rtlil: (code: string) => postMessage({ type: 'showRtlil', code }), 126 | show_verilog: (code: string) => postMessage({ type: 'showVerilog', code }), 127 | _show_waveforms: (data: PyProxy) => postMessage({ 128 | type: 'showWaveforms', 129 | data: data.toJs({ dict_converter: Object.fromEntries }) 130 | }), 131 | show_waveforms, 132 | }); 133 | console.log('[Worker] Pyodide loaded'); 134 | return pyodide; 135 | }); 136 | 137 | self.onmessage = async (event: MessageEvent) => { 138 | console.log('[Worker] Received', event.data); 139 | if (event.data.type === 'loadPackages') { 140 | const pyodide = await pyodidePromise; 141 | // Make sure the following call to `loadPackages` or `runPython` waits until it's done. 142 | pyodidePromise = pyodide.loadPackage(event.data.pkgs).then(() => pyodide); 143 | } else if (event.data.type === 'runPython') { 144 | // Wait until all resources are loaded that the final `runYosys` call becomes synchronous. 145 | await yosysPromise; 146 | const pyodide = await pyodidePromise; 147 | try { 148 | runInNewContext(pyodide, event.data.code); 149 | postMessage({ type: 'pythonDone', error: null }); 150 | } catch (e) { 151 | postMessage({ type: 'pythonDone', error: e.message }); 152 | } 153 | } else { 154 | throw new Error(`[Worker] Unexpected message ${(event.data as any).type}`); 155 | } 156 | } 157 | 158 | self.onerror = (event) => { 159 | console.error('[Worker] Failure', event); 160 | }; 161 | --------------------------------------------------------------------------------