diff --git a/package.json b/package.json
index 849b152..570c983 100644
--- a/package.json
+++ b/package.json
@@ -14,7 +14,11 @@
"make:windows": "electron-forge make --platform=win32",
"make:mac": "electron-forge make --platform=darwin",
"format": "pnpm exec biome check --write",
- "react-dev": "npx webpack serve --config webpack.dev.config.ts"
+ "react-dev": "npx webpack serve --config webpack.dev.config.ts",
+ "test": "vitest",
+ "test:watch": "vitest --watch",
+ "test:ui": "vitest --ui",
+ "test:coverage": "vitest --coverage"
},
"keywords": [],
"license": "O'Saasy",
@@ -34,19 +38,25 @@
"@electron-forge/maker-squirrel": "^7.8.0",
"@electron-forge/maker-zip": "^7.8.0",
"@electron-forge/plugin-webpack": "^7.8.0",
+ "@testing-library/jest-dom": "^6.9.1",
+ "@testing-library/react": "^16.3.2",
"@types/node": "^22.13.14",
"@types/node-cron": "^3.0.11",
"@types/react": "^19.0.12",
"@types/react-dom": "^19.0.4",
"@vercel/webpack-asset-relocator-loader": "1.7.3",
+ "@vitejs/plugin-react": "^5.1.4",
"css-loader": "^7.1.2",
"electron": "^35.1.2",
+ "happy-dom": "^20.7.0",
+ "jsdom": "^28.1.0",
"node-loader": "^2.1.0",
"postcss-loader": "^8.1.1",
"style-loader": "^4.0.0",
"ts-loader": "^9.5.2",
"ts-node": "^10.9.2",
"typescript": "~5.8.2",
+ "vitest": "^4.0.18",
"webpack-cli": "^6.0.1"
},
"dependencies": {
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 1966a1a..e4373b9 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -108,6 +108,12 @@ importers:
'@electron-forge/plugin-webpack':
specifier: ^7.8.0
version: 7.10.2(webpack-cli@6.0.1)
+ '@testing-library/jest-dom':
+ specifier: ^6.9.1
+ version: 6.9.1
+ '@testing-library/react':
+ specifier: ^16.3.2
+ version: 16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.2(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)
'@types/node':
specifier: ^22.13.14
version: 22.18.13
@@ -123,12 +129,21 @@ importers:
'@vercel/webpack-asset-relocator-loader':
specifier: 1.7.3
version: 1.7.3
+ '@vitejs/plugin-react':
+ specifier: ^5.1.4
+ version: 5.1.4(vite@7.3.1(@types/node@22.18.13)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0))
css-loader:
specifier: ^7.1.2
version: 7.1.2(webpack@5.102.1)
electron:
specifier: ^35.1.2
version: 35.7.5
+ happy-dom:
+ specifier: ^20.7.0
+ version: 20.7.0
+ jsdom:
+ specifier: ^28.1.0
+ version: 28.1.0
node-loader:
specifier: ^2.1.0
version: 2.1.0(webpack@5.102.1)
@@ -147,24 +162,126 @@ importers:
typescript:
specifier: ~5.8.2
version: 5.8.3
+ vitest:
+ specifier: ^4.0.18
+ version: 4.0.18(@types/node@22.18.13)(happy-dom@20.7.0)(jiti@2.6.1)(jsdom@28.1.0)(lightningcss@1.30.2)(terser@5.44.0)
webpack-cli:
specifier: ^6.0.1
version: 6.0.1(webpack@5.102.1)
packages:
+ '@acemir/cssom@0.9.31':
+ resolution: {integrity: sha512-ZnR3GSaH+/vJ0YlHau21FjfLYjMpYVIzTD8M8vIEQvIGxeOXyXdzCI140rrCY862p/C/BbzWsjc1dgnM9mkoTA==}
+
+ '@adobe/css-tools@4.4.4':
+ resolution: {integrity: sha512-Elp+iwUx5rN5+Y8xLt5/GRoG20WGoDCQ/1Fb+1LiGtvwbDavuSk0jhD/eZdckHAuzcDzccnkv+rEjyWfRx18gg==}
+
'@alloc/quick-lru@5.2.0':
resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==}
engines: {node: '>=10'}
+ '@asamuzakjp/css-color@5.0.1':
+ resolution: {integrity: sha512-2SZFvqMyvboVV1d15lMf7XiI3m7SDqXUuKaTymJYLN6dSGadqp+fVojqJlVoMlbZnlTmu3S0TLwLTJpvBMO1Aw==}
+ engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0}
+
+ '@asamuzakjp/dom-selector@6.8.1':
+ resolution: {integrity: sha512-MvRz1nCqW0fsy8Qz4dnLIvhOlMzqDVBabZx6lH+YywFDdjXhMY37SmpV1XFX3JzG5GWHn63j6HX6QPr3lZXHvQ==}
+
+ '@asamuzakjp/nwsapi@2.3.9':
+ resolution: {integrity: sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==}
+
'@babel/code-frame@7.27.1':
resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==}
engines: {node: '>=6.9.0'}
+ '@babel/code-frame@7.29.0':
+ resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/compat-data@7.29.0':
+ resolution: {integrity: sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/core@7.29.0':
+ resolution: {integrity: sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/generator@7.29.1':
+ resolution: {integrity: sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-compilation-targets@7.28.6':
+ resolution: {integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-globals@7.28.0':
+ resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-module-imports@7.28.6':
+ resolution: {integrity: sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-module-transforms@7.28.6':
+ resolution: {integrity: sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
+ '@babel/helper-plugin-utils@7.28.6':
+ resolution: {integrity: sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-string-parser@7.27.1':
+ resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==}
+ engines: {node: '>=6.9.0'}
+
'@babel/helper-validator-identifier@7.28.5':
resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==}
engines: {node: '>=6.9.0'}
+ '@babel/helper-validator-option@7.27.1':
+ resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helpers@7.28.6':
+ resolution: {integrity: sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/parser@7.29.0':
+ resolution: {integrity: sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==}
+ engines: {node: '>=6.0.0'}
+ hasBin: true
+
+ '@babel/plugin-transform-react-jsx-self@7.27.1':
+ resolution: {integrity: sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-react-jsx-source@7.27.1':
+ resolution: {integrity: sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/runtime@7.28.6':
+ resolution: {integrity: sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/template@7.28.6':
+ resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/traverse@7.29.0':
+ resolution: {integrity: sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/types@7.29.0':
+ resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==}
+ engines: {node: '>=6.9.0'}
+
'@biomejs/biome@2.3.8':
resolution: {integrity: sha512-Qjsgoe6FEBxWAUzwFGFrB+1+M8y/y5kwmg5CHac+GSVOdmOIqsAiXM5QMVGZJ1eCUCLlPZtq4aFAQ0eawEUuUA==}
engines: {node: '>=14.21.3'}
@@ -187,24 +304,28 @@ packages:
engines: {node: '>=14.21.3'}
cpu: [arm64]
os: [linux]
+ libc: [musl]
'@biomejs/cli-linux-arm64@2.3.8':
resolution: {integrity: sha512-Uo1OJnIkJgSgF+USx970fsM/drtPcQ39I+JO+Fjsaa9ZdCN1oysQmy6oAGbyESlouz+rzEckLTF6DS7cWse95g==}
engines: {node: '>=14.21.3'}
cpu: [arm64]
os: [linux]
+ libc: [glibc]
'@biomejs/cli-linux-x64-musl@2.3.8':
resolution: {integrity: sha512-YGLkqU91r1276uwSjiUD/xaVikdxgV1QpsicT0bIA1TaieM6E5ibMZeSyjQ/izBn4tKQthUSsVZacmoJfa3pDA==}
engines: {node: '>=14.21.3'}
cpu: [x64]
os: [linux]
+ libc: [musl]
'@biomejs/cli-linux-x64@2.3.8':
resolution: {integrity: sha512-QDPMD5bQz6qOVb3kiBui0zKZXASLo0NIQ9JVJio5RveBEFgDgsvJFUvZIbMbUZT3T00M/1wdzwWXk4GIh0KaAw==}
engines: {node: '>=14.21.3'}
cpu: [x64]
os: [linux]
+ libc: [glibc]
'@biomejs/cli-win32-arm64@2.3.8':
resolution: {integrity: sha512-H4IoCHvL1fXKDrTALeTKMiE7GGWFAraDwBYFquE/L/5r1927Te0mYIGseXi4F+lrrwhSWbSGt5qPFswNoBaCxg==}
@@ -218,10 +339,45 @@ packages:
cpu: [x64]
os: [win32]
+ '@bramus/specificity@2.4.2':
+ resolution: {integrity: sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw==}
+ hasBin: true
+
'@cspotcode/source-map-support@0.8.1':
resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==}
engines: {node: '>=12'}
+ '@csstools/color-helpers@6.0.2':
+ resolution: {integrity: sha512-LMGQLS9EuADloEFkcTBR3BwV/CGHV7zyDxVRtVDTwdI2Ca4it0CCVTT9wCkxSgokjE5Ho41hEPgb8OEUwoXr6Q==}
+ engines: {node: '>=20.19.0'}
+
+ '@csstools/css-calc@3.1.1':
+ resolution: {integrity: sha512-HJ26Z/vmsZQqs/o3a6bgKslXGFAungXGbinULZO3eMsOyNJHeBBZfup5FiZInOghgoM4Hwnmw+OgbJCNg1wwUQ==}
+ engines: {node: '>=20.19.0'}
+ peerDependencies:
+ '@csstools/css-parser-algorithms': ^4.0.0
+ '@csstools/css-tokenizer': ^4.0.0
+
+ '@csstools/css-color-parser@4.0.2':
+ resolution: {integrity: sha512-0GEfbBLmTFf0dJlpsNU7zwxRIH0/BGEMuXLTCvFYxuL1tNhqzTbtnFICyJLTNK4a+RechKP75e7w42ClXSnJQw==}
+ engines: {node: '>=20.19.0'}
+ peerDependencies:
+ '@csstools/css-parser-algorithms': ^4.0.0
+ '@csstools/css-tokenizer': ^4.0.0
+
+ '@csstools/css-parser-algorithms@4.0.0':
+ resolution: {integrity: sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==}
+ engines: {node: '>=20.19.0'}
+ peerDependencies:
+ '@csstools/css-tokenizer': ^4.0.0
+
+ '@csstools/css-syntax-patches-for-csstree@1.0.28':
+ resolution: {integrity: sha512-1NRf1CUBjnr3K7hu8BLxjQrKCxEe8FP/xmPTenAxCRZWVLbmGotkFvG9mfNpjA6k7Bw1bw4BilZq9cu19RA5pg==}
+
+ '@csstools/css-tokenizer@4.0.0':
+ resolution: {integrity: sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==}
+ engines: {node: '>=20.19.0'}
+
'@date-fns/tz@1.4.1':
resolution: {integrity: sha512-P5LUNhtbj6YfI3iJjw5EL9eUAG6OitD0W3fWQcpQjDRc/QIsL0tRNuO1PcDvPccWL1fSTXXdE1ds+l95DV/OFA==}
@@ -353,6 +509,171 @@ packages:
engines: {node: '>=14.14'}
hasBin: true
+ '@esbuild/aix-ppc64@0.27.3':
+ resolution: {integrity: sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==}
+ engines: {node: '>=18'}
+ cpu: [ppc64]
+ os: [aix]
+
+ '@esbuild/android-arm64@0.27.3':
+ resolution: {integrity: sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [android]
+
+ '@esbuild/android-arm@0.27.3':
+ resolution: {integrity: sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==}
+ engines: {node: '>=18'}
+ cpu: [arm]
+ os: [android]
+
+ '@esbuild/android-x64@0.27.3':
+ resolution: {integrity: sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [android]
+
+ '@esbuild/darwin-arm64@0.27.3':
+ resolution: {integrity: sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@esbuild/darwin-x64@0.27.3':
+ resolution: {integrity: sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@esbuild/freebsd-arm64@0.27.3':
+ resolution: {integrity: sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [freebsd]
+
+ '@esbuild/freebsd-x64@0.27.3':
+ resolution: {integrity: sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@esbuild/linux-arm64@0.27.3':
+ resolution: {integrity: sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@esbuild/linux-arm@0.27.3':
+ resolution: {integrity: sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==}
+ engines: {node: '>=18'}
+ cpu: [arm]
+ os: [linux]
+
+ '@esbuild/linux-ia32@0.27.3':
+ resolution: {integrity: sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==}
+ engines: {node: '>=18'}
+ cpu: [ia32]
+ os: [linux]
+
+ '@esbuild/linux-loong64@0.27.3':
+ resolution: {integrity: sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==}
+ engines: {node: '>=18'}
+ cpu: [loong64]
+ os: [linux]
+
+ '@esbuild/linux-mips64el@0.27.3':
+ resolution: {integrity: sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==}
+ engines: {node: '>=18'}
+ cpu: [mips64el]
+ os: [linux]
+
+ '@esbuild/linux-ppc64@0.27.3':
+ resolution: {integrity: sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==}
+ engines: {node: '>=18'}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@esbuild/linux-riscv64@0.27.3':
+ resolution: {integrity: sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==}
+ engines: {node: '>=18'}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@esbuild/linux-s390x@0.27.3':
+ resolution: {integrity: sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==}
+ engines: {node: '>=18'}
+ cpu: [s390x]
+ os: [linux]
+
+ '@esbuild/linux-x64@0.27.3':
+ resolution: {integrity: sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [linux]
+
+ '@esbuild/netbsd-arm64@0.27.3':
+ resolution: {integrity: sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [netbsd]
+
+ '@esbuild/netbsd-x64@0.27.3':
+ resolution: {integrity: sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [netbsd]
+
+ '@esbuild/openbsd-arm64@0.27.3':
+ resolution: {integrity: sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [openbsd]
+
+ '@esbuild/openbsd-x64@0.27.3':
+ resolution: {integrity: sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [openbsd]
+
+ '@esbuild/openharmony-arm64@0.27.3':
+ resolution: {integrity: sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [openharmony]
+
+ '@esbuild/sunos-x64@0.27.3':
+ resolution: {integrity: sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [sunos]
+
+ '@esbuild/win32-arm64@0.27.3':
+ resolution: {integrity: sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@esbuild/win32-ia32@0.27.3':
+ resolution: {integrity: sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==}
+ engines: {node: '>=18'}
+ cpu: [ia32]
+ os: [win32]
+
+ '@esbuild/win32-x64@0.27.3':
+ resolution: {integrity: sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [win32]
+
+ '@exodus/bytes@1.14.1':
+ resolution: {integrity: sha512-OhkBFWI6GcRMUroChZiopRiSp2iAMvEBK47NhJooDqz1RERO4QuZIZnjP63TXX8GAiLABkYmX+fuQsdJ1dd2QQ==}
+ engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0}
+ peerDependencies:
+ '@noble/hashes': ^1.8.0 || ^2.0.0
+ peerDependenciesMeta:
+ '@noble/hashes':
+ optional: true
+
'@floating-ui/core@1.7.3':
resolution: {integrity: sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==}
@@ -1233,6 +1554,147 @@ packages:
react-redux:
optional: true
+ '@rolldown/pluginutils@1.0.0-rc.3':
+ resolution: {integrity: sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==}
+
+ '@rollup/rollup-android-arm-eabi@4.59.0':
+ resolution: {integrity: sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==}
+ cpu: [arm]
+ os: [android]
+
+ '@rollup/rollup-android-arm64@4.59.0':
+ resolution: {integrity: sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==}
+ cpu: [arm64]
+ os: [android]
+
+ '@rollup/rollup-darwin-arm64@4.59.0':
+ resolution: {integrity: sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@rollup/rollup-darwin-x64@4.59.0':
+ resolution: {integrity: sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==}
+ cpu: [x64]
+ os: [darwin]
+
+ '@rollup/rollup-freebsd-arm64@4.59.0':
+ resolution: {integrity: sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==}
+ cpu: [arm64]
+ os: [freebsd]
+
+ '@rollup/rollup-freebsd-x64@4.59.0':
+ resolution: {integrity: sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@rollup/rollup-linux-arm-gnueabihf@4.59.0':
+ resolution: {integrity: sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==}
+ cpu: [arm]
+ os: [linux]
+ libc: [glibc]
+
+ '@rollup/rollup-linux-arm-musleabihf@4.59.0':
+ resolution: {integrity: sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==}
+ cpu: [arm]
+ os: [linux]
+ libc: [musl]
+
+ '@rollup/rollup-linux-arm64-gnu@4.59.0':
+ resolution: {integrity: sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==}
+ cpu: [arm64]
+ os: [linux]
+ libc: [glibc]
+
+ '@rollup/rollup-linux-arm64-musl@4.59.0':
+ resolution: {integrity: sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==}
+ cpu: [arm64]
+ os: [linux]
+ libc: [musl]
+
+ '@rollup/rollup-linux-loong64-gnu@4.59.0':
+ resolution: {integrity: sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==}
+ cpu: [loong64]
+ os: [linux]
+ libc: [glibc]
+
+ '@rollup/rollup-linux-loong64-musl@4.59.0':
+ resolution: {integrity: sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==}
+ cpu: [loong64]
+ os: [linux]
+ libc: [musl]
+
+ '@rollup/rollup-linux-ppc64-gnu@4.59.0':
+ resolution: {integrity: sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==}
+ cpu: [ppc64]
+ os: [linux]
+ libc: [glibc]
+
+ '@rollup/rollup-linux-ppc64-musl@4.59.0':
+ resolution: {integrity: sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==}
+ cpu: [ppc64]
+ os: [linux]
+ libc: [musl]
+
+ '@rollup/rollup-linux-riscv64-gnu@4.59.0':
+ resolution: {integrity: sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==}
+ cpu: [riscv64]
+ os: [linux]
+ libc: [glibc]
+
+ '@rollup/rollup-linux-riscv64-musl@4.59.0':
+ resolution: {integrity: sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==}
+ cpu: [riscv64]
+ os: [linux]
+ libc: [musl]
+
+ '@rollup/rollup-linux-s390x-gnu@4.59.0':
+ resolution: {integrity: sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==}
+ cpu: [s390x]
+ os: [linux]
+ libc: [glibc]
+
+ '@rollup/rollup-linux-x64-gnu@4.59.0':
+ resolution: {integrity: sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==}
+ cpu: [x64]
+ os: [linux]
+ libc: [glibc]
+
+ '@rollup/rollup-linux-x64-musl@4.59.0':
+ resolution: {integrity: sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==}
+ cpu: [x64]
+ os: [linux]
+ libc: [musl]
+
+ '@rollup/rollup-openbsd-x64@4.59.0':
+ resolution: {integrity: sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==}
+ cpu: [x64]
+ os: [openbsd]
+
+ '@rollup/rollup-openharmony-arm64@4.59.0':
+ resolution: {integrity: sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==}
+ cpu: [arm64]
+ os: [openharmony]
+
+ '@rollup/rollup-win32-arm64-msvc@4.59.0':
+ resolution: {integrity: sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==}
+ cpu: [arm64]
+ os: [win32]
+
+ '@rollup/rollup-win32-ia32-msvc@4.59.0':
+ resolution: {integrity: sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==}
+ cpu: [ia32]
+ os: [win32]
+
+ '@rollup/rollup-win32-x64-gnu@4.59.0':
+ resolution: {integrity: sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==}
+ cpu: [x64]
+ os: [win32]
+
+ '@rollup/rollup-win32-x64-msvc@4.59.0':
+ resolution: {integrity: sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==}
+ cpu: [x64]
+ os: [win32]
+
'@sindresorhus/is@4.6.0':
resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==}
engines: {node: '>=10'}
@@ -1285,24 +1747,28 @@ packages:
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
+ libc: [glibc]
'@tailwindcss/oxide-linux-arm64-musl@4.1.16':
resolution: {integrity: sha512-H81UXMa9hJhWhaAUca6bU2wm5RRFpuHImrwXBUvPbYb+3jo32I9VIwpOX6hms0fPmA6f2pGVlybO6qU8pF4fzQ==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
+ libc: [musl]
'@tailwindcss/oxide-linux-x64-gnu@4.1.16':
resolution: {integrity: sha512-ZGHQxDtFC2/ruo7t99Qo2TTIvOERULPl5l0K1g0oK6b5PGqjYMga+FcY1wIUnrUxY56h28FxybtDEla+ICOyew==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
+ libc: [glibc]
'@tailwindcss/oxide-linux-x64-musl@4.1.16':
resolution: {integrity: sha512-Oi1tAaa0rcKf1Og9MzKeINZzMLPbhxvm7rno5/zuP1WYmpiG0bEHq4AcRUiG2165/WUzvxkW4XDYCscZWbTLZw==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
+ libc: [musl]
'@tailwindcss/oxide-wasm32-wasi@4.1.16':
resolution: {integrity: sha512-B01u/b8LteGRwucIBmCQ07FVXLzImWESAIMcUU6nvFt/tYsQ6IHz8DmZ5KtvmwxD+iTYBtM1xwoGXswnlu9v0Q==}
@@ -1335,6 +1801,29 @@ packages:
'@tailwindcss/postcss@4.1.16':
resolution: {integrity: sha512-Qn3SFGPXYQMKR/UtqS+dqvPrzEeBZHrFA92maT4zijCVggdsXnDBMsPFJo1eArX3J+O+Gi+8pV4PkqjLCNBk3A==}
+ '@testing-library/dom@10.4.1':
+ resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==}
+ engines: {node: '>=18'}
+
+ '@testing-library/jest-dom@6.9.1':
+ resolution: {integrity: sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA==}
+ engines: {node: '>=14', npm: '>=6', yarn: '>=1'}
+
+ '@testing-library/react@16.3.2':
+ resolution: {integrity: sha512-XU5/SytQM+ykqMnAnvB2umaJNIOsLF3PVv//1Ew4CTcpz0/BRyy/af40qqrt7SjKpDdT1saBMc42CUok5gaw+g==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ '@testing-library/dom': ^10.0.0
+ '@types/react': ^18.0.0 || ^19.0.0
+ '@types/react-dom': ^18.0.0 || ^19.0.0
+ react: ^18.0.0 || ^19.0.0
+ react-dom: ^18.0.0 || ^19.0.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
'@tootallnate/once@2.0.0':
resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==}
engines: {node: '>= 10'}
@@ -1354,6 +1843,21 @@ packages:
'@tsconfig/node16@1.0.4':
resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==}
+ '@types/aria-query@5.0.4':
+ resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==}
+
+ '@types/babel__core@7.20.5':
+ resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==}
+
+ '@types/babel__generator@7.27.0':
+ resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==}
+
+ '@types/babel__template@7.4.4':
+ resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==}
+
+ '@types/babel__traverse@7.28.0':
+ resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==}
+
'@types/body-parser@1.19.6':
resolution: {integrity: sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==}
@@ -1363,6 +1867,9 @@ packages:
'@types/cacheable-request@6.0.3':
resolution: {integrity: sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==}
+ '@types/chai@5.2.3':
+ resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==}
+
'@types/connect-history-api-fallback@1.5.4':
resolution: {integrity: sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==}
@@ -1462,6 +1969,9 @@ packages:
'@types/d3@7.4.3':
resolution: {integrity: sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==}
+ '@types/deep-eql@4.0.2':
+ resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==}
+
'@types/eslint-scope@3.7.7':
resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==}
@@ -1557,6 +2067,9 @@ packages:
'@types/use-sync-external-store@0.0.6':
resolution: {integrity: sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==}
+ '@types/whatwg-mimetype@3.0.2':
+ resolution: {integrity: sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA==}
+
'@types/wrap-ansi@3.0.0':
resolution: {integrity: sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==}
@@ -1569,6 +2082,41 @@ packages:
'@vercel/webpack-asset-relocator-loader@1.7.3':
resolution: {integrity: sha512-vizrI18v8Lcb1PmNNUBz7yxPxxXoOeuaVEjTG9MjvDrphjiSxFZrRJ5tIghk+qdLFRCXI5HBCshgobftbmrC5g==}
+ '@vitejs/plugin-react@5.1.4':
+ resolution: {integrity: sha512-VIcFLdRi/VYRU8OL/puL7QXMYafHmqOnwTZY50U1JPlCNj30PxCMx65c494b1K9be9hX83KVt0+gTEwTWLqToA==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ peerDependencies:
+ vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0
+
+ '@vitest/expect@4.0.18':
+ resolution: {integrity: sha512-8sCWUyckXXYvx4opfzVY03EOiYVxyNrHS5QxX3DAIi5dpJAAkyJezHCP77VMX4HKA2LDT/Jpfo8i2r5BE3GnQQ==}
+
+ '@vitest/mocker@4.0.18':
+ resolution: {integrity: sha512-HhVd0MDnzzsgevnOWCBj5Otnzobjy5wLBe4EdeeFGv8luMsGcYqDuFRMcttKWZA5vVO8RFjexVovXvAM4JoJDQ==}
+ peerDependencies:
+ msw: ^2.4.9
+ vite: ^6.0.0 || ^7.0.0-0
+ peerDependenciesMeta:
+ msw:
+ optional: true
+ vite:
+ optional: true
+
+ '@vitest/pretty-format@4.0.18':
+ resolution: {integrity: sha512-P24GK3GulZWC5tz87ux0m8OADrQIUVDPIjjj65vBXYG17ZeU3qD7r+MNZ1RNv4l8CGU2vtTRqixrOi9fYk/yKw==}
+
+ '@vitest/runner@4.0.18':
+ resolution: {integrity: sha512-rpk9y12PGa22Jg6g5M3UVVnTS7+zycIGk9ZNGN+m6tZHKQb7jrP7/77WfZy13Y/EUDd52NDsLRQhYKtv7XfPQw==}
+
+ '@vitest/snapshot@4.0.18':
+ resolution: {integrity: sha512-PCiV0rcl7jKQjbgYqjtakly6T1uwv/5BQ9SwBLekVg/EaYeQFPiXcgrC2Y7vDMA8dM1SUEAEV82kgSQIlXNMvA==}
+
+ '@vitest/spy@4.0.18':
+ resolution: {integrity: sha512-cbQt3PTSD7P2OARdVW3qWER5EGq7PHlvE+QfzSC0lbwO+xnt7+XH06ZzFjFRgzUX//JmpxrCu92VdwvEPlWSNw==}
+
+ '@vitest/utils@4.0.18':
+ resolution: {integrity: sha512-msMRKLMVLWygpK3u2Hybgi4MNjcYJvwTb0Ru09+fOyCXIgT5raYP041DRRdiJiI3k/2U6SEbAETB3YtBrUkCFA==}
+
'@vscode/sudo-prompt@9.3.1':
resolution: {integrity: sha512-9ORTwwS74VaTn38tNbQhsA5U44zkJfcb0BdTSyyG6frP4e8KMtHuTXYmwefe5dpL8XB1aGSIVTaLjD3BbWb5iA==}
@@ -1731,6 +2279,10 @@ packages:
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
engines: {node: '>=8'}
+ ansi-styles@5.2.0:
+ resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==}
+ engines: {node: '>=10'}
+
ansi-styles@6.2.3:
resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==}
engines: {node: '>=12'}
@@ -1749,9 +2301,20 @@ packages:
resolution: {integrity: sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==}
engines: {node: '>=10'}
+ aria-query@5.3.0:
+ resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==}
+
+ aria-query@5.3.2:
+ resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==}
+ engines: {node: '>= 0.4'}
+
array-flatten@1.1.1:
resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==}
+ assertion-error@2.0.1:
+ resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==}
+ engines: {node: '>=12'}
+
ast-types@0.13.4:
resolution: {integrity: sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==}
engines: {node: '>=4'}
@@ -1840,6 +2403,9 @@ packages:
batch@0.6.1:
resolution: {integrity: sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==}
+ bidi-js@1.0.3:
+ resolution: {integrity: sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==}
+
big.js@5.2.2:
resolution: {integrity: sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==}
@@ -1925,6 +2491,10 @@ packages:
caniuse-lite@1.0.30001752:
resolution: {integrity: sha512-vKUk7beoukxE47P5gcVNKkDRzXdVofotshHwfR9vmpeFKxmI5PBpgOMC18LUJUA/DvJ70Y7RveasIBraqsyO/g==}
+ chai@6.2.2:
+ resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==}
+ engines: {node: '>=18'}
+
chalk@4.1.2:
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
engines: {node: '>=10'}
@@ -2075,6 +2645,9 @@ packages:
resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==}
engines: {node: '>= 0.6'}
+ convert-source-map@2.0.0:
+ resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
+
cookie-signature@1.0.6:
resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==}
@@ -2127,15 +2700,26 @@ packages:
css-select@4.3.0:
resolution: {integrity: sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==}
+ css-tree@3.1.0:
+ resolution: {integrity: sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==}
+ engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0}
+
css-what@6.2.2:
resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==}
engines: {node: '>= 6'}
+ css.escape@1.5.1:
+ resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==}
+
cssesc@3.0.0:
resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
engines: {node: '>=4'}
hasBin: true
+ cssstyle@6.1.0:
+ resolution: {integrity: sha512-Ml4fP2UT2K3CUBQnVlbdV/8aFDdlY69E+YnwJM+3VUWl08S3J8c8aRuJqCkD9Py8DHZ7zNNvsfKl8psocHZEFg==}
+ engines: {node: '>=20'}
+
csstype@3.1.3:
resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
@@ -2209,6 +2793,10 @@ packages:
resolution: {integrity: sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==}
engines: {node: '>= 14'}
+ data-urls@7.0.0:
+ resolution: {integrity: sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==}
+ engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0}
+
date-fns-jalali@4.1.0-0:
resolution: {integrity: sha512-hTIP/z+t+qKwBDcmmsnmjWTduxCg+5KfdqWQvb2X/8C9+knYY6epN/pfxdDuyVlSVeFz0sM5eEfwIUQ70U4ckg==}
@@ -2235,6 +2823,9 @@ packages:
decimal.js-light@2.5.1:
resolution: {integrity: sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==}
+ decimal.js@10.6.0:
+ resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==}
+
decompress-response@6.0.0:
resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==}
engines: {node: '>=10'}
@@ -2278,6 +2869,10 @@ packages:
resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
engines: {node: '>= 0.8'}
+ dequal@2.0.3:
+ resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
+ engines: {node: '>=6'}
+
destroy@1.2.0:
resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==}
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
@@ -2306,6 +2901,12 @@ packages:
resolution: {integrity: sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==}
engines: {node: '>=6'}
+ dom-accessibility-api@0.5.16:
+ resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==}
+
+ dom-accessibility-api@0.6.3:
+ resolution: {integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==}
+
dom-converter@0.2.0:
resolution: {integrity: sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==}
@@ -2410,6 +3011,14 @@ packages:
entities@2.2.0:
resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==}
+ entities@6.0.1:
+ resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==}
+ engines: {node: '>=0.12'}
+
+ entities@7.0.1:
+ resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==}
+ engines: {node: '>=0.12'}
+
env-paths@2.2.1:
resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==}
engines: {node: '>=6'}
@@ -2450,6 +3059,11 @@ packages:
es6-error@4.1.1:
resolution: {integrity: sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==}
+ esbuild@0.27.3:
+ resolution: {integrity: sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==}
+ engines: {node: '>=18'}
+ hasBin: true
+
escalade@3.2.0:
resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
engines: {node: '>=6'}
@@ -2491,6 +3105,9 @@ packages:
resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==}
engines: {node: '>=4.0'}
+ estree-walker@3.0.3:
+ resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==}
+
esutils@2.0.3:
resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
engines: {node: '>=0.10.0'}
@@ -2520,6 +3137,10 @@ packages:
resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==}
engines: {node: '>=10'}
+ expect-type@1.3.0:
+ resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==}
+ engines: {node: '>=12.0.0'}
+
exponential-backoff@3.1.3:
resolution: {integrity: sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==}
@@ -2569,6 +3190,15 @@ packages:
fd-slicer@1.1.0:
resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==}
+ fdir@6.5.0:
+ resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==}
+ engines: {node: '>=12.0.0'}
+ peerDependencies:
+ picomatch: ^3 || ^4
+ peerDependenciesMeta:
+ picomatch:
+ optional: true
+
filename-reserved-regex@2.0.0:
resolution: {integrity: sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==}
engines: {node: '>=4'}
@@ -2675,6 +3305,10 @@ packages:
resolution: {integrity: sha512-w4n9cPWyP7aHxKxYHFQMegj7WIAsL/YX/C4Bs5Rr8s1H9M1rNtRWRsw+ovYMkXDQ5S4ZbYHsHAPmevPjPgw44w==}
deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.
+ gensync@1.0.0-beta.2:
+ resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
+ engines: {node: '>=6.9.0'}
+
get-caller-file@2.0.5:
resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
engines: {node: 6.* || 8.* || >= 10.*}
@@ -2729,7 +3363,7 @@ packages:
glob@8.1.0:
resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==}
engines: {node: '>=12'}
- deprecated: Glob versions prior to v9 are no longer supported
+ deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me
global-agent@3.0.0:
resolution: {integrity: sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==}
@@ -2757,6 +3391,10 @@ packages:
handle-thing@2.0.1:
resolution: {integrity: sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==}
+ happy-dom@20.7.0:
+ resolution: {integrity: sha512-hR/uLYQdngTyEfxnOoa+e6KTcfBFyc1hgFj/Cc144A5JJUuHFYqIEBDcD4FeGqUeKLRZqJ9eN9u7/GDjYEgS1g==}
+ engines: {node: '>=20.0.0'}
+
has-flag@4.0.0:
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
engines: {node: '>=8'}
@@ -2786,6 +3424,10 @@ packages:
hpack.js@2.1.6:
resolution: {integrity: sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==}
+ html-encoding-sniffer@6.0.0:
+ resolution: {integrity: sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==}
+ engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0}
+
html-entities@2.6.0:
resolution: {integrity: sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==}
@@ -2997,6 +3639,9 @@ packages:
resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==}
engines: {node: '>=0.10.0'}
+ is-potential-custom-element-name@1.0.1:
+ resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==}
+
is-stream@1.1.0:
resolution: {integrity: sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==}
engines: {node: '>=0.10.0'}
@@ -3042,6 +3687,20 @@ packages:
resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==}
hasBin: true
+ jsdom@28.1.0:
+ resolution: {integrity: sha512-0+MoQNYyr2rBHqO1xilltfDjV9G7ymYGlAUazgcDLQaUf8JDHbuGwsxN6U9qWaElZ4w1B2r7yEGIL3GdeW3Rug==}
+ engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0}
+ peerDependencies:
+ canvas: ^3.0.0
+ peerDependenciesMeta:
+ canvas:
+ optional: true
+
+ jsesc@3.1.0:
+ resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==}
+ engines: {node: '>=6'}
+ hasBin: true
+
json-buffer@3.0.1:
resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
@@ -3114,24 +3773,28 @@ packages:
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
+ libc: [glibc]
lightningcss-linux-arm64-musl@1.30.2:
resolution: {integrity: sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
+ libc: [musl]
lightningcss-linux-x64-gnu@1.30.2:
resolution: {integrity: sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
+ libc: [glibc]
lightningcss-linux-x64-musl@1.30.2:
resolution: {integrity: sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
+ libc: [musl]
lightningcss-win32-arm64-msvc@1.30.2:
resolution: {integrity: sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==}
@@ -3202,6 +3865,13 @@ packages:
resolution: {integrity: sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==}
engines: {node: '>=8'}
+ lru-cache@11.2.6:
+ resolution: {integrity: sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==}
+ engines: {node: 20 || >=22}
+
+ lru-cache@5.1.1:
+ resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
+
lru-cache@7.18.3:
resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==}
engines: {node: '>=12'}
@@ -3211,6 +3881,10 @@ packages:
peerDependencies:
react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0
+ lz-string@1.5.0:
+ resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==}
+ hasBin: true
+
magic-string@0.30.21:
resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
@@ -3233,6 +3907,9 @@ packages:
resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
engines: {node: '>= 0.4'}
+ mdn-data@2.12.2:
+ resolution: {integrity: sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==}
+
media-typer@0.3.0:
resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==}
engines: {node: '>= 0.6'}
@@ -3292,6 +3969,10 @@ packages:
resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==}
engines: {node: '>=10'}
+ min-indent@1.0.1:
+ resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==}
+ engines: {node: '>=4'}
+
minimalistic-assert@1.0.1:
resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==}
@@ -3474,6 +4155,9 @@ packages:
obuf@1.1.2:
resolution: {integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==}
+ obug@2.1.1:
+ resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==}
+
on-finished@2.4.1:
resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==}
engines: {node: '>= 0.8'}
@@ -3584,6 +4268,9 @@ packages:
resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==}
engines: {node: '>=8'}
+ parse5@8.0.0:
+ resolution: {integrity: sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA==}
+
parseurl@1.3.3:
resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==}
engines: {node: '>= 0.8'}
@@ -3621,6 +4308,9 @@ packages:
resolution: {integrity: sha512-dUnb5dXUf+kzhC/W/F4e5/SkluXIFf5VUHolW1Eg1irn1hGWjPGdsRcvYJ1nD6lhk8Ir7VM0bHJKsYTx8Jx9OQ==}
engines: {node: '>=4'}
+ pathe@2.0.3:
+ resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
+
pe-library@1.0.1:
resolution: {integrity: sha512-nh39Mo1eGWmZS7y+mK/dQIqg7S1lp38DpRxkyoHf0ZcUs/HDc+yyTjuOtTvSMZHmfSLuSQaX945u05Y2Q6UWZg==}
engines: {node: '>=14', npm: '>=7'}
@@ -3635,6 +4325,10 @@ packages:
resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
engines: {node: '>=8.6'}
+ picomatch@4.0.3:
+ resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==}
+ engines: {node: '>=12'}
+
pify@2.3.0:
resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==}
engines: {node: '>=0.10.0'}
@@ -3708,6 +4402,10 @@ packages:
pretty-error@4.0.0:
resolution: {integrity: sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==}
+ pretty-format@27.5.1:
+ resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==}
+ engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
+
proc-log@2.0.1:
resolution: {integrity: sha512-Kcmo2FhfDTXdcbfDH76N7uBYHINxc/8GW7UAVuVP9I+Va3uHSerrnKV6dLooga/gh7GlgzuCCr/eoldnL1muGw==}
engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
@@ -3745,6 +4443,10 @@ packages:
pump@3.0.3:
resolution: {integrity: sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==}
+ punycode@2.3.1:
+ resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
+ engines: {node: '>=6'}
+
puppeteer-core@24.34.0:
resolution: {integrity: sha512-24evawO+mUGW4mvS2a2ivwLdX3gk8zRLZr9HP+7+VT2vBQnm0oh9jJEZmUE3ePJhRkYlZ93i7OMpdcoi2qNCLg==}
engines: {node: '>=18'}
@@ -3806,6 +4508,9 @@ packages:
peerDependencies:
react: ^16.8.0 || ^17 || ^18 || ^19
+ react-is@17.0.2:
+ resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==}
+
react-is@19.2.0:
resolution: {integrity: sha512-x3Ax3kNSMIIkyVYhWPyO09bu0uttcAIoecO/um/rKGQ4EltYWVYtyiGkS/3xMynrbVQdS69Jhlv8FXUEZehlzA==}
@@ -3821,6 +4526,10 @@ packages:
redux:
optional: true
+ react-refresh@0.18.0:
+ resolution: {integrity: sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==}
+ engines: {node: '>=0.10.0'}
+
react-remove-scroll-bar@2.3.8:
resolution: {integrity: sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==}
engines: {node: '>=10'}
@@ -3902,6 +4611,10 @@ packages:
resolution: {integrity: sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==}
engines: {node: '>= 10.13.0'}
+ redent@3.0.0:
+ resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==}
+ engines: {node: '>=8'}
+
redux-thunk@3.1.0:
resolution: {integrity: sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==}
peerDependencies:
@@ -3995,6 +4708,11 @@ packages:
resolution: {integrity: sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==}
engines: {node: '>=8.0'}
+ rollup@4.59.0:
+ resolution: {integrity: sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==}
+ engines: {node: '>=18.0.0', npm: '>=8.0.0'}
+ hasBin: true
+
run-parallel@1.2.0:
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
@@ -4007,6 +4725,10 @@ packages:
safer-buffer@2.1.2:
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
+ saxes@6.0.0:
+ resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==}
+ engines: {node: '>=v12.22.7'}
+
scheduler@0.27.0:
resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==}
@@ -4102,6 +4824,9 @@ packages:
resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==}
engines: {node: '>= 0.4'}
+ siginfo@2.0.0:
+ resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==}
+
signal-exit@3.0.7:
resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
@@ -4179,6 +4904,9 @@ packages:
resolution: {integrity: sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==}
engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
+ stackback@0.0.2:
+ resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==}
+
statuses@1.5.0:
resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==}
engines: {node: '>= 0.6'}
@@ -4187,6 +4915,9 @@ packages:
resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==}
engines: {node: '>= 0.8'}
+ std-env@3.10.0:
+ resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==}
+
streamx@2.23.0:
resolution: {integrity: sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg==}
@@ -4224,6 +4955,10 @@ packages:
resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==}
engines: {node: '>=6'}
+ strip-indent@3.0.0:
+ resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==}
+ engines: {node: '>=8'}
+
strip-outer@1.0.1:
resolution: {integrity: sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==}
engines: {node: '>=0.10.0'}
@@ -4250,6 +4985,9 @@ packages:
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
engines: {node: '>= 0.4'}
+ symbol-tree@3.2.4:
+ resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==}
+
tailwind-merge@3.3.1:
resolution: {integrity: sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g==}
@@ -4307,6 +5045,28 @@ packages:
tiny-invariant@1.3.3:
resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==}
+ tinybench@2.9.0:
+ resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==}
+
+ tinyexec@1.0.2:
+ resolution: {integrity: sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==}
+ engines: {node: '>=18'}
+
+ tinyglobby@0.2.15:
+ resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==}
+ engines: {node: '>=12.0.0'}
+
+ tinyrainbow@3.0.3:
+ resolution: {integrity: sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==}
+ engines: {node: '>=14.0.0'}
+
+ tldts-core@7.0.23:
+ resolution: {integrity: sha512-0g9vrtDQLrNIiCj22HSe9d4mLVG3g5ph5DZ8zCKBr4OtrspmNB6ss7hVyzArAeE88ceZocIEGkyW1Ime7fxPtQ==}
+
+ tldts@7.0.23:
+ resolution: {integrity: sha512-ASdhgQIBSay0R/eXggAkQ53G4nTJqTXqC2kbaBbdDwM7SkjyZyO0OaaN1/FH7U/yCeqOHDwFO5j8+Os/IS1dXw==}
+ hasBin: true
+
tmp-promise@3.0.3:
resolution: {integrity: sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==}
@@ -4326,9 +5086,17 @@ packages:
resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==}
engines: {node: '>=0.6'}
+ tough-cookie@6.0.0:
+ resolution: {integrity: sha512-kXuRi1mtaKMrsLUxz3sQYvVl37B0Ns6MzfrtV5DvJceE9bPyspOqk9xxv7XbZWcfLWbFmm997vl83qUWVJA64w==}
+ engines: {node: '>=16'}
+
tr46@0.0.3:
resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
+ tr46@6.0.0:
+ resolution: {integrity: sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==}
+ engines: {node: '>=20'}
+
trim-repeated@1.0.0:
resolution: {integrity: sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==}
engines: {node: '>=0.10.0'}
@@ -4389,6 +5157,10 @@ packages:
undici-types@6.21.0:
resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
+ undici@7.22.0:
+ resolution: {integrity: sha512-RqslV2Us5BrllB+JeiZnK4peryVTndy9Dnqq62S3yYRRTj0tFQCwEniUy2167skdGOy3vqRzEvl1Dm4sV2ReDg==}
+ engines: {node: '>=20.18.1'}
+
unique-filename@2.0.1:
resolution: {integrity: sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==}
engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
@@ -4477,6 +5249,84 @@ packages:
victory-vendor@37.3.6:
resolution: {integrity: sha512-SbPDPdDBYp+5MJHhBCAyI7wKM3d5ivekigc2Dk2s7pgbZ9wIgIBYGVw4zGHBml/qTFbexrofXW6Gu4noGxrOwQ==}
+ vite@7.3.1:
+ resolution: {integrity: sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ hasBin: true
+ peerDependencies:
+ '@types/node': ^20.19.0 || >=22.12.0
+ jiti: '>=1.21.0'
+ less: ^4.0.0
+ lightningcss: ^1.21.0
+ sass: ^1.70.0
+ sass-embedded: ^1.70.0
+ stylus: '>=0.54.8'
+ sugarss: ^5.0.0
+ terser: ^5.16.0
+ tsx: ^4.8.1
+ yaml: ^2.4.2
+ peerDependenciesMeta:
+ '@types/node':
+ optional: true
+ jiti:
+ optional: true
+ less:
+ optional: true
+ lightningcss:
+ optional: true
+ sass:
+ optional: true
+ sass-embedded:
+ optional: true
+ stylus:
+ optional: true
+ sugarss:
+ optional: true
+ terser:
+ optional: true
+ tsx:
+ optional: true
+ yaml:
+ optional: true
+
+ vitest@4.0.18:
+ resolution: {integrity: sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ==}
+ engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0}
+ hasBin: true
+ peerDependencies:
+ '@edge-runtime/vm': '*'
+ '@opentelemetry/api': ^1.9.0
+ '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0
+ '@vitest/browser-playwright': 4.0.18
+ '@vitest/browser-preview': 4.0.18
+ '@vitest/browser-webdriverio': 4.0.18
+ '@vitest/ui': 4.0.18
+ happy-dom: '*'
+ jsdom: '*'
+ peerDependenciesMeta:
+ '@edge-runtime/vm':
+ optional: true
+ '@opentelemetry/api':
+ optional: true
+ '@types/node':
+ optional: true
+ '@vitest/browser-playwright':
+ optional: true
+ '@vitest/browser-preview':
+ optional: true
+ '@vitest/browser-webdriverio':
+ optional: true
+ '@vitest/ui':
+ optional: true
+ happy-dom:
+ optional: true
+ jsdom:
+ optional: true
+
+ w3c-xmlserializer@5.0.0:
+ resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==}
+ engines: {node: '>=18'}
+
watchpack@2.4.4:
resolution: {integrity: sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==}
engines: {node: '>=10.13.0'}
@@ -4493,6 +5343,10 @@ packages:
webidl-conversions@3.0.1:
resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
+ webidl-conversions@8.0.1:
+ resolution: {integrity: sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==}
+ engines: {node: '>=20'}
+
webpack-cli@6.0.1:
resolution: {integrity: sha512-MfwFQ6SfwinsUVi0rNJm7rHZ31GyTcpVE5pgVA3hwFRb7COD4TzjUUwhGWKfO50+xdc2MQPuEBBJoqIMGt3JDw==}
engines: {node: '>=18.12.0'}
@@ -4556,6 +5410,18 @@ packages:
resolution: {integrity: sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==}
engines: {node: '>=0.8.0'}
+ whatwg-mimetype@3.0.0:
+ resolution: {integrity: sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==}
+ engines: {node: '>=12'}
+
+ whatwg-mimetype@5.0.0:
+ resolution: {integrity: sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==}
+ engines: {node: '>=20'}
+
+ whatwg-url@16.0.1:
+ resolution: {integrity: sha512-1to4zXBxmXHV3IiSSEInrreIlu02vUOvrhxJJH5vcxYTBDAx51cqZiKdyTxlecdKNSjj8EcxGBxNf6Vg+945gw==}
+ engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0}
+
whatwg-url@5.0.0:
resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==}
@@ -4568,6 +5434,11 @@ packages:
engines: {node: '>= 8'}
hasBin: true
+ why-is-node-running@2.3.0:
+ resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==}
+ engines: {node: '>=8'}
+ hasBin: true
+
wildcard@2.0.1:
resolution: {integrity: sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==}
@@ -4614,10 +5485,17 @@ packages:
utf-8-validate:
optional: true
+ xml-name-validator@5.0.0:
+ resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==}
+ engines: {node: '>=18'}
+
xmlbuilder@15.1.1:
resolution: {integrity: sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==}
engines: {node: '>=8.0'}
+ xmlchars@2.2.0:
+ resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==}
+
xterm-addon-fit@0.5.0:
resolution: {integrity: sha512-DsS9fqhXHacEmsPxBJZvfj2la30Iz9xk+UKjhQgnYNkrUIN5CYLbw7WEfz117c7+S86S/tpHPfvNxJsF5/G8wQ==}
deprecated: This package is now deprecated. Move to @xterm/addon-fit instead.
@@ -4638,6 +5516,9 @@ packages:
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
engines: {node: '>=10'}
+ yallist@3.1.1:
+ resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
+
yallist@4.0.0:
resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
@@ -4692,16 +5573,150 @@ packages:
snapshots:
+ '@acemir/cssom@0.9.31': {}
+
+ '@adobe/css-tools@4.4.4': {}
+
'@alloc/quick-lru@5.2.0': {}
+ '@asamuzakjp/css-color@5.0.1':
+ dependencies:
+ '@csstools/css-calc': 3.1.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)
+ '@csstools/css-color-parser': 4.0.2(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)
+ '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0)
+ '@csstools/css-tokenizer': 4.0.0
+ lru-cache: 11.2.6
+
+ '@asamuzakjp/dom-selector@6.8.1':
+ dependencies:
+ '@asamuzakjp/nwsapi': 2.3.9
+ bidi-js: 1.0.3
+ css-tree: 3.1.0
+ is-potential-custom-element-name: 1.0.1
+ lru-cache: 11.2.6
+
+ '@asamuzakjp/nwsapi@2.3.9': {}
+
'@babel/code-frame@7.27.1':
dependencies:
'@babel/helper-validator-identifier': 7.28.5
js-tokens: 4.0.0
picocolors: 1.1.1
+ '@babel/code-frame@7.29.0':
+ dependencies:
+ '@babel/helper-validator-identifier': 7.28.5
+ js-tokens: 4.0.0
+ picocolors: 1.1.1
+
+ '@babel/compat-data@7.29.0': {}
+
+ '@babel/core@7.29.0':
+ dependencies:
+ '@babel/code-frame': 7.29.0
+ '@babel/generator': 7.29.1
+ '@babel/helper-compilation-targets': 7.28.6
+ '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0)
+ '@babel/helpers': 7.28.6
+ '@babel/parser': 7.29.0
+ '@babel/template': 7.28.6
+ '@babel/traverse': 7.29.0
+ '@babel/types': 7.29.0
+ '@jridgewell/remapping': 2.3.5
+ convert-source-map: 2.0.0
+ debug: 4.4.3
+ gensync: 1.0.0-beta.2
+ json5: 2.2.3
+ semver: 6.3.1
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/generator@7.29.1':
+ dependencies:
+ '@babel/parser': 7.29.0
+ '@babel/types': 7.29.0
+ '@jridgewell/gen-mapping': 0.3.13
+ '@jridgewell/trace-mapping': 0.3.31
+ jsesc: 3.1.0
+
+ '@babel/helper-compilation-targets@7.28.6':
+ dependencies:
+ '@babel/compat-data': 7.29.0
+ '@babel/helper-validator-option': 7.27.1
+ browserslist: 4.27.0
+ lru-cache: 5.1.1
+ semver: 6.3.1
+
+ '@babel/helper-globals@7.28.0': {}
+
+ '@babel/helper-module-imports@7.28.6':
+ dependencies:
+ '@babel/traverse': 7.29.0
+ '@babel/types': 7.29.0
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-module-transforms@7.28.6(@babel/core@7.29.0)':
+ dependencies:
+ '@babel/core': 7.29.0
+ '@babel/helper-module-imports': 7.28.6
+ '@babel/helper-validator-identifier': 7.28.5
+ '@babel/traverse': 7.29.0
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-plugin-utils@7.28.6': {}
+
+ '@babel/helper-string-parser@7.27.1': {}
+
'@babel/helper-validator-identifier@7.28.5': {}
+ '@babel/helper-validator-option@7.27.1': {}
+
+ '@babel/helpers@7.28.6':
+ dependencies:
+ '@babel/template': 7.28.6
+ '@babel/types': 7.29.0
+
+ '@babel/parser@7.29.0':
+ dependencies:
+ '@babel/types': 7.29.0
+
+ '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.29.0)':
+ dependencies:
+ '@babel/core': 7.29.0
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.29.0)':
+ dependencies:
+ '@babel/core': 7.29.0
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/runtime@7.28.6': {}
+
+ '@babel/template@7.28.6':
+ dependencies:
+ '@babel/code-frame': 7.29.0
+ '@babel/parser': 7.29.0
+ '@babel/types': 7.29.0
+
+ '@babel/traverse@7.29.0':
+ dependencies:
+ '@babel/code-frame': 7.29.0
+ '@babel/generator': 7.29.1
+ '@babel/helper-globals': 7.28.0
+ '@babel/parser': 7.29.0
+ '@babel/template': 7.28.6
+ '@babel/types': 7.29.0
+ debug: 4.4.3
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/types@7.29.0':
+ dependencies:
+ '@babel/helper-string-parser': 7.27.1
+ '@babel/helper-validator-identifier': 7.28.5
+
'@biomejs/biome@2.3.8':
optionalDependencies:
'@biomejs/cli-darwin-arm64': 2.3.8
@@ -4737,10 +5752,36 @@ snapshots:
'@biomejs/cli-win32-x64@2.3.8':
optional: true
+ '@bramus/specificity@2.4.2':
+ dependencies:
+ css-tree: 3.1.0
+
'@cspotcode/source-map-support@0.8.1':
dependencies:
'@jridgewell/trace-mapping': 0.3.9
+ '@csstools/color-helpers@6.0.2': {}
+
+ '@csstools/css-calc@3.1.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)':
+ dependencies:
+ '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0)
+ '@csstools/css-tokenizer': 4.0.0
+
+ '@csstools/css-color-parser@4.0.2(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)':
+ dependencies:
+ '@csstools/color-helpers': 6.0.2
+ '@csstools/css-calc': 3.1.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)
+ '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0)
+ '@csstools/css-tokenizer': 4.0.0
+
+ '@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0)':
+ dependencies:
+ '@csstools/css-tokenizer': 4.0.0
+
+ '@csstools/css-syntax-patches-for-csstree@1.0.28': {}
+
+ '@csstools/css-tokenizer@4.0.0': {}
+
'@date-fns/tz@1.4.1': {}
'@discoveryjs/json-ext@0.6.3': {}
@@ -5117,27 +6158,107 @@ snapshots:
- bluebird
- supports-color
- '@electron/universal@2.0.3':
- dependencies:
- '@electron/asar': 3.4.1
- '@malept/cross-spawn-promise': 2.0.0
- debug: 4.4.3
- dir-compare: 4.2.0
- fs-extra: 11.3.2
- minimatch: 9.0.5
- plist: 3.1.0
- transitivePeerDependencies:
- - supports-color
+ '@electron/universal@2.0.3':
+ dependencies:
+ '@electron/asar': 3.4.1
+ '@malept/cross-spawn-promise': 2.0.0
+ debug: 4.4.3
+ dir-compare: 4.2.0
+ fs-extra: 11.3.2
+ minimatch: 9.0.5
+ plist: 3.1.0
+ transitivePeerDependencies:
+ - supports-color
+
+ '@electron/windows-sign@1.2.2':
+ dependencies:
+ cross-dirname: 0.1.0
+ debug: 4.4.3
+ fs-extra: 11.3.2
+ minimist: 1.2.8
+ postject: 1.0.0-alpha.6
+ transitivePeerDependencies:
+ - supports-color
+
+ '@esbuild/aix-ppc64@0.27.3':
+ optional: true
+
+ '@esbuild/android-arm64@0.27.3':
+ optional: true
+
+ '@esbuild/android-arm@0.27.3':
+ optional: true
+
+ '@esbuild/android-x64@0.27.3':
+ optional: true
+
+ '@esbuild/darwin-arm64@0.27.3':
+ optional: true
+
+ '@esbuild/darwin-x64@0.27.3':
+ optional: true
+
+ '@esbuild/freebsd-arm64@0.27.3':
+ optional: true
+
+ '@esbuild/freebsd-x64@0.27.3':
+ optional: true
+
+ '@esbuild/linux-arm64@0.27.3':
+ optional: true
+
+ '@esbuild/linux-arm@0.27.3':
+ optional: true
+
+ '@esbuild/linux-ia32@0.27.3':
+ optional: true
+
+ '@esbuild/linux-loong64@0.27.3':
+ optional: true
+
+ '@esbuild/linux-mips64el@0.27.3':
+ optional: true
+
+ '@esbuild/linux-ppc64@0.27.3':
+ optional: true
+
+ '@esbuild/linux-riscv64@0.27.3':
+ optional: true
+
+ '@esbuild/linux-s390x@0.27.3':
+ optional: true
+
+ '@esbuild/linux-x64@0.27.3':
+ optional: true
+
+ '@esbuild/netbsd-arm64@0.27.3':
+ optional: true
+
+ '@esbuild/netbsd-x64@0.27.3':
+ optional: true
+
+ '@esbuild/openbsd-arm64@0.27.3':
+ optional: true
+
+ '@esbuild/openbsd-x64@0.27.3':
+ optional: true
- '@electron/windows-sign@1.2.2':
- dependencies:
- cross-dirname: 0.1.0
- debug: 4.4.3
- fs-extra: 11.3.2
- minimist: 1.2.8
- postject: 1.0.0-alpha.6
- transitivePeerDependencies:
- - supports-color
+ '@esbuild/openharmony-arm64@0.27.3':
+ optional: true
+
+ '@esbuild/sunos-x64@0.27.3':
+ optional: true
+
+ '@esbuild/win32-arm64@0.27.3':
+ optional: true
+
+ '@esbuild/win32-ia32@0.27.3':
+ optional: true
+
+ '@esbuild/win32-x64@0.27.3':
+ optional: true
+
+ '@exodus/bytes@1.14.1': {}
'@floating-ui/core@1.7.3':
dependencies:
@@ -6177,6 +7298,83 @@ snapshots:
react: 19.2.0
react-redux: 9.2.0(@types/react@19.2.2)(react@19.2.0)(redux@5.0.1)
+ '@rolldown/pluginutils@1.0.0-rc.3': {}
+
+ '@rollup/rollup-android-arm-eabi@4.59.0':
+ optional: true
+
+ '@rollup/rollup-android-arm64@4.59.0':
+ optional: true
+
+ '@rollup/rollup-darwin-arm64@4.59.0':
+ optional: true
+
+ '@rollup/rollup-darwin-x64@4.59.0':
+ optional: true
+
+ '@rollup/rollup-freebsd-arm64@4.59.0':
+ optional: true
+
+ '@rollup/rollup-freebsd-x64@4.59.0':
+ optional: true
+
+ '@rollup/rollup-linux-arm-gnueabihf@4.59.0':
+ optional: true
+
+ '@rollup/rollup-linux-arm-musleabihf@4.59.0':
+ optional: true
+
+ '@rollup/rollup-linux-arm64-gnu@4.59.0':
+ optional: true
+
+ '@rollup/rollup-linux-arm64-musl@4.59.0':
+ optional: true
+
+ '@rollup/rollup-linux-loong64-gnu@4.59.0':
+ optional: true
+
+ '@rollup/rollup-linux-loong64-musl@4.59.0':
+ optional: true
+
+ '@rollup/rollup-linux-ppc64-gnu@4.59.0':
+ optional: true
+
+ '@rollup/rollup-linux-ppc64-musl@4.59.0':
+ optional: true
+
+ '@rollup/rollup-linux-riscv64-gnu@4.59.0':
+ optional: true
+
+ '@rollup/rollup-linux-riscv64-musl@4.59.0':
+ optional: true
+
+ '@rollup/rollup-linux-s390x-gnu@4.59.0':
+ optional: true
+
+ '@rollup/rollup-linux-x64-gnu@4.59.0':
+ optional: true
+
+ '@rollup/rollup-linux-x64-musl@4.59.0':
+ optional: true
+
+ '@rollup/rollup-openbsd-x64@4.59.0':
+ optional: true
+
+ '@rollup/rollup-openharmony-arm64@4.59.0':
+ optional: true
+
+ '@rollup/rollup-win32-arm64-msvc@4.59.0':
+ optional: true
+
+ '@rollup/rollup-win32-ia32-msvc@4.59.0':
+ optional: true
+
+ '@rollup/rollup-win32-x64-gnu@4.59.0':
+ optional: true
+
+ '@rollup/rollup-win32-x64-msvc@4.59.0':
+ optional: true
+
'@sindresorhus/is@4.6.0': {}
'@standard-schema/spec@1.0.0': {}
@@ -6256,6 +7454,36 @@ snapshots:
postcss: 8.5.6
tailwindcss: 4.1.16
+ '@testing-library/dom@10.4.1':
+ dependencies:
+ '@babel/code-frame': 7.27.1
+ '@babel/runtime': 7.28.6
+ '@types/aria-query': 5.0.4
+ aria-query: 5.3.0
+ dom-accessibility-api: 0.5.16
+ lz-string: 1.5.0
+ picocolors: 1.1.1
+ pretty-format: 27.5.1
+
+ '@testing-library/jest-dom@6.9.1':
+ dependencies:
+ '@adobe/css-tools': 4.4.4
+ aria-query: 5.3.2
+ css.escape: 1.5.1
+ dom-accessibility-api: 0.6.3
+ picocolors: 1.1.1
+ redent: 3.0.0
+
+ '@testing-library/react@16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.2(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)':
+ dependencies:
+ '@babel/runtime': 7.28.6
+ '@testing-library/dom': 10.4.1
+ react: 19.2.0
+ react-dom: 19.2.0(react@19.2.0)
+ optionalDependencies:
+ '@types/react': 19.2.2
+ '@types/react-dom': 19.2.2(@types/react@19.2.2)
+
'@tootallnate/once@2.0.0': {}
'@tootallnate/quickjs-emscripten@0.23.0': {}
@@ -6268,6 +7496,29 @@ snapshots:
'@tsconfig/node16@1.0.4': {}
+ '@types/aria-query@5.0.4': {}
+
+ '@types/babel__core@7.20.5':
+ dependencies:
+ '@babel/parser': 7.29.0
+ '@babel/types': 7.29.0
+ '@types/babel__generator': 7.27.0
+ '@types/babel__template': 7.4.4
+ '@types/babel__traverse': 7.28.0
+
+ '@types/babel__generator@7.27.0':
+ dependencies:
+ '@babel/types': 7.29.0
+
+ '@types/babel__template@7.4.4':
+ dependencies:
+ '@babel/parser': 7.29.0
+ '@babel/types': 7.29.0
+
+ '@types/babel__traverse@7.28.0':
+ dependencies:
+ '@babel/types': 7.29.0
+
'@types/body-parser@1.19.6':
dependencies:
'@types/connect': 3.4.38
@@ -6284,6 +7535,11 @@ snapshots:
'@types/node': 22.18.13
'@types/responselike': 1.0.3
+ '@types/chai@5.2.3':
+ dependencies:
+ '@types/deep-eql': 4.0.2
+ assertion-error: 2.0.1
+
'@types/connect-history-api-fallback@1.5.4':
dependencies:
'@types/express-serve-static-core': 5.1.0
@@ -6410,6 +7666,8 @@ snapshots:
'@types/d3-transition': 3.0.9
'@types/d3-zoom': 3.0.8
+ '@types/deep-eql@4.0.2': {}
+
'@types/eslint-scope@3.7.7':
dependencies:
'@types/eslint': 9.6.1
@@ -6525,6 +7783,8 @@ snapshots:
'@types/use-sync-external-store@0.0.6': {}
+ '@types/whatwg-mimetype@3.0.2': {}
+
'@types/wrap-ansi@3.0.0': {}
'@types/ws@8.18.1':
@@ -6540,6 +7800,57 @@ snapshots:
dependencies:
resolve: 1.22.11
+ '@vitejs/plugin-react@5.1.4(vite@7.3.1(@types/node@22.18.13)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0))':
+ dependencies:
+ '@babel/core': 7.29.0
+ '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.29.0)
+ '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.29.0)
+ '@rolldown/pluginutils': 1.0.0-rc.3
+ '@types/babel__core': 7.20.5
+ react-refresh: 0.18.0
+ vite: 7.3.1(@types/node@22.18.13)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)
+ transitivePeerDependencies:
+ - supports-color
+
+ '@vitest/expect@4.0.18':
+ dependencies:
+ '@standard-schema/spec': 1.0.0
+ '@types/chai': 5.2.3
+ '@vitest/spy': 4.0.18
+ '@vitest/utils': 4.0.18
+ chai: 6.2.2
+ tinyrainbow: 3.0.3
+
+ '@vitest/mocker@4.0.18(vite@7.3.1(@types/node@22.18.13)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0))':
+ dependencies:
+ '@vitest/spy': 4.0.18
+ estree-walker: 3.0.3
+ magic-string: 0.30.21
+ optionalDependencies:
+ vite: 7.3.1(@types/node@22.18.13)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)
+
+ '@vitest/pretty-format@4.0.18':
+ dependencies:
+ tinyrainbow: 3.0.3
+
+ '@vitest/runner@4.0.18':
+ dependencies:
+ '@vitest/utils': 4.0.18
+ pathe: 2.0.3
+
+ '@vitest/snapshot@4.0.18':
+ dependencies:
+ '@vitest/pretty-format': 4.0.18
+ magic-string: 0.30.21
+ pathe: 2.0.3
+
+ '@vitest/spy@4.0.18': {}
+
+ '@vitest/utils@4.0.18':
+ dependencies:
+ '@vitest/pretty-format': 4.0.18
+ tinyrainbow: 3.0.3
+
'@vscode/sudo-prompt@9.3.1': {}
'@webassemblyjs/ast@1.14.1':
@@ -6707,6 +8018,8 @@ snapshots:
dependencies:
color-convert: 2.0.1
+ ansi-styles@5.2.0: {}
+
ansi-styles@6.2.3: {}
anymatch@3.1.3:
@@ -6722,8 +8035,16 @@ snapshots:
dependencies:
tslib: 2.8.1
+ aria-query@5.3.0:
+ dependencies:
+ dequal: 2.0.3
+
+ aria-query@5.3.2: {}
+
array-flatten@1.1.1: {}
+ assertion-error@2.0.1: {}
+
ast-types@0.13.4:
dependencies:
tslib: 2.8.1
@@ -6801,6 +8122,10 @@ snapshots:
batch@0.6.1: {}
+ bidi-js@1.0.3:
+ dependencies:
+ require-from-string: 2.0.2
+
big.js@5.2.2: {}
binary-extensions@2.3.0: {}
@@ -6926,6 +8251,8 @@ snapshots:
caniuse-lite@1.0.30001752: {}
+ chai@6.2.2: {}
+
chalk@4.1.2:
dependencies:
ansi-styles: 4.3.0
@@ -7075,6 +8402,8 @@ snapshots:
content-type@1.0.5: {}
+ convert-source-map@2.0.0: {}
+
cookie-signature@1.0.6: {}
cookie@0.7.1: {}
@@ -7131,10 +8460,24 @@ snapshots:
domutils: 2.8.0
nth-check: 2.1.1
+ css-tree@3.1.0:
+ dependencies:
+ mdn-data: 2.12.2
+ source-map-js: 1.2.1
+
css-what@6.2.2: {}
+ css.escape@1.5.1: {}
+
cssesc@3.0.0: {}
+ cssstyle@6.1.0:
+ dependencies:
+ '@asamuzakjp/css-color': 5.0.1
+ '@csstools/css-syntax-patches-for-csstree': 1.0.28
+ css-tree: 3.1.0
+ lru-cache: 11.2.6
+
csstype@3.1.3: {}
d3-array@3.2.4:
@@ -7203,6 +8546,13 @@ snapshots:
data-uri-to-buffer@6.0.2: {}
+ data-urls@7.0.0:
+ dependencies:
+ whatwg-mimetype: 5.0.0
+ whatwg-url: 16.0.1
+ transitivePeerDependencies:
+ - '@noble/hashes'
+
date-fns-jalali@4.1.0-0: {}
date-fns@4.1.0: {}
@@ -7217,6 +8567,8 @@ snapshots:
decimal.js-light@2.5.1: {}
+ decimal.js@10.6.0: {}
+
decompress-response@6.0.0:
dependencies:
mimic-response: 3.1.0
@@ -7259,6 +8611,8 @@ snapshots:
depd@2.0.0: {}
+ dequal@2.0.3: {}
+
destroy@1.2.0: {}
detect-libc@2.1.2: {}
@@ -7280,6 +8634,10 @@ snapshots:
dependencies:
'@leichtgewicht/ip-codec': 2.0.5
+ dom-accessibility-api@0.5.16: {}
+
+ dom-accessibility-api@0.6.3: {}
+
dom-converter@0.2.0:
dependencies:
utila: 0.4.0
@@ -7428,6 +8786,10 @@ snapshots:
entities@2.2.0: {}
+ entities@6.0.1: {}
+
+ entities@7.0.1: {}
+
env-paths@2.2.1: {}
envinfo@7.19.0: {}
@@ -7460,6 +8822,35 @@ snapshots:
es6-error@4.1.1:
optional: true
+ esbuild@0.27.3:
+ optionalDependencies:
+ '@esbuild/aix-ppc64': 0.27.3
+ '@esbuild/android-arm': 0.27.3
+ '@esbuild/android-arm64': 0.27.3
+ '@esbuild/android-x64': 0.27.3
+ '@esbuild/darwin-arm64': 0.27.3
+ '@esbuild/darwin-x64': 0.27.3
+ '@esbuild/freebsd-arm64': 0.27.3
+ '@esbuild/freebsd-x64': 0.27.3
+ '@esbuild/linux-arm': 0.27.3
+ '@esbuild/linux-arm64': 0.27.3
+ '@esbuild/linux-ia32': 0.27.3
+ '@esbuild/linux-loong64': 0.27.3
+ '@esbuild/linux-mips64el': 0.27.3
+ '@esbuild/linux-ppc64': 0.27.3
+ '@esbuild/linux-riscv64': 0.27.3
+ '@esbuild/linux-s390x': 0.27.3
+ '@esbuild/linux-x64': 0.27.3
+ '@esbuild/netbsd-arm64': 0.27.3
+ '@esbuild/netbsd-x64': 0.27.3
+ '@esbuild/openbsd-arm64': 0.27.3
+ '@esbuild/openbsd-x64': 0.27.3
+ '@esbuild/openharmony-arm64': 0.27.3
+ '@esbuild/sunos-x64': 0.27.3
+ '@esbuild/win32-arm64': 0.27.3
+ '@esbuild/win32-ia32': 0.27.3
+ '@esbuild/win32-x64': 0.27.3
+
escalade@3.2.0: {}
escape-html@1.0.3: {}
@@ -7492,6 +8883,10 @@ snapshots:
estraverse@5.3.0: {}
+ estree-walker@3.0.3:
+ dependencies:
+ '@types/estree': 1.0.8
+
esutils@2.0.3: {}
etag@1.8.1: {}
@@ -7530,6 +8925,8 @@ snapshots:
signal-exit: 3.0.7
strip-final-newline: 2.0.0
+ expect-type@1.3.0: {}
+
exponential-backoff@3.1.3: {}
express-ws@5.0.2(express@4.21.2):
@@ -7620,6 +9017,10 @@ snapshots:
dependencies:
pend: 1.2.0
+ fdir@6.5.0(picomatch@4.0.3):
+ optionalDependencies:
+ picomatch: 4.0.3
+
filename-reserved-regex@2.0.0: {}
filenamify@4.3.0:
@@ -7741,6 +9142,8 @@ snapshots:
gar@1.0.4:
optional: true
+ gensync@1.0.0-beta.2: {}
+
get-caller-file@2.0.5: {}
get-folder-size@2.0.1:
@@ -7859,6 +9262,18 @@ snapshots:
handle-thing@2.0.1: {}
+ happy-dom@20.7.0:
+ dependencies:
+ '@types/node': 22.18.13
+ '@types/whatwg-mimetype': 3.0.2
+ '@types/ws': 8.18.1
+ entities: 7.0.1
+ whatwg-mimetype: 3.0.0
+ ws: 8.18.3
+ transitivePeerDependencies:
+ - bufferutil
+ - utf-8-validate
+
has-flag@4.0.0: {}
has-property-descriptors@1.0.2:
@@ -7887,6 +9302,12 @@ snapshots:
readable-stream: 2.3.8
wbuf: 1.7.3
+ html-encoding-sniffer@6.0.0:
+ dependencies:
+ '@exodus/bytes': 1.14.1
+ transitivePeerDependencies:
+ - '@noble/hashes'
+
html-entities@2.6.0: {}
html-minifier-terser@6.1.0:
@@ -8090,6 +9511,8 @@ snapshots:
dependencies:
isobject: 3.0.1
+ is-potential-custom-element-name@1.0.1: {}
+
is-stream@1.1.0: {}
is-stream@2.0.1: {}
@@ -8122,6 +9545,35 @@ snapshots:
dependencies:
argparse: 2.0.1
+ jsdom@28.1.0:
+ dependencies:
+ '@acemir/cssom': 0.9.31
+ '@asamuzakjp/dom-selector': 6.8.1
+ '@bramus/specificity': 2.4.2
+ '@exodus/bytes': 1.14.1
+ cssstyle: 6.1.0
+ data-urls: 7.0.0
+ decimal.js: 10.6.0
+ html-encoding-sniffer: 6.0.0
+ http-proxy-agent: 7.0.2
+ https-proxy-agent: 7.0.6
+ is-potential-custom-element-name: 1.0.1
+ parse5: 8.0.0
+ saxes: 6.0.0
+ symbol-tree: 3.2.4
+ tough-cookie: 6.0.0
+ undici: 7.22.0
+ w3c-xmlserializer: 5.0.0
+ webidl-conversions: 8.0.1
+ whatwg-mimetype: 5.0.0
+ whatwg-url: 16.0.1
+ xml-name-validator: 5.0.0
+ transitivePeerDependencies:
+ - '@noble/hashes'
+ - supports-color
+
+ jsesc@3.1.0: {}
+
json-buffer@3.0.1: {}
json-parse-even-better-errors@2.3.1: {}
@@ -8267,12 +9719,20 @@ snapshots:
lowercase-keys@2.0.0: {}
+ lru-cache@11.2.6: {}
+
+ lru-cache@5.1.1:
+ dependencies:
+ yallist: 3.1.1
+
lru-cache@7.18.3: {}
lucide-react@0.544.0(react@19.2.0):
dependencies:
react: 19.2.0
+ lz-string@1.5.0: {}
+
magic-string@0.30.21:
dependencies:
'@jridgewell/sourcemap-codec': 1.5.5
@@ -8312,6 +9772,8 @@ snapshots:
math-intrinsics@1.1.0: {}
+ mdn-data@2.12.2: {}
+
media-typer@0.3.0: {}
mem@4.3.0:
@@ -8353,6 +9815,8 @@ snapshots:
mimic-response@3.1.0: {}
+ min-indent@1.0.1: {}
+
minimalistic-assert@1.0.1: {}
minimatch@3.1.2:
@@ -8509,6 +9973,8 @@ snapshots:
obuf@1.1.2: {}
+ obug@2.1.1: {}
+
on-finished@2.4.1:
dependencies:
ee-first: 1.1.1
@@ -8630,6 +10096,10 @@ snapshots:
json-parse-even-better-errors: 2.3.1
lines-and-columns: 1.2.4
+ parse5@8.0.0:
+ dependencies:
+ entities: 6.0.1
+
parseurl@1.3.3: {}
pascal-case@3.1.2:
@@ -8655,6 +10125,8 @@ snapshots:
dependencies:
pify: 2.3.0
+ pathe@2.0.3: {}
+
pe-library@1.0.1: {}
pend@1.2.0: {}
@@ -8663,6 +10135,8 @@ snapshots:
picomatch@2.3.1: {}
+ picomatch@4.0.3: {}
+
pify@2.3.0: {}
pkg-dir@4.2.0:
@@ -8731,6 +10205,12 @@ snapshots:
lodash: 4.17.21
renderkid: 3.0.0
+ pretty-format@27.5.1:
+ dependencies:
+ ansi-regex: 5.0.1
+ ansi-styles: 5.2.0
+ react-is: 17.0.2
+
proc-log@2.0.1: {}
process-nextick-args@2.0.1: {}
@@ -8769,6 +10249,8 @@ snapshots:
end-of-stream: 1.4.5
once: 1.4.0
+ punycode@2.3.1: {}
+
puppeteer-core@24.34.0:
dependencies:
'@puppeteer/browsers': 2.11.0
@@ -8903,6 +10385,8 @@ snapshots:
dependencies:
react: 19.2.0
+ react-is@17.0.2: {}
+
react-is@19.2.0: {}
react-redux@9.2.0(@types/react@19.2.2)(react@19.2.0)(redux@5.0.1):
@@ -8914,6 +10398,8 @@ snapshots:
'@types/react': 19.2.2
redux: 5.0.1
+ react-refresh@0.18.0: {}
+
react-remove-scroll-bar@2.3.8(@types/react@19.2.2)(react@19.2.0):
dependencies:
react: 19.2.0
@@ -9023,6 +10509,11 @@ snapshots:
dependencies:
resolve: 1.22.11
+ redent@3.0.0:
+ dependencies:
+ indent-string: 4.0.0
+ strip-indent: 3.0.0
+
redux-thunk@3.1.0(redux@5.0.1):
dependencies:
redux: 5.0.1
@@ -9108,6 +10599,37 @@ snapshots:
sprintf-js: 1.1.3
optional: true
+ rollup@4.59.0:
+ dependencies:
+ '@types/estree': 1.0.8
+ optionalDependencies:
+ '@rollup/rollup-android-arm-eabi': 4.59.0
+ '@rollup/rollup-android-arm64': 4.59.0
+ '@rollup/rollup-darwin-arm64': 4.59.0
+ '@rollup/rollup-darwin-x64': 4.59.0
+ '@rollup/rollup-freebsd-arm64': 4.59.0
+ '@rollup/rollup-freebsd-x64': 4.59.0
+ '@rollup/rollup-linux-arm-gnueabihf': 4.59.0
+ '@rollup/rollup-linux-arm-musleabihf': 4.59.0
+ '@rollup/rollup-linux-arm64-gnu': 4.59.0
+ '@rollup/rollup-linux-arm64-musl': 4.59.0
+ '@rollup/rollup-linux-loong64-gnu': 4.59.0
+ '@rollup/rollup-linux-loong64-musl': 4.59.0
+ '@rollup/rollup-linux-ppc64-gnu': 4.59.0
+ '@rollup/rollup-linux-ppc64-musl': 4.59.0
+ '@rollup/rollup-linux-riscv64-gnu': 4.59.0
+ '@rollup/rollup-linux-riscv64-musl': 4.59.0
+ '@rollup/rollup-linux-s390x-gnu': 4.59.0
+ '@rollup/rollup-linux-x64-gnu': 4.59.0
+ '@rollup/rollup-linux-x64-musl': 4.59.0
+ '@rollup/rollup-openbsd-x64': 4.59.0
+ '@rollup/rollup-openharmony-arm64': 4.59.0
+ '@rollup/rollup-win32-arm64-msvc': 4.59.0
+ '@rollup/rollup-win32-ia32-msvc': 4.59.0
+ '@rollup/rollup-win32-x64-gnu': 4.59.0
+ '@rollup/rollup-win32-x64-msvc': 4.59.0
+ fsevents: 2.3.3
+
run-parallel@1.2.0:
dependencies:
queue-microtask: 1.2.3
@@ -9118,6 +10640,10 @@ snapshots:
safer-buffer@2.1.2: {}
+ saxes@6.0.0:
+ dependencies:
+ xmlchars: 2.2.0
+
scheduler@0.27.0: {}
schema-utils@4.3.3:
@@ -9241,6 +10767,8 @@ snapshots:
side-channel-map: 1.0.1
side-channel-weakmap: 1.0.2
+ siginfo@2.0.0: {}
+
signal-exit@3.0.7: {}
signal-exit@4.1.0: {}
@@ -9337,10 +10865,14 @@ snapshots:
dependencies:
minipass: 3.3.6
+ stackback@0.0.2: {}
+
statuses@1.5.0: {}
statuses@2.0.1: {}
+ std-env@3.10.0: {}
+
streamx@2.23.0:
dependencies:
events-universal: 1.0.1
@@ -9384,6 +10916,10 @@ snapshots:
strip-final-newline@2.0.0: {}
+ strip-indent@3.0.0:
+ dependencies:
+ min-indent: 1.0.1
+
strip-outer@1.0.1:
dependencies:
escape-string-regexp: 1.0.5
@@ -9408,6 +10944,8 @@ snapshots:
supports-preserve-symlinks-flag@1.0.0: {}
+ symbol-tree@3.2.4: {}
+
tailwind-merge@3.3.1: {}
tailwindcss@4.1.16: {}
@@ -9479,6 +11017,23 @@ snapshots:
tiny-invariant@1.3.3: {}
+ tinybench@2.9.0: {}
+
+ tinyexec@1.0.2: {}
+
+ tinyglobby@0.2.15:
+ dependencies:
+ fdir: 6.5.0(picomatch@4.0.3)
+ picomatch: 4.0.3
+
+ tinyrainbow@3.0.3: {}
+
+ tldts-core@7.0.23: {}
+
+ tldts@7.0.23:
+ dependencies:
+ tldts-core: 7.0.23
+
tmp-promise@3.0.3:
dependencies:
tmp: 0.2.5
@@ -9497,8 +11052,16 @@ snapshots:
toidentifier@1.0.1: {}
+ tough-cookie@6.0.0:
+ dependencies:
+ tldts: 7.0.23
+
tr46@0.0.3: {}
+ tr46@6.0.0:
+ dependencies:
+ punycode: 2.3.1
+
trim-repeated@1.0.0:
dependencies:
escape-string-regexp: 1.0.5
@@ -9553,6 +11116,8 @@ snapshots:
undici-types@6.21.0: {}
+ undici@7.22.0: {}
+
unique-filename@2.0.1:
dependencies:
unique-slug: 3.0.0
@@ -9640,6 +11205,64 @@ snapshots:
d3-time: 3.1.0
d3-timer: 3.0.1
+ vite@7.3.1(@types/node@22.18.13)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0):
+ dependencies:
+ esbuild: 0.27.3
+ fdir: 6.5.0(picomatch@4.0.3)
+ picomatch: 4.0.3
+ postcss: 8.5.6
+ rollup: 4.59.0
+ tinyglobby: 0.2.15
+ optionalDependencies:
+ '@types/node': 22.18.13
+ fsevents: 2.3.3
+ jiti: 2.6.1
+ lightningcss: 1.30.2
+ terser: 5.44.0
+
+ vitest@4.0.18(@types/node@22.18.13)(happy-dom@20.7.0)(jiti@2.6.1)(jsdom@28.1.0)(lightningcss@1.30.2)(terser@5.44.0):
+ dependencies:
+ '@vitest/expect': 4.0.18
+ '@vitest/mocker': 4.0.18(vite@7.3.1(@types/node@22.18.13)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0))
+ '@vitest/pretty-format': 4.0.18
+ '@vitest/runner': 4.0.18
+ '@vitest/snapshot': 4.0.18
+ '@vitest/spy': 4.0.18
+ '@vitest/utils': 4.0.18
+ es-module-lexer: 1.7.0
+ expect-type: 1.3.0
+ magic-string: 0.30.21
+ obug: 2.1.1
+ pathe: 2.0.3
+ picomatch: 4.0.3
+ std-env: 3.10.0
+ tinybench: 2.9.0
+ tinyexec: 1.0.2
+ tinyglobby: 0.2.15
+ tinyrainbow: 3.0.3
+ vite: 7.3.1(@types/node@22.18.13)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)
+ why-is-node-running: 2.3.0
+ optionalDependencies:
+ '@types/node': 22.18.13
+ happy-dom: 20.7.0
+ jsdom: 28.1.0
+ transitivePeerDependencies:
+ - jiti
+ - less
+ - lightningcss
+ - msw
+ - sass
+ - sass-embedded
+ - stylus
+ - sugarss
+ - terser
+ - tsx
+ - yaml
+
+ w3c-xmlserializer@5.0.0:
+ dependencies:
+ xml-name-validator: 5.0.0
+
watchpack@2.4.4:
dependencies:
glob-to-regexp: 0.4.1
@@ -9657,6 +11280,8 @@ snapshots:
webidl-conversions@3.0.1: {}
+ webidl-conversions@8.0.1: {}
+
webpack-cli@6.0.1(webpack@5.102.1):
dependencies:
'@discoveryjs/json-ext': 0.6.3
@@ -9780,6 +11405,18 @@ snapshots:
websocket-extensions@0.1.4: {}
+ whatwg-mimetype@3.0.0: {}
+
+ whatwg-mimetype@5.0.0: {}
+
+ whatwg-url@16.0.1:
+ dependencies:
+ '@exodus/bytes': 1.14.1
+ tr46: 6.0.0
+ webidl-conversions: 8.0.1
+ transitivePeerDependencies:
+ - '@noble/hashes'
+
whatwg-url@5.0.0:
dependencies:
tr46: 0.0.3
@@ -9793,6 +11430,11 @@ snapshots:
dependencies:
isexe: 2.0.0
+ why-is-node-running@2.3.0:
+ dependencies:
+ siginfo: 2.0.0
+ stackback: 0.0.2
+
wildcard@2.0.1: {}
word-wrap@1.2.5:
@@ -9822,8 +11464,12 @@ snapshots:
ws@8.18.3: {}
+ xml-name-validator@5.0.0: {}
+
xmlbuilder@15.1.1: {}
+ xmlchars@2.2.0: {}
+
xterm-addon-fit@0.5.0(xterm@4.19.0):
dependencies:
xterm: 4.19.0
@@ -9836,6 +11482,8 @@ snapshots:
y18n@5.0.8: {}
+ yallist@3.1.1: {}
+
yallist@4.0.0: {}
yargs-parser@20.2.9:
diff --git a/src/components/automationBuilder/nodeDetails/stepTypes/browser/ClickStep.test.tsx b/src/components/automationBuilder/nodeDetails/stepTypes/browser/ClickStep.test.tsx
new file mode 100644
index 0000000..f49e422
--- /dev/null
+++ b/src/components/automationBuilder/nodeDetails/stepTypes/browser/ClickStep.test.tsx
@@ -0,0 +1,84 @@
+import { ClickStep } from "@components/automationBuilder/nodeDetails/stepTypes/browser/ClickStep";
+import type { TestStep } from "@src/test/testUtils";
+import { createMockStepProps } from "@src/test/testUtils";
+import { render, screen } from "@testing-library/react";
+import { describe, expect, it, vi } from "vitest";
+
+describe("ClickStep", () => {
+ it("renders without errors", () => {
+ const step = {
+ type: "click" as const,
+ selector: "#button",
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ expect(screen.getByPlaceholderText("Selector")).toBeInTheDocument();
+ });
+
+ it("returns null when step type does not match", () => {
+ const step = {
+ type: "navigate" as const,
+ value: "https://example.com",
+ };
+ const props = createMockStepProps(step);
+
+ const { container } = render();
+ expect(container.firstChild).toBeNull();
+ });
+
+ it("displays selector value from props", () => {
+ const step = {
+ type: "click" as const,
+ selector: ".my-selector",
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ const input = screen.getByPlaceholderText("Selector") as HTMLInputElement;
+ expect(input.value).toBe(".my-selector");
+ });
+
+ it("handles empty selector", () => {
+ const step = {
+ type: "click" as const,
+ selector: "",
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ const input = screen.getByPlaceholderText("Selector") as HTMLInputElement;
+ expect(input.value).toBe("");
+ });
+
+ it("accepts onUpdate callback prop", () => {
+ const onUpdate = vi.fn();
+ const step = {
+ type: "click" as const,
+ selector: "#button",
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ expect(screen.getByPlaceholderText("Selector")).toBeInTheDocument();
+ });
+
+ it("accepts onPickWithSetter callback prop", () => {
+ const onPickWithSetter = vi.fn();
+ const step = {
+ type: "click" as const,
+ selector: "#button",
+ };
+ const props = createMockStepProps(step);
+
+ render(
+
+ );
+ expect(screen.getByPlaceholderText("Selector")).toBeInTheDocument();
+ });
+});
diff --git a/src/components/automationBuilder/nodeDetails/stepTypes/browser/ExtractStep.test.tsx b/src/components/automationBuilder/nodeDetails/stepTypes/browser/ExtractStep.test.tsx
new file mode 100644
index 0000000..a777bd2
--- /dev/null
+++ b/src/components/automationBuilder/nodeDetails/stepTypes/browser/ExtractStep.test.tsx
@@ -0,0 +1,78 @@
+import { ExtractStep } from "@components/automationBuilder/nodeDetails/stepTypes/browser/ExtractStep";
+import { createMockStepProps } from "@src/test/testUtils";
+import { render, screen } from "@testing-library/react";
+import { describe, expect, it, vi } from "vitest";
+
+describe("ExtractStep", () => {
+ it("renders without errors", () => {
+ const step = {
+ type: "extract" as const,
+ selector: ".price",
+ storeKey: "productPrice",
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ expect(screen.getByPlaceholderText("Selector")).toBeInTheDocument();
+ expect(screen.getByPlaceholderText("e.g., productPrice, title")).toBeInTheDocument();
+ });
+
+ it("returns null when step type does not match", () => {
+ const step = {
+ type: "click" as const,
+ selector: "#button",
+ };
+ const props = createMockStepProps(step);
+
+ const { container } = render();
+ expect(container.firstChild).toBeNull();
+ });
+
+ it("displays selector and storeKey from props", () => {
+ const step = {
+ type: "extract" as const,
+ selector: ".title",
+ storeKey: "pageTitle",
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ const selectorInput = screen.getByPlaceholderText("Selector") as HTMLInputElement;
+ const storeKeyInput = screen.getByPlaceholderText(
+ "e.g., productPrice, title"
+ ) as HTMLInputElement;
+ expect(selectorInput.value).toBe(".title");
+ expect(storeKeyInput.value).toBe("pageTitle");
+ });
+
+ it("handles empty values", () => {
+ const step = {
+ type: "extract" as const,
+ selector: "",
+ storeKey: "",
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ const selectorInput = screen.getByPlaceholderText("Selector") as HTMLInputElement;
+ const storeKeyInput = screen.getByPlaceholderText(
+ "e.g., productPrice, title"
+ ) as HTMLInputElement;
+ expect(selectorInput.value).toBe("");
+ expect(storeKeyInput.value).toBe("");
+ });
+
+ it("accepts all required callback props", () => {
+ const onUpdate = vi.fn();
+ const onPickWithSetter = vi.fn();
+ const step = {
+ type: "extract" as const,
+ selector: ".price",
+ storeKey: "price",
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ expect(screen.getByPlaceholderText("Selector")).toBeInTheDocument();
+ });
+});
diff --git a/src/components/automationBuilder/nodeDetails/stepTypes/browser/NavigateStep.test.tsx b/src/components/automationBuilder/nodeDetails/stepTypes/browser/NavigateStep.test.tsx
new file mode 100644
index 0000000..c72d5d8
--- /dev/null
+++ b/src/components/automationBuilder/nodeDetails/stepTypes/browser/NavigateStep.test.tsx
@@ -0,0 +1,64 @@
+import { NavigateStep } from "@components/automationBuilder/nodeDetails/stepTypes/browser/NavigateStep";
+import { createMockStepProps } from "@src/test/testUtils";
+import { render, screen } from "@testing-library/react";
+import { describe, expect, it, vi } from "vitest";
+
+describe("NavigateStep", () => {
+ it("renders without errors", () => {
+ const step = {
+ type: "navigate" as const,
+ value: "https://example.com",
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ expect(screen.getByPlaceholderText("https://google.com")).toBeInTheDocument();
+ });
+
+ it("returns null when step type does not match", () => {
+ const step = {
+ type: "click" as const,
+ selector: "#button",
+ };
+ const props = createMockStepProps(step);
+
+ const { container } = render();
+ expect(container.firstChild).toBeNull();
+ });
+
+ it("displays URL value from props", () => {
+ const step = {
+ type: "navigate" as const,
+ value: "https://example.com",
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ const input = screen.getByPlaceholderText("https://google.com") as HTMLInputElement;
+ expect(input.value).toBe("https://example.com");
+ });
+
+ it("handles empty URL", () => {
+ const step = {
+ type: "navigate" as const,
+ value: "",
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ const input = screen.getByPlaceholderText("https://google.com") as HTMLInputElement;
+ expect(input.value).toBe("");
+ });
+
+ it("accepts onUpdate callback prop", () => {
+ const onUpdate = vi.fn();
+ const step = {
+ type: "navigate" as const,
+ value: "https://example.com",
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ expect(screen.getByPlaceholderText("https://google.com")).toBeInTheDocument();
+ });
+});
diff --git a/src/components/automationBuilder/nodeDetails/stepTypes/browser/ScreenshotStep.test.tsx b/src/components/automationBuilder/nodeDetails/stepTypes/browser/ScreenshotStep.test.tsx
new file mode 100644
index 0000000..b2369b1
--- /dev/null
+++ b/src/components/automationBuilder/nodeDetails/stepTypes/browser/ScreenshotStep.test.tsx
@@ -0,0 +1,64 @@
+import { ScreenshotStep } from "@components/automationBuilder/nodeDetails/stepTypes/browser/ScreenshotStep";
+import { createMockStepProps } from "@src/test/testUtils";
+import { render, screen } from "@testing-library/react";
+import { describe, expect, it, vi } from "vitest";
+
+describe("ScreenshotStep", () => {
+ it("renders without errors", () => {
+ const step = {
+ type: "screenshot" as const,
+ savePath: "screenshots/test.png",
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ expect(screen.getByPlaceholderText("save/path/filename.png")).toBeInTheDocument();
+ });
+
+ it("returns null when step type does not match", () => {
+ const step = {
+ type: "click" as const,
+ selector: "#button",
+ };
+ const props = createMockStepProps(step);
+
+ const { container } = render();
+ expect(container.firstChild).toBeNull();
+ });
+
+ it("displays savePath from props", () => {
+ const step = {
+ type: "screenshot" as const,
+ savePath: "images/screenshot.png",
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ const input = screen.getByPlaceholderText("save/path/filename.png") as HTMLInputElement;
+ expect(input.value).toBe("images/screenshot.png");
+ });
+
+ it("handles empty savePath", () => {
+ const step = {
+ type: "screenshot" as const,
+ savePath: "",
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ const input = screen.getByPlaceholderText("save/path/filename.png") as HTMLInputElement;
+ expect(input.value).toBe("");
+ });
+
+ it("accepts onUpdate callback prop", () => {
+ const onUpdate = vi.fn();
+ const step = {
+ type: "screenshot" as const,
+ savePath: "test.png",
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ expect(screen.getByPlaceholderText("save/path/filename.png")).toBeInTheDocument();
+ });
+});
diff --git a/src/components/automationBuilder/nodeDetails/stepTypes/browser/ScrollStep.test.tsx b/src/components/automationBuilder/nodeDetails/stepTypes/browser/ScrollStep.test.tsx
new file mode 100644
index 0000000..cc43c0a
--- /dev/null
+++ b/src/components/automationBuilder/nodeDetails/stepTypes/browser/ScrollStep.test.tsx
@@ -0,0 +1,83 @@
+import { ScrollStep } from "@components/automationBuilder/nodeDetails/stepTypes/browser/ScrollStep";
+import { createMockStepProps } from "@src/test/testUtils";
+import { render, screen } from "@testing-library/react";
+import { describe, expect, it, vi } from "vitest";
+
+describe("ScrollStep", () => {
+ it("renders without errors for toElement scrollType", () => {
+ const step = {
+ type: "scroll" as const,
+ scrollType: "toElement" as const,
+ selector: ".target",
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ expect(screen.getByText("To element")).toBeInTheDocument();
+ expect(screen.getByPlaceholderText("Selector")).toBeInTheDocument();
+ });
+
+ it("renders without errors for byAmount scrollType", () => {
+ const step = {
+ type: "scroll" as const,
+ scrollType: "byAmount" as const,
+ scrollAmount: 200,
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ expect(screen.getByText("By amount")).toBeInTheDocument();
+ expect(screen.getByPlaceholderText("e.g. 200")).toBeInTheDocument();
+ });
+
+ it("returns null when step type does not match", () => {
+ const step = {
+ type: "click" as const,
+ selector: "#button",
+ };
+ const props = createMockStepProps(step);
+
+ const { container } = render();
+ expect(container.firstChild).toBeNull();
+ });
+
+ it("displays scroll amount from props", () => {
+ const step = {
+ type: "scroll" as const,
+ scrollType: "byAmount" as const,
+ scrollAmount: 500,
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ const input = screen.getByPlaceholderText("e.g. 200") as HTMLInputElement;
+ expect(input.value).toBe("500");
+ });
+
+ it("displays selector for toElement type", () => {
+ const step = {
+ type: "scroll" as const,
+ scrollType: "toElement" as const,
+ selector: "#footer",
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ const input = screen.getByPlaceholderText("Selector") as HTMLInputElement;
+ expect(input.value).toBe("#footer");
+ });
+
+ it("accepts all required callback props", () => {
+ const onUpdate = vi.fn();
+ const onPickWithSetter = vi.fn();
+ const step = {
+ type: "scroll" as const,
+ scrollType: "toElement" as const,
+ selector: ".target",
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ expect(screen.getByText("To element")).toBeInTheDocument();
+ });
+});
diff --git a/src/components/automationBuilder/nodeDetails/stepTypes/browser/SelectOptionStep.test.tsx b/src/components/automationBuilder/nodeDetails/stepTypes/browser/SelectOptionStep.test.tsx
new file mode 100644
index 0000000..b28797e
--- /dev/null
+++ b/src/components/automationBuilder/nodeDetails/stepTypes/browser/SelectOptionStep.test.tsx
@@ -0,0 +1,81 @@
+import { SelectOptionStep } from "@components/automationBuilder/nodeDetails/stepTypes/browser/SelectOptionStep";
+import { createMockStepProps } from "@src/test/testUtils";
+import { render, screen } from "@testing-library/react";
+import { describe, expect, it, vi } from "vitest";
+
+describe("SelectOptionStep", () => {
+ it("renders without errors", () => {
+ const step = {
+ type: "selectOption" as const,
+ selector: "select#dropdown",
+ optionValue: "option1",
+ optionIndex: 0,
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ expect(screen.getByPlaceholderText("Selector")).toBeInTheDocument();
+ expect(screen.getByPlaceholderText("Option value to select")).toBeInTheDocument();
+ expect(screen.getByPlaceholderText("Option index to select")).toBeInTheDocument();
+ });
+
+ it("returns null when step type does not match", () => {
+ const step = {
+ type: "click" as const,
+ selector: "#button",
+ };
+ const props = createMockStepProps(step);
+
+ const { container } = render();
+ expect(container.firstChild).toBeNull();
+ });
+
+ it("displays selector, optionValue, and optionIndex from props", () => {
+ const step = {
+ type: "selectOption" as const,
+ selector: "select#country",
+ optionValue: "usa",
+ optionIndex: 2,
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ const selectorInput = screen.getByPlaceholderText("Selector") as HTMLInputElement;
+ const valueInput = screen.getByPlaceholderText("Option value to select") as HTMLInputElement;
+ const indexInput = screen.getByPlaceholderText("Option index to select") as HTMLInputElement;
+ expect(selectorInput.value).toBe("select#country");
+ expect(valueInput.value).toBe("usa");
+ expect(indexInput.value).toBe("2");
+ });
+
+ it("handles empty values", () => {
+ const step = {
+ type: "selectOption" as const,
+ selector: "",
+ optionValue: "",
+ optionIndex: 0,
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ const selectorInput = screen.getByPlaceholderText("Selector") as HTMLInputElement;
+ const valueInput = screen.getByPlaceholderText("Option value to select") as HTMLInputElement;
+ expect(selectorInput.value).toBe("");
+ expect(valueInput.value).toBe("");
+ });
+
+ it("accepts all required callback props", () => {
+ const onUpdate = vi.fn();
+ const onPickWithSetter = vi.fn();
+ const step = {
+ type: "selectOption" as const,
+ selector: "select",
+ optionValue: "value",
+ optionIndex: 0,
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ expect(screen.getByPlaceholderText("Selector")).toBeInTheDocument();
+ });
+});
diff --git a/src/components/automationBuilder/nodeDetails/stepTypes/browser/TypeStep.test.tsx b/src/components/automationBuilder/nodeDetails/stepTypes/browser/TypeStep.test.tsx
new file mode 100644
index 0000000..f6f075e
--- /dev/null
+++ b/src/components/automationBuilder/nodeDetails/stepTypes/browser/TypeStep.test.tsx
@@ -0,0 +1,75 @@
+import type { AutomationStep } from "@app-types/steps";
+import { TypeStep } from "@components/automationBuilder/nodeDetails/stepTypes/browser/TypeStep";
+import { createMockStepProps } from "@src/test/testUtils";
+import { render, screen } from "@testing-library/react";
+import { describe, expect, it, vi } from "vitest";
+
+describe("TypeStep", () => {
+ it("renders without errors", () => {
+ const step = {
+ type: "type" as const,
+ selector: "#input",
+ value: "Hello World",
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ expect(screen.getByPlaceholderText("Selector")).toBeInTheDocument();
+ expect(screen.getByPlaceholderText("Text to type")).toBeInTheDocument();
+ });
+
+ it("returns null when step type does not match", () => {
+ const step = {
+ type: "click" as const,
+ selector: "#button",
+ };
+ const props = createMockStepProps(step);
+
+ const { container } = render();
+ expect(container.firstChild).toBeNull();
+ });
+
+ it("displays selector and value from props", () => {
+ const step = {
+ type: "type" as const,
+ selector: "#input",
+ value: "Test value",
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ const selectorInput = screen.getByPlaceholderText("Selector") as HTMLInputElement;
+ const valueInput = screen.getByPlaceholderText("Text to type") as HTMLInputElement;
+ expect(selectorInput.value).toBe("#input");
+ expect(valueInput.value).toBe("Test value");
+ });
+
+ it("handles empty values", () => {
+ const step = {
+ type: "type" as const,
+ selector: "",
+ value: "",
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ const selectorInput = screen.getByPlaceholderText("Selector") as HTMLInputElement;
+ const valueInput = screen.getByPlaceholderText("Text to type") as HTMLInputElement;
+ expect(selectorInput.value).toBe("");
+ expect(valueInput.value).toBe("");
+ });
+
+ it("accepts all required callback props", () => {
+ const onUpdate = vi.fn();
+ const onPickWithSetter = vi.fn();
+ const step = {
+ type: "type" as const,
+ selector: "#input",
+ value: "text",
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ expect(screen.getByPlaceholderText("Selector")).toBeInTheDocument();
+ });
+});
diff --git a/src/components/automationBuilder/nodeDetails/stepTypes/browser/WaitStep.test.tsx b/src/components/automationBuilder/nodeDetails/stepTypes/browser/WaitStep.test.tsx
new file mode 100644
index 0000000..decc68a
--- /dev/null
+++ b/src/components/automationBuilder/nodeDetails/stepTypes/browser/WaitStep.test.tsx
@@ -0,0 +1,64 @@
+import { WaitStep } from "@components/automationBuilder/nodeDetails/stepTypes/browser/WaitStep";
+import { createMockStepProps } from "@src/test/testUtils";
+import { render, screen } from "@testing-library/react";
+import { describe, expect, it, vi } from "vitest";
+
+describe("WaitStep", () => {
+ it("renders without errors", () => {
+ const step = {
+ type: "wait" as const,
+ value: "5",
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ expect(screen.getByPlaceholderText("Milliseconds to wait")).toBeInTheDocument();
+ });
+
+ it("returns null when step type does not match", () => {
+ const step = {
+ type: "click" as const,
+ selector: "#button",
+ };
+ const props = createMockStepProps(step);
+
+ const { container } = render();
+ expect(container.firstChild).toBeNull();
+ });
+
+ it("displays duration value from props", () => {
+ const step = {
+ type: "wait" as const,
+ value: "10",
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ const input = screen.getByPlaceholderText("Milliseconds to wait") as HTMLInputElement;
+ expect(input.value).toBe("10");
+ });
+
+ it("handles default value", () => {
+ const step = {
+ type: "wait" as const,
+ value: "",
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ const input = screen.getByPlaceholderText("Milliseconds to wait") as HTMLInputElement;
+ expect(input).toBeInTheDocument();
+ });
+
+ it("accepts onUpdate callback prop", () => {
+ const onUpdate = vi.fn();
+ const step = {
+ type: "wait" as const,
+ value: "5",
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ expect(screen.getByPlaceholderText("Milliseconds to wait")).toBeInTheDocument();
+ });
+});
diff --git a/src/components/automationBuilder/nodeDetails/stepTypes/discord/DiscordSendMessageStep.test.tsx b/src/components/automationBuilder/nodeDetails/stepTypes/discord/DiscordSendMessageStep.test.tsx
new file mode 100644
index 0000000..53762ff
--- /dev/null
+++ b/src/components/automationBuilder/nodeDetails/stepTypes/discord/DiscordSendMessageStep.test.tsx
@@ -0,0 +1,59 @@
+import { DiscordSendMessageStep } from "@components/automationBuilder/nodeDetails/stepTypes/discord/DiscordSendMessageStep";
+import { createMockStepProps } from "@src/test/testUtils";
+import { render, screen } from "@testing-library/react";
+import { describe, expect, it, vi } from "vitest";
+
+describe("DiscordSendMessageStep", () => {
+ it("renders without errors", () => {
+ const step = {
+ type: "discordSendMessage" as const,
+ channelId: "123456789",
+ content: "Test message",
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ expect(screen.getByPlaceholderText("Channel ID")).toBeInTheDocument();
+ });
+
+ it("returns null when step type does not match", () => {
+ const step = {
+ type: "click" as const,
+ selector: "#button",
+ };
+ const props = createMockStepProps(step);
+
+ const { container } = render();
+ expect(container.firstChild).toBeNull();
+ });
+
+ it("displays channelId and content from props", () => {
+ const step = {
+ type: "discordSendMessage" as const,
+ channelId: "987654321",
+ content: "Hello Discord",
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ const channelInput = screen.getByPlaceholderText("Channel ID") as HTMLInputElement;
+ const contentInput = screen.getByPlaceholderText(
+ "Message content (supports variables like {{name}})"
+ ) as HTMLTextAreaElement;
+ expect(channelInput.value).toBe("987654321");
+ expect(contentInput.value).toBe("Hello Discord");
+ });
+
+ it("accepts onUpdate callback prop", () => {
+ const onUpdate = vi.fn();
+ const step = {
+ type: "discordSendMessage" as const,
+ channelId: "123",
+ content: "Test",
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ expect(screen.getByPlaceholderText("Channel ID")).toBeInTheDocument();
+ });
+});
diff --git a/src/components/automationBuilder/nodeDetails/stepTypes/integration/AiOpenAIStep.test.tsx b/src/components/automationBuilder/nodeDetails/stepTypes/integration/AiOpenAIStep.test.tsx
new file mode 100644
index 0000000..1d429c7
--- /dev/null
+++ b/src/components/automationBuilder/nodeDetails/stepTypes/integration/AiOpenAIStep.test.tsx
@@ -0,0 +1,63 @@
+import { AiOpenAIStep } from "@components/automationBuilder/nodeDetails/stepTypes/integration/AiOpenAIStep";
+import { createMockStepProps } from "@src/test/testUtils";
+import { render, screen } from "@testing-library/react";
+import { describe, expect, it, vi } from "vitest";
+
+describe("AiOpenAIStep", () => {
+ it("renders without errors", () => {
+ const step = {
+ type: "aiOpenAI" as const,
+ model: "gpt-4o-mini",
+ prompt: "Test prompt",
+ temperature: 0,
+ maxTokens: 256,
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ expect(screen.getByPlaceholderText("e.g., gpt-4o-mini, gpt-4-turbo")).toBeInTheDocument();
+ });
+
+ it("returns null when step type does not match", () => {
+ const step = {
+ type: "click" as const,
+ selector: "#button",
+ };
+ const props = createMockStepProps(step);
+
+ const { container } = render();
+ expect(container.firstChild).toBeNull();
+ });
+
+ it("displays model value from props", () => {
+ const step = {
+ type: "aiOpenAI" as const,
+ model: "gpt-4-turbo",
+ prompt: "Test",
+ temperature: 0.5,
+ maxTokens: 512,
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ const modelInput = screen.getByPlaceholderText(
+ "e.g., gpt-4o-mini, gpt-4-turbo"
+ ) as HTMLInputElement;
+ expect(modelInput.value).toBe("gpt-4-turbo");
+ });
+
+ it("accepts onUpdate callback prop", () => {
+ const onUpdate = vi.fn();
+ const step = {
+ type: "aiOpenAI" as const,
+ model: "gpt-4o-mini",
+ prompt: "Test",
+ temperature: 0,
+ maxTokens: 256,
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ expect(screen.getByPlaceholderText("e.g., gpt-4o-mini, gpt-4-turbo")).toBeInTheDocument();
+ });
+});
diff --git a/src/components/automationBuilder/nodeDetails/stepTypes/integration/ApiCallStep.test.tsx b/src/components/automationBuilder/nodeDetails/stepTypes/integration/ApiCallStep.test.tsx
new file mode 100644
index 0000000..3395e6a
--- /dev/null
+++ b/src/components/automationBuilder/nodeDetails/stepTypes/integration/ApiCallStep.test.tsx
@@ -0,0 +1,87 @@
+import { ApiCallStep } from "@components/automationBuilder/nodeDetails/stepTypes/integration/ApiCallStep";
+import { createMockStepProps } from "@src/test/testUtils";
+import { render, screen } from "@testing-library/react";
+import { describe, expect, it, vi } from "vitest";
+
+describe("ApiCallStep", () => {
+ it("renders without errors", () => {
+ const step = {
+ type: "apiCall" as const,
+ method: "GET" as const,
+ url: "https://api.example.com",
+ headers: {},
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ expect(screen.getByPlaceholderText("https://api.example.com/endpoint")).toBeInTheDocument();
+ });
+
+ it("returns null when step type does not match", () => {
+ const step = {
+ type: "click" as const,
+ selector: "#button",
+ };
+ const props = createMockStepProps(step);
+
+ const { container } = render();
+ expect(container.firstChild).toBeNull();
+ });
+
+ it("displays URL from props", () => {
+ const step = {
+ type: "apiCall" as const,
+ method: "GET" as const,
+ url: "https://api.test.com/endpoint",
+ headers: {},
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ const urlInput = screen.getByPlaceholderText(
+ "https://api.example.com/endpoint"
+ ) as HTMLInputElement;
+ expect(urlInput.value).toBe("https://api.test.com/endpoint");
+ });
+
+ it("shows body field for POST method", () => {
+ const step = {
+ type: "apiCall" as const,
+ method: "POST" as const,
+ url: "https://api.example.com",
+ body: '{"test": "data"}',
+ headers: {},
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ expect(screen.getByPlaceholderText('{"key": "value"}')).toBeInTheDocument();
+ });
+
+ it("hides body field for GET method", () => {
+ const step = {
+ type: "apiCall" as const,
+ method: "GET" as const,
+ url: "https://api.example.com",
+ headers: {},
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ expect(screen.queryByPlaceholderText('{"key": "value"}')).not.toBeInTheDocument();
+ });
+
+ it("accepts onUpdate callback prop", () => {
+ const onUpdate = vi.fn();
+ const step = {
+ type: "apiCall" as const,
+ method: "GET" as const,
+ url: "https://api.example.com",
+ headers: {},
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ expect(screen.getByPlaceholderText("https://api.example.com/endpoint")).toBeInTheDocument();
+ });
+});
diff --git a/src/components/automationBuilder/nodeDetails/stepTypes/slack/SlackSendMessageStep.test.tsx b/src/components/automationBuilder/nodeDetails/stepTypes/slack/SlackSendMessageStep.test.tsx
new file mode 100644
index 0000000..05c0191
--- /dev/null
+++ b/src/components/automationBuilder/nodeDetails/stepTypes/slack/SlackSendMessageStep.test.tsx
@@ -0,0 +1,65 @@
+import { SlackSendMessageStep } from "@components/automationBuilder/nodeDetails/stepTypes/slack/SlackSendMessageStep";
+import { createMockStepProps } from "@src/test/testUtils";
+import { render, screen } from "@testing-library/react";
+import { describe, expect, it, vi } from "vitest";
+
+describe("SlackSendMessageStep", () => {
+ it("renders without errors", () => {
+ const step = {
+ type: "slackSendMessage" as const,
+ channelId: "C123456",
+ text: "Test message",
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ expect(
+ screen.getByPlaceholderText("Channel ID or name (e.g., C123456 or #general)")
+ ).toBeInTheDocument();
+ });
+
+ it("returns null when step type does not match", () => {
+ const step = {
+ type: "click" as const,
+ selector: "#button",
+ };
+ const props = createMockStepProps(step);
+
+ const { container } = render();
+ expect(container.firstChild).toBeNull();
+ });
+
+ it("displays channelId and text from props", () => {
+ const step = {
+ type: "slackSendMessage" as const,
+ channelId: "#general",
+ text: "Hello Slack",
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ const channelInput = screen.getByPlaceholderText(
+ "Channel ID or name (e.g., C123456 or #general)"
+ ) as HTMLInputElement;
+ const textInput = screen.getByPlaceholderText(
+ "Message content (supports variables like {{variableName}})"
+ ) as HTMLTextAreaElement;
+ expect(channelInput.value).toBe("#general");
+ expect(textInput.value).toBe("Hello Slack");
+ });
+
+ it("accepts onUpdate callback prop", () => {
+ const onUpdate = vi.fn();
+ const step = {
+ type: "slackSendMessage" as const,
+ channelId: "C123",
+ text: "Test",
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ expect(
+ screen.getByPlaceholderText("Channel ID or name (e.g., C123456 or #general)")
+ ).toBeInTheDocument();
+ });
+});
diff --git a/src/components/automationBuilder/nodeDetails/stepTypes/twitter/TwitterCreateTweetStep.test.tsx b/src/components/automationBuilder/nodeDetails/stepTypes/twitter/TwitterCreateTweetStep.test.tsx
new file mode 100644
index 0000000..7e30b4f
--- /dev/null
+++ b/src/components/automationBuilder/nodeDetails/stepTypes/twitter/TwitterCreateTweetStep.test.tsx
@@ -0,0 +1,64 @@
+import { TwitterCreateTweetStep } from "@components/automationBuilder/nodeDetails/stepTypes/twitter/TwitterCreateTweetStep";
+import { createMockStepProps } from "@src/test/testUtils";
+import { render, screen } from "@testing-library/react";
+import { describe, expect, it, vi } from "vitest";
+
+describe("TwitterCreateTweetStep", () => {
+ it("renders without errors", () => {
+ const step = {
+ type: "twitterCreateTweet" as const,
+ text: "Test tweet",
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ expect(screen.getByPlaceholderText("What's happening?")).toBeInTheDocument();
+ });
+
+ it("returns null when step type does not match", () => {
+ const step = {
+ type: "click" as const,
+ selector: "#button",
+ };
+ const props = createMockStepProps(step);
+
+ const { container } = render();
+ expect(container.firstChild).toBeNull();
+ });
+
+ it("displays tweet text from props", () => {
+ const step = {
+ type: "twitterCreateTweet" as const,
+ text: "Hello Twitter!",
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ const textInput = screen.getByPlaceholderText("What's happening?") as HTMLTextAreaElement;
+ expect(textInput.value).toBe("Hello Twitter!");
+ });
+
+ it("handles empty text", () => {
+ const step = {
+ type: "twitterCreateTweet" as const,
+ text: "",
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ const textInput = screen.getByPlaceholderText("What's happening?") as HTMLTextAreaElement;
+ expect(textInput.value).toBe("");
+ });
+
+ it("accepts onUpdate callback prop", () => {
+ const onUpdate = vi.fn();
+ const step = {
+ type: "twitterCreateTweet" as const,
+ text: "Test tweet",
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ expect(screen.getByPlaceholderText("What's happening?")).toBeInTheDocument();
+ });
+});
diff --git a/src/components/automationBuilder/nodeDetails/stepTypes/variable/ModifyVariableStep.test.tsx b/src/components/automationBuilder/nodeDetails/stepTypes/variable/ModifyVariableStep.test.tsx
new file mode 100644
index 0000000..df422e5
--- /dev/null
+++ b/src/components/automationBuilder/nodeDetails/stepTypes/variable/ModifyVariableStep.test.tsx
@@ -0,0 +1,79 @@
+import { ModifyVariableStep } from "@components/automationBuilder/nodeDetails/stepTypes/variable/ModifyVariableStep";
+import { createMockStepProps } from "@src/test/testUtils";
+import { render, screen } from "@testing-library/react";
+import { describe, expect, it, vi } from "vitest";
+
+describe("ModifyVariableStep", () => {
+ it("renders without errors", () => {
+ const step = {
+ type: "modifyVariable" as const,
+ variableName: "counter",
+ operation: "increment" as const,
+ value: "1",
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ expect(screen.getByPlaceholderText("variable name")).toBeInTheDocument();
+ expect(screen.getByPlaceholderText("Value or {{otherVar}}")).toBeInTheDocument();
+ });
+
+ it("returns null when step type does not match", () => {
+ const step = {
+ type: "click" as const,
+ selector: "#button",
+ };
+ const props = createMockStepProps(step);
+
+ const { container } = render();
+ expect(container.firstChild).toBeNull();
+ });
+
+ it("displays variableName, operation, and value from props", () => {
+ const step = {
+ type: "modifyVariable" as const,
+ variableName: "count",
+ operation: "increment" as const,
+ value: "5",
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ const nameInput = screen.getByPlaceholderText("variable name") as HTMLInputElement;
+ const valueInput = screen.getByPlaceholderText("Value or {{otherVar}}") as HTMLInputElement;
+ const operationSelect = screen.getByDisplayValue("Increment") as HTMLSelectElement;
+ expect(nameInput.value).toBe("count");
+ expect(valueInput.value).toBe("5");
+ expect(operationSelect.value).toBe("increment");
+ });
+
+ it("handles empty values", () => {
+ const step = {
+ type: "modifyVariable" as const,
+ variableName: "",
+ operation: "set" as const,
+ value: "",
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ const nameInput = screen.getByPlaceholderText("variable name") as HTMLInputElement;
+ const valueInput = screen.getByPlaceholderText("Value or {{otherVar}}") as HTMLInputElement;
+ expect(nameInput.value).toBe("");
+ expect(valueInput.value).toBe("");
+ });
+
+ it("accepts onUpdate callback prop", () => {
+ const onUpdate = vi.fn();
+ const step = {
+ type: "modifyVariable" as const,
+ variableName: "test",
+ operation: "set" as const,
+ value: "value",
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ expect(screen.getByPlaceholderText("variable name")).toBeInTheDocument();
+ });
+});
diff --git a/src/components/automationBuilder/nodeDetails/stepTypes/variable/SetVariableStep.test.tsx b/src/components/automationBuilder/nodeDetails/stepTypes/variable/SetVariableStep.test.tsx
new file mode 100644
index 0000000..87af8d2
--- /dev/null
+++ b/src/components/automationBuilder/nodeDetails/stepTypes/variable/SetVariableStep.test.tsx
@@ -0,0 +1,77 @@
+import { SetVariableStep } from "@components/automationBuilder/nodeDetails/stepTypes/variable/SetVariableStep";
+import { createMockStepProps } from "@src/test/testUtils";
+import { render, screen } from "@testing-library/react";
+import { describe, expect, it, vi } from "vitest";
+
+describe("SetVariableStep", () => {
+ it("renders without errors", () => {
+ const step = {
+ type: "setVariable" as const,
+ variableName: "productTitle",
+ value: "Test Product",
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ expect(screen.getByPlaceholderText("e.g. productTitle")).toBeInTheDocument();
+ expect(screen.getByPlaceholderText("Use static text or {{otherVar}}")).toBeInTheDocument();
+ });
+
+ it("returns null when step type does not match", () => {
+ const step = {
+ type: "click" as const,
+ selector: "#button",
+ };
+ const props = createMockStepProps(step);
+
+ const { container } = render();
+ expect(container.firstChild).toBeNull();
+ });
+
+ it("displays variableName and value from props", () => {
+ const step = {
+ type: "setVariable" as const,
+ variableName: "myVar",
+ value: "myValue",
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ const nameInput = screen.getByPlaceholderText("e.g. productTitle") as HTMLInputElement;
+ const valueInput = screen.getByPlaceholderText(
+ "Use static text or {{otherVar}}"
+ ) as HTMLInputElement;
+ expect(nameInput.value).toBe("myVar");
+ expect(valueInput.value).toBe("myValue");
+ });
+
+ it("handles empty values", () => {
+ const step = {
+ type: "setVariable" as const,
+ variableName: "",
+ value: "",
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ const nameInput = screen.getByPlaceholderText("e.g. productTitle") as HTMLInputElement;
+ const valueInput = screen.getByPlaceholderText(
+ "Use static text or {{otherVar}}"
+ ) as HTMLInputElement;
+ expect(nameInput.value).toBe("");
+ expect(valueInput.value).toBe("");
+ });
+
+ it("accepts onUpdate callback prop", () => {
+ const onUpdate = vi.fn();
+ const step = {
+ type: "setVariable" as const,
+ variableName: "test",
+ value: "value",
+ };
+ const props = createMockStepProps(step);
+
+ render();
+ expect(screen.getByPlaceholderText("e.g. productTitle")).toBeInTheDocument();
+ });
+});
diff --git a/src/test/setup.ts b/src/test/setup.ts
new file mode 100644
index 0000000..e11859f
--- /dev/null
+++ b/src/test/setup.ts
@@ -0,0 +1,8 @@
+import "@testing-library/jest-dom";
+import { cleanup } from "@testing-library/react";
+import { afterEach } from "vitest";
+
+// Cleanup after each test
+afterEach(() => {
+ cleanup();
+});
diff --git a/src/test/testUtils.tsx b/src/test/testUtils.tsx
new file mode 100644
index 0000000..9d7da52
--- /dev/null
+++ b/src/test/testUtils.tsx
@@ -0,0 +1,35 @@
+import type { AutomationStep } from "@app-types/steps";
+import type { StepProps } from "@components/automationBuilder/nodeDetails/stepTypes/types";
+import { render } from "@testing-library/react";
+
+// Mock functions for testing
+export const mockOnUpdate = () => {
+ // Intentionally empty for testing
+};
+export const mockOnPickWithSetter = async () => {
+ // Intentionally empty for testing
+};
+
+// Type for partial step objects in tests (id and description are optional)
+export type TestStep = Partial & { type: string };
+
+// Helper to create mock StepProps
+export function createMockStepProps(step: TestStep): StepProps {
+ const fullStep = {
+ id: "test-step-id",
+ description: "Test step description",
+ ...step,
+ } as AutomationStep;
+
+ return {
+ step: fullStep,
+ id: "test-id",
+ onUpdate: mockOnUpdate,
+ onPickWithSetter: mockOnPickWithSetter,
+ };
+}
+
+// Custom render function that includes common providers
+export function renderStep(ui: React.ReactElement) {
+ return render(ui);
+}
diff --git a/vitest.config.ts b/vitest.config.ts
new file mode 100644
index 0000000..b75f10c
--- /dev/null
+++ b/vitest.config.ts
@@ -0,0 +1,28 @@
+import { resolve } from "node:path";
+import react from "@vitejs/plugin-react";
+import { defineConfig } from "vitest/config";
+
+export default defineConfig({
+ plugins: [react()],
+ test: {
+ globals: true,
+ environment: "happy-dom",
+ setupFiles: ["./src/test/setup.ts"],
+ include: ["src/**/*.test.{ts,tsx}"],
+ coverage: {
+ provider: "v8",
+ reporter: ["text", "json", "html"],
+ exclude: ["node_modules/", "src/test/"],
+ },
+ },
+ resolve: {
+ alias: {
+ "@src": resolve(__dirname, "./src"),
+ "@components": resolve(__dirname, "./src/components"),
+ "@hooks": resolve(__dirname, "./src/hooks"),
+ "@main": resolve(__dirname, "./src/main"),
+ "@app-types": resolve(__dirname, "./src/types"),
+ "@utils": resolve(__dirname, "./src/utils"),
+ },
+ },
+});