diff --git a/.vscode/launch.json b/.vscode/launch.json index eb3021f..58a4893 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -47,6 +47,13 @@ "${workspaceFolder}/packages/vscode-messenger-devtools/lib/**/*.js", "${workspaceFolder}/packages/vscode-messenger/lib/**/*.js", ], + "debugWebviews": true, + "rendererDebugOptions": { + "webRoot": "${workspaceFolder}/packages/vscode-messenger-devtools/webview-ui", + "outFiles": [ + "${workspaceFolder}/packages/vscode-messenger-devtools/webview-ui/build/**/*.js" + ] + }, "preLaunchTask": "Watch All" } ] diff --git a/README.md b/README.md index 1f21f78..0753e02 100644 --- a/README.md +++ b/README.md @@ -7,88 +7,151 @@ RPC messaging library for the VS Code extension platform. Makes the communicatio [![License](https://img.shields.io/github/license/TypeFox/vscode-messenger?color=green)](https://github.com/TypeFox/vscode-messenger/blob/main/LICENSE) [![Codespaces](https://img.shields.io/badge/Codespaces-Open-blue?logo=github)](https://codespaces.new/TypeFox/vscode-messenger) -#### Supported features - -- Sending notification or a request from an __extension to a view__, a __view group__ or __broadcast__ to all registered views -- Sending notification or a request from a __view to other view__, a view group or the host extension -- Support for __sync and async__ request/notification handlers -- Support for __request cancellation__ -- __Typed__ API -- Automatically unregister views on view dispose +## Features + +- Send notifications or requests from an **extension to a view**, a **view group**, or **broadcast** to all registered views +- Send notifications or requests from a **view to another view**, a view group, or the host extension +- **Typed API** — `RequestType` and `NotificationType

` enforce matching parameter and result types on both sides +- Sync and async request/notification handlers +- Request cancellation +- Automatically unregisters views on dispose - Configurable logging -#### Diagnostics vs-code extension +## Packages -[![Visual Studio Marketplace Version](https://img.shields.io/visual-studio-marketplace/v/typefox.vscode-messenger-devtools?label=VS-Code%20Marketplace)](https://marketplace.visualstudio.com/items?itemName=typefox.vscode-messenger-devtools) +Install only what each side needs: + +| Package | Install in | Purpose | +|---|---|---| +| [`vscode-messenger`](https://www.npmjs.com/package/vscode-messenger) | Extension host | `Messenger` class, view registration, diagnostic API | +| [`vscode-messenger-webview`](https://www.npmjs.com/package/vscode-messenger-webview) | Webview script | `Messenger` class for webview, `createCancellationToken` | +| [`vscode-messenger-common`](https://www.npmjs.com/package/vscode-messenger-common) | Shared module | `NotificationType`, `RequestType`, `HOST_EXTENSION`, `BROADCAST` | -[Devtool vscode extension](https://github.com/TypeFox/vscode-messenger/tree/main/packages/vscode-messenger-devtools) helps inspecting messages interaction between your extension components. +**Tip:** Keep all `NotificationType` / `RequestType` declarations in a shared TypeScript module imported by both the extension and the webview. The same `method` string and parameter/result types must match on both ends. -#### Usage in an extension (TS example) +## Usage in an extension (TypeScript) ```ts +import * as vscode from 'vscode'; +import { Messenger } from 'vscode-messenger'; +import { NotificationType, RequestType } from 'vscode-messenger-common'; + const messenger = new Messenger(); -// register one or more views +// Register a webview view (or use registerWebviewPanel for WebviewPanel) messenger.registerWebviewView(webviewView); - -// Handle incoming view notification +// Define message types — declare once, import on both sides const colorSelectType: NotificationType = { method: 'colorSelected' }; +const availableColorsType: RequestType = { method: 'availableColor' }; +const colorModifyType: NotificationType = { method: 'colorModify' }; -messenger.onNotification(colorSelectType, (params: string) => { - vscode.window.activeTextEditor?.insertSnippet(new vscode.SnippetString(`#${params}`)); +// Handle a notification from the webview +messenger.onNotification(colorSelectType, (color: string) => { + vscode.window.activeTextEditor?.insertSnippet(new vscode.SnippetString(`#${color}`)); }); -// Handle view requests and return a result -const availableColorsType: RequestType = { method: 'availableColor' }; - -messenger.onRequest(availableColorsType, (params: string) => { +// Handle a request from the webview and return a result +messenger.onRequest(availableColorsType, (_params: string) => { return ['020202', 'f1eeee', 'a85b20', 'daab70', 'efcb99']; }); -// Send a notification to a view of type 'calicoColors.colorsView' -const colorModifyType: NotificationType = { method: 'colorModify' }; +// Send a notification to all views of a given type +messenger.sendNotification(colorModifyType, { type: 'webview', webviewType: 'calicoColors.colorsView' }, 'clear'); + +// Send a request to a view and await the result +const selectedColor = await messenger.sendRequest( + { method: 'getSelectedColor' }, + { type: 'webview', webviewType: 'calicoColors.colorsView' }, + '' +); +``` -messenger.sendNotification(colorModifyType, {type: 'webview', webviewType: 'calicoColors.colorsView' }, 'clear'); +## Usage in a webview (TypeScript) +```ts +import { Messenger } from 'vscode-messenger-webview'; +import { HOST_EXTENSION } from 'vscode-messenger-common'; +import { colorModifyType, availableColorsType, colorSelectType } from './shared/message-types'; -// Send a request to a view of type 'calicoColors.colorsView' and get a result -const selectedColor = await messenger.sendRequest({ method: 'getSelectedColor' }, {type: 'webview', webviewType: 'calicoColors.colorsView' }, ''); -``` +const messenger = new Messenger(); // acquireVsCodeApi() is called automatically -#### Usage in a webview (JS Example) - -Using JS in this example for simplicity. You can use TypeScript as well. - -```js -const vscode = acquireVsCodeApi(); -const vscode_messenger = require("vscode-messenger-webview"); - -const messenger = new vscode_messenger.Messenger(vscode); - -// Handle extension Notifications. For requests use `onRequest()` -messenger.onNotification({method: 'colorModify'}, (params) => { - switch(params) { - case 'add': { - addColor(); - break; - } - case 'clear': { - colors = []; - updateColorList(colors); - break; - } - } +// Handle notifications from the extension +messenger.onNotification(colorModifyType, (action: string) => { + if (action === 'clear') clearColors(); + if (action === 'add') addColor(); }); -messenger.start(); // start listening for incoming events -// Send a request to your extension. -// For notification use `sendNotification()` - const colors = await messenger.sendRequest({ method: 'availableColors'}, HOST_EXTENSION, ''); - console.log(colors); +messenger.start(); // required — starts listening for incoming messages + +// Send a request to the host extension +const colors = await messenger.sendRequest(availableColorsType, HOST_EXTENSION, ''); + +// Send a notification to the host extension +messenger.sendNotification(colorSelectType, HOST_EXTENSION, 'a85b20'); +``` + +> **Note:** `messenger.start()` must be called before any messages can be received. Forgetting it causes all incoming messages to be silently dropped. + +## Key concepts + +### Message participants + +| Participant | How to construct | Use for | +|---|---|---| +| Host extension | `HOST_EXTENSION` | Targeting the extension from a webview | +| Webview by type | `{ type: 'webview', webviewType: '...' }` | All instances of a view type | +| Webview by id | returned by `registerWebviewView` / `registerWebviewPanel` | One specific instance | +| Broadcast | `BROADCAST` | All registered views (notifications only) | +### Request cancellation + +```ts +// Extension side — pass any CancellationToken +const cts = new vscode.CancellationTokenSource(); +const result = await messenger.sendRequest(longOpType, target, params, cts.token); +cts.cancel(); + +// Webview side — bridge an AbortSignal +import { createCancellationToken } from 'vscode-messenger-webview'; +const ctrl = new AbortController(); +const result = await messenger.sendRequest(longOpType, HOST_EXTENSION, params, createCancellationToken(ctrl.signal)); +ctrl.abort('timeout'); +``` + +### Broadcast notifications + +A webview receives a broadcast only when registered with `broadcastMethods` listing the method: + +```ts +// Extension: opt the view in to specific broadcast methods +messenger.registerWebviewView(view, { broadcastMethods: [refreshType.method] }); + +// Either side: broadcast to all opted-in views +messenger.sendNotification(refreshType, BROADCAST); +``` + +## Diagnostics and devtools + +[![Visual Studio Marketplace Version](https://img.shields.io/visual-studio-marketplace/v/typefox.vscode-messenger-devtools?label=VS-Code%20Marketplace)](https://marketplace.visualstudio.com/items?itemName=typefox.vscode-messenger-devtools) + +The companion **[VS Code Messenger Developer Tool](https://marketplace.visualstudio.com/items?itemName=typefox.vscode-messenger-devtools)** extension visualizes live message traffic — requests, responses, and notifications — between the extension host and its webviews. To enable it, expose `messenger.diagnosticApi()` from your extension's `activate` return value: + +```ts +import { Messenger, type MessengerDiagnostic } from 'vscode-messenger'; + +const messenger = new Messenger(); + +export function activate(context: vscode.ExtensionContext): MessengerDiagnostic { + // ... register views, handlers, etc. + return messenger.diagnosticApi(); +} ``` -#### More examples +Open the devtool with **Developer: Open vscode-messenger devtools** from the Command Palette. + +See the [devtools README](packages/vscode-messenger-devtools/README.md) for full setup instructions, `DiagnosticOptions`, the event schema, and troubleshooting. + +## More examples -See tests for more examples. +The [calico-colors example](examples/calico-colors) demonstrates a complete extension with a `WebviewView` and a `WebviewPanel` sharing a single `Messenger` instance, typed message definitions in a shared module, broadcast usage, and diagnostic API integration. diff --git a/eslint.config.js b/eslint.config.js index 7a0cb1c..e6e9bbc 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -47,9 +47,10 @@ module.exports = { "no-multiple-empty-lines": ["error", { "max": 1 }], // two or more empty lines need to be fused to one "no-new-wrappers": "error", // there is no reason to wrap primitve values "no-throw-literal": "error", // only throw Error but no objects {} - "no-trailing-spaces": "error", // trim end of lines + "no-trailing-spaces": "off", // trim end of lines "no-unsafe-finally": "error", // safe try/catch/finally behavior "no-var": "error", // use const and let instead of var + "no-constant-binary-expression": "warn", // warn about expressions like if (a === 1 || 0) which are always true "space-before-function-paren": ["error", { // space in function decl: f() vs async () => {} "anonymous": "never", "asyncArrow": "always", diff --git a/package-lock.json b/package-lock.json index 637f958..405162c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -45,9 +45,9 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.28.6.tgz", - "integrity": "sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", "dev": true, "license": "MIT", "dependencies": { @@ -60,9 +60,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.6.tgz", - "integrity": "sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz", + "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", "dev": true, "license": "MIT", "engines": { @@ -70,21 +70,21 @@ } }, "node_modules/@babel/core": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.6.tgz", - "integrity": "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", + "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.28.6", - "@babel/generator": "^7.28.6", + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", "@babel/helper-compilation-targets": "^7.28.6", "@babel/helper-module-transforms": "^7.28.6", "@babel/helpers": "^7.28.6", - "@babel/parser": "^7.28.6", + "@babel/parser": "^7.29.0", "@babel/template": "^7.28.6", - "@babel/traverse": "^7.28.6", - "@babel/types": "^7.28.6", + "@babel/traverse": "^7.29.0", + "@babel/types": "^7.29.0", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", @@ -118,14 +118,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.6.tgz", - "integrity": "sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw==", + "version": "7.29.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", + "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.28.6", - "@babel/types": "^7.28.6", + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" @@ -244,27 +244,27 @@ } }, "node_modules/@babel/helpers": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", - "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz", + "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==", "dev": true, "license": "MIT", "dependencies": { "@babel/template": "^7.28.6", - "@babel/types": "^7.28.6" + "@babel/types": "^7.29.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.6.tgz", - "integrity": "sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==", + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz", + "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.28.6" + "@babel/types": "^7.29.0" }, "bin": { "parser": "bin/babel-parser.js" @@ -529,9 +529,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz", - "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==", + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.2.tgz", + "integrity": "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==", "dev": true, "license": "MIT", "engines": { @@ -554,18 +554,18 @@ } }, "node_modules/@babel/traverse": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.6.tgz", - "integrity": "sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", + "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.28.6", - "@babel/generator": "^7.28.6", + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.28.6", + "@babel/parser": "^7.29.0", "@babel/template": "^7.28.6", - "@babel/types": "^7.28.6", + "@babel/types": "^7.29.0", "debug": "^4.3.1" }, "engines": { @@ -573,9 +573,9 @@ } }, "node_modules/@babel/types": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.6.tgz", - "integrity": "sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", "dev": true, "license": "MIT", "dependencies": { @@ -1065,24 +1065,31 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.21.1", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", - "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", + "version": "0.21.2", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz", + "integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==", "dev": true, "license": "Apache-2.0", "dependencies": { "@eslint/object-schema": "^2.1.7", "debug": "^4.3.1", - "minimatch": "^3.1.2" + "minimatch": "^3.1.5" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@eslint/config-array/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, "node_modules/@eslint/config-array/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", + "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", "dev": true, "license": "MIT", "dependencies": { @@ -1091,9 +1098,9 @@ } }, "node_modules/@eslint/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "license": "ISC", "dependencies": { @@ -1130,20 +1137,20 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz", - "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==", + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.5.tgz", + "integrity": "sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==", "dev": true, "license": "MIT", "dependencies": { - "ajv": "^6.12.4", + "ajv": "^6.14.0", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.1", - "minimatch": "^3.1.2", + "minimatch": "^3.1.5", "strip-json-comments": "^3.1.1" }, "engines": { @@ -1153,10 +1160,17 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@eslint/eslintrc/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", + "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", "dev": true, "license": "MIT", "dependencies": { @@ -1175,9 +1189,9 @@ } }, "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "license": "ISC", "dependencies": { @@ -1188,9 +1202,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.39.2", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz", - "integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==", + "version": "9.39.4", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.4.tgz", + "integrity": "sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==", "dev": true, "license": "MIT", "engines": { @@ -1224,6 +1238,65 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@floating-ui/core": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.5.tgz", + "integrity": "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.11" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz", + "integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.7.5", + "@floating-ui/utils": "^0.2.11" + } + }, + "node_modules/@floating-ui/react": { + "version": "0.27.19", + "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.27.19.tgz", + "integrity": "sha512-31B8h5mm8YxotlE7/AU/PhNAl8eWxAmjL/v2QOxroDNkTFLk3Uu82u63N3b6TXa4EGJeeZLVcd/9AlNlVqzeog==", + "license": "MIT", + "dependencies": { + "@floating-ui/react-dom": "^2.1.8", + "@floating-ui/utils": "^0.2.11", + "tabbable": "^6.0.0" + }, + "peerDependencies": { + "react": ">=17.0.0", + "react-dom": ">=17.0.0" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.8.tgz", + "integrity": "sha512-cC52bHwM/n/CxS87FH0yWdngEZrjdtLW/qVruo68qg+prK7ZQ4YGdut2GyDVpoGeAYe/h899rVeOVm6Oi40k2A==", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.7.6" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/react/node_modules/tabbable": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.4.0.tgz", + "integrity": "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==", + "license": "MIT" + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.11.tgz", + "integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==", + "license": "MIT" + }, "node_modules/@humanfs/core": { "version": "0.19.1", "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", @@ -1736,46 +1809,6 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@microsoft/fast-element": { - "version": "1.14.0", - "resolved": "https://registry.npmjs.org/@microsoft/fast-element/-/fast-element-1.14.0.tgz", - "integrity": "sha512-zXvuSOzvsu8zDTy9eby8ix8VqLop2rwKRgp++ZN2kTCsoB3+QJVoaGD2T/Cyso2ViZQFXNpiNCVKfnmxBvmWkQ==", - "license": "MIT" - }, - "node_modules/@microsoft/fast-foundation": { - "version": "2.50.0", - "resolved": "https://registry.npmjs.org/@microsoft/fast-foundation/-/fast-foundation-2.50.0.tgz", - "integrity": "sha512-8mFYG88Xea1jZf2TI9Lm/jzZ6RWR8x29r24mGuLojNYqIR2Bl8+hnswoV6laApKdCbGMPKnsAL/O68Q0sRxeVg==", - "license": "MIT", - "dependencies": { - "@microsoft/fast-element": "^1.14.0", - "@microsoft/fast-web-utilities": "^5.4.1", - "tabbable": "^5.2.0", - "tslib": "^1.13.0" - } - }, - "node_modules/@microsoft/fast-react-wrapper": { - "version": "0.1.48", - "resolved": "https://registry.npmjs.org/@microsoft/fast-react-wrapper/-/fast-react-wrapper-0.1.48.tgz", - "integrity": "sha512-9NvEjru9Kn5ZKjomAMX6v+eF0DR+eDkxKDwDfi+Wb73kTbrNzcnmlwd4diN15ygH97kldgj2+lpvI4CKLQQWLg==", - "license": "MIT", - "dependencies": { - "@microsoft/fast-element": "^1.9.0", - "@microsoft/fast-foundation": "^2.41.1" - }, - "peerDependencies": { - "react": ">=16.9.0" - } - }, - "node_modules/@microsoft/fast-web-utilities": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/@microsoft/fast-web-utilities/-/fast-web-utilities-5.4.1.tgz", - "integrity": "sha512-ReWYncndjV3c8D8iq9tp7NcFNc1vbVHvcBFPME2nNFKNbS1XCesYZGlIlf3ot5EmuOXPlrzUHOWzQ2vFpIkqDg==", - "license": "MIT", - "dependencies": { - "exenv-es6": "^1.1.1" - } - }, "node_modules/@rolldown/pluginutils": { "version": "1.0.0-beta.27", "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz", @@ -1784,9 +1817,9 @@ "license": "MIT" }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.55.1.tgz", - "integrity": "sha512-9R0DM/ykwfGIlNu6+2U09ga0WXeZ9MRC2Ter8jnz8415VbuIykVuc6bhdrbORFZANDmTDvq26mJrEVTl8TdnDg==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz", + "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==", "cpu": [ "arm" ], @@ -1798,9 +1831,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.55.1.tgz", - "integrity": "sha512-eFZCb1YUqhTysgW3sj/55du5cG57S7UTNtdMjCW7LwVcj3dTTcowCsC8p7uBdzKsZYa8J7IDE8lhMI+HX1vQvg==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz", + "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==", "cpu": [ "arm64" ], @@ -1812,9 +1845,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.55.1.tgz", - "integrity": "sha512-p3grE2PHcQm2e8PSGZdzIhCKbMCw/xi9XvMPErPhwO17vxtvCN5FEA2mSLgmKlCjHGMQTP6phuQTYWUnKewwGg==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz", + "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==", "cpu": [ "arm64" ], @@ -1826,9 +1859,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.55.1.tgz", - "integrity": "sha512-rDUjG25C9qoTm+e02Esi+aqTKSBYwVTaoS1wxcN47/Luqef57Vgp96xNANwt5npq9GDxsH7kXxNkJVEsWEOEaQ==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz", + "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==", "cpu": [ "x64" ], @@ -1840,9 +1873,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.55.1.tgz", - "integrity": "sha512-+JiU7Jbp5cdxekIgdte0jfcu5oqw4GCKr6i3PJTlXTCU5H5Fvtkpbs4XJHRmWNXF+hKmn4v7ogI5OQPaupJgOg==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz", + "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==", "cpu": [ "arm64" ], @@ -1854,9 +1887,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.55.1.tgz", - "integrity": "sha512-V5xC1tOVWtLLmr3YUk2f6EJK4qksksOYiz/TCsFHu/R+woubcLWdC9nZQmwjOAbmExBIVKsm1/wKmEy4z4u4Bw==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz", + "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==", "cpu": [ "x64" ], @@ -1868,9 +1901,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.55.1.tgz", - "integrity": "sha512-Rn3n+FUk2J5VWx+ywrG/HGPTD9jXNbicRtTM11e/uorplArnXZYsVifnPPqNNP5BsO3roI4n8332ukpY/zN7rQ==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz", + "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==", "cpu": [ "arm" ], @@ -1882,9 +1915,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.55.1.tgz", - "integrity": "sha512-grPNWydeKtc1aEdrJDWk4opD7nFtQbMmV7769hiAaYyUKCT1faPRm2av8CX1YJsZ4TLAZcg9gTR1KvEzoLjXkg==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz", + "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==", "cpu": [ "arm" ], @@ -1896,9 +1929,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.55.1.tgz", - "integrity": "sha512-a59mwd1k6x8tXKcUxSyISiquLwB5pX+fJW9TkWU46lCqD/GRDe9uDN31jrMmVP3feI3mhAdvcCClhV8V5MhJFQ==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz", + "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==", "cpu": [ "arm64" ], @@ -1910,9 +1943,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.55.1.tgz", - "integrity": "sha512-puS1MEgWX5GsHSoiAsF0TYrpomdvkaXm0CofIMG5uVkP6IBV+ZO9xhC5YEN49nsgYo1DuuMquF9+7EDBVYu4uA==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz", + "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==", "cpu": [ "arm64" ], @@ -1924,9 +1957,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.55.1.tgz", - "integrity": "sha512-r3Wv40in+lTsULSb6nnoudVbARdOwb2u5fpeoOAZjFLznp6tDU8kd+GTHmJoqZ9lt6/Sys33KdIHUaQihFcu7g==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz", + "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==", "cpu": [ "loong64" ], @@ -1938,9 +1971,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.55.1.tgz", - "integrity": "sha512-MR8c0+UxAlB22Fq4R+aQSPBayvYa3+9DrwG/i1TKQXFYEaoW3B5b/rkSRIypcZDdWjWnpcvxbNaAJDcSbJU3Lw==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz", + "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==", "cpu": [ "loong64" ], @@ -1952,9 +1985,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.55.1.tgz", - "integrity": "sha512-3KhoECe1BRlSYpMTeVrD4sh2Pw2xgt4jzNSZIIPLFEsnQn9gAnZagW9+VqDqAHgm1Xc77LzJOo2LdigS5qZ+gw==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz", + "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==", "cpu": [ "ppc64" ], @@ -1966,9 +1999,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.55.1.tgz", - "integrity": "sha512-ziR1OuZx0vdYZZ30vueNZTg73alF59DicYrPViG0NEgDVN8/Jl87zkAPu4u6VjZST2llgEUjaiNl9JM6HH1Vdw==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz", + "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==", "cpu": [ "ppc64" ], @@ -1980,9 +2013,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.55.1.tgz", - "integrity": "sha512-uW0Y12ih2XJRERZ4jAfKamTyIHVMPQnTZcQjme2HMVDAHY4amf5u414OqNYC+x+LzRdRcnIG1YodLrrtA8xsxw==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz", + "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==", "cpu": [ "riscv64" ], @@ -1994,9 +2027,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.55.1.tgz", - "integrity": "sha512-u9yZ0jUkOED1BFrqu3BwMQoixvGHGZ+JhJNkNKY/hyoEgOwlqKb62qu+7UjbPSHYjiVy8kKJHvXKv5coH4wDeg==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz", + "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==", "cpu": [ "riscv64" ], @@ -2008,9 +2041,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.55.1.tgz", - "integrity": "sha512-/0PenBCmqM4ZUd0190j7J0UsQ/1nsi735iPRakO8iPciE7BQ495Y6msPzaOmvx0/pn+eJVVlZrNrSh4WSYLxNg==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz", + "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==", "cpu": [ "s390x" ], @@ -2022,9 +2055,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.55.1.tgz", - "integrity": "sha512-a8G4wiQxQG2BAvo+gU6XrReRRqj+pLS2NGXKm8io19goR+K8lw269eTrPkSdDTALwMmJp4th2Uh0D8J9bEV1vg==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz", + "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==", "cpu": [ "x64" ], @@ -2036,9 +2069,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.55.1.tgz", - "integrity": "sha512-bD+zjpFrMpP/hqkfEcnjXWHMw5BIghGisOKPj+2NaNDuVT+8Ds4mPf3XcPHuat1tz89WRL+1wbcxKY3WSbiT7w==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz", + "integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==", "cpu": [ "x64" ], @@ -2050,9 +2083,9 @@ ] }, "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.55.1.tgz", - "integrity": "sha512-eLXw0dOiqE4QmvikfQ6yjgkg/xDM+MdU9YJuP4ySTibXU0oAvnEWXt7UDJmD4UkYialMfOGFPJnIHSe/kdzPxg==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz", + "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==", "cpu": [ "x64" ], @@ -2064,9 +2097,9 @@ ] }, "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.55.1.tgz", - "integrity": "sha512-xzm44KgEP11te3S2HCSyYf5zIzWmx3n8HDCc7EE59+lTcswEWNpvMLfd9uJvVX8LCg9QWG67Xt75AuHn4vgsXw==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz", + "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==", "cpu": [ "arm64" ], @@ -2078,9 +2111,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.55.1.tgz", - "integrity": "sha512-yR6Bl3tMC/gBok5cz/Qi0xYnVbIxGx5Fcf/ca0eB6/6JwOY+SRUcJfI0OpeTpPls7f194as62thCt/2BjxYN8g==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz", + "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==", "cpu": [ "arm64" ], @@ -2092,9 +2125,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.55.1.tgz", - "integrity": "sha512-3fZBidchE0eY0oFZBnekYCfg+5wAB0mbpCBuofh5mZuzIU/4jIVkbESmd2dOsFNS78b53CYv3OAtwqkZZmU5nA==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz", + "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==", "cpu": [ "ia32" ], @@ -2106,9 +2139,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.55.1.tgz", - "integrity": "sha512-xGGY5pXj69IxKb4yv/POoocPy/qmEGhimy/FoTpTSVju3FYXUQQMFCaZZXJVidsmGxRioZAwpThl/4zX41gRKg==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz", + "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==", "cpu": [ "x64" ], @@ -2120,9 +2153,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.55.1.tgz", - "integrity": "sha512-SPEpaL6DX4rmcXtnhdrQYgzQ5W2uW3SCJch88lB2zImhJRhIIK44fkUrgIV/Q8yUNfw5oyZ5vkeQsZLhCb06lw==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz", + "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==", "cpu": [ "x64" ], @@ -2160,6 +2193,39 @@ "@sinonjs/commons": "^1.7.0" } }, + "node_modules/@tanstack/react-table": { + "version": "8.21.3", + "resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.21.3.tgz", + "integrity": "sha512-5nNMTSETP4ykGegmVkhjcS8tTLW6Vl4axfEGQN3v0zdHYbK4UfoqfPChclTrJ4EoK9QynqAu9oUf8VEmrpZ5Ww==", + "license": "MIT", + "dependencies": { + "@tanstack/table-core": "8.21.3" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, + "node_modules/@tanstack/table-core": { + "version": "8.21.3", + "resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-8.21.3.tgz", + "integrity": "sha512-ldZXEhOBb8Is7xLs01fR3YEc3DERiz5silj8tnGkFZytt1abEvl/GhUmCE0PMLaMPTa3Jk4HbKmRlHmu+gCftg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, "node_modules/@tootallnate/once": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", @@ -2170,12 +2236,6 @@ "node": ">= 6" } }, - "node_modules/@tweenjs/tween.js": { - "version": "25.0.0", - "resolved": "https://registry.npmjs.org/@tweenjs/tween.js/-/tween.js-25.0.0.tgz", - "integrity": "sha512-XKLA6syeBUaPzx4j3qwMqzzq+V4uo72BnlbOjmuljLrRqdsd3qnzvZZoxvMHZ23ndsRS4aufU6JOZYpCbU6T1A==", - "license": "MIT" - }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -2319,42 +2379,26 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/prop-types": { - "version": "15.7.15", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", - "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/react": { - "version": "17.0.90", - "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.90.tgz", - "integrity": "sha512-P9beVR/x06U9rCJzSxtENnOr4BrbJ6VrsrDTc+73TtHv9XHhryXKbjGRB+6oooB2r0G/pQkD/S4dHo/7jUfwFw==", + "version": "19.2.14", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", + "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", "dev": true, "license": "MIT", "dependencies": { - "@types/prop-types": "*", - "@types/scheduler": "^0.16", "csstype": "^3.2.2" } }, "node_modules/@types/react-dom": { - "version": "17.0.26", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.26.tgz", - "integrity": "sha512-Z+2VcYXJwOqQ79HreLU/1fyQ88eXSSFh6I3JdrEHQIfYSI0kCQpTGvOrbE6jFGGYXKsHuwY9tBa/w5Uo6KzrEg==", + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", + "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", "dev": true, "license": "MIT", "peerDependencies": { - "@types/react": "^17.0.0" + "@types/react": "^19.2.0" } }, - "node_modules/@types/scheduler": { - "version": "0.16.8", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz", - "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/stack-utils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", @@ -2370,9 +2414,9 @@ "license": "MIT" }, "node_modules/@types/vscode": { - "version": "1.108.1", - "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.108.1.tgz", - "integrity": "sha512-DerV0BbSzt87TbrqmZ7lRDIYaMiqvP8tmJTzW2p49ZBVtGUnGAu2RGQd1Wv4XMzEVUpaHbsemVM5nfuQJj7H6w==", + "version": "1.110.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.110.0.tgz", + "integrity": "sha512-AGuxUEpU4F4mfuQjxPPaQVyuOMhs+VT/xRok1jiHVBubHK7lBRvCuOMZG0LKUwxncrPorJ5qq/uil3IdZBd5lA==", "dev": true, "license": "MIT" }, @@ -2401,17 +2445,17 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.53.0.tgz", - "integrity": "sha512-eEXsVvLPu8Z4PkFibtuFJLJOTAV/nPdgtSjkGoPpddpFk3/ym2oy97jynY6ic2m6+nc5M8SE1e9v/mHKsulcJg==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.57.1.tgz", + "integrity": "sha512-Gn3aqnvNl4NGc6x3/Bqk1AOn0thyTU9bqDRhiRnUWezgvr2OnhYCWCgC8zXXRVqBsIL1pSDt7T9nJUe0oM0kDQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.53.0", - "@typescript-eslint/type-utils": "8.53.0", - "@typescript-eslint/utils": "8.53.0", - "@typescript-eslint/visitor-keys": "8.53.0", + "@typescript-eslint/scope-manager": "8.57.1", + "@typescript-eslint/type-utils": "8.57.1", + "@typescript-eslint/utils": "8.57.1", + "@typescript-eslint/visitor-keys": "8.57.1", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.4.0" @@ -2424,22 +2468,22 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.53.0", - "eslint": "^8.57.0 || ^9.0.0", + "@typescript-eslint/parser": "^8.57.1", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/parser": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.53.0.tgz", - "integrity": "sha512-npiaib8XzbjtzS2N4HlqPvlpxpmZ14FjSJrteZpPxGUaYPlvhzlzUZ4mZyABo0EFrOWnvyd0Xxroq//hKhtAWg==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.57.1.tgz", + "integrity": "sha512-k4eNDan0EIMTT/dUKc/g+rsJ6wcHYhNPdY19VoX/EOtaAG8DLtKCykhrUnuHPYvinn5jhAPgD2Qw9hXBwrahsw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.53.0", - "@typescript-eslint/types": "8.53.0", - "@typescript-eslint/typescript-estree": "8.53.0", - "@typescript-eslint/visitor-keys": "8.53.0", + "@typescript-eslint/scope-manager": "8.57.1", + "@typescript-eslint/types": "8.57.1", + "@typescript-eslint/typescript-estree": "8.57.1", + "@typescript-eslint/visitor-keys": "8.57.1", "debug": "^4.4.3" }, "engines": { @@ -2450,19 +2494,19 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.53.0.tgz", - "integrity": "sha512-Bl6Gdr7NqkqIP5yP9z1JU///Nmes4Eose6L1HwpuVHwScgDPPuEWbUVhvlZmb8hy0vX9syLk5EGNL700WcBlbg==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.57.1.tgz", + "integrity": "sha512-vx1F37BRO1OftsYlmG9xay1TqnjNVlqALymwWVuYTdo18XuKxtBpCj1QlzNIEHlvlB27osvXFWptYiEWsVdYsg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.53.0", - "@typescript-eslint/types": "^8.53.0", + "@typescript-eslint/tsconfig-utils": "^8.57.1", + "@typescript-eslint/types": "^8.57.1", "debug": "^4.4.3" }, "engines": { @@ -2477,14 +2521,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.53.0.tgz", - "integrity": "sha512-kWNj3l01eOGSdVBnfAF2K1BTh06WS0Yet6JUgb9Cmkqaz3Jlu0fdVUjj9UI8gPidBWSMqDIglmEXifSgDT/D0g==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.57.1.tgz", + "integrity": "sha512-hs/QcpCwlwT2L5S+3fT6gp0PabyGk4Q0Rv2doJXA0435/OpnSR3VRgvrp8Xdoc3UAYSg9cyUjTeFXZEPg/3OKg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.53.0", - "@typescript-eslint/visitor-keys": "8.53.0" + "@typescript-eslint/types": "8.57.1", + "@typescript-eslint/visitor-keys": "8.57.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2495,9 +2539,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.53.0.tgz", - "integrity": "sha512-K6Sc0R5GIG6dNoPdOooQ+KtvT5KCKAvTcY8h2rIuul19vxH5OTQk7ArKkd4yTzkw66WnNY0kPPzzcmWA+XRmiA==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.57.1.tgz", + "integrity": "sha512-0lgOZB8cl19fHO4eI46YUx2EceQqhgkPSuCGLlGi79L2jwYY1cxeYc1Nae8Aw1xjgW3PKVDLlr3YJ6Bxx8HkWg==", "dev": true, "license": "MIT", "engines": { @@ -2512,15 +2556,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.53.0.tgz", - "integrity": "sha512-BBAUhlx7g4SmcLhn8cnbxoxtmS7hcq39xKCgiutL3oNx1TaIp+cny51s8ewnKMpVUKQUGb41RAUWZ9kxYdovuw==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.57.1.tgz", + "integrity": "sha512-+Bwwm0ScukFdyoJsh2u6pp4S9ktegF98pYUU0hkphOOqdMB+1sNQhIz8y5E9+4pOioZijrkfNO/HUJVAFFfPKA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.53.0", - "@typescript-eslint/typescript-estree": "8.53.0", - "@typescript-eslint/utils": "8.53.0", + "@typescript-eslint/types": "8.57.1", + "@typescript-eslint/typescript-estree": "8.57.1", + "@typescript-eslint/utils": "8.57.1", "debug": "^4.4.3", "ts-api-utils": "^2.4.0" }, @@ -2532,14 +2576,14 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/types": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.53.0.tgz", - "integrity": "sha512-Bmh9KX31Vlxa13+PqPvt4RzKRN1XORYSLlAE+sO1i28NkisGbTtSLFVB3l7PWdHtR3E0mVMuC7JilWJ99m2HxQ==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.57.1.tgz", + "integrity": "sha512-S29BOBPJSFUiblEl6RzPPjJt6w25A6XsBqRVDt53tA/tlL8q7ceQNZHTjPeONt/3S7KRI4quk+yP9jK2WjBiPQ==", "dev": true, "license": "MIT", "engines": { @@ -2551,18 +2595,18 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.53.0.tgz", - "integrity": "sha512-pw0c0Gdo7Z4xOG987u3nJ8akL9093yEEKv8QTJ+Bhkghj1xyj8cgPaavlr9rq8h7+s6plUJ4QJYw2gCZodqmGw==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.57.1.tgz", + "integrity": "sha512-ybe2hS9G6pXpqGtPli9Gx9quNV0TWLOmh58ADlmZe9DguLq0tiAKVjirSbtM1szG6+QH6rVXyU6GTLQbWnMY+g==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.53.0", - "@typescript-eslint/tsconfig-utils": "8.53.0", - "@typescript-eslint/types": "8.53.0", - "@typescript-eslint/visitor-keys": "8.53.0", + "@typescript-eslint/project-service": "8.57.1", + "@typescript-eslint/tsconfig-utils": "8.57.1", + "@typescript-eslint/types": "8.57.1", + "@typescript-eslint/visitor-keys": "8.57.1", "debug": "^4.4.3", - "minimatch": "^9.0.5", + "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.4.0" @@ -2579,16 +2623,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.53.0.tgz", - "integrity": "sha512-XDY4mXTez3Z1iRDI5mbRhH4DFSt46oaIFsLg+Zn97+sYrXACziXSQcSelMybnVZ5pa1P6xYkPr5cMJyunM1ZDA==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.57.1.tgz", + "integrity": "sha512-XUNSJ/lEVFttPMMoDVA2r2bwrl8/oPx8cURtczkSEswY5T3AeLmCy+EKWQNdL4u0MmAHOjcWrqJp2cdvgjn8dQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.53.0", - "@typescript-eslint/types": "8.53.0", - "@typescript-eslint/typescript-estree": "8.53.0" + "@typescript-eslint/scope-manager": "8.57.1", + "@typescript-eslint/types": "8.57.1", + "@typescript-eslint/typescript-estree": "8.57.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2598,19 +2642,19 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.53.0.tgz", - "integrity": "sha512-LZ2NqIHFhvFwxG0qZeLL9DvdNAHPGCY5dIRwBhyYeU+LfLhcStE1ImjsuTG/WaVh3XysGaeLW8Rqq7cGkPCFvw==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.57.1.tgz", + "integrity": "sha512-YWnmJkXbofiz9KbnbbwuA2rpGkFPLbAIetcCNO6mJ8gdhdZ/v7WDXsoGFAJuM6ikUFKTlSQnjWnVO4ux+UzS6A==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.53.0", - "eslint-visitor-keys": "^4.2.1" + "@typescript-eslint/types": "8.57.1", + "eslint-visitor-keys": "^5.0.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2621,13 +2665,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", "dev": true, "license": "Apache-2.0", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://opencollective.com/eslint" @@ -2661,21 +2705,6 @@ "dev": true, "license": "CC-BY-4.0" }, - "node_modules/@vscode/webview-ui-toolkit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@vscode/webview-ui-toolkit/-/webview-ui-toolkit-1.0.1.tgz", - "integrity": "sha512-jitA17enYUoMadv9exoHJiYcBK+X+gTlUyyIFvXRrA/mhHrxZfel5Eh6z/u57UZScK/i0Sn7EtlEYV1ZKFbeHw==", - "deprecated": "This package has been deprecated, https://github.com/microsoft/vscode-webview-ui-toolkit/issues/561", - "license": "MIT", - "dependencies": { - "@microsoft/fast-element": "^1.6.2", - "@microsoft/fast-foundation": "^2.38.0", - "@microsoft/fast-react-wrapper": "^0.1.18" - }, - "peerDependencies": { - "react": ">=16.9.0" - } - }, "node_modules/abab": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", @@ -2684,19 +2713,10 @@ "dev": true, "license": "BSD-3-Clause" }, - "node_modules/accessor-fn": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/accessor-fn/-/accessor-fn-1.5.3.tgz", - "integrity": "sha512-rkAofCwe/FvYFUlMB0v0gWmhqtfAtV1IUkdPbfhTUyYniu5LrC0A0UJkTH0Jv3S8SvwkmfuAlY+mQIJATdocMA==", - "license": "MIT", - "engines": { - "node": ">=12" - } - }, "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "dev": true, "license": "MIT", "bin": { @@ -2775,26 +2795,6 @@ "node": ">=0.4.0" } }, - "node_modules/ag-grid-community": { - "version": "31.3.4", - "resolved": "https://registry.npmjs.org/ag-grid-community/-/ag-grid-community-31.3.4.tgz", - "integrity": "sha512-jOxQO86C6eLnk1GdP24HB6aqaouFzMWizgfUwNY5MnetiWzz9ZaAmOGSnW/XBvdjXvC5Fpk3gSbvVKKQ7h9kBw==", - "license": "MIT" - }, - "node_modules/ag-grid-react": { - "version": "31.3.4", - "resolved": "https://registry.npmjs.org/ag-grid-react/-/ag-grid-react-31.3.4.tgz", - "integrity": "sha512-WmPASHRFGSTxCMRStWG5bRtln0Ugsdqbb3+Y8sEyGHeLw4hXqfpqie3lT9kqCOl7wPWUjCpwmFdXzRnWPmyyeg==", - "license": "MIT", - "dependencies": { - "ag-grid-community": "31.3.4", - "prop-types": "^15.8.1" - }, - "peerDependencies": { - "react": "^16.3.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.3.0 || ^17.0.0 || ^18.0.0" - } - }, "node_modules/agent-base": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", @@ -2809,9 +2809,9 @@ } }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "dev": true, "license": "MIT", "dependencies": { @@ -2901,9 +2901,9 @@ } }, "node_modules/asn1.js/node_modules/bn.js": { - "version": "4.12.2", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", - "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz", + "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==", "dev": true, "license": "MIT" }, @@ -3058,11 +3058,14 @@ } }, "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } }, "node_modules/base64-js": { "version": "1.5.1", @@ -3086,40 +3089,36 @@ "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.9.14", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.14.tgz", - "integrity": "sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg==", + "version": "2.10.9", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.9.tgz", + "integrity": "sha512-OZd0e2mU11ClX8+IdXe3r0dbqMEznRiT4TfbhYIbcRPZkqJ7Qwer8ij3GZAmLsRKa+II9V1v5czCkvmHH3XZBg==", "dev": true, "license": "Apache-2.0", "bin": { - "baseline-browser-mapping": "dist/cli.js" - } - }, - "node_modules/bezier-js": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/bezier-js/-/bezier-js-6.1.4.tgz", - "integrity": "sha512-PA0FW9ZpcHbojUCMu28z9Vg/fNkwTj5YhusSAjHHDfHDGLxJ6YUKrAN2vk1fP2MMOxVw4Oko16FMlRGVBGqLKg==", - "license": "MIT", - "funding": { - "type": "individual", - "url": "https://github.com/Pomax/bezierjs/blob/master/FUNDING.md" + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" } }, "node_modules/bn.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.2.tgz", - "integrity": "sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.3.tgz", + "integrity": "sha512-EAcmnPkxpntVL+DS7bO1zhcZNvCkxqtkd0ZY53h06GNQ3DEkkGZ/gKgmDv6DdZQGj9BgfSPKtJJ7Dp1GPP8f7w==", "dev": true, "license": "MIT" }, "node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", + "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0" + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" } }, "node_modules/braces": { @@ -3504,9 +3503,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001764", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001764.tgz", - "integrity": "sha512-9JGuzl2M+vPL+pz70gtMF9sHdMFbY9FJaQBi186cHKH3pSzDvzoUJUPV6fqiKIMyXbud9ZLg4F3Yza1vJ1+93g==", + "version": "1.0.30001780", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001780.tgz", + "integrity": "sha512-llngX0E7nQci5BPJDqoZSbuZ5Bcs9F5db7EtgfwBerX9XGtkkiO4NwfDDIRzHTTwcYC8vC7bmeUEPGrKlR/TkQ==", "dev": true, "funding": [ { @@ -3524,18 +3523,6 @@ ], "license": "CC-BY-4.0" }, - "node_modules/canvas-color-tracker": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/canvas-color-tracker/-/canvas-color-tracker-1.3.2.tgz", - "integrity": "sha512-ryQkDX26yJ3CXzb3hxUVNlg1NKE4REc5crLBq661Nxzr8TNd236SaEf2ffYLXyI5tSABSeguHLqcVq4vf9L3Zg==", - "license": "MIT", - "dependencies": { - "tinycolor2": "^1.6.0" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -3616,6 +3603,15 @@ "node": ">=12" } }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -3810,9 +3806,9 @@ } }, "node_modules/create-ecdh/node_modules/bn.js": { - "version": "4.12.2", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", - "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz", + "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==", "dev": true, "license": "MIT" }, @@ -3921,222 +3917,6 @@ "dev": true, "license": "MIT" }, - "node_modules/d3-array": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", - "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", - "license": "ISC", - "dependencies": { - "internmap": "1 - 2" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-binarytree": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/d3-binarytree/-/d3-binarytree-1.0.2.tgz", - "integrity": "sha512-cElUNH+sHu95L04m92pG73t2MEJXKu+GeKUN1TJkFsu93E5W8E9Sc3kHEGJKgenGvj19m6upSn2EunvMgMD2Yw==", - "license": "MIT" - }, - "node_modules/d3-color": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", - "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-dispatch": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", - "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-drag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", - "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", - "license": "ISC", - "dependencies": { - "d3-dispatch": "1 - 3", - "d3-selection": "3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-ease": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", - "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-force-3d": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/d3-force-3d/-/d3-force-3d-3.0.6.tgz", - "integrity": "sha512-4tsKHUPLOVkyfEffZo1v6sFHvGFwAIIjt/W8IThbp08DYAsXZck+2pSHEG5W1+gQgEvFLdZkYvmJAbRM2EzMnA==", - "license": "MIT", - "dependencies": { - "d3-binarytree": "1", - "d3-dispatch": "1 - 3", - "d3-octree": "1", - "d3-quadtree": "1 - 3", - "d3-timer": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-format": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.2.tgz", - "integrity": "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-interpolate": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", - "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", - "license": "ISC", - "dependencies": { - "d3-color": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-octree": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/d3-octree/-/d3-octree-1.1.0.tgz", - "integrity": "sha512-F8gPlqpP+HwRPMO/8uOu5wjH110+6q4cgJvgJT6vlpy3BEaDIKlTZrgHKZSp/i1InRpVfh4puY/kvL6MxK930A==", - "license": "MIT" - }, - "node_modules/d3-quadtree": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", - "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-scale": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", - "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", - "license": "ISC", - "dependencies": { - "d3-array": "2.10.0 - 3", - "d3-format": "1 - 3", - "d3-interpolate": "1.2.0 - 3", - "d3-time": "2.1.1 - 3", - "d3-time-format": "2 - 4" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-scale-chromatic": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", - "integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==", - "license": "ISC", - "dependencies": { - "d3-color": "1 - 3", - "d3-interpolate": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-selection": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", - "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-time": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", - "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", - "license": "ISC", - "dependencies": { - "d3-array": "2 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-time-format": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", - "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", - "license": "ISC", - "dependencies": { - "d3-time": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-timer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", - "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-transition": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", - "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", - "license": "ISC", - "dependencies": { - "d3-color": "1 - 3", - "d3-dispatch": "1 - 3", - "d3-ease": "1 - 3", - "d3-interpolate": "1 - 3", - "d3-timer": "1 - 3" - }, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "d3-selection": "2 - 3" - } - }, - "node_modules/d3-zoom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", - "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", - "license": "ISC", - "dependencies": { - "d3-dispatch": "1 - 3", - "d3-drag": "2 - 3", - "d3-interpolate": "1 - 3", - "d3-selection": "2 - 3", - "d3-transition": "2 - 3" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/dash-ast": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/dash-ast/-/dash-ast-1.0.0.tgz", @@ -4410,9 +4190,9 @@ } }, "node_modules/diffie-hellman/node_modules/bn.js": { - "version": "4.12.2", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", - "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz", + "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==", "dev": true, "license": "MIT" }, @@ -4476,26 +4256,10 @@ "readable-stream": "^2.0.2" } }, - "node_modules/echarts": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/echarts/-/echarts-5.6.0.tgz", - "integrity": "sha512-oTbVTsXfKuEhxftHqL5xprgLoc0k7uScAwtryCgWF6hPYFLRwOUHiFmHGCBKP5NPFNkDVopOieyUqYGH8Fa3kA==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "2.3.0", - "zrender": "5.6.1" - } - }, - "node_modules/echarts/node_modules/tslib": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", - "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", - "license": "0BSD" - }, "node_modules/electron-to-chromium": { - "version": "1.5.267", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz", - "integrity": "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==", + "version": "1.5.321", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.321.tgz", + "integrity": "sha512-L2C7Q279W2D/J4PLZLk7sebOILDSWos7bMsMNN06rK482umHUrh/3lM8G7IlHFOYip2oAg5nha1rCMxr/rs6ZQ==", "dev": true, "license": "ISC" }, @@ -4516,9 +4280,9 @@ } }, "node_modules/elliptic/node_modules/bn.js": { - "version": "4.12.2", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", - "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz", + "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==", "dev": true, "license": "MIT" }, @@ -4689,25 +4453,25 @@ } }, "node_modules/eslint": { - "version": "9.39.2", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.2.tgz", - "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", + "version": "9.39.4", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz", + "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.21.1", + "@eslint/config-array": "^0.21.2", "@eslint/config-helpers": "^0.4.2", "@eslint/core": "^0.17.0", - "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.39.2", + "@eslint/eslintrc": "^3.3.5", + "@eslint/js": "9.39.4", "@eslint/plugin-kit": "^0.4.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", - "ajv": "^6.12.4", + "ajv": "^6.14.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", @@ -4726,7 +4490,7 @@ "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", + "minimatch": "^3.1.5", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, @@ -4797,10 +4561,17 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", + "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", "dev": true, "license": "MIT", "dependencies": { @@ -4832,9 +4603,9 @@ } }, "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "license": "ISC", "dependencies": { @@ -4980,12 +4751,6 @@ "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/exenv-es6": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/exenv-es6/-/exenv-es6-1.1.1.tgz", - "integrity": "sha512-vlVu3N8d6yEMpMsEm+7sUBAI81aqYYuEvfK0jNqmdb/OPXzzH7QWDDnVjMvDSY47JdHEqx/dfC/q8WkfoTmpGQ==", - "license": "MIT" - }, "node_modules/exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", @@ -5108,26 +4873,12 @@ } }, "node_modules/flatted": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", - "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", "dev": true, "license": "ISC" }, - "node_modules/float-tooltip": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/float-tooltip/-/float-tooltip-1.7.5.tgz", - "integrity": "sha512-/kXzuDnnBqyyWyhDMH7+PfP8J/oXiAavGzcRxASOMRHFuReDtofizLLJsf7nnDLAfEaMW4pVWaXrAjtnglpEkg==", - "license": "MIT", - "dependencies": { - "d3-selection": "2 - 3", - "kapsule": "^1.16", - "preact": "10" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/for-each": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", @@ -5144,32 +4895,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/force-graph": { - "version": "1.51.0", - "resolved": "https://registry.npmjs.org/force-graph/-/force-graph-1.51.0.tgz", - "integrity": "sha512-aTnihCmiMA0ItLJLCbrQYS9mzriopW24goFPgUnKAAmAlPogTSmFWqoBPMXzIfPb7bs04Hur5zEI4WYgLW3Sig==", - "license": "MIT", - "dependencies": { - "@tweenjs/tween.js": "18 - 25", - "accessor-fn": "1", - "bezier-js": "3 - 6", - "canvas-color-tracker": "^1.3", - "d3-array": "1 - 3", - "d3-drag": "2 - 3", - "d3-force-3d": "2 - 3", - "d3-scale": "1 - 4", - "d3-scale-chromatic": "1 - 3", - "d3-selection": "2 - 3", - "d3-zoom": "2 - 3", - "float-tooltip": "^1.7", - "index-array-by": "1", - "kapsule": "^1.16", - "lodash-es": "4" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/form-data": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", @@ -5322,7 +5047,7 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, "license": "ISC", "dependencies": { @@ -5353,10 +5078,17 @@ "node": ">=10.13.0" } }, + "node_modules/glob/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, "node_modules/glob/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", + "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", "dev": true, "license": "MIT", "dependencies": { @@ -5365,9 +5097,9 @@ } }, "node_modules/glob/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "license": "ISC", "dependencies": { @@ -5679,15 +5411,6 @@ "node": ">=0.8.19" } }, - "node_modules/index-array-by": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/index-array-by/-/index-array-by-1.4.2.tgz", - "integrity": "sha512-SP23P27OUKzXWEC/TOyWlwLviofQkCSCKONnc62eItjp69yCZZPqDQtr3Pw5gJDnPeUMqExmKydNZaJO0FU9pw==", - "license": "MIT", - "engines": { - "node": ">=12" - } - }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -5749,15 +5472,6 @@ "insert-module-globals": "bin/cmd.js" } }, - "node_modules/internmap": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", - "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, "node_modules/is-arguments": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz", @@ -6041,15 +5755,6 @@ "node": ">=8" } }, - "node_modules/jerrypick": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/jerrypick/-/jerrypick-1.1.2.tgz", - "integrity": "sha512-YKnxXEekXKzhpf7CLYA0A+oDP8V0OhICNCr5lv96FvSsDEmrb0GKM776JgQvHTMjr7DTTPEVv/1Ciaw0uEWzBA==", - "license": "MIT", - "engines": { - "node": ">=12" - } - }, "node_modules/jest": { "version": "28.1.3", "resolved": "https://registry.npmjs.org/jest/-/jest-28.1.3.tgz", @@ -6270,9 +5975,9 @@ } }, "node_modules/jest-environment-jsdom/node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.1.tgz", + "integrity": "sha512-HqmEUIGRJ5fSXchkVgR5F7qn48bDBzv0kWj/Kfu5e6uci4UlEeng4331LnBkWffb++Ei3FOVLxo8JJWMFBDMeQ==", "dev": true, "license": "MIT", "engines": { @@ -6996,18 +6701,6 @@ "node": "*" } }, - "node_modules/kapsule": { - "version": "1.16.3", - "resolved": "https://registry.npmjs.org/kapsule/-/kapsule-1.16.3.tgz", - "integrity": "sha512-4+5mNNf4vZDSwPhKprKwz3330iisPrb08JyMgbsdFrimBCKNHecua/WBwvVg3n7vwx0C1ARjfhwIpbrbd9n5wg==", - "license": "MIT", - "dependencies": { - "lodash-es": "4" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -7087,18 +6780,12 @@ } }, "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", "dev": true, "license": "MIT" }, - "node_modules/lodash-es": { - "version": "4.17.22", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.22.tgz", - "integrity": "sha512-XEawp1t0gxSi9x01glktRZ5HDy0HXqrM0x5pXQM98EaI0NxO6jVM7omDOxsuEo5UIASAnm2bRp1Jt/e0a2XU8Q==", - "license": "MIT" - }, "node_modules/lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -7118,6 +6805,7 @@ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", "license": "MIT", + "peer": true, "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, @@ -7226,9 +6914,9 @@ } }, "node_modules/miller-rabin/node_modules/bn.js": { - "version": "4.12.2", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", - "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz", + "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==", "dev": true, "license": "MIT" }, @@ -7280,16 +6968,16 @@ "license": "MIT" }, "node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", + "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", "dev": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^5.0.2" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": "18 || 20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -7350,9 +7038,9 @@ "license": "MIT" }, "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", + "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", "dev": true, "funding": [ { @@ -7383,9 +7071,9 @@ "license": "MIT" }, "node_modules/node-releases": { - "version": "2.0.27", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", - "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", + "version": "2.0.36", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.36.tgz", + "integrity": "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==", "dev": true, "license": "MIT" }, @@ -7419,15 +7107,6 @@ "dev": true, "license": "MIT" }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/object-inspect": { "version": "1.13.4", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", @@ -7718,9 +7397,9 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true, "license": "MIT", "engines": { @@ -7820,9 +7499,9 @@ } }, "node_modules/postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "version": "8.5.15", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", + "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", "dev": true, "funding": [ { @@ -7840,7 +7519,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.11", + "nanoid": "^3.3.12", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -7848,16 +7527,6 @@ "node": "^10 || ^12 || >=14" } }, - "node_modules/preact": { - "version": "10.28.2", - "resolved": "https://registry.npmjs.org/preact/-/preact-10.28.2.tgz", - "integrity": "sha512-lbteaWGzGHdlIuiJ0l2Jq454m6kcpI1zNje6d8MlGAFlYvP2GO4ibnat7P74Esfz4sPTdM6UxtTwh/d3pwM9JA==", - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/preact" - } - }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -7928,23 +7597,6 @@ "node": ">= 6" } }, - "node_modules/prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "license": "MIT", - "dependencies": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - } - }, - "node_modules/prop-types/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "license": "MIT" - }, "node_modules/psl": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz", @@ -7974,9 +7626,9 @@ } }, "node_modules/public-encrypt/node_modules/bn.js": { - "version": "4.12.2", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", - "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz", + "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==", "dev": true, "license": "MIT" }, @@ -7991,9 +7643,9 @@ } }, "node_modules/qs": { - "version": "6.14.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz", - "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz", + "integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -8044,47 +7696,30 @@ } }, "node_modules/react": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", - "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "license": "MIT", + "peer": true, "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" + "loose-envify": "^1.1.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/react-dom": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", - "integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==", + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", "license": "MIT", + "peer": true, "dependencies": { "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "scheduler": "^0.20.2" + "scheduler": "^0.23.2" }, "peerDependencies": { - "react": "17.0.2" - } - }, - "node_modules/react-force-graph-2d": { - "version": "1.24.4", - "resolved": "https://registry.npmjs.org/react-force-graph-2d/-/react-force-graph-2d-1.24.4.tgz", - "integrity": "sha512-TRJiS0wlOgcTmFm3RqX/FEGoNz1P/YdNMhN+ht02ZzDcaVXw7jsIXgrMLi9WJc5EzFi6DJvcI7x1iZvLsW+PTA==", - "license": "MIT", - "dependencies": { - "force-graph": "1", - "prop-types": "15", - "react-kapsule": "2" - }, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "react": "*" + "react": "^18.3.1" } }, "node_modules/react-is": { @@ -8094,21 +7729,6 @@ "dev": true, "license": "MIT" }, - "node_modules/react-kapsule": { - "version": "2.5.7", - "resolved": "https://registry.npmjs.org/react-kapsule/-/react-kapsule-2.5.7.tgz", - "integrity": "sha512-kifAF4ZPD77qZKc4CKLmozq6GY1sBzPEJTIJb0wWFK6HsePJatK3jXplZn2eeAt3x67CDozgi7/rO8fNQ/AL7A==", - "license": "MIT", - "dependencies": { - "jerrypick": "^1.1.1" - }, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "react": ">=16.13.1" - } - }, "node_modules/react-refresh": { "version": "0.17.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", @@ -8291,9 +7911,9 @@ } }, "node_modules/rollup": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.55.1.tgz", - "integrity": "sha512-wDv/Ht1BNHB4upNbK74s9usvl7hObDnvVzknxqY/E/O3X6rW1U1rV1aENEfJ54eFZDTNo7zv1f5N4edCluH7+A==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz", + "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==", "dev": true, "license": "MIT", "dependencies": { @@ -8307,31 +7927,31 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.55.1", - "@rollup/rollup-android-arm64": "4.55.1", - "@rollup/rollup-darwin-arm64": "4.55.1", - "@rollup/rollup-darwin-x64": "4.55.1", - "@rollup/rollup-freebsd-arm64": "4.55.1", - "@rollup/rollup-freebsd-x64": "4.55.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.55.1", - "@rollup/rollup-linux-arm-musleabihf": "4.55.1", - "@rollup/rollup-linux-arm64-gnu": "4.55.1", - "@rollup/rollup-linux-arm64-musl": "4.55.1", - "@rollup/rollup-linux-loong64-gnu": "4.55.1", - "@rollup/rollup-linux-loong64-musl": "4.55.1", - "@rollup/rollup-linux-ppc64-gnu": "4.55.1", - "@rollup/rollup-linux-ppc64-musl": "4.55.1", - "@rollup/rollup-linux-riscv64-gnu": "4.55.1", - "@rollup/rollup-linux-riscv64-musl": "4.55.1", - "@rollup/rollup-linux-s390x-gnu": "4.55.1", - "@rollup/rollup-linux-x64-gnu": "4.55.1", - "@rollup/rollup-linux-x64-musl": "4.55.1", - "@rollup/rollup-openbsd-x64": "4.55.1", - "@rollup/rollup-openharmony-arm64": "4.55.1", - "@rollup/rollup-win32-arm64-msvc": "4.55.1", - "@rollup/rollup-win32-ia32-msvc": "4.55.1", - "@rollup/rollup-win32-x64-gnu": "4.55.1", - "@rollup/rollup-win32-x64-msvc": "4.55.1", + "@rollup/rollup-android-arm-eabi": "4.59.0", + "@rollup/rollup-android-arm64": "4.59.0", + "@rollup/rollup-darwin-arm64": "4.59.0", + "@rollup/rollup-darwin-x64": "4.59.0", + "@rollup/rollup-freebsd-arm64": "4.59.0", + "@rollup/rollup-freebsd-x64": "4.59.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", + "@rollup/rollup-linux-arm-musleabihf": "4.59.0", + "@rollup/rollup-linux-arm64-gnu": "4.59.0", + "@rollup/rollup-linux-arm64-musl": "4.59.0", + "@rollup/rollup-linux-loong64-gnu": "4.59.0", + "@rollup/rollup-linux-loong64-musl": "4.59.0", + "@rollup/rollup-linux-ppc64-gnu": "4.59.0", + "@rollup/rollup-linux-ppc64-musl": "4.59.0", + "@rollup/rollup-linux-riscv64-gnu": "4.59.0", + "@rollup/rollup-linux-riscv64-musl": "4.59.0", + "@rollup/rollup-linux-s390x-gnu": "4.59.0", + "@rollup/rollup-linux-x64-gnu": "4.59.0", + "@rollup/rollup-linux-x64-musl": "4.59.0", + "@rollup/rollup-openbsd-x64": "4.59.0", + "@rollup/rollup-openharmony-arm64": "4.59.0", + "@rollup/rollup-win32-arm64-msvc": "4.59.0", + "@rollup/rollup-win32-ia32-msvc": "4.59.0", + "@rollup/rollup-win32-x64-gnu": "4.59.0", + "@rollup/rollup-win32-x64-msvc": "4.59.0", "fsevents": "~2.3.2" } }, @@ -8412,19 +8032,19 @@ } }, "node_modules/scheduler": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", - "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", "license": "MIT", + "peer": true, "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" + "loose-envify": "^1.1.0" } }, "node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", "dev": true, "license": "ISC", "bin": { @@ -8938,12 +8558,6 @@ "acorn-node": "^1.2.0" } }, - "node_modules/tabbable": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-5.3.3.tgz", - "integrity": "sha512-QD9qKY3StfbZqWOPLp0++pOrAVb/HbUi5xCc8cUo4XjP19808oaMiDzn0leBY5mCespIBM0CIZePzZjgzR83kA==", - "license": "MIT" - }, "node_modules/terminal-link": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", @@ -8976,10 +8590,17 @@ "node": ">=8" } }, + "node_modules/test-exclude/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, "node_modules/test-exclude/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", + "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", "dev": true, "license": "MIT", "dependencies": { @@ -8988,9 +8609,9 @@ } }, "node_modules/test-exclude/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "license": "ISC", "dependencies": { @@ -9030,12 +8651,6 @@ "node": ">=0.6.0" } }, - "node_modules/tinycolor2": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz", - "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==", - "license": "MIT" - }, "node_modules/tinyglobby": { "version": "0.2.15", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", @@ -9072,9 +8687,9 @@ } }, "node_modules/tinyglobby/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", "engines": { @@ -9166,9 +8781,9 @@ } }, "node_modules/ts-api-utils": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz", - "integrity": "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", + "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", "dev": true, "license": "MIT", "engines": { @@ -9222,12 +8837,6 @@ } } }, - "node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "license": "0BSD" - }, "node_modules/tty-browserify": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", @@ -9468,9 +9077,9 @@ "license": "MIT" }, "node_modules/vite": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz", - "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.2.tgz", + "integrity": "sha512-2N/55r4JDJ4gdrCvGgINMy+HH3iRpNIz8K6SFwVsA+JbQScLiC+clmAxBgwiSPgcG9U15QmvqCGWzMbqda5zGQ==", "dev": true, "license": "MIT", "dependencies": { @@ -9561,9 +9170,9 @@ } }, "node_modules/vite/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", "engines": { @@ -9760,9 +9369,9 @@ } }, "node_modules/ws": { - "version": "8.19.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz", - "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==", + "version": "8.20.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.1.tgz", + "integrity": "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==", "dev": true, "license": "MIT", "engines": { @@ -9864,21 +9473,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/zrender": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/zrender/-/zrender-5.6.1.tgz", - "integrity": "sha512-OFXkDJKcrlx5su2XbzJvj/34Q3m6PvyCZkVPHGYpcCJ52ek4U/ymZyfuV1nKE23AyBJ51E/6Yr0mhZ7xGTO4ag==", - "license": "BSD-3-Clause", - "dependencies": { - "tslib": "2.3.0" + "node_modules/zustand": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-3.7.2.tgz", + "integrity": "sha512-PIJDIZKtokhof+9+60cpockVOq05sJzHCriyvaLBmEJixseQ1a5Kdov6fWZfWOu5SK9c+FhH1jU0tntLxRJYMA==", + "license": "MIT", + "engines": { + "node": ">=12.7.0" + }, + "peerDependencies": { + "react": ">=16.8" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + } } }, - "node_modules/zrender/node_modules/tslib": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", - "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", - "license": "0BSD" - }, "packages/vscode-messenger": { "version": "0.6.1", "license": "MIT", @@ -9897,12 +9508,10 @@ "version": "0.6.0", "license": "MIT", "dependencies": { - "@vscode/webview-ui-toolkit": "~1.0.0", "vscode-messenger": "^0.6" }, "devDependencies": { "@types/vscode": "^1.70.0", - "@types/vscode-webview": "^1.57.0", "concurrently": "^7.6.0", "esbuild": "^0.25.0" }, @@ -9910,22 +9519,74 @@ "vscode": "^1.70.0" } }, + "packages/vscode-messenger-devtools/node_modules/baukasten-ui": { + "version": "0.3.0-next.027be66", + "resolved": "https://registry.npmjs.org/baukasten-ui/-/baukasten-ui-0.3.0-next.027be66.tgz", + "integrity": "sha512-Y4ta8bxlbuZiCPnQMrdal3pFzb51MUa5ag/z/55dsnsmaAM4al+fIe52aPfyODRL9AMrm7ktZyXmdJuJjE6yCQ==", + "license": "MIT", + "dependencies": { + "@floating-ui/react": "^0.27.16", + "@vscode/codicons": "^0.0.41", + "clsx": "^2.1.1" + }, + "peerDependencies": { + "@tanstack/react-table": "^8.21.3", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@tanstack/react-table": { + "optional": true + } + } + }, + "packages/vscode-messenger-devtools/node_modules/baukasten-ui/node_modules/@vscode/codicons": { + "version": "0.0.41", + "resolved": "https://registry.npmjs.org/@vscode/codicons/-/codicons-0.0.41.tgz", + "integrity": "sha512-v6/8nx76zau3Joxjzi3eN/FVw+7jKBq4j7LTZY5FhFhq2g0OoFebZ3vRZbv/pUopGpbCnJJ4FOz+NzbjVsmoiw==", + "license": "CC-BY-4.0" + }, + "packages/vscode-messenger-devtools/node_modules/react": { + "version": "19.2.6", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.6.tgz", + "integrity": "sha512-sfWGGfavi0xr8Pg0sVsyHMAOziVYKgPLNrS7ig+ivMNb3wbCBw3KxtflsGBAwD3gYQlE/AEZsTLgToRrSCjb0Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "packages/vscode-messenger-devtools/node_modules/react-dom": { + "version": "19.2.6", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.6.tgz", + "integrity": "sha512-0prMI+hvBbPjsWnxDLxlCGyM8PN6UuWjEUCYmZhO67xIV9Xasa/r/vDnq+Xyq4Lo27g8QSbO5YzARu0D1Sps3g==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.6" + } + }, + "packages/vscode-messenger-devtools/node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "license": "MIT" + }, "packages/vscode-messenger-devtools/webview-ui": { "name": "devtools-ui", "version": "0.6.0", "dependencies": { - "@vscode/webview-ui-toolkit": "^1.0.0", - "ag-grid-community": "~31.3.4", - "ag-grid-react": "~31.3.4", - "echarts": "^5.3.3", - "react": "^17.0.0", - "react-dom": "^17.0.0", - "react-force-graph-2d": "~1.24.0", - "vscode-messenger-webview": "~0.6.0" + "@tanstack/react-table": "~8.21.3", + "baukasten-ui": "0.3.0-next.027be66", + "react": "~19.2", + "react-dom": "~19.2", + "vscode-messenger-webview": "~0.6.0", + "zustand": "^3.7.2" }, "devDependencies": { - "@types/react": "^17.0.0", - "@types/react-dom": "^17.0.0", + "@types/react": "~19.2", + "@types/react-dom": "~19.2", "@types/vscode-webview": "^1.57.0", "@vitejs/plugin-react": "^4.7.0", "@vscode/codicons": "0.0.20", diff --git a/packages/vscode-messenger-devtools/README.md b/packages/vscode-messenger-devtools/README.md index 5a56cfe..d9f7a0d 100644 --- a/packages/vscode-messenger-devtools/README.md +++ b/packages/vscode-messenger-devtools/README.md @@ -1,29 +1,123 @@ # VS Code Messenger Developer Tool -Shows messages sended between extension and registered extension webviews. Provides information about installed extensions that uses -[vscode-messenger](https://github.com/TypeFox/vscode-messenger) library. +Visualizes message traffic — requests, responses, and notifications — between a VS Code extension host and its registered webviews for extensions that use the [vscode-messenger](https://github.com/TypeFox/vscode-messenger) library. It is the fastest way to answer "is the message actually being sent?", "did the receiver get it?", and "what does the payload look like?" while developing or debugging. -## Open Devtool View +## Open the devtool view -Open _Command Palette..._ (Shift + Cmd + P) -Type _devtools_, execute command 'Developer: Open vscode-messenger devtools' +Open the Command Palette (`Shift+Cmd+P` / `Ctrl+Shift+P`) and run **Developer: Open vscode-messenger devtools**. -![Missing Devtool View Screenshot](https://github.com/TypeFox/vscode-messenger/blob/main/packages/vscode-messenger-devtools/media/view-screenshot.png?raw=true) +The devtool lists every installed extension that depends on `vscode-messenger`. Select yours to see its registered webviews, pending requests, registered handlers, and a live event log. -**Note:** Your extension must export `Messenger.diagnosticApi()` as public API. Otherwise it is not possible to display relevant information. +![Devtool View Screenshot](https://github.com/TypeFox/vscode-messenger/blob/main/packages/vscode-messenger-devtools/media/view-screenshot.png?raw=true) + +## Exposing the diagnostic API from your extension + +The devtool reads from the public API your `activate` function returns. Your extension must call `messenger.diagnosticApi()` and return the result — otherwise the devtool can see that your extension uses the library but cannot display any traffic. ```ts import * as vscode from 'vscode'; -import { Messenger } from 'vscode-messenger'; +import { Messenger, type MessengerDiagnostic } from 'vscode-messenger'; const messenger = new Messenger(); -export function activate(context: vscode.ExtensionContext) { +export function activate(context: vscode.ExtensionContext): MessengerDiagnostic { // Your activation code... return messenger.diagnosticApi(); } ``` -[Devtools Repository](https://github.com/TypeFox/vscode-messenger/tree/main/packages/vscode-messenger-devtools#readme) +If your extension already exports a public API, spread the diagnostic methods into it: + +```ts +export function activate(context: vscode.ExtensionContext) { + // Your activation code... + return { + ...yourApi, + ...messenger.diagnosticApi() + }; +} +``` + +The devtool checks `isMessengerDiagnostic(api)` against the returned object — it looks for `extensionInfo`, `addEventListener`, and `removeEventListener` on the value. Spreading preserves those. + +## `DiagnosticOptions` + +`diagnosticApi(options?)` accepts two optional flags. Both default to `false` to avoid leaking sensitive payload data to anything that can read your extension's public API. + +| Option | Default | Effect | +|---|---|---| +| `withParameterData` | `false` | Includes request/notification `params` as `MessengerEvent.parameter` in every event. | +| `withResponseData` | `false` | Includes response `result` as `MessengerEvent.parameter` on `type: 'response'` events. | + +Enable both during development to see full payload values in the event details panel: + +```ts +return messenger.diagnosticApi({ withParameterData: true, withResponseData: true }); +``` + +## What the devtool shows + +The devtool calls `extensionInfo()` to populate the overview panel: + +- **webviews** — registered webview instances (`{ id, type }`) +- **handlers** — registered message handlers (`{ method, count }`) +- **pendingRequest** — count of in-flight requests +- **diagnosticListeners** — count of active event subscribers + +It also subscribes via `addEventListener` to receive a `MessengerEvent` for every message that passes through the host-side `Messenger`: + +| Field | Description | +|---|---| +| `type` | `'request'`, `'response'`, `'notification'`, or `'unknown'` | +| `id?` | Request id — set for requests and their matching responses | +| `method?` | Message method name (absent on `response` events — correlate by `id`) | +| `sender`, `receiver` | Stringified participants: `'host extension'`, `webviewId`, `webviewType`, or `'broadcast'` | +| `parameter?` | Payload — only populated when `withParameterData` / `withResponseData` is enabled | +| `error?` | Error message for failed responses | +| `size` | Serialized payload byte-size estimate | +| `timestamp` | `Date.now()` at the moment the event was emitted | + +## Customizing events before they reach the devtool + +You can wrap `addEventListener` to mutate events before any listener — including the devtool — sees them. A useful pattern is to decorate method names with their parameter values so the event timeline is easier to read: + +```ts +export function activate(context: vscode.ExtensionContext): MessengerDiagnostic { + // Your activation code... + + const diagnostics = messenger.diagnosticApi({ + withParameterData: true, + withResponseData: true + }); + + return { + ...diagnostics, + addEventListener: (listener) => diagnostics.addEventListener(event => { + if (event.method === 'colorSelected') { + event.method = `colorSelected(${JSON.stringify(event.parameter)})`; + } + listener(event); + }) + }; +} +``` + +The wrapper must still satisfy `isMessengerDiagnostic` — keep the original `extensionInfo` and `removeEventListener` on the returned object (the spread above handles this). + +## Troubleshooting + +**No row for my extension in the devtool** +The devtool detected that your extension depends on `vscode-messenger` but `activate` either threw, returned `undefined`, or returned something where `isMessengerDiagnostic` is false. Confirm that `activate` returns the diagnostic object (or a spread that includes its three methods: `extensionInfo`, `addEventListener`, `removeEventListener`). + +**Extension is listed, but no events appear** +`activate` returned the diagnostic API, but no traffic has been produced yet — trigger a message. Note that the host-side `Messenger` only observes host-side traffic; webview-internal processing does not produce events until a message is posted back to the host. + +**Events appear but `parameter` is always empty** +`withParameterData` and `withResponseData` are both `false` by default. Pass `{ withParameterData: true, withResponseData: true }` to `diagnosticApi` in your dev build. + +**Events visible for one webview only** +The diagnostic API observes only the `Messenger` instance you exposed. If your extension creates multiple `Messenger` instances (uncommon), each needs its own diagnostic export. + +--- -[Messenger Repository](https://github.com/TypeFox/vscode-messenger#readme) +[Devtools Repository](https://github.com/TypeFox/vscode-messenger/tree/main/packages/vscode-messenger-devtools#readme) · [Messenger Repository](https://github.com/TypeFox/vscode-messenger#readme) diff --git a/packages/vscode-messenger-devtools/media/view-screenshot.png b/packages/vscode-messenger-devtools/media/view-screenshot.png index 5afda7a..8cb6833 100644 Binary files a/packages/vscode-messenger-devtools/media/view-screenshot.png and b/packages/vscode-messenger-devtools/media/view-screenshot.png differ diff --git a/packages/vscode-messenger-devtools/package.json b/packages/vscode-messenger-devtools/package.json index 35c1eaa..3eb0391 100644 --- a/packages/vscode-messenger-devtools/package.json +++ b/packages/vscode-messenger-devtools/package.json @@ -51,12 +51,10 @@ "test": "node ./lib/test/runTest.js" }, "dependencies": { - "@vscode/webview-ui-toolkit": "~1.0.0", "vscode-messenger": "^0.6" }, "devDependencies": { "@types/vscode": "^1.70.0", - "@types/vscode-webview": "^1.57.0", "concurrently": "^7.6.0", "esbuild": "^0.25.0" }, diff --git a/packages/vscode-messenger-devtools/src/devtool-ext.ts b/packages/vscode-messenger-devtools/src/devtool-ext.ts index 736030a..4c6cc92 100644 --- a/packages/vscode-messenger-devtools/src/devtool-ext.ts +++ b/packages/vscode-messenger-devtools/src/devtool-ext.ts @@ -4,31 +4,19 @@ * terms of the MIT License, which is available in the project root. */ -import * as vscode from 'vscode'; import * as path from 'path'; +import * as vscode from 'vscode'; import type { ExtensionInfo, MessengerDiagnostic, MessengerEvent } from 'vscode-messenger'; import { isMessengerDiagnostic, Messenger } from 'vscode-messenger'; +import type { WebviewTypeMessageParticipant } from 'vscode-messenger-common'; import { MessagesPanel, WEBVIEW_TYPE } from './panels/MessagesPanel'; -import type { NotificationType, RequestType, WebviewTypeMessageParticipant } from 'vscode-messenger-common'; +import { ExtensionListRequest, PushDataNotification } from './messenger-types'; const devtoolsView: WebviewTypeMessageParticipant = { type: 'webview', webviewType: WEBVIEW_TYPE }; -type DataEvent = { - extension: string; - event: MessengerEvent; -}; - -const PushDataNotification: NotificationType = { - method: 'pushData' -}; - -const ExtensionListRequest: RequestType = { - method: 'extensionList' -}; - const msg = new Messenger({ debugLog: false }); const listeners = new Map(); let panel: vscode.WebviewPanel | undefined; @@ -52,7 +40,7 @@ export function activate(context: vscode.ExtensionContext) { active: ext.isActive, exportsDiagnosticApi: supportedApi, info: supportedApi ? getExtensionInfo(ext) : undefined - } as ExtensionData; + }; }); }); @@ -90,13 +78,13 @@ export function activate(context: vscode.ExtensionContext) { lastExportDirectory = path.dirname(uri.fsPath); await vscode.workspace.fs.writeFile(uri, Buffer.from(params.content, 'utf8')); vscode.window.showInformationMessage(`File exported: ${uri.fsPath}`); - return true; + return 'success'; } - return false; + return 'cancelled'; } catch (error) { console.error('Error saving file:', error); vscode.window.showErrorMessage(`Failed to save file: ${error}`); - return false; + return 'error'; } }); @@ -158,7 +146,6 @@ function listenToNotifications(messengerExts: Array>): } function listenToNotification(extension: vscode.Extension): void { - console.debug(`Extension '${extension.id}' uses vscode-messenger. Extension active: ${extension.isActive}`); const publicApi = diagnosticApi(extension); if (publicApi && !listeners.has(extension.id)) { const eventListener = (event: MessengerEvent) => { @@ -177,11 +164,3 @@ function listenToNotification(extension: vscode.Extension): void { } } -interface ExtensionData { - id: string - name: string - active: boolean - exportsDiagnosticApi: boolean - info?: ExtensionInfo - events?: MessengerEvent[] -} diff --git a/packages/vscode-messenger-devtools/src/messenger-types.ts b/packages/vscode-messenger-devtools/src/messenger-types.ts new file mode 100644 index 0000000..6424496 --- /dev/null +++ b/packages/vscode-messenger-devtools/src/messenger-types.ts @@ -0,0 +1,23 @@ +import type { ExtensionInfo, MessengerEvent } from 'vscode-messenger'; +import type { NotificationType, RequestType } from 'vscode-messenger-common'; + +export type DataEvent = { + extension: string; + event: MessengerEvent; +}; + +export const PushDataNotification: NotificationType = { + method: 'pushData' +}; + +export const ExtensionListRequest: RequestType = { + method: 'extensionList' +}; + +export interface ExtensionData { + id: string + name: string + active: boolean + exportsDiagnosticApi: boolean + info?: ExtensionInfo +} diff --git a/packages/vscode-messenger-devtools/webview-ui/css/devtools-view.css b/packages/vscode-messenger-devtools/webview-ui/css/devtools-view.css index 59c2d54..df04786 100644 --- a/packages/vscode-messenger-devtools/webview-ui/css/devtools-view.css +++ b/packages/vscode-messenger-devtools/webview-ui/css/devtools-view.css @@ -34,7 +34,14 @@ html { body { height: 100%; - --event-table-class: ag-theme-alpine + --event-table-class: ag-theme-alpine; + + /* Shared message-type colors used by the data table rows (rowType_*) + and the messenger chart (.messenger-chart__bar). Override these to + re-skin the entire devtools UI in one place. */ + --messenger-color-request: var(--vscode-textLink-foreground); + --messenger-color-response: var(--vscode-editorGutter-addedBackground); + --messenger-color-notification: var(--vscode-editorMarkerNavigationWarning-background); } body[data-vscode-theme-kind="vscode-dark"] { @@ -66,6 +73,177 @@ body[data-vscode-theme-kind="vscode-dark"] { #charts { display: flex; flex-direction: row; + align-items: flex-start; + gap: 12px; + padding: 8px 0 4px 0; +} + +/* MessengerChart component */ +.messenger-chart { + position: relative; + flex: 1 1 0; + min-width: 0; + display: flex; + flex-direction: column; + font-family: var(--vscode-font-family); + font-size: var(--vscode-font-size); + color: var(--vscode-foreground); + background: color-mix(in srgb, var(--vscode-editor-background) 92%, transparent); + border: 1px solid var(--vscode-panel-border, color-mix(in srgb, var(--vscode-foreground) 12%, transparent)); + border-radius: 8px; + padding: 12px 0 4px 0; + box-sizing: border-box; + z-index: 0; +} + +.messenger-chart:hover { + z-index: 1; +} + +.messenger-chart__title { + font-size: 11px; + font-weight: 600; + letter-spacing: 0.04em; + text-transform: uppercase; + color: var(--vscode-descriptionForeground, var(--vscode-foreground)); + margin-bottom: 8px; + padding: 0 14px; + box-sizing: border-box; +} + +.messenger-chart__legend { + display: flex; + flex-wrap: wrap; + gap: 12px; + margin-bottom: 10px; + padding: 0 14px; + box-sizing: border-box; +} + +.messenger-chart__legend-item { + display: inline-flex; + align-items: center; + gap: 6px; + font-size: 11px; + color: var(--vscode-descriptionForeground, var(--vscode-foreground)); +} + +.messenger-chart__legend-swatch { + display: inline-block; + width: 10px; + height: 10px; + border-radius: 3px; + flex-shrink: 0; +} + +.messenger-chart__legend-label { + text-transform: capitalize; +} + +.messenger-chart__canvas { + position: relative; + flex: 1 1 auto; + min-width: 0; + overflow: hidden; + padding: 0 14px; + box-sizing: border-box; +} + +.messenger-chart__svg { + display: block; + width: 100%; + height: 100%; + overflow: visible; + cursor: default; + user-select: none; +} + +.messenger-chart__gridline { + stroke: var(--vscode-charts-lines, color-mix(in srgb, var(--vscode-foreground) 14%, transparent)); + stroke-width: 1; + stroke-dasharray: 2 4; + shape-rendering: crispEdges; +} + +.messenger-chart__tick-label, +.messenger-chart__sender-label, +.messenger-chart__value-label { + fill: var(--vscode-descriptionForeground, var(--vscode-foreground)); + font-size: 10.5px; + font-family: var(--vscode-font-family); +} + +.messenger-chart__sender-label { + fill: var(--vscode-foreground); + font-size: 11px; +} + +.messenger-chart__value-label { + font-variant-numeric: tabular-nums; +} + +.messenger-chart__track { + fill: color-mix(in srgb, var(--vscode-foreground) 6%, transparent); +} + +.messenger-chart__bar { + transition: width 240ms cubic-bezier(0.2, 0.8, 0.2, 1), + x 240ms cubic-bezier(0.2, 0.8, 0.2, 1), + opacity 160ms ease; + cursor: default; +} + +.messenger-chart__bar:hover { + opacity: 0.85; +} + +.messenger-chart__empty { + position: absolute; + inset: 0; + display: flex; + align-items: center; + justify-content: center; + font-size: 12px; + color: var(--vscode-descriptionForeground, var(--vscode-foreground)); + opacity: 0.7; +} + +.messenger-chart__tooltip { + position: absolute; + pointer-events: none; + background: var(--vscode-editorHoverWidget-background, var(--vscode-editor-background)); + color: var(--vscode-editorHoverWidget-foreground, var(--vscode-foreground)); + border: 1px solid var(--vscode-editorHoverWidget-border, var(--vscode-panel-border, transparent)); + border-radius: 6px; + padding: 6px 8px; + font-size: 11px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.18); + white-space: nowrap; + z-index: 100; + max-width: 280px; +} + +.messenger-chart__tooltip-sender { + font-weight: 600; + margin-bottom: 4px; + overflow: hidden; + text-overflow: ellipsis; +} + +.messenger-chart__tooltip-row { + display: flex; + align-items: center; + gap: 6px; +} + +.messenger-chart__tooltip-type { + text-transform: capitalize; +} + +.messenger-chart__tooltip-value { + margin-left: auto; + font-variant-numeric: tabular-nums; + font-weight: 600; } #diagram { @@ -76,31 +254,29 @@ body[data-vscode-theme-kind="vscode-dark"] { .refresh-button, .export-json-button, .export-csv-button, -.clear-button { +.trashcan-button { margin-left: 4px; margin-top: auto; } +/* unused */ .toggle-charts-button { margin-left: auto; margin-top: auto; } -span.info-param-name { - margin-right: 10px; -} - -.ext-info-badge { - vertical-align: 'center'; - margin-right: 10px; +span.codicon.codicon-pass, +i.codicon.codicon-pass { + color: green; } - -span.ext-info-badge.codicon.codicon-warning { +span.codicon.codicon-warning, +i.codicon.codicon-warning { color: #eba800; } -span.ext-info-badge.codicon.codicon-stop { +span.codicon.codicon-stop, +i.codicon.codicon-stop { color: #ec3f00; } @@ -110,25 +286,19 @@ span.table-cell.codicon.codicon-stop { padding-left: 10px; } -span.ext-info-badge.codicon.codicon-pass { - color: green; -} -/* Table row colors*/ +/* Table row colors - share variables with .messenger-chart bars */ div.rowType_request { - color: var(--vscode-textLink-foreground) - /* blue */ + color: var(--messenger-color-request); } div.rowType_response { - color: var(--vscode-editorGutter-addedBackground) - /* green */ + color: var(--messenger-color-response); } div.rowType_notification { - color: var(--vscode-editorMarkerNavigationWarning-background) - /* orange/braun */ + color: var(--messenger-color-notification); } /* Graph diff --git a/packages/vscode-messenger-devtools/webview-ui/package.json b/packages/vscode-messenger-devtools/webview-ui/package.json index 9b93712..1e5d84e 100644 --- a/packages/vscode-messenger-devtools/webview-ui/package.json +++ b/packages/vscode-messenger-devtools/webview-ui/package.json @@ -6,24 +6,22 @@ "start": "vite", "clean": "rimraf build", "build": "tsc && vite build", - "watch": "tsc -w & vite build --watch", + "watch": "tsc -w & vite build --watch --mode development", "preview": "vite preview", "lint": "eslint src" }, "dependencies": { - "@vscode/webview-ui-toolkit": "^1.0.0", - "ag-grid-community": "~31.3.4", - "ag-grid-react": "~31.3.4", - "echarts": "^5.3.3", - "react": "^17.0.0", - "react-dom": "^17.0.0", - "react-force-graph-2d": "~1.24.0", - "vscode-messenger-webview": "~0.6.0" + "vscode-messenger-webview": "~0.6.0", + "baukasten-ui": "0.3.0-next.027be66", + "@tanstack/react-table": "~8.21.3", + "zustand": "^3.7.2", + "react": "~19.2", + "react-dom": "~19.2" }, "devDependencies": { - "@types/react": "^17.0.0", - "@types/react-dom": "^17.0.0", "@types/vscode-webview": "^1.57.0", + "@types/react": "~19.2", + "@types/react-dom": "~19.2", "@vitejs/plugin-react": "^4.7.0", "@vscode/codicons": "0.0.20", "vite": "^6.4.1" diff --git a/packages/vscode-messenger-devtools/webview-ui/src/components/data-table.tsx b/packages/vscode-messenger-devtools/webview-ui/src/components/data-table.tsx new file mode 100644 index 0000000..de9abaa --- /dev/null +++ b/packages/vscode-messenger-devtools/webview-ui/src/components/data-table.tsx @@ -0,0 +1,133 @@ +import { type ColumnDef, DataTable, type DataTableProps, Tooltip } from 'baukasten-ui'; +import type { DataTableRef } from 'baukasten-ui/extra'; +import { forwardRef } from 'react'; +import type { ExtendedMessengerEvent } from '../model/messenger-types'; +import { useDevtoolsStore } from '../utilities/data-store'; + +function renderPayloadInfo(payloadInfo: string) { + const newlineIdx = payloadInfo.indexOf('\n'); + if (newlineIdx === -1) { + return {payloadInfo}; + } + const label = payloadInfo.slice(0, newlineIdx); + const json = payloadInfo.slice(newlineIdx + 1); + return ( +

+
{label}
+
{json}
+
+ ); +} + +const columnsDef: Array> = [ + { + accessorKey: 'type', + header: 'Type', + size: 110, + cell: ({ row, getValue }) => { + const data = row.original; + const rowType = data.type ?? 'unknown'; + const error = data.error ? : undefined; + const content =
{String(getValue())}{error}
; + return data.payloadInfo + ? {content} + : content; + }, + }, + { + accessorKey: 'sender', + header: 'Sender', + size: 180, + }, + { + accessorKey: 'receiver', + header: 'Receiver', + size: 180, + }, + { + accessorKey: 'method', + header: 'Method', + size: 135, + cell: ({ row, getValue }) => { + const value = String(getValue() ?? ''); + return row.original.payloadInfo + ? {value} + : value; + }, + }, + { + accessorKey: 'size', + header: 'Size (Time)', + size: 135, + cell: ({ row }) => { + const event = row.original; + const charsCount = Intl.NumberFormat('en', { notation: 'compact' }).format(event.size); + let text = charsCount; + if (event.type === 'response' && typeof event.timeAfterRequest === 'number') { + const tookMs = event.timeAfterRequest % 1000; + const tookSec = Math.trunc(event.timeAfterRequest / 1000); + const secPart = (tookSec > 0) ? `${tookSec}s ` : ''; + text = `${charsCount} (${secPart}${tookMs}ms)`; + } + return {text}; + }, + }, + { + accessorKey: 'id', + header: 'ID', + }, + { + accessorKey: 'timestamp', + header: 'Timestamp', + size: 135, + cell: ({ getValue }) => { + const time = getValue() as number; + if (typeof time === 'number') { + const date = new Date(time); + const prependZero = (n: number) => ('0' + n).slice(-2); + return `${prependZero(date.getHours())}:${prependZero(date.getMinutes())}:${prependZero(date.getSeconds())}-${('00' + date.getMilliseconds()).slice(-3)}`; + } + return String(time); + }, + }, + { + accessorKey: 'error', + header: 'Error', + }, +]; + +export const EventTable = forwardRef>( + function EventTable(_, ref) { + const extensionId = useDevtoolsStore((state) => state.selectedExtension); + const selectedData = useDevtoolsStore((state) => state.getSelectedExtension()); + const events = selectedData?.events ?? []; + + const tableOptions: Partial> = { + enableSorting: true, + enableRowSelection: true, + enableColumnResizing: true, + fillHeight: true, + stickyHeader: true, + size: 'sm', + variant: 'zebra', + }; + + return ( + + ); + } +); \ No newline at end of file diff --git a/packages/vscode-messenger-devtools/webview-ui/src/components/diagram.tsx b/packages/vscode-messenger-devtools/webview-ui/src/components/diagram.tsx deleted file mode 100644 index d8e17ed..0000000 --- a/packages/vscode-messenger-devtools/webview-ui/src/components/diagram.tsx +++ /dev/null @@ -1,207 +0,0 @@ -import { useEffect, useRef, useState } from 'react'; -import type { ForceGraphMethods, GraphData, LinkObject, NodeObject } from 'react-force-graph-2d'; -import ForceGraph2D from 'react-force-graph-2d'; -import { HOST_EXTENSION_NAME } from '../devtools-view'; - -type GraphObjectExtension = { - name: string; - value: number; -} - -type ComponentNode = NodeObject & GraphObjectExtension & { - shortName: string; - outdated: boolean; -} -type ComponentLink = LinkObject & GraphObjectExtension - -let graphData: GraphData = { nodes: [], links: [] }; - -let storedProps: DiagramProps = { - extensionName: '', - webviews: [], - outdatedWebviews: [], - doCenter: false -}; - -type WebviewInfo = { - id: string - type: string -} - -type DiagramProps = { - extensionName: string - webviews: WebviewInfo[] - outdatedWebviews: string[] - doCenter: boolean -} - -function createDiagramData(componentProps: DiagramProps): GraphData { - if (!componentProps) { - return graphData; - } - const toCompareString = (state: DiagramProps) => - `${state.extensionName} ${[...state.webviews.map(wv => wv.id), ...state.outdatedWebviews.map(wvId => '#' + wvId)].join(',')}`; - if (toCompareString(storedProps) === toCompareString(componentProps)) { - // same data, just return the existing graph data - return graphData; - } - // reset graphData, store new state - graphData = { nodes: [], links: [] }; - - storedProps = componentProps; - - const unqualifiedName = (name: string) => name.split('.').pop(); - - if (componentProps.extensionName) { - graphData.nodes.push({ - id: HOST_EXTENSION_NAME, - name: componentProps.extensionName, - shortName: unqualifiedName(componentProps.extensionName), - nodeLabel: 'Host', - outdated: false, - value: 10 - } as ComponentNode); - - } - - const createNodeAndLinks = (webview: WebviewInfo, outdated = false) => { - const linkDist = outdated ? 30 : 40; - graphData.nodes.push({ - id: webview.id, - name: webview.type, - shortName: unqualifiedName(webview.type), - outdated, - value: outdated ? 7 : 7, - } as ComponentNode); - // connect both ends to send particles both directions - graphData.links.push({ - source: HOST_EXTENSION_NAME, - target: webview.id, - name: `${HOST_EXTENSION_NAME} to ${webview.id}`, - value: linkDist - } as ComponentLink); - graphData.links.push({ - source: webview.id, - target: HOST_EXTENSION_NAME, - name: `${webview.id} to ${HOST_EXTENSION_NAME}`, - value: linkDist - } as ComponentLink); - }; - componentProps.webviews.forEach(view => createNodeAndLinks(view)); - componentProps.outdatedWebviews.forEach(view => - createNodeAndLinks({ id: view, type: view }, true) - ); - return graphData; -} - -export type HighlightData = { link: string | string[], type: string } - -export let updateLinks: (update: HighlightData[]) => void = () => void 0; - -export function Diagram(props: DiagramProps): JSX.Element { - - const [highlightLinks, setHighlightLinks] = useState(Array()); - updateLinks = setHighlightLinks; - - function toParticleColor(type: string | undefined): string { - switch (type) { - case 'request': return '#0088ff'; - case 'response': return '#27ba10'; - case 'notification': return '#ebe809'; - default: return ''; - } - } - const diagramRef = useRef(); - - useEffect(() => { - setTimeout(() => { - if (diagramRef.current && props.doCenter) { - // set distance between nodes - diagramRef.current.d3Force('link')?.distance((link: { value: number }) => link.value); - // center diagram after diagram panel is shown - diagramRef.current.zoomToFit(500, 50); - } - }, 150); - }, [props.doCenter]); - - const graphData = createDiagramData(props); - let particleSize = 0; - let particleColor: string | undefined = undefined; - - useEffect(() => { - highlightLinks.forEach((highlight, index) => { - const initiateParticle = (linkStr: string) => { - const linkObj = graphData.links.find(link => linkStr === linkId(link)); - if (linkObj) { - setTimeout(() => { - particleSize = 12; - particleColor = toParticleColor(highlight.type); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (linkObj as unknown as any).color = particleColor; - diagramRef.current?.emitParticle(linkObj); - }, index * 600); - } - }; - if (Array.isArray(highlight.link)) { - // broadcast case - highlight.link.forEach(initiateParticle); - } else { - initiateParticle(highlight.link); - } - }); - }, [highlightLinks]); - - return (link.target as NodeObject)?.id === HOST_EXTENSION_NAME ? 1 : 3} - nodeCanvasObject={(rawNode, ctx, _globalScale) => { - rawNode.vx = 10; - rawNode.vy = 10; - paintNode(rawNode, (rawNode as { color: string }).color, ctx); - }} - nodePointerAreaPaint={paintNode} - />; - -} - -function linkId(link: LinkObject): string { - return toLinkId((link.source as NodeObject).id, (link.target as NodeObject).id); -} - -export function toLinkId(source: string | number | undefined, target: string | number | undefined): string { - return `${source}->${target}`; -} - -function paintNode(rawNode: NodeObject, color: string, ctx: CanvasRenderingContext2D) { - const node = rawNode as NodeObject & ComponentNode; - if (node.x && node.y) { - ctx.fillStyle = color; - ctx.beginPath(); - const radius = node.value; - const circleData = { x: node.x, y: node.y, radius: node.outdated ? radius - 3 : radius }; - ctx.arc(circleData.x, circleData.y, circleData.radius, 0, 2 * Math.PI); - ctx.fill(); - ctx.setLineDash([]); - ctx.lineWidth = 0.3; - ctx.strokeStyle = '#888888'; - ctx.stroke(); - ctx.closePath(); - - if (node.outdated) { - ctx.beginPath(); - ctx.setLineDash([1, 1]); - ctx.strokeStyle = '#aabbbb'; - ctx.arc(circleData.x, circleData.y, circleData.radius + 1, 0, 2 * Math.PI); - ctx.stroke(); - ctx.closePath(); - } - } -} \ No newline at end of file diff --git a/packages/vscode-messenger-devtools/webview-ui/src/components/event-table.tsx b/packages/vscode-messenger-devtools/webview-ui/src/components/event-table.tsx deleted file mode 100644 index 9cbf2e9..0000000 --- a/packages/vscode-messenger-devtools/webview-ui/src/components/event-table.tsx +++ /dev/null @@ -1,139 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import type { ColDef, GridApi } from 'ag-grid-community'; -import 'ag-grid-community/styles/ag-grid.css'; -import 'ag-grid-community/styles/ag-theme-alpine.css'; -import { AgGridReact } from 'ag-grid-react'; -import React from 'react'; -import type { MessengerEvent } from 'vscode-messenger'; -import type { ExtendedMessengerEvent } from '../devtools-view'; - -const columnDefs: ColDef[] = [ - { - field: 'type', - initialWidth: 110, - cellRenderer: (params: any) => { - const rowType = params.data.type ?? 'unknown'; - const error = params.data.error ? : undefined; - return
{params.value}{error}
; - }, - tooltipField: 'payloadInfo' - }, - { field: 'sender', initialWidth: 180 }, - { field: 'receiver', initialWidth: 180 }, - { - field: 'method', initialWidth: 135, - tooltipField: 'payloadInfo' - }, - { - field: 'size', headerName: 'Size (Time)', initialWidth: 135, - cellRenderer: (params: any) => { - const event = (params.data as ExtendedMessengerEvent); - const charsCount = Intl.NumberFormat('en', { notation: 'compact' }).format(event.size); - if (event.type === 'response' && typeof event.timeAfterRequest === 'number') { - const tookMs = event.timeAfterRequest % 1000; - const tookSec = Math.trunc(event.timeAfterRequest / 1000); - const secPart = (tookSec > 0) ? `${tookSec}s ` : ''; - return `${charsCount} (${secPart}${tookMs}ms)`; - } - return charsCount; - - } - }, - { field: 'id' }, - { - field: 'timestamp', - initialWidth: 135, - cellRenderer: (params: any) => { - const time = params.data.timestamp; - if (typeof time === 'number') { - const date = new Date(time); - const prependZero = (n: number) => ('0' + n).slice(-2); - return `${prependZero(date.getHours())}:${prependZero(date.getMinutes())}:${prependZero(date.getSeconds())}-${('00' + date.getMilliseconds()).slice(-3)}`; - } - return String(time); - } - }, - { field: 'error' }, -]; - -/** - * Table that shows messages exchanged between the extension and the webviews. - */ -export class EventTable extends React.Component { - - gridRefObj: React.RefObject>; - props: { gridRowSelected: (e: any) => void }; - - constructor(props: { gridRowSelected: (e: any) => void }) { - super({}); - this.props = props; - this.gridRefObj = React.createRef(); - } - - getGridApi(): GridApi | undefined { - return this.gridRefObj.current?.api; - } - - /** - * Export grid data as JSON - * @param onlySelected - if true, exports only selected rows - * @returns JSON string of the grid data - */ - exportAsJSON(onlySelected: boolean = false): string { - const api = this.getGridApi(); - if (!api) return '[]'; - - const rowData: any[] = []; - - if (onlySelected) { - // Export only selected rows - const selectedNodes = api.getSelectedNodes(); - selectedNodes.forEach(node => { - if (node.data) { - rowData.push(node.data); - } - }); - } else { - // Export all rows (respecting current filter/sort) - api.forEachNodeAfterFilterAndSort(node => { - if (node.data) { - rowData.push(node.data); - } - }); - } - - return JSON.stringify(rowData, null, 2); - } - - render(): JSX.Element { - return ( -
- { - return { - filter: true, resizable: true, sortable: true, - cellStyle: (params: any) => { - if (params.value === 'Police') { - return { color: 'red', backgroundColor: 'green' }; - } - return null; - }, - tooltipField: col.field, - ...col - }; - })} - rowHeight={25} - headerHeight={28} - enableBrowserTooltips={true} - rowSelection="multiple" - onCellFocused={(e) => this.props.gridRowSelected(e)} - onSelectionChanged={(e) => this.props.gridRowSelected(e)} - > - -
- ); - } -} \ No newline at end of file diff --git a/packages/vscode-messenger-devtools/webview-ui/src/components/extension-info.tsx b/packages/vscode-messenger-devtools/webview-ui/src/components/extension-info.tsx new file mode 100644 index 0000000..c4b140a --- /dev/null +++ b/packages/vscode-messenger-devtools/webview-ui/src/components/extension-info.tsx @@ -0,0 +1,78 @@ +import type { CodiconName } from 'baukasten-ui'; +import { Badge, Icon, Text } from 'baukasten-ui'; +import React from 'react'; +import type { ExtendedExtensionData } from '../model/messenger-types'; +import { useDevtoolsStore } from '../utilities/data-store'; + +interface ExtensionInfoPanelProps { + selectedExtensionProp?: ExtendedExtensionData; +} + +export const ExtensionInfoPanel: React.FC = ({ selectedExtensionProp }) => { + const selectedExtension = selectedExtensionProp ?? useDevtoolsStore((state) => state.getSelectedExtension()); + const statusData: OptionalInfoBadgeProps = + (selectedExtension) ? + { + icon: !selectedExtension?.active ? 'warning' : (!selectedExtension?.exportsDiagnosticApi ? 'stop' : 'pass'), + title: + 'Extension ' + + (!selectedExtension?.active ? 'is not active' : + (!selectedExtension?.exportsDiagnosticApi ? "doesn't export diagnostic API" + : 'is active and exports diagnostic API.')) + } + : { + icon: 'question', + title: 'No extension selected' + }; + const webviewsData = { + value: selectedExtension?.info?.webviews?.length ?? 0, + title: 'Registered views:\n' + (selectedExtension?.info?.webviews ?? []).map(entry => ' ' + entry.id) + .join('\n') + }; + const handlersData = { + value: selectedExtension?.info?.handlers?.length ?? 0, + title: 'Number of added method handlers: \n' + + (selectedExtension?.info?.handlers ?? []).map(entry => ' ' + entry.method + ': ' + entry.count) + .join('\n') + }; + return ( + <> +
+ + + + + + +
+ + ); +}; + +type OptionalInfoBadgeProps = { + value?: string | number; + icon?: CodiconName; + title?: string; +}; + +function InfoBadge(props: { label: string } & OptionalInfoBadgeProps): React.JSX.Element { + // TODO move back to css file + const marginRight = { marginRight: '10px' }; + return (<> + {props.label} + {props.icon && + + } + {props.value !== undefined && + + {props.value ?? '?'} + + } + ); +} diff --git a/packages/vscode-messenger-devtools/webview-ui/src/components/messenger-chart.tsx b/packages/vscode-messenger-devtools/webview-ui/src/components/messenger-chart.tsx new file mode 100644 index 0000000..29ac496 --- /dev/null +++ b/packages/vscode-messenger-devtools/webview-ui/src/components/messenger-chart.tsx @@ -0,0 +1,444 @@ +import React, { useEffect, useId, useMemo, useRef, useState } from 'react'; +import type { MessengerEvent } from 'vscode-messenger'; + +export type MessengerEventType = 'request' | 'response' | 'notification'; + +export interface MessengerSenderStats { + sender: string; + count: Record; + size: Record; +} + +export type ChartLayout = 'stacked' | 'grouped'; +export type ChartMetric = 'count' | 'size'; + +export interface MessengerChartProps { + data: MessengerSenderStats[]; + metric: ChartMetric; + layout?: ChartLayout; + title?: string; + /** Suffix appended to values in legend/tooltip, e.g. " chars". */ + unitSuffix?: string; + /** Optional fixed SVG height. When omitted, height is derived from row count. */ + height?: number; +} + +const EVENT_TYPES: readonly MessengerEventType[] = ['request', 'response', 'notification'] as const; + +// Sourced from CSS custom properties defined on `body` in devtools-view.css. +// The same variables drive the data table's rowType_* classes, so changing them +// in one place updates both the table and the chart. +const TYPE_COLORS: Record = { + request: 'var(--messenger-color-request, #3794ff)', + response: 'var(--messenger-color-response, #6cc063)', + notification: 'var(--messenger-color-notification, #d18616)' +}; + +const STACKED_BAR_HEIGHT = 22; +const STACKED_ROW_GAP = 14; +const GROUPED_BAR_HEIGHT = 9; +const GROUPED_BAR_GAP = 2; +const GROUPED_OUTER_GAP = 14; +const TOP_PADDING = 8; +const BOTTOM_PADDING = 20; +const LEFT_GUTTER = 140; +const RIGHT_PADDING = 56; +const MIN_WIDTH = 280; +const MAX_LABEL_CHARS = 18; + +const valueFormatter = new Intl.NumberFormat('en', { notation: 'compact', maximumFractionDigits: 1 }); +const fullFormatter = new Intl.NumberFormat('en'); + +/** + * Aggregate raw messenger events into per-sender request/response/notification totals. + */ +export function collectSenderStats(events: MessengerEvent[]): MessengerSenderStats[] { + const map = new Map(); + const ensure = (sender: string): MessengerSenderStats => { + let stats = map.get(sender); + if (!stats) { + stats = { + sender, + count: { request: 0, response: 0, notification: 0 }, + size: { request: 0, response: 0, notification: 0 } + }; + map.set(sender, stats); + } + return stats; + }; + + for (const event of events) { + const type = event.type as MessengerEventType; + if (type !== 'request' && type !== 'response' && type !== 'notification') continue; + const stats = ensure(event.sender ?? 'unknown'); + stats.count[type] += 1; + stats.size[type] += event.size; + } + + return Array.from(map.values()).sort((a, b) => a.sender.localeCompare(b.sender)); +} + +interface NiceScale { max: number; ticks: number[]; } + +function niceScale(rawMax: number, tickCount = 4): NiceScale { + if (rawMax <= 0) { + return { max: 1, ticks: [0, 1] }; + } + const exp = Math.floor(Math.log10(rawMax)); + const fraction = rawMax / Math.pow(10, exp); + let niceFraction: number; + if (fraction <= 1) niceFraction = 1; + else if (fraction <= 2) niceFraction = 2; + else if (fraction <= 5) niceFraction = 5; + else niceFraction = 10; + const niceMax = niceFraction * Math.pow(10, exp); + const step = niceMax / tickCount; + const ticks: number[] = []; + for (let i = 0; i <= tickCount; i++) ticks.push(step * i); + return { max: niceMax, ticks }; +} + +function truncate(value: string, max: number): string { + if (value.length <= max) return value; + const half = Math.floor((max - 1) / 2); + return value.slice(0, half) + '\u2026' + value.slice(value.length - (max - 1 - half)); +} + +interface TooltipState { + x: number; + y: number; + sender: string; + type: MessengerEventType; + value: number; +} + +export function MessengerChart({ + data, + metric, + layout = 'stacked', + title, + unitSuffix, + height +}: MessengerChartProps): React.JSX.Element { + const containerRef = useRef(null); + const clipBaseId = useId(); + const [width, setWidth] = useState(0); + const [tooltip, setTooltip] = useState(null); + + useEffect(() => { + const el = containerRef.current; + if (!el) return; + const observer = new ResizeObserver(entries => { + for (const entry of entries) { + setWidth(entry.contentRect.width); + } + }); + observer.observe(el); + setWidth(el.clientWidth); + return () => observer.disconnect(); + }, []); + + const senders = data; + + const rawMax = useMemo(() => { + if (senders.length === 0) return 0; + if (layout === 'stacked') { + return senders.reduce((acc, s) => { + const total = EVENT_TYPES.reduce((sum, t) => sum + s[metric][t], 0); + return Math.max(acc, total); + }, 0); + } + return senders.reduce( + (acc, s) => EVENT_TYPES.reduce((sub, t) => Math.max(sub, s[metric][t]), acc), + 0 + ); + }, [senders, metric, layout]); + + const scale = useMemo(() => niceScale(rawMax, 4), [rawMax]); + + const computedRowsHeight = useMemo(() => { + if (senders.length === 0) return 60; + if (layout === 'stacked') { + return senders.length * (STACKED_BAR_HEIGHT + STACKED_ROW_GAP) - STACKED_ROW_GAP; + } + const groupHeight = GROUPED_BAR_HEIGHT * 3 + GROUPED_BAR_GAP * 2; + return senders.length * (groupHeight + GROUPED_OUTER_GAP) - GROUPED_OUTER_GAP; + }, [senders.length, layout]); + + const svgHeight = height ?? (TOP_PADDING + computedRowsHeight + BOTTOM_PADDING); + + const effectiveWidth = Math.max(MIN_WIDTH, width || MIN_WIDTH); + const chartWidth = Math.max(40, effectiveWidth - LEFT_GUTTER - RIGHT_PADDING); + const chartLeft = LEFT_GUTTER; + const chartRight = chartLeft + chartWidth; + + const valueToX = (v: number): number => + chartLeft + (scale.max === 0 ? 0 : (v / scale.max) * chartWidth); + + const handleHover = ( + sender: string, + type: MessengerEventType, + value: number, + event: React.MouseEvent + ): void => { + const rect = containerRef.current?.getBoundingClientRect(); + if (!rect) return; + setTooltip({ + x: event.clientX - rect.left, + y: event.clientY - rect.top, + sender, + type, + value + }); + }; + const handleLeave = (): void => setTooltip(null); + + return ( +
+ {title &&
{title}
} +
+ {EVENT_TYPES.map(type => ( +
+
+ ))} +
+
+ {senders.length === 0 ? ( +
No events yet
+ ) : ( + + + {senders.map((s, idx) => { + const rowY = layout === 'stacked' + ? TOP_PADDING + idx * (STACKED_BAR_HEIGHT + STACKED_ROW_GAP) + : 0; + return ( + + + + ); + })} + + + {scale.ticks.map((tick, i) => { + const x = valueToX(tick); + return ( + + + {valueFormatter.format(tick)} + + ); + })} + + {senders.map((s, idx) => ( + layout === 'stacked' + ? renderStackedRow({ + s, idx, metric, scale, chartLeft, chartWidth, chartRight, + clipId: `${clipBaseId}-row-${idx}`, + unitSuffix, onHover: handleHover, onLeave: handleLeave + }) + : renderGroupedRow({ + s, idx, metric, scale, chartLeft, chartWidth, + onHover: handleHover, onLeave: handleLeave + }) + ))} + + )} +
+ {tooltip && ( +
+
{tooltip.sender}
+
+
+
+ )} +
+ ); +} + +interface StackedRowArgs { + s: MessengerSenderStats; + idx: number; + metric: ChartMetric; + scale: NiceScale; + chartLeft: number; + chartWidth: number; + chartRight: number; + clipId: string; + unitSuffix?: string; + onHover: (sender: string, type: MessengerEventType, value: number, e: React.MouseEvent) => void; + onLeave: () => void; +} + +function renderStackedRow(args: StackedRowArgs): React.JSX.Element { + const { s, idx, metric, scale, chartLeft, chartWidth, chartRight, clipId, unitSuffix, onHover, onLeave } = args; + const rowY = TOP_PADDING + idx * (STACKED_BAR_HEIGHT + STACKED_ROW_GAP); + const total = EVENT_TYPES.reduce((sum, t) => sum + s[metric][t], 0); + let cursor = chartLeft; + return ( + + + {truncate(s.sender, MAX_LABEL_CHARS)} + + + + {EVENT_TYPES.map(type => { + const value = s[metric][type]; + if (value <= 0) return null; + const segWidth = scale.max === 0 ? 0 : (value / scale.max) * chartWidth; + const x = cursor; + cursor += segWidth; + return ( + onHover(s.sender, type, value, e)} + onMouseLeave={onLeave} + /> + ); + })} + + {total > 0 && ( + {valueFormatter.format(total)}{unitSuffix ?? ''} + )} + + ); +} + +interface GroupedRowArgs { + s: MessengerSenderStats; + idx: number; + metric: ChartMetric; + scale: NiceScale; + chartLeft: number; + chartWidth: number; + onHover: (sender: string, type: MessengerEventType, value: number, e: React.MouseEvent) => void; + onLeave: () => void; +} + +function renderGroupedRow(args: GroupedRowArgs): React.JSX.Element { + const { s, idx, metric, scale, chartLeft, chartWidth, onHover, onLeave } = args; + const groupHeight = GROUPED_BAR_HEIGHT * 3 + GROUPED_BAR_GAP * 2; + const groupY = TOP_PADDING + idx * (groupHeight + GROUPED_OUTER_GAP); + return ( + + + {truncate(s.sender, MAX_LABEL_CHARS)} + + {EVENT_TYPES.map((type, ti) => { + const value = s[metric][type]; + const barY = groupY + ti * (GROUPED_BAR_HEIGHT + GROUPED_BAR_GAP); + const barWidth = scale.max === 0 ? 0 : (value / scale.max) * chartWidth; + return ( + + + onHover(s.sender, type, value, e)} + onMouseLeave={onLeave} + /> + + ); + })} + + ); +} diff --git a/packages/vscode-messenger-devtools/webview-ui/src/components/react-echart.tsx b/packages/vscode-messenger-devtools/webview-ui/src/components/react-echart.tsx deleted file mode 100644 index 85e7bfa..0000000 --- a/packages/vscode-messenger-devtools/webview-ui/src/components/react-echart.tsx +++ /dev/null @@ -1,169 +0,0 @@ -import type { ECharts, EChartsOption, SetOptionOpts } from 'echarts'; -import { getInstanceByDom, init } from 'echarts'; -import type { CSSProperties } from 'react'; -import { useEffect, useRef } from 'react'; -import type { MessengerEvent } from 'vscode-messenger'; - -export interface ReactEChartsProps { - option: EChartsOption; - style?: CSSProperties; - settings?: SetOptionOpts; - loading?: boolean; - theme?: 'light' | 'dark'; -} - -export type ChartData = Map; - -export function createOptions(charSeries: Array<{ name: string, data: number[] }>, yAxis: string[], legendFormat = '', theme?: 'light' | 'dark'): ReactEChartsProps['option'] { - // Use VS Code theme colors for better integration - // In dark theme, use a lighter gray; in light theme, use a darker gray for better contrast - const legendTextColor = theme === 'dark' ? '#cccccc' : '#616161'; - - const option: ReactEChartsProps['option'] = { - tooltip: { - trigger: 'axis', - axisPointer: { - type: 'shadow', - }, - }, - legend: { - orient: 'horizontal', - formatter: `{name}${legendFormat}`, - textStyle: { - color: legendTextColor - } - }, - grid: { - show: true, - top: 30, - left: 1, - bottom: '2%', - containLabel: true - }, - xAxis: { - type: 'value', - boundaryGap: [0, 0.01] - }, - yAxis: { - type: 'category', - data: yAxis - }, - series: charSeries.map((chunk) => { return { ...chunk, type: 'bar' }; }) - }; - return option; -} - -export function collectChartData(renderingData: MessengerEvent[]): { series: [Array<{ name: string, data: number[] }>, Array<{ name: string, data: number[] }>], senderY: string[] } { - const chartData: ChartData = new Map(); - const charSeries: [Array<{ name: string, data: number[] }>, Array<{ name: string, data: number[] }>] = [[], []]; - renderingData.map(d => d.sender ?? 'unknown').filter((value, index, self) => self.indexOf(value) === index).sort().forEach((it) => { - chartData.set(it, { - notification: [0, 0], - response: [0, 0], - request: [0, 0] - }); - }); - - renderingData.forEach((entry) => { - const value = chartData.get(entry.sender ?? 'unknown'); - if (value) { - switch (entry.type) { - case 'request': - value.request[0] += entry.size; - value.request[1] += 1; - break; - case 'response': - value.response[0] += entry.size; - value.response[1] += 1; - break; - case 'notification': - value.notification[0] += entry.size; - value.notification[1] += 1; - break; - } - } - }); - ['request', 'response', 'notification'].forEach(type => { - const data = Array.from(chartData.values()).map(value => { - if (type === 'request') - return value.request; - else if (type === 'response') - return value.response; - else if (type === 'notification') - return value.notification; - else - return [0, 0]; - }); - charSeries[0].push({ - name: type, - data: data.map(senderData => senderData[0]) - }); - charSeries[1].push({ - name: type, - data: data.map(senderData => senderData[1]) - }); - }); - return { series: charSeries, senderY: Array.from(chartData.keys()) }; -} -export function ReactECharts({ - option, - style, - settings, - loading, - theme -}: ReactEChartsProps): JSX.Element { - const chartRef = useRef(null); - - useEffect(() => { - // Initialize chart - let chart: ECharts | undefined; - if (chartRef.current !== null) { - chart = init(chartRef.current, theme); - } - - // Add chart resize listener - // ResizeObserver is leading to a bit janky UX - function resizeChart() { - chart?.resize(); - } - window.addEventListener('resize', resizeChart); - - // Return cleanup function - return () => { - chart?.dispose(); - window.removeEventListener('resize', resizeChart); - }; - }, [theme]); - - useEffect(() => { - // Resize chart when shown - let chart: ECharts | undefined; - if (chartRef.current !== null) { - chart = init(chartRef.current, theme); - } - chart?.resize(); - }, [option]); // Whenever theme changes we need to add option and setting due to it being deleted in cleanup function - - useEffect(() => { - // Update chart - if (chartRef.current !== null) { - const chart = getInstanceByDom(chartRef.current); - if (chart) - chart.setOption(option, settings); - } - }, [option, settings, theme]); // Whenever theme changes we need to add option and setting due to it being deleted in cleanup function - - useEffect(() => { - // Update chart - if (chartRef.current !== null) { - const chart = getInstanceByDom(chartRef.current); - if (chart) { - if (loading === true) - chart.showLoading(); - else - chart.hideLoading(); - } - } - }, [loading, theme]); - return
; -} \ No newline at end of file diff --git a/packages/vscode-messenger-devtools/webview-ui/src/components/view-header.tsx b/packages/vscode-messenger-devtools/webview-ui/src/components/view-header.tsx index 2d44629..58d40b8 100644 --- a/packages/vscode-messenger-devtools/webview-ui/src/components/view-header.tsx +++ b/packages/vscode-messenger-devtools/webview-ui/src/components/view-header.tsx @@ -1,52 +1,106 @@ -import { VSCodeButton, VSCodeDropdown, VSCodeOption } from '@vscode/webview-ui-toolkit/react'; -import type { MouseEventHandler } from 'react'; -import type { ExtensionData } from '../devtools-view'; +import type { CodiconName } from 'baukasten-ui'; +import { Select, Tooltip } from 'baukasten-ui'; + +import { Icon, IconButton } from 'baukasten-ui/core'; +import React, { useEffect, type CSSProperties, type MouseEventHandler } from 'react'; +import { HOST_EXTENSION } from 'vscode-messenger-common'; +import type { Messenger } from 'vscode-messenger-webview'; +import { ExtensionListRequest, MESSENGER_EXTENSION_ID, type ExtensionData } from '../model/messenger-types'; +import { useDevtoolsStore } from '../utilities/data-store'; export function ViewHeader(props: { - state: { selectedExtension: string | undefined; extensions: ExtensionData[]; }, + messenger: Messenger + state: { selectedExtension: string | undefined; extensions: ExtensionData[] | undefined; }, onExtensionSelected: (extId: string) => void, - onRefreshClicked: MouseEventHandler | undefined, onClearClicked: (extId: string | undefined) => void, + onRefreshClicked: MouseEventHandler | undefined, onToggleCharts: MouseEventHandler | undefined, - onToggleDiagram: () => void, onExportJSON?: () => void, onExportCSV?: () => void, -}): JSX.Element { +}): React.JSX.Element { + + const selectedExtensionId: string | undefined = props.state.selectedExtension ?? useDevtoolsStore((state) => state.selectedExtension);; + + const loadedExtensions: ExtensionData[] = props.state.extensions ?? useDevtoolsStore((state) => state.getExtensions()); + const updateExtensionData = useDevtoolsStore((state) => state.updateExtensionData); + const updateEvents = useDevtoolsStore((state) => state.updateEvents); + const updateSelectedExtension = useDevtoolsStore((state) => state.updateSelectedExtension); + const updateVisualization = useDevtoolsStore((state) => state.updateVisualizationSelect); + + useEffect(() => { + // Initial load of extensions + (async () => { + const extensions = await props?.messenger?.sendRequest(ExtensionListRequest, HOST_EXTENSION, true); + if (!extensions) { + return; + } + updateExtensionData(extensions); + if (selectedExtensionId === '' && extensions.length > 0) { + // set first not vscode-messenger entry as selected extension + let extensionToPreset = extensions[0]; + if (extensions.length > 1) { + extensionToPreset = extensions.find(ex => ex.id !== MESSENGER_EXTENSION_ID) ?? extensionToPreset; + } + if (extensionToPreset) { + updateSelectedExtension(extensionToPreset.id); + } + } + })(); + }, []); + return ( -