diff --git a/docs/UI_test.md b/docs/UI_test.md index 9be4ecb..eb3a985 100644 --- a/docs/UI_test.md +++ b/docs/UI_test.md @@ -26,3 +26,8 @@ This list grows as test steps are recorded when creating PRs. - [ ] terminal size react to tab size - Config - [ ] terminal font size react to settings + +## Channel test +- [ ] visit http://localhost:5173/ to confirm dev and beta are not visible +- [ ] visit http://localhost:5173/?channel=beta to confirm that beta features are available +- [ ] visit http://localhost:5173/?channel=dev to confirm that dev and beta features are available \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 00fba46..3e5d6e0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,19 +20,26 @@ "gh-pages": "^6.0.0", "json-schema-defaults": "^0.4.0", "markdown-to-jsx": "^7.3.2", + "parse-url": "^9.2.0", "plotly.js": "^2.28.0", "react": "^18.2.0", "react-ace": "^10.1.0", + "react-colorful": "^5.6.1", "react-device-detect": "^2.2.3", "react-dom": "^18.2.0", + "react-draggable": "^4.4.6", "react-helmet": "^6.1.0", + "react-konva": "^18.2.10", "react-markdown": "^9.0.1", "react-new-window": "^1.0.1", "react-plotly.js": "^2.6.0", + "react-resizable": "^3.0.5", + "react-rnd": "^10.4.11", "react-router-dom": "^6.15.0", "react-scrollable-feed": "^1.3.2", "remark-gfm": "^4.0.0", - "tslib": "^2.6.2" + "tslib": "^2.6.2", + "vite": "^5.2.12" }, "devDependencies": { "@types/react": "^18.2.15", @@ -42,9 +49,9 @@ "eslint-plugin-react": "^7.32.2", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.4.3", - "vite": "^4.4.5", "vite-plugin-pwa": "^0.16.4", - "vite-plugin-singlefile": "^0.13.5" + "vite-plugin-singlefile": "^0.13.5", + "vitest": "^1.6.0" } }, "node_modules/@ampproject/remapping": { @@ -1926,14 +1933,28 @@ "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz", "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==" }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", + "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/@esbuild/android-arm": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", - "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz", + "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", "cpu": [ "arm" ], - "dev": true, "optional": true, "os": [ "android" @@ -1943,13 +1964,12 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", - "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", + "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "android" @@ -1959,13 +1979,12 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", - "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", + "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "android" @@ -1975,13 +1994,12 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", - "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", + "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==", "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "darwin" @@ -1991,13 +2009,12 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", - "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", + "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "darwin" @@ -2007,13 +2024,12 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", - "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", + "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "freebsd" @@ -2023,13 +2039,12 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", - "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", + "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "freebsd" @@ -2039,13 +2054,12 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", - "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", + "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", "cpu": [ "arm" ], - "dev": true, "optional": true, "os": [ "linux" @@ -2055,13 +2069,12 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", - "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", + "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -2071,13 +2084,12 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", - "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", + "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", "cpu": [ "ia32" ], - "dev": true, "optional": true, "os": [ "linux" @@ -2087,13 +2099,12 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", - "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", + "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", "cpu": [ "loong64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -2103,13 +2114,12 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", - "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", + "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", "cpu": [ "mips64el" ], - "dev": true, "optional": true, "os": [ "linux" @@ -2119,13 +2129,12 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", - "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", + "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", "cpu": [ "ppc64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -2135,13 +2144,12 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", - "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", + "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", "cpu": [ "riscv64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -2151,13 +2159,12 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", - "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", + "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", "cpu": [ "s390x" ], - "dev": true, "optional": true, "os": [ "linux" @@ -2167,13 +2174,12 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", - "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", + "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -2183,13 +2189,12 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", - "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", + "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "netbsd" @@ -2199,13 +2204,12 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", - "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", + "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "openbsd" @@ -2215,13 +2219,12 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", - "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", + "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "sunos" @@ -2231,13 +2234,12 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", - "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", + "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "win32" @@ -2247,13 +2249,12 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", - "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", + "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", "cpu": [ "ia32" ], - "dev": true, "optional": true, "os": [ "win32" @@ -2263,13 +2264,12 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", - "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", + "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "win32" @@ -2384,9 +2384,9 @@ } }, "node_modules/@floating-ui/core": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.1.tgz", - "integrity": "sha512-42UH54oPZHPdRHdw6BgoBD6cg/eVTmVrFcgeRDM3jbO7uxSoipVcmcIGFcA5jmOHO5apcyvBhkSKES3fQJnu7A==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.2.tgz", + "integrity": "sha512-+2XpQV9LLZeanU4ZevzRnGFg2neDeKHgFLjP6YLW+tly0IvrhqT4u8enLGjLH3qeh85g19xY5rsAusfwTdn5lg==", "dependencies": { "@floating-ui/utils": "^0.2.0" } @@ -2401,9 +2401,9 @@ } }, "node_modules/@floating-ui/react-dom": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.0.9.tgz", - "integrity": "sha512-q0umO0+LQK4+p6aGyvzASqKbKOJcAHJ7ycE9CuUvfx3s9zTHWmGJTPOIlM/hmSBfUfg/XfY5YhLBLR/LHwShQQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.0.tgz", + "integrity": "sha512-lNzj5EQmEKn5FFKc04+zasr09h/uX8RtJRNj5gUXsSQIXHVWTVh+hVAg1vOMCexkX8EgvemMvIFpQfkosnVNyA==", "dependencies": { "@floating-ui/dom": "^1.0.0" }, @@ -2450,11 +2450,23 @@ "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", "dev": true }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", - "dev": true, + "devOptional": true, "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -2468,7 +2480,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, + "devOptional": true, "engines": { "node": ">=6.0.0" } @@ -2477,7 +2489,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true, + "devOptional": true, "engines": { "node": ">=6.0.0" } @@ -2486,7 +2498,7 @@ "version": "0.3.6", "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", - "dev": true, + "devOptional": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25" @@ -2496,13 +2508,13 @@ "version": "1.4.15", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true + "devOptional": true }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.25", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, + "devOptional": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" @@ -2604,18 +2616,18 @@ } }, "node_modules/@mui/core-downloads-tracker": { - "version": "5.15.17", - "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.15.17.tgz", - "integrity": "sha512-DVAejDQkjNnIac7MfP8sLzuo7fyrBPxNdXe+6bYqOqg1z2OPTlfFAejSNzWe7UenRMuFu9/AyFXj/X2vN2w6dA==", + "version": "5.15.18", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.15.18.tgz", + "integrity": "sha512-/9pVk+Al8qxAjwFUADv4BRZgMpZM4m5E+2Q/20qhVPuIJWqKp4Ie4tGExac6zu93rgPTYVQGgu+1vjiT0E+cEw==", "funding": { "type": "opencollective", "url": "https://opencollective.com/mui-org" } }, "node_modules/@mui/icons-material": { - "version": "5.15.17", - "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.15.17.tgz", - "integrity": "sha512-xVzl2De7IY36s/keHX45YMiCpsIx3mNv2xwDgtBkRSnZQtVk+Gqufwj1ktUxEyjzEhBl0+PiNJqYC31C+n1n6A==", + "version": "5.15.18", + "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.15.18.tgz", + "integrity": "sha512-jGhyw02TSLM0NgW+MDQRLLRUD/K4eN9rlK2pTBTL1OtzyZmQ8nB060zK1wA0b7cVrIiG+zyrRmNAvGWXwm2N9Q==", "peer": true, "dependencies": { "@babel/runtime": "^7.23.9" @@ -2639,13 +2651,13 @@ } }, "node_modules/@mui/material": { - "version": "5.15.17", - "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.15.17.tgz", - "integrity": "sha512-ru/MLvTkCh0AZXmqwIpqGTOoVBS/sX48zArXq/DvktxXZx4fskiRA2PEc7Rk5ZlFiZhKh4moL4an+l8zZwq49Q==", + "version": "5.15.18", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.15.18.tgz", + "integrity": "sha512-n+/dsiqux74fFfcRUJjok+ieNQ7+BEk6/OwX9cLcLvriZrZb+/7Y8+Fd2HlUUbn5N0CDurgAHm0VH1DqyJ9HAw==", "dependencies": { "@babel/runtime": "^7.23.9", "@mui/base": "5.0.0-beta.40", - "@mui/core-downloads-tracker": "^5.15.17", + "@mui/core-downloads-tracker": "^5.15.18", "@mui/system": "^5.15.15", "@mui/types": "^7.2.14", "@mui/utils": "^5.15.14", @@ -2946,9 +2958,9 @@ } }, "node_modules/@rjsf/core": { - "version": "5.18.3", - "resolved": "https://registry.npmjs.org/@rjsf/core/-/core-5.18.3.tgz", - "integrity": "sha512-HVqqoVzcjYX1BUCqHm7iUjBoVx1UDud1KP6bJ5drtOOvHChfKEbMUt2hWJcuXIlmNPuw2lRxETtcuRbEM2wsRA==", + "version": "5.18.4", + "resolved": "https://registry.npmjs.org/@rjsf/core/-/core-5.18.4.tgz", + "integrity": "sha512-OUPC+l44X1geYT9sSsmQC2pakvFWCQB+5Iy/ITfLMJq3MIjJn0gakCwYHXMMBGUAKM1SSMIyKWyCazt3kY9fhg==", "dependencies": { "lodash": "^4.17.21", "lodash-es": "^4.17.21", @@ -2965,9 +2977,9 @@ } }, "node_modules/@rjsf/mui": { - "version": "5.18.3", - "resolved": "https://registry.npmjs.org/@rjsf/mui/-/mui-5.18.3.tgz", - "integrity": "sha512-zcudsSECpm3hSTEjWsRLnrT5IMzG4Q3/muBaYtdlapzTaK0Mb3ktEPyXN+iZ6NjxZQTwH7aYn1vo/msbend4ww==", + "version": "5.18.4", + "resolved": "https://registry.npmjs.org/@rjsf/mui/-/mui-5.18.4.tgz", + "integrity": "sha512-SDKBcp/LOCdb8Rn4f4mBiEV8M+FCFQWK8KB4ymyzqjB5/2sVf5rw9u7o84SSXmdnQKt4SAztQf3Sd8tLhEzvPg==", "engines": { "node": ">=14" }, @@ -2982,9 +2994,9 @@ } }, "node_modules/@rjsf/utils": { - "version": "5.18.3", - "resolved": "https://registry.npmjs.org/@rjsf/utils/-/utils-5.18.3.tgz", - "integrity": "sha512-0TzjAKAlqXSCneVnHhcL3gAr4DlIPgwzkFdNEI4A+LFjLFlECPah2o3RhEgvqJnUXFviDGF1dqhkxa/Pr59ajw==", + "version": "5.18.4", + "resolved": "https://registry.npmjs.org/@rjsf/utils/-/utils-5.18.4.tgz", + "integrity": "sha512-svLMk5aW6q3JQRYVTJradFc9tLeQ1vX5/k6fPwxf+08eweqPbINq7aokLBSStUNr8FfYgThTl8IfehLoVP2dvw==", "dependencies": { "json-schema-merge-allof": "^0.8.1", "jsonpointer": "^5.0.1", @@ -3000,9 +3012,9 @@ } }, "node_modules/@rjsf/validator-ajv8": { - "version": "5.18.3", - "resolved": "https://registry.npmjs.org/@rjsf/validator-ajv8/-/validator-ajv8-5.18.3.tgz", - "integrity": "sha512-geEVuNuYulHVUBnnkLCS7QZRvAuD1clOjuUbwNjFzSpnYHVO0+mvvi4uHTia/eSvRyDy4vdkxu320uPe4TsgeQ==", + "version": "5.18.4", + "resolved": "https://registry.npmjs.org/@rjsf/validator-ajv8/-/validator-ajv8-5.18.4.tgz", + "integrity": "sha512-D0bUtruWbUmXG8z3VBbCky0Cx65rmcdG/QypB9ri5YTSNTQIxuq28StBpZUZn84CO/oMOtociGy4afW1aj5C0g==", "dependencies": { "ajv": "^8.12.0", "ajv-formats": "^2.1.1", @@ -3016,29 +3028,6 @@ "@rjsf/utils": "^5.18.x" } }, - "node_modules/@rollup/plugin-babel": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", - "integrity": "sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==", - "dev": true, - "dependencies": { - "@babel/helper-module-imports": "^7.10.4", - "@rollup/pluginutils": "^3.1.0" - }, - "engines": { - "node": ">= 10.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0", - "@types/babel__core": "^7.1.9", - "rollup": "^1.20.0||^2.0.0" - }, - "peerDependenciesMeta": { - "@types/babel__core": { - "optional": true - } - } - }, "node_modules/@rollup/plugin-node-resolve": { "version": "15.2.3", "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.2.3.tgz", @@ -3064,47 +3053,6 @@ } } }, - "node_modules/@rollup/plugin-node-resolve/node_modules/@rollup/pluginutils": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz", - "integrity": "sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==", - "dev": true, - "dependencies": { - "@types/estree": "^1.0.0", - "estree-walker": "^2.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "node_modules/@rollup/plugin-node-resolve/node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true - }, - "node_modules/@rollup/plugin-replace": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-2.4.2.tgz", - "integrity": "sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==", - "dev": true, - "dependencies": { - "@rollup/pluginutils": "^3.1.0", - "magic-string": "^0.25.7" - }, - "peerDependencies": { - "rollup": "^1.20.0 || ^2.0.0" - } - }, "node_modules/@rollup/plugin-terser": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.4.tgz", @@ -3128,26 +3076,229 @@ } }, "node_modules/@rollup/pluginutils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", - "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz", + "integrity": "sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==", "dev": true, "dependencies": { - "@types/estree": "0.0.39", - "estree-walker": "^1.0.1", - "picomatch": "^2.2.2" + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^2.3.1" }, "engines": { - "node": ">= 8.0.0" + "node": ">=14.0.0" }, "peerDependencies": { - "rollup": "^1.20.0||^2.0.0" + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } } }, - "node_modules/@rollup/pluginutils/node_modules/@types/estree": { - "version": "0.0.39", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", - "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", + "node_modules/@rollup/pluginutils/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz", + "integrity": "sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.0.tgz", + "integrity": "sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.0.tgz", + "integrity": "sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.0.tgz", + "integrity": "sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.0.tgz", + "integrity": "sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.0.tgz", + "integrity": "sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.0.tgz", + "integrity": "sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.0.tgz", + "integrity": "sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.0.tgz", + "integrity": "sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.0.tgz", + "integrity": "sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.0.tgz", + "integrity": "sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.0.tgz", + "integrity": "sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.0.tgz", + "integrity": "sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.0.tgz", + "integrity": "sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.0.tgz", + "integrity": "sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.0.tgz", + "integrity": "sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", "dev": true }, "node_modules/@surma/rollup-plugin-off-main-thread": { @@ -3162,6 +3313,15 @@ "string.prototype.matchall": "^4.0.6" } }, + "node_modules/@surma/rollup-plugin-off-main-thread/node_modules/magic-string": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "dev": true, + "dependencies": { + "sourcemap-codec": "^1.4.8" + } + }, "node_modules/@turf/area": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/@turf/area/-/area-6.5.0.tgz", @@ -3250,9 +3410,9 @@ } }, "node_modules/@types/babel__traverse": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.5.tgz", - "integrity": "sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==", + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", + "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", "dev": true, "dependencies": { "@babel/types": "^7.20.7" @@ -3305,15 +3465,20 @@ "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==" }, + "node_modules/@types/parse-path": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@types/parse-path/-/parse-path-7.0.3.tgz", + "integrity": "sha512-LriObC2+KYZD3FzCrgWGv/qufdUy4eXrxcLgQMfYXgPbLIecKIsVBaQgUPmxSSLcjmYbDTQbMgr6qr6l/eb7Bg==" + }, "node_modules/@types/prop-types": { "version": "15.7.12", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==" }, "node_modules/@types/react": { - "version": "18.3.2", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.2.tgz", - "integrity": "sha512-Btgg89dAnqD4vV7R3hlwOxgqobUQKgx3MmrQRi0yYbs/P0ym8XozIAlkqVilPqHQwXs4e9Tf63rrCgl58BcO4w==", + "version": "18.3.3", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", + "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -3328,6 +3493,14 @@ "@types/react": "*" } }, + "node_modules/@types/react-reconciler": { + "version": "0.28.8", + "resolved": "https://registry.npmjs.org/@types/react-reconciler/-/react-reconciler-0.28.8.tgz", + "integrity": "sha512-SN9c4kxXZonFhbX4hJrZy37yw9e7EIxcpHCxQv5JUS18wDE5ovkQKlqQEkufdJCCMfuI9BnjUJvhYeJ9x5Ra7g==", + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@types/react-transition-group": { "version": "4.4.10", "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.10.tgz", @@ -3353,28 +3526,124 @@ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" + }, + "node_modules/@vitejs/plugin-react": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.3.0.tgz", + "integrity": "sha512-KcEbMsn4Dpk+LIbHMj7gDPRKaTMStxxWRkRmxsg/jVdFdJCZWt1SchZcf0M4t8lIKdwwMsEyzhrcOXRrDPtOBw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.24.5", + "@babel/plugin-transform-react-jsx-self": "^7.24.5", + "@babel/plugin-transform-react-jsx-source": "^7.24.1", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.14.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0" + } + }, + "node_modules/@vitest/expect": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.6.0.tgz", + "integrity": "sha512-ixEvFVQjycy/oNgHjqsL6AZCDduC+tflRluaHIzKIsdbzkLn2U/iBnVeJwB6HsIjQBdfMR8Z0tRxKUsvFJEeWQ==", + "dev": true, + "dependencies": { + "@vitest/spy": "1.6.0", + "@vitest/utils": "1.6.0", + "chai": "^4.3.10" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.6.0.tgz", + "integrity": "sha512-P4xgwPjwesuBiHisAVz/LSSZtDjOTPYZVmNAnpHHSR6ONrf8eCJOFRvUwdHn30F5M1fxhqtl7QZQUk2dprIXAg==", + "dev": true, + "dependencies": { + "@vitest/utils": "1.6.0", + "p-limit": "^5.0.0", + "pathe": "^1.1.1" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner/node_modules/p-limit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-5.0.0.tgz", + "integrity": "sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@vitest/runner/node_modules/yocto-queue": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", + "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@vitest/snapshot": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.6.0.tgz", + "integrity": "sha512-+Hx43f8Chus+DCmygqqfetcAZrDJwvTj0ymqjQq4CvmpKFSTVteEOBzCusu1x2tt4OJcvBflyHUE0DZSLgEMtQ==", + "dev": true, + "dependencies": { + "magic-string": "^0.30.5", + "pathe": "^1.1.1", + "pretty-format": "^29.7.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } }, - "node_modules/@vitejs/plugin-react": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.2.1.tgz", - "integrity": "sha512-oojO9IDc4nCUUi8qIR11KoQm0XFFLIwsRBwHRR4d/88IWghn1y6ckz/bJ8GHDCsYEJee8mDzqtJxh15/cisJNQ==", + "node_modules/@vitest/spy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.6.0.tgz", + "integrity": "sha512-leUTap6B/cqi/bQkXUu6bQV5TZPx7pmMBKBQiI0rJA8c3pB56ZsaTbREnF7CJfmvAS4V2cXIBAh/3rVwrrCYgw==", "dev": true, "dependencies": { - "@babel/core": "^7.23.5", - "@babel/plugin-transform-react-jsx-self": "^7.23.3", - "@babel/plugin-transform-react-jsx-source": "^7.23.3", - "@types/babel__core": "^7.20.5", - "react-refresh": "^0.14.0" + "tinyspy": "^2.2.0" }, - "engines": { - "node": "^14.18.0 || >=16.0.0" + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.6.0.tgz", + "integrity": "sha512-21cPiuGMoMZwiOHa2i4LXkMkMkCGzA+MVFV70jRwHo95dL4x/ts5GZhML1QWuy7yfp3WzK3lRvZi3JnXTYqrBw==", + "dev": true, + "dependencies": { + "diff-sequences": "^29.6.3", + "estree-walker": "^3.0.3", + "loupe": "^2.3.7", + "pretty-format": "^29.7.0" }, - "peerDependencies": { - "vite": "^4.2.0 || ^5.0.0" + "funding": { + "url": "https://opencollective.com/vitest" } }, "node_modules/abs-svg-path": { @@ -3383,15 +3652,15 @@ "integrity": "sha512-d8XPSGjfyzlXC3Xx891DJRyZfqk5JU0BJrDQcsWomFIV1/BIzPW5HDH5iDdWpqWaav0YVIEzT1RHTwWr0FFshA==" }, "node_modules/ace-builds": { - "version": "1.33.2", - "resolved": "https://registry.npmjs.org/ace-builds/-/ace-builds-1.33.2.tgz", - "integrity": "sha512-uDqCe+XDIdnADaDrA8o+x+qAfbM6uqyDQ43QcE6qC7zBPTvQSMOSPcXW+HvjZhEc2YbVYSaxXJX1qQKPgYqi5w==" + "version": "1.34.0", + "resolved": "https://registry.npmjs.org/ace-builds/-/ace-builds-1.34.0.tgz", + "integrity": "sha512-ZQqoV76wl4guDE5zvEnxCDrvy9gzLAwu7eD4ikYj/Gdlb4+qRLbb+aOFVnweZZRsHh089V0WVaw2NMNuiiEdTw==" }, "node_modules/acorn": { "version": "8.11.3", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", - "dev": true, + "devOptional": true, "bin": { "acorn": "bin/acorn" }, @@ -3408,6 +3677,15 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, + "node_modules/acorn-walk": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", + "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/ajv": { "version": "8.13.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.13.0.tgz", @@ -3659,6 +3937,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/async": { "version": "3.2.5", "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", @@ -3797,12 +4084,12 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -3857,6 +4144,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/call-bind": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", @@ -3885,9 +4181,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001618", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001618.tgz", - "integrity": "sha512-p407+D1tIkDvsEAPS22lJxLQQaG8OTBEqo0KhzfABGk0TU4juBNDSfH0hyAp/HRyx+M8L17z/ltyhxh27FTfQg==", + "version": "1.0.30001621", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001621.tgz", + "integrity": "sha512-+NLXZiviFFKX0fk8Piwv3PfLPGtRqJeq2TiNoUff/qB5KJgwecJTvCXDpmlyP/eCI/GUEmp/h/y5j0yckiiZrA==", "dev": true, "funding": [ { @@ -3921,6 +4217,24 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/chai": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz", + "integrity": "sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==", + "dev": true, + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.3", + "deep-eql": "^4.1.3", + "get-func-name": "^2.0.2", + "loupe": "^2.3.6", + "pathval": "^1.1.1", + "type-detect": "^4.0.8" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -3978,6 +4292,18 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/check-error": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", + "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.2" + }, + "engines": { + "node": "*" + } + }, "node_modules/clamp": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/clamp/-/clamp-1.0.1.tgz", @@ -4144,6 +4470,12 @@ "typedarray": "^0.0.6" } }, + "node_modules/confbox": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.7.tgz", + "integrity": "sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==", + "dev": true + }, "node_modules/convert-source-map": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", @@ -4479,6 +4811,18 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/deep-eql": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", + "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", + "dev": true, + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -4566,6 +4910,15 @@ "resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.5.tgz", "integrity": "sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==" }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -4641,9 +4994,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.768", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.768.tgz", - "integrity": "sha512-z2U3QcvNuxdkk33YV7R1bVMNq7fL23vq3WfO5BHcqrm4TnDGReouBfYKLEFh5umoK1XACjEwp8mmnhXk2EJigw==", + "version": "1.4.782", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.782.tgz", + "integrity": "sha512-JUfU61e8tr+i5Y1FKXcKs+Xe+rJ+CEqm4cgv1kMihPE2EvYHmYyVr3Im/+1+Z5B29Be2EEGCZCwAc6Tazdl1Yg==", "dev": true }, "node_modules/element-size": { @@ -4887,10 +5240,9 @@ } }, "node_modules/esbuild": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", - "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", - "dev": true, + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", + "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", "hasInstallScript": true, "bin": { "esbuild": "bin/esbuild" @@ -4899,28 +5251,29 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/android-arm": "0.18.20", - "@esbuild/android-arm64": "0.18.20", - "@esbuild/android-x64": "0.18.20", - "@esbuild/darwin-arm64": "0.18.20", - "@esbuild/darwin-x64": "0.18.20", - "@esbuild/freebsd-arm64": "0.18.20", - "@esbuild/freebsd-x64": "0.18.20", - "@esbuild/linux-arm": "0.18.20", - "@esbuild/linux-arm64": "0.18.20", - "@esbuild/linux-ia32": "0.18.20", - "@esbuild/linux-loong64": "0.18.20", - "@esbuild/linux-mips64el": "0.18.20", - "@esbuild/linux-ppc64": "0.18.20", - "@esbuild/linux-riscv64": "0.18.20", - "@esbuild/linux-s390x": "0.18.20", - "@esbuild/linux-x64": "0.18.20", - "@esbuild/netbsd-x64": "0.18.20", - "@esbuild/openbsd-x64": "0.18.20", - "@esbuild/sunos-x64": "0.18.20", - "@esbuild/win32-arm64": "0.18.20", - "@esbuild/win32-ia32": "0.18.20", - "@esbuild/win32-x64": "0.18.20" + "@esbuild/aix-ppc64": "0.20.2", + "@esbuild/android-arm": "0.20.2", + "@esbuild/android-arm64": "0.20.2", + "@esbuild/android-x64": "0.20.2", + "@esbuild/darwin-arm64": "0.20.2", + "@esbuild/darwin-x64": "0.20.2", + "@esbuild/freebsd-arm64": "0.20.2", + "@esbuild/freebsd-x64": "0.20.2", + "@esbuild/linux-arm": "0.20.2", + "@esbuild/linux-arm64": "0.20.2", + "@esbuild/linux-ia32": "0.20.2", + "@esbuild/linux-loong64": "0.20.2", + "@esbuild/linux-mips64el": "0.20.2", + "@esbuild/linux-ppc64": "0.20.2", + "@esbuild/linux-riscv64": "0.20.2", + "@esbuild/linux-s390x": "0.20.2", + "@esbuild/linux-x64": "0.20.2", + "@esbuild/netbsd-x64": "0.20.2", + "@esbuild/openbsd-x64": "0.20.2", + "@esbuild/sunos-x64": "0.20.2", + "@esbuild/win32-arm64": "0.20.2", + "@esbuild/win32-ia32": "0.20.2", + "@esbuild/win32-x64": "0.20.2" } }, "node_modules/escalade": { @@ -5341,10 +5694,13 @@ } }, "node_modules/estree-walker": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", - "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", - "dev": true + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0" + } }, "node_modules/esutils": { "version": "2.0.3", @@ -5371,6 +5727,41 @@ "node": ">=0.8.x" } }, + "node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/execa/node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/ext": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", @@ -5536,9 +5927,9 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "dependencies": { "to-regex-range": "^5.0.1" @@ -5677,7 +6068,6 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, "hasInstallScript": true, "optional": true, "os": [ @@ -5741,6 +6131,15 @@ "resolved": "https://registry.npmjs.org/get-canvas-context/-/get-canvas-context-1.0.2.tgz", "integrity": "sha512-LnpfLf/TNzr9zVOGiIY6aKCz8EKuXmlYNV7CM2pUjBa/B+c2I15tS7KLySep75+FuerJdmArvJLcsAXWEy2H0A==" }, + "node_modules/get-func-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/get-intrinsic": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", @@ -6303,6 +6702,15 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "engines": { + "node": ">=16.17.0" + } + }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -6376,6 +6784,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -6794,12 +7203,12 @@ } }, "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", "dev": true, "engines": { - "node": ">=8" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -6924,6 +7333,17 @@ "set-function-name": "^2.0.1" } }, + "node_modules/its-fine": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/its-fine/-/its-fine-1.2.5.tgz", + "integrity": "sha512-fXtDA0X0t0eBYAGLVM5YsgJGsJ5jEmqZEPrGbzdf5awjv0xE7nqv3TVnvtUF060Tkes15DbDAKW/I48vsb6SyA==", + "dependencies": { + "@types/react-reconciler": "^0.28.0" + }, + "peerDependencies": { + "react": ">=18.0" + } + }, "node_modules/jake": { "version": "10.9.1", "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.1.tgz", @@ -7169,6 +7589,26 @@ "json-buffer": "3.0.1" } }, + "node_modules/konva": { + "version": "9.3.11", + "resolved": "https://registry.npmjs.org/konva/-/konva-9.3.11.tgz", + "integrity": "sha512-ZkFF4CXKZCDd2+6sBPA0y3hQ+X4uTqIS6JxTl3BEOFJzKr1tId+rxxJgtsk1FQIH3auuvnMj/rkbatUcf9C2Wg==", + "funding": [ + { + "type": "patreon", + "url": "https://www.patreon.com/lavrton" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/konva" + }, + { + "type": "github", + "url": "https://github.com/sponsors/lavrton" + } + ], + "peer": true + }, "node_modules/leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", @@ -7196,6 +7636,22 @@ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" }, + "node_modules/local-pkg": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.0.tgz", + "integrity": "sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==", + "dev": true, + "dependencies": { + "mlly": "^1.4.2", + "pkg-types": "^1.0.3" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -7268,6 +7724,15 @@ "loose-envify": "cli.js" } }, + "node_modules/loupe": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", + "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.1" + } + }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -7278,12 +7743,12 @@ } }, "node_modules/magic-string": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", - "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "version": "0.30.10", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz", + "integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==", "dev": true, "dependencies": { - "sourcemap-codec": "^1.4.8" + "@jridgewell/sourcemap-codec": "^1.4.15" } }, "node_modules/make-dir": { @@ -7643,6 +8108,12 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -8188,18 +8659,30 @@ ] }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", + "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", "dev": true, "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { "node": ">=8.6" } }, + "node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -8219,6 +8702,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/mlly": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.0.tgz", + "integrity": "sha512-U9SDaXGEREBYQgfejV97coK0UL1r+qnF2SyO9A3qcI8MzKnsIFKHNVEkrDyNncQTKQQumsasmeq84eNMdBfsNQ==", + "dev": true, + "dependencies": { + "acorn": "^8.11.3", + "pathe": "^1.1.2", + "pkg-types": "^1.1.0", + "ufo": "^1.5.3" + } + }, "node_modules/mouse-change": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/mouse-change/-/mouse-change-1.4.0.tgz", @@ -8334,6 +8829,33 @@ "resolved": "https://registry.npmjs.org/normalize-svg-path/-/normalize-svg-path-0.1.0.tgz", "integrity": "sha512-1/kmYej2iedi5+ROxkRESL/pI02pkg0OBnaR4hJkSIX6+ORzepwbuUXfrdZaPjysTsJInj0Rj5NuX027+dMBvA==" }, + "node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dev": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/number-is-integer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-integer/-/number-is-integer-1.0.1.tgz", @@ -8463,6 +8985,21 @@ "wrappy": "1" } }, + "node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -8575,6 +9112,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/parse-path": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse-path/-/parse-path-7.0.0.tgz", + "integrity": "sha512-Euf9GG8WT9CdqwuWJGdf3RkUcTBArppHABkO7Lm8IzRQp0e2r/kkFnmhu4TSK30Wcu5rVAZLmfPKSBBi9tWFog==", + "dependencies": { + "protocols": "^2.0.0" + } + }, "node_modules/parse-rect": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/parse-rect/-/parse-rect-1.2.0.tgz", @@ -8593,6 +9138,18 @@ "resolved": "https://registry.npmjs.org/parse-unit/-/parse-unit-1.0.1.tgz", "integrity": "sha512-hrqldJHokR3Qj88EIlV/kAyAi/G5R2+R56TBANxNMy0uPlYcttx0jnMW6Yx5KsKPSbC3KddM/7qQm3+0wEXKxg==" }, + "node_modules/parse-url": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-9.2.0.tgz", + "integrity": "sha512-bCgsFI+GeGWPAvAiUv63ZorMeif3/U0zaXABGJbOWt5OH2KCaPHF6S+0ok4aqM9RuIPGyZdx9tR9l13PsW4AYQ==", + "dependencies": { + "@types/parse-path": "^7.0.0", + "parse-path": "^7.0.0" + }, + "engines": { + "node": ">=14.13.0" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -8631,6 +9188,21 @@ "node": ">=8" } }, + "node_modules/pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "dev": true + }, + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/pbf": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/pbf/-/pbf-3.2.1.tgz", @@ -8756,6 +9328,17 @@ "node": ">=8" } }, + "node_modules/pkg-types": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.1.1.tgz", + "integrity": "sha512-ko14TjmDuQJ14zsotODv7dBlwxKhUKQEhuhmbqo1uCi9BB0Z2alo/wAXg6q1dTR5TyuqYyWhjtfe/Tsh+X28jQ==", + "dev": true, + "dependencies": { + "confbox": "^0.1.7", + "mlly": "^1.7.0", + "pathe": "^1.1.2" + } + }, "node_modules/plotly.js": { "version": "2.32.0", "resolved": "https://registry.npmjs.org/plotly.js/-/plotly.js-2.32.0.tgz", @@ -8835,7 +9418,6 @@ "version": "8.4.38", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", - "dev": true, "funding": [ { "type": "opencollective", @@ -8885,6 +9467,32 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/probe-image-size": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/probe-image-size/-/probe-image-size-7.2.3.tgz", @@ -8929,6 +9537,11 @@ "resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz", "integrity": "sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==" }, + "node_modules/protocols": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/protocols/-/protocols-2.0.1.tgz", + "integrity": "sha512-/XJ368cyBJ7fzLMwLKv1e4vLxOju2MNAIokcr7meSaNcVbWz/CPcW22cP04mwxOErdA5mwjA8Q6w/cdAQxVn7Q==" + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -8979,6 +9592,15 @@ "safe-buffer": "^5.1.0" } }, + "node_modules/re-resizable": { + "version": "6.9.17", + "resolved": "https://registry.npmjs.org/re-resizable/-/re-resizable-6.9.17.tgz", + "integrity": "sha512-OBqd1BwVXpEJJn/yYROG+CbeqIDBWIp6wathlpB0kzZWWZIY1gPTsgK2yJEui5hOvkCdC2mcexF2V3DZVfLq2g==", + "peerDependencies": { + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/react": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", @@ -9006,6 +9628,15 @@ "react-dom": "^0.13.0 || ^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0 || ^18.0.0" } }, + "node_modules/react-colorful": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.6.1.tgz", + "integrity": "sha512-1exovf0uGTGyq5mXQT0zgQ80uvj2PCwvF8zY1RN9/vbJVSjSo3fsB/4L3ObbF7u70NduSiK4xu4Y6q1MHoUGEw==", + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, "node_modules/react-device-detect": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/react-device-detect/-/react-device-detect-2.2.3.tgz", @@ -9030,6 +9661,27 @@ "react": "^18.3.1" } }, + "node_modules/react-draggable": { + "version": "4.4.6", + "resolved": "https://registry.npmjs.org/react-draggable/-/react-draggable-4.4.6.tgz", + "integrity": "sha512-LtY5Xw1zTPqHkVmtM3X8MUOxNDOUhv/khTgBgrUvwaS064bwVvxT+q5El0uUFNx5IEPKXuRejr7UqLwBIg5pdw==", + "dependencies": { + "clsx": "^1.1.1", + "prop-types": "^15.8.1" + }, + "peerDependencies": { + "react": ">= 16.3.0", + "react-dom": ">= 16.3.0" + } + }, + "node_modules/react-draggable/node_modules/clsx": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", + "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", + "engines": { + "node": ">=6" + } + }, "node_modules/react-fast-compare": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", @@ -9054,6 +9706,36 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" }, + "node_modules/react-konva": { + "version": "18.2.10", + "resolved": "https://registry.npmjs.org/react-konva/-/react-konva-18.2.10.tgz", + "integrity": "sha512-ohcX1BJINL43m4ynjZ24MxFI1syjBdrXhqVxYVDw2rKgr3yuS0x/6m1Y2Z4sl4T/gKhfreBx8KHisd0XC6OT1g==", + "funding": [ + { + "type": "patreon", + "url": "https://www.patreon.com/lavrton" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/konva" + }, + { + "type": "github", + "url": "https://github.com/sponsors/lavrton" + } + ], + "dependencies": { + "@types/react-reconciler": "^0.28.2", + "its-fine": "^1.1.1", + "react-reconciler": "~0.29.0", + "scheduler": "^0.23.0" + }, + "peerDependencies": { + "konva": "^8.0.1 || ^7.2.5 || ^9.0.0", + "react": ">=18.0.0", + "react-dom": ">=18.0.0" + } + }, "node_modules/react-markdown": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-9.0.1.tgz", @@ -9103,6 +9785,21 @@ "react": ">0.13.0" } }, + "node_modules/react-reconciler": { + "version": "0.29.2", + "resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.29.2.tgz", + "integrity": "sha512-zZQqIiYgDCTP/f1N/mAR10nJGrPD2ZR+jDSEsKWJHYC7Cm2wodlwbR3upZRdC3cjIjSlTLNVyO7Iu0Yy7t2AYg==", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "engines": { + "node": ">=0.10.0" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, "node_modules/react-refresh": { "version": "0.14.2", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", @@ -9112,6 +9809,32 @@ "node": ">=0.10.0" } }, + "node_modules/react-resizable": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/react-resizable/-/react-resizable-3.0.5.tgz", + "integrity": "sha512-vKpeHhI5OZvYn82kXOs1bC8aOXktGU5AmKAgaZS4F5JPburCtbmDPqE7Pzp+1kN4+Wb81LlF33VpGwWwtXem+w==", + "dependencies": { + "prop-types": "15.x", + "react-draggable": "^4.0.3" + }, + "peerDependencies": { + "react": ">= 16.3" + } + }, + "node_modules/react-rnd": { + "version": "10.4.11", + "resolved": "https://registry.npmjs.org/react-rnd/-/react-rnd-10.4.11.tgz", + "integrity": "sha512-XTfNGNcS0ad2vo3to7qNTB0BkFML9k1csIUI0Nlj44M6Uuh7yP/2h8WXiXcV3v3bxxVJck1C9K6FS1LrLH0E0Q==", + "dependencies": { + "re-resizable": "6.9.17", + "react-draggable": "4.4.6", + "tslib": "2.6.2" + }, + "peerDependencies": { + "react": ">=16.3.0", + "react-dom": ">=16.3.0" + } + }, "node_modules/react-router": { "version": "6.23.1", "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.23.1.tgz", @@ -9520,17 +10243,36 @@ } }, "node_modules/rollup": { - "version": "2.79.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", - "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==", - "dev": true, + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.18.0.tgz", + "integrity": "sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==", + "dependencies": { + "@types/estree": "1.0.5" + }, "bin": { "rollup": "dist/bin/rollup" }, "engines": { - "node": ">=10.0.0" + "node": ">=18.0.0", + "npm": ">=8.0.0" }, "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.18.0", + "@rollup/rollup-android-arm64": "4.18.0", + "@rollup/rollup-darwin-arm64": "4.18.0", + "@rollup/rollup-darwin-x64": "4.18.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.18.0", + "@rollup/rollup-linux-arm-musleabihf": "4.18.0", + "@rollup/rollup-linux-arm64-gnu": "4.18.0", + "@rollup/rollup-linux-arm64-musl": "4.18.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.18.0", + "@rollup/rollup-linux-riscv64-gnu": "4.18.0", + "@rollup/rollup-linux-s390x-gnu": "4.18.0", + "@rollup/rollup-linux-x64-gnu": "4.18.0", + "@rollup/rollup-linux-x64-musl": "4.18.0", + "@rollup/rollup-win32-arm64-msvc": "4.18.0", + "@rollup/rollup-win32-ia32-msvc": "4.18.0", + "@rollup/rollup-win32-x64-msvc": "4.18.0", "fsevents": "~2.3.2" } }, @@ -9727,6 +10469,24 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/signum": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/signum/-/signum-1.0.0.tgz", @@ -9750,7 +10510,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -9759,7 +10518,7 @@ "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, + "devOptional": true, "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -9769,7 +10528,7 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, + "devOptional": true, "engines": { "node": ">=0.10.0" } @@ -9803,6 +10562,12 @@ "node": "*" } }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true + }, "node_modules/static-eval": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.1.1.tgz", @@ -9811,6 +10576,12 @@ "escodegen": "^2.1.0" } }, + "node_modules/std-env": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.7.0.tgz", + "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==", + "dev": true + }, "node_modules/stream-parser": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/stream-parser/-/stream-parser-0.3.1.tgz", @@ -9981,6 +10752,18 @@ "node": ">=10" } }, + "node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -9993,6 +10776,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/strip-literal": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-2.1.0.tgz", + "integrity": "sha512-Op+UycaUt/8FbN/Z2TWPBLge3jWrP3xj10f3fnYxf052bKuS3EKs1ZQcVGjnEMdsNVAM+plXRdmjrZ/KgG3Skw==", + "dev": true, + "dependencies": { + "js-tokens": "^9.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/strip-literal/node_modules/js-tokens": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.0.tgz", + "integrity": "sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==", + "dev": true + }, "node_modules/strip-outer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", @@ -10128,11 +10929,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/tempy/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/terser": { "version": "5.31.0", "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.0.tgz", "integrity": "sha512-Q1JFAoUKE5IMfI4Z/lkE/E6+SwgzO+x4tq4v1AyBLRj8VSYvRO6A/rQrPg1yud4g0En9EKI1TvFRF2tQFcoUkg==", - "dev": true, + "devOptional": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.8.2", @@ -10150,7 +10963,7 @@ "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true + "devOptional": true }, "node_modules/text-table": { "version": "0.2.0", @@ -10167,16 +10980,40 @@ "xtend": "~4.0.1" } }, + "node_modules/tinybench": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.8.0.tgz", + "integrity": "sha512-1/eK7zUnIklz4JUUlL+658n58XO2hHLQfSk1Zf2LKieUjxidN16eKFEoDEfjHc3ohofSSqK3X5yO6VGb6iW8Lw==", + "dev": true + }, "node_modules/tinycolor2": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz", "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==" }, + "node_modules/tinypool": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.8.4.tgz", + "integrity": "sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/tinyqueue": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/tinyqueue/-/tinyqueue-2.0.3.tgz", "integrity": "sha512-ppJZNDuKGgxzkHihX8v9v9G5f+18gzaTfrukGrq6ueg0lmH4nqVnA2IPG0AEH3jKEk2GRJCUhDoqpoiw3PHLBA==" }, + "node_modules/tinyspy": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.1.tgz", + "integrity": "sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -10296,6 +11133,15 @@ "node": ">= 0.8.0" } }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/type-fest": { "version": "0.16.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", @@ -10417,6 +11263,12 @@ "node": "*" } }, + "node_modules/ufo": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.3.tgz", + "integrity": "sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==", + "dev": true + }, "node_modules/unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", @@ -10720,29 +11572,28 @@ } }, "node_modules/vite": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.3.tgz", - "integrity": "sha512-kQL23kMeX92v3ph7IauVkXkikdDRsYMGTVl5KY2E9OY4ONLvkHf04MDTbnfo6NKxZiDLWzVpP5oTa8hQD8U3dg==", - "dev": true, + "version": "5.2.12", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.12.tgz", + "integrity": "sha512-/gC8GxzxMK5ntBwb48pR32GGhENnjtY30G4A0jemunsBkiEZFw60s8InGpN8gkhHEkjnRK1aSAxeQgwvFhUHAA==", "dependencies": { - "esbuild": "^0.18.10", - "postcss": "^8.4.27", - "rollup": "^3.27.1" + "esbuild": "^0.20.1", + "postcss": "^8.4.38", + "rollup": "^4.13.0" }, "bin": { "vite": "bin/vite.js" }, "engines": { - "node": "^14.18.0 || >=16.0.0" + "node": "^18.0.0 || >=20.0.0" }, "funding": { "url": "https://github.com/vitejs/vite?sponsor=1" }, "optionalDependencies": { - "fsevents": "~2.3.2" + "fsevents": "~2.3.3" }, "peerDependencies": { - "@types/node": ">= 14", + "@types/node": "^18.0.0 || >=20.0.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", @@ -10774,6 +11625,28 @@ } } }, + "node_modules/vite-node": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.6.0.tgz", + "integrity": "sha512-de6HJgzC+TFzOu0NTC4RAIsyf/DY/ibWDYQUcuEA84EMHhcefTUGkjFHKKEJhQN4A+6I0u++kr3l36ZF2d7XRw==", + "dev": true, + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.3.4", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "vite": "^5.0.0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, "node_modules/vite-plugin-pwa": { "version": "0.16.7", "resolved": "https://registry.npmjs.org/vite-plugin-pwa/-/vite-plugin-pwa-0.16.7.tgz", @@ -10814,20 +11687,69 @@ "vite": ">=3.2.0" } }, - "node_modules/vite/node_modules/rollup": { - "version": "3.29.4", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", - "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==", + "node_modules/vitest": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.6.0.tgz", + "integrity": "sha512-H5r/dN06swuFnzNFhq/dnz37bPXnq8xB2xB5JOVk8K09rUtoeNN+LHWkoQ0A/i3hvbUKKcCei9KpbxqHMLhLLA==", "dev": true, + "dependencies": { + "@vitest/expect": "1.6.0", + "@vitest/runner": "1.6.0", + "@vitest/snapshot": "1.6.0", + "@vitest/spy": "1.6.0", + "@vitest/utils": "1.6.0", + "acorn-walk": "^8.3.2", + "chai": "^4.3.10", + "debug": "^4.3.4", + "execa": "^8.0.1", + "local-pkg": "^0.5.0", + "magic-string": "^0.30.5", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "std-env": "^3.5.0", + "strip-literal": "^2.0.0", + "tinybench": "^2.5.1", + "tinypool": "^0.8.3", + "vite": "^5.0.0", + "vite-node": "1.6.0", + "why-is-node-running": "^2.2.2" + }, "bin": { - "rollup": "dist/bin/rollup" + "vitest": "vitest.mjs" }, "engines": { - "node": ">=14.18.0", - "npm": ">=8.0.0" + "node": "^18.0.0 || >=20.0.0" }, - "optionalDependencies": { - "fsevents": "~2.3.2" + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/node": "^18.0.0 || >=20.0.0", + "@vitest/browser": "1.6.0", + "@vitest/ui": "1.6.0", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } } }, "node_modules/vt-pbf": { @@ -10964,6 +11886,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/why-is-node-running": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.2.2.tgz", + "integrity": "sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==", + "dev": true, + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", @@ -11040,6 +11978,71 @@ "node": ">=16.0.0" } }, + "node_modules/workbox-build/node_modules/@rollup/plugin-babel": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", + "integrity": "sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.10.4", + "@rollup/pluginutils": "^3.1.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0", + "@types/babel__core": "^7.1.9", + "rollup": "^1.20.0||^2.0.0" + }, + "peerDependenciesMeta": { + "@types/babel__core": { + "optional": true + } + } + }, + "node_modules/workbox-build/node_modules/@rollup/plugin-replace": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-2.4.2.tgz", + "integrity": "sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==", + "dev": true, + "dependencies": { + "@rollup/pluginutils": "^3.1.0", + "magic-string": "^0.25.7" + }, + "peerDependencies": { + "rollup": "^1.20.0 || ^2.0.0" + } + }, + "node_modules/workbox-build/node_modules/@rollup/pluginutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", + "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", + "dev": true, + "dependencies": { + "@types/estree": "0.0.39", + "estree-walker": "^1.0.1", + "picomatch": "^2.2.2" + }, + "engines": { + "node": ">= 8.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0" + } + }, + "node_modules/workbox-build/node_modules/@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", + "dev": true + }, + "node_modules/workbox-build/node_modules/estree-walker": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", + "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", + "dev": true + }, "node_modules/workbox-build/node_modules/fs-extra": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", @@ -11055,6 +12058,15 @@ "node": ">=10" } }, + "node_modules/workbox-build/node_modules/magic-string": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "dev": true, + "dependencies": { + "sourcemap-codec": "^1.4.8" + } + }, "node_modules/workbox-build/node_modules/pretty-bytes": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", @@ -11067,6 +12079,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/workbox-build/node_modules/rollup": { + "version": "2.79.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", + "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=10.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, "node_modules/workbox-build/node_modules/source-map": { "version": "0.8.0-beta.0", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", diff --git a/package.json b/package.json index df513af..e84ebe0 100644 --- a/package.json +++ b/package.json @@ -24,19 +24,26 @@ "gh-pages": "^6.0.0", "json-schema-defaults": "^0.4.0", "markdown-to-jsx": "^7.3.2", + "parse-url": "^9.2.0", "plotly.js": "^2.28.0", "react": "^18.2.0", "react-ace": "^10.1.0", + "react-colorful": "^5.6.1", "react-device-detect": "^2.2.3", "react-dom": "^18.2.0", + "react-draggable": "^4.4.6", "react-helmet": "^6.1.0", + "react-konva": "^18.2.10", "react-markdown": "^9.0.1", "react-new-window": "^1.0.1", "react-plotly.js": "^2.6.0", + "react-resizable": "^3.0.5", + "react-rnd": "^10.4.11", "react-router-dom": "^6.15.0", "react-scrollable-feed": "^1.3.2", "remark-gfm": "^4.0.0", - "tslib": "^2.6.2" + "tslib": "^2.6.2", + "vite": "^5.2.12" }, "devDependencies": { "@types/react": "^18.2.15", @@ -46,8 +53,8 @@ "eslint-plugin-react": "^7.32.2", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.4.3", - "vite": "^4.4.5", "vite-plugin-pwa": "^0.16.4", - "vite-plugin-singlefile": "^0.13.5" + "vite-plugin-singlefile": "^0.13.5", + "vitest": "^1.6.0" } } diff --git a/src/App.jsx b/src/App.jsx index 3c491a6..5df873f 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -24,6 +24,11 @@ import * as FlexLayout from "flexlayout-react"; import layout from "./layout/layout.json"; function App() { + const queryParams = new URLSearchParams(window.location.search); + const channel = queryParams.get("channel"); // Retrieve the value of a specific query parameter + const showDevFeatures = channel === "dev"; + const showBetaFeatures = channel === "dev" || channel === "beta"; // beta level feature shows in dev and beta channel + // main directory for folderView const { openDirectory, @@ -121,6 +126,8 @@ function App() { return ( ); + } else if (component === "widgets") { + return ( +
+ +
+ ); } // document else if (component === "about") { diff --git a/src/IdeHead.jsx b/src/IdeHead.jsx index 5279693..bc18e86 100644 --- a/src/IdeHead.jsx +++ b/src/IdeHead.jsx @@ -16,6 +16,8 @@ import ideContext from "./ideContext"; export default function IdeHead() { const { + showDevFeatures, + showBetaFeatures, flexModel: model, openDirectory, openBackupDirectory, @@ -77,106 +79,113 @@ export default function IdeHead() { } } - const menuStructure = { - menu: [ - { - label: "CircuitPython Online IDE", - color: deepPurple[500], - options: [ - { - text: "About", - handler: () => { - openTab("About", "about"); - }, + const menuStructure = [ + { + label: "CircuitPython Online IDE", + color: deepPurple[500], + options: [ + { + text: "About", + handler: () => { + openTab("About", "about"); }, - { - text: "GitHub Repo", - handler: () => { - window.open("https://github.com/urfdvw/circuitpython-online-ide-2", "_blank"); - }, + }, + { + text: "GitHub Repo", + handler: () => { + window.open("https://github.com/urfdvw/circuitpython-online-ide-2", "_blank"); }, - ], - }, - { - label: "Connect", - color: grey[900], - options: [ - { - text: "CircuitPy Drive", - handler: () => { - console.log("clicked on `CircuitPy Drive`"); - openDirectory(); - }, + }, + ], + }, + { + label: "Connect", + color: grey[900], + options: [ + { + text: "CircuitPy Drive", + handler: () => { + console.log("clicked on `CircuitPy Drive`"); + openDirectory(); }, - { - text: "Serial Port", - handler: () => { - console.log("clicked on Serial"); - connectToSerialPort(); - }, + }, + { + text: "Serial Port", + handler: () => { + console.log("clicked on Serial"); + connectToSerialPort(); }, - { - text: "Backup Folder", - handler: () => { - console.log("clicked on `Backup Folder`"); - openBackupDirectory(); - }, + }, + { + text: "Backup Folder", + handler: () => { + console.log("clicked on `Backup Folder`"); + openBackupDirectory(); }, - ], - }, - { - label: "Tools", - color: grey[900], - options: [ - { - text: "Navigation", - handler: () => { - openTab("Navigation", "navigation"); - }, + }, + ], + }, + { + label: "Tools", + color: grey[900], + options: [ + { + text: "Navigation", + handler: () => { + openTab("Navigation", "navigation"); }, - { - text: "Plot", - handler: () => { - openTab("Plot", "raw_plot"); - }, + }, + { + text: "Plot", + handler: () => { + openTab("Plot", "raw_plot"); }, - { - text: "Backup", - handler: () => { - openTab("Backup", "backup_drive"); - }, + }, + { + text: "Backup", + handler: () => { + openTab("Backup", "backup_drive"); }, - ], - }, - { - label: "Help", - color: grey[900], - options: [ - { - text: "Quick Start", - handler: () => { - openTab("Quick Start", "quick_start"); - }, + }, + showDevFeatures + ? { + text: "Widgets (dev)", + handler: () => { + openTab("Widgets", "widgets"); + }, + } + : undefined, + ].filter((x) => x), // remove undefined + }, + { + label: "Help", + color: grey[900], + options: [ + { + text: "Quick Start", + handler: () => { + openTab("Quick Start", "quick_start"); }, - { - text: "Help & Learn", - handler: () => { - window.open("https://github.com/urfdvw/circuitpython-online-ide-2/wiki/", "_blank"); - }, + }, + { + text: "Help & Learn", + handler: () => { + window.open("https://github.com/urfdvw/circuitpython-online-ide-2/wiki/", "_blank"); }, - { - text: "Feedback", - handler: () => { - window.open( - "https://docs.google.com/forms/d/e/1FAIpQLSdupiJIRViFwPpuQC1hMp8gRvhxACLoAjgepm_-IRZumwK7Cg/viewform", - "_blank" - ); - }, + }, + { + text: "Feedback", + handler: () => { + window.open( + "https://docs.google.com/forms/d/e/1FAIpQLSdupiJIRViFwPpuQC1hMp8gRvhxACLoAjgepm_-IRZumwK7Cg/viewform", + "_blank" + ); }, - ], - }, - ], - }; + }, + ], + }, + ].filter((x) => x); // remove undefined; + return (
- {menuStructure.menu.map((column) => { + {menuStructure.map((column) => { return ( l.trim()) + .filter((x) => x); + // get dir handle + let curDirectoryHandle = directoryHandle; + for (const l of levels.slice(0, -1)) { + const nextHandle = await curDirectoryHandle.getDirectoryHandle(l, opt); + curDirectoryHandle = nextHandle; + } + // get file handle + const fileHandle = levels.at(-1) === "" ? null : await curDirectoryHandle.getFileHandle(levels.at(-1), opt); + return { dirHandle: curDirectoryHandle, fileHandle }; +} + +export async function writeToPath(rootDirHandle, path, text) { + const { dirHandle, fileHandle } = await path2Handles(rootDirHandle, path); + await writeFileText(fileHandle, text); +} + +export async function getFromPath(rootDirHandle, path) { + const { dirHandle, fileHandle } = await path2Handles(rootDirHandle, path); + return await getFileText(fileHandle); +} // file level ==================================== export async function writeFileText(fileHandle, text) { diff --git a/src/tabs/RawPlotter.jsx b/src/tabs/RawPlotter.jsx index 72c49ee..e1b7dd8 100644 --- a/src/tabs/RawPlotter.jsx +++ b/src/tabs/RawPlotter.jsx @@ -8,6 +8,9 @@ import ideContext from "../ideContext"; import Document from "./Document"; import plotHelp from "../documents/wiki/Plot.md"; +import { removeInBetween } from "../serial/textProcessor"; +import * as constants from "../constants"; + function text_to_data(text) { var lines = text.split("\n"); for (var i = 0; i < lines.length; i++) { @@ -49,8 +52,11 @@ export default function RawPlotter({ node }) { var data = []; var xLabel = "index"; + + const output = removeInBetween(serialOutput, constants.CV_JSON_START, constants.CV_JSON_END); + try { - var plot_raw_list = serialOutput.split("startplot:").slice(1); + var plot_raw_list = output.split("startplot:").slice(1); var plot_raw_text = plot_raw_list.at(-1); var plot_raw_lines = text_to_data(plot_raw_text); var plot_labels = plot_raw_lines[0]; diff --git a/src/tabs/Widgets/CIRCUITPY/connected_variables.py b/src/tabs/Widgets/CIRCUITPY/connected_variables.py new file mode 100644 index 0000000..0cae030 --- /dev/null +++ b/src/tabs/Widgets/CIRCUITPY/connected_variables.py @@ -0,0 +1,111 @@ +import json, sys, supervisor, time +from matcher import BracketMatcher, MatcherProcessor + +CV_JSON_START = "" +CV_JSON_END = "" +LINE_END = "\n" +UPDATE_PERIOD = 0.5 + + +def update(d, u): + """Deep Update of dict class""" + for k, v in u.items(): + if isinstance(v, dict): + d[k] = update(d.get(k, {}), v) + else: + d[k] = v + return d + + +class ConnectedVariables: + def __init__(self): + self.vars = {} + self.cv_processor = MatcherProcessor( + BracketMatcher(CV_JSON_START, CV_JSON_END), + exit_action=self.exit_action, + ) + self.last_time_stamp = time.monotonic() + + def update(self): + self.serial_read() + print(CV_JSON_START + json.dumps(self.vars) + CV_JSON_END, end="") + + def heart_beat(self): + if time.monotonic() - self.last_time_stamp > UPDATE_PERIOD: + self.update() + self.last_time_stamp = time.monotonic() + + def exit_action(self, text, branch): + try: + # parse + serial_updates_dict = json.loads(branch.strip()) + # check + assert all( + [key in self.vars for key in serial_updates_dict] + ), "get unknown variable names from serial" + # cast type + for key, value in serial_updates_dict.items(): + serial_updates_dict[key] = type(self.vars[key])(value) + # echo update + print(CV_JSON_START + json.dumps(serial_updates_dict) + CV_JSON_END, end="") + # update + self.vars.update(serial_updates_dict) + except Exception as e: + self.serial_updates = "" # clean up bad data + print(e) + + def define(self, var_name, initdata): + """ + define a connected variable + """ + assert type(var_name) == type(""), "var_name should be string" + self.vars[var_name] = initdata + self.update() + + def serial_read(self): + """ + read CDC data from serial buffer if any + don't use input() in other parts of the code + """ + # read from serial + while n_bytes := supervisor.runtime.serial_bytes_available: + self.cv_processor.push([sys.stdin.read(n_bytes)]) + + def read(self, var_names): + """ + read a defined variable or a list of defined variables + """ + # type enforce + ## convert the input to a list if it is not + if type(var_names) != type([]): + var_names = [var_names] + assert all( + [type(name) == type("") for name in var_names] + ), "all names should be strings" + # get updates + self.serial_read() + # get values + output = [self.vars[name] for name in var_names] + if len(output) == 1: + return output[0] + return output + + def write(self, var_names, var_values): + # type enforce + if type(var_names) != type([]): + var_names = [var_names] + var_values = [var_values] + assert all( + [type(name) == type("") for name in var_names] + ), "all names should be strings in python" + assert all( + [ + type(self.vars[name]) == type(value) + for name, value in zip(var_names, var_values) + ] + ), "variable type does not match in python" + # update + updates_dict = {name: value for name, value in zip(var_names, var_values)} + self.vars.update(updates_dict) + # send updates + print(CV_JSON_START + json.dumps(updates_dict) + CV_JSON_END, end="") diff --git a/src/tabs/Widgets/CIRCUITPY/matcher.py b/src/tabs/Widgets/CIRCUITPY/matcher.py new file mode 100644 index 0000000..18d08e1 --- /dev/null +++ b/src/tabs/Widgets/CIRCUITPY/matcher.py @@ -0,0 +1,132 @@ +class State: + def __init__(self, val=0): + self._val = val + self._last = val + + @property + def now(self): + return self._val + + @now.setter + def now(self, val): + self._last = self._val + self._val = val + + @property + def diff(self): + return self._val - self._last + + +class TargetMatcher: + def __init__(self, target=None): + if target is None: + self.clear_target() + else: + self.target = target + self.segment = "" + self.mood = State() + + def push(self, segment): + result = [] + segment = self.segment + segment + self.segment = "" + for i in range(len(segment) - len(self.target), len(segment)): + if i < 0: + continue + tail = segment[i:] + if tail == self.target: + break + if tail == self.target[: len(tail)]: + self.segment = tail + segment = segment[: len(segment) - len(tail)] + break + else: + self.segment = "" + parts = segment.split(self.target) + for i in range(len(parts)): + if i != 0: + self.mood.now = 1 + result.append([self.target, self.mood.now, self.mood.diff]) + if len(parts[i]) > 0: + self.mood.now = 0 + result.append([parts[i], self.mood.now, self.mood.diff]) + return result + + def clear_target(self): + self.target = "You shall not pass! (∩๏‿‿๏)⊃━☆゚.*" + + +class BracketMatcher: + def __init__(self, begin_str, end_str): + self.begin_matcher = TargetMatcher(begin_str) + self.end_matcher = TargetMatcher(end_str) + self.mood = State() + self.matcher = self.begin_matcher + + def push(self, segment): + outlet = [] + parts = self.matcher.push(segment) + while len(parts) > 0: + current = parts.pop(0) + if len(current[0]) == 0: + continue + if current[1] == 0: + outlet.append([current[0], self.mood.now, self.mood.diff]) + self.mood.now = self.mood.now + else: + self.mood.now = 1 - self.mood.now + if self.mood.now == 1: + self.matcher = self.end_matcher + else: + self.matcher = self.begin_matcher + rest = [p[0] for p in parts] + text = "".join(rest) + parts = self.matcher.push(text) + return outlet + + +def none_fun(text, branch): + return None + + +class MatcherProcessor: + def __init__( + self, + matcher, + in_action=none_fun, + enter_action=none_fun, + exit_action=none_fun, + out_action=none_fun, + ): + self.matcher = matcher + self.in_action = in_action + self.enter_action = enter_action + self.exit_action = exit_action + self.out_action = out_action + self.through = False + self.branch = [] + + def push(self, parts): + outlet = [] + for part_in in parts: + for part_out in self.matcher.push(part_in): + text = part_out[0] + mood = part_out[1] + diff = part_out[2] + + # print('debug', part_out) + if diff == 1: + self.enter_action(text, "".join(self.branch)) + if mood == 1: + self.in_action(text, "".join(self.branch)) + if self.through: + outlet.append(text) + else: + self.branch.append(text) + if diff == -1: + self.exit_action(text, "".join(self.branch)) + self.branch = [] + if mood == 0: + self.out_action(text, "".join(self.branch)) + outlet.append(text) + return outlet diff --git a/src/tabs/Widgets/CIRCUITPY/test_connected_variables.py b/src/tabs/Widgets/CIRCUITPY/test_connected_variables.py new file mode 100644 index 0000000..d9fecbb --- /dev/null +++ b/src/tabs/Widgets/CIRCUITPY/test_connected_variables.py @@ -0,0 +1,18 @@ +import time +from connected_variables import ConnectedVariables + +cv = ConnectedVariables() +cv.define("a", 1) +cv.define("b", 1.0) +cv.define("c", [255, 255, 100]) +cv.define("d", "Hello") +cv.write("a", 10) +cv.write(["a", "b"], [100, 0.1]) +print(cv.read("a")) +print(cv.read(["a", "b"])) + +while True: + cv.heart_beat() + cv.write("a", cv.read("a") + 1) + print(cv.read(["a", "b"])) + time.sleep(1) diff --git a/src/tabs/Widgets/CIRCUITPY/test_matcher.py b/src/tabs/Widgets/CIRCUITPY/test_matcher.py new file mode 100644 index 0000000..6ed9e26 --- /dev/null +++ b/src/tabs/Widgets/CIRCUITPY/test_matcher.py @@ -0,0 +1,86 @@ +from matcher import BracketMatcher, TargetMatcher, MatcherProcessor + +# target matcher test start +print("INFO", "test started") +test_target_matcher = TargetMatcher("@#$") + +texts = ["", "12345", "12@#$345", "12345@#", "$12345", "12@#$@#$345", "12345@#$"] + +for text in texts: + parts = test_target_matcher.push(text) + print("DEBUG", [text], parts, test_target_matcher.mood) + +print("INFO", "test ended") +# target matcher test end + +# BracketMatcher test start +print("INFO", "test started") + +test_bracket_matcher = BracketMatcher("{{", "}}") + +texts = ["", "123456", "12{{34}}56", "12{{34}}{{56}}", "12{{3456", "1234}}{{56}}78"] + +for text in texts: + parts = test_bracket_matcher.push(text) + print("DEBUG", [text]) + print("DEBUG", parts) + +print("INFO", "test ended") +# BracketMatcher test end + +echo_matcher = TargetMatcher('print("Hello CircuitPython!")') +echo_processor = MatcherProcessor(echo_matcher) + +fake_echo_matcher = BracketMatcher("{{{", "}}}") +fake_echo_processor = MatcherProcessor(fake_echo_matcher) + +print(echo_processor.push(['print("Hello CircuitPy'])) +print(echo_processor.branch) +print(echo_processor.push(['thon!")', "1234"])) +print(echo_processor.branch) + +print(fake_echo_processor.push(['{{{print("Hello CircuitPy'])) +print(fake_echo_processor.branch) +print(fake_echo_processor.push(['thon!")}}}', "1234"])) +print(fake_echo_processor.branch) + + +def enter_action(text, branch): + print("enter:", text, branch) + + +def in_action(text, branch): + print("in:", text, branch) + + +def exit_action(text, branch): + print("exit:", text, branch) + + +def out_action(text, branch): + print("out:", text, branch) + + +cv_processor = MatcherProcessor( + BracketMatcher("", ""), + enter_action=enter_action, + in_action=in_action, + exit_action=exit_action, + out_action=out_action, +) + +cv_processor.push(["out"]) +cv_processor.push([""]) +cv_processor.push(["in"]) +cv_processor.push([""]) +cv_processor.push(["in"]) +cv_processor.push(["out"]) +cv_processor.push(["in"]) +cv_processor.push([""]) +cv_processor.push(["in"]) +cv_processor.push(["in"]) +cv_processor.push(["in"]) +cv_processor.push(["in"]) +cv_processor.push([""]) +cv_processor.push(["out"]) diff --git a/src/tabs/Widgets/VariableBase.jsx b/src/tabs/Widgets/VariableBase.jsx new file mode 100644 index 0000000..fddbe03 --- /dev/null +++ b/src/tabs/Widgets/VariableBase.jsx @@ -0,0 +1,74 @@ +import { useState, useContext } from "react"; +import { Autocomplete, TextField, Typography, Box } from "@mui/material"; +import { Rnd } from "react-rnd"; +import WidgetContext from "./WidgetsContext"; + +const style = { + border: "solid 1px #ddd", + background: "#f0f0f0", + overflow: "hidden", + borderRadius: "8pt", + padding: "10pt", + touchAction: "none", +}; + +const VariableBase = ({ connectedVariables, widgetTitle, getWidgetProperty, setWidgetProperty, children }) => { + const variableName = getWidgetProperty("variableName"); + const setVariableName = (name) => setWidgetProperty("variableName", name); + const description = getWidgetProperty("description"); + const x = getWidgetProperty("x"); + const setX = (x) => setWidgetProperty("x", x); + const y = getWidgetProperty("y"); + const setY = (y) => setWidgetProperty("y", y); + + const { layoutIsLocked } = useContext(WidgetContext); + + return ( + { + setX(d.x); + setY(d.y); + }} + disableDragging={layoutIsLocked} + enableResizing={false} + > + + + {widgetTitle} + + {description} +
+ { + // return option.label === value + return true; + }} + freeSolo={true} + disableClearable + id="combo-box-demo" + value={variableName} + onChange={(e, newValue) => { + setVariableName(newValue.label); + }} + options={Object.keys(connectedVariables).map((key) => { + return { + label: key, + }; + })} + renderInput={(params) => } + /> +
+ {children} +
+
+ ); +}; +export default VariableBase; diff --git a/src/tabs/Widgets/VariableButton.jsx b/src/tabs/Widgets/VariableButton.jsx new file mode 100644 index 0000000..cefc968 --- /dev/null +++ b/src/tabs/Widgets/VariableButton.jsx @@ -0,0 +1,31 @@ +import Button from "@mui/material/Button"; + +import VariableBase from "./VariableBase"; + +const VariableButton = ({ connectedVariables, setVariableOnMcu, getWidgetProperty, setWidgetProperty }) => { + const variableName = getWidgetProperty("variableName"); + const buttonText = getWidgetProperty("buttonText"); + + return ( + + + + ); +}; +export default VariableButton; diff --git a/src/tabs/Widgets/VariableColorPicker.jsx b/src/tabs/Widgets/VariableColorPicker.jsx new file mode 100644 index 0000000..fd98ea3 --- /dev/null +++ b/src/tabs/Widgets/VariableColorPicker.jsx @@ -0,0 +1,51 @@ +import { useState, useEffect } from "react"; +import { RgbColorPicker } from "react-colorful"; +import { useSlowChangeState } from "./utilities"; +import { NoTheme } from "../../react-lazy-dark-theme"; + +import VariableBase from "./VariableBase"; + +const VariableColorPicker = ({ connectedVariables, setVariableOnMcu, getWidgetProperty, setWidgetProperty }) => { + const variableName = getWidgetProperty("variableName"); + const period = getWidgetProperty("period") === null ? 0.1 : getWidgetProperty("period"); + + const [color, setColor] = useState({ + r: 16, + g: 0, + b: 0, + }); + + // send data on change + const slowColor = useSlowChangeState(color, period); + + const handleSend = (color) => { + setVariableOnMcu(variableName, [color.r, color.g, color.b]); + }; + + useEffect(() => { + handleSend(color); + }, [slowColor]); + + return ( + + + { + handleSend(color); + }} + onMouseLeave={() => { + handleSend(color); + }} + /> + + + ); +}; +export default VariableColorPicker; diff --git a/src/tabs/Widgets/VariableCursor.jsx b/src/tabs/Widgets/VariableCursor.jsx new file mode 100644 index 0000000..8e8c62a --- /dev/null +++ b/src/tabs/Widgets/VariableCursor.jsx @@ -0,0 +1,126 @@ +import { useState, useEffect } from "react"; +import Button from "@mui/material/Button"; + +import { Stage, Layer, Line } from "react-konva"; + +import VariableBase from "./VariableBase"; +import { useSlowChangeState } from "./utilities"; + +function round(num) { + return Math.round(num * 10) / 10; +} + +const VariableCursor = ({ connectedVariables, setVariableOnMcu, getWidgetProperty, setWidgetProperty }) => { + const variableName = getWidgetProperty("variableName"); + + const [tool, setTool] = useState("pen"); + const [lines, setLines] = useState([]); + const [cursorDown, setCursorDown] = useState(false); + + const [pos, setPos] = useState({ + x: 0, + y: 0, + }); + + const xMin = getWidgetProperty("xMin"); + const xMax = getWidgetProperty("xMax"); + const yMin = getWidgetProperty("yMin"); + const yMax = getWidgetProperty("yMax"); + const period = getWidgetProperty("period") === null ? 0.1 : getWidgetProperty("period"); + + const canvasRange = { x: 300, y: (300 / (xMax - xMin)) * (yMax - yMin) }; + + // const canvasRange = { x: 300, y: 300 }; + // send data on change + const slowPos = useSlowChangeState(pos, period); + const slowCursorDown = useSlowChangeState(cursorDown, period); + + useEffect(() => { + setVariableOnMcu(variableName, [ + round((pos.x / canvasRange.x) * (xMax - xMin) + xMin), + round(((canvasRange.y - pos.y) / canvasRange.y) * (yMax - yMin) + yMin), + cursorDown ? 1 : 0, + ]); + }, [slowPos, slowCursorDown]); + + const handleMouseDown = (e) => { + const pos = e.target.getStage().getPointerPosition(); + // send pos + setPos({ + x: pos.x, + y: pos.y, + }); + setCursorDown(true); + + setLines([...lines, { tool, points: [pos.x, pos.y] }]); + }; + + const handleMouseMove = (e) => { + const pos = e.target.getStage().getPointerPosition(); + // send pos + setPos({ + x: pos.x, + y: pos.y, + }); + + // no drawing - skipping + if (!cursorDown) { + return; + } + let lastLine = lines[lines.length - 1]; + // add point + lastLine.points = lastLine.points.concat([pos.x, pos.y]); + + // replace last + lines.splice(lines.length - 1, 1, lastLine); + setLines(lines.concat()); + }; + + const handleMouseUp = () => { + setCursorDown(false); + }; + + return ( + + + + {lines.map((line, i) => ( + + ))} + + + + + ); +}; +export default VariableCursor; diff --git a/src/tabs/Widgets/VariableDisplay.jsx b/src/tabs/Widgets/VariableDisplay.jsx new file mode 100644 index 0000000..464091c --- /dev/null +++ b/src/tabs/Widgets/VariableDisplay.jsx @@ -0,0 +1,17 @@ +import VariableBase from "./VariableBase"; + +const VariableDisplay = ({ connectedVariables, getVariableOnMcu, getWidgetProperty, setWidgetProperty }) => { + const variableName = getWidgetProperty("variableName"); + + return ( + +
{JSON.stringify(getVariableOnMcu(variableName), null, 2)}
+
+ ); +}; +export default VariableDisplay; diff --git a/src/tabs/Widgets/VariableSet.jsx b/src/tabs/Widgets/VariableSet.jsx new file mode 100644 index 0000000..348dc81 --- /dev/null +++ b/src/tabs/Widgets/VariableSet.jsx @@ -0,0 +1,79 @@ +import { useState } from "react"; +import FormControl from "@mui/material/FormControl"; +import TextField from "@mui/material/TextField"; +import InputLabel from "@mui/material/InputLabel"; +import Select from "@mui/material/Select"; +import MenuItem from "@mui/material/MenuItem"; +import Button from "@mui/material/Button"; + +import VariableBase from "./VariableBase"; + +const VariableSet = ({ connectedVariables, setVariableOnMcu, getWidgetProperty, setWidgetProperty }) => { + const variableName = getWidgetProperty("variableName"); + const type = getWidgetProperty("type"); + const setType = (type) => { + setWidgetProperty("type", type); + }; + const [value, setValue] = useState("0"); + + const handleSubmit = (event) => { + event.preventDefault(); + let variableValue; + if (type === "int") { + variableValue = parseInt(value); + } else if (type === "float") { + variableValue = parseFloat(value); + } else if (type === "string") { + variableValue = String(value); + } else if (type === "bool") { + variableValue = value.trim().toLowerCase() === "true" ? true : false; + } else if (type === "json") { + try { + variableValue = JSON.parse(value); + } catch { + alert("Input is not a valid json"); + } + } + setVariableOnMcu(variableName, variableValue); + // don't up date variable value on web directly, let the change reflected by update echo + }; + return ( + + { + setValue(event.target.value); + }} + label="value" + > +
+ + type + + + + +
+ ); +}; +export default VariableSet; diff --git a/src/tabs/Widgets/VariableSlider.jsx b/src/tabs/Widgets/VariableSlider.jsx new file mode 100644 index 0000000..0cd6bc3 --- /dev/null +++ b/src/tabs/Widgets/VariableSlider.jsx @@ -0,0 +1,48 @@ +import { useState, useEffect } from "react"; +import Slider from "@mui/material/Slider"; +import VariableBase from "./VariableBase"; +import { useSlowChangeState } from "./utilities"; + +const VariableSlider = ({ connectedVariables, setVariableOnMcu, getWidgetProperty, setWidgetProperty }) => { + const rangeMin = getWidgetProperty("rangeMin"); + const rangeMax = getWidgetProperty("rangeMax"); + const step = getWidgetProperty("step"); + const value = getWidgetProperty("set"); + const setValue = (value) => { + setWidgetProperty("set", value); + }; + const variableName = getWidgetProperty("variableName"); + const period = getWidgetProperty("period") === null ? 0.2 : getWidgetProperty("period"); + + // const [value, setValue] = useState(-1); + const slowValue = useSlowChangeState(value, period); + + useEffect(() => { + setVariableOnMcu(variableName, value); + }, [slowValue]); + + return ( + + { + setValue(event.target.value); + }} + valueLabelDisplay="on" + onMouseUp={() => { + setVariableOnMcu(variableName, value); + }} + /> + + ); +}; +export default VariableSlider; diff --git a/src/tabs/Widgets/VariableSliderReadOnly.jsx b/src/tabs/Widgets/VariableSliderReadOnly.jsx new file mode 100644 index 0000000..e5df888 --- /dev/null +++ b/src/tabs/Widgets/VariableSliderReadOnly.jsx @@ -0,0 +1,27 @@ +import Slider from "@mui/material/Slider"; +import VariableBase from "./VariableBase"; + +const VariableSliderReadOnly = ({ connectedVariables, getVariableOnMcu, getWidgetProperty, setWidgetProperty }) => { + const rangeMin = getWidgetProperty("rangeMin"); + const rangeMax = getWidgetProperty("rangeMax"); + const variableName = getWidgetProperty("variableName"); + + return ( + + + + ); +}; +export default VariableSliderReadOnly; diff --git a/src/tabs/Widgets/WidgetSchema.json b/src/tabs/Widgets/WidgetSchema.json new file mode 100644 index 0000000..31bfea2 --- /dev/null +++ b/src/tabs/Widgets/WidgetSchema.json @@ -0,0 +1,238 @@ +{ + "title": "Widgets Configuration", + "type": "array", + "items": { + "type": "object", + "anyOf": [ + { + "title": "Display", + "properties": { + "widgetType": { + "type": "string", + "default": "Display", + "readOnly": true + }, + "variableName": { + "type": "string" + }, + "description": { + "type": "string" + }, + "x": { + "type": "number", + "default": 30 + }, + "y": { + "type": "number", + "default": 30 + } + } + }, + { + "title": "Set", + "properties": { + "widgetType": { + "type": "string", + "default": "Set", + "readOnly": true + }, + "variableName": { + "type": "string" + }, + "description": { + "type": "string" + }, + "x": { + "type": "number", + "default": 30 + }, + "y": { + "type": "number", + "default": 30 + }, + "type": { + "type": "string", + "enum": ["int", "float", "string", "bool", "json"], + "default": "int" + } + } + }, + { + "title": "Cursor", + "properties": { + "widgetType": { + "type": "string", + "default": "Cursor", + "readOnly": true + }, + "variableName": { + "type": "string" + }, + "description": { + "type": "string" + }, + "x": { + "type": "number", + "default": 30 + }, + "y": { + "type": "number", + "default": 30 + }, + "xMin": { + "type": "number", + "default": 0 + }, + "xMax": { + "type": "number", + "default": 10 + }, + "yMin": { + "type": "number", + "default": 0 + }, + "yMax": { + "type": "number", + "default": 10 + }, + "period": { + "type": "number", + "default": 0.15 + } + } + }, + { + "title": "Slider", + "properties": { + "widgetType": { + "type": "string", + "default": "Slider", + "readOnly": true + }, + "variableName": { + "type": "string" + }, + "description": { + "type": "string" + }, + "x": { + "type": "number", + "default": 30 + }, + "y": { + "type": "number", + "default": 30 + }, + "rangeMin": { + "type": "number", + "default": 0 + }, + "rangeMax": { + "type": "number", + "default": 10 + }, + "step": { + "type": "number", + "default": 1 + }, + "set": { + "type": "number", + "default": 5 + }, + "period": { + "type": "number", + "default": 0.2 + } + } + }, + { + "title": "SliderReadOnly", + "properties": { + "widgetType": { + "type": "string", + "default": "SliderReadOnly", + "readOnly": true + }, + "variableName": { + "type": "string" + }, + "description": { + "type": "string" + }, + "x": { + "type": "number", + "default": 30 + }, + "y": { + "type": "number", + "default": 30 + }, + "rangeMin": { + "type": "number", + "default": 0 + }, + "rangeMax": { + "type": "number", + "default": 10 + } + } + }, + { + "title": "ColorPicker", + "properties": { + "widgetType": { + "type": "string", + "default": "ColorPicker", + "readOnly": true + }, + "variableName": { + "type": "string" + }, + "description": { + "type": "string" + }, + "x": { + "type": "number", + "default": 30 + }, + "y": { + "type": "number", + "default": 30 + }, + "period": { + "type": "number", + "default": 0.1 + } + } + }, + { + "title": "Button", + "properties": { + "widgetType": { + "type": "string", + "default": "Button", + "readOnly": true + }, + "variableName": { + "type": "string" + }, + "description": { + "type": "string" + }, + "x": { + "type": "number", + "default": 30 + }, + "y": { + "type": "number", + "default": 30 + }, + "buttonText": { + "type": "string", + "default": "Button" + } + } + } + ] + } +} diff --git a/src/tabs/Widgets/Widgets.jsx b/src/tabs/Widgets/Widgets.jsx new file mode 100644 index 0000000..3624d7a --- /dev/null +++ b/src/tabs/Widgets/Widgets.jsx @@ -0,0 +1,229 @@ +import useConnectedVariables from "./useConnectedVariables"; +import { useContext, useEffect, useState } from "react"; +import ideContext from "../../ideContext"; +import useVariableWidgets from "./useVariableWidgets"; +import VariableSet from "./VariableSet"; +import VariableDisplay from "./VariableDisplay"; +import VariableCursor from "./VariableCursor"; +import VariableSlider from "./VariableSlider"; +import VariableSliderReadOnly from "./VariableSliderReadOnly"; +import VariableColorPicker from "./VariableColorPicker"; +import VariableButton from "./VariableButton"; +import { Typography, Toolbar, Tooltip, Button, Box } from "@mui/material"; +import { Menu } from "../../layout/Menu"; +import { writeToPath, getFromPath } from "../../react-local-file-system"; +import connected_variables from "./CIRCUITPY/connected_variables.py"; +import matcher from "./CIRCUITPY/matcher.py"; +import WidgetContext from "./WidgetsContext"; +import WidgetsConfig from "./WidgetsConfig"; + +import LockOpenOutlinedIcon from "@mui/icons-material/LockOpenOutlined"; +import LockOutlinedIcon from "@mui/icons-material/LockOutlined"; +import { IconButton } from "@mui/material"; + +export default function Widgets({ node }) { + const { rootDirHandle } = useContext(ideContext); + const { serialOutput, sendDataToSerialPort } = useContext(ideContext); + const { setVariableOnMcu, getVariableOnMcu, connectedVariables } = useConnectedVariables( + serialOutput, + sendDataToSerialPort + ); + const { variableWidgets, setVariableWidgets, getWidgetProperty, setWidgetProperty } = useVariableWidgets(); + const [layoutIsLocked, setLayoutIsLocked] = useState(false); + const [showConfig, setShowConfig] = useState(false); + + function toggleLayout() { + console.log("toggleLayout"); + setLayoutIsLocked((state) => { + console.log(state); + return !state; + }); + } + + function toggleEdit() { + console.log("toggleLayout"); + setShowConfig((state) => { + console.log(state); + return !state; + }); + } + + const height = node.getRect().height; + + // // debug + // useEffect(() => { + // console.log(connectedVariables); + // }, [connectedVariables]); + // useEffect(() => { + // console.log(variableWidgets); + // }, [variableWidgets]); + + const hiddenMenuLabelOptions = [ + { + text: "Help", + handler: () => {}, + }, + { + text: "Install Library", + handler: async () => { + await writeToPath(rootDirHandle, "/lib/connected_variables.py", connected_variables); + await writeToPath(rootDirHandle, "/lib/matcher.py", matcher); + }, + }, + { + text: "Save Widgets", + handler: async () => { + await writeToPath(rootDirHandle, "/ide/widgets.json", JSON.stringify(variableWidgets, null, 2)); + }, + }, + { + text: "Load Widgets", + handler: async () => { + const loadedText = await getFromPath(rootDirHandle, "/ide/widgets.json"); + setVariableWidgets(JSON.parse(loadedText)); + }, + }, + ]; + + return ( + + +
+
+ + {/* Title */} + +
+
+ + + + + {layoutIsLocked ? : } + + + + + +
+
+ {showConfig ? ( + + + + ) : ( +
+ {variableWidgets.map((w) => { + if (w.widgetType === "Set") { + return ( + getWidgetProperty(w.id, propertyName)} + setWidgetProperty={(propertyName, newValue) => + setWidgetProperty(w.id, propertyName, newValue) + } + /> + ); + } else if (w.widgetType === "Display") { + return ( + getWidgetProperty(w.id, propertyName)} + setWidgetProperty={(propertyName, newValue) => + setWidgetProperty(w.id, propertyName, newValue) + } + /> + ); + } else if (w.widgetType === "Cursor") { + return ( + getWidgetProperty(w.id, propertyName)} + setWidgetProperty={(propertyName, newValue) => + setWidgetProperty(w.id, propertyName, newValue) + } + /> + ); + } else if (w.widgetType === "Slider") { + return ( + getWidgetProperty(w.id, propertyName)} + setWidgetProperty={(propertyName, newValue) => + setWidgetProperty(w.id, propertyName, newValue) + } + /> + ); + } else if (w.widgetType === "SliderReadOnly") { + return ( + getWidgetProperty(w.id, propertyName)} + setWidgetProperty={(propertyName, newValue) => + setWidgetProperty(w.id, propertyName, newValue) + } + /> + ); + } else if (w.widgetType === "ColorPicker") { + return ( + getWidgetProperty(w.id, propertyName)} + setWidgetProperty={(propertyName, newValue) => + setWidgetProperty(w.id, propertyName, newValue) + } + /> + ); + } else if (w.widgetType === "Button") { + return ( + getWidgetProperty(w.id, propertyName)} + setWidgetProperty={(propertyName, newValue) => + setWidgetProperty(w.id, propertyName, newValue) + } + /> + ); + } + })} +
+ )} +
+
+ ); +} diff --git a/src/tabs/Widgets/WidgetsConfig.jsx b/src/tabs/Widgets/WidgetsConfig.jsx new file mode 100644 index 0000000..e545fa6 --- /dev/null +++ b/src/tabs/Widgets/WidgetsConfig.jsx @@ -0,0 +1,24 @@ +import Form from "@rjsf/mui"; +import validator from "@rjsf/validator-ajv8"; +import schema from "./WidgetSchema.json"; +import uiSchema from "./uiSchema.json"; + +export default function WidgetsConfig({ variableWidgets, setVariableWidgets }) { + function handleSubmit(e) { + setVariableWidgets( + e.formData.map((x, i) => { + return { id: i, ...x }; + }) + ); + } + return ( +
+ ); +} diff --git a/src/tabs/Widgets/WidgetsContext.jsx b/src/tabs/Widgets/WidgetsContext.jsx new file mode 100644 index 0000000..493a0d5 --- /dev/null +++ b/src/tabs/Widgets/WidgetsContext.jsx @@ -0,0 +1,5 @@ +import { createContext } from "react"; + +const WidgetContext = createContext(); + +export default WidgetContext; diff --git a/src/tabs/Widgets/index.jsx b/src/tabs/Widgets/index.jsx new file mode 100644 index 0000000..5cee876 --- /dev/null +++ b/src/tabs/Widgets/index.jsx @@ -0,0 +1,3 @@ +import Widgets from "./Widgets"; + +export default Widgets; diff --git a/src/tabs/Widgets/uiSchema.json b/src/tabs/Widgets/uiSchema.json new file mode 100644 index 0000000..5e8a958 --- /dev/null +++ b/src/tabs/Widgets/uiSchema.json @@ -0,0 +1,5 @@ +{ + "ui:submitButtonOptions": { + "submitText": "Apply" + } +} \ No newline at end of file diff --git a/src/tabs/Widgets/useConnectedVariables.js b/src/tabs/Widgets/useConnectedVariables.js new file mode 100644 index 0000000..b979602 --- /dev/null +++ b/src/tabs/Widgets/useConnectedVariables.js @@ -0,0 +1,34 @@ +import { useState, useEffect } from "react"; +import { CV_JSON_START, CV_JSON_END, LINE_END, SOFT_REBOOT } from "../../constants"; +import { matchesInBetween } from "../../serial/textProcessor"; + +function getLatestSession(dataFromMcu) { + return dataFromMcu.split(SOFT_REBOOT).at(-1); +} + +const aggregateConnectedVariable = (text) => { + const cvBlocks = matchesInBetween(text, CV_JSON_START, CV_JSON_END); + var ConnectedVariable = {}; + for (const b of cvBlocks) { + ConnectedVariable = { ...ConnectedVariable, ...JSON.parse(b) }; + } + return ConnectedVariable; +}; + +export default function useConnectedVariables(dataFromMcu, sendDataToMcu) { + const [connectedVariables, setConnectedVariables] = useState({}); + + useEffect(() => { + setConnectedVariables(aggregateConnectedVariable(getLatestSession(dataFromMcu))); + }, [dataFromMcu]); + + function getVariableOnMcu(variableName) { + return connectedVariables[variableName]; + } + + function setVariableOnMcu(variableName, variableValue) { + const updatedVariable = { [variableName]: variableValue }; + sendDataToMcu(CV_JSON_START + JSON.stringify(updatedVariable) + CV_JSON_END + LINE_END); + } + return { setVariableOnMcu, getVariableOnMcu, connectedVariables }; +} diff --git a/src/tabs/Widgets/useVariableWidgets.js b/src/tabs/Widgets/useVariableWidgets.js new file mode 100644 index 0000000..96e38fc --- /dev/null +++ b/src/tabs/Widgets/useVariableWidgets.js @@ -0,0 +1,104 @@ +import { useState } from "react"; +export default function useVariableWidgets() { + // planned feature + const [variableWidgets, setVariableWidgets] = useState([ + // // Examples + // { + // id: 1, + // widgetType: "Set", + // variableName: "a", + // description: "set a test variable", + // x: 30, + // y: 30, + // type: "int", + // }, + // { + // id: 2, + // widgetType: "Display", + // variableName: "a", + // description: "display a test variable", + // x: 30, + // y: 30, + // }, + // { + // id: 3, + // widgetType: "Cursor", + // variableName: "draw_pos", + // description: "control the drawing robot", + // x: 30, + // y: 30, + // x_min: -25, + // x_max: 15, + // y_min: 45, + // y_max: 85, + // }, + // { + // id: 4, + // widgetType: "Slider", + // variableName: "thr", + // description: "volume threshold", + // x: 30, + // y: 30, + // rangeMin: 0, + // rangeMax: 15, + // step: 0.1, + // set: 7, + // }, + // { + // id: 5, + // widgetType: "SliderReadOnly", + // variableName: "vol", + // description: "volume", + // x: 30, + // y: 30, + // rangeMin: 0, + // rangeMax: 15, + // }, + // { + // id: 6, + // widgetType: "Color", + // variableName: "cur_color", + // description: "Color of the cursor", + // x: 30, + // y: 30, + // }, + // { + // id: 7, + // widgetType: "Button", + // variableName: "clear", + // description: "Color of the cursor", + // x: 30, + // y: 30, + // buttonText: "Clear" + // }, + ]); + + function getWidget(widgets, id) { + return widgets.filter((w) => { + return w.id === id; + })[0]; + } + + function getWidgetProperty(id, propertyName) { + try { + return getWidget(variableWidgets, id)[propertyName]; + } catch (e) { + console.error(e); + } + } + + function setWidgetProperty(id, propertyName, newValue) { + setVariableWidgets((widgets) => { + return [ + ...widgets.filter((w) => { + return w.id !== id; + }), + { + ...getWidget(widgets, id), + [propertyName]: newValue, + }, + ]; + }); + } + return { variableWidgets, setVariableWidgets, getWidgetProperty, setWidgetProperty }; +} diff --git a/src/tabs/Widgets/utilities.js b/src/tabs/Widgets/utilities.js new file mode 100644 index 0000000..3c9d50f --- /dev/null +++ b/src/tabs/Widgets/utilities.js @@ -0,0 +1,17 @@ +import { useState, useEffect } from "react"; + +export const useSlowChangeState = (inState, interval) => { + const [lastTime, setLastTime] = useState(new Date()); + const [outState, setOutState] = useState(inState); + + useEffect(() => { + const curTime = new Date(); + const timeDiff = (curTime - lastTime) / 1000; + if (timeDiff > interval) { + setOutState(inState); + setLastTime(curTime); + } + }, [inState]); + + return outState; +}; diff --git a/vite.config.js b/vite.config.js index 327ac81..56d7699 100644 --- a/vite.config.js +++ b/vite.config.js @@ -10,9 +10,9 @@ export default build_config["single-file"] react(), viteSingleFile(), { - name: "markdown-loader", + name: "text-loader", transform(code, id) { - if (id.slice(-3) === ".md") { + if (id.slice(-3).toLowerCase() === ".md" || id.slice(-3).toLowerCase() === ".py") { // For .md files, get the raw content return `export default ${JSON.stringify(code)};`; } @@ -28,9 +28,9 @@ export default build_config["single-file"] plugins: [ react(), { - name: "markdown-loader", + name: "text-loader", transform(code, id) { - if (id.slice(-3) === ".md") { + if (id.slice(-3).toLowerCase() === ".md" || id.slice(-3).toLowerCase() === ".py") { // For .md files, get the raw content return `export default ${JSON.stringify(code)};`; }