diff --git a/.changeset/bumpy-feet-bow.md b/.changeset/bumpy-feet-bow.md
new file mode 100644
index 0000000..0a1a10c
--- /dev/null
+++ b/.changeset/bumpy-feet-bow.md
@@ -0,0 +1,5 @@
+---
+"ui-test-visualizer": minor
+---
+
+Add "Record input as code" feature
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 633b564..4d9100f 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -84,5 +84,7 @@ jobs:
- name: Install dependencies
run: pnpm install --frozen-lockfile
+ - run: pnpm run build
+
# Just run the "extension" tests to make sure the paths are detected correctly on Windows
- run: pnpm run --filter ./packages/extension test
diff --git a/.vscode/launch.json b/.vscode/launch.json
index b264dba..7ae4d97 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -90,7 +90,7 @@
"sourceMaps": true
},
{
- "name": "Bun Test Runner Example",
+ "name": "Bun + React Example",
"type": "extensionHost",
"request": "launch",
"args": [
@@ -100,6 +100,17 @@
"outFiles": ["${workspaceFolder}/build-dev/**/*.js"],
"sourceMaps": true
},
+ {
+ "name": "Bun + Solid Example",
+ "type": "extensionHost",
+ "request": "launch",
+ "args": [
+ "--extensionDevelopmentPath=${workspaceFolder}/build-dev",
+ "${workspaceFolder}/examples/bun-solid"
+ ],
+ "outFiles": ["${workspaceFolder}/build-dev/**/*.js"],
+ "sourceMaps": true
+ },
{
"name": "All examples",
"type": "extensionHost",
diff --git a/README.md b/README.md
index 004bc01..a1cf380 100644
--- a/README.md
+++ b/README.md
@@ -12,12 +12,41 @@ This is a VSCode extension: no code changes should be required to watch your UI
- [Vitest](https://vitest.dev/) or [Jest v28+](https://jestjs.io/) or [Bun Test Runner](https://bun.com/docs/test/dom)
- Your test framework is auto-detected by walking up the directories from your test file until it finds `vitest.config.{ts,js}`, `vite.config.{ts,js}`, `jest.config.{ts,js,json}`, or `bun.lock`
+ - The [Bun VSCode extension](https://marketplace.visualstudio.com/items?itemName=oven.bun-vscode) is required for Bun tests
- [jsdom](https://github.com/jsdom/jsdom) or [happy-dom](https://github.com/capricorn86/happy-dom) test environment (what you're probably already using for UI in Vitest or Jest)
## Usage
+### Visualizing tests
+
Click the "Visually Debug UI" button above your test. If there's no breakpoint in your test already, the extension will add one automatically. A side panel should open, and render your UI as you step through with the debugger.
+### Record Input as Code
+
+You can also write tests by recording your input as you interact with your UI.
+
+**Project Requirements:**
+- Test runner: Vitest, Jest, or Bun
+- Testing libraries:
+ - `@testing-library/react` or `@solidjs/testing-library`
+ - `@testing-library/user-event`
+
+Steps:
+
+- *Optional*: Generate a starter test file for a React or Solid component by right-clicking the component name in the editor (e.g. MyForm) and clicking "Create UI test".
+
+- Click the "Visually Debug UI" button to start your test
+
+- Click "Step Over" until you get your UI into the state where you want to generate new code.
+
+- Click the "Record input as code" button in the side panel, and you'll see the recorder panel appear.
+
+- Click your UI elements, or change text inputs, and the extension will generate code for you to use in your test.
+
+- Right+click to generate `expect` statements or other mouse events.
+
+- The generated code is inserted into your test file when the test is ended or restarted.
+
## UI Framework Compatibility
Since this extension hooks into the DOM API directly, you should be able to use any DOM-based UI framework, including React, Solid, Angular, Vue, Svelte, jQuery, etc.
@@ -50,14 +79,14 @@ This extension could fail to auto-build your source CSS files, in which case you
- Vitest:
- Adds a `--require` argument to the Vitest command.
- Jest:
- - Adds a `--setupFiles` argument to the Jest command in addition to any setupFiles you've already defined in your config.
+ - Adds a `--setupFiles` argument to the Jest command in addition to any setupFiles defined in your config.
+ - Bun:
+ - Adds a `--preload` argument to the `bun test` command in addition to any preloads defined in your bunfig.toml.
- **Replicates the test DOM into a real DOM**: The extension then replicates those method calls and their arguments in a VSCode WebView (the side panel), which renders your UI in a real Chromium DOM. This panel only shows a **replica** of the test DOM without your UI's Javascript, so you can't interact with it using the mouse or keyboard.
## Caveats
-- **Can be slow to run until your first breakpoint**: Because of the code inserted at startup for watching the DOM and optionally loading your styles, your test can be slightly slower to startup than when debugging your tests normally with other test extensions.
-
- **Possible de-synchronization**: The visual DOM replica gets updated incrementally as your test runs, but accurate synchronization relies on this extension's code to correctly handle every possible DOM mutation that happens in your UI. The DOM replication code is pretty thorough, even accounting for weird cases involving nested Shadow DOMs and Web Component lifecycles, but it's still possible for the visual replica to get out of sync with your actual test DOM. If this happens, you can click the panel's Refresh button to re-sync it.
## Contributing / Extension Development
diff --git a/eslint.config.js b/eslint.config.js
index 9766bea..894efd6 100644
--- a/eslint.config.js
+++ b/eslint.config.js
@@ -16,5 +16,6 @@ module.exports = config({
// Convenient for this project
'node/prefer-global/process': 'off',
'antfu/no-import-node-modules-by-path': 'off',
+ 'test/consistent-test-it': 'off',
},
})
diff --git a/examples/bun-react/bun.lock b/examples/bun-react/bun.lock
index 3ba0289..81316bc 100644
--- a/examples/bun-react/bun.lock
+++ b/examples/bun-react/bun.lock
@@ -10,9 +10,9 @@
"react-dom": "^19.2.0",
},
"devDependencies": {
- "@types/bun": "^1.3.0",
"@types/react": "^19.2.2",
"@types/react-dom": "^19.2.1",
+ "bun-types": "^1.3.0",
},
},
},
@@ -31,9 +31,7 @@
"@types/aria-query": ["@types/aria-query@5.0.4", "", {}, "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw=="],
- "@types/bun": ["@types/bun@1.3.0", "", { "dependencies": { "bun-types": "1.3.0" } }, "sha512-+lAGCYjXjip2qY375xX/scJeVRmZ5cY0wyHYyCYxNcdEXrQ4AOe3gACgd4iQ8ksOslJtW4VNxBJ8llUwc3a6AA=="],
-
- "@types/node": ["@types/node@20.19.21", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-CsGG2P3I5y48RPMfprQGfy4JPRZ6csfC3ltBZSRItG3ngggmNY/qs2uZKp4p9VbrpqNNSMzUZNFZKzgOGnd/VA=="],
+ "@types/node": ["@types/node@24.7.2", "", { "dependencies": { "undici-types": "~7.14.0" } }, "sha512-/NbVmcGTP+lj5oa4yiYxxeBjRivKQ5Ns1eSZeB99ExsEQ6rX5XYU1Zy/gGxY/ilqtD4Etx9mKyrPxZRetiahhA=="],
"@types/react": ["@types/react@19.2.2", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA=="],
@@ -73,12 +71,16 @@
"scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="],
- "undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="],
+ "undici-types": ["undici-types@7.14.0", "", {}, "sha512-QQiYxHuyZ9gQUIrmPo3IA+hUl4KYk8uSA7cHrcKd/l3p1OTpZcM0Tbp9x7FAtXdAYhlasd60ncPpgu6ihG6TOA=="],
"whatwg-mimetype": ["whatwg-mimetype@3.0.0", "", {}, "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q=="],
- "bun-types/@types/node": ["@types/node@24.7.2", "", { "dependencies": { "undici-types": "~7.14.0" } }, "sha512-/NbVmcGTP+lj5oa4yiYxxeBjRivKQ5Ns1eSZeB99ExsEQ6rX5XYU1Zy/gGxY/ilqtD4Etx9mKyrPxZRetiahhA=="],
+ "@happy-dom/global-registrator/@types/node": ["@types/node@20.19.21", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-CsGG2P3I5y48RPMfprQGfy4JPRZ6csfC3ltBZSRItG3ngggmNY/qs2uZKp4p9VbrpqNNSMzUZNFZKzgOGnd/VA=="],
+
+ "happy-dom/@types/node": ["@types/node@20.19.21", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-CsGG2P3I5y48RPMfprQGfy4JPRZ6csfC3ltBZSRItG3ngggmNY/qs2uZKp4p9VbrpqNNSMzUZNFZKzgOGnd/VA=="],
+
+ "@happy-dom/global-registrator/@types/node/undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="],
- "bun-types/@types/node/undici-types": ["undici-types@7.14.0", "", {}, "sha512-QQiYxHuyZ9gQUIrmPo3IA+hUl4KYk8uSA7cHrcKd/l3p1OTpZcM0Tbp9x7FAtXdAYhlasd60ncPpgu6ihG6TOA=="],
+ "happy-dom/@types/node/undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="],
}
}
diff --git a/examples/bun-react/bunfig.toml b/examples/bun-react/bunfig.toml
index ec27f0f..c08e690 100644
--- a/examples/bun-react/bunfig.toml
+++ b/examples/bun-react/bunfig.toml
@@ -1,6 +1,3 @@
-[serve.static]
-env = "BUN_PUBLIC_*"
-
[install]
linker = "isolated"
diff --git a/examples/bun-react/package.json b/examples/bun-react/package.json
index 079abf6..9df88fc 100644
--- a/examples/bun-react/package.json
+++ b/examples/bun-react/package.json
@@ -14,6 +14,6 @@
"devDependencies": {
"@types/react": "^19.2.2",
"@types/react-dom": "^19.2.1",
- "@types/bun": "^1.3.0"
+ "bun-types": "^1.3.0"
}
}
diff --git a/examples/bun-react/src/Counter.tsx b/examples/bun-react/src/Counter.tsx
index c1c3883..e9c4449 100644
--- a/examples/bun-react/src/Counter.tsx
+++ b/examples/bun-react/src/Counter.tsx
@@ -1,4 +1,4 @@
-import React, { useState } from 'react'
+import { useState } from 'react'
export function Counter() {
const [count, setCount] = useState(0)
@@ -14,7 +14,7 @@ export function Counter() {
return (
Counter
-
Count: {count}
+
Count: {count}
Increment
Decrement
diff --git a/examples/bun-react/test/basic.test.tsx b/examples/bun-react/test/basic.test.tsx
index 59480b8..cf59e7b 100644
--- a/examples/bun-react/test/basic.test.tsx
+++ b/examples/bun-react/test/basic.test.tsx
@@ -9,5 +9,5 @@ it('simple react testing library test', () => {
fireEvent.click(screen.getByText('Increment'))
fireEvent.click(screen.getByText('Decrement'))
- expect(screen.getByText('Count: 1')).toBeTruthy()
+ expect(screen.getByText('Count: 1'))
})
diff --git a/examples/bun-react/tsconfig.json b/examples/bun-react/tsconfig.json
index 632a36f..08dec4b 100644
--- a/examples/bun-react/tsconfig.json
+++ b/examples/bun-react/tsconfig.json
@@ -29,7 +29,9 @@
// Some stricter flags (disabled by default)
"noUnusedLocals": false,
"noUnusedParameters": false,
- "noPropertyAccessFromIndexSignature": false
+ "noPropertyAccessFromIndexSignature": false,
+
+ "types": ["bun-types"]
},
"exclude": ["dist", "node_modules"]
diff --git a/examples/bun-solid/.gitignore b/examples/bun-solid/.gitignore
new file mode 100644
index 0000000..a14702c
--- /dev/null
+++ b/examples/bun-solid/.gitignore
@@ -0,0 +1,34 @@
+# dependencies (bun install)
+node_modules
+
+# output
+out
+dist
+*.tgz
+
+# code coverage
+coverage
+*.lcov
+
+# logs
+logs
+_.log
+report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
+
+# dotenv environment variable files
+.env
+.env.development.local
+.env.test.local
+.env.production.local
+.env.local
+
+# caches
+.eslintcache
+.cache
+*.tsbuildinfo
+
+# IntelliJ based IDEs
+.idea
+
+# Finder (MacOS) folder config
+.DS_Store
diff --git a/examples/bun-solid/README.md b/examples/bun-solid/README.md
new file mode 100644
index 0000000..54a7261
--- /dev/null
+++ b/examples/bun-solid/README.md
@@ -0,0 +1,15 @@
+# bun-solid
+
+To install dependencies:
+
+```bash
+bun install
+```
+
+To run:
+
+```bash
+bun run index.ts
+```
+
+This project was created using `bun init` in bun v1.3.0. [Bun](https://bun.com) is a fast all-in-one JavaScript runtime.
diff --git a/examples/bun-solid/bun.lock b/examples/bun-solid/bun.lock
new file mode 100644
index 0000000..349ad68
--- /dev/null
+++ b/examples/bun-solid/bun.lock
@@ -0,0 +1,207 @@
+{
+ "lockfileVersion": 1,
+ "workspaces": {
+ "": {
+ "name": "bun-solid",
+ "dependencies": {
+ "solid-js": "^1.9.9",
+ },
+ "devDependencies": {
+ "@babel/core": "^7.28.4",
+ "@babel/plugin-transform-react-jsx": "^7.27.1",
+ "@babel/preset-typescript": "^7.27.1",
+ "@happy-dom/global-registrator": "^20.0.5",
+ "@solidjs/testing-library": "^0.8.10",
+ "@testing-library/user-event": "^14.6.1",
+ "@types/babel__core": "^7.20.5",
+ "babel-preset-solid": "^1.9.9",
+ "bun-types": "^1.3.0",
+ "happy-dom": "^20.0.5",
+ "typescript": "^5.9.3",
+ },
+ },
+ },
+ "packages": {
+ "@babel/code-frame": ["@babel/code-frame@7.27.1", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg=="],
+
+ "@babel/compat-data": ["@babel/compat-data@7.28.4", "", {}, "sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw=="],
+
+ "@babel/core": ["@babel/core@7.28.4", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.3", "@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-module-transforms": "^7.28.3", "@babel/helpers": "^7.28.4", "@babel/parser": "^7.28.4", "@babel/template": "^7.27.2", "@babel/traverse": "^7.28.4", "@babel/types": "^7.28.4", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA=="],
+
+ "@babel/generator": ["@babel/generator@7.28.3", "", { "dependencies": { "@babel/parser": "^7.28.3", "@babel/types": "^7.28.2", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw=="],
+
+ "@babel/helper-annotate-as-pure": ["@babel/helper-annotate-as-pure@7.27.3", "", { "dependencies": { "@babel/types": "^7.27.3" } }, "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg=="],
+
+ "@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.27.2", "", { "dependencies": { "@babel/compat-data": "^7.27.2", "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ=="],
+
+ "@babel/helper-create-class-features-plugin": ["@babel/helper-create-class-features-plugin@7.28.3", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", "@babel/helper-member-expression-to-functions": "^7.27.1", "@babel/helper-optimise-call-expression": "^7.27.1", "@babel/helper-replace-supers": "^7.27.1", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", "@babel/traverse": "^7.28.3", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-V9f6ZFIYSLNEbuGA/92uOvYsGCJNsuA8ESZ4ldc09bWk/j8H8TKiPw8Mk1eG6olpnO0ALHJmYfZvF4MEE4gajg=="],
+
+ "@babel/helper-globals": ["@babel/helper-globals@7.28.0", "", {}, "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw=="],
+
+ "@babel/helper-member-expression-to-functions": ["@babel/helper-member-expression-to-functions@7.27.1", "", { "dependencies": { "@babel/traverse": "^7.27.1", "@babel/types": "^7.27.1" } }, "sha512-E5chM8eWjTp/aNoVpcbfM7mLxu9XGLWYise2eBKGQomAk/Mb4XoxyqXTZbuTohbsl8EKqdlMhnDI2CCLfcs9wA=="],
+
+ "@babel/helper-module-imports": ["@babel/helper-module-imports@7.27.1", "", { "dependencies": { "@babel/traverse": "^7.27.1", "@babel/types": "^7.27.1" } }, "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w=="],
+
+ "@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.28.3", "", { "dependencies": { "@babel/helper-module-imports": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1", "@babel/traverse": "^7.28.3" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw=="],
+
+ "@babel/helper-optimise-call-expression": ["@babel/helper-optimise-call-expression@7.27.1", "", { "dependencies": { "@babel/types": "^7.27.1" } }, "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw=="],
+
+ "@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.27.1", "", {}, "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw=="],
+
+ "@babel/helper-replace-supers": ["@babel/helper-replace-supers@7.27.1", "", { "dependencies": { "@babel/helper-member-expression-to-functions": "^7.27.1", "@babel/helper-optimise-call-expression": "^7.27.1", "@babel/traverse": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA=="],
+
+ "@babel/helper-skip-transparent-expression-wrappers": ["@babel/helper-skip-transparent-expression-wrappers@7.27.1", "", { "dependencies": { "@babel/traverse": "^7.27.1", "@babel/types": "^7.27.1" } }, "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg=="],
+
+ "@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="],
+
+ "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.27.1", "", {}, "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="],
+
+ "@babel/helper-validator-option": ["@babel/helper-validator-option@7.27.1", "", {}, "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg=="],
+
+ "@babel/helpers": ["@babel/helpers@7.28.4", "", { "dependencies": { "@babel/template": "^7.27.2", "@babel/types": "^7.28.4" } }, "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w=="],
+
+ "@babel/parser": ["@babel/parser@7.28.4", "", { "dependencies": { "@babel/types": "^7.28.4" }, "bin": "./bin/babel-parser.js" }, "sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg=="],
+
+ "@babel/plugin-syntax-jsx": ["@babel/plugin-syntax-jsx@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w=="],
+
+ "@babel/plugin-syntax-typescript": ["@babel/plugin-syntax-typescript@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ=="],
+
+ "@babel/plugin-transform-modules-commonjs": ["@babel/plugin-transform-modules-commonjs@7.27.1", "", { "dependencies": { "@babel/helper-module-transforms": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-OJguuwlTYlN0gBZFRPqwOGNWssZjfIUdS7HMYtN8c1KmwpwHFBwTeFZrg9XZa+DFTitWOW5iTAG7tyCUPsCCyw=="],
+
+ "@babel/plugin-transform-react-jsx": ["@babel/plugin-transform-react-jsx@7.27.1", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.1", "@babel/helper-module-imports": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1", "@babel/plugin-syntax-jsx": "^7.27.1", "@babel/types": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-2KH4LWGSrJIkVf5tSiBFYuXDAoWRq2MMwgivCf+93dd0GQi8RXLjKA/0EvRnVV5G0hrHczsquXuD01L8s6dmBw=="],
+
+ "@babel/plugin-transform-typescript": ["@babel/plugin-transform-typescript@7.28.0", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", "@babel/helper-create-class-features-plugin": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", "@babel/plugin-syntax-typescript": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-4AEiDEBPIZvLQaWlc9liCavE0xRM0dNca41WtBeM3jgFptfUOSG9z0uteLhq6+3rq+WB6jIvUwKDTpXEHPJ2Vg=="],
+
+ "@babel/preset-typescript": ["@babel/preset-typescript@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-validator-option": "^7.27.1", "@babel/plugin-syntax-jsx": "^7.27.1", "@babel/plugin-transform-modules-commonjs": "^7.27.1", "@babel/plugin-transform-typescript": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-l7WfQfX0WK4M0v2RudjuQK4u99BS6yLHYEmdtVPP7lKV013zr9DygFuWNlnbvQ9LR+LS0Egz/XAvGx5U9MX0fQ=="],
+
+ "@babel/runtime": ["@babel/runtime@7.28.4", "", {}, "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ=="],
+
+ "@babel/template": ["@babel/template@7.27.2", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/parser": "^7.27.2", "@babel/types": "^7.27.1" } }, "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw=="],
+
+ "@babel/traverse": ["@babel/traverse@7.28.4", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.3", "@babel/helper-globals": "^7.28.0", "@babel/parser": "^7.28.4", "@babel/template": "^7.27.2", "@babel/types": "^7.28.4", "debug": "^4.3.1" } }, "sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ=="],
+
+ "@babel/types": ["@babel/types@7.28.4", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q=="],
+
+ "@happy-dom/global-registrator": ["@happy-dom/global-registrator@20.0.5", "", { "dependencies": { "@types/node": "^20.0.0", "happy-dom": "^20.0.5" } }, "sha512-RWQ85on4fiYKw5D1xk0nU2YGCYsJEJ5iXmZHTRyeYft4OCN4IRMFZ3uX91/Tncf/9K4tPOnU1HiEOtLs2Zxukw=="],
+
+ "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
+
+ "@jridgewell/remapping": ["@jridgewell/remapping@2.3.5", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="],
+
+ "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
+
+ "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
+
+ "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],
+
+ "@solidjs/testing-library": ["@solidjs/testing-library@0.8.10", "", { "dependencies": { "@testing-library/dom": "^10.4.0" }, "peerDependencies": { "@solidjs/router": ">=0.9.0", "solid-js": ">=1.0.0" }, "optionalPeers": ["@solidjs/router"] }, "sha512-qdeuIerwyq7oQTIrrKvV0aL9aFeuwTd86VYD3afdq5HYEwoox1OBTJy4y8A3TFZr8oAR0nujYgCzY/8wgHGfeQ=="],
+
+ "@testing-library/dom": ["@testing-library/dom@10.4.1", "", { "dependencies": { "@babel/code-frame": "^7.10.4", "@babel/runtime": "^7.12.5", "@types/aria-query": "^5.0.1", "aria-query": "5.3.0", "dom-accessibility-api": "^0.5.9", "lz-string": "^1.5.0", "picocolors": "1.1.1", "pretty-format": "^27.0.2" } }, "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg=="],
+
+ "@testing-library/user-event": ["@testing-library/user-event@14.6.1", "", { "peerDependencies": { "@testing-library/dom": ">=7.21.4" } }, "sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw=="],
+
+ "@types/aria-query": ["@types/aria-query@5.0.4", "", {}, "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw=="],
+
+ "@types/babel__core": ["@types/babel__core@7.20.5", "", { "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", "@types/babel__generator": "*", "@types/babel__template": "*", "@types/babel__traverse": "*" } }, "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA=="],
+
+ "@types/babel__generator": ["@types/babel__generator@7.27.0", "", { "dependencies": { "@babel/types": "^7.0.0" } }, "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg=="],
+
+ "@types/babel__template": ["@types/babel__template@7.4.4", "", { "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" } }, "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A=="],
+
+ "@types/babel__traverse": ["@types/babel__traverse@7.28.0", "", { "dependencies": { "@babel/types": "^7.28.2" } }, "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q=="],
+
+ "@types/node": ["@types/node@20.19.22", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-hRnu+5qggKDSyWHlnmThnUqg62l29Aj/6vcYgUaSFL9oc7DVjeWEQN3PRgdSc6F8d9QRMWkf36CLMch1Do/+RQ=="],
+
+ "@types/react": ["@types/react@19.2.2", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA=="],
+
+ "@types/whatwg-mimetype": ["@types/whatwg-mimetype@3.0.2", "", {}, "sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA=="],
+
+ "ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
+
+ "ansi-styles": ["ansi-styles@5.2.0", "", {}, "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA=="],
+
+ "aria-query": ["aria-query@5.3.0", "", { "dependencies": { "dequal": "^2.0.3" } }, "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A=="],
+
+ "babel-plugin-jsx-dom-expressions": ["babel-plugin-jsx-dom-expressions@0.40.1", "", { "dependencies": { "@babel/helper-module-imports": "7.18.6", "@babel/plugin-syntax-jsx": "^7.18.6", "@babel/types": "^7.20.7", "html-entities": "2.3.3", "parse5": "^7.1.2", "validate-html-nesting": "^1.2.1" }, "peerDependencies": { "@babel/core": "^7.20.12" } }, "sha512-b4iHuirqK7RgaMzB2Lsl7MqrlDgQtVRSSazyrmx7wB3T759ggGjod5Rkok5MfHjQXhR7tRPmdwoeGPqBnW2KfA=="],
+
+ "babel-preset-solid": ["babel-preset-solid@1.9.9", "", { "dependencies": { "babel-plugin-jsx-dom-expressions": "^0.40.1" }, "peerDependencies": { "@babel/core": "^7.0.0", "solid-js": "^1.9.8" }, "optionalPeers": ["solid-js"] }, "sha512-pCnxWrciluXCeli/dj5PIEHgbNzim3evtTn12snjqqg8QZWJNMjH1AWIp4iG/tbVjqQ72aBEymMSagvmgxubXw=="],
+
+ "baseline-browser-mapping": ["baseline-browser-mapping@2.8.18", "", { "bin": { "baseline-browser-mapping": "dist/cli.js" } }, "sha512-UYmTpOBwgPScZpS4A+YbapwWuBwasxvO/2IOHArSsAhL/+ZdmATBXTex3t+l2hXwLVYK382ibr/nKoY9GKe86w=="],
+
+ "browserslist": ["browserslist@4.26.3", "", { "dependencies": { "baseline-browser-mapping": "^2.8.9", "caniuse-lite": "^1.0.30001746", "electron-to-chromium": "^1.5.227", "node-releases": "^2.0.21", "update-browserslist-db": "^1.1.3" }, "bin": { "browserslist": "cli.js" } }, "sha512-lAUU+02RFBuCKQPj/P6NgjlbCnLBMp4UtgTx7vNHd3XSIJF87s9a5rA3aH2yw3GS9DqZAUbOtZdCCiZeVRqt0w=="],
+
+ "bun-types": ["bun-types@1.3.0", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-u8X0thhx+yJ0KmkxuEo9HAtdfgCBaM/aI9K90VQcQioAmkVp3SG3FkwWGibUFz3WdXAdcsqOcbU40lK7tbHdkQ=="],
+
+ "caniuse-lite": ["caniuse-lite@1.0.30001751", "", {}, "sha512-A0QJhug0Ly64Ii3eIqHu5X51ebln3k4yTUkY1j8drqpWHVreg/VLijN48cZ1bYPiqOQuqpkIKnzr/Ul8V+p6Cw=="],
+
+ "convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="],
+
+ "csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
+
+ "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
+
+ "dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="],
+
+ "dom-accessibility-api": ["dom-accessibility-api@0.5.16", "", {}, "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg=="],
+
+ "electron-to-chromium": ["electron-to-chromium@1.5.237", "", {}, "sha512-icUt1NvfhGLar5lSWH3tHNzablaA5js3HVHacQimfP8ViEBOQv+L7DKEuHdbTZ0SKCO1ogTJTIL1Gwk9S6Qvcg=="],
+
+ "entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="],
+
+ "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="],
+
+ "gensync": ["gensync@1.0.0-beta.2", "", {}, "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="],
+
+ "happy-dom": ["happy-dom@20.0.5", "", { "dependencies": { "@types/node": "^20.0.0", "@types/whatwg-mimetype": "^3.0.2", "whatwg-mimetype": "^3.0.0" } }, "sha512-AiqA0rfS7WR1kihXt9W9aA5LFLaOKzwiL+QoI7BkOQ0r21C7VHTOf4k8QNlnWYaHLhpI2tZzJPLV1lY1obDTmw=="],
+
+ "html-entities": ["html-entities@2.3.3", "", {}, "sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA=="],
+
+ "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
+
+ "jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="],
+
+ "json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="],
+
+ "lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="],
+
+ "lz-string": ["lz-string@1.5.0", "", { "bin": { "lz-string": "bin/bin.js" } }, "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ=="],
+
+ "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
+
+ "node-releases": ["node-releases@2.0.25", "", {}, "sha512-4auku8B/vw5psvTiiN9j1dAOsXvMoGqJuKJcR+dTdqiXEK20mMTk1UEo3HS16LeGQsVG6+qKTPM9u/qQ2LqATA=="],
+
+ "parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="],
+
+ "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
+
+ "pretty-format": ["pretty-format@27.5.1", "", { "dependencies": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", "react-is": "^17.0.1" } }, "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ=="],
+
+ "react-is": ["react-is@17.0.2", "", {}, "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="],
+
+ "semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
+
+ "seroval": ["seroval@1.3.2", "", {}, "sha512-RbcPH1n5cfwKrru7v7+zrZvjLurgHhGyso3HTyGtRivGWgYjbOmGuivCQaORNELjNONoK35nj28EoWul9sb1zQ=="],
+
+ "seroval-plugins": ["seroval-plugins@1.3.3", "", { "peerDependencies": { "seroval": "^1.0" } }, "sha512-16OL3NnUBw8JG1jBLUoZJsLnQq0n5Ua6aHalhJK4fMQkz1lqR7Osz1sA30trBtd9VUDc2NgkuRCn8+/pBwqZ+w=="],
+
+ "solid-js": ["solid-js@1.9.9", "", { "dependencies": { "csstype": "^3.1.0", "seroval": "~1.3.0", "seroval-plugins": "~1.3.0" } }, "sha512-A0ZBPJQldAeGCTW0YRYJmt7RCeh5rbFfPZ2aOttgYnctHE7HgKeHCBB/PVc2P7eOfmNXqMFFFoYYdm3S4dcbkA=="],
+
+ "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
+
+ "undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="],
+
+ "update-browserslist-db": ["update-browserslist-db@1.1.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw=="],
+
+ "validate-html-nesting": ["validate-html-nesting@1.2.3", "", {}, "sha512-kdkWdCl6eCeLlRShJKbjVOU2kFKxMF8Ghu50n+crEoyx+VKm3FxAxF9z4DCy6+bbTOqNW0+jcIYRnjoIRzigRw=="],
+
+ "whatwg-mimetype": ["whatwg-mimetype@3.0.0", "", {}, "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q=="],
+
+ "yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="],
+
+ "babel-plugin-jsx-dom-expressions/@babel/helper-module-imports": ["@babel/helper-module-imports@7.18.6", "", { "dependencies": { "@babel/types": "^7.18.6" } }, "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA=="],
+
+ "bun-types/@types/node": ["@types/node@24.8.1", "", { "dependencies": { "undici-types": "~7.14.0" } }, "sha512-alv65KGRadQVfVcG69MuB4IzdYVpRwMG/mq8KWOaoOdyY617P5ivaDiMCGOFDWD2sAn5Q0mR3mRtUOgm99hL9Q=="],
+
+ "bun-types/@types/node/undici-types": ["undici-types@7.14.0", "", {}, "sha512-QQiYxHuyZ9gQUIrmPo3IA+hUl4KYk8uSA7cHrcKd/l3p1OTpZcM0Tbp9x7FAtXdAYhlasd60ncPpgu6ihG6TOA=="],
+ }
+}
diff --git a/examples/bun-solid/bunfig.toml b/examples/bun-solid/bunfig.toml
new file mode 100644
index 0000000..81650dd
--- /dev/null
+++ b/examples/bun-solid/bunfig.toml
@@ -0,0 +1,7 @@
+jsx = "solid"
+
+[install]
+linker = "isolated"
+
+[test]
+preload = "./test/test-setup.ts"
diff --git a/examples/bun-solid/index.ts b/examples/bun-solid/index.ts
new file mode 100644
index 0000000..f67b2c6
--- /dev/null
+++ b/examples/bun-solid/index.ts
@@ -0,0 +1 @@
+console.log("Hello via Bun!");
\ No newline at end of file
diff --git a/examples/bun-solid/package.json b/examples/bun-solid/package.json
new file mode 100644
index 0000000..988ab03
--- /dev/null
+++ b/examples/bun-solid/package.json
@@ -0,0 +1,24 @@
+{
+ "name": "bun-solid",
+ "private": true,
+ "type": "module",
+ "scripts": {
+ "test": "bun test --conditions=browser"
+ },
+ "devDependencies": {
+ "@babel/core": "^7.28.4",
+ "@babel/plugin-transform-react-jsx": "^7.27.1",
+ "@babel/preset-typescript": "^7.27.1",
+ "@happy-dom/global-registrator": "^20.0.5",
+ "@solidjs/testing-library": "^0.8.10",
+ "@testing-library/user-event": "^14.6.1",
+ "@types/babel__core": "^7.20.5",
+ "babel-preset-solid": "^1.9.9",
+ "bun-types": "^1.3.0",
+ "happy-dom": "^20.0.5",
+ "typescript": "^5.9.3"
+ },
+ "dependencies": {
+ "solid-js": "^1.9.9"
+ }
+}
diff --git a/examples/bun-solid/src/Counter.tsx b/examples/bun-solid/src/Counter.tsx
new file mode 100644
index 0000000..fc05b20
--- /dev/null
+++ b/examples/bun-solid/src/Counter.tsx
@@ -0,0 +1,22 @@
+import { createSignal } from 'solid-js'
+
+export function Counter() {
+ const [count, setCount] = createSignal(0)
+
+ function increment() {
+ setCount(count() + 1)
+ };
+
+ function decrement() {
+ setCount(count() - 1)
+ };
+
+ return (
+
+
Counter
+
Count: {count()}
+
Increment
+
Decrement
+
+ )
+}
diff --git a/examples/bun-solid/src/FormExample.tsx b/examples/bun-solid/src/FormExample.tsx
new file mode 100644
index 0000000..21bcf6b
--- /dev/null
+++ b/examples/bun-solid/src/FormExample.tsx
@@ -0,0 +1,54 @@
+import { createSignal } from 'solid-js'
+
+export function FormExample() {
+ const [submitCount, setSubmitCount] = createSignal(0)
+ return (
+
+
+ Submit Count: {submitCount()}
+
+
+
+ )
+}
diff --git a/examples/bun-solid/src/blue-title.css b/examples/bun-solid/src/blue-title.css
new file mode 100644
index 0000000..ccf22a0
--- /dev/null
+++ b/examples/bun-solid/src/blue-title.css
@@ -0,0 +1,3 @@
+h1 {
+ color: blue;
+}
diff --git a/examples/bun-solid/test/basic.test.tsx b/examples/bun-solid/test/basic.test.tsx
new file mode 100644
index 0000000..a65db18
--- /dev/null
+++ b/examples/bun-solid/test/basic.test.tsx
@@ -0,0 +1,13 @@
+import { expect, it } from 'bun:test'
+import { fireEvent, render, screen } from '@solidjs/testing-library'
+import { Counter } from '../src/Counter'
+
+it('simple react testing library test', () => {
+ render(() => )
+
+ fireEvent.click(screen.getByText('Increment'))
+ fireEvent.click(screen.getByText('Increment'))
+ fireEvent.click(screen.getByText('Decrement'))
+
+ expect(screen.getByText('Count: 1'))
+})
diff --git a/examples/bun-solid/test/form-test-for-e2e.test.tsx b/examples/bun-solid/test/form-test-for-e2e.test.tsx
new file mode 100644
index 0000000..ec0317d
--- /dev/null
+++ b/examples/bun-solid/test/form-test-for-e2e.test.tsx
@@ -0,0 +1,10 @@
+import { render, screen } from '@solidjs/testing-library'
+import { describe, expect, it } from 'bun:test'
+import { FormExample } from '../src/FormExample'
+
+describe('form test for e2e test', () => {
+ it('basic usage', async () => {
+ render(() => )
+ expect(screen.getByLabelText('First input'))
+ })
+})
diff --git a/examples/bun-solid/test/test-setup.ts b/examples/bun-solid/test/test-setup.ts
new file mode 100644
index 0000000..41c193d
--- /dev/null
+++ b/examples/bun-solid/test/test-setup.ts
@@ -0,0 +1,31 @@
+import { transformAsync } from '@babel/core'
+import { GlobalRegistrator } from '@happy-dom/global-registrator'
+
+// @ts-expect-error no types
+import solid from 'babel-preset-solid'
+// @ts-expect-error no types
+import ts from '@babel/preset-typescript'
+
+GlobalRegistrator.register()
+
+await Bun.plugin({
+ name: 'bun-plugin-solid',
+ setup: (build) => {
+ build.onLoad({ filter: /\.(js|ts)x$/ }, async (args) => {
+ const code = await Bun.file(args.path).text()
+ const transforms = await transformAsync(code, {
+ filename: args.path,
+ presets: [
+ [solid, { generate: 'dom', debug: true }],
+ [ts, {}],
+ ],
+ retainLines: true,
+ })
+
+ return {
+ contents: transforms!.code!,
+ loader: 'js',
+ }
+ })
+ },
+})
diff --git a/examples/bun-solid/tsconfig.json b/examples/bun-solid/tsconfig.json
new file mode 100644
index 0000000..b8f7753
--- /dev/null
+++ b/examples/bun-solid/tsconfig.json
@@ -0,0 +1,31 @@
+{
+ "compilerOptions": {
+ // Environment setup & latest features
+ "lib": ["ESNext"],
+ "target": "ESNext",
+ "module": "Preserve",
+ "moduleDetection": "force",
+ "jsx": "preserve",
+ "allowJs": true,
+
+ // Bundler mode
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "verbatimModuleSyntax": true,
+ "noEmit": true,
+
+ // Best practices
+ "strict": true,
+ "skipLibCheck": true,
+ "noFallthroughCasesInSwitch": true,
+ "noUncheckedIndexedAccess": true,
+ "noImplicitOverride": true,
+
+ // Some stricter flags (disabled by default)
+ "noUnusedLocals": false,
+ "noUnusedParameters": false,
+ "noPropertyAccessFromIndexSignature": false,
+
+ "types": ["bun-types", "@babel/types"]
+ }
+}
diff --git a/examples/jest-babel-nextjs/package.json b/examples/jest-babel-nextjs/package.json
index 68ef533..698ac70 100644
--- a/examples/jest-babel-nextjs/package.json
+++ b/examples/jest-babel-nextjs/package.json
@@ -5,13 +5,13 @@
"test": "jest"
},
"dependencies": {
- "next": "^15.5.4",
+ "next": "^15.5.6",
"react": "^19.2.0",
"react-dom": "^19.2.0"
},
"devDependencies": {
"@babel/runtime": "^7.28.4",
- "@testing-library/jest-dom": "^6.9.0",
+ "@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^16.3.0",
"@testing-library/user-event": "^14.6.1",
"@types/jest": "^30.0.0",
@@ -20,6 +20,6 @@
"identity-obj-proxy": "^3.0.0",
"jest": "^30.2.0",
"jest-environment-jsdom": "^30.2.0",
- "typescript": "^5.9.2"
+ "typescript": "^5.9.3"
}
}
diff --git a/examples/jest-monorepo/packages/inner-package/test/basic.test.tsx b/examples/jest-monorepo/packages/inner-package/test/basic.test.tsx
index cc68005..e098e49 100644
--- a/examples/jest-monorepo/packages/inner-package/test/basic.test.tsx
+++ b/examples/jest-monorepo/packages/inner-package/test/basic.test.tsx
@@ -9,5 +9,5 @@ it('simple react testing library test', () => {
fireEvent.click(screen.getByText('Increment'))
fireEvent.click(screen.getByText('Decrement'))
- expect(screen.getByText('Count: 1')).toBeTruthy()
+ expect(screen.getByText('Count: 1'))
})
diff --git a/examples/jest-nextjs-minimal/components/TodoList.test.tsx b/examples/jest-nextjs-minimal/components/TodoList.test.tsx
new file mode 100644
index 0000000..dcb5476
--- /dev/null
+++ b/examples/jest-nextjs-minimal/components/TodoList.test.tsx
@@ -0,0 +1,6 @@
+import { render } from '@testing-library/react'
+import { TodoList } from './TodoList'
+
+test('basic usage', async () => {
+ (() => render( ))()
+})
diff --git a/examples/jest-nextjs-minimal/components/TodoList.tsx b/examples/jest-nextjs-minimal/components/TodoList.tsx
new file mode 100644
index 0000000..111e0fc
--- /dev/null
+++ b/examples/jest-nextjs-minimal/components/TodoList.tsx
@@ -0,0 +1,91 @@
+import React, { useState } from 'react'
+
+interface Todo {
+ id: number
+ text: string
+ completed: boolean
+}
+
+export function TodoList() {
+ const [todos, setTodos] = useState([])
+ const [input, setInput] = useState('')
+
+ const addTodo = () => {
+ if (input.trim()) {
+ setTodos([...todos, { id: Date.now(), text: input, completed: false }])
+ setInput('')
+ }
+ }
+
+ const toggleTodo = (id: number) => {
+ setTodos(todos.map(todo => (todo.id === id ? { ...todo, completed: !todo.completed } : todo)))
+ }
+
+ const deleteTodo = (id: number) => {
+ setTodos(todos.filter(todo => todo.id !== id))
+ }
+
+ const doneCount = todos.filter(todo => todo.completed).length
+ const notDoneCount = todos.filter(todo => !todo.completed).length
+
+ return (
+
+
+
+
Todo List
+
+
{doneCount} done
+
{notDoneCount} in progress
+
+
+
+
+ setInput(e.target.value)}
+ onKeyDown={e => e.key === 'Enter' && addTodo()}
+ placeholder="Add a new todo"
+ className="flex-1 bg-gray-800 border border-gray-700 rounded px-3 py-2 text-sm text-white placeholder:text-gray-500 focus:outline-none focus:ring-1 focus:ring-gray-600"
+ />
+
+ Add
+
+
+
+
+ {todos.map(todo => (
+
+ toggleTodo(todo.id)}
+ className="h-4 w-4 rounded border-gray-600 cursor-pointer"
+ aria-label="Toggle done"
+ />
+
+ {todo.text}
+
+ deleteTodo(todo.id)}
+ className="opacity-0 group-hover:opacity-100 transition-opacity h-8 w-8 flex items-center justify-center hover:bg-muted rounded"
+ aria-label="Delete"
+ >
+
+
+
+
+
+
+ ))}
+
+
+ {todos.length === 0 && (
+
No todos yet. Add one to get started.
+ )}
+
+
+ )
+}
diff --git a/examples/jest-nextjs-minimal/package.json b/examples/jest-nextjs-minimal/package.json
index 81b7591..5fec0dd 100644
--- a/examples/jest-nextjs-minimal/package.json
+++ b/examples/jest-nextjs-minimal/package.json
@@ -5,18 +5,20 @@
"test": "jest"
},
"dependencies": {
- "next": "^15.5.4",
+ "next": "^15.5.6",
"react": "^19.2.0",
"react-dom": "^19.2.0",
"server-only": "^0.0.1"
},
"devDependencies": {
- "@testing-library/jest-dom": "^6.9.0",
+ "@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^16.3.0",
+ "@testing-library/user-event": "^14.6.1",
"@types/jest": "^30.0.0",
"@types/react": "^19.2.2",
"jest": "^30.2.0",
"jest-environment-jsdom": "^30.2.0",
- "typescript": "^5.9.2"
+ "tailwindcss": "^4.1.16",
+ "typescript": "^5.9.3"
}
}
diff --git a/examples/jest-nextjs-minimal/styles/global.css b/examples/jest-nextjs-minimal/styles/global.css
index 4d03bee..05a2710 100644
--- a/examples/jest-nextjs-minimal/styles/global.css
+++ b/examples/jest-nextjs-minimal/styles/global.css
@@ -1,3 +1,5 @@
+@import "tailwindcss";
+
html,
body {
padding: 0;
diff --git a/examples/jest-nextjs-ts-node/app/counter.test.tsx b/examples/jest-nextjs-ts-node/app/counter.test.tsx
index 70dbe57..314b5b3 100644
--- a/examples/jest-nextjs-ts-node/app/counter.test.tsx
+++ b/examples/jest-nextjs-ts-node/app/counter.test.tsx
@@ -10,7 +10,7 @@ it('simple react testing library test', () => {
fireEvent.click(screen.getByText('Increment'))
fireEvent.click(screen.getByText('Decrement'))
- expect(screen.getByText('Count: 1')).toBeTruthy()
+ expect(screen.getByText('Count: 1'))
})
// For some reason calling 'render' in the test block needs multiple
diff --git a/examples/jest-nextjs-ts-node/package.json b/examples/jest-nextjs-ts-node/package.json
index f50e020..893cb80 100644
--- a/examples/jest-nextjs-ts-node/package.json
+++ b/examples/jest-nextjs-ts-node/package.json
@@ -5,19 +5,19 @@
"test": "jest"
},
"dependencies": {
- "next": "^15.5.4",
+ "next": "^15.5.6",
"react": "^19.2.0",
"react-dom": "^19.2.0",
"server-only": "^0.0.1"
},
"devDependencies": {
- "@testing-library/jest-dom": "^6.9.0",
+ "@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^16.3.0",
"@types/jest": "^30.0.0",
"@types/react": "^19.2.2",
"jest": "^30.2.0",
"jest-environment-jsdom": "^30.2.0",
"ts-node": "^10.9.2",
- "typescript": "^5.9.2"
+ "typescript": "^5.9.3"
}
}
diff --git a/examples/jest-react-with-packagejson-config/test/basic.test.tsx b/examples/jest-react-with-packagejson-config/test/basic.test.tsx
index cc68005..e098e49 100644
--- a/examples/jest-react-with-packagejson-config/test/basic.test.tsx
+++ b/examples/jest-react-with-packagejson-config/test/basic.test.tsx
@@ -9,5 +9,5 @@ it('simple react testing library test', () => {
fireEvent.click(screen.getByText('Increment'))
fireEvent.click(screen.getByText('Decrement'))
- expect(screen.getByText('Count: 1')).toBeTruthy()
+ expect(screen.getByText('Count: 1'))
})
diff --git a/examples/jest-react/components/Counter.tsx b/examples/jest-react/components/Counter.tsx
index c1c3883..54f7f73 100644
--- a/examples/jest-react/components/Counter.tsx
+++ b/examples/jest-react/components/Counter.tsx
@@ -14,7 +14,7 @@ export function Counter() {
return (
Counter
-
Count: {count}
+
Count: {count}
Increment
Decrement
diff --git a/examples/jest-react/components/FormExample.tsx b/examples/jest-react/components/FormExample.tsx
new file mode 100644
index 0000000..d4762a4
--- /dev/null
+++ b/examples/jest-react/components/FormExample.tsx
@@ -0,0 +1,54 @@
+import React, { useState } from 'react'
+
+export function FormExample() {
+ const [submitCount, setSubmitCount] = useState(0)
+ return (
+
+
+ Submit Count: {submitCount}
+
+
+
+ )
+}
diff --git a/examples/jest-react/package.json b/examples/jest-react/package.json
index 3afaa89..5016deb 100644
--- a/examples/jest-react/package.json
+++ b/examples/jest-react/package.json
@@ -12,6 +12,7 @@
"@babel/preset-react": "^7.27.1",
"@babel/preset-typescript": "^7.27.1",
"@testing-library/react": "^16.3.0",
+ "@testing-library/user-event": "^14.6.1",
"@types/jest": "^30.0.0",
"@types/react": "^19.2.2",
"jest": "^30.2.0",
diff --git a/examples/jest-react/test/basic.test.tsx b/examples/jest-react/test/basic.test.tsx
index cc68005..e098e49 100644
--- a/examples/jest-react/test/basic.test.tsx
+++ b/examples/jest-react/test/basic.test.tsx
@@ -9,5 +9,5 @@ it('simple react testing library test', () => {
fireEvent.click(screen.getByText('Increment'))
fireEvent.click(screen.getByText('Decrement'))
- expect(screen.getByText('Count: 1')).toBeTruthy()
+ expect(screen.getByText('Count: 1'))
})
diff --git a/examples/jest-react/test/form-test-for-e2e.test.tsx b/examples/jest-react/test/form-test-for-e2e.test.tsx
new file mode 100644
index 0000000..c3ba43f
--- /dev/null
+++ b/examples/jest-react/test/form-test-for-e2e.test.tsx
@@ -0,0 +1,10 @@
+import { render, screen } from '@testing-library/react'
+import React from 'react'
+import { FormExample } from '../components/FormExample'
+
+describe('form test for e2e test', () => {
+ it('basic usage', async () => {
+ render( )
+ expect(screen.getByLabelText('First input'))
+ })
+})
diff --git a/examples/vitest-react-tailwind3/package.json b/examples/vitest-react-tailwind3/package.json
index b044293..cee6479 100644
--- a/examples/vitest-react-tailwind3/package.json
+++ b/examples/vitest-react-tailwind3/package.json
@@ -13,7 +13,7 @@
"@vitejs/plugin-react": "^5.0.4",
"autoprefixer": "^10.4.21",
"happy-dom": "^14.11.4",
- "less": "^4.4.1",
+ "less": "^4.4.2",
"postcss": "^8.5.6",
"sass": "^1.93.2",
"stylus": "^0.64.0",
diff --git a/examples/vitest-react-tailwind3/test/basic.test.tsx b/examples/vitest-react-tailwind3/test/basic.test.tsx
index c8b5763..5bb8ee9 100644
--- a/examples/vitest-react-tailwind3/test/basic.test.tsx
+++ b/examples/vitest-react-tailwind3/test/basic.test.tsx
@@ -9,5 +9,5 @@ it('simple react testing library test', () => {
fireEvent.click(screen.getByText('Increment'))
fireEvent.click(screen.getByText('Decrement'))
- expect(screen.getByText('Count: 1')).toBeTruthy()
+ expect(screen.getByText('Count: 1'))
})
diff --git a/examples/vitest-react-tailwind4/components/FormExample.tsx b/examples/vitest-react-tailwind4/components/FormExample.tsx
new file mode 100644
index 0000000..cdf93b1
--- /dev/null
+++ b/examples/vitest-react-tailwind4/components/FormExample.tsx
@@ -0,0 +1,79 @@
+import { useState } from 'react'
+
+export function FormExample() {
+ const [submitCount, setSubmitCount] = useState(0)
+ return (
+
+
+ Submit Count: {submitCount}
+
+
+
Form Section
+
+
+
+
Non-Form Section
+
+
+ Outside input 1
+
+
+
+ Outside input 2
+
+
+
+ Outside Button
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
+
+
+
+
+ )
+}
diff --git a/examples/vitest-react-tailwind4/package.json b/examples/vitest-react-tailwind4/package.json
index 37526ae..d06845f 100644
--- a/examples/vitest-react-tailwind4/package.json
+++ b/examples/vitest-react-tailwind4/package.json
@@ -9,14 +9,15 @@
"react": "^19.2.0"
},
"devDependencies": {
- "@tailwindcss/vite": "^4.1.13",
+ "@tailwindcss/vite": "^4.1.14",
"@testing-library/react": "^16.3.0",
+ "@testing-library/user-event": "^14.6.1",
"@types/react": "^19.2.2",
"@vitejs/plugin-react": "^5.0.4",
"happy-dom": "^14.11.4",
"sass": "^1.93.2",
- "tailwindcss": "^4.1.13",
- "vite": "^7.1.7",
- "vitest": "^4.0.0-beta.8"
+ "tailwindcss": "^4.1.14",
+ "vite": "^7.1.10",
+ "vitest": "^4.0.0-beta.18"
}
}
diff --git a/examples/vitest-react-tailwind4/test/basic.test.tsx b/examples/vitest-react-tailwind4/test/basic.test.tsx
index a16124a..e4258ad 100644
--- a/examples/vitest-react-tailwind4/test/basic.test.tsx
+++ b/examples/vitest-react-tailwind4/test/basic.test.tsx
@@ -9,7 +9,7 @@ it('simple react testing library test', () => {
fireEvent.click(screen.getByText('Increment'))
fireEvent.click(screen.getByText('Decrement'))
- expect(screen.getByText('Count: 1')).toBeTruthy()
+ expect(screen.getByText('Count: 1'))
})
function setupUi() {
diff --git a/examples/vitest-react-tailwind4/test/form-test-for-e2e.test.tsx b/examples/vitest-react-tailwind4/test/form-test-for-e2e.test.tsx
new file mode 100644
index 0000000..08b0168
--- /dev/null
+++ b/examples/vitest-react-tailwind4/test/form-test-for-e2e.test.tsx
@@ -0,0 +1,14 @@
+import { describe, it } from 'vitest'
+import { render, screen } from '@testing-library/react'
+import { FormExample } from '../components/FormExample'
+
+describe('form test for e2e test', () => {
+ it('basic usage', async () => {
+ setupUi()
+ expect(screen.getByLabelText('First input'))
+ })
+})
+
+function setupUi() {
+ render( )
+}
diff --git a/examples/vitest-react-tailwind4/test/form.test.tsx b/examples/vitest-react-tailwind4/test/form.test.tsx
new file mode 100644
index 0000000..7412410
--- /dev/null
+++ b/examples/vitest-react-tailwind4/test/form.test.tsx
@@ -0,0 +1,18 @@
+import { expect } from 'vitest'
+import { render, screen } from '@testing-library/react'
+import { userEvent } from '@testing-library/user-event'
+import { FormExample } from '../components/FormExample'
+
+it('renders FormExample with form and non-form sections', async () => {
+ (() => render( ))()
+
+ // Fill form inputs and submit
+ const firstInput = screen.getByLabelText('First input')
+ await userEvent.type(firstInput, 'Test Value 1')
+ expect((firstInput as HTMLInputElement).value).toBe('Test Value 1')
+
+ const secondInput = screen.getByPlaceholderText('Second input')
+ await userEvent.type(secondInput, 'Test Value 2')
+
+ expect((secondInput as HTMLInputElement).value).toBe('Test Value 2')
+})
diff --git a/examples/vitest-react-tailwind4/test/inspector-demo.test.tsx b/examples/vitest-react-tailwind4/test/inspector-demo.test.tsx
index 00edef6..ac7f5cc 100644
--- a/examples/vitest-react-tailwind4/test/inspector-demo.test.tsx
+++ b/examples/vitest-react-tailwind4/test/inspector-demo.test.tsx
@@ -5,7 +5,7 @@ import { Counter } from '../../jest-react/components/Counter'
it('example ui test to be run within the e2e test', async () => {
setupUi()
- expect(screen.getByText('Count: 1')).toBeTruthy()
+ expect(screen.getByText('Count: 1'))
})
function setupUi() {
diff --git a/examples/vitest-react-tailwind4/tsconfig.json b/examples/vitest-react-tailwind4/tsconfig.json
index 0068949..06568a5 100644
--- a/examples/vitest-react-tailwind4/tsconfig.json
+++ b/examples/vitest-react-tailwind4/tsconfig.json
@@ -1,6 +1,6 @@
{
"compilerOptions": {
- "jsx": "react",
+ "jsx": "react-jsx",
"module": "Preserve",
"moduleResolution": "bundler",
"types": ["vitest/globals"],
diff --git a/examples/vitest-react-tailwind4/vite.config.ts b/examples/vitest-react-tailwind4/vite.config.ts
index 5066940..fa6a3f5 100644
--- a/examples/vitest-react-tailwind4/vite.config.ts
+++ b/examples/vitest-react-tailwind4/vite.config.ts
@@ -2,9 +2,10 @@
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
+import react from '@vitejs/plugin-react'
export default defineConfig({
- plugins: [tailwindcss()],
+ plugins: [react(), tailwindcss()],
test: {
globals: true,
environment: 'happy-dom',
diff --git a/package.json b/package.json
index 8a8e87b..5df3293 100644
--- a/package.json
+++ b/package.json
@@ -68,10 +68,24 @@
"description": "Test Framework: Vitest or Jest. Auto-detects by default by walking up directories from your test file."
}
}
- }
+ },
+ "menus": {
+ "editor/context": [
+ {
+ "command": "ui-test-visualizer.createUiTest",
+ "when": "editorTextFocus && editorLangId =~ /typescript|javascript/"
+ }
+ ]
+ },
+ "commands": [
+ {
+ "command": "ui-test-visualizer.createUiTest",
+ "title": "Create UI test (UI Test Visualizer)"
+ }
+ ]
},
"scripts": {
- "prepare": "which bun && bun install --cwd ./examples/bun-react || true",
+ "prepare": "which bun && (bun install --cwd ./examples/bun-react) && (bun install --cwd ./examples/bun-solid)",
"dev": "rm -rf build-dev && pnpm run -r dev",
"build": "rm -rf build-prod && pnpm run -r build && (cd build-prod && npx vsce package --allow-missing-repository --skip-license --out ./extension.vsix)",
"lint": "tsc",
@@ -86,16 +100,17 @@
"devDependencies": {
"@antfu/eslint-config": "^2.19.1",
"@changesets/cli": "^2.29.7",
- "@playwright/test": "^1.55.1",
+ "@playwright/test": "^1.56.1",
"@total-typescript/ts-reset": "^0.6.1",
- "@types/node": "^24.6.0",
+ "@types/node": "^24.8.1",
"@vitest/expect": "^3.2.4",
"@vscode/vsce": "^3.6.2",
- "eslint": "^9.36.0",
+ "eslint": "^9.38.0",
"ovsx": "^0.10.6",
+ "pathe": "^2.0.3",
"tsup": "^8.5.0",
"type-fest": "^5.0.1",
- "typescript": "^5.9.2",
+ "typescript": "^5.9.3",
"vitest": "^3.2.4"
},
"pnpm": {
@@ -103,5 +118,5 @@
"jest-config@30.2.0": "patches/jest-config@30.2.0.patch"
}
},
- "packageManager": "pnpm@10.17.1"
+ "packageManager": "pnpm@10.19.0+sha512.c9fc7236e92adf5c8af42fd5bf1612df99c2ceb62f27047032f4720b33f8eacdde311865e91c411f2774f618d82f320808ecb51718bfa82c060c4ba7c76a32b8"
}
diff --git a/packages/extension/package.json b/packages/extension/package.json
index ac4d82a..b80d2e1 100644
--- a/packages/extension/package.json
+++ b/packages/extension/package.json
@@ -9,11 +9,11 @@
"build": "tsup --minify"
},
"dependencies": {
- "@napi-rs/wasm-runtime": "^1.0.5",
- "@oxc-parser/binding-wasm32-wasi": "^0.93.0",
- "@tailwindcss/oxide-wasm32-wasi": "^4.1.13",
+ "@napi-rs/wasm-runtime": "^1.0.7",
+ "@oxc-parser/binding-wasm32-wasi": "^0.95.0",
+ "@tailwindcss/oxide-wasm32-wasi": "^4.1.14",
"@trpc/server": "^11.6.0",
- "@vscode/extension-telemetry": "^1.0.0",
+ "@vscode/extension-telemetry": "^1.1.0",
"enhanced-resolve": "^5.18.3",
"estree-walker": "^3.0.3",
"find-up": "^8.0.0",
@@ -24,20 +24,22 @@
"postcss": "^8.5.6",
"postcss-load-config": "^6.0.1",
"replicate-dom": "workspace:*",
- "zod": "^4.1.11"
+ "zod": "^4.1.12"
},
"devDependencies": {
+ "@testing-library/user-event": "^13.5.0",
"@types/less": "^3.0.8",
"@types/lodash": "^4.17.20",
- "@types/node": "^24.6.0",
+ "@types/node": "^24.8.1",
"@types/stylus": "^0.48.43",
- "@types/vscode": "^1.104.0",
+ "@types/vscode": "^1.105.0",
"@types/ws": "^8.18.1",
"@vitest/expect": "^3.2.4",
- "@vscode/codicons": "^0.0.40",
- "esbuild": "^0.25.10",
+ "@vscode/codicons": "^0.0.41",
+ "esbuild": "^0.25.11",
"execa": "^9.6.0",
- "less": "^4.4.1",
+ "less": "^4.4.2",
+ "oxc-parser": "^0.95.0",
"sass": "^1.93.2",
"stylus": "^0.64.0",
"vitest": "^3.2.4",
diff --git a/packages/extension/src/code-lens-provider.ts b/packages/extension/src/code-lens-provider.ts
index 7dcec54..7fc91f9 100644
--- a/packages/extension/src/code-lens-provider.ts
+++ b/packages/extension/src/code-lens-provider.ts
@@ -46,8 +46,16 @@ export const codeLensProvider: vscode.CodeLensProvider = {
walk(program, {
enter(node) {
if (node.type === 'CallExpression' && ['it', 'fit', 'test'].includes(node?.callee.name)) {
+ const functionNode = (() => {
+ for (const argNode of node.arguments) {
+ if (['FunctionDeclaration', 'FunctionExpression', 'ArrowFunctionExpression'].includes(argNode?.type ?? '')) {
+ return argNode
+ }
+ }
+ })()
+
const name = node?.arguments?.[0]?.value
- let firstStatementStartChar: number | null = Number(node?.arguments?.[1]?.body?.body?.[0]?.start ?? undefined)
+ let firstStatementStartChar: number | null = Number(functionNode?.body?.body?.[0]?.start ?? undefined)
if (Number.isNaN(firstStatementStartChar)) {
firstStatementStartChar = null
}
diff --git a/packages/extension/src/debug-config.ts b/packages/extension/src/debug-config.ts
index 0df2d30..8a508ea 100644
--- a/packages/extension/src/debug-config.ts
+++ b/packages/extension/src/debug-config.ts
@@ -1,9 +1,7 @@
+import { findUp } from 'find-up'
import path from 'pathe'
import type vscode from 'vscode'
-import type { z } from 'zod/mini'
-import { findUp } from 'find-up'
-import type { zFrameworkSetting } from './extension'
-import { detectTestFramework } from './framework-support/detect'
+import type { TestFrameworkInfo } from './framework-support/detect-test-framework'
import { jestDebugConfig } from './framework-support/jest-support'
import { vitestDebugConfig } from './framework-support/vitest-support'
import { bunDebugConfig } from './framework-support/bun-support'
@@ -11,14 +9,12 @@ import { bunDebugConfig } from './framework-support/bun-support'
const DEBUG_NAME = 'Visually Debug UI'
export async function makeDebugConfig(
+ fwInfo: TestFrameworkInfo,
testFile: string,
testName: string,
- frameworkSetting: z.infer,
htmlUpdaterPort: number,
testCssFiles?: string[],
) {
- const fwInfo = await detectTestFramework(testFile, frameworkSetting)
-
const pkgPath = await findUp('package.json', { cwd: testFile })
if (!pkgPath) {
throw new Error(`Could not find related package.json for test file ${testFile}`)
diff --git a/packages/extension/src/extension.ts b/packages/extension/src/extension.ts
index 586a44c..93be27a 100644
--- a/packages/extension/src/extension.ts
+++ b/packages/extension/src/extension.ts
@@ -3,16 +3,24 @@ import '@total-typescript/ts-reset'
import { TelemetryReporter } from '@vscode/extension-telemetry'
import * as vscode from 'vscode'
import * as z from 'zod/mini'
+import zodEn from 'zod/v4/locales/en.js'
import getPort from 'get-port'
import { autoSetFirstBreakpoint } from './auto-set-first-breakpoint'
import { codeLensProvider } from './code-lens-provider'
import { makeDebugConfig } from './debug-config'
+import { detectTestFramework } from './framework-support/detect-test-framework'
+import { detectTestLibrary } from './framework-support/detect-test-library'
import { myExtensionStorage } from './my-extension-storage'
import { startPanelController } from './panel-controller/panel-controller'
+import { createUiTestFile } from './recorder/create-new-test-file/create-ui-test-file'
+import { startRecorderCodeGenSession } from './recorder/recorder-codegen-session'
import { startDebuggerTracker } from './util/debugger-tracker'
import { extensionSetting } from './util/extension-setting'
+import { onceWithPeek } from './util/util'
import { enableHotReload } from './util/hot-reload'
+z.config(zodEn())
+
const reporter = (() => {
try {
return new TelemetryReporter('InstrumentationKey=ffa9ad6b-9974-4d5c-9247-9ff01c0a4cc8;IngestionEndpoint=https://eastus-8.in.applicationinsights.azure.com/;LiveEndpoint=https://eastus.livediagnostics.monitor.azure.com/;ApplicationId=55f0d25f-492a-4af3-8487-d8abce8a41f6')
@@ -80,6 +88,11 @@ export async function activate(extensionContext: vscode.ExtensionContext) {
}),
)
}
+
+ // Right-click a component name and click "Create UI test" -> create a test file with the name of the component
+ extensionContext.subscriptions.push(
+ vscode.commands.registerCommand('ui-test-visualizer.createUiTest', () => createUiTestFile()),
+ )
}
export function deactivate() {
@@ -115,21 +128,23 @@ async function startTest(
throw new TypeError(`Expected number or null argument \"firstStatementStartLine\", received ${firstStatementStartLineRaw}`)
}
- // Save the test file before starting the debug session
- await vscode.window.activeTextEditor?.document.save()
-
- const htmlUpdaterPort = await getPort()
-
const frameworkSetting = (() => {
const parsed = zFrameworkSetting
.safeParse(extensionSetting('ui-test-visualizer.testFramework'))
return parsed.success ? parsed.data : 'autodetect'
})()
+ const frameworkInfo = await detectTestFramework(testFile, frameworkSetting)
+
+ // Save the test file before starting the debug session
+ await vscode.window.activeTextEditor?.document.save()
+
+ const htmlUpdaterPort = await getPort()
+
const debugConfig = await makeDebugConfig(
+ frameworkInfo,
testFile,
testName,
- frameworkSetting,
htmlUpdaterPort,
await storage.get('enabledCssFiles'),
)
@@ -158,17 +173,28 @@ async function startWebView(extensionContext: vscode.ExtensionContext, currentSe
const storage = myExtensionStorage(extensionContext)
+ const testLibrary = await detectTestLibrary(testFile)
+
+ // Only initialize the recorder state once per debug session
+ const recorderCodeGenSession = onceWithPeek(
+ () => testLibrary
+ ? startRecorderCodeGenSession(testFile, env.TEST_FRAMEWORK, testLibrary, panelController)
+ : null,
+ )
+
const sessionTracker = startDebuggerTracker(
currentSession,
{
onFrameChange: () => panelController.flushPatches(),
onDebugRestarted: () => panelController.notifyDebuggerRestarted(),
+ onDebugTerminated: async () => recorderCodeGenSession.peek()?.performEdit(),
},
)
const panelController = await startPanelController(
extensionContext,
storage,
+ recorderCodeGenSession,
sessionTracker,
htmlUpdaterPort,
)
@@ -193,6 +219,7 @@ async function startWebView(extensionContext: vscode.ExtensionContext, currentSe
autoBreakpoint?.dispose()
sessionTracker.dispose()
panelController.dispose()
+ recorderCodeGenSession.peek()?.dispose()
onTerminate.dispose()
},
)
diff --git a/packages/extension/src/framework-support/detect.ts b/packages/extension/src/framework-support/detect-test-framework.ts
similarity index 96%
rename from packages/extension/src/framework-support/detect.ts
rename to packages/extension/src/framework-support/detect-test-framework.ts
index 4cbb4d3..eb65803 100644
--- a/packages/extension/src/framework-support/detect.ts
+++ b/packages/extension/src/framework-support/detect-test-framework.ts
@@ -2,14 +2,16 @@ import path from 'pathe'
import { findUp, findUpMultiple } from 'find-up'
import { readInitialOptions } from 'jest-config'
+export type SupportedFramework = 'vitest' | 'jest' | 'bun'
+
export interface TestFrameworkInfo {
- framework: 'jest' | 'vitest' | 'bun'
+ framework: SupportedFramework
configPath: string
}
export async function detectTestFramework(
testFilePath: string,
- frameworkSetting: 'autodetect' | 'jest' | 'vitest' | 'bun',
+ frameworkSetting: 'autodetect' | SupportedFramework,
): Promise {
// auto detect test config files
diff --git a/packages/extension/src/framework-support/detect-test-library.ts b/packages/extension/src/framework-support/detect-test-library.ts
new file mode 100644
index 0000000..19fcaf5
--- /dev/null
+++ b/packages/extension/src/framework-support/detect-test-library.ts
@@ -0,0 +1,30 @@
+import type { SupportedFramework } from './detect-test-framework'
+
+export const SUPPORTED_TESTING_LIBRARIES = [
+ '@solidjs/testing-library',
+ '@testing-library/react',
+ '@testing-library/dom',
+] as const
+
+export type TestingLibrary = typeof SUPPORTED_TESTING_LIBRARIES[number]
+
+export async function detectTestLibrary(testFilePath: string): Promise {
+ // Lookup the test framework in node_modules
+ const detectedLibrary = (() => {
+ for (const testingLibrary of SUPPORTED_TESTING_LIBRARIES) {
+ const resolved = (() => {
+ try {
+ return require.resolve(testingLibrary, { paths: [testFilePath] })
+ }
+ catch {
+ return undefined
+ }
+ })()
+ if (resolved) {
+ return testingLibrary
+ }
+ }
+ })() ?? null
+
+ return detectedLibrary
+}
diff --git a/packages/extension/src/framework-support/jest-support.ts b/packages/extension/src/framework-support/jest-support.ts
index 1187742..cccc4ad 100644
--- a/packages/extension/src/framework-support/jest-support.ts
+++ b/packages/extension/src/framework-support/jest-support.ts
@@ -2,7 +2,7 @@ import { findUp, findUpSync } from 'find-up'
import { readInitialOptions } from 'jest-config'
import path from 'pathe'
import type * as vscode from 'vscode'
-import type { TestFrameworkInfo } from './detect'
+import type { TestFrameworkInfo } from './detect-test-framework'
import { cleanTestNameForTerminal } from './util'
function buildPath() {
@@ -59,6 +59,7 @@ export async function jestDebugConfig(
'--detectOpenHandles',
// TODO find out why Jest doesn't exit on its own
'--forceExit',
+ '--colors', // Show green text for the 'pass' text. TODO find out why the rest of the output is red text
],
autoAttachChildProcesses: true,
}
diff --git a/packages/extension/src/framework-support/vitest-support.ts b/packages/extension/src/framework-support/vitest-support.ts
index 21686a7..152b26a 100644
--- a/packages/extension/src/framework-support/vitest-support.ts
+++ b/packages/extension/src/framework-support/vitest-support.ts
@@ -24,6 +24,7 @@ export async function vitestDebugConfig(
filePath,
'-t',
cleanTestNameForTerminal(testName),
+ '--globals', // Needed for the recorder's generated 'expect' statements
// Use child process instead of the default threads.
'--pool',
'forks',
diff --git a/packages/extension/src/panel-controller/panel-controller.ts b/packages/extension/src/panel-controller/panel-controller.ts
index 377ae98..668f9d1 100644
--- a/packages/extension/src/panel-controller/panel-controller.ts
+++ b/packages/extension/src/panel-controller/panel-controller.ts
@@ -4,6 +4,7 @@ import type { HTMLPatch } from 'replicate-dom'
import * as vscode from 'vscode'
import type { Server as WsServer } from 'ws'
import type { MyStorageType } from '../my-extension-storage'
+import type { RecorderCodeGenSession } from '../recorder/recorder-codegen-session'
import type { DebuggerTracker } from '../util/debugger-tracker'
import { type PanelRouterCtx, panelRouter } from './panel-router'
@@ -11,10 +12,13 @@ import { type PanelRouterCtx, panelRouter } from './panel-router'
// eslint-disable-next-line ts/no-var-requires, ts/no-require-imports
const Server = require('../../node_modules/ws/lib/websocket-server') as typeof WsServer
+export type PanelController = Awaited>
+
export async function startPanelController(
extensionContext: vscode.ExtensionContext,
storage: MyStorageType,
- sessionTracker: DebuggerTracker,
+ recorderCodeGenSession: () => RecorderCodeGenSession | null,
+ debuggerTracker: DebuggerTracker,
htmlUpdaterPort: number,
) {
let setWebviewIsReady = () => {}
@@ -80,6 +84,7 @@ export async function startPanelController(
+
@@ -109,11 +114,11 @@ export async function startPanelController(
}
catch (error) {
console.log(error)
- if (error instanceof TRPCError) {
- vscode.window.showErrorMessage(String(error.cause))
+ if (error instanceof TRPCError && error.cause) {
+ vscode.window.showErrorMessage(error.cause.message)
}
else if (error instanceof Error) {
- vscode.window.showErrorMessage(String(error))
+ vscode.window.showErrorMessage(error.message)
}
panel.webview.postMessage({
id,
@@ -135,6 +140,10 @@ export async function startPanelController(
notifyDebuggerRestarted: () => {
panel.webview.postMessage({ debuggerRestarted: true })
},
+ notifyRecorderEditPerformed: () => {
+ panel?.webview.postMessage({ recorderEditPerformed: true })
+ },
+
dispose() {
htmlUpdaterServer.close()
panel.dispose()
@@ -143,10 +152,11 @@ export async function startPanelController(
}
const ctx: PanelRouterCtx = {
- sessionTracker,
+ debuggerTracker,
storage,
flushPatches: controller.flushPatches,
setWebviewIsReady,
+ recorderCodeGenSession,
}
return controller
diff --git a/packages/extension/src/panel-controller/panel-router.ts b/packages/extension/src/panel-controller/panel-router.ts
index 14a3779..7c2eeff 100644
--- a/packages/extension/src/panel-controller/panel-router.ts
+++ b/packages/extension/src/panel-controller/panel-router.ts
@@ -1,20 +1,47 @@
+import { initTRPC } from '@trpc/server'
import path from 'pathe'
import * as vscode from 'vscode'
-import { initTRPC } from '@trpc/server'
import * as z from 'zod/mini'
-import { workspaceCssFiles } from '../util/workspace-css-files'
import type { MyStorageType } from '../my-extension-storage'
+import { type RecorderCodeGenSession, zSerializedRegexp } from '../recorder/recorder-codegen-session'
import type { DebuggerTracker } from '../util/debugger-tracker'
+import { workspaceCssFiles } from '../util/workspace-css-files'
export interface PanelRouterCtx {
- sessionTracker: DebuggerTracker
+ debuggerTracker: DebuggerTracker
storage: MyStorageType
flushPatches: () => void
+ recorderCodeGenSession: () => RecorderCodeGenSession | null
setWebviewIsReady: () => void
}
const t = initTRPC.context().create()
+const zTestingLibraryQueryArgs = z.tuple([
+ z.string(),
+ z.tuple([
+ z.union([z.string(), zSerializedRegexp]),
+ z.optional(z.record(
+ z.string(),
+ z.union([z.string(), z.boolean(), zSerializedRegexp]),
+ )),
+ ]),
+])
+export type TestingLibraryQueryArgs = z.infer
+
+export const zRecordedEventData = z.object({
+ text: z.optional(z.string()), // Used for change events
+ options: z.optional(z.array(z.string())), // Used for selectOptions events
+ enterKeyPressed: z.optional(z.boolean()), // Used for Enter keydown events
+ indexIfMultipleFound: z.optional(z.number()), // Used when there are multiple elements for the same query
+ clearBeforeType: z.optional(z.boolean()), // Clear the input before typing
+ checked: z.optional(z.boolean()), // Used for expect/toBeChecked statements
+ enabled: z.optional(z.boolean()), // Used for expect/toBeEnabled statements
+})
+
+const zExpectStatementType = z.enum(['minimal', 'toHaveValue', 'toBeEnabled', 'toHaveTextContent', 'toBeChecked'])
+export type ExpectStatementType = z.infer
+
/** Defines RPCs callable from the WebView to the VSCode Extension. */
export const panelRouter = t.router({
setWebviewIsReady: t.procedure
@@ -24,7 +51,7 @@ export const panelRouter = t.router({
serializeHtml: t.procedure
.query(async ({ ctx }) => {
- const html = await ctx.sessionTracker.runDebugExpression('globalThis.__serializeHtml()')
+ const html = await ctx.debuggerTracker.runDebugExpression('globalThis.__serializeHtml()')
return html
}),
@@ -111,7 +138,7 @@ export const panelRouter = t.router({
.mutation(async ({ ctx }) => {
const files = await ctx.storage.get('enabledCssFiles') ?? []
const filesAsString = JSON.stringify(files)
- const resultStr = await ctx.sessionTracker.runDebugExpression(
+ const resultStr = await ctx.debuggerTracker.runDebugExpression(
`globalThis.__replaceStyles(${filesAsString})`,
)
ctx.flushPatches()
@@ -179,6 +206,50 @@ export const panelRouter = t.router({
.mutation(async ({ ctx }) => {
ctx.storage.set('stylePromptDismissed', false)
}),
+
+ recordInputAsCode: t.procedure
+ .input(
+ z.object({
+ event: z.string(),
+ eventData: zRecordedEventData,
+ query: zTestingLibraryQueryArgs,
+ // Whether to generate an 'expect' statement
+ useExpect: z.optional(zExpectStatementType),
+ // Whether to use fireEvent instead of userEvent
+ useFireEvent: z.optional(z.boolean()),
+ }),
+ )
+ .mutation(async ({ ctx, input }) => {
+ const { event, eventData, query: [findMethod, [queryArg0, queryOptions]], useExpect, useFireEvent } = input
+ const recorderCodeGenSession = ctx.recorderCodeGenSession()
+ const _insertion = await recorderCodeGenSession?.recordInputAsCode(
+ ctx.debuggerTracker,
+ {
+ event,
+ eventData,
+ findMethod,
+ queryArg0,
+ queryOptions,
+ useExpect,
+ useFireEvent,
+ },
+ )
+ return recorderCodeGenSession?.insertions
+ }),
+
+ removeRecorderInsertion: t.procedure
+ .input(
+ z.object({
+ line: z.number(),
+ idx: z.optional(z.number()),
+ }),
+ )
+ .mutation(async ({ ctx, input }) => {
+ const { line, idx } = input
+ const session = ctx.recorderCodeGenSession()
+ session?.removeInsertion(line, idx)
+ return session?.insertions
+ }),
})
export type PanelRouter = typeof panelRouter
diff --git a/packages/extension/src/recorder/create-new-test-file/create-ui-test-code.ts b/packages/extension/src/recorder/create-new-test-file/create-ui-test-code.ts
new file mode 100644
index 0000000..1fde14d
--- /dev/null
+++ b/packages/extension/src/recorder/create-new-test-file/create-ui-test-code.ts
@@ -0,0 +1,60 @@
+import { walk } from 'estree-walker'
+import type { ParseResult } from 'oxc-parser'
+import type { TestFrameworkInfo } from '../../framework-support/detect-test-framework'
+import type { TestingLibrary } from '../../framework-support/detect-test-library'
+
+export function createUITestCode(
+ { program, word, frameworkInfo, testingLibrary, relativePathToSrc }:
+ {
+ program: ParseResult
+ word: string
+ frameworkInfo: TestFrameworkInfo
+ testingLibrary: TestingLibrary
+ relativePathToSrc: string
+ },
+): [Error, null] | [null, { exportName: string, testContent: string }] {
+ const { exportName, isDefaultExport } = (() => {
+ let result: string | null = null
+ let isDefaultExport = false
+ walk(program, {
+ enter(node) {
+ if (node.type === 'ExportNamedDeclaration' || node.type === 'ExportDefaultDeclaration') {
+ const nodeName = node?.declaration?.name
+ ?? node?.declaration?.id?.name
+ ?? node?.declaration?.declarations?.[0]?.id?.name
+ ?? node?.declaration?.declarations?.[0]?.name
+ if (nodeName === word) {
+ result = nodeName ?? null
+ isDefaultExport = node.type === 'ExportDefaultDeclaration'
+ }
+ }
+ },
+ })
+
+ return { exportName: result as string | null, isDefaultExport }
+ })()
+
+ if (!exportName) {
+ return [new Error(`No valid export found. Must be an exported capitalized function name. Got ${word}`), null]
+ }
+
+ // React/Solid component convention: starts with capital letter
+ if (!/^[A-Z]/.test(exportName)) {
+ return [new Error(`Selection must be a capitalized identifier, e.g. a React component name. Got "${word}".`), null]
+ }
+
+ const fwImport = frameworkInfo.framework === 'bun' ? 'bun:test' : frameworkInfo.framework
+ const testImport = frameworkInfo.framework === 'jest' ? '' : `import { test } from '${fwImport}'\n`
+
+ const isArrowRender = testingLibrary === '@solidjs/testing-library'
+
+ // Create basic test content
+ const testContent = `${testImport}import { render } from '${testingLibrary}'
+import ${isDefaultExport ? exportName : `{ ${exportName} }`} from './${relativePathToSrc}'
+
+test('basic usage', async () => {
+ (() => render(${isArrowRender ? `() => <${exportName} />` : `<${exportName} />`}))()
+})
+`
+ return [null, { exportName, testContent }]
+}
diff --git a/packages/extension/src/recorder/create-new-test-file/create-ui-test-file.ts b/packages/extension/src/recorder/create-new-test-file/create-ui-test-file.ts
new file mode 100644
index 0000000..bf19e9a
--- /dev/null
+++ b/packages/extension/src/recorder/create-new-test-file/create-ui-test-file.ts
@@ -0,0 +1,84 @@
+import { Buffer } from 'node:buffer'
+import type { ParseResult } from 'oxc-parser'
+import * as path from 'pathe'
+import * as vscode from 'vscode'
+import { zFrameworkSetting } from '../../extension'
+import { detectTestFramework } from '../../framework-support/detect-test-framework'
+import { SUPPORTED_TESTING_LIBRARIES, detectTestLibrary } from '../../framework-support/detect-test-library'
+import { extensionSetting } from '../../util/extension-setting'
+import { createUITestCode } from './create-ui-test-code'
+
+export async function createUiTestFile() {
+ const editor = vscode.window.activeTextEditor
+ if (!editor) {
+ return
+ }
+
+ const doc = editor.document
+
+ const selection = editor.selection
+ const wordRange = doc.getWordRangeAtPosition(selection.active, /\w+/)
+ const word = doc.getText(wordRange)
+
+ if (!wordRange || !word) {
+ vscode.window.showErrorMessage(
+ `No valid identifier found. Must be an exported capitalized function name. Got ${word}`,
+ )
+ return
+ }
+
+ const docFileName = doc.fileName
+ const docText = doc.getText()
+
+ const frameworkSetting = (() => {
+ const parsed = zFrameworkSetting
+ .safeParse(extensionSetting('ui-test-visualizer.testFramework'))
+ return parsed.success ? parsed.data : 'autodetect'
+ })()
+
+ const frameworkInfo = await detectTestFramework(editor.document.uri.fsPath, frameworkSetting)
+ const testingLibrary = await detectTestLibrary(editor.document.uri.fsPath)
+
+ if (!testingLibrary) {
+ vscode.window.showErrorMessage(`Could not detect a testing library for ${editor.document.uri.fsPath}. Supported testing libraries are ${SUPPORTED_TESTING_LIBRARIES.join(', ')}.`)
+ return
+ }
+
+ const currentDir = path.dirname(editor.document.uri.fsPath)
+
+ const relativePathToSrc = path.relative(currentDir, doc.fileName).replace(/\.[jt]sx?$/, '')
+
+ // @ts-expect-error import the wasm file directly
+ const { parseSync } = (await import('@oxc-parser/binding-wasm32-wasi')) as typeof import('oxc-parser')
+
+ let program: ParseResult = parseSync(docFileName, docText, {}).program
+ // @ts-expect-error needs to be JSON.parse'd when using the wasm parser
+ program = JSON.parse(program)
+
+ const [error, result] = await createUITestCode({ program, word, frameworkInfo, testingLibrary, relativePathToSrc })
+ if (error) {
+ vscode.window.showErrorMessage(error.message)
+ return
+ }
+ const { exportName, testContent } = result
+
+ const testFileName = `${exportName}.test.tsx`
+ const testFileUri = vscode.Uri.file(path.join(currentDir, testFileName))
+
+ // Check if the test file already exists
+ try {
+ await vscode.workspace.fs.stat(testFileUri)
+ vscode.window.showErrorMessage(`Test file ${testFileName} already exists.`)
+ return
+ }
+ catch {
+ // File does not exist, proceed to create
+ }
+
+ // Write the file
+ await vscode.workspace.fs.writeFile(testFileUri, Buffer.from(testContent, 'utf8'))
+
+ // Open the new test file
+ const newDocument = await vscode.workspace.openTextDocument(testFileUri)
+ await vscode.window.showTextDocument(newDocument)
+}
diff --git a/packages/extension/src/recorder/generate-code-from-input.ts b/packages/extension/src/recorder/generate-code-from-input.ts
new file mode 100644
index 0000000..3a715de
--- /dev/null
+++ b/packages/extension/src/recorder/generate-code-from-input.ts
@@ -0,0 +1,232 @@
+import type { SupportedFramework } from '../framework-support/detect-test-framework'
+import type { TestingLibrary } from '../framework-support/detect-test-library'
+import type { RecordInputAsCodeParams } from './recorder-codegen-session'
+
+export interface RecorderGeneratedCode {
+ code: string[]
+ debugExpression: string
+ requiredImports: Record
+}
+
+export function generateCodeFromInput(
+ hasUserEventLib: boolean,
+ testLibrary: TestingLibrary,
+ testFramework: SupportedFramework,
+ userEventLibPath: string,
+ {
+ event,
+ eventData,
+ findMethod,
+ queryArg0,
+ queryOptions,
+ useExpect,
+ useFireEvent,
+ }: RecordInputAsCodeParams,
+): RecorderGeneratedCode {
+ const parsedQueryOptions = queryOptions && Object.entries(queryOptions).reduce(
+ (result, entry) => {
+ const [key, val] = entry
+ result[key] = (() => {
+ if (typeof val === 'string') {
+ return `'${val.replace(/'/g, '\\\'')}'`
+ }
+ else if (typeof val === 'boolean') {
+ return val
+ }
+ else if (val.type === 'regexp') {
+ return val.value
+ }
+ else {
+ return ''
+ }
+ })()
+
+ return result
+ },
+ {} as Record,
+ )
+
+ const queryArgsStr = (() => {
+ let result = typeof queryArg0 === 'string' ? `'${queryArg0}'` : queryArg0.value
+ if (!parsedQueryOptions) {
+ return result
+ }
+ const entries = Object.entries(parsedQueryOptions).map(([key, val]) => {
+ return `${key}: ${String(val)}`
+ })
+ let optionsStr = entries.join(', ')
+ if (entries.length > 0) {
+ optionsStr = `{ ${optionsStr} }`
+ result += `, ${optionsStr}`
+ }
+ return result
+ })()
+
+ const screen = 'screen'
+ const fireEvent = 'fireEvent'
+ const userEvent = 'userEvent'
+ const expect = 'expect'
+
+ /**
+ * e.g. `screen.getByRole('button', { name: 'Submit' })`
+ * or just `document`
+ */
+ const selector = (() => {
+ if (queryArg0 === 'document') {
+ return 'document'
+ }
+ let index = ''
+ if (eventData.indexIfMultipleFound !== undefined) {
+ findMethod = findMethod.replace(/^getBy/, 'getAllBy')
+ index = `[${eventData.indexIfMultipleFound}]`
+ }
+ return `${screen}.${findMethod}(${queryArgsStr})${index}`
+ })()
+
+ let mainLine = ''
+ const requiredImports: Record = {
+ [screen]: testLibrary,
+ }
+
+ // When 'useExpect' is defined, generate an 'expect' statement
+ if (useExpect) {
+ // Generate an 'expect' statement based on the selected type
+ mainLine = (() => {
+ function escapeQuotes(str: string) {
+ return str.replaceAll(/['\\]/g, (match) => {
+ return `\\${match}`
+ })
+ }
+ switch (useExpect) {
+ case 'toHaveTextContent': {
+ const textContent = escapeQuotes(eventData.text ?? '')
+ return `${expect}(${selector}).toHaveTextContent('${textContent}')`
+ }
+ case 'toHaveValue': {
+ const value = escapeQuotes(eventData.text ?? '')
+ return `${expect}(${selector}).toHaveValue('${value}')`
+ }
+ case 'toBeEnabled': {
+ const not = eventData.enabled ? '' : 'not.'
+ return `${expect}(${selector}).${not}toBeEnabled()`
+ }
+ case 'toBeChecked': {
+ const not = eventData.checked ? '' : 'not.'
+ return `${expect}(${selector}).${not}toBeChecked()`
+ }
+ case 'minimal':
+ default:
+ return `${expect}(${selector})`
+ }
+ })()
+
+ if (testFramework === 'vitest') {
+ requiredImports[expect] = testFramework
+ }
+ if (testFramework === 'bun') {
+ requiredImports[expect] = 'bun:test'
+ }
+ }
+ // Otherwise, generate a userEvent call
+ else if (useFireEvent) {
+ const fireEventArgs = (() => {
+ if (event === 'change' && eventData.text) {
+ const value = eventData.text.replace(/'/g, '\\\'')
+ return `, { target: { value: '${value}' } }`
+ }
+ if (event === 'selectOptions' && eventData.options) {
+ return `, { target: { value: '${eventData.options[0]}' } }`
+ }
+ return ''
+ })()
+
+ mainLine = `${fireEvent}.${event}(${selector}${fireEventArgs})`
+
+ requiredImports[fireEvent] = testLibrary
+ }
+ else if (!hasUserEventLib) {
+ throw new Error('Cannot use userEvent without @testing-library/user-event installed')
+ }
+ else {
+ const userEventArgs = (() => {
+ // When using userEvent with text inputs, the method is either 'type' or 'clear'
+ if (event === 'change' && typeof eventData.text === 'string') {
+ // If the text is empty, use 'clear' instead of 'type'
+ if (eventData.text.length === 0) {
+ event = 'clear'
+ return ''
+ }
+
+ // Otherwise 'type' the text
+ event = 'type'
+ const value = eventData.text.replace(/'/g, '\\\'')
+ return `, '${value}'`
+ }
+ if (event === 'selectOptions' && eventData.options) {
+ return `, [${eventData.options.map(it => `'${it.replace(/'/g, '\\\'')}'`).join(', ')}]`
+ }
+ return ''
+ })()
+
+ mainLine = `await ${userEvent}.${event}(${selector}${userEventArgs})`
+
+ if (event === 'keydown' && eventData.enterKeyPressed) {
+ mainLine = `await ${userEvent}.keyboard('{enter}')`
+ }
+
+ requiredImports[userEvent] = '@testing-library/user-event'
+ }
+
+ const importCode = Object.entries(requiredImports).map(([importName, from]) => {
+ if (from === 'vitest') {
+ // Workaround: we can't import vitest in the debug expressions because it can't be imported with 'require',
+ // so run the global 'expect' function (using `vitest --globals` flag),
+ // but still generate the import code after the recording session.
+ return ''
+ }
+
+ // user-event v13 is used when running the debug expressions, because it's the last version
+ // where the methods were synchronous e.g. `userEvent.click(...);`.
+ // Newer versions use async code e.g. `await userEvent.click(...);`,
+ // which fail when running through the debugger's 'evaluate' request.
+ if (from === '@testing-library/user-event') {
+ from = userEventLibPath
+ return `const ${importName} = globalThis.require('${from}').default;`
+ }
+ return `const { ${importName} } = globalThis.require('${from}');`
+ }).filter(Boolean).join('\n')
+
+ const code = [mainLine]
+
+ // Clear the input before typing when the 'clearBeforeType' flag is set
+ if (event === 'type' && eventData.clearBeforeType) {
+ code.unshift(`await ${userEvent}.clear(${selector})`)
+ }
+
+ // The fireEvent or userEvent statement to run in the debugger.
+ // May be slightly different than the code that is actually generated for the user.
+ const debugEventStatement = (() => {
+ const result = code.map(line => line.replace(/\s*await\s*/, '')).join('\n') // No 'awaits' allowed in debug expressions
+
+ // When writing react tests with userEvent v13, wrap in 'act'.
+ if (testLibrary === '@testing-library/react' && !useFireEvent && !useExpect) {
+ return `globalThis.require('react').act(() => { ${result} });`
+ }
+ return result
+ })()
+
+ // Replicate the input event from the webview to the test runtime.
+ // We do this through a debug expression, which is the same as running code through vscode's 'Debug Terminal'.
+ const debugExpression = `
+(() => {
+${importCode}
+${debugEventStatement}
+})()
+`
+
+ return {
+ code,
+ debugExpression,
+ requiredImports,
+ }
+}
diff --git a/packages/extension/src/recorder/perform-edit.ts b/packages/extension/src/recorder/perform-edit.ts
new file mode 100644
index 0000000..8e19d64
--- /dev/null
+++ b/packages/extension/src/recorder/perform-edit.ts
@@ -0,0 +1,156 @@
+import { walk } from 'estree-walker'
+import * as vscode from 'vscode'
+import type { PanelController } from '../panel-controller/panel-controller'
+import { getOrOpenEditor } from '../util/util'
+import type { RecorderCodeInsertions } from './recorder-codegen-session'
+
+export async function performEdit(
+ filePath: string,
+ insertions: RecorderCodeInsertions,
+ panelController: PanelController,
+) {
+ if (Object.keys(insertions).length === 0) {
+ // No edits to perform
+ return
+ }
+
+ const editor = await getOrOpenEditor(filePath)
+
+ if (!editor) {
+ vscode.window.showErrorMessage(`No editor found for ${filePath.split('/').pop()}`)
+ return
+ }
+
+ // eslint-disable-next-line ts/no-var-requires, ts/no-require-imports
+ const { parseSync } = require('@oxc-parser/binding-wasm32-wasi')
+
+ // Convert insertion line numbers to character indexes
+ const insertionCharIndexes: number[] = []
+ for (const line in insertions) {
+ const lineNumber = Number.parseInt(line) - 1 // 0-based
+ const position = new vscode.Position(lineNumber, 0)
+ const offset = editor.document.offsetAt(position)
+ insertionCharIndexes.push(offset)
+ }
+
+ const requiresAsync = Object.keys(insertions)
+ .some(lineNum => insertions[Number(lineNum)]?.some(line => /\s*await*/.test(line[0])))
+
+ const reverseOrderInsertions = Object.entries(insertions)
+ .sort((a, b) => Number(b[0]) - Number(a[0]))
+
+ await editor.edit((editBuilder) => {
+ for (const [line, lines] of reverseOrderInsertions) {
+ const lineNumber = Number.parseInt(line)
+ const position = new vscode.Position(lineNumber - 1, 0)
+ for (let [code, _requiredImports] of lines) {
+ const indent: string = (() => {
+ // Indent should be the longest indentation between the paused line and the previous line.
+ // This is to make sure the right indent is used when paused at the end of the test.
+ // e.g.
+ // test('click button', () => {
+ // const button = screen.getByRole('button')
+ // button.click() <-- when paused here, use this line's indent.
+ // }) <-- when paused here, use previous line's indent.
+
+ const line1 = editor.document.lineAt(lineNumber - 1)
+ const line2 = editor.document.lineAt(lineNumber - 2)
+ return [line1, line2].map(it => it.text.match(/^\s*/)?.[0] || '').sort((a, b) => b.length - a.length)[0] || ''
+ })()
+
+ code = `${indent}${code}\n`
+
+ editBuilder.insert(position, code)
+ }
+ }
+
+ // Figure out where to put each import statement
+ // Either add a new import, or edit an existing one to import something else
+ const importInsertionPoints = new Map()
+ const existingImports = new Set()
+ {
+ const parsed = parseSync(editor.document.fileName, editor.document.getText(), {})
+ const programJson = parsed.program
+ const program = JSON.parse(programJson)
+
+ walk(program, {
+ enter(node) {
+ if (node.type === 'ImportDeclaration') {
+ if (node.source.type === 'Literal') {
+ const endOfLastSpecifier = node.specifiers.at(-1)?.end
+ if (endOfLastSpecifier) {
+ importInsertionPoints.set(node.source.value, endOfLastSpecifier)
+ }
+ }
+ for (const specifier of node.specifiers) {
+ if (['ImportSpecifier', 'ImportDefaultSpecifier', 'ImportNamespaceSpecifier'].includes(specifier.type)) {
+ existingImports.add(specifier.local.name)
+ }
+ }
+ }
+
+ // When the test needs to be async, insert the 'async' keyword if it's missing
+ if (
+ requiresAsync
+ // Find the running test
+ && node.type === 'CallExpression' && ['it', 'fit', 'test'].includes(node?.callee.name)
+ ) {
+ for (const argNode of node.arguments) {
+ // Find the arrow function containing the insertion char indexes
+ if (
+ ['FunctionDeclaration', 'FunctionExpression', 'ArrowFunctionExpression'].includes(argNode?.type ?? '')
+ && argNode?.async === false
+ && insertionCharIndexes.some(charIndex => charIndex >= argNode.start && charIndex <= argNode.end)
+ ) {
+ // Check if the function node contains any insertion char indexes
+ for (const charIndex of insertionCharIndexes) {
+ if (charIndex >= argNode.start && charIndex <= argNode.end) {
+ const position = editor.document.positionAt(argNode.start)
+ editBuilder.insert(position, 'async ')
+ }
+ }
+ }
+ }
+ }
+ },
+ })
+ }
+
+ // Get the list of imports to add
+ const importList: { importName: string, from: string }[] = []
+ for (const [_lineNum, insertionGroup] of Object.entries(insertions)) {
+ for (const [_code, requiredImports] of insertionGroup) {
+ for (const [importName, from] of Object.entries(requiredImports)) {
+ if (existingImports.has(importName)) {
+ continue
+ }
+
+ importList.push({ importName, from })
+
+ existingImports.add(importName)
+ }
+ }
+ }
+
+ // Edit the imports into the file
+ for (const { importName, from } of importList) {
+ const insertionPoint = importInsertionPoints.get(from)
+ if (insertionPoint) {
+ const position = editor.document.positionAt(insertionPoint)
+ editBuilder.insert(position, `, ${importName}`)
+ }
+ else {
+ editBuilder.insert(new vscode.Position(0, 0), `import { ${importName} } from '${from}'\n`)
+ }
+ }
+ })
+
+ // Remove the insertions from the state after they've been inserted into the code
+ for (const line in insertions) {
+ delete insertions[Number(line)]
+ }
+
+ panelController.notifyRecorderEditPerformed()
+
+ await editor.document.save()
+}
diff --git a/packages/extension/src/recorder/recorder-codegen-session.ts b/packages/extension/src/recorder/recorder-codegen-session.ts
new file mode 100644
index 0000000..ae6fcfe
--- /dev/null
+++ b/packages/extension/src/recorder/recorder-codegen-session.ts
@@ -0,0 +1,145 @@
+import path from 'pathe'
+import * as vscode from 'vscode'
+import * as z from 'zod/mini'
+import type { SupportedFramework } from '../framework-support/detect-test-framework'
+import type { TestingLibrary } from '../framework-support/detect-test-library'
+import type { PanelController } from '../panel-controller/panel-controller'
+import type { ExpectStatementType, zRecordedEventData } from '../panel-controller/panel-router'
+import type { DebuggerTracker } from '../util/debugger-tracker'
+import { generateCodeFromInput } from './generate-code-from-input'
+import { performEdit } from './perform-edit'
+
+export type RecorderCodeGenSession = Awaited>
+
+export type RecorderCodeInsertions = Record][]>
+
+export type SerializedRegexp = z.infer
+export const zSerializedRegexp = z.object({
+ type: z.literal('regexp'),
+ value: z.string(),
+})
+
+export interface RecordInputAsCodeParams {
+ event: string
+ eventData: z.infer
+ findMethod: string
+ queryArg0: string | SerializedRegexp
+ queryOptions?: Record
+ useExpect?: ExpectStatementType
+ useFireEvent?: boolean
+}
+
+export function startRecorderCodeGenSession(
+ testFile: string,
+ testFramework: SupportedFramework,
+ testLibrary: TestingLibrary,
+ panelController: PanelController,
+) {
+ const insertions: RecorderCodeInsertions = {}
+ function addInsertion(line: number, text: string, requiredImports: Record) {
+ const lines = insertions[line] ?? (insertions[line] = [])
+ lines.push([text, requiredImports])
+ updateCodeLens.fire()
+ }
+ function removeInsertion(line: number, idx?: number) {
+ if (idx === undefined) {
+ delete insertions[line]
+ }
+ else {
+ insertions[line]?.splice(idx, 1)
+ if (insertions[line]?.length === 0) {
+ delete insertions[line]
+ }
+ }
+ updateCodeLens.fire()
+ }
+
+ const disposables = new Set()
+
+ // Show Code Lens in between lines of code to indicate where the generated code will go.
+ const updateCodeLens = new vscode.EventEmitter()
+ disposables.add(vscode.languages.registerCodeLensProvider(
+ [{ pattern: testFile }],
+ {
+ provideCodeLenses(document: vscode.TextDocument): vscode.CodeLens[] {
+ const lenses: vscode.CodeLens[] = []
+ for (const [lineStr, _codeLines] of Object.entries(insertions)) {
+ const line = Number(lineStr) - 1
+ if (line >= 0 && line < document.lineCount) {
+ const lineText = document.lineAt(line).text
+ const range = new vscode.Range(line, 0, line, lineText.length)
+ const title = 'Code will be inserted here after the test'
+ lenses.push(new vscode.CodeLens(range, { title, command: '' }))
+ }
+ }
+ return lenses
+ },
+
+ // Weird trick to manually trigger the code lens update.
+ onDidChangeCodeLenses: updateCodeLens.event,
+ },
+ ))
+
+ async function runPerformEdit() {
+ await performEdit(
+ testFile,
+ insertions,
+ panelController,
+ )
+ }
+
+ disposables.add(vscode.debug.onDidChangeActiveStackItem((stackItem) => {
+ if (stackItem === undefined) {
+ runPerformEdit()
+ }
+ }))
+
+ const hasUserEventLib = (() => {
+ try {
+ require.resolve('@testing-library/user-event', { paths: [path.dirname(testFile)] })
+ return true
+ }
+ catch {
+ return false
+ }
+ })()
+
+ return {
+ recordInputAsCode: async (
+ debuggerTracker: DebuggerTracker,
+ recordInputAsCodeParams: RecordInputAsCodeParams,
+ ): Promise<[number, string[]] | null> => {
+ const pausedLocation = await debuggerTracker.getPausedLocation()
+ if (!pausedLocation) {
+ return null
+ }
+
+ const { code, debugExpression, requiredImports } = generateCodeFromInput(
+ hasUserEventLib,
+ testLibrary,
+ testFramework,
+ path.join(__dirname, 'user-event-13.js'),
+ recordInputAsCodeParams,
+ )
+
+ await debuggerTracker.runDebugExpression(debugExpression)
+ panelController.flushPatches()
+
+ // Add the fireEvent code
+ for (const line of code) {
+ addInsertion(pausedLocation.lineNumber, line, requiredImports)
+ }
+
+ return [pausedLocation.lineNumber, code] as const
+ },
+ performEdit: runPerformEdit,
+ insertions,
+ removeInsertion,
+ hasUserEventLib,
+ dispose: () => {
+ for (const disposable of disposables) {
+ disposable.dispose()
+ }
+ },
+ }
+}
diff --git a/packages/extension/src/util/debugger-tracker.ts b/packages/extension/src/util/debugger-tracker.ts
index 30d3738..4e5269d 100644
--- a/packages/extension/src/util/debugger-tracker.ts
+++ b/packages/extension/src/util/debugger-tracker.ts
@@ -2,6 +2,11 @@ import * as vscode from 'vscode'
export type DebuggerTracker = ReturnType
+export interface DebugPauseLocation {
+ filePath: string
+ lineNumber: number
+}
+
/**
* Wrapper around the VSCode debug session with convenience methods.
* Emits debugger-related events e.g. onFrameChange (Step Over) and onDebugRestarted (the Restart button is clicked).
@@ -12,7 +17,12 @@ export function startDebuggerTracker(
{
onFrameChange,
onDebugRestarted,
- }: { onFrameChange: () => void, onDebugRestarted: () => void },
+ onDebugTerminated,
+ }: {
+ onFrameChange: () => void
+ onDebugRestarted: () => void
+ onDebugTerminated: () => void
+ },
) {
const disposables = new Set()
@@ -21,7 +31,13 @@ export function startDebuggerTracker(
let hasHitFirstBreakpoint = false
const startedSessions = new WeakSet()
disposables.add(vscode.debug.onDidStartDebugSession(session => startedSessions.add(session)))
- disposables.add(vscode.debug.onDidTerminateDebugSession(session => startedSessions.delete(session)))
+ disposables.add(vscode.debug.onDidTerminateDebugSession((session) => {
+ startedSessions.delete(session)
+
+ if (session === rootSession) {
+ onDebugTerminated()
+ }
+ }))
disposables.add(vscode.debug.onDidChangeActiveStackItem((stackItem) => {
if (stackItem && startedSessions.has(stackItem?.session)) {
if (hasHitFirstBreakpoint) {
@@ -79,8 +95,38 @@ export function startDebuggerTracker(
return result
}
+ async function getPausedLocation(): Promise {
+ const session = vscode.debug.activeDebugSession
+ if (!session) {
+ return null
+ }
+ try {
+ const response = await session.customRequest('stackTrace', {
+ threadId: 1, // TODO is this always the right threadId?
+ startFrame: 0,
+ levels: 1,
+ })
+ if (response.stackFrames && response.stackFrames.length > 0) {
+ const frame = response.stackFrames[0]
+ const fileUri = frame.source?.path
+ const lineNumber = frame.line
+ const filePath = vscode.Uri.parse(fileUri).fsPath
+ return { filePath, lineNumber }
+ }
+ else {
+ vscode.window.showErrorMessage('No stack frames')
+ return null
+ }
+ }
+ catch (error) {
+ vscode.window.showErrorMessage(`Error: ${error}`)
+ return null
+ }
+ }
+
return {
runDebugExpression,
+ getPausedLocation,
dispose: () => {
for (const disposable of disposables) {
disposable.dispose()
diff --git a/packages/extension/src/util/util.ts b/packages/extension/src/util/util.ts
new file mode 100644
index 0000000..8b06621
--- /dev/null
+++ b/packages/extension/src/util/util.ts
@@ -0,0 +1,46 @@
+import * as vscode from 'vscode'
+
+/**
+ * Creates a function that is restricted to invoking func once.
+ * Repeat calls to the function return the value of the first call.
+ * The func is invoked with the this binding and arguments of the created function.
+ *
+ * You can peek at the result of the first call to the function by calling the peek() method.
+ *
+ * Copied and adapted from lodash's 'once' function.
+ */
+export function onceWithPeek any>(fn: T): {
+ (): ReturnType
+ peek: () => ReturnType | undefined
+} {
+ let called = false
+ let result: ReturnType
+
+ const wrapper = (...args: Parameters): ReturnType => {
+ if (!called) {
+ result = fn(...args)
+ called = true
+ }
+ return result
+ }
+
+ wrapper.peek = (): ReturnType | undefined => {
+ return called ? result : undefined
+ }
+
+ return wrapper
+}
+
+/**
+ * Returns the editor for the given file path, or opens a new editor if it doesn't exist.
+ */
+export async function getOrOpenEditor(filePath: string) {
+ let editor = vscode.window.visibleTextEditors.find(
+ editor => editor.document.uri.path === filePath,
+ )
+ if (!editor) {
+ const document = await vscode.workspace.openTextDocument(vscode.Uri.file(filePath))
+ editor = await vscode.window.showTextDocument(document, vscode.ViewColumn.One)
+ }
+ return editor
+}
diff --git a/packages/extension/test/compat.test.ts b/packages/extension/test/compat.test.ts
index 7bad98e..d2c7460 100644
--- a/packages/extension/test/compat.test.ts
+++ b/packages/extension/test/compat.test.ts
@@ -1,10 +1,10 @@
import { execa } from 'execa'
-import { findUp } from 'find-up'
import getPort from 'get-port'
import path from 'pathe'
import { beforeAll, describe, expect, it } from 'vitest'
import type { Server as WsServer } from 'ws'
import { makeDebugConfig } from '../src/debug-config'
+import { detectTestFramework } from '../src/framework-support/detect-test-framework'
describe('tool compatibility', async () => {
it('works with Jest + Nextjs + SWC minimal/default setup', async () => {
@@ -89,28 +89,6 @@ describe('tool compatibility', async () => {
let fakeHtmlUpdaterServer: WsServer
beforeAll(async () => {
- // These tests require the "build-prod" folder to exist
- {
- const buildDir = await findUp(
- 'build-prod',
- { cwd: examplesPath, type: 'directory' },
- )
- if (!buildDir) {
- const pnpmLock = await findUp(
- 'pnpm-lock.yaml',
- { cwd: __dirname },
- )
- if (!pnpmLock) {
- throw new Error(`Could not find project root from ${__dirname}`)
- }
- console.log('These tests requires the "build-prod" folder to exist. Building it...')
- await execa({
- cwd: path.dirname(pnpmLock),
- stdout: ['pipe', 'inherit'],
- })`pnpm run build`
- }
- }
-
htmlUpdaterPort = await getPort()
fakeHtmlUpdaterServer = new Server({ port: htmlUpdaterPort })
@@ -123,10 +101,11 @@ describe('tool compatibility', async () => {
testFile: string,
testName: string,
) {
+ const fwInfo = await detectTestFramework(path.join(examplesPath, testFile), 'autodetect')
const cfg = await makeDebugConfig(
+ fwInfo,
path.join(examplesPath, testFile),
testName,
- 'autodetect',
htmlUpdaterPort,
[],
)
diff --git a/packages/extension/test/detect-test-framework.test.ts b/packages/extension/test/detect-test-framework.test.ts
index 0f3c564..369f76e 100644
--- a/packages/extension/test/detect-test-framework.test.ts
+++ b/packages/extension/test/detect-test-framework.test.ts
@@ -1,6 +1,6 @@
import { describe, expect, it } from 'vitest'
import path from 'pathe'
-import { detectTestFramework } from '../src/framework-support/detect'
+import { detectTestFramework } from '../src/framework-support/detect-test-framework'
const examplesPath = path.join(__dirname, '../../../examples')
diff --git a/packages/extension/test/recorder/create-ui-test-code.test.ts b/packages/extension/test/recorder/create-ui-test-code.test.ts
new file mode 100644
index 0000000..6c3efb6
--- /dev/null
+++ b/packages/extension/test/recorder/create-ui-test-code.test.ts
@@ -0,0 +1,69 @@
+import { parseSync } from 'oxc-parser'
+import { describe, expect, it } from 'vitest'
+import { createUITestCode } from '../../src/recorder/create-new-test-file/create-ui-test-code'
+import type { SupportedFramework } from '../../src/framework-support/detect-test-framework'
+import type { TestingLibrary } from '../../src/framework-support/detect-test-library'
+
+const program = parseSync('my-component.ts', 'export function MyComponent() {}', {}).program
+
+function input(
+ framework: SupportedFramework,
+ testingLibrary: TestingLibrary,
+): Parameters[0] {
+ return {
+ program,
+ word: 'MyComponent',
+ frameworkInfo: {
+ framework,
+ configPath: '',
+ },
+ relativePathToSrc: 'my-component',
+ testingLibrary,
+ }
+}
+
+describe('createUITestCode', () => {
+ it('jest+react', () => {
+ const [_, result] = createUITestCode(input('jest', '@testing-library/react'))
+ expect(result).toEqual({
+ exportName: 'MyComponent',
+ testContent: `import { render } from '@testing-library/react'
+import { MyComponent } from './my-component'
+
+test('basic usage', async () => {
+ (() => render( ))()
+})
+`,
+ })
+ })
+
+ it('vitest+solid', () => {
+ const [_, result] = createUITestCode(input('vitest', '@solidjs/testing-library'))
+ expect(result).toEqual({
+ exportName: 'MyComponent',
+ testContent: `import { test } from 'vitest'
+import { render } from '@solidjs/testing-library'
+import { MyComponent } from './my-component'
+
+test('basic usage', async () => {
+ (() => render(() => ))()
+})
+`,
+ })
+ })
+
+ it('bun+react', () => {
+ const [_, result] = createUITestCode(input('bun', '@testing-library/react'))
+ expect(result).toEqual({
+ exportName: 'MyComponent',
+ testContent: `import { test } from 'bun:test'
+import { render } from '@testing-library/react'
+import { MyComponent } from './my-component'
+
+test('basic usage', async () => {
+ (() => render( ))()
+})
+`,
+ })
+ })
+})
diff --git a/packages/extension/test/recorder/generate-code-from-input.test.ts b/packages/extension/test/recorder/generate-code-from-input.test.ts
new file mode 100644
index 0000000..165d3fe
--- /dev/null
+++ b/packages/extension/test/recorder/generate-code-from-input.test.ts
@@ -0,0 +1,428 @@
+import { expect, test } from 'vitest'
+import type { RecorderGeneratedCode } from '../../src/recorder/generate-code-from-input'
+import { generateCodeFromInput } from '../../src/recorder/generate-code-from-input'
+
+const userEventLibPath = '/fakepath/user-event-13.js'
+
+test('change an empty text input: vitest + react', () => {
+ const result = generateCodeFromInput(
+ true,
+ '@testing-library/react',
+ 'vitest',
+ userEventLibPath,
+ {
+ event: 'change',
+ eventData: { text: 'test-input' },
+ findMethod: 'getByRole',
+ queryArg0: 'textbox',
+ queryOptions: { name: { type: 'regexp', value: '/^my-input$/i' } },
+ },
+ )
+
+ const expected: RecorderGeneratedCode = {
+ code: [
+ `await userEvent.type(screen.getByRole('textbox', { name: /^my-input$/i }), 'test-input')`,
+ ],
+ debugExpression: `
+(() => {
+const { screen } = globalThis.require('@testing-library/react');
+const userEvent = globalThis.require('/fakepath/user-event-13.js').default;
+globalThis.require('react').act(() => { userEvent.type(screen.getByRole('textbox', { name: /^my-input$/i }), 'test-input') });
+})()
+`,
+ requiredImports: {
+ screen: '@testing-library/react',
+ userEvent: '@testing-library/user-event',
+ },
+ }
+
+ expect(result).toEqual(expected)
+})
+
+test('change an empty text input: vitest + solid', () => {
+ const result = generateCodeFromInput(
+ true,
+ '@solidjs/testing-library',
+ 'vitest',
+ userEventLibPath,
+ {
+ event: 'change',
+ eventData: { text: 'test-input' },
+ findMethod: 'getByRole',
+ queryArg0: 'textbox',
+ queryOptions: { name: { type: 'regexp', value: '/^my-input$/i' } },
+ },
+ )
+
+ const expected: RecorderGeneratedCode = {
+ code: [
+ `await userEvent.type(screen.getByRole('textbox', { name: /^my-input$/i }), 'test-input')`,
+ ],
+ debugExpression: `
+(() => {
+const { screen } = globalThis.require('@solidjs/testing-library');
+const userEvent = globalThis.require('/fakepath/user-event-13.js').default;
+userEvent.type(screen.getByRole('textbox', { name: /^my-input$/i }), 'test-input')
+})()
+`,
+ requiredImports: {
+ screen: '@solidjs/testing-library',
+ userEvent: '@testing-library/user-event',
+ },
+ }
+
+ expect(result).toEqual(expected)
+})
+
+test('change a pre-filled text input', () => {
+ const result = generateCodeFromInput(
+ true,
+ '@testing-library/react',
+ 'vitest',
+ userEventLibPath,
+ {
+ event: 'change',
+ eventData: { text: 'test-input', clearBeforeType: true },
+ findMethod: 'getByRole',
+ queryArg0: 'textbox',
+ queryOptions: { name: { type: 'regexp', value: '/^my-input$/i' } },
+ },
+ )
+
+ const expected: RecorderGeneratedCode = {
+ code: [
+ `await userEvent.clear(screen.getByRole('textbox', { name: /^my-input$/i }))`,
+ `await userEvent.type(screen.getByRole('textbox', { name: /^my-input$/i }), 'test-input')`,
+ ],
+ debugExpression: `
+(() => {
+const { screen } = globalThis.require('@testing-library/react');
+const userEvent = globalThis.require('/fakepath/user-event-13.js').default;
+globalThis.require('react').act(() => { userEvent.clear(screen.getByRole('textbox', { name: /^my-input$/i }))
+userEvent.type(screen.getByRole('textbox', { name: /^my-input$/i }), 'test-input') });
+})()
+`,
+ requiredImports: {
+ screen: '@testing-library/react',
+ userEvent: '@testing-library/user-event',
+ },
+ }
+
+ expect(result).toEqual(expected)
+})
+
+test('generate an expect statement: vitest', () => {
+ const result = generateCodeFromInput(
+ true,
+ '@testing-library/react',
+ 'vitest',
+ userEventLibPath,
+ {
+ event: 'click',
+ eventData: { enabled: true },
+ findMethod: 'getByRole',
+ queryArg0: 'button',
+ queryOptions: { name: 'my-button' },
+ useExpect: 'toBeEnabled',
+ },
+ )
+
+ const expected: RecorderGeneratedCode = {
+ code: [
+ 'expect(screen.getByRole(\'button\', { name: \'my-button\' })).toBeEnabled()',
+ ],
+ debugExpression: `
+(() => {
+const { screen } = globalThis.require('@testing-library/react');
+expect(screen.getByRole('button', { name: 'my-button' })).toBeEnabled()
+})()
+`,
+ requiredImports: {
+ expect: 'vitest',
+ screen: '@testing-library/react',
+ },
+ }
+
+ expect(result).toEqual(expected)
+})
+
+test('generate an expect statement: vitest + solid', () => {
+ const result = generateCodeFromInput(
+ true,
+ '@solidjs/testing-library',
+ 'vitest',
+ userEventLibPath,
+ {
+ event: 'click',
+ eventData: { enabled: true },
+ findMethod: 'getByRole',
+ queryArg0: 'button',
+ queryOptions: { name: 'my-button' },
+ useExpect: 'toBeEnabled',
+ },
+ )
+
+ const expected: RecorderGeneratedCode = {
+ code: [
+ 'expect(screen.getByRole(\'button\', { name: \'my-button\' })).toBeEnabled()',
+ ],
+ debugExpression: `
+(() => {
+const { screen } = globalThis.require('@solidjs/testing-library');
+expect(screen.getByRole('button', { name: 'my-button' })).toBeEnabled()
+})()
+`,
+ requiredImports: {
+ expect: 'vitest',
+ screen: '@solidjs/testing-library',
+ },
+ }
+
+ expect(result).toEqual(expected)
+})
+
+test('generate an expect statement: jest', () => {
+ const result = generateCodeFromInput(
+ true,
+ '@testing-library/react',
+ 'jest',
+ userEventLibPath,
+ {
+ event: 'click',
+ eventData: { enabled: true },
+ findMethod: 'getByRole',
+ queryArg0: 'button',
+ queryOptions: { name: 'my-button' },
+ useExpect: 'toBeEnabled',
+ },
+ )
+
+ const expected: RecorderGeneratedCode = {
+ code: [
+ 'expect(screen.getByRole(\'button\', { name: \'my-button\' })).toBeEnabled()',
+ ],
+ debugExpression: `
+(() => {
+const { screen } = globalThis.require('@testing-library/react');
+expect(screen.getByRole('button', { name: 'my-button' })).toBeEnabled()
+})()
+`,
+ requiredImports: {
+ screen: '@testing-library/react',
+ },
+ }
+
+ expect(result).toEqual(expected)
+})
+
+test('generate an expect statement: bun test api', () => {
+ const result = generateCodeFromInput(
+ true,
+ '@testing-library/react',
+ 'bun',
+ userEventLibPath,
+ {
+ event: 'click',
+ eventData: { enabled: true },
+ findMethod: 'getByRole',
+ queryArg0: 'button',
+ queryOptions: { name: 'my-button' },
+ useExpect: 'toBeEnabled',
+ },
+ )
+
+ const expected: RecorderGeneratedCode = {
+ code: [
+ 'expect(screen.getByRole(\'button\', { name: \'my-button\' })).toBeEnabled()',
+ ],
+ debugExpression: `
+(() => {
+const { screen } = globalThis.require('@testing-library/react');
+const { expect } = globalThis.require('bun:test');
+expect(screen.getByRole('button', { name: 'my-button' })).toBeEnabled()
+})()
+`,
+ requiredImports: {
+ expect: 'bun:test',
+ screen: '@testing-library/react',
+ },
+ }
+
+ expect(result).toEqual(expected)
+})
+
+test('generate a mouseup event with fireEvent', () => {
+ const result = generateCodeFromInput(
+ true,
+ '@testing-library/react',
+ 'vitest',
+ userEventLibPath,
+ {
+ event: 'mouseUp',
+ eventData: {},
+ findMethod: 'getByRole',
+ queryArg0: 'button',
+ queryOptions: { name: 'my-button' },
+ useFireEvent: true,
+ },
+ )
+
+ const expected: RecorderGeneratedCode = {
+ code: [
+ 'fireEvent.mouseUp(screen.getByRole(\'button\', { name: \'my-button\' }))',
+ ],
+ debugExpression: `
+(() => {
+const { screen } = globalThis.require('@testing-library/react');
+const { fireEvent } = globalThis.require('@testing-library/react');
+fireEvent.mouseUp(screen.getByRole('button', { name: 'my-button' }))
+})()
+`,
+ requiredImports: {
+ fireEvent: '@testing-library/react',
+ screen: '@testing-library/react',
+ },
+ }
+
+ expect(result).toEqual(expected)
+})
+
+test('generate toBeChecked expect statement', () => {
+ const result = generateCodeFromInput(
+ true,
+ '@testing-library/react',
+ 'vitest',
+ userEventLibPath,
+ {
+ event: 'click',
+ eventData: { checked: true },
+ findMethod: 'getByRole',
+ queryArg0: 'checkbox',
+ queryOptions: { name: 'my-checkbox' },
+ useExpect: 'toBeChecked',
+ },
+ )
+
+ const expected: RecorderGeneratedCode = {
+ code: [
+ 'expect(screen.getByRole(\'checkbox\', { name: \'my-checkbox\' })).toBeChecked()',
+ ],
+ debugExpression: `
+(() => {
+const { screen } = globalThis.require('@testing-library/react');
+expect(screen.getByRole('checkbox', { name: 'my-checkbox' })).toBeChecked()
+})()
+`,
+ requiredImports: {
+ expect: 'vitest',
+ screen: '@testing-library/react',
+ },
+ }
+
+ expect(result).toEqual(expected)
+})
+
+test('generate not.toBeChecked expect statement', () => {
+ const result = generateCodeFromInput(
+ true,
+ '@testing-library/react',
+ 'vitest',
+ userEventLibPath,
+ {
+ event: 'click',
+ eventData: { checked: false },
+ findMethod: 'getByRole',
+ queryArg0: 'checkbox',
+ queryOptions: { name: 'my-checkbox' },
+ useExpect: 'toBeChecked',
+ },
+ )
+
+ const expected: RecorderGeneratedCode = {
+ code: [
+ 'expect(screen.getByRole(\'checkbox\', { name: \'my-checkbox\' })).not.toBeChecked()',
+ ],
+ debugExpression: `
+(() => {
+const { screen } = globalThis.require('@testing-library/react');
+expect(screen.getByRole('checkbox', { name: 'my-checkbox' })).not.toBeChecked()
+})()
+`,
+ requiredImports: {
+ expect: 'vitest',
+ screen: '@testing-library/react',
+ },
+ }
+
+ expect(result).toEqual(expected)
+})
+
+test('generate toBeEnabled expect statement', () => {
+ const result = generateCodeFromInput(
+ true,
+ '@testing-library/react',
+ 'vitest',
+ userEventLibPath,
+ {
+ event: 'click',
+ eventData: { enabled: true },
+ findMethod: 'getByRole',
+ queryArg0: 'button',
+ queryOptions: { name: 'my-button' },
+ useExpect: 'toBeEnabled',
+ },
+ )
+
+ const expected: RecorderGeneratedCode = {
+ code: [
+ 'expect(screen.getByRole(\'button\', { name: \'my-button\' })).toBeEnabled()',
+ ],
+ debugExpression: `
+(() => {
+const { screen } = globalThis.require('@testing-library/react');
+expect(screen.getByRole('button', { name: 'my-button' })).toBeEnabled()
+})()
+`,
+ requiredImports: {
+ expect: 'vitest',
+ screen: '@testing-library/react',
+ },
+ }
+
+ expect(result).toEqual(expected)
+})
+
+test('generate not.toBeEnabled expect statement', () => {
+ const result = generateCodeFromInput(
+ true,
+ '@testing-library/react',
+ 'vitest',
+ userEventLibPath,
+ {
+ event: 'click',
+ eventData: { enabled: false },
+ findMethod: 'getByRole',
+ queryArg0: 'button',
+ queryOptions: { name: 'my-button' },
+ useExpect: 'toBeEnabled',
+ },
+ )
+
+ const expected: RecorderGeneratedCode = {
+ code: [
+ 'expect(screen.getByRole(\'button\', { name: \'my-button\' })).not.toBeEnabled()',
+ ],
+ debugExpression: `
+(() => {
+const { screen } = globalThis.require('@testing-library/react');
+expect(screen.getByRole('button', { name: 'my-button' })).not.toBeEnabled()
+})()
+`,
+ requiredImports: {
+ expect: 'vitest',
+ screen: '@testing-library/react',
+ },
+ }
+
+ expect(result).toEqual(expected)
+})
diff --git a/packages/extension/tsup.config.ts b/packages/extension/tsup.config.ts
index c79e26c..b197e45 100644
--- a/packages/extension/tsup.config.ts
+++ b/packages/extension/tsup.config.ts
@@ -23,6 +23,11 @@ export default defineConfig((options) => {
'vitest-cli-setup': '../test-setup/src/vitest-cli-setup.ts',
'test-runtime-setup': '../test-setup/src/test-runtime-setup.ts',
'transform-css': './src/transform-css/transform-css.ts',
+
+ // user-event v13 is used when running the recorder's generated code as debug expressions, because it's the last version
+ // where the methods were synchronous e.g. `userEvent.click(...);`. Newer versions use async code like `await userEvent.click(...);`
+ // which fail when running through the debugger's 'evaluate' request.
+ 'user-event-13': './node_modules/@testing-library/user-event/dist/index.js',
},
format: ['cjs'],
outExtension: () => ({
diff --git a/packages/replicate-dom/src/primary/ignored-node-methods.ts b/packages/replicate-dom/src/primary/ignored-node-methods.ts
index d85f56e..da6fb10 100644
--- a/packages/replicate-dom/src/primary/ignored-node-methods.ts
+++ b/packages/replicate-dom/src/primary/ignored-node-methods.ts
@@ -227,6 +227,7 @@ export const IGNORED_NODE_METHODS: {
getEnclosureList: true,
getIntersectionList: true,
getScreenCTM: true,
+ getHTML: true,
querySelector: true,
querySelectorAll: true,
diff --git a/packages/test-setup/src/test-runtime-setup.ts b/packages/test-setup/src/test-runtime-setup.ts
index faf2fd0..5c9fc9f 100644
--- a/packages/test-setup/src/test-runtime-setup.ts
+++ b/packages/test-setup/src/test-runtime-setup.ts
@@ -1,6 +1,7 @@
// Run this script at the beginning of the test process
import { log, error as logError } from 'node:console'
+import { createRequire } from 'node:module'
import { initPrimaryDom, serializeDomNode } from 'replicate-dom'
import difference from 'lodash/difference'
import shadowCss from './shadow.css.txt'
@@ -178,6 +179,10 @@ if (process.env.TEST_FRAMEWORK === 'jest') {
module.exports = preTest
}
+// Make 'require' available in debug expressions for the recorder.
+// May be undefined when running in Bun and Jest.
+globalThis.require ??= createRequire(process.env.TEST_FILE_PATH!)
+
function validateStringArray(value: unknown): string[] | null {
if (!Array.isArray(value)) {
logError(`Invalid CSS files: ${JSON.stringify(value)} ( ${String(value)} )`)
diff --git a/packages/web-view-vite/index.html b/packages/web-view-vite/index.html
index 110d016..d792321 100644
--- a/packages/web-view-vite/index.html
+++ b/packages/web-view-vite/index.html
@@ -2,6 +2,7 @@
+
diff --git a/packages/web-view-vite/package.json b/packages/web-view-vite/package.json
index 94c8aff..d142902 100644
--- a/packages/web-view-vite/package.json
+++ b/packages/web-view-vite/package.json
@@ -7,33 +7,43 @@
"build": "vite build"
},
"dependencies": {
+ "@corvu/resizable": "^0.2.5",
+ "@happy-dom/global-registrator": "^20.0.8",
"@kobalte/core": "0.13.11",
"@kobalte/utils": "^0.9.1",
+ "@shikijs/core": "^3.13.0",
+ "@shikijs/langs": "^3.13.0",
+ "@shikijs/themes": "^3.13.0",
"@solid-primitives/event-listener": "^2.4.3",
"@solid-primitives/map": "^0.7.2",
"@solid-primitives/mutation-observer": "^1.2.2",
+ "@testing-library/dom": "^10.4.1",
+ "@testing-library/user-event": "^14.6.1",
"@trpc/client": "^11.6.0",
"@trpc/server": "^11.6.0",
"@vscode/webview-ui-toolkit": "^1.4.0",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"csstype": "^3.1.3",
+ "happy-dom": "^20.0.8",
"kagekiri": "^2.0.0",
"lodash": "^4.17.21",
- "lucide-solid": "^0.544.0",
+ "lucide-solid": "^0.546.0",
"replicate-dom": "workspace:*",
+ "shiki": "^3.13.0",
"solid-js": "^1.9.9",
"tailwind-merge": "^3.3.1",
"tailwindcss-animate": "^1.0.7",
- "ws": "^8.18.3"
+ "ws": "^8.18.3",
+ "zod": "^4.1.12"
},
"devDependencies": {
- "@tailwindcss/vite": "^4.1.13",
+ "@tailwindcss/vite": "^4.1.14",
"@types/lodash": "^4.17.20",
"@types/vscode-webview": "^1.57.5",
"@types/ws": "^8.18.1",
- "tailwindcss": "^4.1.13",
- "vite": "^7.1.7",
- "vite-plugin-solid": "^2.11.8"
+ "tailwindcss": "^4.1.14",
+ "vite": "^7.1.10",
+ "vite-plugin-solid": "^2.11.9"
}
}
diff --git a/packages/web-view-vite/src/App.tsx b/packages/web-view-vite/src/App.tsx
index 06822d0..4f26e6f 100644
--- a/packages/web-view-vite/src/App.tsx
+++ b/packages/web-view-vite/src/App.tsx
@@ -1,29 +1,17 @@
-import * as webviewToolkit from '@vscode/webview-ui-toolkit'
-import { ErrorBoundary, Show, createSignal } from 'solid-js'
-import { createColorTheme } from './lib/color-theme'
-import { createDomReplica } from './lib/create-dom-replica'
-import { createInspectorHeight } from './inspector/inspector-height'
+import clamp from 'lodash/clamp'
+import debounce from 'lodash/debounce'
+import { ErrorBoundary, Match, Show, Switch, createSignal } from 'solid-js'
+import { Resizable, ResizableHandle, ResizablePanel } from './components/solid-ui/resizable'
import { Toolbar } from './components/Toolbar'
import { Inspector } from './inspector/Inspector'
-import { Resizer } from './inspector/Resizer'
-
-// Importing the router type from the server file
-
-// In order to use the Webview UI Toolkit web components they
-// must be registered with the browser (i.e. webview) using the
-// syntax below.
-{
- const prefix = 'ui-test-visualizer'
- webviewToolkit
- .provideVSCodeDesignSystem()
- .register(webviewToolkit.vsCodeButton({ prefix }))
- .register(webviewToolkit.vsCodeCheckbox({ prefix }))
- .register(webviewToolkit.vsCodeProgressRing({ prefix }))
- .register(webviewToolkit.vsCodeTextField({ prefix }))
-}
+import { createColorTheme } from './lib/color-theme'
+import { createDomReplica } from './lib/create-dom-replica'
+import { createRecorder } from './recorder/recorder'
+import { RecorderPanel } from './recorder/recorder-panel'
+import { ContextMenu } from './components/solid-ui/context-menu'
+import { RecorderContextMenuProvider } from './recorder/recorder-context-menu'
// TODO put these into a context provider
-
export const [replicaHtmlEl, setReplicaHtmlEl] = createSignal()
export const [theme, toggleTheme] = createColorTheme(
replicaHtmlEl,
@@ -36,9 +24,27 @@ export const {
stylesAreLoading,
} = createDomReplica()
-export const inspector = createInspectorHeight()
+export const STORAGE_KEY_INSPECTOR_IS_OPEN = 'ui-test-visualizer.inspector-is-open'
+const inspectorWasOpen = localStorage.getItem(STORAGE_KEY_INSPECTOR_IS_OPEN) === 'true'
+
+export type Panel = 'inspector' | 'recorder'
+const [openPanel, _setOpenPanel] = createSignal(
+ inspectorWasOpen ? 'inspector' : null,
+)
+export { openPanel }
+
+export function updateOpenPanel(newPanel: Panel | null) {
+ _setOpenPanel(newPanel)
+ if (newPanel === 'inspector' || newPanel === null) {
+ localStorage.setItem(STORAGE_KEY_INSPECTOR_IS_OPEN, newPanel === 'inspector' ? 'true' : 'false')
+ }
+}
+
+export const recorder = createRecorder(shadowHost)
export function App() {
+ const { panelSizes, updateBottomPanelHeight } = createBottomPanelHeight()
+
return (
@@ -53,30 +59,74 @@ export function App() {
-
sizes[1] && updateBottomPanelHeight(sizes[1])}
>
- {shadowHost}
-
-
-
-
-
(
-
- Error showing the inspector{error instanceof Error ? `: ${error.message}` : ''}
-
- )}
- >
-
-
-
-
+
+
+ {shadowHost}
+
+
+
+
+
+
+
+ (
+
+ Error showing the recorder UI{error instanceof Error ? `: ${error.message}` : ''}
+
+ )}
+ >
+
+
+
+
+ (
+
+ Error showing the inspector{error instanceof Error ? `: ${error.message}` : ''}
+
+ )}
+ >
+
+
+
+
+
+
+
)
}
+
+/** Store the bottom panel size in localStorage and return a signal for the panel layout sizes. */
+function createBottomPanelHeight() {
+ const BOTTOMPANEL_SIZE_KEY = 'ui-test-visualizer.bottom-panel-size'
+ const BOTTOMPANEL_DEFAULT_SIZE = 0.4
+ const persistPanelSize = debounce((size: number) => {
+ localStorage.setItem(BOTTOMPANEL_SIZE_KEY, size.toString())
+ }, 200)
+ const storedBottomPanelSize = Number(localStorage.getItem(BOTTOMPANEL_SIZE_KEY)) || BOTTOMPANEL_DEFAULT_SIZE
+
+ const [bottomPanelHeight, _setBottomPanelHeight] = createSignal(BOTTOMPANEL_DEFAULT_SIZE)
+ function updateBottomPanelHeight(newHeight: number) {
+ newHeight = clamp(newHeight, 0.15, 0.8)
+ _setBottomPanelHeight(newHeight)
+ persistPanelSize(newHeight)
+ }
+ updateBottomPanelHeight(storedBottomPanelSize)
+
+ function panelSizes() {
+ return openPanel()
+ ? [1 - bottomPanelHeight(), bottomPanelHeight()]
+ : [1, 0]
+ }
+
+ return { panelSizes, updateBottomPanelHeight }
+}
diff --git a/packages/web-view-vite/src/components/HighlightedNode.tsx b/packages/web-view-vite/src/components/HighlightedNode.tsx
new file mode 100644
index 0000000..fa4d043
--- /dev/null
+++ b/packages/web-view-vite/src/components/HighlightedNode.tsx
@@ -0,0 +1,39 @@
+import { makeEventListener } from '@solid-primitives/event-listener'
+import { createSignal } from 'solid-js'
+
+/** Shows a highlight overlay over the given node */
+export function HighlightedNode(props: { node: Node }) {
+ function newRect() {
+ return props.node instanceof Text
+ ? (() => {
+ const range = document.createRange()
+ range.selectNodeContents(props.node)
+ return range.getBoundingClientRect()
+ })()
+ : props.node instanceof Element
+ ? props.node.getBoundingClientRect()
+ : props.node.parentElement?.getBoundingClientRect()
+ }
+
+ const [rect, setRect] = createSignal(newRect())
+
+ // Update the rect on scroll, click, etc
+ makeEventListener(window, 'resize', () => setRect(newRect()))
+ makeEventListener(window, 'scroll', () => setRect(newRect()))
+ makeEventListener(window, 'wheel', () => setRect(newRect()))
+ makeEventListener(window, 'mousedown', () => setRect(newRect()))
+ makeEventListener(window, 'mouseup', () => setRect(newRect()))
+ makeEventListener(window, 'click', () => setRect(newRect()))
+
+ return (
+
+ )
+}
diff --git a/packages/web-view-vite/src/components/Toolbar.tsx b/packages/web-view-vite/src/components/Toolbar.tsx
index e6e39ef..7ffc153 100644
--- a/packages/web-view-vite/src/components/Toolbar.tsx
+++ b/packages/web-view-vite/src/components/Toolbar.tsx
@@ -1,23 +1,28 @@
-import Sun from 'lucide-solid/icons/sun'
+import Code from 'lucide-solid/icons/code'
+import Info from 'lucide-solid/icons/info'
import Moon from 'lucide-solid/icons/moon'
import RefreshCw from 'lucide-solid/icons/refresh-cw'
-import Code from 'lucide-solid/icons/code'
-import type { ParentProps } from 'solid-js'
-import { firstPatchReceived, inspector, refreshShadow, theme, toggleTheme } from '../App'
+import Sun from 'lucide-solid/icons/sun'
+import { type ParentProps, Show, createSignal } from 'solid-js'
+import { firstPatchReceived, openPanel, recorder, refreshShadow, theme, toggleTheme, updateOpenPanel } from '../App'
import { StyleIcon, StylePicker } from './StylePicker'
+import { Popover, PopoverArrow, PopoverContent, PopoverTrigger } from './solid-ui/popover'
import { Tooltip, TooltipContent, TooltipTrigger } from './solid-ui/tooltip'
export function Toolbar() {
+ const [recorderPopoverOpen, setRecorderPopoverOpen] = createSignal(false)
return (
updateOpenPanel(openPanel() === 'inspector' ? null : 'inspector')}
label="Toggle Inspector"
>
-
+
)}
/>
+
)
}
@@ -49,6 +111,7 @@ export function Toolbar() {
interface ToolbarButtonProps extends ParentProps {
label: string
onClick?: () => void
+ appearance?: string
}
function ToolbarButton(props: ToolbarButtonProps) {
@@ -57,7 +120,7 @@ function ToolbarButton(props: ToolbarButtonProps) {
diff --git a/packages/web-view-vite/src/components/solid-ui/context-menu.tsx b/packages/web-view-vite/src/components/solid-ui/context-menu.tsx
new file mode 100644
index 0000000..ab95072
--- /dev/null
+++ b/packages/web-view-vite/src/components/solid-ui/context-menu.tsx
@@ -0,0 +1,234 @@
+import type { Component, ComponentProps, JSX, ValidComponent } from 'solid-js'
+import { splitProps } from 'solid-js'
+
+import * as ContextMenuPrimitive from '@kobalte/core/context-menu'
+import type { PolymorphicProps } from '@kobalte/core/polymorphic'
+
+import { cn } from './utils'
+
+const ContextMenuTrigger = ContextMenuPrimitive.Trigger
+const ContextMenuPortal = ContextMenuPrimitive.Portal
+const ContextMenuSub = ContextMenuPrimitive.Sub
+const ContextMenuGroup = ContextMenuPrimitive.Group
+const ContextMenuRadioGroup = ContextMenuPrimitive.RadioGroup
+
+const ContextMenu: Component = (props) => {
+ return
+}
+
+type ContextMenuContentProps =
+ ContextMenuPrimitive.ContextMenuContentProps & {
+ class?: string | undefined
+ }
+
+function ContextMenuContent(props: PolymorphicProps>) {
+ const [local, others] = splitProps(props as ContextMenuContentProps, ['class'])
+ return (
+
+
+
+ )
+}
+
+type ContextMenuItemProps =
+ ContextMenuPrimitive.ContextMenuItemProps & {
+ class?: string | undefined
+ }
+
+function ContextMenuItem(props: PolymorphicProps>) {
+ const [local, others] = splitProps(props as ContextMenuItemProps, ['class'])
+ return (
+
+ )
+}
+
+const ContextMenuShortcut: Component> = (props) => {
+ const [local, others] = splitProps(props, ['class'])
+ return
+}
+
+type ContextMenuSeparatorProps =
+ ContextMenuPrimitive.ContextMenuSeparatorProps & {
+ class?: string | undefined
+ }
+
+function ContextMenuSeparator(props: PolymorphicProps>) {
+ const [local, others] = splitProps(props as ContextMenuSeparatorProps, ['class'])
+ return (
+
+ )
+}
+
+type ContextMenuSubTriggerProps =
+ ContextMenuPrimitive.ContextMenuSubTriggerProps & {
+ class?: string | undefined
+ children?: JSX.Element
+ }
+
+function ContextMenuSubTrigger(props: PolymorphicProps>) {
+ const [local, others] = splitProps(props as ContextMenuSubTriggerProps, ['class', 'children'])
+ return (
+
+ {local.children}
+
+
+
+
+ )
+}
+
+type ContextMenuSubContentProps =
+ ContextMenuPrimitive.ContextMenuSubContentProps & {
+ class?: string | undefined
+ }
+
+function ContextMenuSubContent(props: PolymorphicProps>) {
+ const [local, others] = splitProps(props as ContextMenuSubContentProps, ['class'])
+ return (
+
+ )
+}
+
+type ContextMenuCheckboxItemProps =
+ ContextMenuPrimitive.ContextMenuCheckboxItemProps & {
+ class?: string | undefined
+ children?: JSX.Element
+ }
+
+function ContextMenuCheckboxItem(props: PolymorphicProps>) {
+ const [local, others] = splitProps(props as ContextMenuCheckboxItemProps, ['class', 'children'])
+ return (
+
+
+
+
+
+
+
+
+ {local.children}
+
+ )
+}
+
+type ContextMenuGroupLabelProps =
+ ContextMenuPrimitive.ContextMenuGroupLabelProps & {
+ class?: string | undefined
+ }
+
+function ContextMenuGroupLabel(props: PolymorphicProps>) {
+ const [local, others] = splitProps(props as ContextMenuGroupLabelProps, ['class'])
+ return (
+
+ )
+}
+
+type ContextMenuRadioItemProps =
+ ContextMenuPrimitive.ContextMenuRadioItemProps & {
+ class?: string | undefined
+ children?: JSX.Element
+ }
+
+function ContextMenuRadioItem(props: PolymorphicProps>) {
+ const [local, others] = splitProps(props as ContextMenuRadioItemProps, ['class', 'children'])
+ return (
+
+
+
+
+
+
+
+
+ {local.children}
+
+ )
+}
+
+export {
+ ContextMenu,
+ ContextMenuTrigger,
+ ContextMenuPortal,
+ ContextMenuContent,
+ ContextMenuItem,
+ ContextMenuShortcut,
+ ContextMenuSeparator,
+ ContextMenuSub,
+ ContextMenuSubTrigger,
+ ContextMenuSubContent,
+ ContextMenuCheckboxItem,
+ ContextMenuGroup,
+ ContextMenuGroupLabel,
+ ContextMenuRadioGroup,
+ ContextMenuRadioItem,
+}
diff --git a/packages/web-view-vite/src/components/solid-ui/resizable.tsx b/packages/web-view-vite/src/components/solid-ui/resizable.tsx
new file mode 100644
index 0000000..b34884f
--- /dev/null
+++ b/packages/web-view-vite/src/components/solid-ui/resizable.tsx
@@ -0,0 +1,63 @@
+import type { ValidComponent } from 'solid-js'
+import { Show, splitProps } from 'solid-js'
+
+import type { DynamicProps, HandleProps, RootProps } from '@corvu/resizable'
+import ResizablePrimitive from '@corvu/resizable'
+
+import { cn } from './utils'
+
+type ResizableProps = RootProps & { class?: string }
+
+function Resizable(props: DynamicProps>) {
+ const [, rest] = splitProps(props as ResizableProps, ['class'])
+ return (
+
+ )
+}
+
+const ResizablePanel = ResizablePrimitive.Panel
+
+type ResizableHandleProps = HandleProps & {
+ class?: string
+ withHandle?: boolean
+}
+
+function ResizableHandle(props: DynamicProps>) {
+ const [, rest] = splitProps(props as ResizableHandleProps, ['class', 'withHandle'])
+ return (
+ div]:rotate-90 z-70',
+ props.class,
+ )}
+ {...rest}
+ >
+
+
+
+
+ )
+}
+
+export { Resizable, ResizablePanel, ResizableHandle }
diff --git a/packages/web-view-vite/src/index.css b/packages/web-view-vite/src/index.css
index f88ff51..5beb6c7 100644
--- a/packages/web-view-vite/src/index.css
+++ b/packages/web-view-vite/src/index.css
@@ -44,7 +44,7 @@
--success-foreground: 160 84% 39%;
--warning: 48 96% 89%;
- --warning-foreground: 25 95% 53%;
+ --warning-foreground: var(--vscode-editorWarning-foreground);
--error: 0 93% 94%;
--error-foreground: var(--vscode-list-errorForeground);
diff --git a/packages/web-view-vite/src/index.tsx b/packages/web-view-vite/src/index.tsx
index 0305992..20d30d9 100644
--- a/packages/web-view-vite/src/index.tsx
+++ b/packages/web-view-vite/src/index.tsx
@@ -1,8 +1,24 @@
/* @refresh reload */
+
+import * as webviewToolkit from '@vscode/webview-ui-toolkit'
import { render } from 'solid-js/web'
+import { App } from './App'
import './index.css'
-import { App } from './App'
+
+// In order to use the Webview UI Toolkit web components they
+// must be registered with the browser (i.e. webview) using the
+// syntax below.
+{
+ const prefix = 'ui-test-visualizer'
+ webviewToolkit
+ .provideVSCodeDesignSystem()
+ .register(webviewToolkit.vsCodeButton({ prefix }))
+ .register(webviewToolkit.vsCodeCheckbox({ prefix }))
+ .register(webviewToolkit.vsCodeProgressRing({ prefix }))
+ .register(webviewToolkit.vsCodeTextField({ prefix }))
+ .register(webviewToolkit.vsCodeRadio({ prefix }))
+}
const root = document.getElementById('root')
diff --git a/packages/web-view-vite/src/inspector/Inspector.tsx b/packages/web-view-vite/src/inspector/Inspector.tsx
index 2201242..92a5ceb 100644
--- a/packages/web-view-vite/src/inspector/Inspector.tsx
+++ b/packages/web-view-vite/src/inspector/Inspector.tsx
@@ -2,7 +2,8 @@ import { makeEventListener } from '@solid-primitives/event-listener'
import { ReactiveWeakMap } from '@solid-primitives/map'
import { createMutationObserver } from '@solid-primitives/mutation-observer'
import { Show, createEffect, createSignal, onCleanup, onMount } from 'solid-js'
-import { shadowHost } from '../App'
+import { recorder, shadowHost } from '../App'
+import { HighlightedNode } from '../components/HighlightedNode'
import { type InspectedNode, getNewDomTree } from './inspector-dom-tree'
import { createInspectorSearch } from './inspector-search'
import { SearchToolbar } from './SearchToolbar'
@@ -101,42 +102,10 @@ export function Inspector() {
)}
-
- {(node) => {
- function newRect() {
- return node instanceof Text
- ? (() => {
- const range = document.createRange()
- range.selectNodeContents(node)
- return range.getBoundingClientRect()
- })()
- : node instanceof Element
- ? node.getBoundingClientRect()
- : node.parentElement?.getBoundingClientRect()
- }
-
- const [rect, setRect] = createSignal(newRect())
-
- // Update the rect on scroll, click, etc
- makeEventListener(window, 'resize', () => setRect(newRect()))
- makeEventListener(window, 'scroll', () => setRect(newRect()))
- makeEventListener(window, 'wheel', () => setRect(newRect()))
- makeEventListener(window, 'mousedown', () => setRect(newRect()))
- makeEventListener(window, 'mouseup', () => setRect(newRect()))
- makeEventListener(window, 'click', () => setRect(newRect()))
-
- return (
-
- )
- }}
+
+ {node => (
+
+ )}
)
diff --git a/packages/web-view-vite/src/inspector/Resizer.tsx b/packages/web-view-vite/src/inspector/Resizer.tsx
deleted file mode 100644
index 9f4a787..0000000
--- a/packages/web-view-vite/src/inspector/Resizer.tsx
+++ /dev/null
@@ -1,43 +0,0 @@
-import { createSignal } from 'solid-js'
-import { makeEventListener } from '@solid-primitives/event-listener'
-
-interface ResizerProps {
- onResize: (height: number) => void
-}
-
-export function Resizer(props: ResizerProps) {
- const [isDragging, setIsDragging] = createSignal(false)
-
- function handleMouseDown(e: MouseEvent) {
- setIsDragging(true)
- e.preventDefault()
- }
-
- // Use makeEventListener for mousemove
- makeEventListener(document, 'mousemove', (e) => {
- if (!isDragging()) { return }
- props.onResize(window.innerHeight - e.clientY)
- })
-
- // Use makeEventListener for mouseup
- makeEventListener(document, 'mouseup', () => {
- setIsDragging(false)
- })
-
- makeEventListener(document, 'mouseleave', () => {
- setIsDragging(false)
- })
-
- return (
- // invisible line to divide the 2 sections
-
- {/* invisible drag handle with bigger hitbox than the visible line */}
-
- {/* visible drag handle line */}
-
-
- )
-}
diff --git a/packages/web-view-vite/src/inspector/SearchToolbar.tsx b/packages/web-view-vite/src/inspector/SearchToolbar.tsx
index ae4c0f4..0674105 100644
--- a/packages/web-view-vite/src/inspector/SearchToolbar.tsx
+++ b/packages/web-view-vite/src/inspector/SearchToolbar.tsx
@@ -2,7 +2,7 @@ import ChevronDown from 'lucide-solid/icons/chevron-down'
import ChevronUp from 'lucide-solid/icons/chevron-up'
import Search from 'lucide-solid/icons/search'
import X from 'lucide-solid/icons/x'
-import { inspector } from '../App'
+import { updateOpenPanel } from '../App'
import { search } from './Inspector'
import type { InspectedNode } from './inspector-dom-tree'
@@ -70,7 +70,7 @@ export function SearchToolbar(props: { tree: InspectedNode }) {
appearance="icon"
aria-label="Close inspector"
title="Close inspector"
- onClick={() => inspector.toggle()}
+ onClick={() => updateOpenPanel(null)}
>
diff --git a/packages/web-view-vite/src/inspector/inspector-height.ts b/packages/web-view-vite/src/inspector/inspector-height.ts
deleted file mode 100644
index febef5d..0000000
--- a/packages/web-view-vite/src/inspector/inspector-height.ts
+++ /dev/null
@@ -1,39 +0,0 @@
-import { createSignal } from 'solid-js'
-import debounce from 'lodash/debounce'
-
-const STORAGE_KEY_INSPECTOR_HEIGHT = 'ui-test-visualizer.inspector-height'
-const STORAGE_KEY_INSPECTOR_IS_OPEN = 'ui-test-visualizer.inspector-is-open'
-const DEFAULT_HEIGHT = 300
-
-export function createInspectorHeight() {
- const initialIsOpen = Boolean(localStorage.getItem(STORAGE_KEY_INSPECTOR_IS_OPEN))
- const [isOpen, setIsOpen] = createSignal(initialIsOpen)
-
- // Get initial height from storage or use default
- const initialHeight = Number(localStorage.getItem(STORAGE_KEY_INSPECTOR_HEIGHT)) || DEFAULT_HEIGHT
- const [height, setHeight] = createSignal(initialHeight)
-
- // Wrapper for setHeight that also persists to storage
- function updateHeight(newHeight: number) {
- // Clamp height between 0 and 80% of viewport height
- const clampedHeight = Math.max(50, Math.min(newHeight, window.innerHeight * 0.8))
- setHeight(clampedHeight)
- persistHeight(clampedHeight)
- }
-
- function toggle() {
- setIsOpen(!isOpen())
- localStorage.setItem(STORAGE_KEY_INSPECTOR_IS_OPEN, isOpen() ? 'true' : '')
- }
-
- return {
- isOpen,
- height,
- updateHeight,
- toggle,
- }
-}
-
-const persistHeight = debounce((height: number) => {
- localStorage.setItem(STORAGE_KEY_INSPECTOR_HEIGHT, height.toString())
-}, 200)
diff --git a/packages/web-view-vite/src/lib/create-dom-replica.tsx b/packages/web-view-vite/src/lib/create-dom-replica.tsx
index 2cb00dd..c29c9f8 100644
--- a/packages/web-view-vite/src/lib/create-dom-replica.tsx
+++ b/packages/web-view-vite/src/lib/create-dom-replica.tsx
@@ -25,11 +25,16 @@ export function createDomReplica() {
function flushHtmlPatches() {
for (const patch of patches) {
- applyDomPatch(
- shadow,
- patch,
- window,
- )
+ try {
+ applyDomPatch(
+ shadow,
+ patch,
+ window,
+ )
+ }
+ catch (error) {
+ console.error(error)
+ }
}
patches = []
}
diff --git a/packages/web-view-vite/src/lib/panel-client.ts b/packages/web-view-vite/src/lib/panel-client.ts
index 1959f70..f03dfdf 100644
--- a/packages/web-view-vite/src/lib/panel-client.ts
+++ b/packages/web-view-vite/src/lib/panel-client.ts
@@ -1,8 +1,7 @@
+import { makeEventListener } from '@solid-primitives/event-listener'
import type { TRPCLink } from '@trpc/client'
import { TRPCClientError, createTRPCProxyClient } from '@trpc/client'
import { observable } from '@trpc/server/observable'
-
-import { makeEventListener } from '@solid-primitives/event-listener'
import type { PanelRouter } from '../../../extension/src/panel-controller/panel-router'
import { vscode } from './vscode'
diff --git a/packages/web-view-vite/src/recorder/recorder-context-menu.tsx b/packages/web-view-vite/src/recorder/recorder-context-menu.tsx
new file mode 100644
index 0000000..ceacbf1
--- /dev/null
+++ b/packages/web-view-vite/src/recorder/recorder-context-menu.tsx
@@ -0,0 +1,312 @@
+import { createInteractOutside } from '@kobalte/core'
+import type { inferProcedureInput } from '@trpc/server'
+import type { JSX } from 'solid-js'
+import { For, Show, createSignal } from 'solid-js'
+import { Dynamic } from 'solid-js/web'
+import { makeEventListener } from '@solid-primitives/event-listener'
+import type { ExpectStatementType, PanelRouter } from '../../../extension/src/panel-controller/panel-router'
+import { recorder, shadowHost } from '../App'
+import { HighlightedNode } from '../components/HighlightedNode'
+import { ContextMenu, ContextMenuContent, ContextMenuGroup, ContextMenuGroupLabel, ContextMenuItem, ContextMenuPortal, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger } from '../components/solid-ui/context-menu'
+import { deepElementFromPoint } from '../inspector/util'
+import { FIREEVENT_MOUSE_EVENT_TYPES, USEREVENT_MOUSE_EVENT_TYPES } from './recorder'
+
+export function RecorderContextMenuProvider(
+ props: { children: JSX.Element, class?: string },
+) {
+ return (
+
+ {props.children}
+
+ )
+}
+
+function RecorderContextMenu(
+ props: { children: JSX.Element, class?: string },
+) {
+ const [targetElement, setTargetElement] = createSignal(null)
+ function updateTargetElement(e: MouseEvent | null) {
+ if (!e) {
+ setTargetElement(null)
+ return
+ }
+
+ const clickedEl = (shadowHost.shadowRoot && deepElementFromPoint(shadowHost.shadowRoot, e.clientX, e.clientY)) ?? e.target
+ if (!(clickedEl instanceof Element)) {
+ return
+ }
+ setTargetElement(clickedEl)
+ }
+
+ async function submitRecorderInputEvent(
+ eventType: string,
+ { useExpect, useFireEvent, processInput }: {
+ useExpect?: ExpectStatementType
+ useFireEvent?: boolean
+ processInput?: (input: RecorderInput) => RecorderInput
+ } = {},
+ ) {
+ const target = targetElement()
+ if (!target) {
+ return
+ }
+ close()
+ await recorder.submitRecorderInputEvent(target, eventType, { useExpect, useFireEvent, processInput })
+ }
+
+ const { setupMenuRef, isOpen, setOpenIfTrue, close } = enableSelectingDifferentNodeWhileMenuIsOpen(
+ updateTargetElement,
+ )
+
+ function submitExpectStatement(
+ statement: ExpectStatementDef,
+ processInput: RecorderInputChanger | boolean | void,
+ ) {
+ submitRecorderInputEvent(
+ 'click',
+ {
+ useExpect: statement.type,
+ processInput: typeof processInput === 'function' ? processInput : undefined,
+ },
+ )
+ close()
+ }
+
+ function submitInputEvent(eventType: string, useFireEvent?: boolean) {
+ submitRecorderInputEvent(eventType, { useFireEvent })
+ close()
+ }
+
+ // Allow right-clicking on disabled button and input elements
+ if (shadowHost.shadowRoot) {
+ makeEventListener(shadowHost.shadowRoot, 'contextmenu', (e) => {
+ if (e instanceof MouseEvent && e.target instanceof Element) {
+ const element = e.target.closest('button:disabled, input:disabled')
+ if (element) {
+ e.preventDefault()
+ updateTargetElement(e)
+ }
+ }
+ })
+ }
+
+ return (
+ <>
+
+ e.button === 2 && updateTargetElement(e)}
+ >
+ {props.children}
+
+
+
+ {/* 'Expect' statements */}
+
+ {targetElement => (
+
+ 'Expect' Statement
+
+ {statement => (
+
+ {processInput => (
+ submitExpectStatement(statement, processInput)}
+ >
+ {typeof statement.title === 'function' ? statement.title(targetElement()) : statement.title}
+ {statement.shortcutLabel && {statement.shortcutLabel} }
+
+ )}
+
+ )}
+
+
+ )}
+
+
+
+ {/* Mouse events */}
+
+ Mouse Event (userEvent)
+
+ {eventType => (
+ submitInputEvent(eventType)}
+ >
+ {eventType}
+
+ )}
+
+
+
+
+
+
+
+ Mouse Event (fireEvent)
+
+
+
+
+
+ {eventType => (
+ submitInputEvent(eventType, true)}
+ >
+ {eventType}
+
+ )}
+
+
+
+
+
+
+
+
+
+ {target => (
+
+ )}
+
+ >
+ )
+}
+
+type RecorderInput = inferProcedureInput
+
+type RecorderInputChanger = (input: RecorderInput) => RecorderInput
+
+interface ExpectStatementDef {
+ title: string | ((el: Element) => string)
+ type: ExpectStatementType
+ shortcutLabel?: JSX.Element
+ handler?: (e: Element) => (RecorderInputChanger | void) | boolean
+}
+
+/** Definitions of expect statements you can pick from in the context menu. */
+const EXPECT_STATEMENTS: ExpectStatementDef[] = [
+ {
+ title: 'expect(element)',
+ type: 'minimal',
+ shortcutLabel: 'Alt+Click',
+ },
+ {
+ title: '.toHaveTextContent(...)',
+ type: 'toHaveTextContent',
+ handler: (el) => {
+ return (input) => {
+ input.eventData.text = el.textContent
+ return input
+ }
+ },
+ },
+ {
+ title: `.toHaveValue(...)`,
+ type: 'toHaveValue',
+ handler: (el) => {
+ if (
+ (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement)
+ && !['checkbox', 'radio'].includes(el.type)
+ ) {
+ return (input) => {
+ input.eventData.text = el.value
+ return input
+ }
+ }
+ },
+ },
+ {
+ title: el => ((el instanceof HTMLInputElement || el instanceof HTMLButtonElement) && !el.disabled)
+ ? '.toBeEnabled()'
+ : '.not.toBeEnabled()',
+ type: 'toBeEnabled',
+ handler: (el) => {
+ if (el instanceof HTMLInputElement
+ || el instanceof HTMLTextAreaElement
+ || el instanceof HTMLSelectElement
+ || el instanceof HTMLButtonElement) {
+ return (input) => {
+ input.eventData.enabled = !el.disabled
+ return input
+ }
+ }
+ },
+ },
+ {
+ title: el => (el instanceof HTMLInputElement && el.checked)
+ ? '.toBeChecked()'
+ : '.not.toBeChecked()',
+ type: 'toBeChecked',
+ handler: (el) => {
+ if (el instanceof HTMLInputElement && el.type === 'checkbox') {
+ return (input) => {
+ input.eventData.checked = el.checked
+ return input
+ }
+ }
+ },
+ },
+]
+
+/**
+ * Messy workaround to allow right-clicking outside the menu
+ * to re-open it for a different target element
+ */
+function enableSelectingDifferentNodeWhileMenuIsOpen(
+ updateTargetElement: (pointerEvent: PointerEvent | null) => void,
+) {
+ function setupMenuRef(ref: HTMLElement) {
+ createInteractOutside({
+ onPointerDownOutside: (customEvent) => {
+ const target = customEvent.target
+
+ // Behave as usual when cliking on a context sub-menu
+ if (target instanceof HTMLElement && target.closest('[data-ui-test-visualizer-menu-subcontent]')) {
+ return
+ }
+
+ setOpen(false)
+ updateTargetElement(null)
+ const { originalEvent } = customEvent.detail
+ if (originalEvent.button === 2) {
+ queueMicrotask(() => {
+ updateTargetElement(originalEvent)
+ })
+ }
+ },
+ }, () => ref)
+ }
+
+ const [isOpen, setOpen] = createSignal(false)
+
+ function setOpenIfTrue(newVal: boolean) {
+ if (newVal) {
+ setOpen(newVal)
+ }
+ }
+
+ function close() {
+ // Send an escape key event to close the context menu
+ document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape' }))
+
+ setOpen(false)
+ updateTargetElement(null)
+ }
+
+ return {
+ setupMenuRef,
+ isOpen,
+ setOpenIfTrue,
+ close,
+ }
+}
diff --git a/packages/web-view-vite/src/recorder/recorder-panel.tsx b/packages/web-view-vite/src/recorder/recorder-panel.tsx
new file mode 100644
index 0000000..6e3eb36
--- /dev/null
+++ b/packages/web-view-vite/src/recorder/recorder-panel.tsx
@@ -0,0 +1,122 @@
+import { createHighlighterCore } from '@shikijs/core'
+import shikiTypescript from '@shikijs/langs/typescript'
+import shikiDarkPlus from '@shikijs/themes/dark-plus'
+import shikiLightPlus from '@shikijs/themes/light-plus'
+import X from 'lucide-solid/icons/x'
+import { createJavaScriptRegexEngine } from 'shiki'
+import { For, Show, Suspense, createEffect, createResource, on } from 'solid-js'
+import { recorder } from '../App'
+
+export function RecorderPanel() {
+ const [codeHighlighter] = createResource(async () => await createHighlighterCore({
+ themes: [shikiDarkPlus, shikiLightPlus],
+ langs: [shikiTypescript],
+ engine: createJavaScriptRegexEngine(),
+ }))
+
+ function highlightedCode(code: string) {
+ const shikiTheme = document.body.classList.contains('vscode-light') ? 'light-plus' : 'dark-plus'
+
+ const html = codeHighlighter.error
+ ? null
+ // codeHighlighter() triggers Suspense
+ : codeHighlighter()?.codeToHtml(
+ code,
+ { lang: 'typescript', theme: shikiTheme },
+ )
+
+ if (!html) {
+ return code
+ }
+
+ return (
+ {
+ div.innerHTML = html
+ // Remove shiki's default background colors from the generated elements.
+ for (const el of div.querySelectorAll('pre') ?? []) {
+ el.style.backgroundColor = 'transparent'
+ }
+ for (const el of div.querySelectorAll('code') ?? []) {
+ el.style.backgroundColor = 'transparent'
+ }
+ }}
+ />
+ )
+ }
+
+ return (
+
+
Generated Code
+
+
+ 'change' event code generates after unfocusing the input
+
+
+
+
+ None yet
+
+ )}
+ each={Object.entries(recorder.codeInsertions() ?? {})}
+ >{([lineNum, codeLines]) => (
+
+
+ {
+ await recorder.removeInsertion(Number(lineNum))
+ }}
+ >
+
+
+
Insert at line: {lineNum}
+
+
+
+ {([code, _requiredImports], idx) => (
+
+ {
+ await recorder.removeInsertion(Number(lineNum), idx())
+ }}
+ >
+
+
+ {code}
}>
+ <>{highlightedCode(code.trim())}>
+
+
+ )}
+
+
+
+ )}
+
+
+
+ )
+}
+
+/** When a new code line is added, scroll to it. */
+function setupCodePanel(el: HTMLDivElement) {
+ queueMicrotask(() => {
+ el.scrollTop = el.scrollHeight
+ })
+
+ createEffect(on(recorder.codeInsertions, (current, prev) => {
+ if (current && prev) {
+ for (const lineNum of Object.keys(current)) {
+ const currentLen = current[Number(lineNum)]?.length ?? 0
+ const prevLen = prev[Number(lineNum)]?.length ?? 0
+ if (currentLen > prevLen) {
+ queueMicrotask(() => {
+ el.scrollTop = el.scrollHeight
+ })
+ }
+ }
+ }
+ }))
+}
diff --git a/packages/web-view-vite/src/recorder/recorder.ts b/packages/web-view-vite/src/recorder/recorder.ts
new file mode 100644
index 0000000..c1e47a7
--- /dev/null
+++ b/packages/web-view-vite/src/recorder/recorder.ts
@@ -0,0 +1,356 @@
+import { makeEventListener } from '@solid-primitives/event-listener'
+import { ReactiveMap } from '@solid-primitives/map'
+import { createMutationObserver } from '@solid-primitives/mutation-observer'
+import type { EventType, QueryArgs, Suggestion } from '@testing-library/dom'
+import { getSuggestedQuery, queries } from '@testing-library/dom'
+import type { userEvent } from '@testing-library/user-event'
+import type { inferProcedureInput } from '@trpc/server'
+import { createEffect, createSignal } from 'solid-js'
+import type { z } from 'zod/mini'
+import type { ExpectStatementType, PanelRouter, TestingLibraryQueryArgs, zRecordedEventData } from '../../../extension/src/panel-controller/panel-router'
+import type { RecorderCodeInsertions } from '../../../extension/src/recorder/recorder-codegen-session'
+import { openPanel, updateOpenPanel } from '../App'
+import { deepElementFromPoint } from '../inspector/util'
+import { client } from '../lib/panel-client'
+
+export const USEREVENT_MOUSE_EVENT_TYPES: (keyof typeof userEvent)[] = [
+ 'click',
+ 'dblClick',
+ 'hover',
+ 'unhover',
+ 'clear',
+]
+
+export const FIREEVENT_MOUSE_EVENT_TYPES: EventType[] = [
+ 'click',
+ 'dblClick',
+ 'mouseDown',
+ 'mouseUp',
+ 'mouseEnter',
+ 'mouseLeave',
+ 'mouseMove',
+ 'mouseOver',
+ 'mouseOut',
+ 'contextMenu',
+]
+
+export function createRecorder(shadowHost: HTMLDivElement) {
+ function isRecording() {
+ return openPanel() === 'recorder'
+ }
+ const [codeInsertions, setCodeInsertions] = createSignal()
+
+ // When the edit is performed, clear the recorder UI's insertions state
+ makeEventListener(window, 'message', (event) => {
+ if (event.data.recorderEditPerformed) {
+ setCodeInsertions(undefined)
+ }
+ })
+
+ const { hasPendingInputChange } = trackPendingInputChanges(shadowHost, isRecording)
+
+ const [rootElement, setRootElement] = createSignal(
+ shadowHost.shadowRoot?.children[0] ?? null,
+ )
+ createMutationObserver(shadowHost.shadowRoot!, { childList: true }, () => {
+ setRootElement(shadowHost.shadowRoot?.children[0] ?? null)
+ })
+
+ /** Generate a line of test code for the given user input event. */
+ async function submitRecorderInputEvent(
+ target: Element,
+ eventType: string,
+ { useExpect, enterKeyPressed, useFireEvent, processInput }: {
+ useExpect?: ExpectStatementType
+ enterKeyPressed?: boolean
+ useFireEvent?: boolean
+ processInput?: (input: inferProcedureInput) => inferProcedureInput
+ } = {},
+ ) {
+ let suggestedQuery: Suggestion | undefined
+
+ /**
+ * Sometimes testing-library can't find a good query to use.
+ * This fn checks if testing-library generated a useful query.
+ */
+ function hasQuery() {
+ if (!suggestedQuery) {
+ return false
+ }
+ if (suggestedQuery.queryArgs[0] === 'document') {
+ return false
+ }
+ return true
+ }
+
+ // Generate the selector using the closest HTMLElement.
+ // e.g. if you click on an SVG, that doesn't count as an HTMLElement,
+ // so step up to the parent.
+ while (!hasQuery() && target) {
+ if (target instanceof HTMLElement) {
+ suggestedQuery = getSuggestedQuery(target)
+ }
+ if (!hasQuery()) {
+ if (target instanceof Element && target.parentElement) {
+ target = target.parentElement
+ }
+ else {
+ return
+ }
+ }
+ }
+
+ if (!hasQuery() || !suggestedQuery) {
+ return
+ }
+
+ const eventData: z.infer = {}
+ if (enterKeyPressed) {
+ eventData.enterKeyPressed = true
+ }
+
+ // On text input change
+ if (eventType === 'change') {
+ if (target instanceof HTMLTextAreaElement || target instanceof HTMLInputElement) {
+ if (target.type === 'text') {
+ const text = target.value
+ eventData.text = text
+ eventData.clearBeforeType = focusedInputHadText
+ }
+ }
+ }
+
+ const root = rootElement()
+ if (!root) {
+ return
+ }
+
+ // Check if the query returns multiple elements
+ await (async () => {
+ try {
+ const method = `findAllBy${suggestedQuery.queryName}`
+ // @ts-expect-error Method should exist
+ const results = await queries[method](
+ root,
+ ...suggestedQuery.queryArgs,
+ )
+ if (results.length > 1) {
+ eventData.indexIfMultipleFound = results.indexOf(target)
+ }
+ }
+ catch (error) {
+ // Do nothing?
+ }
+ })()
+
+ const recordedEventType = (() => {
+ if (eventType === 'change' && target instanceof HTMLSelectElement) {
+ eventData.options = [target.value]
+ return 'selectOptions'
+ }
+
+ return eventType
+ })()
+
+ const queryArgs: TestingLibraryQueryArgs = [
+ suggestedQuery.queryMethod,
+ serializeQueryArgs(suggestedQuery.queryArgs),
+ ]
+
+ let input: inferProcedureInput = {
+ event: recordedEventType,
+ query: queryArgs,
+ eventData,
+ useExpect,
+ useFireEvent,
+ }
+
+ input = processInput?.(input) ?? input
+
+ // Send the selector to the extension process to record as code
+ const insertions = await client.recordInputAsCode.mutate(input)
+ setCodeInsertions(insertions)
+ }
+
+ let focusedInputHadText = false
+
+ // When recording, listen to events in the shadow root and generate code for them.
+ createEffect(() => {
+ const root = rootElement()
+ if (!root) {
+ return
+ }
+ if (isRecording()) {
+ // Check if a focused input has text before you start typing into it
+ makeEventListener(root, 'focus', (e: Event) => {
+ const target = e.target
+ if (
+ (target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement)
+ && target.value
+ ) {
+ focusedInputHadText = true
+ }
+ }, { capture: true })
+
+ // Capture input events to be recorded as test code
+ for (const eventType of ['click', 'submit', 'change', 'keydown'] as const) {
+ makeEventListener(root, eventType, async (e: Event) => {
+ let target = e.target
+
+ // When clicking, use deepElementFromPoint to get the right element if it's inside a shadow root.
+ if (e instanceof MouseEvent) {
+ const clickedEl = (shadowHost.shadowRoot && deepElementFromPoint(shadowHost.shadowRoot, e.clientX, e.clientY)) ?? e.target
+ if (!(clickedEl instanceof Element)) {
+ return
+ }
+ target = clickedEl
+ }
+
+ if (!(target instanceof Element)) {
+ return
+ }
+
+ if (
+ (target instanceof HTMLTextAreaElement || target instanceof HTMLInputElement)
+ && (target.type === 'checkbox' || target.type === 'radio')
+ && eventType === 'change'
+ ) {
+ e.preventDefault()
+ return // generate code for the 'click' event, not 'change'
+ }
+
+ let enterKeyPressed = false
+ if (eventType === 'keydown') {
+ if (e instanceof KeyboardEvent && target instanceof HTMLInputElement && e.key === 'Enter') {
+ enterKeyPressed = true
+ target.blur()
+ await new Promise(resolve => setTimeout(resolve, 0))
+ target.focus()
+ }
+ else {
+ // Ignore other key presses
+ return
+ }
+ }
+
+ // On alt-click, generate the 'minimal' expect statement
+ // e.g. `expect(screen.getByRole('button'))`
+ const useExpect = (eventType === 'click' && e instanceof MouseEvent && e.altKey)
+ ? 'minimal'
+ : undefined
+ // When the 'alt' key is held while clicking, generate an 'expect' statement
+ if (useExpect) {
+ e.preventDefault()
+ }
+
+ await submitRecorderInputEvent(target, eventType, { useExpect, enterKeyPressed })
+ })
+ }
+ }
+ else {
+ makeEventListener(root, 'beforeinput', (e) => {
+ // Block changing inputs when not recording
+ e.preventDefault()
+ })
+ makeEventListener(root, 'click', (e) => {
+ if (e.target instanceof HTMLInputElement) {
+ // Block changing inputs like checkboxes and radios when not recording
+ e.preventDefault()
+ }
+ })
+ }
+ })
+
+ return {
+ isRecording,
+ toggle: (recording: boolean) => {
+ updateOpenPanel(recording ? 'recorder' : null)
+ },
+ removeInsertion: async (line: number, idx?: number) => {
+ const newInsertions = await client.removeRecorderInsertion.mutate({ line, idx })
+ setCodeInsertions(newInsertions)
+ },
+ codeInsertions,
+ hasPendingInputChange,
+ submitRecorderInputEvent,
+ }
+}
+
+/**
+ * Convert the queryArgs from testing-library to JSON to be sent to the extension process.
+ * Mainly to convert the RegExp to a string before sending it.
+ */
+export function serializeQueryArgs(queryArgs: QueryArgs): [string | SerializedRegexp, { [key: string]: string | boolean | SerializedRegexp }?] {
+ const [query, options] = queryArgs
+ if (!options) {
+ // @ts-expect-error Not declared the testing library, but the query could be a RegExp:
+ const result = query instanceof RegExp ? processRegexp(query) : query
+ return [result]
+ }
+ const serializedOptions = Object.entries(options).reduce((prev, curr) => {
+ const val = curr[1]
+ if (val !== undefined) {
+ prev[curr[0]] = val instanceof RegExp ? processRegexp(val) : val
+ }
+ return prev
+ }, {} as Record)
+
+ return [query, serializedOptions]
+}
+
+export interface SerializedRegexp { type: 'regexp', value: string }
+
+function processRegexp(regexp: RegExp): SerializedRegexp {
+ // Make the regexp exact, to avoid multiple matches.
+ // e.g. when you have buttons aria-labeled "right" and "top right", then the regex /right/ would match both.
+ regexp = makeRegexpExact(regexp)
+
+ return { type: 'regexp', value: regexp.toString() }
+}
+
+function makeRegexpExact(regexp: RegExp) {
+ const { source, flags } = regexp
+
+ // Wrap with ^ and $
+ return new RegExp(`^${source}$`, flags)
+}
+
+function trackPendingInputChanges(shadowHost: HTMLDivElement, isRecording: () => boolean) {
+ const isPendingInputChange = new ReactiveMap()
+ function hasPendingInputChange() {
+ return isPendingInputChange.size > 0
+ }
+
+ makeEventListener(shadowHost.shadowRoot!, 'input', (e) => {
+ if (!(e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement)) {
+ return
+ }
+ isPendingInputChange.set(e.target, true)
+ })
+ makeEventListener(shadowHost.shadowRoot!, 'change', (e) => {
+ if (!(e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement)) {
+ return
+ }
+ isPendingInputChange.delete(e.target)
+ })
+
+ const shadowHtml = shadowHost.shadowRoot?.children[0]
+ if (shadowHtml) {
+ createMutationObserver(shadowHtml, { subtree: true, childList: true }, (mutations) => {
+ for (const mutation of mutations) {
+ for (const removedNode of mutation.removedNodes) {
+ isPendingInputChange.delete(removedNode)
+ }
+ }
+ })
+ }
+ createEffect(() => {
+ if (!isRecording()) {
+ isPendingInputChange.clear()
+ }
+ })
+
+ return {
+ hasPendingInputChange,
+ }
+}
diff --git a/packages/web-view-vite/ui.preset.js b/packages/web-view-vite/ui.preset.js
index 133efcb..ebd696c 100644
--- a/packages/web-view-vite/ui.preset.js
+++ b/packages/web-view-vite/ui.preset.js
@@ -41,7 +41,7 @@ module.exports = {
},
warning: {
DEFAULT: 'hsl(var(--warning))',
- foreground: 'hsl(var(--warning-foreground))',
+ foreground: 'var(--warning-foreground)',
},
error: {
DEFAULT: 'hsl(var(--error))',
diff --git a/playwright.config.ts b/playwright.config.ts
index 35ff30e..46a9d46 100644
--- a/playwright.config.ts
+++ b/playwright.config.ts
@@ -16,6 +16,6 @@ export default defineConfig({
headless: !!process.env.CI || !!process.env.PLAYWRIGHT_HEADLESS,
viewport: { width: 1600, height: 800 },
},
- timeout: 60_000,
+ timeout: 90_000,
retries: process.env.CI ? 1 : 0,
})
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index e4342f2..ff9a349 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -15,19 +15,19 @@ importers:
devDependencies:
'@antfu/eslint-config':
specifier: ^2.19.1
- version: 2.19.1(@vue/compiler-sfc@3.4.34)(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)(vitest@3.2.4(@types/node@24.6.0)(happy-dom@20.0.0)(jiti@2.6.0)(jsdom@26.1.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2))
+ version: 2.19.1(@vue/compiler-sfc@3.4.34)(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)(vitest@3.2.4(@types/node@24.8.1)(happy-dom@20.0.8)(jiti@2.6.1)(jsdom@26.1.0)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2))
'@changesets/cli':
specifier: ^2.29.7
- version: 2.29.7(@types/node@24.6.0)
+ version: 2.29.7(@types/node@24.8.1)
'@playwright/test':
- specifier: ^1.55.1
- version: 1.55.1
+ specifier: ^1.56.1
+ version: 1.56.1
'@total-typescript/ts-reset':
specifier: ^0.6.1
version: 0.6.1
'@types/node':
- specifier: ^24.6.0
- version: 24.6.0
+ specifier: ^24.8.1
+ version: 24.8.1
'@vitest/expect':
specifier: ^3.2.4
version: 3.2.4
@@ -35,29 +35,32 @@ importers:
specifier: ^3.6.2
version: 3.6.2
eslint:
- specifier: ^9.36.0
- version: 9.36.0(jiti@2.6.0)
+ specifier: ^9.38.0
+ version: 9.38.0(jiti@2.6.1)
ovsx:
specifier: ^0.10.6
version: 0.10.6
+ pathe:
+ specifier: ^2.0.3
+ version: 2.0.3
tsup:
specifier: ^8.5.0
- version: 8.5.0(jiti@2.6.0)(postcss@8.5.6)(typescript@5.9.2)(yaml@2.4.2)
+ version: 8.5.0(jiti@2.6.1)(postcss@8.5.6)(typescript@5.9.3)(yaml@2.4.2)
type-fest:
specifier: ^5.0.1
version: 5.0.1
typescript:
- specifier: ^5.9.2
- version: 5.9.2
+ specifier: ^5.9.3
+ version: 5.9.3
vitest:
specifier: ^3.2.4
- version: 3.2.4(@types/node@24.6.0)(happy-dom@20.0.0)(jiti@2.6.0)(jsdom@26.1.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2)
+ version: 3.2.4(@types/node@24.8.1)(happy-dom@20.0.8)(jiti@2.6.1)(jsdom@26.1.0)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2)
examples/jest-babel-nextjs:
dependencies:
next:
- specifier: ^15.5.4
- version: 15.5.4(@babel/core@7.28.4)(@playwright/test@1.55.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(sass@1.93.2)
+ specifier: ^15.5.6
+ version: 15.5.6(@babel/core@7.28.4)(@playwright/test@1.56.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(sass@1.93.2)
react:
specifier: ^19.2.0
version: 19.2.0
@@ -69,14 +72,14 @@ importers:
specifier: ^7.28.4
version: 7.28.4
'@testing-library/jest-dom':
- specifier: ^6.9.0
- version: 6.9.0
+ specifier: ^6.9.1
+ version: 6.9.1
'@testing-library/react':
specifier: ^16.3.0
- version: 16.3.0(@testing-library/dom@10.4.0)(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)
+ version: 16.3.0(@testing-library/dom@10.4.1)(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)
'@testing-library/user-event':
specifier: ^14.6.1
- version: 14.6.1(@testing-library/dom@10.4.0)
+ version: 14.6.1(@testing-library/dom@10.4.1)
'@types/jest':
specifier: ^30.0.0
version: 30.0.0
@@ -91,13 +94,13 @@ importers:
version: 3.0.0
jest:
specifier: ^30.2.0
- version: 30.2.0(@types/node@24.6.0)(ts-node@10.9.2(@types/node@24.6.0)(typescript@5.9.2))
+ version: 30.2.0(@types/node@24.8.1)(ts-node@10.9.2(@types/node@24.8.1)(typescript@5.9.3))
jest-environment-jsdom:
specifier: ^30.2.0
version: 30.2.0
typescript:
- specifier: ^5.9.2
- version: 5.9.2
+ specifier: ^5.9.3
+ version: 5.9.3
examples/jest-monorepo:
dependencies:
@@ -107,7 +110,7 @@ importers:
devDependencies:
'@testing-library/react':
specifier: ^16.3.0
- version: 16.3.0(@testing-library/dom@10.4.0)(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)
+ version: 16.3.0(@testing-library/dom@10.4.1)(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)
'@types/jest':
specifier: ^30.0.0
version: 30.0.0
@@ -116,7 +119,7 @@ importers:
version: 19.2.2
jest:
specifier: ^30.2.0
- version: 30.2.0(@types/node@24.6.0)(ts-node@10.9.2(@types/node@24.6.0)(typescript@5.9.2))
+ version: 30.2.0(@types/node@24.8.1)(ts-node@10.9.2(@types/node@24.8.1)(typescript@5.9.3))
jest-environment-jsdom:
specifier: ^30.2.0
version: 30.2.0
@@ -124,8 +127,8 @@ importers:
examples/jest-nextjs-minimal:
dependencies:
next:
- specifier: ^15.5.4
- version: 15.5.4(@babel/core@7.28.4)(@playwright/test@1.55.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(sass@1.93.2)
+ specifier: ^15.5.6
+ version: 15.5.6(@babel/core@7.28.4)(@playwright/test@1.56.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(sass@1.93.2)
react:
specifier: ^19.2.0
version: 19.2.0
@@ -137,11 +140,14 @@ importers:
version: 0.0.1
devDependencies:
'@testing-library/jest-dom':
- specifier: ^6.9.0
- version: 6.9.0
+ specifier: ^6.9.1
+ version: 6.9.1
'@testing-library/react':
specifier: ^16.3.0
- version: 16.3.0(@testing-library/dom@10.4.0)(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)
+ version: 16.3.0(@testing-library/dom@10.4.1)(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)
+ '@testing-library/user-event':
+ specifier: ^14.6.1
+ version: 14.6.1(@testing-library/dom@10.4.1)
'@types/jest':
specifier: ^30.0.0
version: 30.0.0
@@ -150,19 +156,22 @@ importers:
version: 19.2.2
jest:
specifier: ^30.2.0
- version: 30.2.0(@types/node@24.6.0)(ts-node@10.9.2(@types/node@24.6.0)(typescript@5.9.2))
+ version: 30.2.0(@types/node@24.8.1)(ts-node@10.9.2(@types/node@24.8.1)(typescript@5.9.3))
jest-environment-jsdom:
specifier: ^30.2.0
version: 30.2.0
+ tailwindcss:
+ specifier: ^4.1.16
+ version: 4.1.16
typescript:
- specifier: ^5.9.2
- version: 5.9.2
+ specifier: ^5.9.3
+ version: 5.9.3
examples/jest-nextjs-ts-node:
dependencies:
next:
- specifier: ^15.5.4
- version: 15.5.4(@babel/core@7.28.4)(@playwright/test@1.55.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(sass@1.93.2)
+ specifier: ^15.5.6
+ version: 15.5.6(@babel/core@7.28.4)(@playwright/test@1.56.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(sass@1.93.2)
react:
specifier: ^19.2.0
version: 19.2.0
@@ -174,11 +183,11 @@ importers:
version: 0.0.1
devDependencies:
'@testing-library/jest-dom':
- specifier: ^6.9.0
- version: 6.9.0
+ specifier: ^6.9.1
+ version: 6.9.1
'@testing-library/react':
specifier: ^16.3.0
- version: 16.3.0(@testing-library/dom@10.4.0)(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)
+ version: 16.3.0(@testing-library/dom@10.4.1)(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)
'@types/jest':
specifier: ^30.0.0
version: 30.0.0
@@ -187,16 +196,16 @@ importers:
version: 19.2.2
jest:
specifier: ^30.2.0
- version: 30.2.0(@types/node@24.6.0)(ts-node@10.9.2(@types/node@24.6.0)(typescript@5.9.2))
+ version: 30.2.0(@types/node@24.8.1)(ts-node@10.9.2(@types/node@24.8.1)(typescript@5.9.3))
jest-environment-jsdom:
specifier: ^30.2.0
version: 30.2.0
ts-node:
specifier: ^10.9.2
- version: 10.9.2(@types/node@24.6.0)(typescript@5.9.2)
+ version: 10.9.2(@types/node@24.8.1)(typescript@5.9.3)
typescript:
- specifier: ^5.9.2
- version: 5.9.2
+ specifier: ^5.9.3
+ version: 5.9.3
examples/jest-react:
dependencies:
@@ -215,7 +224,10 @@ importers:
version: 7.27.1(@babel/core@7.28.4)
'@testing-library/react':
specifier: ^16.3.0
- version: 16.3.0(@testing-library/dom@10.4.0)(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)
+ version: 16.3.0(@testing-library/dom@10.4.1)(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)
+ '@testing-library/user-event':
+ specifier: ^14.6.1
+ version: 14.6.1(@testing-library/dom@10.4.1)
'@types/jest':
specifier: ^30.0.0
version: 30.0.0
@@ -224,7 +236,7 @@ importers:
version: 19.2.2
jest:
specifier: ^30.2.0
- version: 30.2.0(@types/node@24.6.0)(ts-node@10.9.2(@types/node@24.6.0)(typescript@5.9.2))
+ version: 30.2.0(@types/node@24.8.1)(ts-node@10.9.2(@types/node@24.8.1)(typescript@5.9.3))
jest-canvas-mock:
specifier: ^2.5.2
version: 2.5.2
@@ -249,7 +261,7 @@ importers:
version: 7.27.1(@babel/core@7.28.4)
'@testing-library/react':
specifier: ^16.3.0
- version: 16.3.0(@testing-library/dom@10.4.0)(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)
+ version: 16.3.0(@testing-library/dom@10.4.1)(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)
'@types/jest':
specifier: ^30.0.0
version: 30.0.0
@@ -258,7 +270,7 @@ importers:
version: 19.2.2
jest:
specifier: ^30.2.0
- version: 30.2.0(@types/node@24.6.0)(ts-node@10.9.2(@types/node@24.6.0)(typescript@5.9.2))
+ version: 30.2.0(@types/node@24.8.1)(ts-node@10.9.2(@types/node@24.8.1)(typescript@5.9.3))
jest-canvas-mock:
specifier: ^2.5.2
version: 2.5.2
@@ -274,13 +286,13 @@ importers:
devDependencies:
'@testing-library/react':
specifier: ^16.3.0
- version: 16.3.0(@testing-library/dom@10.4.0)(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)
+ version: 16.3.0(@testing-library/dom@10.4.1)(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)
'@types/react':
specifier: ^19.2.2
version: 19.2.2
'@vitejs/plugin-react':
specifier: ^5.0.4
- version: 5.0.4(vite@5.4.19(@types/node@24.6.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0))
+ version: 5.0.4(vite@5.4.19(@types/node@24.8.1)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0))
autoprefixer:
specifier: ^10.4.21
version: 10.4.21(postcss@8.5.6)
@@ -288,8 +300,8 @@ importers:
specifier: ^14.11.4
version: 14.12.3
less:
- specifier: ^4.4.1
- version: 4.4.1
+ specifier: ^4.4.2
+ version: 4.4.2
postcss:
specifier: ^8.5.6
version: 8.5.6
@@ -301,13 +313,13 @@ importers:
version: 0.64.0
tailwindcss:
specifier: 3.4.17
- version: 3.4.17(ts-node@10.9.2(@types/node@24.6.0)(typescript@5.9.2))
+ version: 3.4.17(ts-node@10.9.2(@types/node@24.8.1)(typescript@5.9.3))
vite:
specifier: ^5.4.19
- version: 5.4.19(@types/node@24.6.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)
+ version: 5.4.19(@types/node@24.8.1)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)
vitest:
specifier: 2.1.8
- version: 2.1.8(@types/node@24.6.0)(happy-dom@14.12.3)(jsdom@26.1.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)
+ version: 2.1.8(@types/node@24.8.1)(happy-dom@14.12.3)(jsdom@26.1.0)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)
examples/vitest-react-tailwind4:
dependencies:
@@ -316,17 +328,20 @@ importers:
version: 19.2.0
devDependencies:
'@tailwindcss/vite':
- specifier: ^4.1.13
- version: 4.1.13(vite@7.1.7(@types/node@24.6.0)(jiti@2.6.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2))
+ specifier: ^4.1.14
+ version: 4.1.14(vite@7.1.10(@types/node@24.8.1)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2))
'@testing-library/react':
specifier: ^16.3.0
- version: 16.3.0(@testing-library/dom@10.4.0)(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)
+ version: 16.3.0(@testing-library/dom@10.4.1)(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)
+ '@testing-library/user-event':
+ specifier: ^14.6.1
+ version: 14.6.1(@testing-library/dom@10.4.1)
'@types/react':
specifier: ^19.2.2
version: 19.2.2
'@vitejs/plugin-react':
specifier: ^5.0.4
- version: 5.0.4(vite@7.1.7(@types/node@24.6.0)(jiti@2.6.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2))
+ version: 5.0.4(vite@7.1.10(@types/node@24.8.1)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2))
happy-dom:
specifier: ^14.11.4
version: 14.12.3
@@ -334,32 +349,32 @@ importers:
specifier: ^1.93.2
version: 1.93.2
tailwindcss:
- specifier: ^4.1.13
- version: 4.1.13
+ specifier: ^4.1.14
+ version: 4.1.14
vite:
- specifier: ^7.1.7
- version: 7.1.7(@types/node@24.6.0)(jiti@2.6.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2)
+ specifier: ^7.1.10
+ version: 7.1.10(@types/node@24.8.1)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2)
vitest:
- specifier: ^4.0.0-beta.8
- version: 4.0.0-beta.8(@types/node@24.6.0)(happy-dom@14.12.3)(jiti@2.6.0)(jsdom@26.1.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2)
+ specifier: ^4.0.0-beta.18
+ version: 4.0.0-beta.18(@types/node@24.8.1)(happy-dom@14.12.3)(jiti@2.6.1)(jsdom@26.1.0)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2)
packages/extension:
dependencies:
'@napi-rs/wasm-runtime':
- specifier: ^1.0.5
- version: 1.0.5
+ specifier: ^1.0.7
+ version: 1.0.7
'@oxc-parser/binding-wasm32-wasi':
- specifier: ^0.93.0
- version: 0.93.0
+ specifier: ^0.95.0
+ version: 0.95.0
'@tailwindcss/oxide-wasm32-wasi':
- specifier: ^4.1.13
- version: 4.1.13
+ specifier: ^4.1.14
+ version: 4.1.14
'@trpc/server':
specifier: ^11.6.0
- version: 11.6.0(typescript@5.9.2)
+ version: 11.6.0(typescript@5.9.3)
'@vscode/extension-telemetry':
- specifier: ^1.0.0
- version: 1.0.0(tslib@2.8.1)
+ specifier: ^1.1.0
+ version: 1.1.0(tslib@2.8.1)
enhanced-resolve:
specifier: ^5.18.3
version: 5.18.3
@@ -374,7 +389,7 @@ importers:
version: 7.1.0
jest-config:
specifier: 30.2.0
- version: 30.2.0(patch_hash=7183ebeb461331a42f7b4be95c553b6304fa99af85998b66f7f8c91aa96e8d46)(@types/node@24.6.0)(ts-node@10.9.2(@types/node@24.6.0)(typescript@5.9.2))
+ version: 30.2.0(patch_hash=7183ebeb461331a42f7b4be95c553b6304fa99af85998b66f7f8c91aa96e8d46)(@types/node@24.8.1)(ts-node@10.9.2(@types/node@24.8.1)(typescript@5.9.3))
lodash:
specifier: ^4.17.21
version: 4.17.21
@@ -386,14 +401,17 @@ importers:
version: 8.5.6
postcss-load-config:
specifier: ^6.0.1
- version: 6.0.1(jiti@2.6.0)(postcss@8.5.6)(yaml@2.4.2)
+ version: 6.0.1(jiti@2.6.1)(postcss@8.5.6)(yaml@2.4.2)
replicate-dom:
specifier: workspace:*
version: link:../replicate-dom
zod:
- specifier: ^4.1.11
- version: 4.1.11
+ specifier: ^4.1.12
+ version: 4.1.12
devDependencies:
+ '@testing-library/user-event':
+ specifier: ^13.5.0
+ version: 13.5.0(@testing-library/dom@10.4.1)
'@types/less':
specifier: ^3.0.8
version: 3.0.8
@@ -401,14 +419,14 @@ importers:
specifier: ^4.17.20
version: 4.17.20
'@types/node':
- specifier: ^24.6.0
- version: 24.6.0
+ specifier: ^24.8.1
+ version: 24.8.1
'@types/stylus':
specifier: ^0.48.43
version: 0.48.43
'@types/vscode':
- specifier: ^1.104.0
- version: 1.104.0
+ specifier: ^1.105.0
+ version: 1.105.0
'@types/ws':
specifier: ^8.18.1
version: 8.18.1
@@ -416,17 +434,20 @@ importers:
specifier: ^3.2.4
version: 3.2.4
'@vscode/codicons':
- specifier: ^0.0.40
- version: 0.0.40
+ specifier: ^0.0.41
+ version: 0.0.41
esbuild:
- specifier: ^0.25.10
- version: 0.25.10
+ specifier: ^0.25.11
+ version: 0.25.11
execa:
specifier: ^9.6.0
version: 9.6.0
less:
- specifier: ^4.4.1
- version: 4.4.1
+ specifier: ^4.4.2
+ version: 4.4.2
+ oxc-parser:
+ specifier: ^0.95.0
+ version: 0.95.0
sass:
specifier: ^1.93.2
version: 1.93.2
@@ -435,7 +456,7 @@ importers:
version: 0.64.0
vitest:
specifier: ^3.2.4
- version: 3.2.4(@types/node@24.6.0)(happy-dom@20.0.0)(jiti@2.6.0)(jsdom@26.1.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2)
+ version: 3.2.4(@types/node@24.8.1)(happy-dom@20.0.8)(jiti@2.6.1)(jsdom@26.1.0)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2)
ws:
specifier: ^8.18.3
version: 8.18.3
@@ -463,7 +484,7 @@ importers:
version: 26.1.0
vitest:
specifier: ^3.2.4
- version: 3.2.4(@types/node@24.6.0)(happy-dom@14.6.2)(jiti@2.6.0)(jsdom@26.1.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2)
+ version: 3.2.4(@types/node@24.8.1)(happy-dom@14.6.2)(jiti@2.6.1)(jsdom@26.1.0)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2)
packages/test-setup:
dependencies:
@@ -489,12 +510,27 @@ importers:
packages/web-view-vite:
dependencies:
+ '@corvu/resizable':
+ specifier: ^0.2.5
+ version: 0.2.5(solid-js@1.9.9)
+ '@happy-dom/global-registrator':
+ specifier: ^20.0.8
+ version: 20.0.8
'@kobalte/core':
specifier: 0.13.11
version: 0.13.11(solid-js@1.9.9)
'@kobalte/utils':
specifier: ^0.9.1
version: 0.9.1(solid-js@1.9.9)
+ '@shikijs/core':
+ specifier: ^3.13.0
+ version: 3.13.0
+ '@shikijs/langs':
+ specifier: ^3.13.0
+ version: 3.13.0
+ '@shikijs/themes':
+ specifier: ^3.13.0
+ version: 3.13.0
'@solid-primitives/event-listener':
specifier: ^2.4.3
version: 2.4.3(solid-js@1.9.9)
@@ -504,12 +540,18 @@ importers:
'@solid-primitives/mutation-observer':
specifier: ^1.2.2
version: 1.2.2(solid-js@1.9.9)
+ '@testing-library/dom':
+ specifier: ^10.4.1
+ version: 10.4.1
+ '@testing-library/user-event':
+ specifier: ^14.6.1
+ version: 14.6.1(@testing-library/dom@10.4.1)
'@trpc/client':
specifier: ^11.6.0
- version: 11.6.0(@trpc/server@11.6.0(typescript@5.9.2))(typescript@5.9.2)
+ version: 11.6.0(@trpc/server@11.6.0(typescript@5.9.3))(typescript@5.9.3)
'@trpc/server':
specifier: ^11.6.0
- version: 11.6.0(typescript@5.9.2)
+ version: 11.6.0(typescript@5.9.3)
'@vscode/webview-ui-toolkit':
specifier: ^1.4.0
version: 1.4.0(react@19.2.0)
@@ -522,6 +564,9 @@ importers:
csstype:
specifier: ^3.1.3
version: 3.1.3
+ happy-dom:
+ specifier: ^20.0.8
+ version: 20.0.8
kagekiri:
specifier: ^2.0.0
version: 2.0.0
@@ -529,11 +574,14 @@ importers:
specifier: ^4.17.21
version: 4.17.21
lucide-solid:
- specifier: ^0.544.0
- version: 0.544.0(solid-js@1.9.9)
+ specifier: ^0.546.0
+ version: 0.546.0(solid-js@1.9.9)
replicate-dom:
specifier: workspace:*
version: link:../replicate-dom
+ shiki:
+ specifier: ^3.13.0
+ version: 3.13.0
solid-js:
specifier: ^1.9.9
version: 1.9.9
@@ -542,14 +590,17 @@ importers:
version: 3.3.1
tailwindcss-animate:
specifier: ^1.0.7
- version: 1.0.7(tailwindcss@4.1.13)
+ version: 1.0.7(tailwindcss@4.1.14)
ws:
specifier: ^8.18.3
version: 8.18.3
+ zod:
+ specifier: ^4.1.12
+ version: 4.1.12
devDependencies:
'@tailwindcss/vite':
- specifier: ^4.1.13
- version: 4.1.13(vite@7.1.7(@types/node@24.6.0)(jiti@2.6.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2))
+ specifier: ^4.1.14
+ version: 4.1.14(vite@7.1.10(@types/node@24.8.1)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2))
'@types/lodash':
specifier: ^4.17.20
version: 4.17.20
@@ -560,14 +611,14 @@ importers:
specifier: ^8.18.1
version: 8.18.1
tailwindcss:
- specifier: ^4.1.13
- version: 4.1.13
+ specifier: ^4.1.14
+ version: 4.1.14
vite:
- specifier: ^7.1.7
- version: 7.1.7(@types/node@24.6.0)(jiti@2.6.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2)
+ specifier: ^7.1.10
+ version: 7.1.10(@types/node@24.8.1)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2)
vite-plugin-solid:
- specifier: ^2.11.8
- version: 2.11.8(@testing-library/jest-dom@6.9.0)(solid-js@1.9.9)(vite@7.1.7(@types/node@24.6.0)(jiti@2.6.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2))
+ specifier: ^2.11.9
+ version: 2.11.9(@testing-library/jest-dom@6.9.1)(solid-js@1.9.9)(vite@7.1.10(@types/node@24.8.1)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2))
packages:
@@ -581,10 +632,6 @@ packages:
resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==}
engines: {node: '>=10'}
- '@ampproject/remapping@2.3.0':
- resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==}
- engines: {node: '>=6.0.0'}
-
'@antfu/eslint-config@2.19.1':
resolution: {integrity: sha512-gtiyWxoBnk39Vgf23xJiSQrq3esEGYesv7Q4IZXEJJaYSpyiJWHMYxlC6dFr4V9tAczDa7bZjR9E6XWEiU7VEA==}
hasBin: true
@@ -698,18 +745,10 @@ packages:
resolution: {integrity: sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==}
engines: {node: '>=6.9.0'}
- '@babel/core@7.28.0':
- resolution: {integrity: sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==}
- engines: {node: '>=6.9.0'}
-
'@babel/core@7.28.4':
resolution: {integrity: sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==}
engines: {node: '>=6.9.0'}
- '@babel/generator@7.28.0':
- resolution: {integrity: sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg==}
- engines: {node: '>=6.9.0'}
-
'@babel/generator@7.28.3':
resolution: {integrity: sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==}
engines: {node: '>=6.9.0'}
@@ -817,24 +856,10 @@ packages:
resolution: {integrity: sha512-zdf983tNfLZFletc0RRXYrHrucBEg95NIFMkn6K9dbeMYnsgHaSBGcQqdsCSStG2PYwRre0Qc2NNSCXbG+xc6g==}
engines: {node: '>=6.9.0'}
- '@babel/helpers@7.27.6':
- resolution: {integrity: sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==}
- engines: {node: '>=6.9.0'}
-
'@babel/helpers@7.28.4':
resolution: {integrity: sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==}
engines: {node: '>=6.9.0'}
- '@babel/parser@7.27.5':
- resolution: {integrity: sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg==}
- engines: {node: '>=6.0.0'}
- hasBin: true
-
- '@babel/parser@7.28.0':
- resolution: {integrity: sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==}
- engines: {node: '>=6.0.0'}
- hasBin: true
-
'@babel/parser@7.28.3':
resolution: {integrity: sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA==}
engines: {node: '>=6.0.0'}
@@ -1355,6 +1380,10 @@ packages:
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/runtime@7.28.3':
+ resolution: {integrity: sha512-9uIQ10o0WGdpP6GDhXcdOJPJuDgFtIDtN/9+ArJQ2NAfAmiuhTQdzkaTGR33v43GYS2UrSA0eX2pPPHoFVvpxA==}
+ engines: {node: '>=6.9.0'}
+
'@babel/runtime@7.28.4':
resolution: {integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==}
engines: {node: '>=6.9.0'}
@@ -1367,10 +1396,6 @@ packages:
resolution: {integrity: sha512-oNcu2QbHqts9BtOWJosOVJapWjBDSxGCpFvikNR5TGDYDQf3JwpIoMzIKrvfoti93cLfPJEG4tH9SPVeyCGgdA==}
engines: {node: '>=6.9.0'}
- '@babel/traverse@7.28.0':
- resolution: {integrity: sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg==}
- engines: {node: '>=6.9.0'}
-
'@babel/traverse@7.28.3':
resolution: {integrity: sha512-7w4kZYHneL3A6NP2nxzHvT3HCZ7puDZZjFMqDpBPECub79sTtSO5CGXDkKrTQq8ksAwfD/XI2MRFX23njdDaIQ==}
engines: {node: '>=6.9.0'}
@@ -1383,10 +1408,6 @@ packages:
resolution: {integrity: sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q==}
engines: {node: '>=6.9.0'}
- '@babel/types@7.28.0':
- resolution: {integrity: sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==}
- engines: {node: '>=6.9.0'}
-
'@babel/types@7.28.2':
resolution: {integrity: sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==}
engines: {node: '>=6.9.0'}
@@ -1461,6 +1482,11 @@ packages:
bundledDependencies:
- is-unicode-supported
+ '@corvu/resizable@0.2.5':
+ resolution: {integrity: sha512-psax38DraM9SXtaNh/sfvizGO6xLCL4sqT4rWYlMZP5ZsUM05Q30tvXgnTo2roQFNOz2e06WofhDsBXTjY6g4A==}
+ peerDependencies:
+ solid-js: ^1.8
+
'@corvu/utils@0.4.2':
resolution: {integrity: sha512-Ox2kYyxy7NoXdKWdHeDEjZxClwzO4SKM8plAaVwmAJPxHMqA0rLOoAsa+hBDwRLpctf+ZRnAd/ykguuJidnaTA==}
peerDependencies:
@@ -1517,8 +1543,8 @@ packages:
cpu: [ppc64]
os: [aix]
- '@esbuild/aix-ppc64@0.25.10':
- resolution: {integrity: sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw==}
+ '@esbuild/aix-ppc64@0.25.11':
+ resolution: {integrity: sha512-Xt1dOL13m8u0WE8iplx9Ibbm+hFAO0GsU2P34UNoDGvZYkY8ifSiy6Zuc1lYxfG7svWE2fzqCUmFp5HCn51gJg==}
engines: {node: '>=18'}
cpu: [ppc64]
os: [aix]
@@ -1535,8 +1561,8 @@ packages:
cpu: [arm64]
os: [android]
- '@esbuild/android-arm64@0.25.10':
- resolution: {integrity: sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg==}
+ '@esbuild/android-arm64@0.25.11':
+ resolution: {integrity: sha512-9slpyFBc4FPPz48+f6jyiXOx/Y4v34TUeDDXJpZqAWQn/08lKGeD8aDp9TMn9jDz2CiEuHwfhRmGBvpnd/PWIQ==}
engines: {node: '>=18'}
cpu: [arm64]
os: [android]
@@ -1553,8 +1579,8 @@ packages:
cpu: [arm]
os: [android]
- '@esbuild/android-arm@0.25.10':
- resolution: {integrity: sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w==}
+ '@esbuild/android-arm@0.25.11':
+ resolution: {integrity: sha512-uoa7dU+Dt3HYsethkJ1k6Z9YdcHjTrSb5NUy66ZfZaSV8hEYGD5ZHbEMXnqLFlbBflLsl89Zke7CAdDJ4JI+Gg==}
engines: {node: '>=18'}
cpu: [arm]
os: [android]
@@ -1571,8 +1597,8 @@ packages:
cpu: [x64]
os: [android]
- '@esbuild/android-x64@0.25.10':
- resolution: {integrity: sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg==}
+ '@esbuild/android-x64@0.25.11':
+ resolution: {integrity: sha512-Sgiab4xBjPU1QoPEIqS3Xx+R2lezu0LKIEcYe6pftr56PqPygbB7+szVnzoShbx64MUupqoE0KyRlN7gezbl8g==}
engines: {node: '>=18'}
cpu: [x64]
os: [android]
@@ -1589,8 +1615,8 @@ packages:
cpu: [arm64]
os: [darwin]
- '@esbuild/darwin-arm64@0.25.10':
- resolution: {integrity: sha512-JC74bdXcQEpW9KkV326WpZZjLguSZ3DfS8wrrvPMHgQOIEIG/sPXEN/V8IssoJhbefLRcRqw6RQH2NnpdprtMA==}
+ '@esbuild/darwin-arm64@0.25.11':
+ resolution: {integrity: sha512-VekY0PBCukppoQrycFxUqkCojnTQhdec0vevUL/EDOCnXd9LKWqD/bHwMPzigIJXPhC59Vd1WFIL57SKs2mg4w==}
engines: {node: '>=18'}
cpu: [arm64]
os: [darwin]
@@ -1607,8 +1633,8 @@ packages:
cpu: [x64]
os: [darwin]
- '@esbuild/darwin-x64@0.25.10':
- resolution: {integrity: sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg==}
+ '@esbuild/darwin-x64@0.25.11':
+ resolution: {integrity: sha512-+hfp3yfBalNEpTGp9loYgbknjR695HkqtY3d3/JjSRUyPg/xd6q+mQqIb5qdywnDxRZykIHs3axEqU6l1+oWEQ==}
engines: {node: '>=18'}
cpu: [x64]
os: [darwin]
@@ -1625,8 +1651,8 @@ packages:
cpu: [arm64]
os: [freebsd]
- '@esbuild/freebsd-arm64@0.25.10':
- resolution: {integrity: sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg==}
+ '@esbuild/freebsd-arm64@0.25.11':
+ resolution: {integrity: sha512-CmKjrnayyTJF2eVuO//uSjl/K3KsMIeYeyN7FyDBjsR3lnSJHaXlVoAK8DZa7lXWChbuOk7NjAc7ygAwrnPBhA==}
engines: {node: '>=18'}
cpu: [arm64]
os: [freebsd]
@@ -1643,8 +1669,8 @@ packages:
cpu: [x64]
os: [freebsd]
- '@esbuild/freebsd-x64@0.25.10':
- resolution: {integrity: sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA==}
+ '@esbuild/freebsd-x64@0.25.11':
+ resolution: {integrity: sha512-Dyq+5oscTJvMaYPvW3x3FLpi2+gSZTCE/1ffdwuM6G1ARang/mb3jvjxs0mw6n3Lsw84ocfo9CrNMqc5lTfGOw==}
engines: {node: '>=18'}
cpu: [x64]
os: [freebsd]
@@ -1661,8 +1687,8 @@ packages:
cpu: [arm64]
os: [linux]
- '@esbuild/linux-arm64@0.25.10':
- resolution: {integrity: sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ==}
+ '@esbuild/linux-arm64@0.25.11':
+ resolution: {integrity: sha512-Qr8AzcplUhGvdyUF08A1kHU3Vr2O88xxP0Tm8GcdVOUm25XYcMPp2YqSVHbLuXzYQMf9Bh/iKx7YPqECs6ffLA==}
engines: {node: '>=18'}
cpu: [arm64]
os: [linux]
@@ -1679,8 +1705,8 @@ packages:
cpu: [arm]
os: [linux]
- '@esbuild/linux-arm@0.25.10':
- resolution: {integrity: sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg==}
+ '@esbuild/linux-arm@0.25.11':
+ resolution: {integrity: sha512-TBMv6B4kCfrGJ8cUPo7vd6NECZH/8hPpBHHlYI3qzoYFvWu2AdTvZNuU/7hsbKWqu/COU7NIK12dHAAqBLLXgw==}
engines: {node: '>=18'}
cpu: [arm]
os: [linux]
@@ -1697,8 +1723,8 @@ packages:
cpu: [ia32]
os: [linux]
- '@esbuild/linux-ia32@0.25.10':
- resolution: {integrity: sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ==}
+ '@esbuild/linux-ia32@0.25.11':
+ resolution: {integrity: sha512-TmnJg8BMGPehs5JKrCLqyWTVAvielc615jbkOirATQvWWB1NMXY77oLMzsUjRLa0+ngecEmDGqt5jiDC6bfvOw==}
engines: {node: '>=18'}
cpu: [ia32]
os: [linux]
@@ -1715,8 +1741,8 @@ packages:
cpu: [loong64]
os: [linux]
- '@esbuild/linux-loong64@0.25.10':
- resolution: {integrity: sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg==}
+ '@esbuild/linux-loong64@0.25.11':
+ resolution: {integrity: sha512-DIGXL2+gvDaXlaq8xruNXUJdT5tF+SBbJQKbWy/0J7OhU8gOHOzKmGIlfTTl6nHaCOoipxQbuJi7O++ldrxgMw==}
engines: {node: '>=18'}
cpu: [loong64]
os: [linux]
@@ -1733,8 +1759,8 @@ packages:
cpu: [mips64el]
os: [linux]
- '@esbuild/linux-mips64el@0.25.10':
- resolution: {integrity: sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA==}
+ '@esbuild/linux-mips64el@0.25.11':
+ resolution: {integrity: sha512-Osx1nALUJu4pU43o9OyjSCXokFkFbyzjXb6VhGIJZQ5JZi8ylCQ9/LFagolPsHtgw6himDSyb5ETSfmp4rpiKQ==}
engines: {node: '>=18'}
cpu: [mips64el]
os: [linux]
@@ -1751,8 +1777,8 @@ packages:
cpu: [ppc64]
os: [linux]
- '@esbuild/linux-ppc64@0.25.10':
- resolution: {integrity: sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA==}
+ '@esbuild/linux-ppc64@0.25.11':
+ resolution: {integrity: sha512-nbLFgsQQEsBa8XSgSTSlrnBSrpoWh7ioFDUmwo158gIm5NNP+17IYmNWzaIzWmgCxq56vfr34xGkOcZ7jX6CPw==}
engines: {node: '>=18'}
cpu: [ppc64]
os: [linux]
@@ -1769,8 +1795,8 @@ packages:
cpu: [riscv64]
os: [linux]
- '@esbuild/linux-riscv64@0.25.10':
- resolution: {integrity: sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA==}
+ '@esbuild/linux-riscv64@0.25.11':
+ resolution: {integrity: sha512-HfyAmqZi9uBAbgKYP1yGuI7tSREXwIb438q0nqvlpxAOs3XnZ8RsisRfmVsgV486NdjD7Mw2UrFSw51lzUk1ww==}
engines: {node: '>=18'}
cpu: [riscv64]
os: [linux]
@@ -1787,8 +1813,8 @@ packages:
cpu: [s390x]
os: [linux]
- '@esbuild/linux-s390x@0.25.10':
- resolution: {integrity: sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew==}
+ '@esbuild/linux-s390x@0.25.11':
+ resolution: {integrity: sha512-HjLqVgSSYnVXRisyfmzsH6mXqyvj0SA7pG5g+9W7ESgwA70AXYNpfKBqh1KbTxmQVaYxpzA/SvlB9oclGPbApw==}
engines: {node: '>=18'}
cpu: [s390x]
os: [linux]
@@ -1805,8 +1831,8 @@ packages:
cpu: [x64]
os: [linux]
- '@esbuild/linux-x64@0.25.10':
- resolution: {integrity: sha512-QSX81KhFoZGwenVyPoberggdW1nrQZSvfVDAIUXr3WqLRZGZqWk/P4T8p2SP+de2Sr5HPcvjhcJzEiulKgnxtA==}
+ '@esbuild/linux-x64@0.25.11':
+ resolution: {integrity: sha512-HSFAT4+WYjIhrHxKBwGmOOSpphjYkcswF449j6EjsjbinTZbp8PJtjsVK1XFJStdzXdy/jaddAep2FGY+wyFAQ==}
engines: {node: '>=18'}
cpu: [x64]
os: [linux]
@@ -1817,8 +1843,8 @@ packages:
cpu: [x64]
os: [linux]
- '@esbuild/netbsd-arm64@0.25.10':
- resolution: {integrity: sha512-AKQM3gfYfSW8XRk8DdMCzaLUFB15dTrZfnX8WXQoOUpUBQ+NaAFCP1kPS/ykbbGYz7rxn0WS48/81l9hFl3u4A==}
+ '@esbuild/netbsd-arm64@0.25.11':
+ resolution: {integrity: sha512-hr9Oxj1Fa4r04dNpWr3P8QKVVsjQhqrMSUzZzf+LZcYjZNqhA3IAfPQdEh1FLVUJSiu6sgAwp3OmwBfbFgG2Xg==}
engines: {node: '>=18'}
cpu: [arm64]
os: [netbsd]
@@ -1835,8 +1861,8 @@ packages:
cpu: [x64]
os: [netbsd]
- '@esbuild/netbsd-x64@0.25.10':
- resolution: {integrity: sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig==}
+ '@esbuild/netbsd-x64@0.25.11':
+ resolution: {integrity: sha512-u7tKA+qbzBydyj0vgpu+5h5AeudxOAGncb8N6C9Kh1N4n7wU1Xw1JDApsRjpShRpXRQlJLb9wY28ELpwdPcZ7A==}
engines: {node: '>=18'}
cpu: [x64]
os: [netbsd]
@@ -1847,8 +1873,8 @@ packages:
cpu: [x64]
os: [netbsd]
- '@esbuild/openbsd-arm64@0.25.10':
- resolution: {integrity: sha512-5Se0VM9Wtq797YFn+dLimf2Zx6McttsH2olUBsDml+lm0GOCRVebRWUvDtkY4BWYv/3NgzS8b/UM3jQNh5hYyw==}
+ '@esbuild/openbsd-arm64@0.25.11':
+ resolution: {integrity: sha512-Qq6YHhayieor3DxFOoYM1q0q1uMFYb7cSpLD2qzDSvK1NAvqFi8Xgivv0cFC6J+hWVw2teCYltyy9/m/14ryHg==}
engines: {node: '>=18'}
cpu: [arm64]
os: [openbsd]
@@ -1865,8 +1891,8 @@ packages:
cpu: [x64]
os: [openbsd]
- '@esbuild/openbsd-x64@0.25.10':
- resolution: {integrity: sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw==}
+ '@esbuild/openbsd-x64@0.25.11':
+ resolution: {integrity: sha512-CN+7c++kkbrckTOz5hrehxWN7uIhFFlmS/hqziSFVWpAzpWrQoAG4chH+nN3Be+Kzv/uuo7zhX716x3Sn2Jduw==}
engines: {node: '>=18'}
cpu: [x64]
os: [openbsd]
@@ -1877,8 +1903,8 @@ packages:
cpu: [x64]
os: [openbsd]
- '@esbuild/openharmony-arm64@0.25.10':
- resolution: {integrity: sha512-AVTSBhTX8Y/Fz6OmIVBip9tJzZEUcY8WLh7I59+upa5/GPhh2/aM6bvOMQySspnCCHvFi79kMtdJS1w0DXAeag==}
+ '@esbuild/openharmony-arm64@0.25.11':
+ resolution: {integrity: sha512-rOREuNIQgaiR+9QuNkbkxubbp8MSO9rONmwP5nKncnWJ9v5jQ4JxFnLu4zDSRPf3x4u+2VN4pM4RdyIzDty/wQ==}
engines: {node: '>=18'}
cpu: [arm64]
os: [openharmony]
@@ -1895,8 +1921,8 @@ packages:
cpu: [x64]
os: [sunos]
- '@esbuild/sunos-x64@0.25.10':
- resolution: {integrity: sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ==}
+ '@esbuild/sunos-x64@0.25.11':
+ resolution: {integrity: sha512-nq2xdYaWxyg9DcIyXkZhcYulC6pQ2FuCgem3LI92IwMgIZ69KHeY8T4Y88pcwoLIjbed8n36CyKoYRDygNSGhA==}
engines: {node: '>=18'}
cpu: [x64]
os: [sunos]
@@ -1913,8 +1939,8 @@ packages:
cpu: [arm64]
os: [win32]
- '@esbuild/win32-arm64@0.25.10':
- resolution: {integrity: sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw==}
+ '@esbuild/win32-arm64@0.25.11':
+ resolution: {integrity: sha512-3XxECOWJq1qMZ3MN8srCJ/QfoLpL+VaxD/WfNRm1O3B4+AZ/BnLVgFbUV3eiRYDMXetciH16dwPbbHqwe1uU0Q==}
engines: {node: '>=18'}
cpu: [arm64]
os: [win32]
@@ -1931,8 +1957,8 @@ packages:
cpu: [ia32]
os: [win32]
- '@esbuild/win32-ia32@0.25.10':
- resolution: {integrity: sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw==}
+ '@esbuild/win32-ia32@0.25.11':
+ resolution: {integrity: sha512-3ukss6gb9XZ8TlRyJlgLn17ecsK4NSQTmdIXRASVsiS2sQ6zPPZklNJT5GR5tE/MUarymmy8kCEf5xPCNCqVOA==}
engines: {node: '>=18'}
cpu: [ia32]
os: [win32]
@@ -1949,8 +1975,8 @@ packages:
cpu: [x64]
os: [win32]
- '@esbuild/win32-x64@0.25.10':
- resolution: {integrity: sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw==}
+ '@esbuild/win32-x64@0.25.11':
+ resolution: {integrity: sha512-D7Hpz6A2L4hzsRpPaCYkQnGOotdUpDzSGRIv9I+1ITdHROSFUWW95ZPZWQmGka1Fg7W3zFJowyn9WGwMJ0+KPA==}
engines: {node: '>=18'}
cpu: [x64]
os: [win32]
@@ -1981,16 +2007,16 @@ packages:
resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==}
engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
- '@eslint/config-array@0.21.0':
- resolution: {integrity: sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==}
+ '@eslint/config-array@0.21.1':
+ resolution: {integrity: sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- '@eslint/config-helpers@0.3.1':
- resolution: {integrity: sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==}
+ '@eslint/config-helpers@0.4.1':
+ resolution: {integrity: sha512-csZAzkNhsgwb0I/UAV6/RGFTbiakPCf0ZrGmrIxQpYvGZ00PhTkSnyKNolphgIvmnJeGw6rcGVEXfTzUnFuEvw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- '@eslint/core@0.15.2':
- resolution: {integrity: sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==}
+ '@eslint/core@0.16.0':
+ resolution: {integrity: sha512-nmC8/totwobIiFcGkDza3GIKfAw1+hLiYVrh3I1nIomQ8PEr5cxg34jnkmGawul/ep52wGRAcyeDCNtWKSOj4Q==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@eslint/eslintrc@3.1.0':
@@ -2001,16 +2027,16 @@ packages:
resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- '@eslint/js@9.36.0':
- resolution: {integrity: sha512-uhCbYtYynH30iZErszX78U+nR3pJU3RHGQ57NXy5QupD4SBVwDeU8TNBy+MjMngc1UyIW9noKqsRqfjQTBU2dw==}
+ '@eslint/js@9.38.0':
+ resolution: {integrity: sha512-UZ1VpFvXf9J06YG9xQBdnzU+kthors6KjhMAl6f4gH4usHyh31rUf2DLGInT8RFYIReYXNSydgPY0V2LuWgl7A==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- '@eslint/object-schema@2.1.6':
- resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==}
+ '@eslint/object-schema@2.1.7':
+ resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- '@eslint/plugin-kit@0.3.5':
- resolution: {integrity: sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==}
+ '@eslint/plugin-kit@0.4.0':
+ resolution: {integrity: sha512-sB5uyeq+dwCWyPi31B2gQlVlo+j5brPlWx4yZBrEaRo/nhdDE8Xke1gsGgtiBdaBTxuTkceLVuVt/pclrasb0A==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@floating-ui/core@1.7.3':
@@ -2022,6 +2048,10 @@ packages:
'@floating-ui/utils@0.2.10':
resolution: {integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==}
+ '@happy-dom/global-registrator@20.0.8':
+ resolution: {integrity: sha512-6XJ7BGO3tz3yLZcrQF1JIQAEZ6u3mJ2EYfLSZDuZPC5EVdGtz5O2R/RlWgLYATc2tbkPnuxb9qHWHdT4TlzeOw==}
+ engines: {node: '>=20.0.0'}
+
'@humanfs/core@0.19.1':
resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==}
engines: {node: '>=18.18.0'}
@@ -2311,9 +2341,6 @@ packages:
resolution: {integrity: sha512-H9xg1/sfVvyfU7o3zMfBEjQ1gcsdeTMgqHoYdN79tuLqfTtuu7WckRA1R5whDwOzxaZAeMKTYWqP+WCAi0CHsg==}
engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
- '@jridgewell/gen-mapping@0.3.12':
- resolution: {integrity: sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==}
-
'@jridgewell/gen-mapping@0.3.13':
resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==}
@@ -2321,10 +2348,6 @@ packages:
resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==}
engines: {node: '>=6.0.0'}
- '@jridgewell/gen-mapping@0.3.8':
- resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==}
- engines: {node: '>=6.0.0'}
-
'@jridgewell/remapping@2.3.5':
resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==}
@@ -2351,9 +2374,6 @@ packages:
'@jridgewell/trace-mapping@0.3.29':
resolution: {integrity: sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==}
- '@jridgewell/trace-mapping@0.3.30':
- resolution: {integrity: sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==}
-
'@jridgewell/trace-mapping@0.3.31':
resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
@@ -2380,32 +2400,32 @@ packages:
'@manypkg/get-packages@1.1.3':
resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==}
- '@microsoft/1ds-core-js@4.3.8':
- resolution: {integrity: sha512-5y7pmcqoYmh+461xyUog4aQAZ2ZIoYlAg7VkHU0G+dpOwAmwN3WECnsO/8RNagNiVwsFOBeN5e2OxKm3vruJWw==}
+ '@microsoft/1ds-core-js@4.3.10':
+ resolution: {integrity: sha512-5fSZmkGwWkH+mrIA5M1GYPZdPM+SjXwCCl2Am7VhFoVwOBJNhRnwvIpAdzw6sFjiebN/rz+/YH0NdxztGZSa9Q==}
- '@microsoft/1ds-post-js@4.3.8':
- resolution: {integrity: sha512-9Jq6PqEs/wImx246xhOU6WyrhBVMLZPp1MGCKKGexxOQKhHSbK6RzOguSYKT15nfO7JVDde3+nCGc6EPxAagaA==}
+ '@microsoft/1ds-post-js@4.3.10':
+ resolution: {integrity: sha512-VSLjc9cT+Y+eTiSfYltJHJCejn8oYr0E6Pq2BMhOEO7F6IyLGYIxzKKvo78ze9x+iHX7KPTATcZ+PFgjGXuNqg==}
- '@microsoft/applicationinsights-channel-js@3.3.8':
- resolution: {integrity: sha512-uj60YhHTxcHLjLUHRPe2Y9VVdDOcam4/pdBBCbJ6/hkBWh6KZznnM3vb6JRbBVwD69Iq6tdGNWJRSCWNpZhLaA==}
+ '@microsoft/applicationinsights-channel-js@3.3.10':
+ resolution: {integrity: sha512-iolFLz1ocWAzIQqHIEjjov3gNTPkgFQ4ArHnBcJEYoffOGWlJt6copaevS5YPI5rHzmbySsengZ8cLJJBBrXzQ==}
peerDependencies:
tslib: '>= 1.0.0'
- '@microsoft/applicationinsights-common@3.3.8':
- resolution: {integrity: sha512-yfcU3g05Z36S3r4SDtV+LGkoubT3px6Yt4fwINIGDixbTJB6VZXQxLwkTAzWxKwxuvBX2L8PP9O1LY4D7gGrrA==}
+ '@microsoft/applicationinsights-common@3.3.10':
+ resolution: {integrity: sha512-RVIenPIvNgZCbjJdALvLM4rNHgAFuHI7faFzHCgnI6S2WCUNGHeXlQTs9EUUrL+n2TPp9/cd0KKMILU5VVyYiA==}
peerDependencies:
tslib: '>= 1.0.0'
- '@microsoft/applicationinsights-core-js@3.3.8':
- resolution: {integrity: sha512-k1uQCRSbV0aUF4DxgTFAbbk1IlsihLoldgQCMIVwHdnS3X80NjtSDWQPy0n+Hbw1XNlpky9p8jxNDJlZ9PoFDg==}
+ '@microsoft/applicationinsights-core-js@3.3.10':
+ resolution: {integrity: sha512-5yKeyassZTq2l+SAO4npu6LPnbS++UD+M+Ghjm9uRzoBwD8tumFx0/F8AkSVqbniSREd+ztH/2q2foewa2RZyg==}
peerDependencies:
tslib: '>= 1.0.0'
'@microsoft/applicationinsights-shims@3.0.1':
resolution: {integrity: sha512-DKwboF47H1nb33rSUfjqI6ryX29v+2QWcTrRvcQDA32AZr5Ilkr7whOOSsD1aBzwqX0RJEIP1Z81jfE3NBm/Lg==}
- '@microsoft/applicationinsights-web-basic@3.3.8':
- resolution: {integrity: sha512-etHqbg6zwDxObY7GUF1CZZtoNIzzfjzvJyOEvixwnio4ehHyxZLQXBTavoUL424/A2MgWTBQjj6AV2ezayoz4A==}
+ '@microsoft/applicationinsights-web-basic@3.3.10':
+ resolution: {integrity: sha512-AZib5DAT3NU0VT0nLWEwXrnoMDDgZ/5S4dso01CNU5ELNxLdg+1fvchstlVdMy4FrAnxzs8Wf/GIQNFYOVgpAw==}
peerDependencies:
tslib: '>= 1.0.0'
@@ -2429,8 +2449,8 @@ packages:
'@napi-rs/wasm-runtime@0.2.12':
resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==}
- '@napi-rs/wasm-runtime@1.0.5':
- resolution: {integrity: sha512-TBr9Cf9onSAS2LQ2+QHx6XcC6h9+RIzJgbqG3++9TUZSH204AwEy5jg3BTQ0VATsyoGj4ee49tN/y6rvaOOtcg==}
+ '@napi-rs/wasm-runtime@1.0.7':
+ resolution: {integrity: sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw==}
'@nevware21/ts-async@0.5.4':
resolution: {integrity: sha512-IBTyj29GwGlxfzXw2NPnzty+w0Adx61Eze1/lknH/XIVdxtF9UnOpk76tnrHXWa6j84a1RR9hsOcHQPFv9qJjA==}
@@ -2438,53 +2458,53 @@ packages:
'@nevware21/ts-utils@0.12.5':
resolution: {integrity: sha512-JPQZWPKQJjj7kAftdEZL0XDFfbMgXCGiUAZe0d7EhLC3QlXTlZdSckGqqRIQ2QNl0VTEZyZUvRBw6Ednw089Fw==}
- '@next/env@15.5.4':
- resolution: {integrity: sha512-27SQhYp5QryzIT5uO8hq99C69eLQ7qkzkDPsk3N+GuS2XgOgoYEeOav7Pf8Tn4drECOVDsDg8oj+/DVy8qQL2A==}
+ '@next/env@15.5.6':
+ resolution: {integrity: sha512-3qBGRW+sCGzgbpc5TS1a0p7eNxnOarGVQhZxfvTdnV0gFI61lX7QNtQ4V1TSREctXzYn5NetbUsLvyqwLFJM6Q==}
- '@next/swc-darwin-arm64@15.5.4':
- resolution: {integrity: sha512-nopqz+Ov6uvorej8ndRX6HlxCYWCO3AHLfKK2TYvxoSB2scETOcfm/HSS3piPqc3A+MUgyHoqE6je4wnkjfrOA==}
+ '@next/swc-darwin-arm64@15.5.6':
+ resolution: {integrity: sha512-ES3nRz7N+L5Umz4KoGfZ4XX6gwHplwPhioVRc25+QNsDa7RtUF/z8wJcbuQ2Tffm5RZwuN2A063eapoJ1u4nPg==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [darwin]
- '@next/swc-darwin-x64@15.5.4':
- resolution: {integrity: sha512-QOTCFq8b09ghfjRJKfb68kU9k2K+2wsC4A67psOiMn849K9ZXgCSRQr0oVHfmKnoqCbEmQWG1f2h1T2vtJJ9mA==}
+ '@next/swc-darwin-x64@15.5.6':
+ resolution: {integrity: sha512-JIGcytAyk9LQp2/nuVZPAtj8uaJ/zZhsKOASTjxDug0SPU9LAM3wy6nPU735M1OqacR4U20LHVF5v5Wnl9ptTA==}
engines: {node: '>= 10'}
cpu: [x64]
os: [darwin]
- '@next/swc-linux-arm64-gnu@15.5.4':
- resolution: {integrity: sha512-eRD5zkts6jS3VfE/J0Kt1VxdFqTnMc3QgO5lFE5GKN3KDI/uUpSyK3CjQHmfEkYR4wCOl0R0XrsjpxfWEA++XA==}
+ '@next/swc-linux-arm64-gnu@15.5.6':
+ resolution: {integrity: sha512-qvz4SVKQ0P3/Im9zcS2RmfFL/UCQnsJKJwQSkissbngnB/12c6bZTCB0gHTexz1s6d/mD0+egPKXAIRFVS7hQg==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
- '@next/swc-linux-arm64-musl@15.5.4':
- resolution: {integrity: sha512-TOK7iTxmXFc45UrtKqWdZ1shfxuL4tnVAOuuJK4S88rX3oyVV4ZkLjtMT85wQkfBrOOvU55aLty+MV8xmcJR8A==}
+ '@next/swc-linux-arm64-musl@15.5.6':
+ resolution: {integrity: sha512-FsbGVw3SJz1hZlvnWD+T6GFgV9/NYDeLTNQB2MXoPN5u9VA9OEDy6fJEfePfsUKAhJufFbZLgp0cPxMuV6SV0w==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
- '@next/swc-linux-x64-gnu@15.5.4':
- resolution: {integrity: sha512-7HKolaj+481FSW/5lL0BcTkA4Ueam9SPYWyN/ib/WGAFZf0DGAN8frNpNZYFHtM4ZstrHZS3LY3vrwlIQfsiMA==}
+ '@next/swc-linux-x64-gnu@15.5.6':
+ resolution: {integrity: sha512-3QnHGFWlnvAgyxFxt2Ny8PTpXtQD7kVEeaFat5oPAHHI192WKYB+VIKZijtHLGdBBvc16tiAkPTDmQNOQ0dyrA==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
- '@next/swc-linux-x64-musl@15.5.4':
- resolution: {integrity: sha512-nlQQ6nfgN0nCO/KuyEUwwOdwQIGjOs4WNMjEUtpIQJPR2NUfmGpW2wkJln1d4nJ7oUzd1g4GivH5GoEPBgfsdw==}
+ '@next/swc-linux-x64-musl@15.5.6':
+ resolution: {integrity: sha512-OsGX148sL+TqMK9YFaPFPoIaJKbFJJxFzkXZljIgA9hjMjdruKht6xDCEv1HLtlLNfkx3c5w2GLKhj7veBQizQ==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
- '@next/swc-win32-arm64-msvc@15.5.4':
- resolution: {integrity: sha512-PcR2bN7FlM32XM6eumklmyWLLbu2vs+D7nJX8OAIoWy69Kef8mfiN4e8TUv2KohprwifdpFKPzIP1njuCjD0YA==}
+ '@next/swc-win32-arm64-msvc@15.5.6':
+ resolution: {integrity: sha512-ONOMrqWxdzXDJNh2n60H6gGyKed42Ieu6UTVPZteXpuKbLZTH4G4eBMsr5qWgOBA+s7F+uB4OJbZnrkEDnZ5Fg==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [win32]
- '@next/swc-win32-x64-msvc@15.5.4':
- resolution: {integrity: sha512-1ur2tSHZj8Px/KMAthmuI9FMp/YFusMMGoRNJaRZMOlSkgvLjzosSdQI0cJAKogdHl3qXUQKL9MGaYvKwA7DXg==}
+ '@next/swc-win32-x64-msvc@15.5.6':
+ resolution: {integrity: sha512-pxK4VIjFRx1MY92UycLOOw7dTdvccWsNETQ0kDHkBlcFH1GrTLUjSiHU1ohrznnux6TqRHgv5oflhfIWZwVROQ==}
engines: {node: '>= 10'}
cpu: [x64]
os: [win32]
@@ -2588,11 +2608,98 @@ packages:
resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
engines: {node: '>= 8'}
- '@oxc-parser/binding-wasm32-wasi@0.93.0':
- resolution: {integrity: sha512-EXyCyY4GJO+SNTQJPPmJJwYbPkPOzw2nxSRMmUlwG19WKO7QHzHyL6u+4hXpp5IwgIWvgQgoix2/pB9JF+EA7w==}
+ '@oxc-parser/binding-android-arm64@0.95.0':
+ resolution: {integrity: sha512-dZyxhhvJigwWL1wgnLlqyEiSeuqO0WdDH9H+if0dPcBM4fKa5fjVkaUcJT1jBMcBTnkjxMwTXYZy5TK60N0fjg==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [android]
+
+ '@oxc-parser/binding-darwin-arm64@0.95.0':
+ resolution: {integrity: sha512-zun9+V33kyCtNec9oUSWwb0qi3fB8pXwum1yGFECPEr55g/CrWju6/Jv4hwwNBeW2tK9Ch/PRstEtYmOLMhHpg==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@oxc-parser/binding-darwin-x64@0.95.0':
+ resolution: {integrity: sha512-9djMQ/t6Ns/UXtziwUe562uVJMbhtuLtCj+Xav+HMVT/rhV9gWO8PQOG7AwDLUBjJanItsrfqrGtqhNxtZ701w==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [darwin]
+
+ '@oxc-parser/binding-freebsd-x64@0.95.0':
+ resolution: {integrity: sha512-GK6k0PgCVkkeRZtHgcosCYbXIRySpJpuPw/OInfLGFh8f3x9gp2l8Fbcfx+YO+ZOHFBCd2NNedGqw8wMgouxfA==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@oxc-parser/binding-linux-arm-gnueabihf@0.95.0':
+ resolution: {integrity: sha512-+g/lFITtyHHEk69cunOHuiT5cX+mpUTcbGYNe8suguZ7FqgNwai+PnGv0ctCvtgxBPVfckfUK8c3RvFKo+vi/w==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm]
+ os: [linux]
+
+ '@oxc-parser/binding-linux-arm-musleabihf@0.95.0':
+ resolution: {integrity: sha512-SXNasDtPw8ycNV7VEvFxb4LETmykvWKUhHR7K3us818coXYpDj54P8WEx8hJobP/9skuuiFuKHmtYLdjX8wntA==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm]
+ os: [linux]
+
+ '@oxc-parser/binding-linux-arm64-gnu@0.95.0':
+ resolution: {integrity: sha512-0LzebARTU0ROfD6pDK4h1pFn+09meErCZ0MA2TaW08G72+GNneEsksPufOuI+9AxVSRa+jKE3fu0wavvhZgSkg==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [linux]
+
+ '@oxc-parser/binding-linux-arm64-musl@0.95.0':
+ resolution: {integrity: sha512-Pvi1lGe/G+mJZ3hUojMP/aAHAzHA25AEtVr8/iuz7UV72t/15NOgJYr9kELMUMNjPqpr3vKUgXTFmTtAxp11Qw==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [linux]
+
+ '@oxc-parser/binding-linux-riscv64-gnu@0.95.0':
+ resolution: {integrity: sha512-pUEVHIOVNDfhk4sTlLhn6mrNENhE4/dAwemxIfqpcSyBlYG0xYZND1F3jjR2yWY6DakXZ6VSuDbtiv1LPNlOLw==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@oxc-parser/binding-linux-s390x-gnu@0.95.0':
+ resolution: {integrity: sha512-5+olaepHTE3J/+w7g0tr3nocvv5BKilAJnzj4L8tWBCLEZbL6olJcGVoldUO+3cgg1SO1xJywP5BuLhT0mDUDw==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [s390x]
+ os: [linux]
+
+ '@oxc-parser/binding-linux-x64-gnu@0.95.0':
+ resolution: {integrity: sha512-8huzHlK/N98wrnYKxIcYsK8ZGBWomQchu/Mzi6m+CtbhjWOv9DmK0jQ2fUWImtluQVpTwS0uZT06d3g7XIkJrA==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [linux]
+
+ '@oxc-parser/binding-linux-x64-musl@0.95.0':
+ resolution: {integrity: sha512-bWnrLfGDcx/fab0+UQnFbVFbiykof/btImbYf+cI2pU/1Egb2x+OKSmM5Qt0nEUiIpM5fgJmYXxTopybSZOKYA==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [linux]
+
+ '@oxc-parser/binding-wasm32-wasi@0.95.0':
+ resolution: {integrity: sha512-0JLyqkZu1HnQIZ4e5LBGOtzqua1QwFEUOoMSycdoerXqayd4LK2b7WMfAx8eCIf+jGm1Uj6f3R00nlsx8g1faQ==}
engines: {node: '>=14.0.0'}
cpu: [wasm32]
+ '@oxc-parser/binding-win32-arm64-msvc@0.95.0':
+ resolution: {integrity: sha512-RWvaA6s1SYlBj9CxwHfNn0CRlkPdv9fEUAXfZkGQPdP5e1ppIaO2KYE0sUov/zzp9hPTMMsTMHl4dcIbb+pHCQ==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [win32]
+
+ '@oxc-parser/binding-win32-x64-msvc@0.95.0':
+ resolution: {integrity: sha512-BQpgl7rDjFvCIHudmUR0dCwc4ylBYZl4CPVinlD3NhkMif4WD5dADckoo5ES/KOpFyvwcbKZX+grP63cjHi26g==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [win32]
+
+ '@oxc-project/types@0.95.0':
+ resolution: {integrity: sha512-vACy7vhpMPhjEJhULNxrdR0D943TkA/MigMpJCHmBHvMXxRStRi/dPtTlfQ3uDwWSzRpT8z+7ImjZVf8JWBocQ==}
+
'@parcel/watcher-android-arm64@2.5.1':
resolution: {integrity: sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==}
engines: {node: '>= 10.0.0'}
@@ -2683,8 +2790,8 @@ packages:
resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==}
engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
- '@playwright/test@1.55.1':
- resolution: {integrity: sha512-IVAh/nOJaw6W9g+RJVlIQJ6gSiER+ae6mKQ5CX1bERzQgbC1VSeBlwdvczT7pxb0GWiyrxH4TGKbMfDb4Sq/ig==}
+ '@playwright/test@1.56.1':
+ resolution: {integrity: sha512-vSMYtL/zOcFpvJCW71Q/OEGQb7KYBPAdKh35WNSkaZA75JlAO8ED8UN6GUNTm3drWomcbcqRPFqQbLae8yBTdg==}
engines: {node: '>=18'}
hasBin: true
@@ -3034,6 +3141,27 @@ packages:
resolution: {integrity: sha512-Nqc90v4lWCXyakD6xNyNACBJNJ0tNCwj2WNk/7ivyacYHxiITVgmLUFXTBOeCdy79iz6HtN9Y31uw/jbLrdOAg==}
engines: {node: '>=20.0.0'}
+ '@shikijs/core@3.13.0':
+ resolution: {integrity: sha512-3P8rGsg2Eh2qIHekwuQjzWhKI4jV97PhvYjYUzGqjvJfqdQPz+nMlfWahU24GZAyW1FxFI1sYjyhfh5CoLmIUA==}
+
+ '@shikijs/engine-javascript@3.13.0':
+ resolution: {integrity: sha512-Ty7xv32XCp8u0eQt8rItpMs6rU9Ki6LJ1dQOW3V/56PKDcpvfHPnYFbsx5FFUP2Yim34m/UkazidamMNVR4vKg==}
+
+ '@shikijs/engine-oniguruma@3.13.0':
+ resolution: {integrity: sha512-O42rBGr4UDSlhT2ZFMxqM7QzIU+IcpoTMzb3W7AlziI1ZF7R8eS2M0yt5Ry35nnnTX/LTLXFPUjRFCIW+Operg==}
+
+ '@shikijs/langs@3.13.0':
+ resolution: {integrity: sha512-672c3WAETDYHwrRP0yLy3W1QYB89Hbpj+pO4KhxK6FzIrDI2FoEXNiNCut6BQmEApYLfuYfpgOZaqbY+E9b8wQ==}
+
+ '@shikijs/themes@3.13.0':
+ resolution: {integrity: sha512-Vxw1Nm1/Od8jyA7QuAenaV78BG2nSr3/gCGdBkLpfLscddCkzkL36Q5b67SrLLfvAJTOUzW39x4FHVCFriPVgg==}
+
+ '@shikijs/types@3.13.0':
+ resolution: {integrity: sha512-oM9P+NCFri/mmQ8LoFGVfVyemm5Hi27330zuOBp0annwJdKH1kOLndw3zCtAVDehPLg9fKqoEx3Ht/wNZxolfw==}
+
+ '@shikijs/vscode-textmate@10.0.2':
+ resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==}
+
'@sinclair/typebox@0.34.37':
resolution: {integrity: sha512-2TRuQVgQYfy+EzHRTIvkhv2ADEouJ2xNS/Vq+W5EuuewBdOrvATvljZTxHWZSTYr2sTjTHpGvucaGAt67S2akw==}
@@ -3144,6 +3272,9 @@ packages:
peerDependencies:
solid-js: ^1.6.12
+ '@standard-schema/spec@1.0.0':
+ resolution: {integrity: sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==}
+
'@stylistic/eslint-plugin-js@2.1.0':
resolution: {integrity: sha512-gdXUjGNSsnY6nPyqxu6lmDTtVrwCOjun4x8PUn0x04d5ucLI74N3MT1Q0UhdcOR9No3bo5PGDyBgXK+KmD787A==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -3179,65 +3310,65 @@ packages:
'@swc/helpers@0.5.17':
resolution: {integrity: sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==}
- '@tailwindcss/node@4.1.13':
- resolution: {integrity: sha512-eq3ouolC1oEFOAvOMOBAmfCIqZBJuvWvvYWh5h5iOYfe1HFC6+GZ6EIL0JdM3/niGRJmnrOc+8gl9/HGUaaptw==}
+ '@tailwindcss/node@4.1.14':
+ resolution: {integrity: sha512-hpz+8vFk3Ic2xssIA3e01R6jkmsAhvkQdXlEbRTk6S10xDAtiQiM3FyvZVGsucefq764euO/b8WUW9ysLdThHw==}
- '@tailwindcss/oxide-android-arm64@4.1.13':
- resolution: {integrity: sha512-BrpTrVYyejbgGo57yc8ieE+D6VT9GOgnNdmh5Sac6+t0m+v+sKQevpFVpwX3pBrM2qKrQwJ0c5eDbtjouY/+ew==}
+ '@tailwindcss/oxide-android-arm64@4.1.14':
+ resolution: {integrity: sha512-a94ifZrGwMvbdeAxWoSuGcIl6/DOP5cdxagid7xJv6bwFp3oebp7y2ImYsnZBMTwjn5Ev5xESvS3FFYUGgPODQ==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [android]
- '@tailwindcss/oxide-darwin-arm64@4.1.13':
- resolution: {integrity: sha512-YP+Jksc4U0KHcu76UhRDHq9bx4qtBftp9ShK/7UGfq0wpaP96YVnnjFnj3ZFrUAjc5iECzODl/Ts0AN7ZPOANQ==}
+ '@tailwindcss/oxide-darwin-arm64@4.1.14':
+ resolution: {integrity: sha512-HkFP/CqfSh09xCnrPJA7jud7hij5ahKyWomrC3oiO2U9i0UjP17o9pJbxUN0IJ471GTQQmzwhp0DEcpbp4MZTA==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [darwin]
- '@tailwindcss/oxide-darwin-x64@4.1.13':
- resolution: {integrity: sha512-aAJ3bbwrn/PQHDxCto9sxwQfT30PzyYJFG0u/BWZGeVXi5Hx6uuUOQEI2Fa43qvmUjTRQNZnGqe9t0Zntexeuw==}
+ '@tailwindcss/oxide-darwin-x64@4.1.14':
+ resolution: {integrity: sha512-eVNaWmCgdLf5iv6Qd3s7JI5SEFBFRtfm6W0mphJYXgvnDEAZ5sZzqmI06bK6xo0IErDHdTA5/t7d4eTfWbWOFw==}
engines: {node: '>= 10'}
cpu: [x64]
os: [darwin]
- '@tailwindcss/oxide-freebsd-x64@4.1.13':
- resolution: {integrity: sha512-Wt8KvASHwSXhKE/dJLCCWcTSVmBj3xhVhp/aF3RpAhGeZ3sVo7+NTfgiN8Vey/Fi8prRClDs6/f0KXPDTZE6nQ==}
+ '@tailwindcss/oxide-freebsd-x64@4.1.14':
+ resolution: {integrity: sha512-QWLoRXNikEuqtNb0dhQN6wsSVVjX6dmUFzuuiL09ZeXju25dsei2uIPl71y2Ic6QbNBsB4scwBoFnlBfabHkEw==}
engines: {node: '>= 10'}
cpu: [x64]
os: [freebsd]
- '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.13':
- resolution: {integrity: sha512-mbVbcAsW3Gkm2MGwA93eLtWrwajz91aXZCNSkGTx/R5eb6KpKD5q8Ueckkh9YNboU8RH7jiv+ol/I7ZyQ9H7Bw==}
+ '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.14':
+ resolution: {integrity: sha512-VB4gjQni9+F0VCASU+L8zSIyjrLLsy03sjcR3bM0V2g4SNamo0FakZFKyUQ96ZVwGK4CaJsc9zd/obQy74o0Fw==}
engines: {node: '>= 10'}
cpu: [arm]
os: [linux]
- '@tailwindcss/oxide-linux-arm64-gnu@4.1.13':
- resolution: {integrity: sha512-wdtfkmpXiwej/yoAkrCP2DNzRXCALq9NVLgLELgLim1QpSfhQM5+ZxQQF8fkOiEpuNoKLp4nKZ6RC4kmeFH0HQ==}
+ '@tailwindcss/oxide-linux-arm64-gnu@4.1.14':
+ resolution: {integrity: sha512-qaEy0dIZ6d9vyLnmeg24yzA8XuEAD9WjpM5nIM1sUgQ/Zv7cVkharPDQcmm/t/TvXoKo/0knI3me3AGfdx6w1w==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
- '@tailwindcss/oxide-linux-arm64-musl@4.1.13':
- resolution: {integrity: sha512-hZQrmtLdhyqzXHB7mkXfq0IYbxegaqTmfa1p9MBj72WPoDD3oNOh1Lnxf6xZLY9C3OV6qiCYkO1i/LrzEdW2mg==}
+ '@tailwindcss/oxide-linux-arm64-musl@4.1.14':
+ resolution: {integrity: sha512-ISZjT44s59O8xKsPEIesiIydMG/sCXoMBCqsphDm/WcbnuWLxxb+GcvSIIA5NjUw6F8Tex7s5/LM2yDy8RqYBQ==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
- '@tailwindcss/oxide-linux-x64-gnu@4.1.13':
- resolution: {integrity: sha512-uaZTYWxSXyMWDJZNY1Ul7XkJTCBRFZ5Fo6wtjrgBKzZLoJNrG+WderJwAjPzuNZOnmdrVg260DKwXCFtJ/hWRQ==}
+ '@tailwindcss/oxide-linux-x64-gnu@4.1.14':
+ resolution: {integrity: sha512-02c6JhLPJj10L2caH4U0zF8Hji4dOeahmuMl23stk0MU1wfd1OraE7rOloidSF8W5JTHkFdVo/O7uRUJJnUAJg==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
- '@tailwindcss/oxide-linux-x64-musl@4.1.13':
- resolution: {integrity: sha512-oXiPj5mi4Hdn50v5RdnuuIms0PVPI/EG4fxAfFiIKQh5TgQgX7oSuDWntHW7WNIi/yVLAiS+CRGW4RkoGSSgVQ==}
+ '@tailwindcss/oxide-linux-x64-musl@4.1.14':
+ resolution: {integrity: sha512-TNGeLiN1XS66kQhxHG/7wMeQDOoL0S33x9BgmydbrWAb9Qw0KYdd8o1ifx4HOGDWhVmJ+Ul+JQ7lyknQFilO3Q==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
- '@tailwindcss/oxide-wasm32-wasi@4.1.13':
- resolution: {integrity: sha512-+LC2nNtPovtrDwBc/nqnIKYh/W2+R69FA0hgoeOn64BdCX522u19ryLh3Vf3F8W49XBcMIxSe665kwy21FkhvA==}
+ '@tailwindcss/oxide-wasm32-wasi@4.1.14':
+ resolution: {integrity: sha512-uZYAsaW/jS/IYkd6EWPJKW/NlPNSkWkBlaeVBi/WsFQNP05/bzkebUL8FH1pdsqx4f2fH/bWFcUABOM9nfiJkQ==}
engines: {node: '>=14.0.0'}
cpu: [wasm32]
bundledDependencies:
@@ -3248,33 +3379,33 @@ packages:
- '@emnapi/wasi-threads'
- tslib
- '@tailwindcss/oxide-win32-arm64-msvc@4.1.13':
- resolution: {integrity: sha512-dziTNeQXtoQ2KBXmrjCxsuPk3F3CQ/yb7ZNZNA+UkNTeiTGgfeh+gH5Pi7mRncVgcPD2xgHvkFCh/MhZWSgyQg==}
+ '@tailwindcss/oxide-win32-arm64-msvc@4.1.14':
+ resolution: {integrity: sha512-Az0RnnkcvRqsuoLH2Z4n3JfAef0wElgzHD5Aky/e+0tBUxUhIeIqFBTMNQvmMRSP15fWwmvjBxZ3Q8RhsDnxAA==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [win32]
- '@tailwindcss/oxide-win32-x64-msvc@4.1.13':
- resolution: {integrity: sha512-3+LKesjXydTkHk5zXX01b5KMzLV1xl2mcktBJkje7rhFUpUlYJy7IMOLqjIRQncLTa1WZZiFY/foAeB5nmaiTw==}
+ '@tailwindcss/oxide-win32-x64-msvc@4.1.14':
+ resolution: {integrity: sha512-ttblVGHgf68kEE4om1n/n44I0yGPkCPbLsqzjvybhpwa6mKKtgFfAzy6btc3HRmuW7nHe0OOrSeNP9sQmmH9XA==}
engines: {node: '>= 10'}
cpu: [x64]
os: [win32]
- '@tailwindcss/oxide@4.1.13':
- resolution: {integrity: sha512-CPgsM1IpGRa880sMbYmG1s4xhAy3xEt1QULgTJGQmZUeNgXFR7s1YxYygmJyBGtou4SyEosGAGEeYqY7R53bIA==}
+ '@tailwindcss/oxide@4.1.14':
+ resolution: {integrity: sha512-23yx+VUbBwCg2x5XWdB8+1lkPajzLmALEfMb51zZUBYaYVPDQvBSD/WYDqiVyBIo2BZFa3yw1Rpy3G2Jp+K0dw==}
engines: {node: '>= 10'}
- '@tailwindcss/vite@4.1.13':
- resolution: {integrity: sha512-0PmqLQ010N58SbMTJ7BVJ4I2xopiQn/5i6nlb4JmxzQf8zcS5+m2Cv6tqh+sfDwtIdjoEnOvwsGQ1hkUi8QEHQ==}
+ '@tailwindcss/vite@4.1.14':
+ resolution: {integrity: sha512-BoFUoU0XqgCUS1UXWhmDJroKKhNXeDzD7/XwabjkDIAbMnc4ULn5e2FuEuBbhZ6ENZoSYzKlzvZ44Yr6EUDUSA==}
peerDependencies:
vite: ^5.2.0 || ^6 || ^7
- '@testing-library/dom@10.4.0':
- resolution: {integrity: sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==}
+ '@testing-library/dom@10.4.1':
+ resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==}
engines: {node: '>=18'}
- '@testing-library/jest-dom@6.9.0':
- resolution: {integrity: sha512-QHdxYMJ0YPGKYofMc6zYvo7LOViVhdc6nPg/OtM2cf9MQrwEcTxFCs7d/GJ5eSyPkHzOiBkc/KfLdFJBHzldtQ==}
+ '@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.0':
@@ -3292,6 +3423,12 @@ packages:
'@types/react-dom':
optional: true
+ '@testing-library/user-event@13.5.0':
+ resolution: {integrity: sha512-5Kwtbo3Y/NowpkbRuSepbyMFkZmHgD+vPzYB/RJ4oxt5Gj/avFFBYjhw27cqSVPVw/3a67NK1PbiIr9k4Gwmdg==}
+ engines: {node: '>=10', npm: '>=6'}
+ peerDependencies:
+ '@testing-library/dom': '>=7.21.4'
+
'@testing-library/user-event@14.6.1':
resolution: {integrity: sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw==}
engines: {node: '>=12', npm: '>=6'}
@@ -3375,6 +3512,9 @@ packages:
'@types/estree@1.0.8':
resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==}
+ '@types/hast@3.0.4':
+ resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==}
+
'@types/istanbul-lib-coverage@2.0.6':
resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==}
@@ -3402,14 +3542,17 @@ packages:
'@types/mdast@3.0.15':
resolution: {integrity: sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==}
+ '@types/mdast@4.0.4':
+ resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==}
+
'@types/node@12.20.55':
resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==}
- '@types/node@20.19.21':
- resolution: {integrity: sha512-CsGG2P3I5y48RPMfprQGfy4JPRZ6csfC3ltBZSRItG3ngggmNY/qs2uZKp4p9VbrpqNNSMzUZNFZKzgOGnd/VA==}
+ '@types/node@20.19.22':
+ resolution: {integrity: sha512-hRnu+5qggKDSyWHlnmThnUqg62l29Aj/6vcYgUaSFL9oc7DVjeWEQN3PRgdSc6F8d9QRMWkf36CLMch1Do/+RQ==}
- '@types/node@24.6.0':
- resolution: {integrity: sha512-F1CBxgqwOMc4GKJ7eY22hWhBVQuMYTtqI8L0FcszYcpYX0fzfDGpez22Xau8Mgm7O9fI+zA/TYIdq3tGWfweBA==}
+ '@types/node@24.8.1':
+ resolution: {integrity: sha512-alv65KGRadQVfVcG69MuB4IzdYVpRwMG/mq8KWOaoOdyY617P5ivaDiMCGOFDWD2sAn5Q0mR3mRtUOgm99hL9Q==}
'@types/normalize-package-data@2.4.4':
resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==}
@@ -3437,11 +3580,14 @@ packages:
'@types/unist@2.0.10':
resolution: {integrity: sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==}
+ '@types/unist@3.0.3':
+ resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==}
+
'@types/vscode-webview@1.57.5':
resolution: {integrity: sha512-iBAUYNYkz+uk1kdsq05fEcoh8gJmwT3lqqFPN7MGyjQ3HVloViMdo7ZJ8DFIP8WOK74PjOEilosqAyxV2iUFUw==}
- '@types/vscode@1.104.0':
- resolution: {integrity: sha512-0KwoU2rZ2ecsTGFxo4K1+f+AErRsYW0fsp6A0zufzGuhyczc2IoKqYqcwXidKXmy2u8YB2GsYsOtiI9Izx3Tig==}
+ '@types/vscode@1.105.0':
+ resolution: {integrity: sha512-Lotk3CTFlGZN8ray4VxJE7axIyLZZETQJVWi/lYoUVQuqfRxlQhVOfoejsD2V3dVXPSbS15ov5ZyowMAzgUqcw==}
'@types/whatwg-mimetype@3.0.2':
resolution: {integrity: sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA==}
@@ -3627,8 +3773,8 @@ packages:
'@vitest/expect@3.2.4':
resolution: {integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==}
- '@vitest/expect@4.0.0-beta.8':
- resolution: {integrity: sha512-40DZ7nl5AkASkDNaVR7TqsbeJCs5D+dyQNM5cIvgjG3KK+ATeWxtXJbmRNqgdbq+FL3v/pchnrJM1R9BFkTdUQ==}
+ '@vitest/expect@4.0.0-beta.18':
+ resolution: {integrity: sha512-dP38ctyRhGj4DTz4azK7sKR7BULMdVdgmR4Flzmul9wE3GdKUSr4zNd2RVNHhrb7l0NK0GN5/kRquaQmv9krGQ==}
'@vitest/mocker@2.1.8':
resolution: {integrity: sha512-7guJ/47I6uqfttp33mgo6ga5Gr1VnL58rcqYKyShoRK9ebu8T5Rs6HN3s1NABiBeVTdWNrwUMcHH54uXZBN4zA==}
@@ -3652,8 +3798,8 @@ packages:
vite:
optional: true
- '@vitest/mocker@4.0.0-beta.8':
- resolution: {integrity: sha512-a5ynR/Fsrciuq17i8lzS5NH3ICxwFZMlQ4bXPzGV+KlIcVHu20a/8q6KekqUaVBxCbmohORLFXFx9IptHS9gXA==}
+ '@vitest/mocker@4.0.0-beta.18':
+ resolution: {integrity: sha512-vwvvqj4zNaV+uQSBJHhGP72UL4fluU2gLI1Q+hT4e4ruJOF5TWD/UuWnWCpzHjGotfDTNSztypYkZ3ZottPFvA==}
peerDependencies:
msw: ^2.4.9
vite: ^6.0.0 || ^7.0.0-0
@@ -3672,8 +3818,8 @@ packages:
'@vitest/pretty-format@3.2.4':
resolution: {integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==}
- '@vitest/pretty-format@4.0.0-beta.8':
- resolution: {integrity: sha512-sr5HPeeRff4gTpDwI2Kvz8dS2CmDCCZ1PRu3IOeLTcSJjhEWmk3IJILjqaA8yyj+QzWjnqAxr2rmZNpO0h/5Vw==}
+ '@vitest/pretty-format@4.0.0-beta.18':
+ resolution: {integrity: sha512-LzgQxcQ6QxhjDfYGMT/fFH3hdzJaq2KsG0R2CGkhYUNFvAml2nvFAxzQKYtxDDk0olOxk3j29QPvv3j8D4hONg==}
'@vitest/runner@2.1.8':
resolution: {integrity: sha512-17ub8vQstRnRlIU5k50bG+QOMLHRhYPAna5tw8tYbj+jzjcspnwnwtPtiOlkuKC4+ixDPTuLZiqiWWQ2PSXHVg==}
@@ -3681,8 +3827,8 @@ packages:
'@vitest/runner@3.2.4':
resolution: {integrity: sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==}
- '@vitest/runner@4.0.0-beta.8':
- resolution: {integrity: sha512-m7jrT+KMEgONclBI7y3ptUD+/uhRzzHLblws84fo+WesCjS8WT8q7RoPMgqymj5kmzIF5sTh6NOvrNEE5LaLCQ==}
+ '@vitest/runner@4.0.0-beta.18':
+ resolution: {integrity: sha512-HpEaHsxNKJYeKApkxbrGT6OZA9Ty+BLXIc4rxo6xzo+f4zlUGluy4RjQs9GQIzEpQSPP5ehUIcUZbOi7thB49g==}
'@vitest/snapshot@2.1.8':
resolution: {integrity: sha512-20T7xRFbmnkfcmgVEz+z3AU/3b0cEzZOt/zmnvZEctg64/QZbSDJEVm9fLnnlSi74KibmRsO9/Qabi+t0vCRPg==}
@@ -3690,8 +3836,8 @@ packages:
'@vitest/snapshot@3.2.4':
resolution: {integrity: sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==}
- '@vitest/snapshot@4.0.0-beta.8':
- resolution: {integrity: sha512-2hzc/ksGlZ8Rcg11VD/AhTwSaPEsdtrNA+TCV4w6tuZ7I2X+XJXimfk/Cehz5zMgfFuV8tFmGimb/BpyIbNiMg==}
+ '@vitest/snapshot@4.0.0-beta.18':
+ resolution: {integrity: sha512-ruWnM+5xVR5mhiTW5c66JRwxni6riPxupaXNPqdkOHzBuxxz79Cf56yzuYapT/TSRHVwkIyldfKLcZTY18CWig==}
'@vitest/spy@2.1.8':
resolution: {integrity: sha512-5swjf2q95gXeYPevtW0BLk6H8+bPlMb4Vw/9Em4hFxDcaOxS+e0LOX4yqNxoHzMR2akEB2xfpnWUzkZokmgWDg==}
@@ -3699,8 +3845,8 @@ packages:
'@vitest/spy@3.2.4':
resolution: {integrity: sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==}
- '@vitest/spy@4.0.0-beta.8':
- resolution: {integrity: sha512-WfHF35GCf5xx3B1oRrhWMVAfcBBYO4WHAYLbeeaZ1ZSW5/VBXJ/M37bLxRRKnXcgffwcsWA7xpjWnL0dQ1q5NA==}
+ '@vitest/spy@4.0.0-beta.18':
+ resolution: {integrity: sha512-KHxVrn/e1PhcylP3waDajDZ7o5ut9BnN+QDCgz6uMev1cqVHLE1EBaz8qUcxaRH6qFNKcTm8T4x+FIIYSGS/xw==}
'@vitest/utils@2.1.8':
resolution: {integrity: sha512-dwSoui6djdwbfFmIgbIjX2ZhIoG7Ex/+xpxyiEgIGzjliY8xGkcpITKTlp6B4MgtGkF2ilvm97cPM96XZaAgcA==}
@@ -3708,14 +3854,14 @@ packages:
'@vitest/utils@3.2.4':
resolution: {integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==}
- '@vitest/utils@4.0.0-beta.8':
- resolution: {integrity: sha512-+eV3yrDooGMnHHVQ1aqzPJIBlxEsaQg/5BVFRSkbBgfiKqM9HZbqYK736s0D8tfdMLOjeB+7u7Tw0emd/h3MlQ==}
+ '@vitest/utils@4.0.0-beta.18':
+ resolution: {integrity: sha512-Z7r82xwG8G6J755DqWpoP/XEuKMhxVFlIPVunD609iH8wjLJ6VD+vd9cojalhrW/tqHfdnaBpS+hxDLwSrfw3Q==}
- '@vscode/codicons@0.0.40':
- resolution: {integrity: sha512-R8sEDXthD86JHsk3xERrMcTN6sMovbk1AXYB5/tGoEYCE8DWwya6al5VLrAmQYXC1bQhUHIfHALj8ijQUs11cQ==}
+ '@vscode/codicons@0.0.41':
+ resolution: {integrity: sha512-v6/8nx76zau3Joxjzi3eN/FVw+7jKBq4j7LTZY5FhFhq2g0OoFebZ3vRZbv/pUopGpbCnJJ4FOz+NzbjVsmoiw==}
- '@vscode/extension-telemetry@1.0.0':
- resolution: {integrity: sha512-vaTZE65zigWwSWYB6yaZUAyVC/Ux+6U82hnzy/ejuS/KpFifO+0oORNd5yAoPeIRnYjvllM6ES3YlX4K5tUuww==}
+ '@vscode/extension-telemetry@1.1.0':
+ resolution: {integrity: sha512-y3cFCDell/xVn3b2/FdpJSwpspfUzBvVtjAQnD94Z38RXHCsYRZXJOJLZNuFxFgcSihjYZNnL8VPgOzWNiE9/g==}
engines: {vscode: ^1.75.0}
'@vscode/vsce-sign-alpine-arm64@2.0.6':
@@ -4085,15 +4231,18 @@ packages:
caniuse-lite@1.0.30001735:
resolution: {integrity: sha512-EV/laoX7Wq2J9TQlyIXRxTJqIw4sxfXS4OYgudGxBYRuTv0q7AM6yMEpU/Vo1I94thg9U6EZ2NfZx9GJq83u7w==}
- caniuse-lite@1.0.30001746:
- resolution: {integrity: sha512-eA7Ys/DGw+pnkWWSE/id29f2IcPHVoE8wxtvE5JdvD2V28VTDPy1yEeo11Guz0sJ4ZeGRcm3uaTcAqK1LXaphA==}
+ caniuse-lite@1.0.30001751:
+ resolution: {integrity: sha512-A0QJhug0Ly64Ii3eIqHu5X51ebln3k4yTUkY1j8drqpWHVreg/VLijN48cZ1bYPiqOQuqpkIKnzr/Ul8V+p6Cw==}
+
+ ccount@2.0.1:
+ resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==}
chai@5.2.0:
resolution: {integrity: sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==}
engines: {node: '>=12'}
- chai@5.2.1:
- resolution: {integrity: sha512-5nFxhUrX0PqtyogoYOA8IPswy5sZFTOsBFl/9bNsmDLgsxYTzSZQJDPppDnZPTQbzSEm0hqGjWPzRemQCYbD6A==}
+ chai@6.2.0:
+ resolution: {integrity: sha512-aUTnJc/JipRzJrNADXVvpVqi6CO0dn3nx4EVPxijri+fj3LUUDyZQOgVeW54Ob3Y1Xh9Iz8f+CgaCl8v0mn9bA==}
engines: {node: '>=18'}
chalk@4.1.2:
@@ -4108,9 +4257,15 @@ packages:
resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==}
engines: {node: '>=10'}
+ character-entities-html4@2.1.0:
+ resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==}
+
character-entities-legacy@1.1.4:
resolution: {integrity: sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==}
+ character-entities-legacy@3.0.0:
+ resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==}
+
character-entities@1.2.4:
resolution: {integrity: sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==}
@@ -4204,6 +4359,9 @@ packages:
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
engines: {node: '>= 0.8'}
+ comma-separated-tokens@2.0.3:
+ resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==}
+
commander@12.1.0:
resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==}
engines: {node: '>=18'}
@@ -4391,10 +4549,17 @@ packages:
resolution: {integrity: sha512-ecqj/sy1jcK1uWrwpR67UhYrIFQ+5WlGxth34WquCbamhFA6hkkwiu37o6J5xCHdo1oixJRfVRw+ywV+Hq/0Aw==}
engines: {node: '>=8'}
+ detect-libc@2.1.2:
+ resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
+ engines: {node: '>=8'}
+
detect-newline@3.1.0:
resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==}
engines: {node: '>=8'}
+ devlop@1.1.0:
+ resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==}
+
didyoumean@1.2.2:
resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==}
@@ -4526,8 +4691,8 @@ packages:
engines: {node: '>=12'}
hasBin: true
- esbuild@0.25.10:
- resolution: {integrity: sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ==}
+ esbuild@0.25.11:
+ resolution: {integrity: sha512-KohQwyzrKTQmhXDW1PjCv3Tyspn9n5GcY2RTDqeORIdIJY8yKIF7sTSopFmn/wpMPW4rdPXI0UE5LJLuq3bx0Q==}
engines: {node: '>=18'}
hasBin: true
@@ -4733,8 +4898,8 @@ packages:
resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- eslint@9.36.0:
- resolution: {integrity: sha512-hB4FIzXovouYzwzECDcUkJ4OcfOEkXTv2zRY6B9bkwjx/cprAq0uvm1nl7zvQ0/TsUk0zQiN4uPfJpB9m+rPMQ==}
+ eslint@9.38.0:
+ resolution: {integrity: sha512-t5aPOpmtJcZcz5UJyY2GbvpDlsK5E8JqRqoKtfiKE3cNh437KIqfJr3A3AKf5k64NPx6d0G3dno6XDY05PqPtw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
hasBin: true
peerDependencies:
@@ -5048,8 +5213,8 @@ packages:
resolution: {integrity: sha512-yiaVI0Da/tGrBD6QwmXkJZH9RPW1/TCxqadbwkp0MgwRTTDNyBC09Ow+nppVLhbG4Ws2Z6t29Vzbbd6C0y7LCQ==}
engines: {node: '>=16.0.0'}
- happy-dom@20.0.0:
- resolution: {integrity: sha512-GkWnwIFxVGCf2raNrxImLo397RdGhLapj5cT3R2PT7FwL62Ze1DROhzmYW7+J3p9105DYMVenEejEbnq5wA37w==}
+ happy-dom@20.0.8:
+ resolution: {integrity: sha512-TlYaNQNtzsZ97rNMBAm8U+e2cUQXNithgfCizkDgc11lgmN4j9CKMhO3FPGKWQYPwwkFcPpoXYF/CqEPLgzfOg==}
engines: {node: '>=20.0.0'}
harmony-reflect@1.6.2:
@@ -5078,6 +5243,12 @@ packages:
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
engines: {node: '>= 0.4'}
+ hast-util-to-html@9.0.5:
+ resolution: {integrity: sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==}
+
+ hast-util-whitespace@3.0.0:
+ resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==}
+
hosted-git-info@2.8.9:
resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==}
@@ -5099,6 +5270,9 @@ packages:
html-escaper@2.0.2:
resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==}
+ html-void-elements@3.0.0:
+ resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==}
+
htmlparser2@10.0.0:
resolution: {integrity: sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g==}
@@ -5496,8 +5670,8 @@ packages:
resolution: {integrity: sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==}
hasBin: true
- jiti@2.6.0:
- resolution: {integrity: sha512-VXe6RjJkBPj0ohtqaO8vSWP3ZhAKo66fKrFNCll4BTcwljPLz03pCbaNKfzGP5MbrCYcbJ7v0nOYYwUzTEIdXQ==}
+ jiti@2.6.1:
+ resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==}
hasBin: true
joycon@3.1.1:
@@ -5597,8 +5771,8 @@ packages:
keyv@4.5.4:
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
- less@4.4.1:
- resolution: {integrity: sha512-X9HKyiXPi0f/ed0XhgUlBeFfxrlDP3xR4M7768Zl+WXLUViuL9AOPPJP4nCV0tgRWvTYvpNmN0SFhZOQzy16PA==}
+ less@4.4.2:
+ resolution: {integrity: sha512-j1n1IuTX1VQjIy3tT7cyGbX7nvQOsFLoIqobZv4ttI5axP923gA44zUj6miiA6R5Aoms4sEGVIIcucXUbRI14g==}
engines: {node: '>=14'}
hasBin: true
@@ -5754,9 +5928,6 @@ packages:
loupe@3.1.4:
resolution: {integrity: sha512-wJzkKwJrheKtknCOKNEtDK4iqg/MxmZheEMtSTYvnzRdEYaZzmgH976nenp8WdJRdx5Vc1X/9MO0Oszl6ezeXg==}
- loupe@3.2.0:
- resolution: {integrity: sha512-2NCfZcT5VGVNX9mSZIxLRkEAegDGBpuQZBy13desuHeVORmBDyAET4TkJr4SjqQy3A8JDofMN6LpkK8Xcm/dlw==}
-
lru-cache@10.4.3:
resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
@@ -5771,8 +5942,8 @@ packages:
resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==}
engines: {node: '>=10'}
- lucide-solid@0.544.0:
- resolution: {integrity: sha512-BQ4hysggShgAFE66U2AStAyOdD0U2Oraec1P35+m5b+SDuh2mWf8kTGbtMmZEmy0MKKQoKP5PEU77FrADbAQTw==}
+ lucide-solid@0.546.0:
+ resolution: {integrity: sha512-zJX9x7rlOwqsB6eNMWOrzS+vuvZThPFksPVryiXMmC6QGAD6vRihEZHe+r4JSppAGhOaPRBnMhg8XNZ/qLslvA==}
peerDependencies:
solid-js: ^1.4.7
@@ -5811,6 +5982,9 @@ packages:
mdast-util-from-markdown@0.8.5:
resolution: {integrity: sha512-2hkTXtYYnr+NubD/g6KGBS/0mFmBcifAsI0yIWRiRo0PjVs6SSOSOdtzbp6kSGnShDN6G5aWZpKQ2lWRy27mWQ==}
+ mdast-util-to-hast@13.2.0:
+ resolution: {integrity: sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==}
+
mdast-util-to-string@2.0.0:
resolution: {integrity: sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==}
@@ -5828,6 +6002,21 @@ packages:
resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
engines: {node: '>= 8'}
+ micromark-util-character@2.1.1:
+ resolution: {integrity: sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==}
+
+ micromark-util-encode@2.0.1:
+ resolution: {integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==}
+
+ micromark-util-sanitize-uri@2.0.1:
+ resolution: {integrity: sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==}
+
+ micromark-util-symbol@2.0.1:
+ resolution: {integrity: sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==}
+
+ micromark-util-types@2.0.2:
+ resolution: {integrity: sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==}
+
micromark@2.11.4:
resolution: {integrity: sha512-+WoovN/ppKolQOFIAajxi7Lu9kInbPxFuTBVEavFcL8eAfVstoc5MocPmqBeAdBOJV00uaVjegzH4+MA0DN/uA==}
@@ -5935,8 +6124,8 @@ packages:
engines: {node: '>= 4.4.x'}
hasBin: true
- next@15.5.4:
- resolution: {integrity: sha512-xH4Yjhb82sFYQfY3vbkJfgSDgXvBB6a8xPs9i35k6oZJRoQRihZH+4s9Yo2qsWpzBmZ3lPXaJ2KPXLfkvW4LnA==}
+ next@15.5.6:
+ resolution: {integrity: sha512-zTxsnI3LQo3c9HSdSf91O1jMNsEzIXDShXd4wVdg9y5shwLqBXi4ZtUUJyB86KGVSJLZx0PFONvO54aheGX8QQ==}
engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0}
hasBin: true
peerDependencies:
@@ -6031,6 +6220,12 @@ packages:
resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
engines: {node: '>=6'}
+ oniguruma-parser@0.12.1:
+ resolution: {integrity: sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w==}
+
+ oniguruma-to-es@4.3.3:
+ resolution: {integrity: sha512-rPiZhzC3wXwE59YQMRDodUwwT9FZ9nNBwQQfsd1wfdtlKEyCdRV0avrTcSZ5xlIvGRVPd/cx6ZN45ECmS39xvg==}
+
open@10.2.0:
resolution: {integrity: sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==}
engines: {node: '>=18'}
@@ -6047,6 +6242,10 @@ packages:
engines: {node: '>= 20'}
hasBin: true
+ oxc-parser@0.95.0:
+ resolution: {integrity: sha512-Te8fE/SmiiKWIrwBwxz5Dod87uYvsbcZ9JAL5ylPg1DevyKgTkxCXnPEaewk1Su2qpfNmry5RHoN+NywWFCG+A==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+
p-filter@2.1.0:
resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==}
engines: {node: '>=8'}
@@ -6228,13 +6427,13 @@ packages:
pkg-types@1.3.1:
resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==}
- playwright-core@1.55.1:
- resolution: {integrity: sha512-Z6Mh9mkwX+zxSlHqdr5AOcJnfp+xUWLCt9uKV18fhzA8eyxUd8NUWzAjxUh55RZKSYwDGX0cfaySdhZJGMoJ+w==}
+ playwright-core@1.56.1:
+ resolution: {integrity: sha512-hutraynyn31F+Bifme+Ps9Vq59hKuUCz7H1kDOcBs+2oGguKkWTU50bBWrtz34OUWmIwpBTWDxaRPXrIXkgvmQ==}
engines: {node: '>=18'}
hasBin: true
- playwright@1.55.1:
- resolution: {integrity: sha512-cJW4Xd/G3v5ovXtJJ52MAOclqeac9S/aGGgRzLabuF8TnIb6xHvMzKIa6JmrRzUkeXJgfL1MhukP0NK6l39h3A==}
+ playwright@1.56.1:
+ resolution: {integrity: sha512-aFi5B0WovBHTEvpM3DzXTUaeN6eN0qWnTkKx4NQaH4Wvcmc153PdaY2UBdSYKaGYw+UyWXSVyxDUg5DoPEttjw==}
engines: {node: '>=18'}
hasBin: true
@@ -6342,6 +6541,9 @@ packages:
resolution: {integrity: sha512-4yf0QO/sllf/1zbZWYnvWw3NxCQwLXKzIj0G849LSufP15BXKM0rbD2Z3wVnkMfjdn/CB0Dpp444gYAACdsplg==}
engines: {node: '>=18'}
+ property-information@7.1.0:
+ resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==}
+
prr@1.0.1:
resolution: {integrity: sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==}
@@ -6445,6 +6647,15 @@ packages:
regenerate@1.4.2:
resolution: {integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==}
+ regex-recursion@6.0.2:
+ resolution: {integrity: sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==}
+
+ regex-utilities@2.3.0:
+ resolution: {integrity: sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==}
+
+ regex@6.0.1:
+ resolution: {integrity: sha512-uorlqlzAKjKQZ5P+kTJr3eeJGSVroLKoHmquUj4zHWuR+hEyNqlXsSKlYYF5F4NI6nl7tWCs0apKJ0lmfsXAPA==}
+
regexp-ast-analysis@0.7.1:
resolution: {integrity: sha512-sZuz1dYW/ZsfG17WSAG7eS85r5a0dDsvg+7BiiYR5o6lKCAtUrEwdmRmaGF6rwVj3LcmAeYkOWKEPlbPzN3Y3A==}
engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
@@ -6572,6 +6783,11 @@ packages:
engines: {node: '>=10'}
hasBin: true
+ semver@7.7.3:
+ resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==}
+ engines: {node: '>=10'}
+ hasBin: true
+
seroval-plugins@1.3.2:
resolution: {integrity: sha512-0QvCV2lM3aj/U3YozDiVwx9zpH0q8A60CTWIv4Jszj/givcudPb48B+rkU5D51NJ0pTpweGMttHjboPa9/zoIQ==}
engines: {node: '>=10'}
@@ -6597,6 +6813,9 @@ packages:
resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
engines: {node: '>=8'}
+ shiki@3.13.0:
+ resolution: {integrity: sha512-aZW4l8Og16CokuCLf8CF8kq+KK2yOygapU5m3+hoGw0Mdosc6fPitjM+ujYarppj5ZIKGyPDPP1vqmQhr+5/0g==}
+
side-channel-list@1.0.0:
resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==}
engines: {node: '>= 0.4'}
@@ -6686,6 +6905,9 @@ packages:
engines: {node: '>= 8'}
deprecated: The work that was done in this beta branch won't be included in future versions
+ space-separated-tokens@2.0.2:
+ resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==}
+
spawndamnit@3.0.1:
resolution: {integrity: sha512-MmnduQUuHCoFckZoWnXsTg7JaiLBJrKFj9UI2MbRPGaJeVpsLcVBu6P/IGZovziM/YBsellCmsprgNA+w0CzVg==}
@@ -6736,6 +6958,9 @@ packages:
string_decoder@1.3.0:
resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==}
+ stringify-entities@4.0.4:
+ resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==}
+
strip-ansi@6.0.1:
resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
engines: {node: '>=8'}
@@ -6856,8 +7081,11 @@ packages:
engines: {node: '>=14.0.0'}
hasBin: true
- tailwindcss@4.1.13:
- resolution: {integrity: sha512-i+zidfmTqtwquj4hMEwdjshYYgMbOrPzb9a0M3ZgNa0JMoZeFC6bxZvO8yr8ozS6ix2SDz0+mvryPeBs2TFE+w==}
+ tailwindcss@4.1.14:
+ resolution: {integrity: sha512-b7pCxjGO98LnxVkKjaZSDeNuljC4ueKUddjENJOADtubtdo8llTaJy7HwBMeLNSSo2N5QIAgklslK1+Ir8r6CA==}
+
+ tailwindcss@4.1.16:
+ resolution: {integrity: sha512-pONL5awpaQX4LN5eiv7moSiSPd/DLDzKVRJz8Q9PgzmAdd1R4307GQS2ZpfiN7ZmekdQrfhZZiSE5jkLR4WNaA==}
tapable@2.2.2:
resolution: {integrity: sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==}
@@ -6918,6 +7146,10 @@ packages:
resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==}
engines: {node: ^18.0.0 || >=20.0.0}
+ tinypool@2.0.0:
+ resolution: {integrity: sha512-/RX9RzeH2xU5ADE7n2Ykvmi9ED3FBGPAjw9u3zucrNNaEBIO0HPSYgL0NT7+3p147ojeSdaVu08F6hjpv31HJg==}
+ engines: {node: ^20.0.0 || >=22.0.0}
+
tinyrainbow@1.2.0:
resolution: {integrity: sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==}
engines: {node: '>=14.0.0'}
@@ -6926,6 +7158,10 @@ packages:
resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==}
engines: {node: '>=14.0.0'}
+ tinyrainbow@3.0.3:
+ resolution: {integrity: sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==}
+ engines: {node: '>=14.0.0'}
+
tinyspy@3.0.2:
resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==}
engines: {node: '>=14.0.0'}
@@ -6971,6 +7207,9 @@ packages:
resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==}
hasBin: true
+ trim-lines@3.0.1:
+ resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==}
+
ts-api-utils@1.3.0:
resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==}
engines: {node: '>=16'}
@@ -7061,8 +7300,8 @@ packages:
typed-rest-client@1.8.11:
resolution: {integrity: sha512-5UvfMpd1oelmUPRbbaVnq+rHP7ng2cE4qoQkQeAqxRL6PklkxsM0g32/HL0yfvruK6ojQ5x8EE+HF4YV6DtuCA==}
- typescript@5.9.2:
- resolution: {integrity: sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==}
+ typescript@5.9.3:
+ resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
engines: {node: '>=14.17'}
hasBin: true
@@ -7081,8 +7320,8 @@ packages:
undici-types@6.21.0:
resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
- undici-types@7.13.0:
- resolution: {integrity: sha512-Ov2Rr9Sx+fRgagJ5AX0qvItZG/JKKoBRAVITs1zk7IqZGTJUwgUr7qoYBpWwakpWilTZFM98rG/AFRocu10iIQ==}
+ undici-types@7.14.0:
+ resolution: {integrity: sha512-QQiYxHuyZ9gQUIrmPo3IA+hUl4KYk8uSA7cHrcKd/l3p1OTpZcM0Tbp9x7FAtXdAYhlasd60ncPpgu6ihG6TOA==}
undici@7.16.0:
resolution: {integrity: sha512-QEg3HPMll0o3t2ourKwOeUAZ159Kn9mx5pnzHRQO8+Wixmh88YdZRiIwat0iNzNNXn0yoEtXJqFpyW7eM8BV7g==}
@@ -7112,9 +7351,24 @@ packages:
resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==}
engines: {node: '>=18'}
+ unist-util-is@6.0.1:
+ resolution: {integrity: sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==}
+
+ unist-util-position@5.0.0:
+ resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==}
+
unist-util-stringify-position@2.0.3:
resolution: {integrity: sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==}
+ unist-util-stringify-position@4.0.0:
+ resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==}
+
+ unist-util-visit-parents@6.0.2:
+ resolution: {integrity: sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==}
+
+ unist-util-visit@5.0.0:
+ resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==}
+
universalify@0.1.2:
resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==}
engines: {node: '>= 4.0.0'}
@@ -7174,6 +7428,12 @@ packages:
resolution: {integrity: sha512-Ck0EJbAGxHwprkzFO966t4/5QkRuzh+/I1RxhLgUKKwEn+Cd8NwM60mE3AqBZg5gYODoXW0EFsQvbZjRlvdqbg==}
engines: {node: '>=4'}
+ vfile-message@4.0.3:
+ resolution: {integrity: sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==}
+
+ vfile@6.0.3:
+ resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==}
+
vite-node@2.1.8:
resolution: {integrity: sha512-uPAwSr57kYjAUux+8E2j0q0Fxpn8M9VoyfGiRI8Kfktz9NcYMCenwY5RnZxnF1WTu3TGiYipirIzacLL3VVGFg==}
engines: {node: ^18.0.0 || >=20.0.0}
@@ -7184,8 +7444,8 @@ packages:
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
hasBin: true
- vite-plugin-solid@2.11.8:
- resolution: {integrity: sha512-hFrCxBfv3B1BmFqnJF4JOCYpjrmi/zwyeKjcomQ0khh8HFyQ8SbuBWQ7zGojfrz6HUOBFrJBNySDi/JgAHytWg==}
+ vite-plugin-solid@2.11.9:
+ resolution: {integrity: sha512-bTA6p+bspXZsuulSd2y6aTzegF8xGaJYcq1Uyh/mv+W4DQtzCgL9nN6n2fsTaxp/dMk+ZHHKgGndlNeooqHLKw==}
peerDependencies:
'@testing-library/jest-dom': ^5.16.6 || ^5.17.0 || ^6.*
solid-js: ^1.7.2
@@ -7225,8 +7485,8 @@ packages:
terser:
optional: true
- vite@7.1.3:
- resolution: {integrity: sha512-OOUi5zjkDxYrKhTV3V7iKsoS37VUM7v40+HuwEmcrsf11Cdx9y3DIr2Px6liIcZFwt3XSRpQvFpL3WVy7ApkGw==}
+ vite@7.1.10:
+ resolution: {integrity: sha512-CmuvUBzVJ/e3HGxhg6cYk88NGgTnBoOo7ogtfJJ0fefUWAxN/WDSUa50o+oVBxuIhO8FoEZW0j2eW7sfjs5EtA==}
engines: {node: ^20.19.0 || >=22.12.0}
hasBin: true
peerDependencies:
@@ -7265,8 +7525,8 @@ packages:
yaml:
optional: true
- vite@7.1.7:
- resolution: {integrity: sha512-VbA8ScMvAISJNJVbRDTJdCwqQoAareR/wutevKanhR2/1EkoXVZVkkORaYm/tNVCjP/UDTKtcw3bAkwOUdedmA==}
+ vite@7.1.3:
+ resolution: {integrity: sha512-OOUi5zjkDxYrKhTV3V7iKsoS37VUM7v40+HuwEmcrsf11Cdx9y3DIr2Px6liIcZFwt3XSRpQvFpL3WVy7ApkGw==}
engines: {node: ^20.19.0 || >=22.12.0}
hasBin: true
peerDependencies:
@@ -7366,16 +7626,18 @@ packages:
jsdom:
optional: true
- vitest@4.0.0-beta.8:
- resolution: {integrity: sha512-wN/RDeCd5uXHV6tELw4AJzeP5rxR4YWXN3ems+59ZummmiovNjlfwG+CEZp5GitlxDQu7muoY4VPrSUxPzzKiQ==}
- engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
+ vitest@4.0.0-beta.18:
+ resolution: {integrity: sha512-zWvKMoebACjaOZADoHugNLC2GO8rnY4ERj052BunaJ9u/re6RmdIu4xu3mQ7yz97a1jmpSjeGr2tUz4kF1TrLA==}
+ engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0}
hasBin: true
peerDependencies:
'@edge-runtime/vm': '*'
'@types/debug': ^4.1.12
- '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0
- '@vitest/browser': 4.0.0-beta.8
- '@vitest/ui': 4.0.0-beta.8
+ '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0
+ '@vitest/browser-playwright': 4.0.0-beta.18
+ '@vitest/browser-preview': 4.0.0-beta.18
+ '@vitest/browser-webdriverio': 4.0.0-beta.18
+ '@vitest/ui': 4.0.0-beta.18
happy-dom: '*'
jsdom: '*'
peerDependenciesMeta:
@@ -7385,7 +7647,11 @@ packages:
optional: true
'@types/node':
optional: true
- '@vitest/browser':
+ '@vitest/browser-playwright':
+ optional: true
+ '@vitest/browser-preview':
+ optional: true
+ '@vitest/browser-webdriverio':
optional: true
'@vitest/ui':
optional: true
@@ -7554,8 +7820,11 @@ packages:
resolution: {integrity: sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ==}
engines: {node: '>=18'}
- zod@4.1.11:
- resolution: {integrity: sha512-WPsqwxITS2tzx1bzhIKsEs19ABD5vmCVa4xBo2tq/SrV4RNZtfws1EnCWQXM6yh8bD08a1idvkB5MZSBiZsjwg==}
+ zod@4.1.12:
+ resolution: {integrity: sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==}
+
+ zwitch@2.0.4:
+ resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
snapshots:
@@ -7565,47 +7834,42 @@ snapshots:
'@alloc/quick-lru@5.2.0': {}
- '@ampproject/remapping@2.3.0':
- dependencies:
- '@jridgewell/gen-mapping': 0.3.8
- '@jridgewell/trace-mapping': 0.3.29
-
- '@antfu/eslint-config@2.19.1(@vue/compiler-sfc@3.4.34)(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)(vitest@3.2.4(@types/node@24.6.0)(happy-dom@20.0.0)(jiti@2.6.0)(jsdom@26.1.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2))':
+ '@antfu/eslint-config@2.19.1(@vue/compiler-sfc@3.4.34)(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)(vitest@3.2.4(@types/node@24.8.1)(happy-dom@20.0.8)(jiti@2.6.1)(jsdom@26.1.0)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2))':
dependencies:
'@antfu/install-pkg': 0.3.3
'@clack/prompts': 0.7.0
- '@stylistic/eslint-plugin': 2.1.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)
- '@typescript-eslint/eslint-plugin': 7.11.0(@typescript-eslint/parser@7.11.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2))(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)
- '@typescript-eslint/parser': 7.11.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)
- eslint: 9.36.0(jiti@2.6.0)
+ '@stylistic/eslint-plugin': 2.1.0(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)
+ '@typescript-eslint/eslint-plugin': 7.11.0(@typescript-eslint/parser@7.11.0(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)
+ '@typescript-eslint/parser': 7.11.0(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)
+ eslint: 9.38.0(jiti@2.6.1)
eslint-config-flat-gitignore: 0.1.5
eslint-flat-config-utils: 0.2.5
- eslint-merge-processors: 0.1.0(eslint@9.36.0(jiti@2.6.0))
- eslint-plugin-antfu: 2.3.3(eslint@9.36.0(jiti@2.6.0))
- eslint-plugin-command: 0.2.3(eslint@9.36.0(jiti@2.6.0))
- eslint-plugin-eslint-comments: 3.2.0(eslint@9.36.0(jiti@2.6.0))
- eslint-plugin-import-x: 0.5.1(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)
- eslint-plugin-jsdoc: 48.2.7(eslint@9.36.0(jiti@2.6.0))
- eslint-plugin-jsonc: 2.16.0(eslint@9.36.0(jiti@2.6.0))
- eslint-plugin-markdown: 5.0.0(eslint@9.36.0(jiti@2.6.0))
- eslint-plugin-n: 17.7.0(eslint@9.36.0(jiti@2.6.0))
+ eslint-merge-processors: 0.1.0(eslint@9.38.0(jiti@2.6.1))
+ eslint-plugin-antfu: 2.3.3(eslint@9.38.0(jiti@2.6.1))
+ eslint-plugin-command: 0.2.3(eslint@9.38.0(jiti@2.6.1))
+ eslint-plugin-eslint-comments: 3.2.0(eslint@9.38.0(jiti@2.6.1))
+ eslint-plugin-import-x: 0.5.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)
+ eslint-plugin-jsdoc: 48.2.7(eslint@9.38.0(jiti@2.6.1))
+ eslint-plugin-jsonc: 2.16.0(eslint@9.38.0(jiti@2.6.1))
+ eslint-plugin-markdown: 5.0.0(eslint@9.38.0(jiti@2.6.1))
+ eslint-plugin-n: 17.7.0(eslint@9.38.0(jiti@2.6.1))
eslint-plugin-no-only-tests: 3.1.0
- eslint-plugin-perfectionist: 2.10.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)(vue-eslint-parser@9.4.2(eslint@9.36.0(jiti@2.6.0)))
- eslint-plugin-regexp: 2.6.0(eslint@9.36.0(jiti@2.6.0))
- eslint-plugin-toml: 0.11.0(eslint@9.36.0(jiti@2.6.0))
- eslint-plugin-unicorn: 53.0.0(eslint@9.36.0(jiti@2.6.0))
- eslint-plugin-unused-imports: 3.2.0(@typescript-eslint/eslint-plugin@7.11.0(@typescript-eslint/parser@7.11.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2))(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2))(eslint@9.36.0(jiti@2.6.0))
- eslint-plugin-vitest: 0.5.4(@typescript-eslint/eslint-plugin@7.11.0(@typescript-eslint/parser@7.11.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2))(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2))(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)(vitest@3.2.4(@types/node@24.6.0)(happy-dom@20.0.0)(jiti@2.6.0)(jsdom@26.1.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2))
- eslint-plugin-vue: 9.26.0(eslint@9.36.0(jiti@2.6.0))
- eslint-plugin-yml: 1.14.0(eslint@9.36.0(jiti@2.6.0))
- eslint-processor-vue-blocks: 0.1.2(@vue/compiler-sfc@3.4.34)(eslint@9.36.0(jiti@2.6.0))
+ eslint-plugin-perfectionist: 2.10.0(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)(vue-eslint-parser@9.4.2(eslint@9.38.0(jiti@2.6.1)))
+ eslint-plugin-regexp: 2.6.0(eslint@9.38.0(jiti@2.6.1))
+ eslint-plugin-toml: 0.11.0(eslint@9.38.0(jiti@2.6.1))
+ eslint-plugin-unicorn: 53.0.0(eslint@9.38.0(jiti@2.6.1))
+ eslint-plugin-unused-imports: 3.2.0(@typescript-eslint/eslint-plugin@7.11.0(@typescript-eslint/parser@7.11.0(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.38.0(jiti@2.6.1))
+ eslint-plugin-vitest: 0.5.4(@typescript-eslint/eslint-plugin@7.11.0(@typescript-eslint/parser@7.11.0(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)(vitest@3.2.4(@types/node@24.8.1)(happy-dom@20.0.8)(jiti@2.6.1)(jsdom@26.1.0)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2))
+ eslint-plugin-vue: 9.26.0(eslint@9.38.0(jiti@2.6.1))
+ eslint-plugin-yml: 1.14.0(eslint@9.38.0(jiti@2.6.1))
+ eslint-processor-vue-blocks: 0.1.2(@vue/compiler-sfc@3.4.34)(eslint@9.38.0(jiti@2.6.1))
globals: 15.3.0
jsonc-eslint-parser: 2.4.0
local-pkg: 0.5.0
parse-gitignore: 2.0.0
picocolors: 1.1.1
toml-eslint-parser: 0.9.3
- vue-eslint-parser: 9.4.2(eslint@9.36.0(jiti@2.6.0))
+ vue-eslint-parser: 9.4.2(eslint@9.38.0(jiti@2.6.1))
yaml-eslint-parser: 1.2.3
yargs: 17.7.2
transitivePeerDependencies:
@@ -7726,26 +7990,6 @@ snapshots:
'@babel/compat-data@7.28.0': {}
- '@babel/core@7.28.0':
- dependencies:
- '@ampproject/remapping': 2.3.0
- '@babel/code-frame': 7.27.1
- '@babel/generator': 7.28.0
- '@babel/helper-compilation-targets': 7.27.2
- '@babel/helper-module-transforms': 7.27.3(@babel/core@7.28.0)
- '@babel/helpers': 7.27.6
- '@babel/parser': 7.28.0
- '@babel/template': 7.27.2
- '@babel/traverse': 7.28.0
- '@babel/types': 7.28.0
- convert-source-map: 2.0.0
- debug: 4.4.1
- gensync: 1.0.0-beta.2
- json5: 2.2.3
- semver: 6.3.1
- transitivePeerDependencies:
- - supports-color
-
'@babel/core@7.28.4':
dependencies:
'@babel/code-frame': 7.27.1
@@ -7766,25 +8010,17 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@babel/generator@7.28.0':
- dependencies:
- '@babel/parser': 7.28.0
- '@babel/types': 7.28.0
- '@jridgewell/gen-mapping': 0.3.12
- '@jridgewell/trace-mapping': 0.3.29
- jsesc: 3.1.0
-
'@babel/generator@7.28.3':
dependencies:
- '@babel/parser': 7.28.3
- '@babel/types': 7.28.2
+ '@babel/parser': 7.28.4
+ '@babel/types': 7.28.4
'@jridgewell/gen-mapping': 0.3.13
- '@jridgewell/trace-mapping': 0.3.30
+ '@jridgewell/trace-mapping': 0.3.31
jsesc: 3.1.0
'@babel/helper-annotate-as-pure@7.27.3':
dependencies:
- '@babel/types': 7.27.6
+ '@babel/types': 7.28.4
'@babel/helper-compilation-targets@7.27.2':
dependencies:
@@ -7842,28 +8078,19 @@ snapshots:
'@babel/helper-member-expression-to-functions@7.27.1':
dependencies:
- '@babel/traverse': 7.28.3
- '@babel/types': 7.28.2
+ '@babel/traverse': 7.28.4
+ '@babel/types': 7.28.4
transitivePeerDependencies:
- supports-color
'@babel/helper-module-imports@7.18.6':
dependencies:
- '@babel/types': 7.28.2
+ '@babel/types': 7.28.4
'@babel/helper-module-imports@7.27.1':
dependencies:
- '@babel/traverse': 7.27.4
- '@babel/types': 7.27.6
- transitivePeerDependencies:
- - supports-color
-
- '@babel/helper-module-transforms@7.27.3(@babel/core@7.28.0)':
- dependencies:
- '@babel/core': 7.28.0
- '@babel/helper-module-imports': 7.27.1
- '@babel/helper-validator-identifier': 7.27.1
- '@babel/traverse': 7.27.4
+ '@babel/traverse': 7.28.4
+ '@babel/types': 7.28.4
transitivePeerDependencies:
- supports-color
@@ -7887,7 +8114,7 @@ snapshots:
'@babel/helper-optimise-call-expression@7.27.1':
dependencies:
- '@babel/types': 7.28.2
+ '@babel/types': 7.28.4
'@babel/helper-plugin-utils@7.27.1': {}
@@ -7927,32 +8154,19 @@ snapshots:
'@babel/helper-wrap-function@7.28.3':
dependencies:
'@babel/template': 7.27.2
- '@babel/traverse': 7.28.3
- '@babel/types': 7.28.2
+ '@babel/traverse': 7.28.4
+ '@babel/types': 7.28.4
transitivePeerDependencies:
- supports-color
- '@babel/helpers@7.27.6':
- dependencies:
- '@babel/template': 7.27.2
- '@babel/types': 7.27.6
-
'@babel/helpers@7.28.4':
dependencies:
'@babel/template': 7.27.2
'@babel/types': 7.28.4
- '@babel/parser@7.27.5':
- dependencies:
- '@babel/types': 7.27.6
-
- '@babel/parser@7.28.0':
- dependencies:
- '@babel/types': 7.28.0
-
'@babel/parser@7.28.3':
dependencies:
- '@babel/types': 7.28.2
+ '@babel/types': 7.28.4
'@babel/parser@7.28.4':
dependencies:
@@ -8037,11 +8251,6 @@ snapshots:
'@babel/core': 7.28.4
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.28.0)':
- dependencies:
- '@babel/core': 7.28.0
- '@babel/helper-plugin-utils': 7.27.1
-
'@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.28.4)':
dependencies:
'@babel/core': 7.28.4
@@ -8393,7 +8602,7 @@ snapshots:
'@babel/helper-module-imports': 7.27.1
'@babel/helper-plugin-utils': 7.27.1
'@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.4)
- '@babel/types': 7.27.6
+ '@babel/types': 7.28.4
transitivePeerDependencies:
- supports-color
@@ -8587,38 +8796,28 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ '@babel/runtime@7.28.3': {}
+
'@babel/runtime@7.28.4': {}
'@babel/template@7.27.2':
dependencies:
'@babel/code-frame': 7.27.1
- '@babel/parser': 7.27.5
- '@babel/types': 7.27.6
+ '@babel/parser': 7.28.4
+ '@babel/types': 7.28.4
'@babel/traverse@7.27.4':
dependencies:
'@babel/code-frame': 7.27.1
'@babel/generator': 7.28.3
- '@babel/parser': 7.28.3
+ '@babel/parser': 7.28.4
'@babel/template': 7.27.2
- '@babel/types': 7.27.6
- debug: 4.4.1
+ '@babel/types': 7.28.4
+ debug: 4.4.3
globals: 11.12.0
transitivePeerDependencies:
- supports-color
- '@babel/traverse@7.28.0':
- dependencies:
- '@babel/code-frame': 7.27.1
- '@babel/generator': 7.28.0
- '@babel/helper-globals': 7.28.0
- '@babel/parser': 7.28.0
- '@babel/template': 7.27.2
- '@babel/types': 7.28.0
- debug: 4.4.1
- transitivePeerDependencies:
- - supports-color
-
'@babel/traverse@7.28.3':
dependencies:
'@babel/code-frame': 7.27.1
@@ -8648,11 +8847,6 @@ snapshots:
'@babel/helper-string-parser': 7.27.1
'@babel/helper-validator-identifier': 7.27.1
- '@babel/types@7.28.0':
- dependencies:
- '@babel/helper-string-parser': 7.27.1
- '@babel/helper-validator-identifier': 7.27.1
-
'@babel/types@7.28.2':
dependencies:
'@babel/helper-string-parser': 7.27.1
@@ -8694,7 +8888,7 @@ snapshots:
dependencies:
'@changesets/types': 6.1.0
- '@changesets/cli@2.29.7(@types/node@24.6.0)':
+ '@changesets/cli@2.29.7(@types/node@24.8.1)':
dependencies:
'@changesets/apply-release-plan': 7.0.13
'@changesets/assemble-release-plan': 6.0.9
@@ -8710,7 +8904,7 @@ snapshots:
'@changesets/should-skip-package': 0.1.2
'@changesets/types': 6.1.0
'@changesets/write': 0.4.0
- '@inquirer/external-editor': 1.0.2(@types/node@24.6.0)
+ '@inquirer/external-editor': 1.0.2(@types/node@24.8.1)
'@manypkg/get-packages': 1.1.3
ansi-colors: 4.1.3
ci-info: 3.9.0
@@ -8820,6 +9014,11 @@ snapshots:
picocolors: 1.1.1
sisteransi: 1.0.5
+ '@corvu/resizable@0.2.5(solid-js@1.9.9)':
+ dependencies:
+ '@corvu/utils': 0.4.2(solid-js@1.9.9)
+ solid-js: 1.9.9
+
'@corvu/utils@0.4.2(solid-js@1.9.9)':
dependencies:
'@floating-ui/dom': 1.7.3
@@ -8874,7 +9073,7 @@ snapshots:
'@esbuild/aix-ppc64@0.21.5':
optional: true
- '@esbuild/aix-ppc64@0.25.10':
+ '@esbuild/aix-ppc64@0.25.11':
optional: true
'@esbuild/aix-ppc64@0.25.6':
@@ -8883,7 +9082,7 @@ snapshots:
'@esbuild/android-arm64@0.21.5':
optional: true
- '@esbuild/android-arm64@0.25.10':
+ '@esbuild/android-arm64@0.25.11':
optional: true
'@esbuild/android-arm64@0.25.6':
@@ -8892,7 +9091,7 @@ snapshots:
'@esbuild/android-arm@0.21.5':
optional: true
- '@esbuild/android-arm@0.25.10':
+ '@esbuild/android-arm@0.25.11':
optional: true
'@esbuild/android-arm@0.25.6':
@@ -8901,7 +9100,7 @@ snapshots:
'@esbuild/android-x64@0.21.5':
optional: true
- '@esbuild/android-x64@0.25.10':
+ '@esbuild/android-x64@0.25.11':
optional: true
'@esbuild/android-x64@0.25.6':
@@ -8910,7 +9109,7 @@ snapshots:
'@esbuild/darwin-arm64@0.21.5':
optional: true
- '@esbuild/darwin-arm64@0.25.10':
+ '@esbuild/darwin-arm64@0.25.11':
optional: true
'@esbuild/darwin-arm64@0.25.6':
@@ -8919,7 +9118,7 @@ snapshots:
'@esbuild/darwin-x64@0.21.5':
optional: true
- '@esbuild/darwin-x64@0.25.10':
+ '@esbuild/darwin-x64@0.25.11':
optional: true
'@esbuild/darwin-x64@0.25.6':
@@ -8928,7 +9127,7 @@ snapshots:
'@esbuild/freebsd-arm64@0.21.5':
optional: true
- '@esbuild/freebsd-arm64@0.25.10':
+ '@esbuild/freebsd-arm64@0.25.11':
optional: true
'@esbuild/freebsd-arm64@0.25.6':
@@ -8937,7 +9136,7 @@ snapshots:
'@esbuild/freebsd-x64@0.21.5':
optional: true
- '@esbuild/freebsd-x64@0.25.10':
+ '@esbuild/freebsd-x64@0.25.11':
optional: true
'@esbuild/freebsd-x64@0.25.6':
@@ -8946,7 +9145,7 @@ snapshots:
'@esbuild/linux-arm64@0.21.5':
optional: true
- '@esbuild/linux-arm64@0.25.10':
+ '@esbuild/linux-arm64@0.25.11':
optional: true
'@esbuild/linux-arm64@0.25.6':
@@ -8955,7 +9154,7 @@ snapshots:
'@esbuild/linux-arm@0.21.5':
optional: true
- '@esbuild/linux-arm@0.25.10':
+ '@esbuild/linux-arm@0.25.11':
optional: true
'@esbuild/linux-arm@0.25.6':
@@ -8964,7 +9163,7 @@ snapshots:
'@esbuild/linux-ia32@0.21.5':
optional: true
- '@esbuild/linux-ia32@0.25.10':
+ '@esbuild/linux-ia32@0.25.11':
optional: true
'@esbuild/linux-ia32@0.25.6':
@@ -8973,7 +9172,7 @@ snapshots:
'@esbuild/linux-loong64@0.21.5':
optional: true
- '@esbuild/linux-loong64@0.25.10':
+ '@esbuild/linux-loong64@0.25.11':
optional: true
'@esbuild/linux-loong64@0.25.6':
@@ -8982,7 +9181,7 @@ snapshots:
'@esbuild/linux-mips64el@0.21.5':
optional: true
- '@esbuild/linux-mips64el@0.25.10':
+ '@esbuild/linux-mips64el@0.25.11':
optional: true
'@esbuild/linux-mips64el@0.25.6':
@@ -8991,7 +9190,7 @@ snapshots:
'@esbuild/linux-ppc64@0.21.5':
optional: true
- '@esbuild/linux-ppc64@0.25.10':
+ '@esbuild/linux-ppc64@0.25.11':
optional: true
'@esbuild/linux-ppc64@0.25.6':
@@ -9000,7 +9199,7 @@ snapshots:
'@esbuild/linux-riscv64@0.21.5':
optional: true
- '@esbuild/linux-riscv64@0.25.10':
+ '@esbuild/linux-riscv64@0.25.11':
optional: true
'@esbuild/linux-riscv64@0.25.6':
@@ -9009,7 +9208,7 @@ snapshots:
'@esbuild/linux-s390x@0.21.5':
optional: true
- '@esbuild/linux-s390x@0.25.10':
+ '@esbuild/linux-s390x@0.25.11':
optional: true
'@esbuild/linux-s390x@0.25.6':
@@ -9018,13 +9217,13 @@ snapshots:
'@esbuild/linux-x64@0.21.5':
optional: true
- '@esbuild/linux-x64@0.25.10':
+ '@esbuild/linux-x64@0.25.11':
optional: true
'@esbuild/linux-x64@0.25.6':
optional: true
- '@esbuild/netbsd-arm64@0.25.10':
+ '@esbuild/netbsd-arm64@0.25.11':
optional: true
'@esbuild/netbsd-arm64@0.25.6':
@@ -9033,13 +9232,13 @@ snapshots:
'@esbuild/netbsd-x64@0.21.5':
optional: true
- '@esbuild/netbsd-x64@0.25.10':
+ '@esbuild/netbsd-x64@0.25.11':
optional: true
'@esbuild/netbsd-x64@0.25.6':
optional: true
- '@esbuild/openbsd-arm64@0.25.10':
+ '@esbuild/openbsd-arm64@0.25.11':
optional: true
'@esbuild/openbsd-arm64@0.25.6':
@@ -9048,13 +9247,13 @@ snapshots:
'@esbuild/openbsd-x64@0.21.5':
optional: true
- '@esbuild/openbsd-x64@0.25.10':
+ '@esbuild/openbsd-x64@0.25.11':
optional: true
'@esbuild/openbsd-x64@0.25.6':
optional: true
- '@esbuild/openharmony-arm64@0.25.10':
+ '@esbuild/openharmony-arm64@0.25.11':
optional: true
'@esbuild/openharmony-arm64@0.25.6':
@@ -9063,7 +9262,7 @@ snapshots:
'@esbuild/sunos-x64@0.21.5':
optional: true
- '@esbuild/sunos-x64@0.25.10':
+ '@esbuild/sunos-x64@0.25.11':
optional: true
'@esbuild/sunos-x64@0.25.6':
@@ -9072,7 +9271,7 @@ snapshots:
'@esbuild/win32-arm64@0.21.5':
optional: true
- '@esbuild/win32-arm64@0.25.10':
+ '@esbuild/win32-arm64@0.25.11':
optional: true
'@esbuild/win32-arm64@0.25.6':
@@ -9081,7 +9280,7 @@ snapshots:
'@esbuild/win32-ia32@0.21.5':
optional: true
- '@esbuild/win32-ia32@0.25.10':
+ '@esbuild/win32-ia32@0.25.11':
optional: true
'@esbuild/win32-ia32@0.25.6':
@@ -9090,37 +9289,39 @@ snapshots:
'@esbuild/win32-x64@0.21.5':
optional: true
- '@esbuild/win32-x64@0.25.10':
+ '@esbuild/win32-x64@0.25.11':
optional: true
'@esbuild/win32-x64@0.25.6':
optional: true
- '@eslint-community/eslint-utils@4.4.0(eslint@9.36.0(jiti@2.6.0))':
+ '@eslint-community/eslint-utils@4.4.0(eslint@9.38.0(jiti@2.6.1))':
dependencies:
- eslint: 9.36.0(jiti@2.6.0)
+ eslint: 9.38.0(jiti@2.6.1)
eslint-visitor-keys: 3.4.3
- '@eslint-community/eslint-utils@4.9.0(eslint@9.36.0(jiti@2.6.0))':
+ '@eslint-community/eslint-utils@4.9.0(eslint@9.38.0(jiti@2.6.1))':
dependencies:
- eslint: 9.36.0(jiti@2.6.0)
+ eslint: 9.38.0(jiti@2.6.1)
eslint-visitor-keys: 3.4.3
'@eslint-community/regexpp@4.10.0': {}
'@eslint-community/regexpp@4.12.1': {}
- '@eslint/config-array@0.21.0':
+ '@eslint/config-array@0.21.1':
dependencies:
- '@eslint/object-schema': 2.1.6
+ '@eslint/object-schema': 2.1.7
debug: 4.4.3
minimatch: 3.1.2
transitivePeerDependencies:
- supports-color
- '@eslint/config-helpers@0.3.1': {}
+ '@eslint/config-helpers@0.4.1':
+ dependencies:
+ '@eslint/core': 0.16.0
- '@eslint/core@0.15.2':
+ '@eslint/core@0.16.0':
dependencies:
'@types/json-schema': 7.0.15
@@ -9152,13 +9353,13 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@eslint/js@9.36.0': {}
+ '@eslint/js@9.38.0': {}
- '@eslint/object-schema@2.1.6': {}
+ '@eslint/object-schema@2.1.7': {}
- '@eslint/plugin-kit@0.3.5':
+ '@eslint/plugin-kit@0.4.0':
dependencies:
- '@eslint/core': 0.15.2
+ '@eslint/core': 0.16.0
levn: 0.4.1
'@floating-ui/core@1.7.3':
@@ -9172,6 +9373,11 @@ snapshots:
'@floating-ui/utils@0.2.10': {}
+ '@happy-dom/global-registrator@20.0.8':
+ dependencies:
+ '@types/node': 20.19.22
+ happy-dom: 20.0.8
+
'@humanfs/core@0.19.1': {}
'@humanfs/node@0.16.7':
@@ -9272,12 +9478,12 @@ snapshots:
'@img/sharp-win32-x64@0.34.4':
optional: true
- '@inquirer/external-editor@1.0.2(@types/node@24.6.0)':
+ '@inquirer/external-editor@1.0.2(@types/node@24.8.1)':
dependencies:
chardet: 2.1.0
iconv-lite: 0.7.0
optionalDependencies:
- '@types/node': 24.6.0
+ '@types/node': 24.8.1
'@internationalized/date@3.8.2':
dependencies:
@@ -9319,13 +9525,13 @@ snapshots:
'@jest/console@30.2.0':
dependencies:
'@jest/types': 30.2.0
- '@types/node': 24.6.0
+ '@types/node': 24.8.1
chalk: 4.1.2
jest-message-util: 30.2.0
jest-util: 30.2.0
slash: 3.0.0
- '@jest/core@30.2.0(ts-node@10.9.2(@types/node@24.6.0)(typescript@5.9.2))':
+ '@jest/core@30.2.0(ts-node@10.9.2(@types/node@24.8.1)(typescript@5.9.3))':
dependencies:
'@jest/console': 30.2.0
'@jest/pattern': 30.0.1
@@ -9333,14 +9539,14 @@ snapshots:
'@jest/test-result': 30.2.0
'@jest/transform': 30.2.0
'@jest/types': 30.2.0
- '@types/node': 24.6.0
+ '@types/node': 24.8.1
ansi-escapes: 4.3.2
chalk: 4.1.2
ci-info: 4.3.0
exit-x: 0.2.2
graceful-fs: 4.2.11
jest-changed-files: 30.2.0
- jest-config: 30.2.0(patch_hash=7183ebeb461331a42f7b4be95c553b6304fa99af85998b66f7f8c91aa96e8d46)(@types/node@24.6.0)(ts-node@10.9.2(@types/node@24.6.0)(typescript@5.9.2))
+ jest-config: 30.2.0(patch_hash=7183ebeb461331a42f7b4be95c553b6304fa99af85998b66f7f8c91aa96e8d46)(@types/node@24.8.1)(ts-node@10.9.2(@types/node@24.8.1)(typescript@5.9.3))
jest-haste-map: 30.2.0
jest-message-util: 30.2.0
jest-regex-util: 30.0.1
@@ -9369,7 +9575,7 @@ snapshots:
'@jest/fake-timers': 30.2.0
'@jest/types': 30.2.0
'@types/jsdom': 21.1.7
- '@types/node': 24.6.0
+ '@types/node': 24.8.1
jest-mock: 30.2.0
jest-util: 30.2.0
jsdom: 26.1.0
@@ -9378,7 +9584,7 @@ snapshots:
dependencies:
'@jest/fake-timers': 30.2.0
'@jest/types': 30.2.0
- '@types/node': 24.6.0
+ '@types/node': 24.8.1
jest-mock: 30.2.0
'@jest/expect-utils@30.0.4':
@@ -9400,7 +9606,7 @@ snapshots:
dependencies:
'@jest/types': 30.2.0
'@sinonjs/fake-timers': 13.0.5
- '@types/node': 24.6.0
+ '@types/node': 24.8.1
jest-message-util: 30.2.0
jest-mock: 30.2.0
jest-util: 30.2.0
@@ -9420,7 +9626,7 @@ snapshots:
'@jest/pattern@30.0.1':
dependencies:
- '@types/node': 24.6.0
+ '@types/node': 24.8.1
jest-regex-util: 30.0.1
'@jest/reporters@30.2.0':
@@ -9431,7 +9637,7 @@ snapshots:
'@jest/transform': 30.2.0
'@jest/types': 30.2.0
'@jridgewell/trace-mapping': 0.3.31
- '@types/node': 24.6.0
+ '@types/node': 24.8.1
chalk: 4.1.2
collect-v8-coverage: 1.0.2
exit-x: 0.2.2
@@ -9512,7 +9718,7 @@ snapshots:
'@jest/schemas': 30.0.1
'@types/istanbul-lib-coverage': 2.0.6
'@types/istanbul-reports': 3.0.4
- '@types/node': 24.6.0
+ '@types/node': 24.8.1
'@types/yargs': 17.0.33
chalk: 4.1.2
@@ -9522,19 +9728,14 @@ snapshots:
'@jest/schemas': 30.0.5
'@types/istanbul-lib-coverage': 2.0.6
'@types/istanbul-reports': 3.0.4
- '@types/node': 24.6.0
+ '@types/node': 24.8.1
'@types/yargs': 17.0.33
chalk: 4.1.2
- '@jridgewell/gen-mapping@0.3.12':
- dependencies:
- '@jridgewell/sourcemap-codec': 1.5.4
- '@jridgewell/trace-mapping': 0.3.29
-
'@jridgewell/gen-mapping@0.3.13':
dependencies:
'@jridgewell/sourcemap-codec': 1.5.5
- '@jridgewell/trace-mapping': 0.3.30
+ '@jridgewell/trace-mapping': 0.3.31
'@jridgewell/gen-mapping@0.3.5':
dependencies:
@@ -9542,12 +9743,6 @@ snapshots:
'@jridgewell/sourcemap-codec': 1.4.15
'@jridgewell/trace-mapping': 0.3.29
- '@jridgewell/gen-mapping@0.3.8':
- dependencies:
- '@jridgewell/set-array': 1.2.1
- '@jridgewell/sourcemap-codec': 1.5.4
- '@jridgewell/trace-mapping': 0.3.29
-
'@jridgewell/remapping@2.3.5':
dependencies:
'@jridgewell/gen-mapping': 0.3.13
@@ -9570,11 +9765,6 @@ snapshots:
'@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.5.4
- '@jridgewell/trace-mapping@0.3.30':
- dependencies:
- '@jridgewell/resolve-uri': 3.1.2
- '@jridgewell/sourcemap-codec': 1.5.5
-
'@jridgewell/trace-mapping@0.3.31':
dependencies:
'@jridgewell/resolve-uri': 3.1.2
@@ -9631,9 +9821,9 @@ snapshots:
globby: 11.1.0
read-yaml-file: 1.1.0
- '@microsoft/1ds-core-js@4.3.8(tslib@2.8.1)':
+ '@microsoft/1ds-core-js@4.3.10(tslib@2.8.1)':
dependencies:
- '@microsoft/applicationinsights-core-js': 3.3.8(tslib@2.8.1)
+ '@microsoft/applicationinsights-core-js': 3.3.10(tslib@2.8.1)
'@microsoft/applicationinsights-shims': 3.0.1
'@microsoft/dynamicproto-js': 2.0.3
'@nevware21/ts-async': 0.5.4
@@ -9641,9 +9831,9 @@ snapshots:
transitivePeerDependencies:
- tslib
- '@microsoft/1ds-post-js@4.3.8(tslib@2.8.1)':
+ '@microsoft/1ds-post-js@4.3.10(tslib@2.8.1)':
dependencies:
- '@microsoft/1ds-core-js': 4.3.8(tslib@2.8.1)
+ '@microsoft/1ds-core-js': 4.3.10(tslib@2.8.1)
'@microsoft/applicationinsights-shims': 3.0.1
'@microsoft/dynamicproto-js': 2.0.3
'@nevware21/ts-async': 0.5.4
@@ -9651,25 +9841,25 @@ snapshots:
transitivePeerDependencies:
- tslib
- '@microsoft/applicationinsights-channel-js@3.3.8(tslib@2.8.1)':
+ '@microsoft/applicationinsights-channel-js@3.3.10(tslib@2.8.1)':
dependencies:
- '@microsoft/applicationinsights-common': 3.3.8(tslib@2.8.1)
- '@microsoft/applicationinsights-core-js': 3.3.8(tslib@2.8.1)
+ '@microsoft/applicationinsights-common': 3.3.10(tslib@2.8.1)
+ '@microsoft/applicationinsights-core-js': 3.3.10(tslib@2.8.1)
'@microsoft/applicationinsights-shims': 3.0.1
'@microsoft/dynamicproto-js': 2.0.3
'@nevware21/ts-async': 0.5.4
'@nevware21/ts-utils': 0.12.5
tslib: 2.8.1
- '@microsoft/applicationinsights-common@3.3.8(tslib@2.8.1)':
+ '@microsoft/applicationinsights-common@3.3.10(tslib@2.8.1)':
dependencies:
- '@microsoft/applicationinsights-core-js': 3.3.8(tslib@2.8.1)
+ '@microsoft/applicationinsights-core-js': 3.3.10(tslib@2.8.1)
'@microsoft/applicationinsights-shims': 3.0.1
'@microsoft/dynamicproto-js': 2.0.3
'@nevware21/ts-utils': 0.12.5
tslib: 2.8.1
- '@microsoft/applicationinsights-core-js@3.3.8(tslib@2.8.1)':
+ '@microsoft/applicationinsights-core-js@3.3.10(tslib@2.8.1)':
dependencies:
'@microsoft/applicationinsights-shims': 3.0.1
'@microsoft/dynamicproto-js': 2.0.3
@@ -9681,11 +9871,11 @@ snapshots:
dependencies:
'@nevware21/ts-utils': 0.12.5
- '@microsoft/applicationinsights-web-basic@3.3.8(tslib@2.8.1)':
+ '@microsoft/applicationinsights-web-basic@3.3.10(tslib@2.8.1)':
dependencies:
- '@microsoft/applicationinsights-channel-js': 3.3.8(tslib@2.8.1)
- '@microsoft/applicationinsights-common': 3.3.8(tslib@2.8.1)
- '@microsoft/applicationinsights-core-js': 3.3.8(tslib@2.8.1)
+ '@microsoft/applicationinsights-channel-js': 3.3.10(tslib@2.8.1)
+ '@microsoft/applicationinsights-common': 3.3.10(tslib@2.8.1)
+ '@microsoft/applicationinsights-core-js': 3.3.10(tslib@2.8.1)
'@microsoft/applicationinsights-shims': 3.0.1
'@microsoft/dynamicproto-js': 2.0.3
'@nevware21/ts-async': 0.5.4
@@ -9722,7 +9912,7 @@ snapshots:
'@tybys/wasm-util': 0.10.1
optional: true
- '@napi-rs/wasm-runtime@1.0.5':
+ '@napi-rs/wasm-runtime@1.0.7':
dependencies:
'@emnapi/core': 1.5.0
'@emnapi/runtime': 1.5.0
@@ -9734,30 +9924,30 @@ snapshots:
'@nevware21/ts-utils@0.12.5': {}
- '@next/env@15.5.4': {}
+ '@next/env@15.5.6': {}
- '@next/swc-darwin-arm64@15.5.4':
+ '@next/swc-darwin-arm64@15.5.6':
optional: true
- '@next/swc-darwin-x64@15.5.4':
+ '@next/swc-darwin-x64@15.5.6':
optional: true
- '@next/swc-linux-arm64-gnu@15.5.4':
+ '@next/swc-linux-arm64-gnu@15.5.6':
optional: true
- '@next/swc-linux-arm64-musl@15.5.4':
+ '@next/swc-linux-arm64-musl@15.5.6':
optional: true
- '@next/swc-linux-x64-gnu@15.5.4':
+ '@next/swc-linux-x64-gnu@15.5.6':
optional: true
- '@next/swc-linux-x64-musl@15.5.4':
+ '@next/swc-linux-x64-musl@15.5.6':
optional: true
- '@next/swc-win32-arm64-msvc@15.5.4':
+ '@next/swc-win32-arm64-msvc@15.5.6':
optional: true
- '@next/swc-win32-x64-msvc@15.5.4':
+ '@next/swc-win32-x64-msvc@15.5.6':
optional: true
'@node-rs/crc32-android-arm-eabi@1.10.6':
@@ -9833,9 +10023,53 @@ snapshots:
'@nodelib/fs.scandir': 2.1.5
fastq: 1.17.1
- '@oxc-parser/binding-wasm32-wasi@0.93.0':
+ '@oxc-parser/binding-android-arm64@0.95.0':
+ optional: true
+
+ '@oxc-parser/binding-darwin-arm64@0.95.0':
+ optional: true
+
+ '@oxc-parser/binding-darwin-x64@0.95.0':
+ optional: true
+
+ '@oxc-parser/binding-freebsd-x64@0.95.0':
+ optional: true
+
+ '@oxc-parser/binding-linux-arm-gnueabihf@0.95.0':
+ optional: true
+
+ '@oxc-parser/binding-linux-arm-musleabihf@0.95.0':
+ optional: true
+
+ '@oxc-parser/binding-linux-arm64-gnu@0.95.0':
+ optional: true
+
+ '@oxc-parser/binding-linux-arm64-musl@0.95.0':
+ optional: true
+
+ '@oxc-parser/binding-linux-riscv64-gnu@0.95.0':
+ optional: true
+
+ '@oxc-parser/binding-linux-s390x-gnu@0.95.0':
+ optional: true
+
+ '@oxc-parser/binding-linux-x64-gnu@0.95.0':
+ optional: true
+
+ '@oxc-parser/binding-linux-x64-musl@0.95.0':
+ optional: true
+
+ '@oxc-parser/binding-wasm32-wasi@0.95.0':
dependencies:
- '@napi-rs/wasm-runtime': 1.0.5
+ '@napi-rs/wasm-runtime': 1.0.7
+
+ '@oxc-parser/binding-win32-arm64-msvc@0.95.0':
+ optional: true
+
+ '@oxc-parser/binding-win32-x64-msvc@0.95.0':
+ optional: true
+
+ '@oxc-project/types@0.95.0': {}
'@parcel/watcher-android-arm64@2.5.1':
optional: true
@@ -9903,9 +10137,9 @@ snapshots:
'@pkgr/core@0.2.9': {}
- '@playwright/test@1.55.1':
+ '@playwright/test@1.56.1':
dependencies:
- playwright: 1.55.1
+ playwright: 1.56.1
'@rolldown/pluginutils@1.0.0-beta.38': {}
@@ -10162,6 +10396,39 @@ snapshots:
'@secretlint/types@10.2.2': {}
+ '@shikijs/core@3.13.0':
+ dependencies:
+ '@shikijs/types': 3.13.0
+ '@shikijs/vscode-textmate': 10.0.2
+ '@types/hast': 3.0.4
+ hast-util-to-html: 9.0.5
+
+ '@shikijs/engine-javascript@3.13.0':
+ dependencies:
+ '@shikijs/types': 3.13.0
+ '@shikijs/vscode-textmate': 10.0.2
+ oniguruma-to-es: 4.3.3
+
+ '@shikijs/engine-oniguruma@3.13.0':
+ dependencies:
+ '@shikijs/types': 3.13.0
+ '@shikijs/vscode-textmate': 10.0.2
+
+ '@shikijs/langs@3.13.0':
+ dependencies:
+ '@shikijs/types': 3.13.0
+
+ '@shikijs/themes@3.13.0':
+ dependencies:
+ '@shikijs/types': 3.13.0
+
+ '@shikijs/types@3.13.0':
+ dependencies:
+ '@shikijs/vscode-textmate': 10.0.2
+ '@types/hast': 3.0.4
+
+ '@shikijs/vscode-textmate@10.0.2': {}
+
'@sinclair/typebox@0.34.37': {}
'@sinclair/typebox@0.34.41': {}
@@ -10271,49 +10538,51 @@ snapshots:
dependencies:
solid-js: 1.9.9
- '@stylistic/eslint-plugin-js@2.1.0(eslint@9.36.0(jiti@2.6.0))':
+ '@standard-schema/spec@1.0.0': {}
+
+ '@stylistic/eslint-plugin-js@2.1.0(eslint@9.38.0(jiti@2.6.1))':
dependencies:
'@types/eslint': 8.56.10
acorn: 8.15.0
- eslint: 9.36.0(jiti@2.6.0)
+ eslint: 9.38.0(jiti@2.6.1)
eslint-visitor-keys: 4.0.0
espree: 10.0.1
- '@stylistic/eslint-plugin-jsx@2.1.0(eslint@9.36.0(jiti@2.6.0))':
+ '@stylistic/eslint-plugin-jsx@2.1.0(eslint@9.38.0(jiti@2.6.1))':
dependencies:
- '@stylistic/eslint-plugin-js': 2.1.0(eslint@9.36.0(jiti@2.6.0))
+ '@stylistic/eslint-plugin-js': 2.1.0(eslint@9.38.0(jiti@2.6.1))
'@types/eslint': 8.56.10
- eslint: 9.36.0(jiti@2.6.0)
+ eslint: 9.38.0(jiti@2.6.1)
estraverse: 5.3.0
picomatch: 4.0.2
- '@stylistic/eslint-plugin-plus@2.1.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)':
+ '@stylistic/eslint-plugin-plus@2.1.0(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)':
dependencies:
'@types/eslint': 8.56.10
- '@typescript-eslint/utils': 7.11.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)
- eslint: 9.36.0(jiti@2.6.0)
+ '@typescript-eslint/utils': 7.11.0(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)
+ eslint: 9.38.0(jiti@2.6.1)
transitivePeerDependencies:
- supports-color
- typescript
- '@stylistic/eslint-plugin-ts@2.1.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)':
+ '@stylistic/eslint-plugin-ts@2.1.0(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)':
dependencies:
- '@stylistic/eslint-plugin-js': 2.1.0(eslint@9.36.0(jiti@2.6.0))
+ '@stylistic/eslint-plugin-js': 2.1.0(eslint@9.38.0(jiti@2.6.1))
'@types/eslint': 8.56.10
- '@typescript-eslint/utils': 7.11.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)
- eslint: 9.36.0(jiti@2.6.0)
+ '@typescript-eslint/utils': 7.11.0(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)
+ eslint: 9.38.0(jiti@2.6.1)
transitivePeerDependencies:
- supports-color
- typescript
- '@stylistic/eslint-plugin@2.1.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)':
+ '@stylistic/eslint-plugin@2.1.0(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)':
dependencies:
- '@stylistic/eslint-plugin-js': 2.1.0(eslint@9.36.0(jiti@2.6.0))
- '@stylistic/eslint-plugin-jsx': 2.1.0(eslint@9.36.0(jiti@2.6.0))
- '@stylistic/eslint-plugin-plus': 2.1.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)
- '@stylistic/eslint-plugin-ts': 2.1.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)
+ '@stylistic/eslint-plugin-js': 2.1.0(eslint@9.38.0(jiti@2.6.1))
+ '@stylistic/eslint-plugin-jsx': 2.1.0(eslint@9.38.0(jiti@2.6.1))
+ '@stylistic/eslint-plugin-plus': 2.1.0(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)
+ '@stylistic/eslint-plugin-ts': 2.1.0(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)
'@types/eslint': 8.56.10
- eslint: 9.36.0(jiti@2.6.0)
+ eslint: 9.38.0(jiti@2.6.1)
transitivePeerDependencies:
- supports-color
- typescript
@@ -10326,88 +10595,88 @@ snapshots:
dependencies:
tslib: 2.8.1
- '@tailwindcss/node@4.1.13':
+ '@tailwindcss/node@4.1.14':
dependencies:
'@jridgewell/remapping': 2.3.5
enhanced-resolve: 5.18.3
- jiti: 2.6.0
+ jiti: 2.6.1
lightningcss: 1.30.1
magic-string: 0.30.19
source-map-js: 1.2.1
- tailwindcss: 4.1.13
+ tailwindcss: 4.1.14
- '@tailwindcss/oxide-android-arm64@4.1.13':
+ '@tailwindcss/oxide-android-arm64@4.1.14':
optional: true
- '@tailwindcss/oxide-darwin-arm64@4.1.13':
+ '@tailwindcss/oxide-darwin-arm64@4.1.14':
optional: true
- '@tailwindcss/oxide-darwin-x64@4.1.13':
+ '@tailwindcss/oxide-darwin-x64@4.1.14':
optional: true
- '@tailwindcss/oxide-freebsd-x64@4.1.13':
+ '@tailwindcss/oxide-freebsd-x64@4.1.14':
optional: true
- '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.13':
+ '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.14':
optional: true
- '@tailwindcss/oxide-linux-arm64-gnu@4.1.13':
+ '@tailwindcss/oxide-linux-arm64-gnu@4.1.14':
optional: true
- '@tailwindcss/oxide-linux-arm64-musl@4.1.13':
+ '@tailwindcss/oxide-linux-arm64-musl@4.1.14':
optional: true
- '@tailwindcss/oxide-linux-x64-gnu@4.1.13':
+ '@tailwindcss/oxide-linux-x64-gnu@4.1.14':
optional: true
- '@tailwindcss/oxide-linux-x64-musl@4.1.13':
+ '@tailwindcss/oxide-linux-x64-musl@4.1.14':
optional: true
- '@tailwindcss/oxide-wasm32-wasi@4.1.13': {}
+ '@tailwindcss/oxide-wasm32-wasi@4.1.14': {}
- '@tailwindcss/oxide-win32-arm64-msvc@4.1.13':
+ '@tailwindcss/oxide-win32-arm64-msvc@4.1.14':
optional: true
- '@tailwindcss/oxide-win32-x64-msvc@4.1.13':
+ '@tailwindcss/oxide-win32-x64-msvc@4.1.14':
optional: true
- '@tailwindcss/oxide@4.1.13':
+ '@tailwindcss/oxide@4.1.14':
dependencies:
- detect-libc: 2.1.1
+ detect-libc: 2.1.2
tar: 7.5.1
optionalDependencies:
- '@tailwindcss/oxide-android-arm64': 4.1.13
- '@tailwindcss/oxide-darwin-arm64': 4.1.13
- '@tailwindcss/oxide-darwin-x64': 4.1.13
- '@tailwindcss/oxide-freebsd-x64': 4.1.13
- '@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.13
- '@tailwindcss/oxide-linux-arm64-gnu': 4.1.13
- '@tailwindcss/oxide-linux-arm64-musl': 4.1.13
- '@tailwindcss/oxide-linux-x64-gnu': 4.1.13
- '@tailwindcss/oxide-linux-x64-musl': 4.1.13
- '@tailwindcss/oxide-wasm32-wasi': 4.1.13
- '@tailwindcss/oxide-win32-arm64-msvc': 4.1.13
- '@tailwindcss/oxide-win32-x64-msvc': 4.1.13
-
- '@tailwindcss/vite@4.1.13(vite@7.1.7(@types/node@24.6.0)(jiti@2.6.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2))':
- dependencies:
- '@tailwindcss/node': 4.1.13
- '@tailwindcss/oxide': 4.1.13
- tailwindcss: 4.1.13
- vite: 7.1.7(@types/node@24.6.0)(jiti@2.6.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2)
-
- '@testing-library/dom@10.4.0':
+ '@tailwindcss/oxide-android-arm64': 4.1.14
+ '@tailwindcss/oxide-darwin-arm64': 4.1.14
+ '@tailwindcss/oxide-darwin-x64': 4.1.14
+ '@tailwindcss/oxide-freebsd-x64': 4.1.14
+ '@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.14
+ '@tailwindcss/oxide-linux-arm64-gnu': 4.1.14
+ '@tailwindcss/oxide-linux-arm64-musl': 4.1.14
+ '@tailwindcss/oxide-linux-x64-gnu': 4.1.14
+ '@tailwindcss/oxide-linux-x64-musl': 4.1.14
+ '@tailwindcss/oxide-wasm32-wasi': 4.1.14
+ '@tailwindcss/oxide-win32-arm64-msvc': 4.1.14
+ '@tailwindcss/oxide-win32-x64-msvc': 4.1.14
+
+ '@tailwindcss/vite@4.1.14(vite@7.1.10(@types/node@24.8.1)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2))':
+ dependencies:
+ '@tailwindcss/node': 4.1.14
+ '@tailwindcss/oxide': 4.1.14
+ tailwindcss: 4.1.14
+ vite: 7.1.10(@types/node@24.8.1)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2)
+
+ '@testing-library/dom@10.4.1':
dependencies:
'@babel/code-frame': 7.27.1
'@babel/runtime': 7.28.4
'@types/aria-query': 5.0.4
aria-query: 5.3.0
- chalk: 4.1.2
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.0':
+ '@testing-library/jest-dom@6.9.1':
dependencies:
'@adobe/css-tools': 4.4.4
aria-query: 5.3.2
@@ -10416,19 +10685,24 @@ snapshots:
picocolors: 1.1.1
redent: 3.0.0
- '@testing-library/react@16.3.0(@testing-library/dom@10.4.0)(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)':
+ '@testing-library/react@16.3.0(@testing-library/dom@10.4.1)(@types/react-dom@19.2.1(@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.4
- '@testing-library/dom': 10.4.0
+ '@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.1(@types/react@19.2.2)
- '@testing-library/user-event@14.6.1(@testing-library/dom@10.4.0)':
+ '@testing-library/user-event@13.5.0(@testing-library/dom@10.4.1)':
dependencies:
- '@testing-library/dom': 10.4.0
+ '@babel/runtime': 7.28.3
+ '@testing-library/dom': 10.4.1
+
+ '@testing-library/user-event@14.6.1(@testing-library/dom@10.4.1)':
+ dependencies:
+ '@testing-library/dom': 10.4.1
'@textlint/ast-node-types@15.2.2': {}
@@ -10461,14 +10735,14 @@ snapshots:
'@total-typescript/ts-reset@0.6.1': {}
- '@trpc/client@11.6.0(@trpc/server@11.6.0(typescript@5.9.2))(typescript@5.9.2)':
+ '@trpc/client@11.6.0(@trpc/server@11.6.0(typescript@5.9.3))(typescript@5.9.3)':
dependencies:
- '@trpc/server': 11.6.0(typescript@5.9.2)
- typescript: 5.9.2
+ '@trpc/server': 11.6.0(typescript@5.9.3)
+ typescript: 5.9.3
- '@trpc/server@11.6.0(typescript@5.9.2)':
+ '@trpc/server@11.6.0(typescript@5.9.3)':
dependencies:
- typescript: 5.9.2
+ typescript: 5.9.3
'@tsconfig/node10@1.0.9': {}
@@ -10486,24 +10760,24 @@ snapshots:
'@types/babel__core@7.20.5':
dependencies:
- '@babel/parser': 7.28.3
- '@babel/types': 7.28.2
+ '@babel/parser': 7.28.4
+ '@babel/types': 7.28.4
'@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.28.2
+ '@babel/types': 7.28.4
'@types/babel__template@7.4.4':
dependencies:
- '@babel/parser': 7.28.3
- '@babel/types': 7.28.2
+ '@babel/parser': 7.28.4
+ '@babel/types': 7.28.4
'@types/babel__traverse@7.28.0':
dependencies:
- '@babel/types': 7.28.2
+ '@babel/types': 7.28.4
'@types/chai@5.2.2':
dependencies:
@@ -10522,6 +10796,10 @@ snapshots:
'@types/estree@1.0.8': {}
+ '@types/hast@3.0.4':
+ dependencies:
+ '@types/unist': 3.0.3
+
'@types/istanbul-lib-coverage@2.0.6': {}
'@types/istanbul-lib-report@3.0.3':
@@ -10539,7 +10817,7 @@ snapshots:
'@types/jsdom@21.1.7':
dependencies:
- '@types/node': 24.6.0
+ '@types/node': 24.8.1
'@types/tough-cookie': 4.0.5
parse5: 7.2.1
@@ -10553,16 +10831,19 @@ snapshots:
dependencies:
'@types/unist': 2.0.10
+ '@types/mdast@4.0.4':
+ dependencies:
+ '@types/unist': 3.0.3
+
'@types/node@12.20.55': {}
- '@types/node@20.19.21':
+ '@types/node@20.19.22':
dependencies:
undici-types: 6.21.0
- optional: true
- '@types/node@24.6.0':
+ '@types/node@24.8.1':
dependencies:
- undici-types: 7.13.0
+ undici-types: 7.14.0
'@types/normalize-package-data@2.4.4': {}
@@ -10581,22 +10862,23 @@ snapshots:
'@types/stylus@0.48.43':
dependencies:
- '@types/node': 24.6.0
+ '@types/node': 24.8.1
'@types/tough-cookie@4.0.5': {}
'@types/unist@2.0.10': {}
+ '@types/unist@3.0.3': {}
+
'@types/vscode-webview@1.57.5': {}
- '@types/vscode@1.104.0': {}
+ '@types/vscode@1.105.0': {}
- '@types/whatwg-mimetype@3.0.2':
- optional: true
+ '@types/whatwg-mimetype@3.0.2': {}
'@types/ws@8.18.1':
dependencies:
- '@types/node': 24.6.0
+ '@types/node': 24.8.1
'@types/yargs-parser@21.0.3': {}
@@ -10604,34 +10886,34 @@ snapshots:
dependencies:
'@types/yargs-parser': 21.0.3
- '@typescript-eslint/eslint-plugin@7.11.0(@typescript-eslint/parser@7.11.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2))(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)':
+ '@typescript-eslint/eslint-plugin@7.11.0(@typescript-eslint/parser@7.11.0(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)':
dependencies:
'@eslint-community/regexpp': 4.10.0
- '@typescript-eslint/parser': 7.11.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)
+ '@typescript-eslint/parser': 7.11.0(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/scope-manager': 7.11.0
- '@typescript-eslint/type-utils': 7.11.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)
- '@typescript-eslint/utils': 7.11.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)
+ '@typescript-eslint/type-utils': 7.11.0(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)
+ '@typescript-eslint/utils': 7.11.0(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/visitor-keys': 7.11.0
- eslint: 9.36.0(jiti@2.6.0)
+ eslint: 9.38.0(jiti@2.6.1)
graphemer: 1.4.0
ignore: 5.3.1
natural-compare: 1.4.0
- ts-api-utils: 1.3.0(typescript@5.9.2)
+ ts-api-utils: 1.3.0(typescript@5.9.3)
optionalDependencies:
- typescript: 5.9.2
+ typescript: 5.9.3
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/parser@7.11.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)':
+ '@typescript-eslint/parser@7.11.0(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)':
dependencies:
'@typescript-eslint/scope-manager': 7.11.0
'@typescript-eslint/types': 7.11.0
- '@typescript-eslint/typescript-estree': 7.11.0(typescript@5.9.2)
+ '@typescript-eslint/typescript-estree': 7.11.0(typescript@5.9.3)
'@typescript-eslint/visitor-keys': 7.11.0
debug: 4.4.1
- eslint: 9.36.0(jiti@2.6.0)
+ eslint: 9.38.0(jiti@2.6.1)
optionalDependencies:
- typescript: 5.9.2
+ typescript: 5.9.3
transitivePeerDependencies:
- supports-color
@@ -10640,21 +10922,21 @@ snapshots:
'@typescript-eslint/types': 7.11.0
'@typescript-eslint/visitor-keys': 7.11.0
- '@typescript-eslint/type-utils@7.11.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)':
+ '@typescript-eslint/type-utils@7.11.0(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)':
dependencies:
- '@typescript-eslint/typescript-estree': 7.11.0(typescript@5.9.2)
- '@typescript-eslint/utils': 7.11.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)
+ '@typescript-eslint/typescript-estree': 7.11.0(typescript@5.9.3)
+ '@typescript-eslint/utils': 7.11.0(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)
debug: 4.4.1
- eslint: 9.36.0(jiti@2.6.0)
- ts-api-utils: 1.3.0(typescript@5.9.2)
+ eslint: 9.38.0(jiti@2.6.1)
+ ts-api-utils: 1.3.0(typescript@5.9.3)
optionalDependencies:
- typescript: 5.9.2
+ typescript: 5.9.3
transitivePeerDependencies:
- supports-color
'@typescript-eslint/types@7.11.0': {}
- '@typescript-eslint/typescript-estree@7.11.0(typescript@5.9.2)':
+ '@typescript-eslint/typescript-estree@7.11.0(typescript@5.9.3)':
dependencies:
'@typescript-eslint/types': 7.11.0
'@typescript-eslint/visitor-keys': 7.11.0
@@ -10663,19 +10945,19 @@ snapshots:
is-glob: 4.0.3
minimatch: 9.0.5
semver: 7.7.2
- ts-api-utils: 1.3.0(typescript@5.9.2)
+ ts-api-utils: 1.3.0(typescript@5.9.3)
optionalDependencies:
- typescript: 5.9.2
+ typescript: 5.9.3
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/utils@7.11.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)':
+ '@typescript-eslint/utils@7.11.0(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)':
dependencies:
- '@eslint-community/eslint-utils': 4.4.0(eslint@9.36.0(jiti@2.6.0))
+ '@eslint-community/eslint-utils': 4.4.0(eslint@9.38.0(jiti@2.6.1))
'@typescript-eslint/scope-manager': 7.11.0
'@typescript-eslint/types': 7.11.0
- '@typescript-eslint/typescript-estree': 7.11.0(typescript@5.9.2)
- eslint: 9.36.0(jiti@2.6.0)
+ '@typescript-eslint/typescript-estree': 7.11.0(typescript@5.9.3)
+ eslint: 9.38.0(jiti@2.6.1)
transitivePeerDependencies:
- supports-color
- typescript
@@ -10754,7 +11036,7 @@ snapshots:
'@unrs/resolver-binding-win32-x64-msvc@1.11.1':
optional: true
- '@vitejs/plugin-react@5.0.4(vite@5.4.19(@types/node@24.6.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0))':
+ '@vitejs/plugin-react@5.0.4(vite@5.4.19(@types/node@24.8.1)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0))':
dependencies:
'@babel/core': 7.28.4
'@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.4)
@@ -10762,11 +11044,11 @@ snapshots:
'@rolldown/pluginutils': 1.0.0-beta.38
'@types/babel__core': 7.20.5
react-refresh: 0.17.0
- vite: 5.4.19(@types/node@24.6.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)
+ vite: 5.4.19(@types/node@24.8.1)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)
transitivePeerDependencies:
- supports-color
- '@vitejs/plugin-react@5.0.4(vite@7.1.7(@types/node@24.6.0)(jiti@2.6.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2))':
+ '@vitejs/plugin-react@5.0.4(vite@7.1.10(@types/node@24.8.1)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2))':
dependencies:
'@babel/core': 7.28.4
'@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.4)
@@ -10774,7 +11056,7 @@ snapshots:
'@rolldown/pluginutils': 1.0.0-beta.38
'@types/babel__core': 7.20.5
react-refresh: 0.17.0
- vite: 7.1.7(@types/node@24.6.0)(jiti@2.6.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2)
+ vite: 7.1.10(@types/node@24.8.1)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2)
transitivePeerDependencies:
- supports-color
@@ -10793,37 +11075,38 @@ snapshots:
chai: 5.2.0
tinyrainbow: 2.0.0
- '@vitest/expect@4.0.0-beta.8':
+ '@vitest/expect@4.0.0-beta.18':
dependencies:
+ '@standard-schema/spec': 1.0.0
'@types/chai': 5.2.2
- '@vitest/spy': 4.0.0-beta.8
- '@vitest/utils': 4.0.0-beta.8
- chai: 5.2.1
- tinyrainbow: 2.0.0
+ '@vitest/spy': 4.0.0-beta.18
+ '@vitest/utils': 4.0.0-beta.18
+ chai: 6.2.0
+ tinyrainbow: 3.0.3
- '@vitest/mocker@2.1.8(vite@5.4.19(@types/node@24.6.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0))':
+ '@vitest/mocker@2.1.8(vite@5.4.19(@types/node@24.8.1)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0))':
dependencies:
'@vitest/spy': 2.1.8
estree-walker: 3.0.3
magic-string: 0.30.17
optionalDependencies:
- vite: 5.4.19(@types/node@24.6.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)
+ vite: 5.4.19(@types/node@24.8.1)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)
- '@vitest/mocker@3.2.4(vite@7.1.3(@types/node@24.6.0)(jiti@2.6.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2))':
+ '@vitest/mocker@3.2.4(vite@7.1.3(@types/node@24.8.1)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2))':
dependencies:
'@vitest/spy': 3.2.4
estree-walker: 3.0.3
magic-string: 0.30.17
optionalDependencies:
- vite: 7.1.3(@types/node@24.6.0)(jiti@2.6.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2)
+ vite: 7.1.3(@types/node@24.8.1)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2)
- '@vitest/mocker@4.0.0-beta.8(vite@7.1.7(@types/node@24.6.0)(jiti@2.6.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2))':
+ '@vitest/mocker@4.0.0-beta.18(vite@7.1.10(@types/node@24.8.1)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2))':
dependencies:
- '@vitest/spy': 4.0.0-beta.8
+ '@vitest/spy': 4.0.0-beta.18
estree-walker: 3.0.3
- magic-string: 0.30.17
+ magic-string: 0.30.19
optionalDependencies:
- vite: 7.1.7(@types/node@24.6.0)(jiti@2.6.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2)
+ vite: 7.1.10(@types/node@24.8.1)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2)
'@vitest/pretty-format@2.1.8':
dependencies:
@@ -10837,9 +11120,9 @@ snapshots:
dependencies:
tinyrainbow: 2.0.0
- '@vitest/pretty-format@4.0.0-beta.8':
+ '@vitest/pretty-format@4.0.0-beta.18':
dependencies:
- tinyrainbow: 2.0.0
+ tinyrainbow: 3.0.3
'@vitest/runner@2.1.8':
dependencies:
@@ -10852,11 +11135,10 @@ snapshots:
pathe: 2.0.3
strip-literal: 3.0.0
- '@vitest/runner@4.0.0-beta.8':
+ '@vitest/runner@4.0.0-beta.18':
dependencies:
- '@vitest/utils': 4.0.0-beta.8
+ '@vitest/utils': 4.0.0-beta.18
pathe: 2.0.3
- strip-literal: 3.0.0
'@vitest/snapshot@2.1.8':
dependencies:
@@ -10870,10 +11152,10 @@ snapshots:
magic-string: 0.30.17
pathe: 2.0.3
- '@vitest/snapshot@4.0.0-beta.8':
+ '@vitest/snapshot@4.0.0-beta.18':
dependencies:
- '@vitest/pretty-format': 4.0.0-beta.8
- magic-string: 0.30.17
+ '@vitest/pretty-format': 4.0.0-beta.18
+ magic-string: 0.30.19
pathe: 2.0.3
'@vitest/spy@2.1.8':
@@ -10884,7 +11166,7 @@ snapshots:
dependencies:
tinyspy: 4.0.3
- '@vitest/spy@4.0.0-beta.8': {}
+ '@vitest/spy@4.0.0-beta.18': {}
'@vitest/utils@2.1.8':
dependencies:
@@ -10898,19 +11180,18 @@ snapshots:
loupe: 3.1.4
tinyrainbow: 2.0.0
- '@vitest/utils@4.0.0-beta.8':
+ '@vitest/utils@4.0.0-beta.18':
dependencies:
- '@vitest/pretty-format': 4.0.0-beta.8
- loupe: 3.2.0
- tinyrainbow: 2.0.0
+ '@vitest/pretty-format': 4.0.0-beta.18
+ tinyrainbow: 3.0.3
- '@vscode/codicons@0.0.40': {}
+ '@vscode/codicons@0.0.41': {}
- '@vscode/extension-telemetry@1.0.0(tslib@2.8.1)':
+ '@vscode/extension-telemetry@1.1.0(tslib@2.8.1)':
dependencies:
- '@microsoft/1ds-core-js': 4.3.8(tslib@2.8.1)
- '@microsoft/1ds-post-js': 4.3.8(tslib@2.8.1)
- '@microsoft/applicationinsights-web-basic': 3.3.8(tslib@2.8.1)
+ '@microsoft/1ds-core-js': 4.3.10(tslib@2.8.1)
+ '@microsoft/1ds-post-js': 4.3.10(tslib@2.8.1)
+ '@microsoft/applicationinsights-web-basic': 3.3.10(tslib@2.8.1)
transitivePeerDependencies:
- tslib
@@ -11152,12 +11433,12 @@ snapshots:
dependencies:
'@types/babel__core': 7.20.5
- babel-plugin-jsx-dom-expressions@0.40.1(@babel/core@7.28.0):
+ babel-plugin-jsx-dom-expressions@0.40.1(@babel/core@7.28.4):
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.4
'@babel/helper-module-imports': 7.18.6
- '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.0)
- '@babel/types': 7.28.2
+ '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.4)
+ '@babel/types': 7.28.4
html-entities: 2.3.3
parse5: 7.3.0
validate-html-nesting: 1.2.3
@@ -11211,10 +11492,10 @@ snapshots:
babel-plugin-jest-hoist: 30.2.0
babel-preset-current-node-syntax: 1.2.0(@babel/core@7.28.4)
- babel-preset-solid@1.9.9(@babel/core@7.28.0)(solid-js@1.9.9):
+ babel-preset-solid@1.9.9(@babel/core@7.28.4)(solid-js@1.9.9):
dependencies:
- '@babel/core': 7.28.0
- babel-plugin-jsx-dom-expressions: 0.40.1(@babel/core@7.28.0)
+ '@babel/core': 7.28.4
+ babel-plugin-jsx-dom-expressions: 0.40.1(@babel/core@7.28.4)
optionalDependencies:
solid-js: 1.9.9
@@ -11337,7 +11618,9 @@ snapshots:
caniuse-lite@1.0.30001735: {}
- caniuse-lite@1.0.30001746: {}
+ caniuse-lite@1.0.30001751: {}
+
+ ccount@2.0.1: {}
chai@5.2.0:
dependencies:
@@ -11347,13 +11630,7 @@ snapshots:
loupe: 3.1.4
pathval: 2.0.1
- chai@5.2.1:
- dependencies:
- assertion-error: 2.0.1
- check-error: 2.1.1
- deep-eql: 5.0.2
- loupe: 3.2.0
- pathval: 2.0.1
+ chai@6.2.0: {}
chalk@4.1.2:
dependencies:
@@ -11364,8 +11641,12 @@ snapshots:
char-regex@1.0.2: {}
+ character-entities-html4@2.1.0: {}
+
character-entities-legacy@1.1.4: {}
+ character-entities-legacy@3.0.0: {}
+
character-entities@1.2.4: {}
character-reference-invalid@1.1.4: {}
@@ -11462,6 +11743,8 @@ snapshots:
dependencies:
delayed-stream: 1.0.0
+ comma-separated-tokens@2.0.3: {}
+
commander@12.1.0: {}
commander@4.1.1: {}
@@ -11598,10 +11881,17 @@ snapshots:
detect-libc@1.0.3:
optional: true
- detect-libc@2.1.1: {}
+ detect-libc@2.1.1:
+ optional: true
+
+ detect-libc@2.1.2: {}
detect-newline@3.1.0: {}
+ devlop@1.1.0:
+ dependencies:
+ dequal: 2.0.3
+
didyoumean@1.2.2: {}
diff@4.0.2: {}
@@ -11749,34 +12039,34 @@ snapshots:
'@esbuild/win32-ia32': 0.21.5
'@esbuild/win32-x64': 0.21.5
- esbuild@0.25.10:
+ esbuild@0.25.11:
optionalDependencies:
- '@esbuild/aix-ppc64': 0.25.10
- '@esbuild/android-arm': 0.25.10
- '@esbuild/android-arm64': 0.25.10
- '@esbuild/android-x64': 0.25.10
- '@esbuild/darwin-arm64': 0.25.10
- '@esbuild/darwin-x64': 0.25.10
- '@esbuild/freebsd-arm64': 0.25.10
- '@esbuild/freebsd-x64': 0.25.10
- '@esbuild/linux-arm': 0.25.10
- '@esbuild/linux-arm64': 0.25.10
- '@esbuild/linux-ia32': 0.25.10
- '@esbuild/linux-loong64': 0.25.10
- '@esbuild/linux-mips64el': 0.25.10
- '@esbuild/linux-ppc64': 0.25.10
- '@esbuild/linux-riscv64': 0.25.10
- '@esbuild/linux-s390x': 0.25.10
- '@esbuild/linux-x64': 0.25.10
- '@esbuild/netbsd-arm64': 0.25.10
- '@esbuild/netbsd-x64': 0.25.10
- '@esbuild/openbsd-arm64': 0.25.10
- '@esbuild/openbsd-x64': 0.25.10
- '@esbuild/openharmony-arm64': 0.25.10
- '@esbuild/sunos-x64': 0.25.10
- '@esbuild/win32-arm64': 0.25.10
- '@esbuild/win32-ia32': 0.25.10
- '@esbuild/win32-x64': 0.25.10
+ '@esbuild/aix-ppc64': 0.25.11
+ '@esbuild/android-arm': 0.25.11
+ '@esbuild/android-arm64': 0.25.11
+ '@esbuild/android-x64': 0.25.11
+ '@esbuild/darwin-arm64': 0.25.11
+ '@esbuild/darwin-x64': 0.25.11
+ '@esbuild/freebsd-arm64': 0.25.11
+ '@esbuild/freebsd-x64': 0.25.11
+ '@esbuild/linux-arm': 0.25.11
+ '@esbuild/linux-arm64': 0.25.11
+ '@esbuild/linux-ia32': 0.25.11
+ '@esbuild/linux-loong64': 0.25.11
+ '@esbuild/linux-mips64el': 0.25.11
+ '@esbuild/linux-ppc64': 0.25.11
+ '@esbuild/linux-riscv64': 0.25.11
+ '@esbuild/linux-s390x': 0.25.11
+ '@esbuild/linux-x64': 0.25.11
+ '@esbuild/netbsd-arm64': 0.25.11
+ '@esbuild/netbsd-x64': 0.25.11
+ '@esbuild/openbsd-arm64': 0.25.11
+ '@esbuild/openbsd-x64': 0.25.11
+ '@esbuild/openharmony-arm64': 0.25.11
+ '@esbuild/sunos-x64': 0.25.11
+ '@esbuild/win32-arm64': 0.25.11
+ '@esbuild/win32-ia32': 0.25.11
+ '@esbuild/win32-x64': 0.25.11
esbuild@0.25.6:
optionalDependencies:
@@ -11817,9 +12107,9 @@ snapshots:
escape-string-regexp@4.0.0: {}
- eslint-compat-utils@0.5.0(eslint@9.36.0(jiti@2.6.0)):
+ eslint-compat-utils@0.5.0(eslint@9.38.0(jiti@2.6.1)):
dependencies:
- eslint: 9.36.0(jiti@2.6.0)
+ eslint: 9.38.0(jiti@2.6.1)
semver: 7.7.2
eslint-config-flat-gitignore@0.1.5:
@@ -11840,39 +12130,39 @@ snapshots:
transitivePeerDependencies:
- supports-color
- eslint-merge-processors@0.1.0(eslint@9.36.0(jiti@2.6.0)):
+ eslint-merge-processors@0.1.0(eslint@9.38.0(jiti@2.6.1)):
dependencies:
- eslint: 9.36.0(jiti@2.6.0)
+ eslint: 9.38.0(jiti@2.6.1)
- eslint-plugin-antfu@2.3.3(eslint@9.36.0(jiti@2.6.0)):
+ eslint-plugin-antfu@2.3.3(eslint@9.38.0(jiti@2.6.1)):
dependencies:
'@antfu/utils': 0.7.8
- eslint: 9.36.0(jiti@2.6.0)
+ eslint: 9.38.0(jiti@2.6.1)
- eslint-plugin-command@0.2.3(eslint@9.36.0(jiti@2.6.0)):
+ eslint-plugin-command@0.2.3(eslint@9.38.0(jiti@2.6.1)):
dependencies:
'@es-joy/jsdoccomment': 0.43.1
- eslint: 9.36.0(jiti@2.6.0)
+ eslint: 9.38.0(jiti@2.6.1)
- eslint-plugin-es-x@7.6.0(eslint@9.36.0(jiti@2.6.0)):
+ eslint-plugin-es-x@7.6.0(eslint@9.38.0(jiti@2.6.1)):
dependencies:
- '@eslint-community/eslint-utils': 4.4.0(eslint@9.36.0(jiti@2.6.0))
+ '@eslint-community/eslint-utils': 4.4.0(eslint@9.38.0(jiti@2.6.1))
'@eslint-community/regexpp': 4.10.0
- eslint: 9.36.0(jiti@2.6.0)
- eslint-compat-utils: 0.5.0(eslint@9.36.0(jiti@2.6.0))
+ eslint: 9.38.0(jiti@2.6.1)
+ eslint-compat-utils: 0.5.0(eslint@9.38.0(jiti@2.6.1))
- eslint-plugin-eslint-comments@3.2.0(eslint@9.36.0(jiti@2.6.0)):
+ eslint-plugin-eslint-comments@3.2.0(eslint@9.38.0(jiti@2.6.1)):
dependencies:
escape-string-regexp: 1.0.5
- eslint: 9.36.0(jiti@2.6.0)
+ eslint: 9.38.0(jiti@2.6.1)
ignore: 5.3.1
- eslint-plugin-import-x@0.5.1(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2):
+ eslint-plugin-import-x@0.5.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3):
dependencies:
- '@typescript-eslint/utils': 7.11.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)
+ '@typescript-eslint/utils': 7.11.0(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)
debug: 4.4.1
doctrine: 3.0.0
- eslint: 9.36.0(jiti@2.6.0)
+ eslint: 9.38.0(jiti@2.6.1)
eslint-import-resolver-node: 0.3.9
get-tsconfig: 4.7.5
is-glob: 4.0.3
@@ -11883,44 +12173,44 @@ snapshots:
- supports-color
- typescript
- eslint-plugin-jsdoc@48.2.7(eslint@9.36.0(jiti@2.6.0)):
+ eslint-plugin-jsdoc@48.2.7(eslint@9.38.0(jiti@2.6.1)):
dependencies:
'@es-joy/jsdoccomment': 0.43.1
are-docs-informative: 0.0.2
comment-parser: 1.4.1
debug: 4.4.1
escape-string-regexp: 4.0.0
- eslint: 9.36.0(jiti@2.6.0)
+ eslint: 9.38.0(jiti@2.6.1)
esquery: 1.5.0
semver: 7.7.2
spdx-expression-parse: 4.0.0
transitivePeerDependencies:
- supports-color
- eslint-plugin-jsonc@2.16.0(eslint@9.36.0(jiti@2.6.0)):
+ eslint-plugin-jsonc@2.16.0(eslint@9.38.0(jiti@2.6.1)):
dependencies:
- '@eslint-community/eslint-utils': 4.4.0(eslint@9.36.0(jiti@2.6.0))
- eslint: 9.36.0(jiti@2.6.0)
- eslint-compat-utils: 0.5.0(eslint@9.36.0(jiti@2.6.0))
+ '@eslint-community/eslint-utils': 4.4.0(eslint@9.38.0(jiti@2.6.1))
+ eslint: 9.38.0(jiti@2.6.1)
+ eslint-compat-utils: 0.5.0(eslint@9.38.0(jiti@2.6.1))
espree: 9.6.1
graphemer: 1.4.0
jsonc-eslint-parser: 2.4.0
natural-compare: 1.4.0
synckit: 0.6.2
- eslint-plugin-markdown@5.0.0(eslint@9.36.0(jiti@2.6.0)):
+ eslint-plugin-markdown@5.0.0(eslint@9.38.0(jiti@2.6.1)):
dependencies:
- eslint: 9.36.0(jiti@2.6.0)
+ eslint: 9.38.0(jiti@2.6.1)
mdast-util-from-markdown: 0.8.5
transitivePeerDependencies:
- supports-color
- eslint-plugin-n@17.7.0(eslint@9.36.0(jiti@2.6.0)):
+ eslint-plugin-n@17.7.0(eslint@9.38.0(jiti@2.6.1)):
dependencies:
- '@eslint-community/eslint-utils': 4.4.0(eslint@9.36.0(jiti@2.6.0))
+ '@eslint-community/eslint-utils': 4.4.0(eslint@9.38.0(jiti@2.6.1))
enhanced-resolve: 5.18.2
- eslint: 9.36.0(jiti@2.6.0)
- eslint-plugin-es-x: 7.6.0(eslint@9.36.0(jiti@2.6.0))
+ eslint: 9.38.0(jiti@2.6.1)
+ eslint-plugin-es-x: 7.6.0(eslint@9.38.0(jiti@2.6.1))
get-tsconfig: 4.7.5
globals: 15.3.0
ignore: 5.3.1
@@ -11929,48 +12219,48 @@ snapshots:
eslint-plugin-no-only-tests@3.1.0: {}
- eslint-plugin-perfectionist@2.10.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)(vue-eslint-parser@9.4.2(eslint@9.36.0(jiti@2.6.0))):
+ eslint-plugin-perfectionist@2.10.0(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)(vue-eslint-parser@9.4.2(eslint@9.38.0(jiti@2.6.1))):
dependencies:
- '@typescript-eslint/utils': 7.11.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)
- eslint: 9.36.0(jiti@2.6.0)
+ '@typescript-eslint/utils': 7.11.0(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)
+ eslint: 9.38.0(jiti@2.6.1)
minimatch: 9.0.4
natural-compare-lite: 1.4.0
optionalDependencies:
- vue-eslint-parser: 9.4.2(eslint@9.36.0(jiti@2.6.0))
+ vue-eslint-parser: 9.4.2(eslint@9.38.0(jiti@2.6.1))
transitivePeerDependencies:
- supports-color
- typescript
- eslint-plugin-regexp@2.6.0(eslint@9.36.0(jiti@2.6.0)):
+ eslint-plugin-regexp@2.6.0(eslint@9.38.0(jiti@2.6.1)):
dependencies:
- '@eslint-community/eslint-utils': 4.4.0(eslint@9.36.0(jiti@2.6.0))
+ '@eslint-community/eslint-utils': 4.4.0(eslint@9.38.0(jiti@2.6.1))
'@eslint-community/regexpp': 4.10.0
comment-parser: 1.4.1
- eslint: 9.36.0(jiti@2.6.0)
+ eslint: 9.38.0(jiti@2.6.1)
jsdoc-type-pratt-parser: 4.0.0
refa: 0.12.1
regexp-ast-analysis: 0.7.1
scslre: 0.3.0
- eslint-plugin-toml@0.11.0(eslint@9.36.0(jiti@2.6.0)):
+ eslint-plugin-toml@0.11.0(eslint@9.38.0(jiti@2.6.1)):
dependencies:
debug: 4.4.1
- eslint: 9.36.0(jiti@2.6.0)
- eslint-compat-utils: 0.5.0(eslint@9.36.0(jiti@2.6.0))
+ eslint: 9.38.0(jiti@2.6.1)
+ eslint-compat-utils: 0.5.0(eslint@9.38.0(jiti@2.6.1))
lodash: 4.17.21
toml-eslint-parser: 0.9.3
transitivePeerDependencies:
- supports-color
- eslint-plugin-unicorn@53.0.0(eslint@9.36.0(jiti@2.6.0)):
+ eslint-plugin-unicorn@53.0.0(eslint@9.38.0(jiti@2.6.1)):
dependencies:
'@babel/helper-validator-identifier': 7.24.6
- '@eslint-community/eslint-utils': 4.4.0(eslint@9.36.0(jiti@2.6.0))
+ '@eslint-community/eslint-utils': 4.4.0(eslint@9.38.0(jiti@2.6.1))
'@eslint/eslintrc': 3.1.0
ci-info: 4.0.0
clean-regexp: 1.0.0
core-js-compat: 3.37.1
- eslint: 9.36.0(jiti@2.6.0)
+ eslint: 9.38.0(jiti@2.6.1)
esquery: 1.5.0
indent-string: 4.0.0
is-builtin-module: 3.2.1
@@ -11984,53 +12274,53 @@ snapshots:
transitivePeerDependencies:
- supports-color
- eslint-plugin-unused-imports@3.2.0(@typescript-eslint/eslint-plugin@7.11.0(@typescript-eslint/parser@7.11.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2))(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2))(eslint@9.36.0(jiti@2.6.0)):
+ eslint-plugin-unused-imports@3.2.0(@typescript-eslint/eslint-plugin@7.11.0(@typescript-eslint/parser@7.11.0(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.38.0(jiti@2.6.1)):
dependencies:
- eslint: 9.36.0(jiti@2.6.0)
+ eslint: 9.38.0(jiti@2.6.1)
eslint-rule-composer: 0.3.0
optionalDependencies:
- '@typescript-eslint/eslint-plugin': 7.11.0(@typescript-eslint/parser@7.11.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2))(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)
+ '@typescript-eslint/eslint-plugin': 7.11.0(@typescript-eslint/parser@7.11.0(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)
- eslint-plugin-vitest@0.5.4(@typescript-eslint/eslint-plugin@7.11.0(@typescript-eslint/parser@7.11.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2))(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2))(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)(vitest@3.2.4(@types/node@24.6.0)(happy-dom@20.0.0)(jiti@2.6.0)(jsdom@26.1.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2)):
+ eslint-plugin-vitest@0.5.4(@typescript-eslint/eslint-plugin@7.11.0(@typescript-eslint/parser@7.11.0(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)(vitest@3.2.4(@types/node@24.8.1)(happy-dom@20.0.8)(jiti@2.6.1)(jsdom@26.1.0)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2)):
dependencies:
- '@typescript-eslint/utils': 7.11.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)
- eslint: 9.36.0(jiti@2.6.0)
+ '@typescript-eslint/utils': 7.11.0(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)
+ eslint: 9.38.0(jiti@2.6.1)
optionalDependencies:
- '@typescript-eslint/eslint-plugin': 7.11.0(@typescript-eslint/parser@7.11.0(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2))(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)
- vitest: 3.2.4(@types/node@24.6.0)(happy-dom@20.0.0)(jiti@2.6.0)(jsdom@26.1.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2)
+ '@typescript-eslint/eslint-plugin': 7.11.0(@typescript-eslint/parser@7.11.0(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)
+ vitest: 3.2.4(@types/node@24.8.1)(happy-dom@20.0.8)(jiti@2.6.1)(jsdom@26.1.0)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2)
transitivePeerDependencies:
- supports-color
- typescript
- eslint-plugin-vue@9.26.0(eslint@9.36.0(jiti@2.6.0)):
+ eslint-plugin-vue@9.26.0(eslint@9.38.0(jiti@2.6.1)):
dependencies:
- '@eslint-community/eslint-utils': 4.4.0(eslint@9.36.0(jiti@2.6.0))
- eslint: 9.36.0(jiti@2.6.0)
+ '@eslint-community/eslint-utils': 4.4.0(eslint@9.38.0(jiti@2.6.1))
+ eslint: 9.38.0(jiti@2.6.1)
globals: 13.24.0
natural-compare: 1.4.0
nth-check: 2.1.1
postcss-selector-parser: 6.1.0
semver: 7.7.2
- vue-eslint-parser: 9.4.2(eslint@9.36.0(jiti@2.6.0))
+ vue-eslint-parser: 9.4.2(eslint@9.38.0(jiti@2.6.1))
xml-name-validator: 4.0.0
transitivePeerDependencies:
- supports-color
- eslint-plugin-yml@1.14.0(eslint@9.36.0(jiti@2.6.0)):
+ eslint-plugin-yml@1.14.0(eslint@9.38.0(jiti@2.6.1)):
dependencies:
debug: 4.4.1
- eslint: 9.36.0(jiti@2.6.0)
- eslint-compat-utils: 0.5.0(eslint@9.36.0(jiti@2.6.0))
+ eslint: 9.38.0(jiti@2.6.1)
+ eslint-compat-utils: 0.5.0(eslint@9.38.0(jiti@2.6.1))
lodash: 4.17.21
natural-compare: 1.4.0
yaml-eslint-parser: 1.2.3
transitivePeerDependencies:
- supports-color
- eslint-processor-vue-blocks@0.1.2(@vue/compiler-sfc@3.4.34)(eslint@9.36.0(jiti@2.6.0)):
+ eslint-processor-vue-blocks@0.1.2(@vue/compiler-sfc@3.4.34)(eslint@9.38.0(jiti@2.6.1)):
dependencies:
'@vue/compiler-sfc': 3.4.34
- eslint: 9.36.0(jiti@2.6.0)
+ eslint: 9.38.0(jiti@2.6.1)
eslint-rule-composer@0.3.0: {}
@@ -12050,21 +12340,20 @@ snapshots:
eslint-visitor-keys@4.2.1: {}
- eslint@9.36.0(jiti@2.6.0):
+ eslint@9.38.0(jiti@2.6.1):
dependencies:
- '@eslint-community/eslint-utils': 4.9.0(eslint@9.36.0(jiti@2.6.0))
+ '@eslint-community/eslint-utils': 4.9.0(eslint@9.38.0(jiti@2.6.1))
'@eslint-community/regexpp': 4.12.1
- '@eslint/config-array': 0.21.0
- '@eslint/config-helpers': 0.3.1
- '@eslint/core': 0.15.2
+ '@eslint/config-array': 0.21.1
+ '@eslint/config-helpers': 0.4.1
+ '@eslint/core': 0.16.0
'@eslint/eslintrc': 3.3.1
- '@eslint/js': 9.36.0
- '@eslint/plugin-kit': 0.3.5
+ '@eslint/js': 9.38.0
+ '@eslint/plugin-kit': 0.4.0
'@humanfs/node': 0.16.7
'@humanwhocodes/module-importer': 1.0.1
'@humanwhocodes/retry': 0.4.3
'@types/estree': 1.0.8
- '@types/json-schema': 7.0.15
ajv: 6.12.6
chalk: 4.1.2
cross-spawn: 7.0.6
@@ -12088,7 +12377,7 @@ snapshots:
natural-compare: 1.4.0
optionator: 0.9.4
optionalDependencies:
- jiti: 2.6.0
+ jiti: 2.6.1
transitivePeerDependencies:
- supports-color
@@ -12442,12 +12731,11 @@ snapshots:
webidl-conversions: 7.0.0
whatwg-mimetype: 3.0.0
- happy-dom@20.0.0:
+ happy-dom@20.0.8:
dependencies:
- '@types/node': 20.19.21
+ '@types/node': 20.19.22
'@types/whatwg-mimetype': 3.0.2
whatwg-mimetype: 3.0.0
- optional: true
harmony-reflect@1.6.2: {}
@@ -12471,6 +12759,24 @@ snapshots:
dependencies:
function-bind: 1.1.2
+ hast-util-to-html@9.0.5:
+ dependencies:
+ '@types/hast': 3.0.4
+ '@types/unist': 3.0.3
+ ccount: 2.0.1
+ comma-separated-tokens: 2.0.3
+ hast-util-whitespace: 3.0.0
+ html-void-elements: 3.0.0
+ mdast-util-to-hast: 13.2.0
+ property-information: 7.1.0
+ space-separated-tokens: 2.0.2
+ stringify-entities: 4.0.4
+ zwitch: 2.0.4
+
+ hast-util-whitespace@3.0.0:
+ dependencies:
+ '@types/hast': 3.0.4
+
hosted-git-info@2.8.9: {}
hosted-git-info@4.1.0:
@@ -12489,6 +12795,8 @@ snapshots:
html-escaper@2.0.2: {}
+ html-void-elements@3.0.0: {}
+
htmlparser2@10.0.0:
dependencies:
domelementtype: 2.3.0
@@ -12718,7 +13026,7 @@ snapshots:
'@jest/expect': 30.2.0
'@jest/test-result': 30.2.0
'@jest/types': 30.2.0
- '@types/node': 24.6.0
+ '@types/node': 24.8.1
chalk: 4.1.2
co: 4.6.0
dedent: 1.7.0
@@ -12738,15 +13046,15 @@ snapshots:
- babel-plugin-macros
- supports-color
- jest-cli@30.2.0(@types/node@24.6.0)(ts-node@10.9.2(@types/node@24.6.0)(typescript@5.9.2)):
+ jest-cli@30.2.0(@types/node@24.8.1)(ts-node@10.9.2(@types/node@24.8.1)(typescript@5.9.3)):
dependencies:
- '@jest/core': 30.2.0(ts-node@10.9.2(@types/node@24.6.0)(typescript@5.9.2))
+ '@jest/core': 30.2.0(ts-node@10.9.2(@types/node@24.8.1)(typescript@5.9.3))
'@jest/test-result': 30.2.0
'@jest/types': 30.2.0
chalk: 4.1.2
exit-x: 0.2.2
import-local: 3.2.0
- jest-config: 30.2.0(patch_hash=7183ebeb461331a42f7b4be95c553b6304fa99af85998b66f7f8c91aa96e8d46)(@types/node@24.6.0)(ts-node@10.9.2(@types/node@24.6.0)(typescript@5.9.2))
+ jest-config: 30.2.0(patch_hash=7183ebeb461331a42f7b4be95c553b6304fa99af85998b66f7f8c91aa96e8d46)(@types/node@24.8.1)(ts-node@10.9.2(@types/node@24.8.1)(typescript@5.9.3))
jest-util: 30.2.0
jest-validate: 30.2.0
yargs: 17.7.2
@@ -12757,7 +13065,7 @@ snapshots:
- supports-color
- ts-node
- jest-config@30.2.0(patch_hash=7183ebeb461331a42f7b4be95c553b6304fa99af85998b66f7f8c91aa96e8d46)(@types/node@24.6.0)(ts-node@10.9.2(@types/node@24.6.0)(typescript@5.9.2)):
+ jest-config@30.2.0(patch_hash=7183ebeb461331a42f7b4be95c553b6304fa99af85998b66f7f8c91aa96e8d46)(@types/node@24.8.1)(ts-node@10.9.2(@types/node@24.8.1)(typescript@5.9.3)):
dependencies:
'@babel/core': 7.28.4
'@jest/get-type': 30.1.0
@@ -12784,8 +13092,8 @@ snapshots:
slash: 3.0.0
strip-json-comments: 3.1.1
optionalDependencies:
- '@types/node': 24.6.0
- ts-node: 10.9.2(@types/node@24.6.0)(typescript@5.9.2)
+ '@types/node': 24.8.1
+ ts-node: 10.9.2(@types/node@24.8.1)(typescript@5.9.3)
transitivePeerDependencies:
- babel-plugin-macros
- supports-color
@@ -12821,7 +13129,7 @@ snapshots:
'@jest/environment': 30.2.0
'@jest/environment-jsdom-abstract': 30.2.0(jsdom@26.1.0)
'@types/jsdom': 21.1.7
- '@types/node': 24.6.0
+ '@types/node': 24.8.1
jsdom: 26.1.0
transitivePeerDependencies:
- bufferutil
@@ -12833,7 +13141,7 @@ snapshots:
'@jest/environment': 30.2.0
'@jest/fake-timers': 30.2.0
'@jest/types': 30.2.0
- '@types/node': 24.6.0
+ '@types/node': 24.8.1
jest-mock: 30.2.0
jest-util: 30.2.0
jest-validate: 30.2.0
@@ -12841,7 +13149,7 @@ snapshots:
jest-haste-map@30.2.0:
dependencies:
'@jest/types': 30.2.0
- '@types/node': 24.6.0
+ '@types/node': 24.8.1
anymatch: 3.1.3
fb-watchman: 2.0.2
graceful-fs: 4.2.11
@@ -12899,13 +13207,13 @@ snapshots:
jest-mock@30.0.2:
dependencies:
'@jest/types': 30.0.1
- '@types/node': 24.6.0
+ '@types/node': 24.8.1
jest-util: 30.0.2
jest-mock@30.2.0:
dependencies:
'@jest/types': 30.2.0
- '@types/node': 24.6.0
+ '@types/node': 24.8.1
jest-util: 30.2.0
jest-pnp-resolver@1.2.3(jest-resolve@30.2.0):
@@ -12939,7 +13247,7 @@ snapshots:
'@jest/test-result': 30.2.0
'@jest/transform': 30.2.0
'@jest/types': 30.2.0
- '@types/node': 24.6.0
+ '@types/node': 24.8.1
chalk: 4.1.2
emittery: 0.13.1
exit-x: 0.2.2
@@ -12968,7 +13276,7 @@ snapshots:
'@jest/test-result': 30.2.0
'@jest/transform': 30.2.0
'@jest/types': 30.2.0
- '@types/node': 24.6.0
+ '@types/node': 24.8.1
chalk: 4.1.2
cjs-module-lexer: 2.1.0
collect-v8-coverage: 1.0.2
@@ -13015,7 +13323,7 @@ snapshots:
jest-util@30.0.2:
dependencies:
'@jest/types': 30.0.1
- '@types/node': 24.6.0
+ '@types/node': 24.8.1
chalk: 4.1.2
ci-info: 4.3.0
graceful-fs: 4.2.11
@@ -13024,7 +13332,7 @@ snapshots:
jest-util@30.2.0:
dependencies:
'@jest/types': 30.2.0
- '@types/node': 24.6.0
+ '@types/node': 24.8.1
chalk: 4.1.2
ci-info: 4.3.0
graceful-fs: 4.2.11
@@ -13043,7 +13351,7 @@ snapshots:
dependencies:
'@jest/test-result': 30.2.0
'@jest/types': 30.2.0
- '@types/node': 24.6.0
+ '@types/node': 24.8.1
ansi-escapes: 4.3.2
chalk: 4.1.2
emittery: 0.13.1
@@ -13052,18 +13360,18 @@ snapshots:
jest-worker@30.2.0:
dependencies:
- '@types/node': 24.6.0
+ '@types/node': 24.8.1
'@ungap/structured-clone': 1.3.0
jest-util: 30.2.0
merge-stream: 2.0.0
supports-color: 8.1.1
- jest@30.2.0(@types/node@24.6.0)(ts-node@10.9.2(@types/node@24.6.0)(typescript@5.9.2)):
+ jest@30.2.0(@types/node@24.8.1)(ts-node@10.9.2(@types/node@24.8.1)(typescript@5.9.3)):
dependencies:
- '@jest/core': 30.2.0(ts-node@10.9.2(@types/node@24.6.0)(typescript@5.9.2))
+ '@jest/core': 30.2.0(ts-node@10.9.2(@types/node@24.8.1)(typescript@5.9.3))
'@jest/types': 30.2.0
import-local: 3.2.0
- jest-cli: 30.2.0(@types/node@24.6.0)(ts-node@10.9.2(@types/node@24.6.0)(typescript@5.9.2))
+ jest-cli: 30.2.0(@types/node@24.8.1)(ts-node@10.9.2(@types/node@24.8.1)(typescript@5.9.3))
transitivePeerDependencies:
- '@types/node'
- babel-plugin-macros
@@ -13073,7 +13381,7 @@ snapshots:
jiti@1.21.7: {}
- jiti@2.6.0: {}
+ jiti@2.6.1: {}
joycon@3.1.1: {}
@@ -13192,7 +13500,7 @@ snapshots:
dependencies:
json-buffer: 3.0.1
- less@4.4.1:
+ less@4.4.2:
dependencies:
copy-anything: 2.0.6
parse-node-version: 1.0.1
@@ -13245,7 +13553,7 @@ snapshots:
lightningcss@1.30.1:
dependencies:
- detect-libc: 2.1.1
+ detect-libc: 2.1.2
optionalDependencies:
lightningcss-darwin-arm64: 1.30.1
lightningcss-darwin-x64: 1.30.1
@@ -13319,8 +13627,6 @@ snapshots:
loupe@3.1.4: {}
- loupe@3.2.0: {}
-
lru-cache@10.4.3: {}
lru-cache@11.2.2: {}
@@ -13333,7 +13639,7 @@ snapshots:
dependencies:
yallist: 4.0.0
- lucide-solid@0.544.0(solid-js@1.9.9):
+ lucide-solid@0.546.0(solid-js@1.9.9):
dependencies:
solid-js: 1.9.9
@@ -13355,7 +13661,7 @@ snapshots:
make-dir@4.0.0:
dependencies:
- semver: 7.7.2
+ semver: 7.7.3
make-error@1.3.6: {}
@@ -13384,6 +13690,18 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ mdast-util-to-hast@13.2.0:
+ dependencies:
+ '@types/hast': 3.0.4
+ '@types/mdast': 4.0.4
+ '@ungap/structured-clone': 1.3.0
+ devlop: 1.1.0
+ micromark-util-sanitize-uri: 2.0.1
+ trim-lines: 3.0.1
+ unist-util-position: 5.0.0
+ unist-util-visit: 5.0.0
+ vfile: 6.0.3
+
mdast-util-to-string@2.0.0: {}
mdurl@2.0.0: {}
@@ -13396,6 +13714,23 @@ snapshots:
merge2@1.4.1: {}
+ micromark-util-character@2.1.1:
+ dependencies:
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-util-encode@2.0.1: {}
+
+ micromark-util-sanitize-uri@2.0.1:
+ dependencies:
+ micromark-util-character: 2.1.1
+ micromark-util-encode: 2.0.1
+ micromark-util-symbol: 2.0.1
+
+ micromark-util-symbol@2.0.1: {}
+
+ micromark-util-types@2.0.2: {}
+
micromark@2.11.4:
dependencies:
debug: 4.4.1
@@ -13498,25 +13833,25 @@ snapshots:
sax: 1.4.1
optional: true
- next@15.5.4(@babel/core@7.28.4)(@playwright/test@1.55.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(sass@1.93.2):
+ next@15.5.6(@babel/core@7.28.4)(@playwright/test@1.56.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(sass@1.93.2):
dependencies:
- '@next/env': 15.5.4
+ '@next/env': 15.5.6
'@swc/helpers': 0.5.15
- caniuse-lite: 1.0.30001746
+ caniuse-lite: 1.0.30001751
postcss: 8.4.31
react: 19.2.0
react-dom: 19.2.0(react@19.2.0)
styled-jsx: 5.1.6(@babel/core@7.28.4)(react@19.2.0)
optionalDependencies:
- '@next/swc-darwin-arm64': 15.5.4
- '@next/swc-darwin-x64': 15.5.4
- '@next/swc-linux-arm64-gnu': 15.5.4
- '@next/swc-linux-arm64-musl': 15.5.4
- '@next/swc-linux-x64-gnu': 15.5.4
- '@next/swc-linux-x64-musl': 15.5.4
- '@next/swc-win32-arm64-msvc': 15.5.4
- '@next/swc-win32-x64-msvc': 15.5.4
- '@playwright/test': 1.55.1
+ '@next/swc-darwin-arm64': 15.5.6
+ '@next/swc-darwin-x64': 15.5.6
+ '@next/swc-linux-arm64-gnu': 15.5.6
+ '@next/swc-linux-arm64-musl': 15.5.6
+ '@next/swc-linux-x64-gnu': 15.5.6
+ '@next/swc-linux-x64-musl': 15.5.6
+ '@next/swc-win32-arm64-msvc': 15.5.6
+ '@next/swc-win32-x64-msvc': 15.5.6
+ '@playwright/test': 1.56.1
sass: 1.93.2
sharp: 0.34.4
transitivePeerDependencies:
@@ -13593,6 +13928,14 @@ snapshots:
dependencies:
mimic-fn: 2.1.0
+ oniguruma-parser@0.12.1: {}
+
+ oniguruma-to-es@4.3.3:
+ dependencies:
+ oniguruma-parser: 0.12.1
+ regex: 6.0.1
+ regex-recursion: 6.0.2
+
open@10.2.0:
dependencies:
default-browser: 5.2.1
@@ -13625,6 +13968,26 @@ snapshots:
- debug
- supports-color
+ oxc-parser@0.95.0:
+ dependencies:
+ '@oxc-project/types': 0.95.0
+ optionalDependencies:
+ '@oxc-parser/binding-android-arm64': 0.95.0
+ '@oxc-parser/binding-darwin-arm64': 0.95.0
+ '@oxc-parser/binding-darwin-x64': 0.95.0
+ '@oxc-parser/binding-freebsd-x64': 0.95.0
+ '@oxc-parser/binding-linux-arm-gnueabihf': 0.95.0
+ '@oxc-parser/binding-linux-arm-musleabihf': 0.95.0
+ '@oxc-parser/binding-linux-arm64-gnu': 0.95.0
+ '@oxc-parser/binding-linux-arm64-musl': 0.95.0
+ '@oxc-parser/binding-linux-riscv64-gnu': 0.95.0
+ '@oxc-parser/binding-linux-s390x-gnu': 0.95.0
+ '@oxc-parser/binding-linux-x64-gnu': 0.95.0
+ '@oxc-parser/binding-linux-x64-musl': 0.95.0
+ '@oxc-parser/binding-wasm32-wasi': 0.95.0
+ '@oxc-parser/binding-win32-arm64-msvc': 0.95.0
+ '@oxc-parser/binding-win32-x64-msvc': 0.95.0
+
p-filter@2.1.0:
dependencies:
p-map: 2.1.0
@@ -13784,11 +14147,11 @@ snapshots:
mlly: 1.7.4
pathe: 2.0.3
- playwright-core@1.55.1: {}
+ playwright-core@1.56.1: {}
- playwright@1.55.1:
+ playwright@1.56.1:
dependencies:
- playwright-core: 1.55.1
+ playwright-core: 1.56.1
optionalDependencies:
fsevents: 2.3.2
@@ -13808,19 +14171,19 @@ snapshots:
camelcase-css: 2.0.1
postcss: 8.5.6
- postcss-load-config@4.0.2(postcss@8.5.6)(ts-node@10.9.2(@types/node@24.6.0)(typescript@5.9.2)):
+ postcss-load-config@4.0.2(postcss@8.5.6)(ts-node@10.9.2(@types/node@24.8.1)(typescript@5.9.3)):
dependencies:
lilconfig: 3.1.3
yaml: 2.4.2
optionalDependencies:
postcss: 8.5.6
- ts-node: 10.9.2(@types/node@24.6.0)(typescript@5.9.2)
+ ts-node: 10.9.2(@types/node@24.8.1)(typescript@5.9.3)
- postcss-load-config@6.0.1(jiti@2.6.0)(postcss@8.5.6)(yaml@2.4.2):
+ postcss-load-config@6.0.1(jiti@2.6.1)(postcss@8.5.6)(yaml@2.4.2):
dependencies:
lilconfig: 3.1.1
optionalDependencies:
- jiti: 2.6.0
+ jiti: 2.6.1
postcss: 8.5.6
yaml: 2.4.2
@@ -13895,6 +14258,8 @@ snapshots:
dependencies:
parse-ms: 4.0.0
+ property-information@7.1.0: {}
+
prr@1.0.1:
optional: true
@@ -14012,6 +14377,16 @@ snapshots:
regenerate@1.4.2: {}
+ regex-recursion@6.0.2:
+ dependencies:
+ regex-utilities: 2.3.0
+
+ regex-utilities@2.3.0: {}
+
+ regex@6.0.1:
+ dependencies:
+ regex-utilities: 2.3.0
+
regexp-ast-analysis@0.7.1:
dependencies:
'@eslint-community/regexpp': 4.10.0
@@ -14195,6 +14570,8 @@ snapshots:
semver@7.7.2: {}
+ semver@7.7.3: {}
+
seroval-plugins@1.3.2(seroval@1.3.2):
dependencies:
seroval: 1.3.2
@@ -14206,8 +14583,8 @@ snapshots:
sharp@0.34.4:
dependencies:
'@img/colour': 1.0.0
- detect-libc: 2.1.1
- semver: 7.7.2
+ detect-libc: 2.1.2
+ semver: 7.7.3
optionalDependencies:
'@img/sharp-darwin-arm64': 0.34.4
'@img/sharp-darwin-x64': 0.34.4
@@ -14239,6 +14616,17 @@ snapshots:
shebang-regex@3.0.0: {}
+ shiki@3.13.0:
+ dependencies:
+ '@shikijs/core': 3.13.0
+ '@shikijs/engine-javascript': 3.13.0
+ '@shikijs/engine-oniguruma': 3.13.0
+ '@shikijs/langs': 3.13.0
+ '@shikijs/themes': 3.13.0
+ '@shikijs/types': 3.13.0
+ '@shikijs/vscode-textmate': 10.0.2
+ '@types/hast': 3.0.4
+
side-channel-list@1.0.0:
dependencies:
es-errors: 1.3.0
@@ -14315,9 +14703,9 @@ snapshots:
solid-refresh@0.6.3(solid-js@1.9.9):
dependencies:
- '@babel/generator': 7.28.0
+ '@babel/generator': 7.28.3
'@babel/helper-module-imports': 7.27.1
- '@babel/types': 7.28.2
+ '@babel/types': 7.28.4
solid-js: 1.9.9
transitivePeerDependencies:
- supports-color
@@ -14337,6 +14725,8 @@ snapshots:
dependencies:
whatwg-url: 7.1.0
+ space-separated-tokens@2.0.2: {}
+
spawndamnit@3.0.1:
dependencies:
cross-spawn: 7.0.6
@@ -14395,6 +14785,11 @@ snapshots:
safe-buffer: 5.2.1
optional: true
+ stringify-entities@4.0.4:
+ dependencies:
+ character-entities-html4: 2.1.0
+ character-entities-legacy: 3.0.0
+
strip-ansi@6.0.1:
dependencies:
ansi-regex: 5.0.1
@@ -14498,11 +14893,11 @@ snapshots:
tailwind-merge@3.3.1: {}
- tailwindcss-animate@1.0.7(tailwindcss@4.1.13):
+ tailwindcss-animate@1.0.7(tailwindcss@4.1.14):
dependencies:
- tailwindcss: 4.1.13
+ tailwindcss: 4.1.14
- tailwindcss@3.4.17(ts-node@10.9.2(@types/node@24.6.0)(typescript@5.9.2)):
+ tailwindcss@3.4.17(ts-node@10.9.2(@types/node@24.8.1)(typescript@5.9.3)):
dependencies:
'@alloc/quick-lru': 5.2.0
arg: 5.0.2
@@ -14521,7 +14916,7 @@ snapshots:
postcss: 8.5.6
postcss-import: 15.1.0(postcss@8.5.6)
postcss-js: 4.0.1(postcss@8.5.6)
- postcss-load-config: 4.0.2(postcss@8.5.6)(ts-node@10.9.2(@types/node@24.6.0)(typescript@5.9.2))
+ postcss-load-config: 4.0.2(postcss@8.5.6)(ts-node@10.9.2(@types/node@24.8.1)(typescript@5.9.3))
postcss-nested: 6.2.0(postcss@8.5.6)
postcss-selector-parser: 6.1.2
resolve: 1.22.10
@@ -14529,7 +14924,9 @@ snapshots:
transitivePeerDependencies:
- ts-node
- tailwindcss@4.1.13: {}
+ tailwindcss@4.1.14: {}
+
+ tailwindcss@4.1.16: {}
tapable@2.2.2: {}
@@ -14601,10 +14998,14 @@ snapshots:
tinypool@1.1.1: {}
+ tinypool@2.0.0: {}
+
tinyrainbow@1.2.0: {}
tinyrainbow@2.0.0: {}
+ tinyrainbow@3.0.3: {}
+
tinyspy@3.0.2: {}
tinyspy@4.0.3: {}
@@ -14641,27 +15042,29 @@ snapshots:
tree-kill@1.2.2: {}
- ts-api-utils@1.3.0(typescript@5.9.2):
+ trim-lines@3.0.1: {}
+
+ ts-api-utils@1.3.0(typescript@5.9.3):
dependencies:
- typescript: 5.9.2
+ typescript: 5.9.3
ts-interface-checker@0.1.13: {}
- ts-node@10.9.2(@types/node@24.6.0)(typescript@5.9.2):
+ ts-node@10.9.2(@types/node@24.8.1)(typescript@5.9.3):
dependencies:
'@cspotcode/source-map-support': 0.8.1
'@tsconfig/node10': 1.0.9
'@tsconfig/node12': 1.0.11
'@tsconfig/node14': 1.0.3
'@tsconfig/node16': 1.0.4
- '@types/node': 24.6.0
+ '@types/node': 24.8.1
acorn: 8.15.0
acorn-walk: 8.3.2
arg: 4.1.3
create-require: 1.1.1
diff: 4.0.2
make-error: 1.3.6
- typescript: 5.9.2
+ typescript: 5.9.3
v8-compile-cache-lib: 3.0.1
yn: 3.1.1
@@ -14669,7 +15072,7 @@ snapshots:
tslib@2.8.1: {}
- tsup@8.5.0(jiti@2.6.0)(postcss@8.5.6)(typescript@5.9.2)(yaml@2.4.2):
+ tsup@8.5.0(jiti@2.6.1)(postcss@8.5.6)(typescript@5.9.3)(yaml@2.4.2):
dependencies:
bundle-require: 5.1.0(esbuild@0.25.6)
cac: 6.7.14
@@ -14680,7 +15083,7 @@ snapshots:
fix-dts-default-cjs-exports: 1.0.1
joycon: 3.1.1
picocolors: 1.1.1
- postcss-load-config: 6.0.1(jiti@2.6.0)(postcss@8.5.6)(yaml@2.4.2)
+ postcss-load-config: 6.0.1(jiti@2.6.1)(postcss@8.5.6)(yaml@2.4.2)
resolve-from: 5.0.0
rollup: 4.42.0
source-map: 0.8.0-beta.0
@@ -14690,7 +15093,7 @@ snapshots:
tree-kill: 1.2.2
optionalDependencies:
postcss: 8.5.6
- typescript: 5.9.2
+ typescript: 5.9.3
transitivePeerDependencies:
- jiti
- supports-color
@@ -14730,7 +15133,7 @@ snapshots:
tunnel: 0.0.6
underscore: 1.13.7
- typescript@5.9.2: {}
+ typescript@5.9.3: {}
uc.micro@2.1.0: {}
@@ -14740,10 +15143,9 @@ snapshots:
underscore@1.13.7: {}
- undici-types@6.21.0:
- optional: true
+ undici-types@6.21.0: {}
- undici-types@7.13.0: {}
+ undici-types@7.14.0: {}
undici@7.16.0: {}
@@ -14762,10 +15164,33 @@ snapshots:
unicorn-magic@0.3.0: {}
+ unist-util-is@6.0.1:
+ dependencies:
+ '@types/unist': 3.0.3
+
+ unist-util-position@5.0.0:
+ dependencies:
+ '@types/unist': 3.0.3
+
unist-util-stringify-position@2.0.3:
dependencies:
'@types/unist': 2.0.10
+ unist-util-stringify-position@4.0.0:
+ dependencies:
+ '@types/unist': 3.0.3
+
+ unist-util-visit-parents@6.0.2:
+ dependencies:
+ '@types/unist': 3.0.3
+ unist-util-is: 6.0.1
+
+ unist-util-visit@5.0.0:
+ dependencies:
+ '@types/unist': 3.0.3
+ unist-util-is: 6.0.1
+ unist-util-visit-parents: 6.0.2
+
universalify@0.1.2: {}
universalify@2.0.1: {}
@@ -14839,13 +15264,23 @@ snapshots:
version-range@4.15.0: {}
- vite-node@2.1.8(@types/node@24.6.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0):
+ vfile-message@4.0.3:
+ dependencies:
+ '@types/unist': 3.0.3
+ unist-util-stringify-position: 4.0.0
+
+ vfile@6.0.3:
+ dependencies:
+ '@types/unist': 3.0.3
+ vfile-message: 4.0.3
+
+ vite-node@2.1.8(@types/node@24.8.1)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0):
dependencies:
cac: 6.7.14
debug: 4.4.1
es-module-lexer: 1.7.0
pathe: 1.1.2
- vite: 5.4.19(@types/node@24.6.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)
+ vite: 5.4.19(@types/node@24.8.1)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)
transitivePeerDependencies:
- '@types/node'
- less
@@ -14857,16 +15292,15 @@ snapshots:
- supports-color
- terser
- vite-node@3.2.4(@types/node@24.6.0)(jiti@2.6.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2):
+ vite-node@3.2.4(@types/node@24.8.1)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0):
dependencies:
cac: 6.7.14
debug: 4.4.1
es-module-lexer: 1.7.0
pathe: 2.0.3
- vite: 7.1.7(@types/node@24.6.0)(jiti@2.6.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2)
+ vite: 5.4.19(@types/node@24.8.1)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)
transitivePeerDependencies:
- '@types/node'
- - jiti
- less
- lightningcss
- sass
@@ -14875,81 +15309,79 @@ snapshots:
- sugarss
- supports-color
- terser
- - tsx
- - yaml
- vite-plugin-solid@2.11.8(@testing-library/jest-dom@6.9.0)(solid-js@1.9.9)(vite@7.1.7(@types/node@24.6.0)(jiti@2.6.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2)):
+ vite-plugin-solid@2.11.9(@testing-library/jest-dom@6.9.1)(solid-js@1.9.9)(vite@7.1.10(@types/node@24.8.1)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2)):
dependencies:
- '@babel/core': 7.28.0
+ '@babel/core': 7.28.4
'@types/babel__core': 7.20.5
- babel-preset-solid: 1.9.9(@babel/core@7.28.0)(solid-js@1.9.9)
+ babel-preset-solid: 1.9.9(@babel/core@7.28.4)(solid-js@1.9.9)
merge-anything: 5.1.7
solid-js: 1.9.9
solid-refresh: 0.6.3(solid-js@1.9.9)
- vite: 7.1.7(@types/node@24.6.0)(jiti@2.6.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2)
- vitefu: 1.1.1(vite@7.1.7(@types/node@24.6.0)(jiti@2.6.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2))
+ vite: 7.1.10(@types/node@24.8.1)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2)
+ vitefu: 1.1.1(vite@7.1.10(@types/node@24.8.1)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2))
optionalDependencies:
- '@testing-library/jest-dom': 6.9.0
+ '@testing-library/jest-dom': 6.9.1
transitivePeerDependencies:
- supports-color
- vite@5.4.19(@types/node@24.6.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0):
+ vite@5.4.19(@types/node@24.8.1)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0):
dependencies:
esbuild: 0.21.5
postcss: 8.5.6
rollup: 4.32.0
optionalDependencies:
- '@types/node': 24.6.0
+ '@types/node': 24.8.1
fsevents: 2.3.3
- less: 4.4.1
+ less: 4.4.2
lightningcss: 1.30.1
sass: 1.93.2
stylus: 0.64.0
- vite@7.1.3(@types/node@24.6.0)(jiti@2.6.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2):
+ vite@7.1.10(@types/node@24.8.1)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2):
dependencies:
- esbuild: 0.25.10
+ esbuild: 0.25.11
fdir: 6.5.0(picomatch@4.0.3)
picomatch: 4.0.3
postcss: 8.5.6
rollup: 4.49.0
- tinyglobby: 0.2.14
+ tinyglobby: 0.2.15
optionalDependencies:
- '@types/node': 24.6.0
+ '@types/node': 24.8.1
fsevents: 2.3.3
- jiti: 2.6.0
- less: 4.4.1
+ jiti: 2.6.1
+ less: 4.4.2
lightningcss: 1.30.1
sass: 1.93.2
stylus: 0.64.0
yaml: 2.4.2
- vite@7.1.7(@types/node@24.6.0)(jiti@2.6.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2):
+ vite@7.1.3(@types/node@24.8.1)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2):
dependencies:
- esbuild: 0.25.10
+ esbuild: 0.25.11
fdir: 6.5.0(picomatch@4.0.3)
picomatch: 4.0.3
postcss: 8.5.6
rollup: 4.49.0
- tinyglobby: 0.2.15
+ tinyglobby: 0.2.14
optionalDependencies:
- '@types/node': 24.6.0
+ '@types/node': 24.8.1
fsevents: 2.3.3
- jiti: 2.6.0
- less: 4.4.1
+ jiti: 2.6.1
+ less: 4.4.2
lightningcss: 1.30.1
sass: 1.93.2
stylus: 0.64.0
yaml: 2.4.2
- vitefu@1.1.1(vite@7.1.7(@types/node@24.6.0)(jiti@2.6.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2)):
+ vitefu@1.1.1(vite@7.1.10(@types/node@24.8.1)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2)):
optionalDependencies:
- vite: 7.1.7(@types/node@24.6.0)(jiti@2.6.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2)
+ vite: 7.1.10(@types/node@24.8.1)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2)
- vitest@2.1.8(@types/node@24.6.0)(happy-dom@14.12.3)(jsdom@26.1.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0):
+ vitest@2.1.8(@types/node@24.8.1)(happy-dom@14.12.3)(jsdom@26.1.0)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0):
dependencies:
'@vitest/expect': 2.1.8
- '@vitest/mocker': 2.1.8(vite@5.4.19(@types/node@24.6.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0))
+ '@vitest/mocker': 2.1.8(vite@5.4.19(@types/node@24.8.1)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0))
'@vitest/pretty-format': 2.1.9
'@vitest/runner': 2.1.8
'@vitest/snapshot': 2.1.8
@@ -14965,11 +15397,11 @@ snapshots:
tinyexec: 0.3.2
tinypool: 1.1.1
tinyrainbow: 1.2.0
- vite: 5.4.19(@types/node@24.6.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)
- vite-node: 2.1.8(@types/node@24.6.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)
+ vite: 5.4.19(@types/node@24.8.1)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)
+ vite-node: 2.1.8(@types/node@24.8.1)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)
why-is-node-running: 2.3.0
optionalDependencies:
- '@types/node': 24.6.0
+ '@types/node': 24.8.1
happy-dom: 14.12.3
jsdom: 26.1.0
transitivePeerDependencies:
@@ -14983,11 +15415,11 @@ snapshots:
- supports-color
- terser
- vitest@3.2.4(@types/node@24.6.0)(happy-dom@14.6.2)(jiti@2.6.0)(jsdom@26.1.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2):
+ vitest@3.2.4(@types/node@24.8.1)(happy-dom@14.6.2)(jiti@2.6.1)(jsdom@26.1.0)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2):
dependencies:
'@types/chai': 5.2.2
'@vitest/expect': 3.2.4
- '@vitest/mocker': 3.2.4(vite@7.1.3(@types/node@24.6.0)(jiti@2.6.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2))
+ '@vitest/mocker': 3.2.4(vite@7.1.3(@types/node@24.8.1)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2))
'@vitest/pretty-format': 3.2.4
'@vitest/runner': 3.2.4
'@vitest/snapshot': 3.2.4
@@ -15005,11 +15437,11 @@ snapshots:
tinyglobby: 0.2.14
tinypool: 1.1.1
tinyrainbow: 2.0.0
- vite: 7.1.3(@types/node@24.6.0)(jiti@2.6.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2)
- vite-node: 3.2.4(@types/node@24.6.0)(jiti@2.6.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2)
+ vite: 7.1.3(@types/node@24.8.1)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2)
+ vite-node: 3.2.4(@types/node@24.8.1)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)
why-is-node-running: 2.3.0
optionalDependencies:
- '@types/node': 24.6.0
+ '@types/node': 24.8.1
happy-dom: 14.6.2
jsdom: 26.1.0
transitivePeerDependencies:
@@ -15026,11 +15458,11 @@ snapshots:
- tsx
- yaml
- vitest@3.2.4(@types/node@24.6.0)(happy-dom@20.0.0)(jiti@2.6.0)(jsdom@26.1.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2):
+ vitest@3.2.4(@types/node@24.8.1)(happy-dom@20.0.8)(jiti@2.6.1)(jsdom@26.1.0)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2):
dependencies:
'@types/chai': 5.2.2
'@vitest/expect': 3.2.4
- '@vitest/mocker': 3.2.4(vite@7.1.3(@types/node@24.6.0)(jiti@2.6.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2))
+ '@vitest/mocker': 3.2.4(vite@7.1.3(@types/node@24.8.1)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2))
'@vitest/pretty-format': 3.2.4
'@vitest/runner': 3.2.4
'@vitest/snapshot': 3.2.4
@@ -15048,12 +15480,12 @@ snapshots:
tinyglobby: 0.2.14
tinypool: 1.1.1
tinyrainbow: 2.0.0
- vite: 7.1.3(@types/node@24.6.0)(jiti@2.6.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2)
- vite-node: 3.2.4(@types/node@24.6.0)(jiti@2.6.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2)
+ vite: 7.1.3(@types/node@24.8.1)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2)
+ vite-node: 3.2.4(@types/node@24.8.1)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)
why-is-node-running: 2.3.0
optionalDependencies:
- '@types/node': 24.6.0
- happy-dom: 20.0.0
+ '@types/node': 24.8.1
+ happy-dom: 20.0.8
jsdom: 26.1.0
transitivePeerDependencies:
- jiti
@@ -15069,33 +15501,31 @@ snapshots:
- tsx
- yaml
- vitest@4.0.0-beta.8(@types/node@24.6.0)(happy-dom@14.12.3)(jiti@2.6.0)(jsdom@26.1.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2):
+ vitest@4.0.0-beta.18(@types/node@24.8.1)(happy-dom@14.12.3)(jiti@2.6.1)(jsdom@26.1.0)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2):
dependencies:
- '@types/chai': 5.2.2
- '@vitest/expect': 4.0.0-beta.8
- '@vitest/mocker': 4.0.0-beta.8(vite@7.1.7(@types/node@24.6.0)(jiti@2.6.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2))
- '@vitest/pretty-format': 4.0.0-beta.8
- '@vitest/runner': 4.0.0-beta.8
- '@vitest/snapshot': 4.0.0-beta.8
- '@vitest/spy': 4.0.0-beta.8
- '@vitest/utils': 4.0.0-beta.8
- chai: 5.2.1
- debug: 4.4.1
+ '@vitest/expect': 4.0.0-beta.18
+ '@vitest/mocker': 4.0.0-beta.18(vite@7.1.10(@types/node@24.8.1)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2))
+ '@vitest/pretty-format': 4.0.0-beta.18
+ '@vitest/runner': 4.0.0-beta.18
+ '@vitest/snapshot': 4.0.0-beta.18
+ '@vitest/spy': 4.0.0-beta.18
+ '@vitest/utils': 4.0.0-beta.18
+ debug: 4.4.3
es-module-lexer: 1.7.0
expect-type: 1.2.2
- magic-string: 0.30.17
+ magic-string: 0.30.19
pathe: 2.0.3
picomatch: 4.0.3
std-env: 3.9.0
tinybench: 2.9.0
tinyexec: 0.3.2
- tinyglobby: 0.2.14
- tinypool: 1.1.1
- tinyrainbow: 2.0.0
- vite: 7.1.7(@types/node@24.6.0)(jiti@2.6.0)(less@4.4.1)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2)
+ tinyglobby: 0.2.15
+ tinypool: 2.0.0
+ tinyrainbow: 3.0.3
+ vite: 7.1.10(@types/node@24.8.1)(jiti@2.6.1)(less@4.4.2)(lightningcss@1.30.1)(sass@1.93.2)(stylus@0.64.0)(yaml@2.4.2)
why-is-node-running: 2.3.0
optionalDependencies:
- '@types/node': 24.6.0
+ '@types/node': 24.8.1
happy-dom: 14.12.3
jsdom: 26.1.0
transitivePeerDependencies:
@@ -15112,10 +15542,10 @@ snapshots:
- tsx
- yaml
- vue-eslint-parser@9.4.2(eslint@9.36.0(jiti@2.6.0)):
+ vue-eslint-parser@9.4.2(eslint@9.38.0(jiti@2.6.1)):
dependencies:
debug: 4.4.1
- eslint: 9.36.0(jiti@2.6.0)
+ eslint: 9.38.0(jiti@2.6.1)
eslint-scope: 7.2.2
eslint-visitor-keys: 3.4.3
espree: 9.6.1
@@ -15256,4 +15686,6 @@ snapshots:
yoctocolors@2.1.1: {}
- zod@4.1.11: {}
+ zod@4.1.12: {}
+
+ zwitch@2.0.4: {}
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
index e7ae1eb..b1088d5 100644
--- a/pnpm-workspace.yaml
+++ b/pnpm-workspace.yaml
@@ -1,4 +1,4 @@
packages:
- .
- 'packages/*'
- - examples/!(bun-react)
+ - examples/!(bun-react|bun-solid)
diff --git a/test/Dockerfile b/test/Dockerfile
index f456894..00b2986 100644
--- a/test/Dockerfile
+++ b/test/Dockerfile
@@ -1,15 +1,15 @@
+FROM node:22.20.0 AS node-stage
+FROM oven/bun:1.3.0 AS bun-stage
+
FROM codercom/code-server:4.104.2
-ENV NODE_VERSION=22.20.0
-# installs NVM (Node Version Manager)
-RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
-ENV NVM_DIR=/home/coder/.nvm
+# Copy Node and Bun from their stages
+COPY --from=bun-stage /usr/local/bin/bun /usr/local/bin/bun
+COPY --from=node-stage /usr/local /usr/local
USER coder
-# download and install Node.js
-RUN . "$NVM_DIR/nvm.sh" && nvm install ${NODE_VERSION}
-RUN . "$NVM_DIR/nvm.sh" && nvm use v${NODE_VERSION}
-RUN . "$NVM_DIR/nvm.sh" && nvm alias default v${NODE_VERSION}
+# Install Bun VSCode extension
+RUN code-server --install-extension oven.bun-vscode@0.0.31
COPY --chown=coder ./.vscode/settings.json /home/coder/.local/share/code-server/User/settings.json
diff --git a/test/docker-compose.yml b/test/docker-compose.yml
index 39eafcd..ec7b3a8 100644
--- a/test/docker-compose.yml
+++ b/test/docker-compose.yml
@@ -1,7 +1,8 @@
services:
code-server:
# Use the pushed image instead of building it locally, to save time in the CI pipeline
- image: poffm/vscode-server-with-node:4.104.2-22.20.0
+ # The version numbers refer to the versions of (code-server)-(node)-(bun)
+ image: poffm/vscode-server-with-node:4.104.2-22.20.0-1.3.0
# build:
# context: ..
# dockerfile: ./test/Dockerfile
diff --git a/test/e2e-core.test.ts b/test/e2e-core.test.ts
index fa7a076..52975e9 100644
--- a/test/e2e-core.test.ts
+++ b/test/e2e-core.test.ts
@@ -48,6 +48,7 @@ test('Steps through the Vitest+React+Tailwind@4 Counter example', async ({ brows
.evaluate(
button => window.getComputedStyle(button).getPropertyValue('background-color'),
),
+ { timeout: 20_000 },
).toBe('oklch(0.448 0.119 151.328)') // green
await debugHelper.debugStep()
@@ -111,6 +112,7 @@ test('Steps through the Vitest+React+Tailwind@3 Counter example', async ({ brows
.evaluate(
button => window.getComputedStyle(button).getPropertyValue('background-color'),
),
+ { timeout: 20_000 },
).toBe('rgb(22, 101, 52)') // green
await debugHelper.debugStep()
diff --git a/test/e2e-misc-features.test.ts b/test/e2e-misc-features.test.ts
index 4658aad..919806a 100644
--- a/test/e2e-misc-features.test.ts
+++ b/test/e2e-misc-features.test.ts
@@ -59,7 +59,7 @@ test('Load an external css file', async () => {
.evaluate(
button => window.getComputedStyle(button).getPropertyValue('background-color'),
),
- { timeout: 20_000 },
+ { timeout: 40_000 },
).toBe('rgb(128, 0, 128)')
// Disable the external css file
@@ -73,7 +73,7 @@ test('Load an external css file', async () => {
.evaluate(
button => window.getComputedStyle(button).getPropertyValue('background-color'),
),
- { timeout: 20_000 },
+ { timeout: 40_000 },
).toBe('rgb(239, 239, 239)')
})
diff --git a/test/e2e-recorder.test.ts b/test/e2e-recorder.test.ts
new file mode 100644
index 0000000..e59fe43
--- /dev/null
+++ b/test/e2e-recorder.test.ts
@@ -0,0 +1,240 @@
+import fs from 'node:fs/promises'
+import type { Browser } from '@playwright/test'
+import { test } from '@playwright/test'
+import path from 'pathe'
+import { DebuggerHelper } from './debugger-helper'
+
+// Undo changes made to the e2e test file that gets edited
+for (const exampleFolder of ['vitest-react-tailwind4', 'jest-react', 'bun-solid']) {
+ const e2eTestTestPath = path.join(__dirname, `../examples/${exampleFolder}/test/form-test-for-e2e.test.tsx`)
+ let e2eTestTestOriginalContent: string
+ test.beforeAll(async () => {
+ e2eTestTestOriginalContent = await fs.readFile(e2eTestTestPath, 'utf8')
+ })
+ test.afterEach(async () => {
+ // Undo changes made to the e2e test file
+ await fs.writeFile(e2eTestTestPath, e2eTestTestOriginalContent, 'utf8')
+ })
+}
+
+test.afterEach(async () => {
+ // Delete the generated test file
+ const generatedFilePath = path.join(__dirname, '../examples/vitest-react-tailwind4/components/FormExample.test.tsx')
+ try {
+ await fs.access(generatedFilePath)
+ await fs.unlink(generatedFilePath)
+ }
+ catch {
+ // ignore
+ }
+})
+
+test('Create a UI test file', async ({ browser }) => {
+ const page = await browser.newPage()
+
+ await page.goto('http://localhost:8080/?folder=/source/examples/vitest-react-tailwind4')
+
+ // Open FormExample.tsx
+ await page.locator('.search-label').click()
+ await page.locator('.monaco-findInput > .monaco-inputbox > .ibwrapper > .input').clear()
+ await page.locator('.monaco-findInput > .monaco-inputbox > .ibwrapper > .input').type('FormExample.tsx')
+ await page.locator('.highlight').first().click()
+
+ // Create the test file
+ await page.getByText('FormExample', { exact: true }).click({
+ button: 'right',
+ })
+ await page.getByRole('menuitem', { name: 'Create UI test (UI Test' }).click()
+
+ // FormExample.test.tsx should open on its own here
+
+ // Hide the bottom panel to get more space
+ const hideButton = page.getByRole('button', { name: 'Hide Panel' })
+ if (await hideButton.isVisible()) {
+ await hideButton.click()
+ }
+
+ // Wait for the text "render( )" to appear anywhere on the page
+ await page.getByText('render( )').waitFor()
+})
+
+test('Record a UI test, Vitest + React + Tailwind4', async ({ browser }) => {
+ await recordFormTest(browser, 'vitest-react-tailwind4', 'form-test-for-e2e.test.tsx', true)
+})
+
+test('Record a UI test, Jest + React', async ({ browser }) => {
+ test.skip(!!process.env.CI, 'Rely on the other Jest + React recorder test to save time in CI')
+ await recordFormTest(browser, 'jest-react', 'form-test-for-e2e.test.tsx')
+})
+
+test('Record a UI test, Bun + Solid', async ({ browser }) => {
+ await recordFormTest(browser, 'bun-solid', 'form-test-for-e2e.test.tsx', true)
+})
+
+test.describe('Record TodoList test, Jest + React', () => {
+ // Undo changes made to the TodoList.test.tsx file that gets edited
+ {
+ const todoListTestPath = path.join(__dirname, '../examples/jest-nextjs-minimal/components/TodoList.test.tsx')
+ let todoListTestOriginalContent: string = ''
+ test.beforeAll(async () => {
+ todoListTestOriginalContent = await fs.readFile(todoListTestPath, 'utf8')
+ })
+ test.afterEach(async () => {
+ // Undo changes made to the TodoList.test.tsx file
+ await fs.writeFile(todoListTestPath, todoListTestOriginalContent, 'utf8')
+ })
+ }
+
+ test('Record TodoList test, Jest + React', async ({ browser }) => {
+ const { page, replicaPanel } = await startRecorderTest(browser, 'jest-nextjs-minimal', 'TodoList.test.tsx', true)
+
+ // Generate an 'expect/toHaveTextContent' statement for the initial no-todos-message tag
+ await replicaPanel.getByText('No todos yet. Add one to get started.').click({
+ button: 'right',
+ })
+ await replicaPanel.getByText('.toHaveTextContent(...)').click()
+
+ // Add todos
+ await replicaPanel.getByRole('textbox', { name: 'Add a new todo' }).click()
+ await replicaPanel.getByRole('textbox', { name: 'Add a new todo' }).fill('todo 1')
+ await page.keyboard.press('Enter')
+ await replicaPanel.getByRole('textbox', { name: 'Add a new todo' }).fill('todo 2')
+ await page.keyboard.press('Enter')
+ await replicaPanel.getByRole('textbox', { name: 'Add a new todo' }).fill('todo 3')
+ await page.keyboard.press('Enter')
+
+ // Text after adding 3 todos
+ await replicaPanel.getByText('0 done').waitFor()
+ await replicaPanel.getByText('3 in progress').waitFor()
+
+ // Toggle todos
+ await replicaPanel.getByRole('checkbox', { name: 'Toggle done' }).nth(1).check()
+ await replicaPanel.getByRole('checkbox', { name: 'Toggle done' }).nth(2).check()
+ await replicaPanel.getByText('2 done').waitFor()
+ await replicaPanel.getByText('1 in progress').waitFor()
+
+ // Delete todos
+ await replicaPanel.getByRole('button', { name: 'Delete' }).first().click()
+ await replicaPanel.getByRole('button', { name: 'Delete' }).nth(1).click()
+ await replicaPanel.getByText('1 done').waitFor()
+ await replicaPanel.getByText('0 in progress').waitFor()
+
+ // Generate 'expect' statements
+ await replicaPanel.getByText(/^1 done$/).first().click({
+ modifiers: ['Alt'],
+ })
+ await replicaPanel.getByText(/^0 in progress$/).first().click({
+ modifiers: ['Alt'],
+ })
+
+ // End the test
+ await page.getByRole('button', { name: 'Continue (F5)' }).click()
+
+ // Wait for replica panel to be closed
+ await page.frameLocator('iframe.webview.ready').locator('iframe[title="Tested UI"]').waitFor({ state: 'detached' })
+
+ // Check for the generated code in the editor; Make sure indexes are used for the checkboxes and buttons
+ await page.getByText(`await userEvent.click(screen.getAllByRole('checkbox', { name: /^toggle done$/i })[1])`).waitFor()
+ await page.getByText(`await userEvent.click(screen.getAllByRole('button', { name: /^delete$/i })[0])`).first().waitFor()
+ await page.getByText(`expect(screen.getByRole('paragraph')).toHaveTextContent('No todos yet. Add one to get started.')`).first().waitFor()
+ await page.getByText(`expect(screen.getByText(/^1 done$/i))`).waitFor()
+ })
+})
+
+async function startRecorderTest(browser: Browser, exampleFolder: string, testFileSearch: string, dismissStylePrompt = false) {
+ const page = await browser.newPage()
+
+ await page.goto(`http://localhost:8080/?folder=/source/examples/${exampleFolder}`)
+
+ // Open form-test-for-e2e.test.tsx
+ await page.locator('.search-label').click()
+ await page.locator('.monaco-findInput > .monaco-inputbox > .ibwrapper > .input').clear()
+ await page.locator('.monaco-findInput > .monaco-inputbox > .ibwrapper > .input').type(testFileSearch)
+ await page.locator('.highlight').first().click()
+
+ // Hide the bottom panel to get more space
+ const hideButton = page.getByRole('button', { name: 'Hide Panel' })
+ if (await hideButton.isVisible()) {
+ await hideButton.click()
+ }
+
+ // Start the visual debug
+ await page.getByRole('button', { name: 'Visually Debug UI' }).click()
+ await page.getByText('Tested UI').waitFor()
+
+ const replicaPanel = page
+ .frameLocator('iframe.webview.ready')
+ .frameLocator('iframe[title="Tested UI"]')
+
+ if (dismissStylePrompt) {
+ // Click the OK button on the initial style prompt
+ await replicaPanel.locator('ui-test-visualizer-button[title="Dismiss style prompt"]').click()
+ }
+
+ // Wait until the debugger is paused on breakpoint
+ await page.getByText('Paused on breakpoint').waitFor()
+
+ const debugHelper = new DebuggerHelper(page)
+ await debugHelper.debugStep()
+
+ // Start recording
+ await replicaPanel.getByRole('button', { name: 'Record input as code' }).first().click()
+
+ return { page, replicaPanel, debugHelper }
+}
+
+async function recordFormTest(
+ browser: Browser,
+ exampleFolder: string,
+ testFileSearch: string,
+ dismissStylePrompt = false,
+) {
+ const { page, replicaPanel } = await startRecorderTest(
+ browser,
+ exampleFolder,
+ testFileSearch,
+ dismissStylePrompt,
+ )
+
+ // Check that the submission count starts at 0
+ await replicaPanel.getByText(`Submit Count: 0`).waitFor()
+
+ // Fill in the first input
+ await replicaPanel.getByRole('textbox', { name: 'First input' }).click()
+ await replicaPanel.getByRole('textbox', { name: 'First input' }).fill('test input 1')
+
+ // Fill in the second input
+ await replicaPanel.getByRole('textbox', { name: 'Second input' }).click()
+ await replicaPanel.getByRole('textbox', { name: 'Second input' }).fill('test input 2')
+
+ // Select an option from the select menu
+ await replicaPanel.getByRole('combobox', { name: 'Select menu' }).click()
+ await replicaPanel.getByRole('combobox', { name: 'Select menu' }).selectOption('option2')
+
+ // Check the code is generated for the userEvent calls
+ await replicaPanel.getByText(`await userEvent.type(screen.getByRole('textbox', { name: /^first input$/i }), 'test input 1')`).waitFor()
+ await replicaPanel.getByText(`await userEvent.type(screen.getByRole('textbox', { name: /^second input$/i }), 'test input 2')`).waitFor()
+ await replicaPanel.getByText(`await userEvent.selectOptions(screen.getByRole('combobox', { name: /^select menu$/i }), ['option2'])`).waitFor()
+
+ // Submit the form
+ await replicaPanel.getByRole('button', { name: 'Submit' }).click()
+ await replicaPanel.getByText(`await userEvent.click(screen.getByRole('button', { name: /^submit$/i }))`).waitFor()
+
+ // Alt-click the submit count to generate the `expect` statement
+ await replicaPanel.getByText('Submit Count:').click({
+ modifiers: ['Alt'],
+ })
+ // Check that the submission count increased due to the click, which causes the userEvent code to run in the debugger
+ await replicaPanel.getByText(`Submit Count: 1`).waitFor()
+ await replicaPanel.getByText(`expect(screen.getByText(/^submit count: 1$/i))`).waitFor()
+
+ // Finish the test
+ await page.getByRole('button', { name: 'Continue (F5)' }).click()
+
+ // Wait for replica panel to be closed
+ await page.frameLocator('iframe.webview.ready').locator('iframe[title="Tested UI"]').waitFor({ state: 'detached' })
+
+ // Check for the generated code in the editor
+ await page.getByText(`await userEvent.click(screen.getByRole('button', { name: /^submit$/i }))`).waitFor()
+ await page.getByText(`expect(screen.getByText(/^submit count: 1$/i))`).waitFor()
+}