diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 11a125a..c816d4c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -2,8 +2,7 @@ name: Publish Package to npmjs on: release: - types: [created] - pull_request: + types: [published] jobs: publish: @@ -27,11 +26,7 @@ jobs: - name: Build package run: npm run build - # This step is a placeholder for publishing to npm. - # The project structure and Node configuration will need to be adjusted - # before this can be enabled and work as intended. - name: Publish to npm - if: github.event_name == 'release' run: npm publish env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/README.md b/README.md index 9f3fc3f..09789e5 100644 --- a/README.md +++ b/README.md @@ -1,106 +1,54 @@ # Trino Query UI -This Trino Query UI is a new UI component that can be integrated into Trino and run directly from the Trino installation at the `/query/` path. For testing, it can also be run separately and can proxy to a Trino running locally or elsewhere. +A reusable React component for executing queries against Trino. It can be embedded into any react application and configured to proxy requests to a local or remote Trino cluster. + +> [!WARNING] +> This package is under heavy development and is not yet recommended for production workloads. Treat the current release as an early-stage demo; production-ready builds and documentation will follow soon. ![Trino Query UI Demo](demos.gif "Trino Query UI Demo") Implementation details: -* React Typescript project with Vite -* Using Node.js v20+ -* Monaco editor + ANTLR parser using Trino language - -## Building and Shipping in Trino - -The Query UI builds just like the existing UI in Trino. -1. First you build the TypeScript into Javascript and CSS -2. Then copy the distributable path into Trino. -3. Then modify Trino to respond to the query ui path. +* React TypeScript project with Vite +* Uses Node.js v20+ +* Monaco editor + ANTLR parser using the Trino language -### Building for Integration +## Installation ``` -cd precise -npm run build +npm install trino-query-ui ``` -### Copying into Trino - -mkdir -p $TRINO_HOME/core/trino-main/src/main/resources/query_ui_webapp/ -cp -r dist/* $TRINO_HOME/core/trino-main/src/main/resources/query_ui_webapp/ - -### Modifying Trino to Respond to /query/ - -Modify `$TRINO_HOME/core/trino-main/src/main/java/io/trino/server/ui/WebUiStaticResource.java`: - -Add `/query/` path. Note any path can be used: - -```java - @GET - @Path("/query") - public Response getQuery(@BeanParam ExternalUriInfo externalUriInfo) - { - return Response.seeOther(externalUriInfo.absolutePath("/query/")).build(); - } - - // asset files are always visible - @ResourceSecurity(PUBLIC) - @GET - @Path("/query/assets/{path: .*}") - public Response getQueryAssetsFile(@PathParam("path") String path) - throws IOException - { - return getQueryFile("assets/" + path); - } - - @ResourceSecurity(PUBLIC) - @GET - @Path("/query/{path: .*}") - public Response getQueryFile(@PathParam("path") String path) - throws IOException - { - if (path.isEmpty()) { - path = "index.html"; - } - - String fullPath = "/query_ui_webapp/" + path; - if (!isCanonical(fullPath)) { - return Response.status(NOT_FOUND).build(); - } - - URL resource = getClass().getResource(fullPath); - if (resource == null) { - return Response.status(NOT_FOUND).build(); - } - - return Response.ok(resource.openStream()).build(); - } - - private static boolean isCanonical(String fullPath) - { - try { - return new URI(fullPath).normalize().getPath().equals(fullPath); - } - catch (URISyntaxException e) { - return false; - } - } +## Quick Start + +```tsx +import { QueryEditor } from 'trino-query-ui' +import 'trino-query-ui/dist/index.css' + +function MyTrinoApp() { + return +} + +export default MyTrinoApp ``` + ## Development -### Setup the Coding Environment +### Build and Run -Tested on Ubuntu and Windows. +1. Install Node.js (v20 or newer) from +2. Install the dependencies and run the dev server: +``` +cd precise +npm install +npm run dev +``` -1. Install node.js at least v20 -2. Create an NPM enviroment using Vite: `npm create vite@latest`, pick *React*, then *Typescript* -3. In the precise folder, install monaco `npm install @monaco-editor/react` -4. Install Typescript Runtime for ANTLR4 `npm install antlr4ng` and the cli `npm install --save-dev antlr4ng-cli` - because seems abandoned? +The local URL will be displayed, and you can open it in your browser. -### Setup Proxying to Local Trino Instance +### Set Up Proxying to a Local Trino Instance -To run outside of Trino, update the contents of the `vite.config.ts` with the following so that queries can be properly proxied over to Trino's query endpoint running on `http://localhost:8080` or any other proxy path required. +Update `vite.config.ts` with the following so that queries can be properly proxied to Trino's query endpoint running on `http://localhost:8080` (or any other path you require). ```tsx import { defineConfig } from 'vite' @@ -119,26 +67,15 @@ export default defineConfig({ }, }, }, + ... }); ``` -### Build and Run - -To run, start: - -```shell - cd precise - npm install - npm run dev -``` - -The local URL will be be displayed which you can open in your browser. - ### Building the Parser -To build parser: `npm run antlr4ng`, as configured in **package.json** +Run `npm run antlr4ng` to build the parser, as configured in **package.json**. -### Linting and code formatting +### Linting and Code Formatting To check code quality and formatting: @@ -146,37 +83,37 @@ To check code quality and formatting: npm run check ``` -This command runs both eslint and prettier, as defined in **package.json** +This command runs both ESLint and Prettier, as defined in **package.json**. ## Philosophy -This UI's purpose is to provide an environment where once the cluster is stood up, executing queries and exploring data sets can be done right away. The idended use cases are: +This UI's purpose is to provide an environment where, once the cluster is up, you can immediately execute queries and explore data sets. The intended use cases are: * Initial proof-of-concept queries. * Exploration of data sets. * Performance analysis. -* Adhoc query execution. +* Ad hoc query execution. * Quickly enabling a data engineering team to start work before other integrations are in place. * Early demos. -The approach taken: -1. Direct integration into Trino UI - - No need for additional authentication hop (although it could be added in the future) - - Auth as the user executing the query if using Oauth2 +The approach: +1. Direct integration into the Trino UI + - No need for an additional authentication hop (although it could be added in the future) + - Authenticates as the user executing the query when using OAuth2 - Trino does the heavy lifting -2. Don't need to think, just write a query - - Autocomplete must be aware of not just Trino language but tables and columns - - Syntax highlighting, validation - - Comprehensive catalog explorer -3. No black box query execution - - Show progress and details of execution: people ask "why is my query slow" but mostly this is because they are only shown a spinner for 10 minutes. - - Link to Trino query UI to drill into query performance - - Show stages and split counts like Trino console client -4. Easy to navigate +2. Remove friction so you can simply write a query + - Autocomplete understands the Trino language, tables, and columns + - Provides syntax highlighting and validation + - Offers a comprehensive catalog explorer +3. Avoid black-box query execution + - Show progress and execution details. People ask "why is my query slow?" mostly because they only see a spinner for minutes. + - Link to the Trino Query UI to drill into query performance + - Show stages and split counts like the Trino console client +4. Keep the experience easy to navigate ### Gaps and Future Direction -* The ability to save queries and use source control requires either back end capabilities in the Trino service or can utilize Trino to write queries as tables. +* Saving queries and using source control require either backend capabilities in the Trino service or leveraging Trino to write queries as tables. * No autocomplete for the Trino function list. -* Basic graphing capabilities - looking at a table is not enough even for inspecting data sets. -* No LLM copilot integration yet, this is done badly in many query UIs and if done well could make query crafting very fast, and solve other issues like translation from other query languages. -* Parameters and string replace: this is partly implemented in `SubstitutionEditor` and should support both SQL parameters and string replacement. \ No newline at end of file +* Basic graphing capabilities are still missing—looking at a table alone is not enough even for inspecting data sets. +* No LLM copilot integration yet. Many query UIs implement this poorly, but, done well, it could make query crafting fast and help translate from other query languages. +* Parameters and string replacement are only partly implemented in `SubstitutionEditor` and should support both SQL parameters and string replacement. diff --git a/precise/.eslintignore b/precise/.eslintignore deleted file mode 100644 index 4150114..0000000 --- a/precise/.eslintignore +++ /dev/null @@ -1 +0,0 @@ -src/generated/** diff --git a/precise/eslint.config.js b/precise/eslint.config.js new file mode 100644 index 0000000..7355361 --- /dev/null +++ b/precise/eslint.config.js @@ -0,0 +1,77 @@ +import js from '@eslint/js' +import globals from 'globals'; +import tsParser from '@typescript-eslint/parser' +import tsPlugin from '@typescript-eslint/eslint-plugin' +import reactHooksPlugin from 'eslint-plugin-react-hooks'; +import reactRefreshPlugin from 'eslint-plugin-react-refresh'; + +export default [ + js.configs.recommended, + { + files: ['**/*.ts', '**/*.tsx'], + languageOptions: { + parser: tsParser, + ecmaVersion: 'latest', + sourceType: 'module', + globals: { + ...globals.browser, + process: 'readonly', + React: 'readonly', + }, + }, + plugins: { + '@typescript-eslint': tsPlugin, + }, + rules: { + ...tsPlugin.configs.recommended.rules, + '@typescript-eslint/no-unused-expressions': [ + 'error', + { + allowShortCircuit: true, + allowTernary: true, + }, + ], + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-unused-vars': 'off', + }, + }, + { + files: ['**/*.js', '**/*.jsx', '**/*.ts', '**/*.tsx'], + plugins: { + 'react-hooks': reactHooksPlugin, + }, + rules: { + ...reactHooksPlugin.configs.recommended.rules, + }, + }, + { + files: ['**/*.{js,jsx,ts,tsx}'], // Match all JS/TS files + plugins: { + 'react-refresh': reactRefreshPlugin, + }, + rules: { + 'react-refresh/only-export-components': [ + 'warn', + { allowConstantExport: true }, + ], + // Fix and enable separately + // 'eol-last': ['warn', 'always'], + // 'no-multiple-empty-lines': ['warn', { max: 1, maxEOF: 0 }], + }, + }, + { + files: ['src/utils/ProgressBar.tsx'], + rules: { + '@typescript-eslint/no-empty-object-type': 'off', + }, + }, + { + files: ['src/generated/**/*.ts'], + linterOptions: { + reportUnusedDisableDirectives: false, + }, + }, + { + ignores: ['dist', 'src/generated/**', '.eslintrc.cjs'], + }, +]; diff --git a/precise/index.html b/precise/index.html index 8963d85..9f6fd79 100644 --- a/precise/index.html +++ b/precise/index.html @@ -4,7 +4,7 @@ - Trino Query Editor + Trino Query Editor - Example app
diff --git a/precise/package-lock.json b/precise/package-lock.json index e567576..fea73f1 100644 --- a/precise/package-lock.json +++ b/precise/package-lock.json @@ -1,83 +1,66 @@ { - "name": "precise", - "version": "0.0.0", + "name": "trino-query-ui", + "version": "0.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "precise", - "version": "0.0.0", - "dependencies": { - "@monaco-editor/react": "^4.6.0", - "antlr4-c3": "^3.4.1", - "antlr4ng": "^3.0.4", - "lucide-react": "^0.460.0", - "precise": "file:", - "prettier": "^3.5.3", - "react": "^18.2.0", + "name": "trino-query-ui", + "version": "0.0.1", + "license": "Apache-2.0", + "dependencies": { + "@emotion/react": "^11.14.0", + "@emotion/styled": "^11.14.1", + "@monaco-editor/react": "^4.7.0", + "@mui/icons-material": "^7.3.2", + "@mui/material": "^7.3.2", + "@mui/x-data-grid": "^8.14.0", + "@mui/x-tree-view": "^8.13.1", + "antlr4-c3": "^3.4.4", + "antlr4ng": "^3.0.16", + "lucide-react": "^0.544.0", + "prettier": "^3.6.2", "react-dnd": "^16.0.1", "react-dnd-html5-backend": "^16.0.1", - "react-dom": "^18.2.0", - "sql-formatter": "^15.5.2", + "sql-formatter": "^15.6.9", "uuidv4": "^6.2.13" }, "devDependencies": { - "@types/http-proxy-middleware": "^1.0.0", - "@types/react": "^18.2.66", - "@types/react-dom": "^18.2.22", - "@typescript-eslint/eslint-plugin": "^7.2.0", - "@typescript-eslint/parser": "^7.2.0", - "@vitejs/plugin-react": "^4.2.1", + "@types/react": "^19.1.13", + "@types/react-dom": "^19.1.9", + "@typescript-eslint/eslint-plugin": "^8.44.1", + "@typescript-eslint/parser": "^8.44.1", + "@vitejs/plugin-react": "^5.0.3", "antlr4ng-cli": "^2.0.0", - "eslint": "^8.57.0", - "eslint-plugin-react-hooks": "^4.6.0", - "eslint-plugin-react-refresh": "^0.4.6", - "typescript": "^5.2.2", - "vite": "^6.2.4" - } - }, - "node_modules/@aashutoshrathi/word-wrap": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", - "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" + "eslint": "^9.36.0", + "eslint-plugin-react-hooks": "^5.2.0", + "eslint-plugin-react-refresh": "^0.4.21", + "typescript": "^5.9.2", + "vite": "^7.1.7" }, - "engines": { - "node": ">=6.0.0" + "peerDependencies": { + "react": "^19.1.1", + "react-dom": "^19.1.1" } }, "node_modules/@babel/code-frame": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", - "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", - "dev": true, + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.25.9", + "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" + "picocolors": "^1.1.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { - "version": "7.26.8", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz", - "integrity": "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.4.tgz", + "integrity": "sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw==", "dev": true, "license": "MIT", "engines": { @@ -85,22 +68,22 @@ } }, "node_modules/@babel/core": { - "version": "7.26.10", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz", - "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.26.10", - "@babel/helper-compilation-targets": "^7.26.5", - "@babel/helper-module-transforms": "^7.26.0", - "@babel/helpers": "^7.26.10", - "@babel/parser": "^7.26.10", - "@babel/template": "^7.26.9", - "@babel/traverse": "^7.26.10", - "@babel/types": "^7.26.10", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.4.tgz", + "integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.3", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.28.3", + "@babel/helpers": "^7.28.4", + "@babel/parser": "^7.28.4", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.4", + "@babel/types": "^7.28.4", + "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -126,16 +109,15 @@ } }, "node_modules/@babel/generator": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.0.tgz", - "integrity": "sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==", - "dev": true, + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz", + "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==", "license": "MIT", "dependencies": { - "@babel/parser": "^7.27.0", - "@babel/types": "^7.27.0", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", + "@babel/parser": "^7.28.3", + "@babel/types": "^7.28.2", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" }, "engines": { @@ -143,14 +125,14 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.0.tgz", - "integrity": "sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.26.8", - "@babel/helper-validator-option": "^7.25.9", + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" @@ -169,30 +151,38 @@ "semver": "bin/semver.js" } }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-module-imports": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", - "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", - "dev": true, + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", "license": "MIT", "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", - "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", + "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9", - "@babel/traverse": "^7.25.9" + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.28.3" }, "engines": { "node": ">=6.9.0" @@ -202,9 +192,9 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", - "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", + "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", "dev": true, "license": "MIT", "engines": { @@ -212,29 +202,27 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", - "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", - "dev": true, + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", - "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", - "dev": true, + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", - "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", "dev": true, "license": "MIT", "engines": { @@ -242,27 +230,26 @@ } }, "node_modules/@babel/helpers": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.0.tgz", - "integrity": "sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", + "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.27.0", - "@babel/types": "^7.27.0" + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.4" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz", - "integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==", - "dev": true, + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.4.tgz", + "integrity": "sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==", "license": "MIT", "dependencies": { - "@babel/types": "^7.27.0" + "@babel/types": "^7.28.4" }, "bin": { "parser": "bin/babel-parser.js" @@ -272,13 +259,13 @@ } }, "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.25.9.tgz", - "integrity": "sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", + "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -288,13 +275,13 @@ } }, "node_modules/@babel/plugin-transform-react-jsx-source": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.25.9.tgz", - "integrity": "sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", + "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -304,69 +291,237 @@ } }, "node_modules/@babel/runtime": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.0.tgz", - "integrity": "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", + "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", "license": "MIT", - "dependencies": { - "regenerator-runtime": "^0.14.0" - }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/template": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.0.tgz", - "integrity": "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==", - "dev": true, + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/parser": "^7.27.0", - "@babel/types": "^7.27.0" + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.0.tgz", - "integrity": "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==", - "dev": true, + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.4.tgz", + "integrity": "sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==", "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.27.0", - "@babel/parser": "^7.27.0", - "@babel/template": "^7.27.0", - "@babel/types": "^7.27.0", - "debug": "^4.3.1", - "globals": "^11.1.0" + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.3", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.4", + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.4", + "debug": "^4.3.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/types": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz", - "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==", - "dev": true, + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.4.tgz", + "integrity": "sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==", "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9" + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, + "node_modules/@base-ui-components/utils": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@base-ui-components/utils/-/utils-0.1.1.tgz", + "integrity": "sha512-HWXZA8upEKgrdL1rQqxWu1H+2tB2cXzY2jCxvgnpUv3eoWN2jldhXxMZnXIjZF7jahGxSWXfSIM/qskiTWFFxA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.3", + "@floating-ui/utils": "^0.2.10", + "reselect": "^5.1.1", + "use-sync-external-store": "^1.5.0" + }, + "peerDependencies": { + "@types/react": "^17 || ^18 || ^19", + "react": "^17 || ^18 || ^19", + "react-dom": "^17 || ^18 || ^19" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/babel-plugin": { + "version": "11.13.5", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz", + "integrity": "sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/serialize": "^1.3.3", + "babel-plugin-macros": "^3.1.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/babel-plugin/node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "license": "MIT" + }, + "node_modules/@emotion/cache": { + "version": "11.14.0", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.14.0.tgz", + "integrity": "sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==", + "license": "MIT", + "dependencies": { + "@emotion/memoize": "^0.9.0", + "@emotion/sheet": "^1.4.0", + "@emotion/utils": "^1.4.2", + "@emotion/weak-memoize": "^0.4.0", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/hash": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz", + "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==", + "license": "MIT" + }, + "node_modules/@emotion/is-prop-valid": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.4.0.tgz", + "integrity": "sha512-QgD4fyscGcbbKwJmqNvUMSE02OsHUa+lAWKdEUIJKgqe5IwRSKd7+KhibEWdaKwgjLj0DRSHA9biAIqGBk05lw==", + "license": "MIT", + "dependencies": { + "@emotion/memoize": "^0.9.0" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", + "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==", + "license": "MIT" + }, + "node_modules/@emotion/react": { + "version": "11.14.0", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz", + "integrity": "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.13.5", + "@emotion/cache": "^11.14.0", + "@emotion/serialize": "^1.3.3", + "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0", + "@emotion/utils": "^1.4.2", + "@emotion/weak-memoize": "^0.4.0", + "hoist-non-react-statics": "^3.3.1" + }, + "peerDependencies": { + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/serialize": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.3.tgz", + "integrity": "sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==", + "license": "MIT", + "dependencies": { + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/unitless": "^0.10.0", + "@emotion/utils": "^1.4.2", + "csstype": "^3.0.2" + } + }, + "node_modules/@emotion/sheet": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz", + "integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==", + "license": "MIT" + }, + "node_modules/@emotion/styled": { + "version": "11.14.1", + "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.1.tgz", + "integrity": "sha512-qEEJt42DuToa3gurlH4Qqc1kVpNq8wO8cJtDzU46TjlzWjDlsVyevtYCRijVq3SrHsROS+gVQ8Fnea108GnKzw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.13.5", + "@emotion/is-prop-valid": "^1.3.0", + "@emotion/serialize": "^1.3.3", + "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0", + "@emotion/utils": "^1.4.2" + }, + "peerDependencies": { + "@emotion/react": "^11.0.0-rc.0", + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/unitless": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.10.0.tgz", + "integrity": "sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==", + "license": "MIT" + }, + "node_modules/@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.2.0.tgz", + "integrity": "sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==", + "license": "MIT", + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@emotion/utils": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.2.tgz", + "integrity": "sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==", + "license": "MIT" + }, + "node_modules/@emotion/weak-memoize": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz", + "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==", + "license": "MIT" + }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.2.tgz", - "integrity": "sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.10.tgz", + "integrity": "sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw==", "cpu": [ "ppc64" ], @@ -381,9 +536,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.2.tgz", - "integrity": "sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.10.tgz", + "integrity": "sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w==", "cpu": [ "arm" ], @@ -398,9 +553,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.2.tgz", - "integrity": "sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.10.tgz", + "integrity": "sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg==", "cpu": [ "arm64" ], @@ -415,9 +570,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.2.tgz", - "integrity": "sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.10.tgz", + "integrity": "sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg==", "cpu": [ "x64" ], @@ -432,9 +587,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.2.tgz", - "integrity": "sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.10.tgz", + "integrity": "sha512-JC74bdXcQEpW9KkV326WpZZjLguSZ3DfS8wrrvPMHgQOIEIG/sPXEN/V8IssoJhbefLRcRqw6RQH2NnpdprtMA==", "cpu": [ "arm64" ], @@ -449,9 +604,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.2.tgz", - "integrity": "sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.10.tgz", + "integrity": "sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg==", "cpu": [ "x64" ], @@ -466,9 +621,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.2.tgz", - "integrity": "sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.10.tgz", + "integrity": "sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg==", "cpu": [ "arm64" ], @@ -483,9 +638,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.2.tgz", - "integrity": "sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.10.tgz", + "integrity": "sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA==", "cpu": [ "x64" ], @@ -500,9 +655,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.2.tgz", - "integrity": "sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.10.tgz", + "integrity": "sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg==", "cpu": [ "arm" ], @@ -517,9 +672,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.2.tgz", - "integrity": "sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.10.tgz", + "integrity": "sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ==", "cpu": [ "arm64" ], @@ -534,9 +689,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.2.tgz", - "integrity": "sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.10.tgz", + "integrity": "sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ==", "cpu": [ "ia32" ], @@ -551,9 +706,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.2.tgz", - "integrity": "sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.10.tgz", + "integrity": "sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg==", "cpu": [ "loong64" ], @@ -568,9 +723,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.2.tgz", - "integrity": "sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.10.tgz", + "integrity": "sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA==", "cpu": [ "mips64el" ], @@ -585,9 +740,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.2.tgz", - "integrity": "sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.10.tgz", + "integrity": "sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA==", "cpu": [ "ppc64" ], @@ -602,9 +757,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.2.tgz", - "integrity": "sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.10.tgz", + "integrity": "sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA==", "cpu": [ "riscv64" ], @@ -619,9 +774,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.2.tgz", - "integrity": "sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.10.tgz", + "integrity": "sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew==", "cpu": [ "s390x" ], @@ -636,9 +791,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.2.tgz", - "integrity": "sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.10.tgz", + "integrity": "sha512-QSX81KhFoZGwenVyPoberggdW1nrQZSvfVDAIUXr3WqLRZGZqWk/P4T8p2SP+de2Sr5HPcvjhcJzEiulKgnxtA==", "cpu": [ "x64" ], @@ -653,9 +808,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.2.tgz", - "integrity": "sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.10.tgz", + "integrity": "sha512-AKQM3gfYfSW8XRk8DdMCzaLUFB15dTrZfnX8WXQoOUpUBQ+NaAFCP1kPS/ykbbGYz7rxn0WS48/81l9hFl3u4A==", "cpu": [ "arm64" ], @@ -670,9 +825,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.2.tgz", - "integrity": "sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.10.tgz", + "integrity": "sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig==", "cpu": [ "x64" ], @@ -687,9 +842,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.2.tgz", - "integrity": "sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.10.tgz", + "integrity": "sha512-5Se0VM9Wtq797YFn+dLimf2Zx6McttsH2olUBsDml+lm0GOCRVebRWUvDtkY4BWYv/3NgzS8b/UM3jQNh5hYyw==", "cpu": [ "arm64" ], @@ -704,9 +859,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.2.tgz", - "integrity": "sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.10.tgz", + "integrity": "sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw==", "cpu": [ "x64" ], @@ -720,10 +875,27 @@ "node": ">=18" } }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.10.tgz", + "integrity": "sha512-AVTSBhTX8Y/Fz6OmIVBip9tJzZEUcY8WLh7I59+upa5/GPhh2/aM6bvOMQySspnCCHvFi79kMtdJS1w0DXAeag==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@esbuild/sunos-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.2.tgz", - "integrity": "sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.10.tgz", + "integrity": "sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ==", "cpu": [ "x64" ], @@ -738,9 +910,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.2.tgz", - "integrity": "sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.10.tgz", + "integrity": "sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw==", "cpu": [ "arm64" ], @@ -755,9 +927,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.2.tgz", - "integrity": "sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.10.tgz", + "integrity": "sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw==", "cpu": [ "ia32" ], @@ -772,9 +944,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.2.tgz", - "integrity": "sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.10.tgz", + "integrity": "sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw==", "cpu": [ "x64" ], @@ -789,39 +961,107 @@ } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", + "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", "dev": true, + "license": "MIT", "dependencies": { - "eslint-visitor-keys": "^3.3.0" + "eslint-visitor-keys": "^3.4.3" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, + "funding": { + "url": "https://opencollective.com/eslint" + }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "node_modules/@eslint-community/regexpp": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", - "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", "dev": true, + "license": "MIT", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, + "node_modules/@eslint/config-array": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", + "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.6", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "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==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.1.tgz", + "integrity": "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.2.tgz", + "integrity": "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", + "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", "dev": true, + "license": "MIT", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", + "espree": "^10.0.1", + "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", @@ -829,35 +1069,31 @@ "strip-json-comments": "^3.1.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "node_modules/@eslint/eslintrc/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, + "license": "MIT", "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 4" } }, "node_modules/@eslint/eslintrc/node_modules/minimatch": { @@ -865,6 +1101,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -873,48 +1110,70 @@ } }, "node_modules/@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "version": "9.36.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.36.0.tgz", + "integrity": "sha512-uhCbYtYynH30iZErszX78U+nR3pJU3RHGQ57NXy5QupD4SBVwDeU8TNBy+MjMngc1UyIW9noKqsRqfjQTBU2dw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", + "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", "dev": true, + "license": "Apache-2.0", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "node_modules/@eslint/plugin-kit": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz", + "integrity": "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" + "@eslint/core": "^0.15.2", + "levn": "^0.4.1" }, "engines": { - "node": ">=10.10.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/@floating-ui/utils": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz", + "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==", + "license": "MIT" + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" } }, - "node_modules/@humanwhocodes/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==", + "node_modules/@humanfs/node": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", + "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "brace-expansion": "^1.1.7" + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.4.0" }, "engines": { - "node": "*" + "node": ">=18.18.0" } }, "node_modules/@humanwhocodes/module-importer": { @@ -922,6 +1181,7 @@ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=12.22" }, @@ -930,59 +1190,60 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "dev": true + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", - "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" } }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "dev": true, + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -990,34 +1251,444 @@ } }, "node_modules/@monaco-editor/loader": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@monaco-editor/loader/-/loader-1.4.0.tgz", - "integrity": "sha512-00ioBig0x642hytVspPl7DbQyaSWRaolYie/UFNjoTdvoKPzo6xrXLhTk9ixgIKcLH5b5vDOjVNiGyY+uDCUlg==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@monaco-editor/loader/-/loader-1.5.0.tgz", + "integrity": "sha512-hKoGSM+7aAc7eRTRjpqAZucPmoNOC4UUbknb/VNoTkEIkCPhqV8LfbsgM1webRM7S/z21eHEx9Fkwx8Z/C/+Xw==", + "license": "MIT", "dependencies": { "state-local": "^1.0.6" - }, - "peerDependencies": { - "monaco-editor": ">= 0.21.0 < 1" } }, "node_modules/@monaco-editor/react": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/@monaco-editor/react/-/react-4.6.0.tgz", - "integrity": "sha512-RFkU9/i7cN2bsq/iTkurMWOEErmYcY6JiQI3Jn+WeR/FGISH8JbHERjpS9oRuSOPvDMJI0Z8nJeKkbOs9sBYQw==", + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@monaco-editor/react/-/react-4.7.0.tgz", + "integrity": "sha512-cyzXQCtO47ydzxpQtCGSQGOC8Gk3ZUeBXFAxD+CWXYFo5OqZyZUonFl0DwUlTyAfRHntBfw2p3w4s9R6oe1eCA==", + "license": "MIT", "dependencies": { - "@monaco-editor/loader": "^1.4.0" + "@monaco-editor/loader": "^1.5.0" }, "peerDependencies": { "monaco-editor": ">= 0.25.0 < 1", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, + "node_modules/@mui/core-downloads-tracker": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-7.3.2.tgz", + "integrity": "sha512-AOyfHjyDKVPGJJFtxOlept3EYEdLoar/RvssBTWVAvDJGIE676dLi2oT/Kx+FoVXFoA/JdV7DEMq/BVWV3KHRw==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + } + }, + "node_modules/@mui/icons-material": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-7.3.2.tgz", + "integrity": "sha512-TZWazBjWXBjR6iGcNkbKklnwodcwj0SrChCNHc9BhD9rBgET22J1eFhHsEmvSvru9+opDy3umqAimQjokhfJlQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.3" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@mui/material": "^7.3.2", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/material": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-7.3.2.tgz", + "integrity": "sha512-qXvbnawQhqUVfH1LMgMaiytP+ZpGoYhnGl7yYq2x57GYzcFL/iPzSZ3L30tlbwEjSVKNYcbiKO8tANR1tadjUg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.3", + "@mui/core-downloads-tracker": "^7.3.2", + "@mui/system": "^7.3.2", + "@mui/types": "^7.4.6", + "@mui/utils": "^7.3.2", + "@popperjs/core": "^2.11.8", + "@types/react-transition-group": "^4.4.12", + "clsx": "^2.1.1", + "csstype": "^3.1.3", + "prop-types": "^15.8.1", + "react-is": "^19.1.1", + "react-transition-group": "^4.4.5" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@mui/material-pigment-css": "^7.3.2", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@mui/material-pigment-css": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/material/node_modules/react-is": { + "version": "19.1.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.1.1.tgz", + "integrity": "sha512-tr41fA15Vn8p4X9ntI+yCyeGSf1TlYaY5vlTZfQmeLBrFo3psOPX6HhTDnFNL9uj3EhP0KAQ80cugCl4b4BERA==", + "license": "MIT" + }, + "node_modules/@mui/private-theming": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-7.3.2.tgz", + "integrity": "sha512-ha7mFoOyZGJr75xeiO9lugS3joRROjc8tG1u4P50dH0KR7bwhHznVMcYg7MouochUy0OxooJm/OOSpJ7gKcMvg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.3", + "@mui/utils": "^7.3.2", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/styled-engine": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-7.3.2.tgz", + "integrity": "sha512-PkJzW+mTaek4e0nPYZ6qLnW5RGa0KN+eRTf5FA2nc7cFZTeM+qebmGibaTLrgQBy3UpcpemaqfzToBNkzuxqew==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.3", + "@emotion/cache": "^11.14.0", + "@emotion/serialize": "^1.3.3", + "@emotion/sheet": "^1.4.0", + "csstype": "^3.1.3", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.4.1", + "@emotion/styled": "^11.3.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + } + } + }, + "node_modules/@mui/system": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-7.3.2.tgz", + "integrity": "sha512-9d8JEvZW+H6cVkaZ+FK56R53vkJe3HsTpcjMUtH8v1xK6Y1TjzHdZ7Jck02mGXJsE6MQGWVs3ogRHTQmS9Q/rA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.3", + "@mui/private-theming": "^7.3.2", + "@mui/styled-engine": "^7.3.2", + "@mui/types": "^7.4.6", + "@mui/utils": "^7.3.2", + "clsx": "^2.1.1", + "csstype": "^3.1.3", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/types": { + "version": "7.4.7", + "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.4.7.tgz", + "integrity": "sha512-8vVje9rdEr1rY8oIkYgP+Su5Kwl6ik7O3jQ0wl78JGSmiZhRHV+vkjooGdKD8pbtZbutXFVTWQYshu2b3sG9zw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.4" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/utils": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-7.3.3.tgz", + "integrity": "sha512-kwNAUh7bLZ7mRz9JZ+6qfRnnxbE4Zuc+RzXnhSpRSxjTlSTj7b4JxRLXpG+MVtPVtqks5k/XC8No1Vs3x4Z2gg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.4", + "@mui/types": "^7.4.7", + "@types/prop-types": "^15.7.15", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "react-is": "^19.1.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/utils/node_modules/react-is": { + "version": "19.1.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.1.1.tgz", + "integrity": "sha512-tr41fA15Vn8p4X9ntI+yCyeGSf1TlYaY5vlTZfQmeLBrFo3psOPX6HhTDnFNL9uj3EhP0KAQ80cugCl4b4BERA==", + "license": "MIT" + }, + "node_modules/@mui/x-data-grid": { + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@mui/x-data-grid/-/x-data-grid-8.14.0.tgz", + "integrity": "sha512-bzUpD83Wx4mawkgquDQUUbLLnpF+JP7Pe7YQx1ixS6W/AlUwXAVagPTOijwchHvlx0Ky11dJvOQAfrnWu6an/Q==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.4", + "@mui/utils": "^7.3.3", + "@mui/x-internals": "8.14.0", + "@mui/x-virtualizer": "0.2.3", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "use-sync-external-store": "^1.6.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.9.0", + "@emotion/styled": "^11.8.1", + "@mui/material": "^5.15.14 || ^6.0.0 || ^7.0.0", + "@mui/system": "^5.15.14 || ^6.0.0 || ^7.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + } + } + }, + "node_modules/@mui/x-data-grid/node_modules/@mui/x-internals": { + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@mui/x-internals/-/x-internals-8.14.0.tgz", + "integrity": "sha512-esYyl61nuuFXiN631TWuPh2tqdoyTdBI/4UXgwH3rytF8jiWvy6prPBPRHEH1nvW3fgw9FoBI48FlOO+yEI8xg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.4", + "@mui/utils": "^7.3.3", + "reselect": "^5.1.1", + "use-sync-external-store": "^1.6.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@mui/x-internals": { + "version": "8.13.1", + "resolved": "https://registry.npmjs.org/@mui/x-internals/-/x-internals-8.13.1.tgz", + "integrity": "sha512-OKQyCJ9uxtMpjBZCOEQGOR5MhgL1f9HjI4qZHuaLxxtDATK5rcBbVjBF67hI8FzXeF1wrcZP2wsjc4AgGpAo9g==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.4", + "@mui/utils": "^7.3.2", + "reselect": "^5.1.1", + "use-sync-external-store": "^1.5.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@mui/x-tree-view": { + "version": "8.13.1", + "resolved": "https://registry.npmjs.org/@mui/x-tree-view/-/x-tree-view-8.13.1.tgz", + "integrity": "sha512-i5GrIMbNZRGEIYpJDC+d8TStANmvQpwIGYbsGTczrM+6x3KCkASahURgSraZVBfAAxJ2sm55rbrG+6jtkbq5HQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.4", + "@base-ui-components/utils": "0.1.1", + "@mui/utils": "^7.3.2", + "@mui/x-internals": "8.13.1", + "@types/react-transition-group": "^4.4.12", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "react-transition-group": "^4.4.5" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.9.0", + "@emotion/styled": "^11.8.1", + "@mui/material": "^5.15.14 || ^6.0.0 || ^7.0.0", + "@mui/system": "^5.15.14 || ^6.0.0 || ^7.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + } + } + }, + "node_modules/@mui/x-virtualizer": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@mui/x-virtualizer/-/x-virtualizer-0.2.3.tgz", + "integrity": "sha512-CZ+VxFmeJaTduAOlSyo5cVek0PV5Y8gm4coyaHEpCvms207J9AoMUKqWIcdwsVGlTH1Y71j35xT/MwHKutZiNw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.4", + "@mui/utils": "^7.3.3", + "@mui/x-internals": "8.14.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@mui/x-virtualizer/node_modules/@mui/x-internals": { + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@mui/x-internals/-/x-internals-8.14.0.tgz", + "integrity": "sha512-esYyl61nuuFXiN631TWuPh2tqdoyTdBI/4UXgwH3rytF8jiWvy6prPBPRHEH1nvW3fgw9FoBI48FlOO+yEI8xg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.4", + "@mui/utils": "^7.3.3", + "reselect": "^5.1.1", + "use-sync-external-store": "^1.6.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -1031,6 +1702,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8" } @@ -1040,6 +1712,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -1048,6 +1721,16 @@ "node": ">= 8" } }, + "node_modules/@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, "node_modules/@react-dnd/asap": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/@react-dnd/asap/-/asap-5.0.2.tgz", @@ -1066,10 +1749,17 @@ "integrity": "sha512-/RVXdLvJxLg4QKvMoM5WlwNR9ViO9z8B/qPcc+C0Sa/teJY7QG7kJ441DwzOjMYEY7GmU4dj5EcGHIkKZiQZCA==", "license": "MIT" }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.35", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.35.tgz", + "integrity": "sha512-slYrCpoxJUqzFDDNlvrOYRazQUNRvWPjXA17dAOISY3rDMxX6k8K4cj2H+hEYMHF81HO3uNd5rHVigAWRM5dSg==", + "dev": true, + "license": "MIT" + }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.38.0.tgz", - "integrity": "sha512-ldomqc4/jDZu/xpYU+aRxo3V4mGCV9HeTgUBANI3oIQMOL+SsxB+S2lxMpkFp5UamSS3XuTMQVbsS24R4J4Qjg==", + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.52.2.tgz", + "integrity": "sha512-o3pcKzJgSGt4d74lSZ+OCnHwkKBeAbFDmbEm5gg70eA8VkyCuC/zV9TwBnmw6VjDlRdF4Pshfb+WE9E6XY1PoQ==", "cpu": [ "arm" ], @@ -1081,9 +1771,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.38.0.tgz", - "integrity": "sha512-VUsgcy4GhhT7rokwzYQP+aV9XnSLkkhlEJ0St8pbasuWO/vwphhZQxYEKUP3ayeCYLhk6gEtacRpYP/cj3GjyQ==", + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.52.2.tgz", + "integrity": "sha512-cqFSWO5tX2vhC9hJTK8WAiPIm4Q8q/cU8j2HQA0L3E1uXvBYbOZMhE2oFL8n2pKB5sOCHY6bBuHaRwG7TkfJyw==", "cpu": [ "arm64" ], @@ -1095,9 +1785,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.38.0.tgz", - "integrity": "sha512-buA17AYXlW9Rn091sWMq1xGUvWQFOH4N1rqUxGJtEQzhChxWjldGCCup7r/wUnaI6Au8sKXpoh0xg58a7cgcpg==", + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.52.2.tgz", + "integrity": "sha512-vngduywkkv8Fkh3wIZf5nFPXzWsNsVu1kvtLETWxTFf/5opZmflgVSeLgdHR56RQh71xhPhWoOkEBvbehwTlVA==", "cpu": [ "arm64" ], @@ -1109,9 +1799,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.38.0.tgz", - "integrity": "sha512-Mgcmc78AjunP1SKXl624vVBOF2bzwNWFPMP4fpOu05vS0amnLcX8gHIge7q/lDAHy3T2HeR0TqrriZDQS2Woeg==", + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.52.2.tgz", + "integrity": "sha512-h11KikYrUCYTrDj6h939hhMNlqU2fo/X4NB0OZcys3fya49o1hmFaczAiJWVAFgrM1NCP6RrO7lQKeVYSKBPSQ==", "cpu": [ "x64" ], @@ -1123,9 +1813,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.38.0.tgz", - "integrity": "sha512-zzJACgjLbQTsscxWqvrEQAEh28hqhebpRz5q/uUd1T7VTwUNZ4VIXQt5hE7ncs0GrF+s7d3S4on4TiXUY8KoQA==", + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.52.2.tgz", + "integrity": "sha512-/eg4CI61ZUkLXxMHyVlmlGrSQZ34xqWlZNW43IAU4RmdzWEx0mQJ2mN/Cx4IHLVZFL6UBGAh+/GXhgvGb+nVxw==", "cpu": [ "arm64" ], @@ -1137,9 +1827,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.38.0.tgz", - "integrity": "sha512-hCY/KAeYMCyDpEE4pTETam0XZS4/5GXzlLgpi5f0IaPExw9kuB+PDTOTLuPtM10TlRG0U9OSmXJ+Wq9J39LvAg==", + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.52.2.tgz", + "integrity": "sha512-QOWgFH5X9+p+S1NAfOqc0z8qEpJIoUHf7OWjNUGOeW18Mx22lAUOiA9b6r2/vpzLdfxi/f+VWsYjUOMCcYh0Ng==", "cpu": [ "x64" ], @@ -1151,9 +1841,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.38.0.tgz", - "integrity": "sha512-mimPH43mHl4JdOTD7bUMFhBdrg6f9HzMTOEnzRmXbOZqjijCw8LA5z8uL6LCjxSa67H2xiLFvvO67PT05PRKGg==", + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.52.2.tgz", + "integrity": "sha512-kDWSPafToDd8LcBYd1t5jw7bD5Ojcu12S3uT372e5HKPzQt532vW+rGFFOaiR0opxePyUkHrwz8iWYEyH1IIQA==", "cpu": [ "arm" ], @@ -1165,9 +1855,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.38.0.tgz", - "integrity": "sha512-tPiJtiOoNuIH8XGG8sWoMMkAMm98PUwlriOFCCbZGc9WCax+GLeVRhmaxjJtz6WxrPKACgrwoZ5ia/uapq3ZVg==", + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.52.2.tgz", + "integrity": "sha512-gKm7Mk9wCv6/rkzwCiUC4KnevYhlf8ztBrDRT9g/u//1fZLapSRc+eDZj2Eu2wpJ+0RzUKgtNijnVIB4ZxyL+w==", "cpu": [ "arm" ], @@ -1179,9 +1869,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.38.0.tgz", - "integrity": "sha512-wZco59rIVuB0tjQS0CSHTTUcEde+pXQWugZVxWaQFdQQ1VYub/sTrNdY76D1MKdN2NB48JDuGABP6o6fqos8mA==", + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.52.2.tgz", + "integrity": "sha512-66lA8vnj5mB/rtDNwPgrrKUOtCLVQypkyDa2gMfOefXK6rcZAxKLO9Fy3GkW8VkPnENv9hBkNOFfGLf6rNKGUg==", "cpu": [ "arm64" ], @@ -1193,9 +1883,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.38.0.tgz", - "integrity": "sha512-fQgqwKmW0REM4LomQ+87PP8w8xvU9LZfeLBKybeli+0yHT7VKILINzFEuggvnV9M3x1Ed4gUBmGUzCo/ikmFbQ==", + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.52.2.tgz", + "integrity": "sha512-s+OPucLNdJHvuZHuIz2WwncJ+SfWHFEmlC5nKMUgAelUeBUnlB4wt7rXWiyG4Zn07uY2Dd+SGyVa9oyLkVGOjA==", "cpu": [ "arm64" ], @@ -1206,10 +1896,10 @@ "linux" ] }, - "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.38.0.tgz", - "integrity": "sha512-hz5oqQLXTB3SbXpfkKHKXLdIp02/w3M+ajp8p4yWOWwQRtHWiEOCKtc9U+YXahrwdk+3qHdFMDWR5k+4dIlddg==", + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.52.2.tgz", + "integrity": "sha512-8wTRM3+gVMDLLDdaT6tKmOE3lJyRy9NpJUS/ZRWmLCmOPIJhVyXwjBo+XbrrwtV33Em1/eCTd5TuGJm4+DmYjw==", "cpu": [ "loong64" ], @@ -1220,10 +1910,10 @@ "linux" ] }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.38.0.tgz", - "integrity": "sha512-NXqygK/dTSibQ+0pzxsL3r4Xl8oPqVoWbZV9niqOnIHV/J92fe65pOir0xjkUZDRSPyFRvu+4YOpJF9BZHQImw==", + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.52.2.tgz", + "integrity": "sha512-6yqEfgJ1anIeuP2P/zhtfBlDpXUb80t8DpbYwXQ3bQd95JMvUaqiX+fKqYqUwZXqdJDd8xdilNtsHM2N0cFm6A==", "cpu": [ "ppc64" ], @@ -1235,9 +1925,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.38.0.tgz", - "integrity": "sha512-GEAIabR1uFyvf/jW/5jfu8gjM06/4kZ1W+j1nWTSSB3w6moZEBm7iBtzwQ3a1Pxos2F7Gz+58aVEnZHU295QTg==", + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.52.2.tgz", + "integrity": "sha512-sshYUiYVSEI2B6dp4jMncwxbrUqRdNApF2c3bhtLAU0qA8Lrri0p0NauOsTWh3yCCCDyBOjESHMExonp7Nzc0w==", "cpu": [ "riscv64" ], @@ -1249,9 +1939,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.38.0.tgz", - "integrity": "sha512-9EYTX+Gus2EGPbfs+fh7l95wVADtSQyYw4DfSBcYdUEAmP2lqSZY0Y17yX/3m5VKGGJ4UmIH5LHLkMJft3bYoA==", + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.52.2.tgz", + "integrity": "sha512-duBLgd+3pqC4MMwBrKkFxaZerUxZcYApQVC5SdbF5/e/589GwVvlRUnyqMFbM8iUSb1BaoX/3fRL7hB9m2Pj8Q==", "cpu": [ "riscv64" ], @@ -1263,9 +1953,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.38.0.tgz", - "integrity": "sha512-Mpp6+Z5VhB9VDk7RwZXoG2qMdERm3Jw07RNlXHE0bOnEeX+l7Fy4bg+NxfyN15ruuY3/7Vrbpm75J9QHFqj5+Q==", + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.52.2.tgz", + "integrity": "sha512-tzhYJJidDUVGMgVyE+PmxENPHlvvqm1KILjjZhB8/xHYqAGeizh3GBGf9u6WdJpZrz1aCpIIHG0LgJgH9rVjHQ==", "cpu": [ "s390x" ], @@ -1277,9 +1967,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.38.0.tgz", - "integrity": "sha512-vPvNgFlZRAgO7rwncMeE0+8c4Hmc+qixnp00/Uv3ht2x7KYrJ6ERVd3/R0nUtlE6/hu7/HiiNHJ/rP6knRFt1w==", + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.52.2.tgz", + "integrity": "sha512-opH8GSUuVcCSSyHHcl5hELrmnk4waZoVpgn/4FDao9iyE4WpQhyWJ5ryl5M3ocp4qkRuHfyXnGqg8M9oKCEKRA==", "cpu": [ "x64" ], @@ -1291,9 +1981,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.38.0.tgz", - "integrity": "sha512-q5Zv+goWvQUGCaL7fU8NuTw8aydIL/C9abAVGCzRReuj5h30TPx4LumBtAidrVOtXnlB+RZkBtExMsfqkMfb8g==", + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.52.2.tgz", + "integrity": "sha512-LSeBHnGli1pPKVJ79ZVJgeZWWZXkEe/5o8kcn23M8eMKCUANejchJbF/JqzM4RRjOJfNRhKJk8FuqL1GKjF5oQ==", "cpu": [ "x64" ], @@ -1304,10 +1994,24 @@ "linux" ] }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.52.2.tgz", + "integrity": "sha512-uPj7MQ6/s+/GOpolavm6BPo+6CbhbKYyZHUDvZ/SmJM7pfDBgdGisFX3bY/CBDMg2ZO4utfhlApkSfZ92yXw7Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.38.0.tgz", - "integrity": "sha512-u/Jbm1BU89Vftqyqbmxdq14nBaQjQX1HhmsdBWqSdGClNaKwhjsg5TpW+5Ibs1mb8Es9wJiMdl86BcmtUVXNZg==", + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.52.2.tgz", + "integrity": "sha512-Z9MUCrSgIaUeeHAiNkm3cQyst2UhzjPraR3gYYfOjAuZI7tcFRTOD+4cHLPoS/3qinchth+V56vtqz1Tv+6KPA==", "cpu": [ "arm64" ], @@ -1319,9 +2023,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.38.0.tgz", - "integrity": "sha512-mqu4PzTrlpNHHbu5qleGvXJoGgHpChBlrBx/mEhTPpnAL1ZAYFlvHD7rLK839LLKQzqEQMFJfGrrOHItN4ZQqA==", + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.52.2.tgz", + "integrity": "sha512-+GnYBmpjldD3XQd+HMejo+0gJGwYIOfFeoBQv32xF/RUIvccUz20/V6Otdv+57NE70D5pa8W/jVGDoGq0oON4A==", "cpu": [ "ia32" ], @@ -1332,10 +2036,24 @@ "win32" ] }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.52.2.tgz", + "integrity": "sha512-ApXFKluSB6kDQkAqZOKXBjiaqdF1BlKi+/eqnYe9Ee7U2K3pUDKsIyr8EYm/QDHTJIM+4X+lI0gJc3TTRhd+dA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.38.0.tgz", - "integrity": "sha512-jjqy3uWlecfB98Psxb5cD6Fny9Fupv9LrDSPTQZUROqjvZmcCqNu4UMl7qqhlUUGpwiAkotj6GYu4SZdcr/nLw==", + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.52.2.tgz", + "integrity": "sha512-ARz+Bs8kY6FtitYM96PqPEVvPXqEZmPZsSkXvyX19YzDqkCaIlhCieLLMI5hxO9SRZ2XtCtm8wxhy0iJ2jxNfw==", "cpu": [ "x64" ], @@ -1351,6 +2069,7 @@ "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", @@ -1360,10 +2079,11 @@ } }, "node_modules/@types/babel__generator": { - "version": "7.6.8", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", - "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.0.0" } @@ -1373,92 +2093,82 @@ "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", "dev": true, + "license": "MIT", "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" } }, "node_modules/@types/babel__traverse": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.5.tgz", - "integrity": "sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.20.7" + "@babel/types": "^7.28.2" } }, "node_modules/@types/estree": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", - "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "dev": true, "license": "MIT" }, - "node_modules/@types/http-proxy": { - "version": "1.17.15", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.15.tgz", - "integrity": "sha512-25g5atgiVNTIv0LBDTg1H74Hvayx0ajtJPLLcYE3whFv75J0pWNtOBzaXJQgDTmrX1bx5U9YC2w/n65BN1HwRQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/http-proxy-middleware": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/http-proxy-middleware/-/http-proxy-middleware-1.0.0.tgz", - "integrity": "sha512-/s8lFX6rT43hSPqjjD8KNuu0SkPKY7uIdR6u9DCxVqCRhAvfKxGbVOixJsAT2mdpSnCyrGFAGoB39KFh6tmRxw==", - "deprecated": "This is a stub types definition. http-proxy-middleware provides its own type definitions, so you do not need this installed.", - "dev": true, - "dependencies": { - "http-proxy-middleware": "*" - } - }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true + "dev": true, + "license": "MIT" }, - "node_modules/@types/node": { - "version": "20.12.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.12.tgz", - "integrity": "sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==", - "devOptional": true, - "dependencies": { - "undici-types": "~5.26.4" - } + "node_modules/@types/parse-json": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", + "license": "MIT" }, "node_modules/@types/prop-types": { - "version": "15.7.12", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", - "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", - "devOptional": true + "version": "15.7.15", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", + "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", + "license": "MIT" }, "node_modules/@types/react": { - "version": "18.2.74", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.74.tgz", - "integrity": "sha512-9AEqNZZyBx8OdZpxzQlaFEVCSFUM2YXJH46yPOiOpm078k6ZLOCcuAzGum/zK8YBwY+dbahVNbHrbgrAwIRlqw==", - "devOptional": true, + "version": "19.1.13", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.13.tgz", + "integrity": "sha512-hHkbU/eoO3EG5/MZkuFSKmYqPbSVk5byPFa3e7y/8TybHiLMACgI8seVYlicwk7H5K/rI2px9xrQp/C+AUDTiQ==", + "license": "MIT", "dependencies": { - "@types/prop-types": "*", "csstype": "^3.0.2" } }, "node_modules/@types/react-dom": { - "version": "18.2.24", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.24.tgz", - "integrity": "sha512-cN6upcKd8zkGy4HU9F1+/s98Hrp6D4MOcippK4PoE8OZRngohHZpbJn1GsaDLz87MqvHNoT13nHvNqM9ocRHZg==", + "version": "19.1.9", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.9.tgz", + "integrity": "sha512-qXRuZaOsAdXKFyOhRBg6Lqqc0yay13vN7KrIg4L7N4aaHN68ma9OK3NE1BoDFgFOTfM7zg+3/8+2n8rLUH3OKQ==", "dev": true, - "dependencies": { + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.0.0" + } + }, + "node_modules/@types/react-transition-group": { + "version": "4.4.12", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz", + "integrity": "sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==", + "license": "MIT", + "peerDependencies": { "@types/react": "*" } }, - "node_modules/@types/semver": { - "version": "7.5.8", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", - "dev": true + "node_modules/@types/trusted-types": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-1.0.6.tgz", + "integrity": "sha512-230RC8sFeHoT6sSUlRO6a8cAnclO06eeiq1QDfiv2FGCLWFvvERWgwIQD4FWqD9A69BN7Lzee4OXwoMVnnsWDw==", + "license": "MIT", + "peer": true }, "node_modules/@types/uuid": { "version": "8.3.4", @@ -1467,119 +2177,150 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.5.0.tgz", - "integrity": "sha512-HpqNTH8Du34nLxbKgVMGljZMG0rJd2O9ecvr2QLYp+7512ty1j42KnsFwspPXg1Vh8an9YImf6CokUBltisZFQ==", + "version": "8.44.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.44.1.tgz", + "integrity": "sha512-molgphGqOBT7t4YKCSkbasmu1tb1MgrZ2szGzHbclF7PNmOkSTQVHy+2jXOSnxvR3+Xe1yySHFZoqMpz3TfQsw==", "dev": true, + "license": "MIT", "dependencies": { - "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "7.5.0", - "@typescript-eslint/type-utils": "7.5.0", - "@typescript-eslint/utils": "7.5.0", - "@typescript-eslint/visitor-keys": "7.5.0", - "debug": "^4.3.4", + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.44.1", + "@typescript-eslint/type-utils": "8.44.1", + "@typescript-eslint/utils": "8.44.1", + "@typescript-eslint/visitor-keys": "8.44.1", "graphemer": "^1.4.0", - "ignore": "^5.2.4", + "ignore": "^7.0.0", "natural-compare": "^1.4.0", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" + "ts-api-utils": "^2.1.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^7.0.0", - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "@typescript-eslint/parser": "^8.44.1", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/parser": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.5.0.tgz", - "integrity": "sha512-cj+XGhNujfD2/wzR1tabNsidnYRaFfEkcULdcIyVBYcXjBvBKOes+mpMBP7hMpOyk+gBcfXsrg4NBGAStQyxjQ==", + "version": "8.44.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.44.1.tgz", + "integrity": "sha512-EHrrEsyhOhxYt8MTg4zTF+DJMuNBzWwgvvOYNj/zm1vnaD/IC5zCXFehZv94Piqa2cRFfXrTFxIvO95L7Qc/cw==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "7.5.0", - "@typescript-eslint/types": "7.5.0", - "@typescript-eslint/typescript-estree": "7.5.0", - "@typescript-eslint/visitor-keys": "7.5.0", + "@typescript-eslint/scope-manager": "8.44.1", + "@typescript-eslint/types": "8.44.1", + "@typescript-eslint/typescript-estree": "8.44.1", + "@typescript-eslint/visitor-keys": "8.44.1", "debug": "^4.3.4" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.56.0" + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.44.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.44.1.tgz", + "integrity": "sha512-ycSa60eGg8GWAkVsKV4E6Nz33h+HjTXbsDT4FILyL8Obk5/mx4tbvCNsLf9zret3ipSumAOG89UcCs/KRaKYrA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.44.1", + "@typescript-eslint/types": "^8.44.1", + "debug": "^4.3.4" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.5.0.tgz", - "integrity": "sha512-Z1r7uJY0MDeUlql9XJ6kRVgk/sP11sr3HKXn268HZyqL7i4cEfrdFuSSY/0tUqT37l5zT0tJOsuDP16kio85iA==", + "version": "8.44.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.44.1.tgz", + "integrity": "sha512-NdhWHgmynpSvyhchGLXh+w12OMT308Gm25JoRIyTZqEbApiBiQHD/8xgb6LqCWCFcxFtWwaVdFsLPQI3jvhywg==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "7.5.0", - "@typescript-eslint/visitor-keys": "7.5.0" + "@typescript-eslint/types": "8.44.1", + "@typescript-eslint/visitor-keys": "8.44.1" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.44.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.44.1.tgz", + "integrity": "sha512-B5OyACouEjuIvof3o86lRMvyDsFwZm+4fBOqFHccIctYgBjqR3qT39FBYGN87khcgf0ExpdCBeGKpKRhSFTjKQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, "node_modules/@typescript-eslint/type-utils": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.5.0.tgz", - "integrity": "sha512-A021Rj33+G8mx2Dqh0nMO9GyjjIBK3MqgVgZ2qlKf6CJy51wY/lkkFqq3TqqnH34XyAHUkq27IjlUkWlQRpLHw==", + "version": "8.44.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.44.1.tgz", + "integrity": "sha512-KdEerZqHWXsRNKjF9NYswNISnFzXfXNDfPxoTh7tqohU/PRIbwTmsjGK6V9/RTYWau7NZvfo52lgVk+sJh0K3g==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "7.5.0", - "@typescript-eslint/utils": "7.5.0", + "@typescript-eslint/types": "8.44.1", + "@typescript-eslint/typescript-estree": "8.44.1", + "@typescript-eslint/utils": "8.44.1", "debug": "^4.3.4", - "ts-api-utils": "^1.0.1" + "ts-api-utils": "^2.1.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/types": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.5.0.tgz", - "integrity": "sha512-tv5B4IHeAdhR7uS4+bf8Ov3k793VEVHd45viRRkehIUZxm0WF82VPiLgHzA/Xl4TGPg1ZD49vfxBKFPecD5/mg==", + "version": "8.44.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.44.1.tgz", + "integrity": "sha512-Lk7uj7y9uQUOEguiDIDLYLJOrYHQa7oBiURYVFqIpGxclAFQ78f6VUOM8lI2XEuNOKNB7XuvM2+2cMXAoq4ALQ==", "dev": true, + "license": "MIT", "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -1587,106 +2328,116 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.5.0.tgz", - "integrity": "sha512-YklQQfe0Rv2PZEueLTUffiQGKQneiIEKKnfIqPIOxgM9lKSZFCjT5Ad4VqRKj/U4+kQE3fa8YQpskViL7WjdPQ==", + "version": "8.44.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.44.1.tgz", + "integrity": "sha512-qnQJ+mVa7szevdEyvfItbO5Vo+GfZ4/GZWWDRRLjrxYPkhM+6zYB2vRYwCsoJLzqFCdZT4mEqyJoyzkunsZ96A==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "7.5.0", - "@typescript-eslint/visitor-keys": "7.5.0", + "@typescript-eslint/project-service": "8.44.1", + "@typescript-eslint/tsconfig-utils": "8.44.1", + "@typescript-eslint/types": "8.44.1", + "@typescript-eslint/visitor-keys": "8.44.1", "debug": "^4.3.4", - "globby": "^11.1.0", + "fast-glob": "^3.3.2", "is-glob": "^4.0.3", - "minimatch": "9.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.1.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/utils": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.5.0.tgz", - "integrity": "sha512-3vZl9u0R+/FLQcpy2EHyRGNqAS/ofJ3Ji8aebilfJe+fobK8+LbIFmrHciLVDxjDoONmufDcnVSF38KwMEOjzw==", + "version": "8.44.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.44.1.tgz", + "integrity": "sha512-DpX5Fp6edTlocMCwA+mHY8Mra+pPjRZ0TfHkXI8QFelIKcbADQz1LUPNtzOFUriBB2UYqw4Pi9+xV4w9ZczHFg==", "dev": true, + "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "7.5.0", - "@typescript-eslint/types": "7.5.0", - "@typescript-eslint/typescript-estree": "7.5.0", - "semver": "^7.5.4" + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.44.1", + "@typescript-eslint/types": "8.44.1", + "@typescript-eslint/typescript-estree": "8.44.1" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.56.0" + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.5.0.tgz", - "integrity": "sha512-mcuHM/QircmA6O7fy6nn2w/3ditQkj+SgtOc8DW3uQ10Yfj42amm2i+6F2K4YAOPNNTmE6iM1ynM6lrSwdendA==", + "version": "8.44.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.44.1.tgz", + "integrity": "sha512-576+u0QD+Jp3tZzvfRfxon0EA2lzcDt3lhUbsC6Lgzy9x2VR4E+JUiNyGHi5T8vk0TV+fpJ5GLG1JsJuWCaKhw==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "7.5.0", - "eslint-visitor-keys": "^3.4.1" + "@typescript-eslint/types": "8.44.1", + "eslint-visitor-keys": "^4.2.1" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true + "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==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } }, "node_modules/@vitejs/plugin-react": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.3.4.tgz", - "integrity": "sha512-SCCPBJtYLdE8PX/7ZQAs1QAZ8Jqwih+0VBLum1EGqmCCQal+MIUqLCzj3ZUy8ufbC0cAM4LRlSTm7IQJwWT4ug==", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.0.3.tgz", + "integrity": "sha512-PFVHhosKkofGH0Yzrw1BipSedTH68BFF8ZWy1kfUpCtJcouXXY0+racG8sExw7hw0HoX36813ga5o3LTWZ4FUg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/core": "^7.26.0", - "@babel/plugin-transform-react-jsx-self": "^7.25.9", - "@babel/plugin-transform-react-jsx-source": "^7.25.9", + "@babel/core": "^7.28.4", + "@babel/plugin-transform-react-jsx-self": "^7.27.1", + "@babel/plugin-transform-react-jsx-source": "^7.27.1", + "@rolldown/pluginutils": "1.0.0-beta.35", "@types/babel__core": "^7.20.5", - "react-refresh": "^0.14.2" + "react-refresh": "^0.17.0" }, "engines": { - "node": "^14.18.0 || >=16.0.0" + "node": "^20.19.0 || >=22.12.0" }, "peerDependencies": { - "vite": "^4.2.0 || ^5.0.0 || ^6.0.0" + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, "node_modules/acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, + "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -1699,6 +2450,7 @@ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, + "license": "MIT", "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } @@ -1708,6 +2460,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -1719,35 +2472,44 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/antlr4-c3": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/antlr4-c3/-/antlr4-c3-3.4.1.tgz", - "integrity": "sha512-YLO/ncwUp8w2GNK/lnsYXtMkd8izHCWjxtk7EaTGIZq07THfvI5aHDuhls/RctX3EYDlM9zeTKdqn54eLYNglQ==", + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/antlr4-c3/-/antlr4-c3-3.4.4.tgz", + "integrity": "sha512-ixp1i17ypbRzZnffdarIfCVEXJwPydtDt61SHMGkc+UCD7rrbfvHESTMTgx8jFhUgKAgcHyt9060kQ8nU3vlxA==", + "license": "MIT", "dependencies": { - "antlr4ng": "^3.0.1" + "antlr4ng": "3.0.16" } }, "node_modules/antlr4ng": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/antlr4ng/-/antlr4ng-3.0.4.tgz", - "integrity": "sha512-u1Ww6wVv9hq70E9AaYe5qW3ba8hvnjJdO3ZsKnb3iJWFV/medLEEhbyWwXCvvD2ef0ptdaiIUgmaazS/WE6uyQ==", - "peerDependencies": { - "antlr4ng-cli": "^2.0.0" - } + "version": "3.0.16", + "resolved": "https://registry.npmjs.org/antlr4ng/-/antlr4ng-3.0.16.tgz", + "integrity": "sha512-DQuJkC7kX3xunfF4K2KsWTSvoxxslv+FQp/WHQZTJSsH2Ec3QfFmrxC3Nky2ok9yglXn6nHM4zUaVDxcN5f6kA==", + "license": "BSD-3-Clause" }, "node_modules/antlr4ng-cli": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/antlr4ng-cli/-/antlr4ng-cli-2.0.0.tgz", "integrity": "sha512-oAt5OSSYhRQn1PgahtpAP4Vp3BApCoCqlzX7Q8ZUWWls4hX59ryYuu0t7Hwrnfk796OxP/vgIJaqxdltd/oEvQ==", + "deprecated": "This package is deprecated and will no longer be updated. Please use the new antlr-ng package instead: https://github.com/mike-lischke/antlr-ng", + "dev": true, + "license": "BSD-3-Clause", "bin": { "antlr4ng": "index.js" } @@ -1755,28 +2517,47 @@ "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, + "node_modules/babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + }, "engines": { - "node": ">=8" + "node": ">=10", + "npm": ">=6" } }, "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 + "dev": true, + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.8.7", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.7.tgz", + "integrity": "sha512-bxxN2M3a4d1CRoQC//IqsR5XrLh0IJ8TCv2x6Y9N0nckNz/rTjZB3//GGscZziZOxmjP55rzxg/ze7usFI9FqQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } }, "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } @@ -1795,9 +2576,9 @@ } }, "node_modules/browserslist": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", - "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", + "version": "4.26.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.26.2.tgz", + "integrity": "sha512-ECFzp6uFOSB+dcZ5BK/IBaGWssbSYBHvuMeMt3MMFyhI0Z8SqGgEkBLARgpRH3hutIgPVsALcMwbDrJqPxQ65A==", "dev": true, "funding": [ { @@ -1815,10 +2596,11 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001688", - "electron-to-chromium": "^1.5.73", - "node-releases": "^2.0.19", - "update-browserslist-db": "^1.1.1" + "baseline-browser-mapping": "^2.8.3", + "caniuse-lite": "^1.0.30001741", + "electron-to-chromium": "^1.5.218", + "node-releases": "^2.0.21", + "update-browserslist-db": "^1.1.3" }, "bin": { "browserslist": "cli.js" @@ -1831,15 +2613,15 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/caniuse-lite": { - "version": "1.0.30001707", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001707.tgz", - "integrity": "sha512-3qtRjw/HQSMlDWf+X79N206fepf4SOOU6SQLMaq/0KkZLmSjPxAkBOQQ+FxbHKfHmYLZFfdWsO3KA90ceHPSnw==", + "version": "1.0.30001745", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001745.tgz", + "integrity": "sha512-ywt6i8FzvdgrrrGbr1jZVObnVv6adj+0if2/omv9cmR2oiZs30zL4DIyaptKcbOrBdOIc74QTMoJvSE2QHh5UQ==", "dev": true, "funding": [ { @@ -1857,6 +2639,52 @@ ], "license": "CC-BY-4.0" }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "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/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, "node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", @@ -1867,7 +2695,8 @@ "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/convert-source-map": { "version": "2.0.0", @@ -1876,6 +2705,31 @@ "dev": true, "license": "MIT" }, + "node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "license": "MIT", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cosmiconfig/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -1895,13 +2749,12 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "devOptional": true + "license": "MIT" }, "node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "dev": true, + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -1915,24 +2768,13 @@ } } }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, "node_modules/discontinuous-range": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", @@ -1950,29 +2792,36 @@ "redux": "^4.2.0" } }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, + "node_modules/dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "license": "MIT", "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" } }, "node_modules/electron-to-chromium": { - "version": "1.5.129", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.129.tgz", - "integrity": "sha512-JlXUemX4s0+9f8mLqib/bHH8gOHf5elKS6KeWG3sk3xozb/JTq/RLXIv8OKUWiK4Ah00Wm88EFj5PYkFr4RUPA==", + "version": "1.5.223", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.223.tgz", + "integrity": "sha512-qKm55ic6nbEmagFlTFczML33rF90aU+WtrJ9MdTCThrcvDNdUHN4p6QfVN78U06ZmguqXIyMPyYhw2TrbDUwPQ==", "dev": true, "license": "ISC" }, + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, "node_modules/esbuild": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.2.tgz", - "integrity": "sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ==", + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.10.tgz", + "integrity": "sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -1983,31 +2832,32 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.2", - "@esbuild/android-arm": "0.25.2", - "@esbuild/android-arm64": "0.25.2", - "@esbuild/android-x64": "0.25.2", - "@esbuild/darwin-arm64": "0.25.2", - "@esbuild/darwin-x64": "0.25.2", - "@esbuild/freebsd-arm64": "0.25.2", - "@esbuild/freebsd-x64": "0.25.2", - "@esbuild/linux-arm": "0.25.2", - "@esbuild/linux-arm64": "0.25.2", - "@esbuild/linux-ia32": "0.25.2", - "@esbuild/linux-loong64": "0.25.2", - "@esbuild/linux-mips64el": "0.25.2", - "@esbuild/linux-ppc64": "0.25.2", - "@esbuild/linux-riscv64": "0.25.2", - "@esbuild/linux-s390x": "0.25.2", - "@esbuild/linux-x64": "0.25.2", - "@esbuild/netbsd-arm64": "0.25.2", - "@esbuild/netbsd-x64": "0.25.2", - "@esbuild/openbsd-arm64": "0.25.2", - "@esbuild/openbsd-x64": "0.25.2", - "@esbuild/sunos-x64": "0.25.2", - "@esbuild/win32-arm64": "0.25.2", - "@esbuild/win32-ia32": "0.25.2", - "@esbuild/win32-x64": "0.25.2" + "@esbuild/aix-ppc64": "0.25.10", + "@esbuild/android-arm": "0.25.10", + "@esbuild/android-arm64": "0.25.10", + "@esbuild/android-x64": "0.25.10", + "@esbuild/darwin-arm64": "0.25.10", + "@esbuild/darwin-x64": "0.25.10", + "@esbuild/freebsd-arm64": "0.25.10", + "@esbuild/freebsd-x64": "0.25.10", + "@esbuild/linux-arm": "0.25.10", + "@esbuild/linux-arm64": "0.25.10", + "@esbuild/linux-ia32": "0.25.10", + "@esbuild/linux-loong64": "0.25.10", + "@esbuild/linux-mips64el": "0.25.10", + "@esbuild/linux-ppc64": "0.25.10", + "@esbuild/linux-riscv64": "0.25.10", + "@esbuild/linux-s390x": "0.25.10", + "@esbuild/linux-x64": "0.25.10", + "@esbuild/netbsd-arm64": "0.25.10", + "@esbuild/netbsd-x64": "0.25.10", + "@esbuild/openbsd-arm64": "0.25.10", + "@esbuild/openbsd-x64": "0.25.10", + "@esbuild/openharmony-arm64": "0.25.10", + "@esbuild/sunos-x64": "0.25.10", + "@esbuild/win32-arm64": "0.25.10", + "@esbuild/win32-ia32": "0.25.10", + "@esbuild/win32-x64": "0.25.10" } }, "node_modules/escalade": { @@ -2020,93 +2870,114 @@ "node": ">=6" } }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "version": "9.36.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.36.0.tgz", + "integrity": "sha512-hB4FIzXovouYzwzECDcUkJ4OcfOEkXTv2zRY6B9bkwjx/cprAq0uvm1nl7zvQ0/TsUk0zQiN4uPfJpB9m+rPMQ==", "dev": true, + "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.0", + "@eslint/config-helpers": "^0.3.1", + "@eslint/core": "^0.15.2", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.36.0", + "@eslint/plugin-kit": "^0.3.5", + "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", + "cross-spawn": "^7.0.6", "debug": "^4.3.2", - "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", + "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" + "optionator": "^0.9.3" }, "bin": { "eslint": "bin/eslint.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } } }, "node_modules/eslint-plugin-react-hooks": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", - "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz", + "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" } }, "node_modules/eslint-plugin-react-refresh": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.6.tgz", - "integrity": "sha512-NjGXdm7zgcKRkKMua34qVO9doI7VOxZ6ancSvBELJSSoX97jyndXcSoa8XBh69JoB31dNz3EEzlMcizZl7LaMA==", + "version": "0.4.21", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.21.tgz", + "integrity": "sha512-MWDWTtNC4voTcWDxXbdmBNe8b/TxfxRFUL6hXgKWJjN9c1AagYEmpiFWBWzDw+5H3SulWUe1pJKTnoSdmk88UA==", "dev": true, + "license": "MIT", "peerDependencies": { - "eslint": ">=7" + "eslint": ">=8.40" } }, "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -2117,6 +2988,7 @@ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -2124,99 +2996,38 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, - "node_modules/eslint/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/eslint/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/eslint/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/eslint/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "node_modules/eslint/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==", "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, + "license": "Apache-2.0", "engines": { - "node": ">=8" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/eslint/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">= 4" } }, "node_modules/eslint/node_modules/minimatch": { @@ -2224,6 +3035,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -2231,40 +3043,43 @@ "node": "*" } }, - "node_modules/eslint/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "has-flag": "^4.0.0" + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" }, "engines": { - "node": ">=8" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "node_modules/espree/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==", "dev": true, - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, + "license": "Apache-2.0", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "estraverse": "^5.1.0" }, @@ -2277,6 +3092,7 @@ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" }, @@ -2289,6 +3105,7 @@ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } @@ -2298,32 +3115,29 @@ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=0.10.0" } }, - "node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true - }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT" }, "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "micromatch": "^4.0.8" }, "engines": { "node": ">=8.6.0" @@ -2334,6 +3148,7 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -2345,33 +3160,37 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", "dev": true, + "license": "ISC", "dependencies": { "reusify": "^1.0.4" } }, "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, + "license": "MIT", "dependencies": { - "flat-cache": "^3.0.4" + "flat-cache": "^4.0.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16.0.0" } }, "node_modules/fill-range": { @@ -2387,11 +3206,18 @@ "node": ">=8" } }, + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", + "license": "MIT" + }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -2404,50 +3230,25 @@ } }, "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, + "license": "MIT", "dependencies": { "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" + "keyv": "^4.5.4" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16" } }, "node_modules/flatted": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", - "dev": true - }, - "node_modules/follow-redirects": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", - "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true + "license": "ISC" }, "node_modules/fsevents": { "version": "2.3.3", @@ -2464,6 +3265,15 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -2474,31 +3284,12 @@ "node": ">=6.9.0" } }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.3" }, @@ -2506,53 +3297,14 @@ "node": ">=10.13.0" } }, - "node_modules/glob/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "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==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=4" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -2562,63 +3314,55 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, - "node_modules/hoist-non-react-statics": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", - "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", - "license": "BSD-3-Clause", - "dependencies": { - "react-is": "^16.7.0" - } + "dev": true, + "license": "MIT" }, - "node_modules/http-proxy": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "dependencies": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - }, + "license": "MIT", "engines": { - "node": ">=8.0.0" + "node": ">=8" } }, - "node_modules/http-proxy-middleware": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-3.0.3.tgz", - "integrity": "sha512-usY0HG5nyDUwtqpiZdETNbmKtw3QQ1jwYFZ9wi5iHzX2BcILwQKtYDJPo7XHTsu5Z0B2Hj3W9NNnbd+AjFWjqg==", - "dev": true, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "license": "MIT", "dependencies": { - "@types/http-proxy": "^1.17.15", - "debug": "^4.3.6", - "http-proxy": "^1.18.1", - "is-glob": "^4.0.3", - "is-plain-object": "^5.0.0", - "micromatch": "^4.0.8" + "function-bind": "^1.1.2" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.4" + } + }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "license": "BSD-3-Clause", + "dependencies": { + "react-is": "^16.7.0" } }, "node_modules/ignore": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4" } }, "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "license": "MIT", "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -2635,31 +3379,38 @@ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.19" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "license": "MIT" + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "license": "MIT", "dependencies": { - "once": "^1.3.0", - "wrappy": "1" + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -2669,6 +3420,7 @@ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, + "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" }, @@ -2686,41 +3438,25 @@ "node": ">=0.12.0" } }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, + "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -2732,7 +3468,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "dev": true, "license": "MIT", "bin": { "jsesc": "bin/jsesc" @@ -2745,19 +3480,28 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "license": "MIT" }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json5": { "version": "2.2.3", @@ -2777,6 +3521,7 @@ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, + "license": "MIT", "dependencies": { "json-buffer": "3.0.1" } @@ -2786,6 +3531,7 @@ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, + "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -2794,11 +3540,18 @@ "node": ">= 0.8.0" } }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "license": "MIT" + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^5.0.0" }, @@ -2813,12 +3566,14 @@ "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, @@ -2837,12 +3592,12 @@ } }, "node_modules/lucide-react": { - "version": "0.460.0", - "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.460.0.tgz", - "integrity": "sha512-BVtq/DykVeIvRTJvRAgCsOwaGL8Un3Bxh8MbDxMhEWlZay3T4IpEKDEpwt5KZ0KJMHzgm6jrltxlT5eXOWXDHg==", + "version": "0.544.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.544.0.tgz", + "integrity": "sha512-t5tS44bqd825zAW45UQxpG2CvcC4urOwn2TrwSH8u+MjeE+1NnWl6QqeQ/6NdjMqdOygyiT9p3Ev0p1NJykxjw==", "license": "ISC", "peerDependencies": { - "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc" + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "node_modules/merge2": { @@ -2850,6 +3605,7 @@ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8" } @@ -2869,10 +3625,11 @@ } }, "node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -2884,10 +3641,14 @@ } }, "node_modules/monaco-editor": { - "version": "0.47.0", - "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.47.0.tgz", - "integrity": "sha512-VabVvHvQ9QmMwXu4du008ZDuyLnHs9j7ThVFsiJoXSOQk18+LF89N4ADzPbFenm0W4V2bGHnFBztIRQTgBfxzw==", - "peer": true + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.53.0.tgz", + "integrity": "sha512-0WNThgC6CMWNXXBxTbaYYcunj08iB5rnx4/G56UOPeL9UVIUGGHA1GR0EWIh9Ebabj7NpCRawQ5b0hfN1jQmYQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/trusted-types": "^1.0.6" + } }, "node_modules/moo": { "version": "0.5.2", @@ -2899,7 +3660,6 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, "license": "MIT" }, "node_modules/nanoid": { @@ -2925,7 +3685,8 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/nearley": { "version": "2.20.1", @@ -2950,33 +3711,34 @@ } }, "node_modules/node-releases": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", - "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "version": "2.0.21", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.21.tgz", + "integrity": "sha512-5b0pgg78U3hwXkCM8Z9b2FJdPZlr9Psr9V2gQPESdGHqbntyFJKFW4r5TeWGFzafGY3hzs1JC62VEQMbl1JFkw==", "dev": true, "license": "MIT" }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "dependencies": { - "wrappy": "1" + "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/optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, + "license": "MIT", "dependencies": { - "@aashutoshrathi/word-wrap": "^1.2.3", "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" }, "engines": { "node": ">= 0.8.0" @@ -2987,6 +3749,7 @@ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, + "license": "MIT", "dependencies": { "yocto-queue": "^0.1.0" }, @@ -3002,6 +3765,7 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^3.0.2" }, @@ -3016,7 +3780,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, + "license": "MIT", "dependencies": { "callsites": "^3.0.0" }, @@ -3024,38 +3788,55 @@ "node": ">=6" } }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "license": "MIT" + }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -3064,7 +3845,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, "license": "ISC" }, "node_modules/picomatch": { @@ -3072,6 +3852,7 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8.6" }, @@ -3080,9 +3861,9 @@ } }, "node_modules/postcss": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", - "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", "dev": true, "funding": [ { @@ -3100,7 +3881,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.8", + "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -3108,23 +3889,20 @@ "node": "^10 || ^12 || >=14" } }, - "node_modules/precise": { - "resolved": "", - "link": true - }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8.0" } }, "node_modules/prettier": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz", - "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", + "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", "license": "MIT", "bin": { "prettier": "bin/prettier.cjs" @@ -3136,11 +3914,23 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, + "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/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -3163,7 +3953,8 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/railroad-diagrams": { "version": "1.0.0", @@ -3185,12 +3976,11 @@ } }, "node_modules/react": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", - "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", - "dependencies": { - "loose-envify": "^1.1.0" - }, + "version": "19.1.1", + "resolved": "https://registry.npmjs.org/react/-/react-19.1.1.tgz", + "integrity": "sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ==", + "license": "MIT", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -3235,15 +4025,16 @@ } }, "node_modules/react-dom": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", - "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "version": "19.1.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.1.tgz", + "integrity": "sha512-Dlq/5LAZgF0Gaz6yiqZCf6VCcZs1ghAJyrsu84Q/GT0gV+mCxbfmKNoGRKBYMJ8IEdGPqu49YWXD02GCknEDkw==", + "license": "MIT", + "peer": true, "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.0" + "scheduler": "^0.26.0" }, "peerDependencies": { - "react": "^18.2.0" + "react": "^19.1.1" } }, "node_modules/react-is": { @@ -3253,15 +4044,31 @@ "license": "MIT" }, "node_modules/react-refresh": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", - "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", + "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, + "node_modules/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "license": "BSD-3-Clause", + "dependencies": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": ">=16.6.0", + "react-dom": ">=16.6.0" + } + }, "node_modules/redux": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", @@ -3271,23 +4078,37 @@ "@babel/runtime": "^7.9.2" } }, - "node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "node_modules/reselect": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz", + "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==", "license": "MIT" }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true + "node_modules/resolve": { + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -3302,38 +4123,24 @@ } }, "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", "dev": true, + "license": "MIT", "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" } }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/rollup": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.38.0.tgz", - "integrity": "sha512-5SsIRtJy9bf1ErAOiFMFzl64Ex9X5V7bnJ+WlFMb+zmP459OSWCEG7b0ERZ+PEU7xPt4OG3RHbrp1LJlXxYTrw==", + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.52.2.tgz", + "integrity": "sha512-I25/2QgoROE1vYV+NQ1En9T9UFB9Cmfm2CJ83zZOlaDpvz29wGQSZXWKw7MiNXau7wYgB/T9fVIdIuEQ+KbiiA==", "dev": true, "license": "MIT", "dependencies": { - "@types/estree": "1.0.7" + "@types/estree": "1.0.8" }, "bin": { "rollup": "dist/bin/rollup" @@ -3343,26 +4150,28 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.38.0", - "@rollup/rollup-android-arm64": "4.38.0", - "@rollup/rollup-darwin-arm64": "4.38.0", - "@rollup/rollup-darwin-x64": "4.38.0", - "@rollup/rollup-freebsd-arm64": "4.38.0", - "@rollup/rollup-freebsd-x64": "4.38.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.38.0", - "@rollup/rollup-linux-arm-musleabihf": "4.38.0", - "@rollup/rollup-linux-arm64-gnu": "4.38.0", - "@rollup/rollup-linux-arm64-musl": "4.38.0", - "@rollup/rollup-linux-loongarch64-gnu": "4.38.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.38.0", - "@rollup/rollup-linux-riscv64-gnu": "4.38.0", - "@rollup/rollup-linux-riscv64-musl": "4.38.0", - "@rollup/rollup-linux-s390x-gnu": "4.38.0", - "@rollup/rollup-linux-x64-gnu": "4.38.0", - "@rollup/rollup-linux-x64-musl": "4.38.0", - "@rollup/rollup-win32-arm64-msvc": "4.38.0", - "@rollup/rollup-win32-ia32-msvc": "4.38.0", - "@rollup/rollup-win32-x64-msvc": "4.38.0", + "@rollup/rollup-android-arm-eabi": "4.52.2", + "@rollup/rollup-android-arm64": "4.52.2", + "@rollup/rollup-darwin-arm64": "4.52.2", + "@rollup/rollup-darwin-x64": "4.52.2", + "@rollup/rollup-freebsd-arm64": "4.52.2", + "@rollup/rollup-freebsd-x64": "4.52.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.52.2", + "@rollup/rollup-linux-arm-musleabihf": "4.52.2", + "@rollup/rollup-linux-arm64-gnu": "4.52.2", + "@rollup/rollup-linux-arm64-musl": "4.52.2", + "@rollup/rollup-linux-loong64-gnu": "4.52.2", + "@rollup/rollup-linux-ppc64-gnu": "4.52.2", + "@rollup/rollup-linux-riscv64-gnu": "4.52.2", + "@rollup/rollup-linux-riscv64-musl": "4.52.2", + "@rollup/rollup-linux-s390x-gnu": "4.52.2", + "@rollup/rollup-linux-x64-gnu": "4.52.2", + "@rollup/rollup-linux-x64-musl": "4.52.2", + "@rollup/rollup-openharmony-arm64": "4.52.2", + "@rollup/rollup-win32-arm64-msvc": "4.52.2", + "@rollup/rollup-win32-ia32-msvc": "4.52.2", + "@rollup/rollup-win32-x64-gnu": "4.52.2", + "@rollup/rollup-win32-x64-msvc": "4.52.2", "fsevents": "~2.3.2" } }, @@ -3385,26 +4194,24 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "queue-microtask": "^1.2.2" } }, "node_modules/scheduler": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", - "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", - "dependencies": { - "loose-envify": "^1.1.0" - } + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", + "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==", + "license": "MIT", + "peer": true }, "node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -3412,29 +4219,12 @@ "node": ">=10" } }, - "node_modules/semver/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, + "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" }, @@ -3447,17 +4237,18 @@ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, + "node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "license": "BSD-3-Clause", "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, "node_modules/source-map-js": { @@ -3471,9 +4262,9 @@ } }, "node_modules/sql-formatter": { - "version": "15.5.2", - "resolved": "https://registry.npmjs.org/sql-formatter/-/sql-formatter-15.5.2.tgz", - "integrity": "sha512-+9xZgiv1DP/c7GxkkBUHRZOf4j35gquVdwEm0rg16qKRYeFkv1+/vEeO13fsUbbz06KUotIyASJ+hyau8LM8Kg==", + "version": "15.6.9", + "resolved": "https://registry.npmjs.org/sql-formatter/-/sql-formatter-15.6.9.tgz", + "integrity": "sha512-r9VKnkRfKW7jbhTgytwbM+JqmFclQYN9L58Z3UTktuy9V1f1Y+rGK3t70Truh2wIOJzvZkzobAQ2PwGjjXsr6Q==", "license": "MIT", "dependencies": { "argparse": "^2.0.1", @@ -3486,37 +4277,100 @@ "node_modules/state-local": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/state-local/-/state-local-1.0.7.tgz", - "integrity": "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==" + "integrity": "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==", + "license": "MIT" + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/stylis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==", + "license": "MIT" + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { - "ansi-regex": "^5.0.1" + "has-flag": "^4.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, "engines": { - "node": ">=8" + "node": ">=12.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } } }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } }, "node_modules/to-regex-range": { "version": "5.0.1", @@ -3532,15 +4386,16 @@ } }, "node_modules/ts-api-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", - "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", "dev": true, + "license": "MIT", "engines": { - "node": ">=16" + "node": ">=18.12" }, "peerDependencies": { - "typescript": ">=4.2.0" + "typescript": ">=4.8.4" } }, "node_modules/type-check": { @@ -3548,6 +4403,7 @@ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, + "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1" }, @@ -3555,23 +4411,12 @@ "node": ">= 0.8.0" } }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/typescript": { - "version": "5.4.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.4.tgz", - "integrity": "sha512-dGE2Vv8cpVvw28v8HCPqyb08EzbBURxDpuhJvTrusShUfGnhHBafDsLdS1EhhxyL6BJQE+2cT3dDPAv+MQ6oLw==", + "version": "5.9.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", + "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", "dev": true, + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -3580,12 +4425,6 @@ "node": ">=14.17" } }, - "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "devOptional": true - }, "node_modules/update-browserslist-db": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", @@ -3622,10 +4461,20 @@ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" } }, + "node_modules/use-sync-external-store": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", + "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", @@ -3639,6 +4488,7 @@ "version": "6.2.13", "resolved": "https://registry.npmjs.org/uuidv4/-/uuidv4-6.2.13.tgz", "integrity": "sha512-AXyzMjazYB3ovL3q051VLH06Ixj//Knx7QnUSi1T//Ie3io6CpsPu9nVMOx5MoLWh6xV0B9J0hIaxungxXUbPQ==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", "license": "MIT", "dependencies": { "@types/uuid": "8.3.4", @@ -3646,21 +4496,24 @@ } }, "node_modules/vite": { - "version": "6.2.4", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.4.tgz", - "integrity": "sha512-veHMSew8CcRzhL5o8ONjy8gkfmFJAd5Ac16oxBUjlwgX3Gq2Wqr+qNC3TjPIpy7TPV/KporLga5GT9HqdrCizw==", + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.7.tgz", + "integrity": "sha512-VbA8ScMvAISJNJVbRDTJdCwqQoAareR/wutevKanhR2/1EkoXVZVkkORaYm/tNVCjP/UDTKtcw3bAkwOUdedmA==", "dev": true, "license": "MIT", "dependencies": { "esbuild": "^0.25.0", - "postcss": "^8.5.3", - "rollup": "^4.30.1" + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" }, "bin": { "vite": "bin/vite.js" }, "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + "node": "^20.19.0 || >=22.12.0" }, "funding": { "url": "https://github.com/vitejs/vite?sponsor=1" @@ -3669,14 +4522,14 @@ "fsevents": "~2.3.3" }, "peerDependencies": { - "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", - "less": "*", + "less": "^4.0.0", "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" @@ -3717,11 +4570,43 @@ } } }, + "node_modules/vite/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -3732,11 +4617,15 @@ "node": ">= 8" } }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } }, "node_modules/yallist": { "version": "3.1.1", @@ -3750,6 +4639,7 @@ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, diff --git a/precise/package.json b/precise/package.json index 7b7045a..82bf689 100644 --- a/precise/package.json +++ b/precise/package.json @@ -1,8 +1,30 @@ { - "name": "precise", - "homepage": ".", - "private": true, - "version": "0.0.0", + "name": "trino-query-ui", + "description": "Trino Query Editor react component", + "version": "0.0.1", + "author": { + "name": "Trino contributors", + "email": "general@trino.io", + "url": "https://github.com/trinodb/trino-query-ui/graphs/contributors" + }, + "keywords": [ + "trino", + "trinodb", + "react" + ], + "repository": { + "type": "git", + "url": "https://github.com/trinodb/trino-query-ui.git" + }, + "homepage": "https://trinodb.github.io/trino-query-ui", + "bugs": { + "url": "https://github.com/trinodb/trino-query-ui/issues" + }, + "main": "dist/index.js", + "license": "Apache-2.0", + "files": [ + "dist" + ], "type": "module", "scripts": { "dev": "vite", @@ -18,31 +40,37 @@ "antlr4ng": "antlr4ng -visitor -listener -Dlanguage=TypeScript -o src/generated/lexer/SqlBase.g4 trino/SqlBase.g4" }, "dependencies": { - "@monaco-editor/react": "^4.6.0", - "antlr4-c3": "^3.4.1", - "antlr4ng": "^3.0.4", - "lucide-react": "^0.460.0", - "precise": "file:", - "prettier": "^3.5.3", - "react": "^18.2.0", + "@emotion/react": "^11.14.0", + "@emotion/styled": "^11.14.1", + "@monaco-editor/react": "^4.7.0", + "@mui/icons-material": "^7.3.2", + "@mui/material": "^7.3.2", + "@mui/x-data-grid": "^8.14.0", + "@mui/x-tree-view": "^8.13.1", + "antlr4-c3": "^3.4.4", + "antlr4ng": "^3.0.16", + "lucide-react": "^0.544.0", + "prettier": "^3.6.2", "react-dnd": "^16.0.1", "react-dnd-html5-backend": "^16.0.1", - "react-dom": "^18.2.0", - "sql-formatter": "^15.5.2", + "sql-formatter": "^15.6.9", "uuidv4": "^6.2.13" }, "devDependencies": { - "@types/http-proxy-middleware": "^1.0.0", - "@types/react": "^18.2.66", - "@types/react-dom": "^18.2.22", - "@typescript-eslint/eslint-plugin": "^7.2.0", - "@typescript-eslint/parser": "^7.2.0", - "@vitejs/plugin-react": "^4.2.1", + "@types/react": "^19.1.13", + "@types/react-dom": "^19.1.9", + "@typescript-eslint/eslint-plugin": "^8.44.1", + "@typescript-eslint/parser": "^8.44.1", + "@vitejs/plugin-react": "^5.0.3", "antlr4ng-cli": "^2.0.0", - "eslint": "^8.57.0", - "eslint-plugin-react-hooks": "^4.6.0", - "eslint-plugin-react-refresh": "^0.4.6", - "typescript": "^5.2.2", - "vite": "^6.2.4" + "eslint": "^9.36.0", + "eslint-plugin-react-hooks": "^5.2.0", + "eslint-plugin-react-refresh": "^0.4.21", + "typescript": "^5.9.2", + "vite": "^7.1.7" + }, + "peerDependencies": { + "react": "^19.1.1", + "react-dom": "^19.1.1" } } diff --git a/precise/src/App.tsx b/precise/src/App.tsx deleted file mode 100644 index 29fecdf..0000000 --- a/precise/src/App.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import QueryApp from './QueryApp' - -// for now this is a defacto Tab, but we will treat this tab more as a page in the future -function App() { - return ( -
- -
- ) -} - -export default App diff --git a/precise/src/QueryApp.tsx b/precise/src/QueryApp.tsx deleted file mode 100644 index 5a58314..0000000 --- a/precise/src/QueryApp.tsx +++ /dev/null @@ -1,114 +0,0 @@ -import React from 'react' -import QueryCell from './QueryCell' -import Queries from './schema/Queries' -import CatalogViewer from './controls/catalog_viewer/CatalogViewer' -import './style/layout.css' -import './style/components.css' - -interface QueryAppProps {} - -interface QueryAppState { - queries: Queries -} - -class QueryApp extends React.Component { - constructor(props: QueryAppProps) { - super(props) - - this.state = { - queries: new Queries(), - } - } - - setQueryContent = (query: string, catalog?: string, schema?: string) => { - const currentQuery = this.state.queries.getCurrentQuery() - const updates: any = {} - - if (query) { - updates.query = query - } - - if (catalog) { - updates.catalog = catalog - } - - if (schema) { - updates.schema = schema - } - - this.state.queries.updateQuery(currentQuery.id, updates) - } - - appendQueryContent = (query: string, catalog?: string, schema?: string) => { - const currentQuery = this.state.queries.getCurrentQuery() - const updates: any = {} - - if (query) { - // Append to existing query, adding newlines as needed - const existingQuery = currentQuery.query || '' - const separator = existingQuery.trim() === '' ? '' : '\n\n' - updates.query = existingQuery + separator + query - } - - if (catalog) { - updates.catalog = catalog - } - - if (schema) { - updates.schema = schema - } - - this.state.queries.updateQuery(currentQuery.id, updates) - } - - render() { - return ( -
-
-
-
-
-
- -
-
- - - -
-
-
- -
-
-
-
- ) - } -} - -export default QueryApp diff --git a/precise/src/QueryCell.tsx b/precise/src/QueryCell.tsx index ee0506f..e1fb7e8 100644 --- a/precise/src/QueryCell.tsx +++ b/precise/src/QueryCell.tsx @@ -1,12 +1,19 @@ -import React from 'react' -import QueryEditor from './QueryEditor' +import React, { ReactNode } from 'react' +import { Box, Divider, IconButton, Stack, TextField, Toolbar, Typography } from '@mui/material' +import type { TextFieldProps } from '@mui/material/TextField' +import type { TypographyProps } from '@mui/material/Typography' +import MenuIcon from '@mui/icons-material/Menu' +import PlayCircleOutlinedIcon from '@mui/icons-material/PlayCircleOutlined' +import StopCircleOutlinedIcon from '@mui/icons-material/StopCircleOutlined' +import UnfoldLessIcon from '@mui/icons-material/UnfoldLess' +import UnfoldMoreIcon from '@mui/icons-material/UnfoldMore' +import QueryEditorPane from './QueryEditorPane' import ResultSet from './ResultSet' import Queries from './schema/Queries' import QueryInfo from './schema/QueryInfo' import AsyncTrinoClient from './AsyncTrinoClient' -import { Play, StopCircle, Link, Plus, FileEdit, MinusSquare, PlusSquare } from 'lucide-react' -import './style/components.css' -import './style/query-editor.css' + +const TOOLBAR_HEIGHT = 64 interface QueryCellState { results: any[] @@ -15,15 +22,22 @@ interface QueryCellState { errorMessage: string currentQuery: QueryInfo runningQuery: QueryInfo | undefined + editingTitle: boolean + editingCatalog: boolean + editingSchema: boolean + editorCollapsed: boolean } interface QueryCellProps { queries: Queries + drawerOpen: boolean + height: number + onDrawerToggle: () => void + theme?: string } class QueryCell extends React.Component { private queryRunner: AsyncTrinoClient - private isQueryCollapsed: boolean = false constructor(props: QueryCellProps) { super(props) @@ -34,6 +48,10 @@ class QueryCell extends React.Component { errorMessage: '', currentQuery: this.props.queries.getCurrentQuery(), runningQuery: undefined, + editingTitle: false, + editingCatalog: false, + editingSchema: false, + editorCollapsed: false, } this.queryRunner = new AsyncTrinoClient() this.setupQueryRunner() @@ -50,13 +68,19 @@ class QueryCell extends React.Component { shouldComponentUpdate(nextProps: QueryCellProps, nextState: QueryCellState) { // Only update if the ResultSet-related props have changed return ( + this.props.drawerOpen !== nextProps.drawerOpen || + this.props.height !== nextProps.height || this.state.results !== nextState.results || this.state.columns !== nextState.columns || this.state.response !== nextState.response || this.state.errorMessage !== nextState.errorMessage || this.state.runningQuery !== nextState.runningQuery || this.state.currentQuery !== nextState.currentQuery || - this.state.currentQuery.title !== nextState.currentQuery.title + this.state.currentQuery.title !== nextState.currentQuery.title || + this.state.editingTitle !== nextState.editingTitle || + this.state.editingCatalog !== nextState.editingCatalog || + this.state.editingSchema !== nextState.editingSchema || + this.state.editorCollapsed !== nextState.editorCollapsed ) } @@ -109,6 +133,14 @@ class QueryCell extends React.Component { this.props.queries.updateQuery(this.state.currentQuery.id, { title: title }) } + handleCatalogChange = (catalog: string) => { + this.props.queries.updateQuery(this.state.currentQuery.id, { catalog: catalog }) + } + + handleSchemaChange = (schema: string) => { + this.props.queries.updateQuery(this.state.currentQuery.id, { schema: schema }) + } + ClearResults() { this.setState({ results: [], columns: [], errorMessage: '' }) } @@ -132,11 +164,63 @@ class QueryCell extends React.Component { } toggleQueryCollapse = () => { - const queryEditor = document.getElementById('query-editor') - if (queryEditor) { - this.isQueryCollapsed = !this.isQueryCollapsed - queryEditor.style.display = this.isQueryCollapsed ? 'none' : 'block' + this.setState({ editorCollapsed: !this.state.editorCollapsed }) + } + + private renderEditableTextField( + key: 'editingTitle' | 'editingCatalog' | 'editingSchema', + value: string | undefined, + options: { + typographyProps?: TypographyProps + textFieldProps?: TextFieldProps + displayContent?: ReactNode + } = {} + ) { + const { typographyProps = {}, textFieldProps = {}, displayContent } = options + const isEditing = this.state[key] + + if (isEditing) { + const { onChange, onKeyDown, onBlur, autoFocus, ...restTextFieldProps } = textFieldProps + + return ( + { + onChange?.(event) + }} + onKeyDown={(event) => { + onKeyDown?.(event) + if (!event.defaultPrevented && (event.key === 'Enter' || event.key === 'Escape')) { + this.setState({ [key]: false } as Pick) + } + }} + onBlur={(event) => { + onBlur?.(event) + this.setState({ [key]: false } as Pick) + }} + autoFocus={autoFocus ?? true} + /> + ) } + + const { onClick, ...restTypographyProps } = typographyProps + + return ( + { + onClick?.(event) + if (!event.defaultPrevented) { + this.setState({ [key]: true } as Pick) + } + }} + > + {displayContent ?? value} + + ) } render() { @@ -146,123 +230,122 @@ class QueryCell extends React.Component { response.stats !== undefined && (response.stats.state === 'RUNNING' || response.stats.state === 'QUEUED') + const availablePanelHeight = Math.max(this.props.height - TOOLBAR_HEIGHT, 0) + const resultSetHeight = this.state.editorCollapsed ? availablePanelHeight : availablePanelHeight / 2 + return ( - <> -
-
- - this.handleTitleChange(e.target.value)} - value={currentQuery.title} - /> - - this.props.queries.updateQuery(this.state.currentQuery.id, { catalog: e.target.value }) - } - value={currentQuery.catalog ?? ''} - /> - - this.props.queries.updateQuery(this.state.currentQuery.id, { schema: e.target.value }) - } - value={currentQuery.schema ?? ''} - /> - -
- -
- -
- -
-
-
- + + + + + this.Execute()} + > + {!isQueryRunning ? : } + + {this.renderEditableTextField('editingTitle', currentQuery.title, { + typographyProps: { + variant: 'h6', + sx: { ml: 2 }, + }, + textFieldProps: { + sx: { maxWidth: 200 }, + onChange: (event) => this.handleTitleChange(event.target.value), + }, + })} + + + + + Catalog: + + {this.renderEditableTextField('editingCatalog', currentQuery.catalog ?? '', { + typographyProps: { + sx: { ml: 2, maxWidth: 200, fontFamily: 'monospace' }, + noWrap: true, + }, + textFieldProps: { + sx: { + maxWidth: 200, + '& .MuiInputBase-input': { fontFamily: 'monospace' }, + }, + onChange: (event) => this.handleCatalogChange(event.target.value), + }, + displayContent: + currentQuery.catalog && currentQuery.catalog.length > 0 ? ( + currentQuery.catalog + ) : ( + + <no-catalog> + + ), + })} + + + + + Schema: + + {this.renderEditableTextField('editingSchema', currentQuery.schema ?? '', { + typographyProps: { + sx: { ml: 2, maxWidth: 200, fontFamily: 'monospace' }, + noWrap: true, + }, + textFieldProps: { + sx: { + maxWidth: 200, + '& .MuiInputBase-input': { fontFamily: 'monospace' }, + }, + onChange: (event) => this.handleSchemaChange(event.target.value), + }, + displayContent: + currentQuery.schema && currentQuery.schema.length > 0 ? ( + currentQuery.schema + ) : ( + + <no-schema> + + ), + })} + + + + {this.state.editorCollapsed ? : } + + + + + {}} onExecute={() => this.Execute()} queries={this.props.queries} catalog={currentQuery.catalog} schema={currentQuery.schema} + theme={this.props.theme} + maxHeight={availablePanelHeight} /> -
-
- this.ClearResults()} - /> -
- + {this.props.theme != 'dark' && } + + this.ClearResults()} + /> + ) } } diff --git a/precise/src/QueryEditor.tsx b/precise/src/QueryEditor.tsx index e392fa6..2bad7a7 100644 --- a/precise/src/QueryEditor.tsx +++ b/precise/src/QueryEditor.tsx @@ -1,927 +1,208 @@ -import React from 'react' -import Editor from '@monaco-editor/react' -import * as monaco from 'monaco-editor/esm/vs/editor/editor.api' +import React, { useRef, useState } from 'react' +import { styled } from '@mui/material/styles' +import { Box, Drawer, useMediaQuery } from '@mui/material' +import CssBaseline from '@mui/material/CssBaseline' +import MuiAppBar, { AppBarProps as MuiAppBarProps } from '@mui/material/AppBar' +import { ThemeProvider } from '@mui/material/styles' +import QueryCell from './QueryCell' +import { darkTheme, lightTheme } from './theme' import Queries from './schema/Queries' import QueryInfo from './schema/QueryInfo' -import EnterpriseTabs from './controls/tabs/EnterpriseTabs' -import * as editor_api from 'monaco-editor/esm/vs/editor/editor.api' -import * as c3 from 'antlr4-c3' -import { CharStream, CommonTokenStream, TerminalNode, ParseTree, ParserRuleContext } from 'antlr4ng' -import { TableNameContext } from './generated/lexer/SqlBase.g4/SqlBaseParser' -import { SqlBaseLexer } from './generated/lexer/SqlBase.g4/SqlBaseLexer' -import { SqlBaseParser } from './generated/lexer/SqlBase.g4/SqlBaseParser' -import SqlBaseErrorListener from './sql/SqlBaseErrorListener' -import SqlBaseListenerImpl from './sql/SqlBaseListenerImpl' -import StatementDescriptor from './sql/StatementDescriptor' -import SchemaProvider from './sql/SchemaProvider' -import TableReference from './schema/TableReference' -import Table from './schema/Table' -import Column from './schema/Column' -import NamedQuery from './sql/NamedQuery' -import { tokenMap } from './sql/TokenMap' -import SubstitutionEditor from './SubstitutionEditor' -import './style/query-editor.css' -import { format } from 'sql-formatter' -import { Code, Maximize2, Minimize2 } from 'lucide-react' +import CatalogViewer from './controls/catalog_viewer/CatalogViewer' -const TRINO_SQL_LANGUAGE = 'trinosql' - -interface QueryEditorProps { - queries: Queries - onQueryChange: (query: string) => void - onSelectChange: (selectedText: string) => void - onExecute: () => void - catalog?: string - schema?: string -} - -interface QueryEditorState { - currentQuery: QueryInfo | null - substitutions: Record - isMaximized: boolean - height: string - width: string -} - -// create a private class that extends CompletionItem -// this class will be used to create the completion items -// for the monaco editor -class CompletionItemImpl implements editor_api.languages.CompletionItem { - label: string - kind: editor_api.languages.CompletionItemKind - tags?: readonly editor_api.languages.CompletionItemTag[] | undefined - detail?: string | undefined - sortText?: string | undefined - filterText?: string | undefined - preselect?: boolean | undefined - insertText: string - insertTextRules?: editor_api.languages.CompletionItemInsertTextRule | undefined - range: editor_api.IRange | editor_api.languages.CompletionItemRanges - commitCharacters?: string[] | undefined - additionalTextEdits?: editor_api.editor.ISingleEditOperation[] | undefined - command?: editor_api.languages.Command | undefined - - constructor( - label: string, - kind: editor_api.languages.CompletionItemKind, - insertText: string, - insertTextRules: editor_api.languages.CompletionItemInsertTextRule, - range: editor_api.IRange | editor_api.languages.CompletionItemRanges - ) { - this.label = label - this.kind = kind - this.insertText = insertText - this.insertTextRules = insertTextRules - this.preselect = false - // single line - this.range = range - } +interface IQueryEditor { + height: number + theme?: 'dark' | 'light' + enableCatalogSearchColumns?: boolean } -class CustomTokenizerState implements monaco.languages.IState { - clone(): monaco.languages.IState { - return new CustomTokenizerState() - } +const DRAWER_WIDTH = 260 + +const Main = styled('main', { shouldForwardProp: (prop) => prop !== 'open' })<{ + open?: boolean +}>(({ theme }) => ({ + flexGrow: 1, + padding: theme.spacing(3), + transition: theme.transitions.create('margin', { + easing: theme.transitions.easing.sharp, + duration: theme.transitions.duration.leavingScreen, + }), + marginLeft: 0, + variants: [ + { + props: ({ open }) => open, + style: { + transition: theme.transitions.create('margin', { + easing: theme.transitions.easing.easeOut, + duration: theme.transitions.duration.enteringScreen, + }), + marginLeft: `${DRAWER_WIDTH}px`, + }, + }, + ], +})) - equals(other: monaco.languages.IState): boolean { - return other instanceof CustomTokenizerState - } +interface AppBarProps extends MuiAppBarProps { + open?: boolean } -class QueryEditor extends React.Component { - private editorRef: monaco.editor.IStandaloneCodeEditor | null = null - private isRunningParse: boolean = false - private updateCounter: number = 0 - private parseCancelToken: { cancel: boolean } = { cancel: false } - private lastCompletionItemsPosition: monaco.Position | undefined = undefined - private completionItems: monaco.languages.CompletionItem[] = [] - - openModel: any = null - decorations: any = null - state: QueryEditorState - - constructor(props: QueryEditorProps) { - super(props) - this.state = { - currentQuery: props.queries.getCurrentQuery(), - substitutions: {}, - isMaximized: false, - height: '40vh', - width: '100%', - } - } - - setEditorRef = (editor: monaco.editor.IStandaloneCodeEditor) => { - this.editorRef = editor - } - - componentDidMount() { - this.props.queries.addChangeListener(this.handleQueriesChange) - } - - componentWillUnmount() { - this.props.queries.removeChangeListener(this.handleQueriesChange) - } - - handleQueriesChange = () => { - this.setState({ - currentQuery: this.props.queries.getCurrentQuery(), - }) - } - - handleTabChange = (queryId: string) => { - this.props.queries.setCurrentQuery(queryId) - if (this.editorRef) { - const model = monaco.editor.getModel(monaco.Uri.parse(`file:///${queryId}`)) - if (model) { - this.editorRef.setModel(model) - } - } - } - - handleTabSelectAndPromote = (queryId: string) => { - this.props.queries.moveQueryToFront(queryId) - this.props.queries.setCurrentQuery(queryId) - } - - handleTabCreate = () => { - const newQuery = this.props.queries.addQuery(false, 'New Query') - monaco.editor.createModel('', TRINO_SQL_LANGUAGE, monaco.Uri.parse(`file:///${newQuery.id}`)) - this.props.queries.setCurrentQuery(newQuery.id) - return newQuery.id - } - - handleTabClose = (id: string) => { - this.props.queries.deleteQuery(id) - const model = monaco.editor.getModel(monaco.Uri.parse(`file:///${id}`)) - if (model) { - model.dispose() - } - } - - handleTabRename = (id: string, newTitle: string) => { - this.props.queries.updateQuery(id, { title: newTitle }) - } - - handleEditorChange = (newQuery: string | undefined) => { - if (newQuery !== undefined && this.state.currentQuery) { - this.props.queries.updateQuery(this.state.currentQuery.id, { query: newQuery }) - this.props.onQueryChange(newQuery) +const AppBar = styled(MuiAppBar, { + shouldForwardProp: (prop) => prop !== 'open', +})(({ theme }) => ({ + position: 'absolute', + boxShadow: 'none', + borderBottom: `1px solid ${theme.palette.divider}`, + transition: theme.transitions.create(['margin', 'width'], { + easing: theme.transitions.easing.sharp, + duration: theme.transitions.duration.leavingScreen, + }), + variants: [ + { + props: ({ open }) => open, + style: { + width: `calc(100% - ${DRAWER_WIDTH}px)`, + marginLeft: `${DRAWER_WIDTH}px`, + transition: theme.transitions.create(['margin', 'width'], { + easing: theme.transitions.easing.easeOut, + duration: theme.transitions.duration.enteringScreen, + }), + }, + }, + ], +})) + +export const QueryEditor = ({ height, theme, enableCatalogSearchColumns }: IQueryEditor) => { + const [queries, setQueries] = useState(() => new Queries()) + const [drawerOpen, setDrawerOpen] = useState(true) + const [queryRunning, setQueryRunning] = useState(false) + const [currentQuery, setCurrentQuery] = useState(queries.getCurrentQuery()) + const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)') + const containerRef = useRef(null) + + const muiThemeToUse = () => { + if (theme === 'dark') { + return darkTheme + } else if (theme === 'light') { + return lightTheme + } else if (prefersDarkMode) { + return darkTheme + } else { + return lightTheme } } - handleSubstitutionChange = (newSubstitutions: Record) => { - this.setState({ substitutions: newSubstitutions }) - } - - toggleMaximize = () => { - this.setState((prevState) => ({ - isMaximized: !prevState.isMaximized, - // 2.5 em for the tab bar, 3em for the substitution editor, 3em for the brand bar - height: !prevState.isMaximized ? 'calc(100vh - 2.5em - 3em - 3.5em)' : '40vh', - width: '100%', - })) - } - - // method to get contents of react editor - getContent() { - return this.openModel.getValue() - } + const applyQueryUpdates = (updates: Partial) => { + const activeQuery = queries.getCurrentQuery() - async parseAndDecoratePromiseAsync(monaco: any, editor: any, waitForUserToStopTyping: number): Promise { - if (this.isRunningParse) { - //console.error("cancelled parsing:" + this.isRunningParse); - return false + if (!activeQuery) { + return } - this.isRunningParse = true - this.parseCancelToken.cancel = false - - try { - let lastUpdateCounter = 0 - - // Wait for the user to stop typing before parsing - do { - await new Promise((resolve, reject) => { - setTimeout(() => { - this.parseCancelToken.cancel ? reject(new Error('Parsing cancelled')) : resolve() - }, waitForUserToStopTyping) - }) - lastUpdateCounter = this.updateCounter - } while (lastUpdateCounter !== this.updateCounter) - - if (this.parseCancelToken.cancel) { - //console.error("cancelled parsing"); - return false - } - - // Call sync method - return this.parseAndDecoratePromise(monaco, editor, lastUpdateCounter) - } catch (error) { - //console.error(error); - return false - } finally { - this.isRunningParse = false - //console.error("end parsing:" + this.isRunningParse); - } + queries.updateQuery(activeQuery.id, updates) + setCurrentQuery((prev) => ({ ...prev, ...updates })) } - // Takes the editor and parses the text, then decorates the editor with errors, autocomplete, and special syntax highlighting - parseAndDecoratePromise(monaco: any, editor: any, lastUpdateCounter: number): boolean { - const newValue: string = editor.getValue() - const lines: string[] = newValue.split('\n') - const caretPosition: editor_api.Position = editor.getPosition() - - // Gather information about the cursor position - let currentWord = '' - const currentLine: string = lines[caretPosition.lineNumber - 1] - // note: column is 1 indexed, so current position is - 1, previous character is - 2 - const isCursorSurroundedBySpaces = - currentLine[caretPosition.column - 2] == ' ' && - (currentLine[caretPosition.column - 1] == ' ' || caretPosition.column == currentLine.length + 1) - let startWordColumn = caretPosition.column - let endWord = caretPosition.column - 1 - // get characters before the current word - // The cursor position after typing a word is at the end of the word, like this: `word|` - // So: - start -1 to get the last character of the word to the left - // - then -1 because the column is 1 indexed - for (let i = caretPosition.column - 1; i >= 1; i--) { - if (currentLine[i - 1] == ' ' || currentLine[i - 1] == ',') { - break - } - currentWord = currentLine[i - 1] + currentWord - startWordColumn = i - } - - // get characters after the current word - for (let i = caretPosition.column; i < currentLine.length; i++) { - if (currentLine[i - 1] == ' ' || currentLine[i - 1] == ',') { - break - } - currentWord += currentLine[i - 1] - endWord = i - } - - // In parseAndDecoratePromise, after calculating currentWord: - console.log('Current word being parsed:', currentWord) - console.log('Cursor position:', caretPosition.lineNumber, caretPosition.column) - console.log('Word bounds:', startWordColumn, 'to', endWord) - - const inputStream = CharStream.fromString(newValue) - const lexer = new SqlBaseLexer(inputStream) - const tokenStream = new CommonTokenStream(lexer) - const parser = new SqlBaseParser(tokenStream) - - // Pass the current catalog and schema to the listener - const listener = new SqlBaseListenerImpl(this.props.catalog, this.props.schema) - - parser.addParseListener(listener) - // Remove default error listeners for SQL and add our custom one - parser.removeErrorListeners() - const errors: SqlBaseErrorListener = new SqlBaseErrorListener() - parser.addErrorListener(errors) - // Build a parsed structure for a single statement - const tree = parser.singleStatement() - - let currentTreePosition: any = undefined - let currentTreeIndex: number = 0 - - let statements = listener.statements - let namedQueries = listener.namedQueries - currentTreePosition = this.parseTreeFromPosition(tree, caretPosition.column, caretPosition.lineNumber) - if (statements.length == 0 && currentTreePosition == undefined) { - // reconstruct input inserting an underscore at the cursor position - const phantomKeyword: string = 'i' - const newLine = - currentLine.substring(0, caretPosition.column - 1) + - phantomKeyword + - currentLine.substring(caretPosition.column - 1) - const newText = - lines.slice(0, caretPosition.lineNumber - 1).join('\n') + - newLine + - (lines.length > caretPosition.lineNumber ? '\n' + lines.slice(caretPosition.lineNumber).join('\n') : '') - - const inputStreamWithChar = CharStream.fromString(newText) - const lexerWithChar = new SqlBaseLexer(inputStreamWithChar) - const tokenStreamWithChar = new CommonTokenStream(lexerWithChar) - const parserWithChar = new SqlBaseParser(tokenStreamWithChar) - const listenerWithChar = new SqlBaseListenerImpl(this.props.catalog, this.props.schema) - parserWithChar.addParseListener(listenerWithChar) - const treeWithChar = parserWithChar.singleStatement() - currentTreePosition = this.parseTreeFromPosition( - treeWithChar, - caretPosition.column - 1, - caretPosition.lineNumber, - '' - ) - statements = listenerWithChar.statements - namedQueries = listenerWithChar.namedQueries - //console.log("created phantom"); - } else { - // symbol covering caret position - currentTreePosition = this.parseTreeFromPosition(tree, caretPosition.column, caretPosition.lineNumber) - } - - if (currentTreePosition != undefined && currentTreePosition.symbol != undefined) { - currentTreeIndex = currentTreePosition.symbol.tokenIndex - //console.log("found symbol at " + currentTreePosition.symbol.tokenIndex); - } else { - currentTreeIndex = currentTreePosition.ruleIndex - } - - const markers = errors.getMarkers() - monaco.editor.setModelMarkers(editor.getModel(), 'owner', markers) + const setQueryContent = (query: string, catalog?: string, schema?: string) => { + const updates: Partial = {} - // Add decorations for table names - editor.removeDecorationsCollection - if (this.decorations) { - this.decorations.clear() + if (query) { + updates.query = query } - this.decorations = editor.createDecorationsCollection(listener.getDecorations()) - // Autocomplete handling happend after the parse - // Verify no typing - if (this.updateCounter != lastUpdateCounter) { - return false + if (catalog) { + updates.catalog = catalog } - const core = new c3.CodeCompletionCore(parser) - core.showDebugOutput = false // logging debug info from parser - - // create a set of rules that should be used for code completion - const ruleSet = new Set([SqlBaseParser.RULE_selectItem]) - core.preferredRules = ruleSet - - const candidates = core.collectCandidates(currentTreeIndex) - - this.generateLexerAutocompleteCandidates( - lines, - parser, - startWordColumn, - endWord, - caretPosition, - monaco, - editor, - core, - candidates, - currentTreePosition, - statements, - namedQueries - ) - - this.isRunningParse = false - return true - } - - checkForParentOfContext(currentTreePosition: any, parentType: any): boolean { - let current: any = currentTreePosition - while (current) { - if (current instanceof parentType) { - return true - } - current = current.parent + if (schema) { + updates.schema = schema } - return false - } - - createCompletionItem( - match: string, - replace: string, - caretPosition: editor_api.Position, - startWordColumn: number, - endWordColumn: number - ) { - return { - label: match, - kind: editor_api.languages.CompletionItemKind.Keyword, - insertText: replace, - insertTextRules: editor_api.languages.CompletionItemInsertTextRule.None, - // Use Monaco's preferred format for ranges - range: { - startLineNumber: caretPosition.lineNumber, - startColumn: startWordColumn, - endLineNumber: caretPosition.lineNumber, - endColumn: Math.max(startWordColumn, caretPosition.column), // Use at least the cursor position - }, - } + applyQueryUpdates(updates) } - generateLexerAutocompleteCandidates( - lines: string[], - parser: SqlBaseParser, - startWordColumn: number, - endWord: number, - caretPosition: editor_api.Position, - monaco: any, - editor: any, - core: any, - candidates: any, - currentTreePosition: any, - statements: StatementDescriptor[], - namedQueries: Map - ) { - // At the beginning: - // console.log("Generating autocomplete candidates"); - // console.log("Word bounds passed:", startWordColumn, "to", endWord); - const endWordLineOffset: number = endWord + 1 - - const keywords: string[] = [] - const completionItems: CompletionItemImpl[] = [] - for (const candidate of candidates.tokens) { - //var tokenType = parser.getTokenType(candidate[0]); - let displayName = parser.vocabulary.getSymbolicName(candidate[0]) - - if (candidate[1].length > 0) { - for (const candidateId of candidate[1]) { - displayName += ' ' + parser.vocabulary.getSymbolicName(candidateId) - } - } - - if (displayName) { - completionItems.push( - this.createCompletionItem( - displayName.toLowerCase(), - displayName.toLowerCase() + ' ', - caretPosition, - startWordColumn, - startWordColumn + displayName.length - ) - ) - if (displayName.toLowerCase() == 'select') { - completionItems.push( - this.createCompletionItem( - 'select * from', - 'select * from ', - caretPosition, - startWordColumn, - endWordLineOffset - ) - ) - } - if (displayName.toLowerCase() == 'limit') { - completionItems.push( - this.createCompletionItem( - 'limit 5', - 'limit 5', - caretPosition, - startWordColumn, - endWordLineOffset - ) - ) - } - if (displayName.toLowerCase() == 'with') { - completionItems.push( - this.createCompletionItem( - 'with query as (select * from )', - 'with query as (select * from )', - caretPosition, - startWordColumn, - endWordLineOffset - ) - ) - } - } - } - - //console.log("Keyword completion items:", completionItems.length); - - // check if parent is the parser's TableNameContext - if (this.checkForParentOfContext(currentTreePosition, TableNameContext)) { - // loop through all tables in the catalog - const tableNames: string[] = SchemaProvider.getTableNameList(undefined, undefined) - for (const tableName of tableNames) { - completionItems.push( - new CompletionItemImpl( - tableName, - editor_api.languages.CompletionItemKind.Reference, - tableName, - monaco.languages.CompletionItemInsertTextRule.None, - { - startLineNumber: caretPosition.lineNumber, - startColumn: startWordColumn, - endLineNumber: caretPosition.lineNumber, - endColumn: endWordLineOffset, - } - ) - ) - } + const appendQueryContent = (query: string, catalog?: string, schema?: string) => { + const activeQuery = queries.getCurrentQuery() + const updates: Partial = {} - // add named queries - for (const [key, value] of namedQueries) { - completionItems.push( - new CompletionItemImpl( - key, - editor_api.languages.CompletionItemKind.Reference, - key, - monaco.languages.CompletionItemInsertTextRule.None, - { - startLineNumber: caretPosition.lineNumber, - startColumn: startWordColumn, - endLineNumber: caretPosition.lineNumber, - endColumn: endWordLineOffset, - } - ) - ) - } + if (query !== undefined) { + const existingQuery = activeQuery.query || '' + const separator = existingQuery.trim() === '' || query.trim() === '' ? '' : '\n\n' + updates.query = existingQuery + separator + query } - //console.log("After table names, completion items:", completionItems.length); - for (const statement of statements) { - console.log(statement) - // log location of caret vs statement position - console.log('caret: ' + caretPosition.column + ' ' + caretPosition.lineNumber) - console.log('statement start: ' + statement.start.column + ' ' + statement.start.line) - console.log('statement end: ' + statement.end.column + ' ' + statement.end.line) - - // if inside ColumnReferenceContext, we can use the table name to get the columns - if ( - (caretPosition.column >= statement.start.column && statement.start.line == caretPosition.lineNumber) || - (caretPosition.column <= statement.end.column && statement.end.line == caretPosition.lineNumber) || - (caretPosition.lineNumber > statement.start.line && caretPosition.lineNumber < statement.end.line) - ) { - console.log('Found statement') - - const tableName: string = statement.tableName - let tableReference: TableReference | undefined - if (TableReference.isFullyQualified(tableName)) { - tableReference = TableReference.fromFullyQualified(tableName) - } else if (this.props.catalog && this.props.schema) { - // Use current catalog and schema from props - tableReference = new TableReference(this.props.catalog, this.props.schema, tableName) - } - - if (tableReference) { - SchemaProvider.getTableWithCache(tableReference, (table: Table) => { - for (const column of table.getColumns()) { - completionItems.push( - new CompletionItemImpl( - column.getName(), - editor_api.languages.CompletionItemKind.Field, - column.getName(), - monaco.languages.CompletionItemInsertTextRule.None, - { - insert: { - startLineNumber: caretPosition.lineNumber, - startColumn: startWordColumn, - endLineNumber: caretPosition.lineNumber, - endColumn: endWordLineOffset, - }, - replace: { - startLineNumber: caretPosition.lineNumber, - startColumn: startWordColumn, - endLineNumber: caretPosition.lineNumber, - endColumn: endWordLineOffset, - }, - } - ) - ) - } - - const singleListOfColumnsJoinedByCommas: string = - '\n ' + - table - .getColumns() - .map((column: Column) => column.getName()) - .join('\n ,') - - completionItems.push( - new CompletionItemImpl( - singleListOfColumnsJoinedByCommas, - editor_api.languages.CompletionItemKind.Field, - singleListOfColumnsJoinedByCommas + ' ', - monaco.languages.CompletionItemInsertTextRule.None, - { - insert: { - startLineNumber: caretPosition.lineNumber, - startColumn: startWordColumn, - endLineNumber: caretPosition.lineNumber, - endColumn: endWordLineOffset, - }, - replace: { - startLineNumber: caretPosition.lineNumber, - startColumn: startWordColumn, - endLineNumber: caretPosition.lineNumber, - endColumn: endWordLineOffset, - }, - } - ) - ) - }) - } - } - } - - const selectNames: string[] = [] - for (const candidate of candidates.rules) { - switch (candidate[0]) { - case SqlBaseParser.RULE_selectItem: { - // unused - } - } - } - - // Finally combine all found lists into one for the UI. - // We do that in separate steps so that you can apply some ordering to each of your sub lists. - // Then you also can order symbols groups as a whole depending their importance. - // let candidates: string[] = []; - // candidates.push(...keywords); - // candidates.push(...functionNames); - - if (completionItems.length > 0) { - this.completionItems = completionItems - this.lastCompletionItemsPosition = caretPosition - } - - // At the very end of the method: - console.log('Final completion items:', completionItems.length) - } - - cancelParsing() { - //console.error("CANCEL"); - this.parseCancelToken.cancel = true - this.isRunningParse = false - } - - editorDidMount = (editor: monaco.editor.IStandaloneCodeEditor, monaco: typeof import('monaco-editor')) => { - this.setEditorRef(editor) - - editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter, () => { - this.props.onExecute() - }) - - editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter, () => { - // execute the query on ctrl+enter - this.props.onExecute() - }) - - editor.addAction({ - id: 'format-sql', - label: 'Format SQL', - keybindings: [monaco.KeyMod.Alt | monaco.KeyMod.Shift | monaco.KeyCode.KeyF], - contextMenuGroupId: 'modification', - contextMenuOrder: 1.5, - run: () => { - this.formatSql() - }, - }) - - // Check if the provider is already registered - if (!monaco.languages.getLanguages().some((lang: any) => lang.id === TRINO_SQL_LANGUAGE)) { - monaco.languages.register({ id: TRINO_SQL_LANGUAGE }) - - monaco.languages.setTokensProvider(TRINO_SQL_LANGUAGE, { - getInitialState: () => new CustomTokenizerState(), - tokenize: (line: any, state: any) => { - const inputStream = CharStream.fromString(line) - const lexer = new SqlBaseLexer(inputStream) - const tokenStream = new CommonTokenStream(lexer) - lexer.reset() - - const tokens = [] - let token = lexer.nextToken() - while (token.type !== SqlBaseLexer.EOF) { - tokens.push({ - startIndex: token.start, - scopes: tokenMap[token.type as keyof typeof tokenMap] || 'identifier', - }) - token = lexer.nextToken() - } - - return { tokens, endState: state } - }, - }) - - monaco.languages.registerCompletionItemProvider(TRINO_SQL_LANGUAGE, { - provideCompletionItems: async (model: any, position: any) => { - this.cancelParsing() // Cancel any ongoing parsing - const parseResult = await this.parseAndDecoratePromiseAsync(monaco, editor, 0) - if ( - this.lastCompletionItemsPosition && - this.lastCompletionItemsPosition.lineNumber == position.lineNumber && - this.lastCompletionItemsPosition.column == position.column - ) { - return { suggestions: this.completionItems } - } else { - return { suggestions: [] } // either parsing failed or the position is not the same as the last parse - } - }, - }) + if (catalog !== undefined) { + updates.catalog = catalog } - editor.onDidChangeModelContent(async (e: any) => { - this.updateCounter++ - this.handleEditorChange(editor.getValue()) - await this.parseAndDecoratePromiseAsync(monaco, editor, 200).then((result) => { - //console.log("done parsing"); - }) - }) - - editor.onDidChangeCursorSelection(() => { - const selection = editor.getSelection() - if (selection == null) { - return - } - if (selection.startLineNumber != selection.endLineNumber || selection.startColumn != selection.endColumn) { - const model = editor.getModel() - if (model) { - const selectedText = model.getValueInRange(selection) - this.props.onSelectChange(selectedText) - } - } else { - this.props.onSelectChange(editor.getValue()) - } - }) - - // init the parser once to get the initial state - this.parseAndDecoratePromiseAsync(monaco, editor, 0).then((result) => { - //console.log("done parsing"); - }) - } - - parseTreeFromPosition( - root: ParseTree, - cursorColumnOffsetZero: number, - row: number, - phantomKeyword: string = '' - ): any | undefined { - // Does the root node actually contain the position? If not, we don't need to look further. - if (root instanceof TerminalNode) { - const terminal = root as TerminalNode - const token = terminal.symbol - if (token.line != row) return undefined - //let tokenStop = token.column + (token.stop - token.start + 1); - if (cursorColumnOffsetZero >= token.column && token.text !== phantomKeyword && token.text !== '') { - // all we care about is whether it's the last token after this one starts - return terminal - } - return undefined - } else { - const context = root as ParserRuleContext - if (!context.start || !context.stop) { - // Invalid tree? - return undefined - } - - let result = undefined - if (context.children) { - let lastresult = undefined - for (const child of context.children) { - result = this.parseTreeFromPosition(child, cursorColumnOffsetZero, row, phantomKeyword) - if (result == undefined && lastresult != undefined) { - return lastresult - } - lastresult = result - } - if (result != undefined) { - return result - } - } - - if ( - context.children && - context.children.length > 1 && - context.children[0].getText() !== phantomKeyword && - context.children[0].getText() !== '' - ) { - return context.children[0] - } else { - return undefined - } + if (schema !== undefined) { + updates.schema = schema } - } - - // Format the entire SQL query - formatSql = () => { - if (this.editorRef) { - const currentValue = this.editorRef.getValue() - - try { - const config = { - indent: ' ', - uppercase: true, - linesBetweenQueries: 2, - } - const formattedSql = format(currentValue, config) - - // Replace the entire editor content with the formatted SQL - this.editorRef.setValue(formattedSql) - // Trigger a save to update the query in state - this.handleEditorChange(formattedSql) - } catch (error) { - console.error('Error formatting SQL:', error) - } - } + applyQueryUpdates(updates) } - // Format only the selected text - formatSelection = () => { - if (this.editorRef) { - const selection = this.editorRef.getSelection() - if (!selection || selection.isEmpty()) { - // No selection, format the entire query - this.formatSql() - return - } - - const model = this.editorRef.getModel() - if (model) { - const selectedText = model.getValueInRange(selection) - try { - // Format just the selected text - const config = { - indent: ' ', - uppercase: true, - linesBetweenQueries: 2, - } - const formattedSql = format(selectedText, config) + return ( + + + + - // Replace just the selected part - this.editorRef.executeEdits('format-selection', [ - { - range: selection, - text: formattedSql, - forceMoveMarkers: true, + { - this.setState({ height: newHeight }) - } - - render() { - const options = { - selectOnLineNumbers: true, - } - - const { currentQuery, isMaximized, height, width } = this.state - - return ( - <> - - -
-
-
- - -
- -
-
- - ) - } + }} + variant="persistent" + anchor="left" + open={drawerOpen} + ModalProps={{ + container: containerRef.current, + disablePortal: true, + }} + slotProps={{ + paper: { + sx: { + position: 'absolute', + display: 'flex', + flexDirection: 'column', + overflow: 'hidden', + }, + }, + }} + > + setDrawerOpen(false)} + enableSearchColumns={enableCatalogSearchColumns} + /> +
+ +
+ setDrawerOpen(true)} + theme={theme} + /> +
+
+
+ ) } export default QueryEditor diff --git a/precise/src/QueryEditorPane.tsx b/precise/src/QueryEditorPane.tsx new file mode 100644 index 0000000..31d9452 --- /dev/null +++ b/precise/src/QueryEditorPane.tsx @@ -0,0 +1,951 @@ +import React from 'react' +import { Box, Stack, Tooltip, IconButton } from '@mui/material' +import CodeIcon from '@mui/icons-material/Code' +import Maximize from '@mui/icons-material/Maximize' +import Minimize from '@mui/icons-material/Minimize' +import Editor from '@monaco-editor/react' +import * as monaco from 'monaco-editor/esm/vs/editor/editor.api' +import Queries from './schema/Queries' +import QueryInfo from './schema/QueryInfo' +import EnterpriseTabs from './controls/tabs/EnterpriseTabs' +import * as editor_api from 'monaco-editor/esm/vs/editor/editor.api' +import * as c3 from 'antlr4-c3' +import { CharStream, CommonTokenStream, TerminalNode, ParseTree, ParserRuleContext } from 'antlr4ng' +import { TableNameContext } from './generated/lexer/SqlBase.g4/SqlBaseParser' +import { SqlBaseLexer } from './generated/lexer/SqlBase.g4/SqlBaseLexer' +import { SqlBaseParser } from './generated/lexer/SqlBase.g4/SqlBaseParser' +import SqlBaseErrorListener from './sql/SqlBaseErrorListener' +import SqlBaseListenerImpl from './sql/SqlBaseListenerImpl' +import StatementDescriptor from './sql/StatementDescriptor' +import SchemaProvider from './sql/SchemaProvider' +import TableReference from './schema/TableReference' +import Table from './schema/Table' +import Column from './schema/Column' +import NamedQuery from './sql/NamedQuery' +import { tokenMap } from './sql/TokenMap' +import SubstitutionEditor from './SubstitutionEditor' +import { format } from 'sql-formatter' + +const TRINO_SQL_LANGUAGE = 'trinosql' +const TABS_HEIGHT = 64 + +interface QueryEditorPaneProps { + queries: Queries + maxHeight: number + onQueryChange: (query: string) => void + onSelectChange: (selectedText: string) => void + onExecute: () => void + catalog?: string + schema?: string + theme?: string +} + +interface QueryEditorPaneState { + currentQuery: QueryInfo | null + substitutions: Record + isMaximized: boolean + height: number + width: string +} + +// create a private class that extends CompletionItem +// this class will be used to create the completion items +// for the monaco editor +class CompletionItemImpl implements editor_api.languages.CompletionItem { + label: string + kind: editor_api.languages.CompletionItemKind + tags?: readonly editor_api.languages.CompletionItemTag[] | undefined + detail?: string | undefined + sortText?: string | undefined + filterText?: string | undefined + preselect?: boolean | undefined + insertText: string + insertTextRules?: editor_api.languages.CompletionItemInsertTextRule | undefined + range: editor_api.IRange | editor_api.languages.CompletionItemRanges + commitCharacters?: string[] | undefined + additionalTextEdits?: editor_api.editor.ISingleEditOperation[] | undefined + command?: editor_api.languages.Command | undefined + + constructor( + label: string, + kind: editor_api.languages.CompletionItemKind, + insertText: string, + insertTextRules: editor_api.languages.CompletionItemInsertTextRule, + range: editor_api.IRange | editor_api.languages.CompletionItemRanges + ) { + this.label = label + this.kind = kind + this.insertText = insertText + this.insertTextRules = insertTextRules + this.preselect = false + // single line + this.range = range + } +} + +class CustomTokenizerState implements monaco.languages.IState { + clone(): monaco.languages.IState { + return new CustomTokenizerState() + } + + equals(other: monaco.languages.IState): boolean { + return other instanceof CustomTokenizerState + } +} + +class QueryEditorPane extends React.Component { + private editorRef: monaco.editor.IStandaloneCodeEditor | null = null + private isRunningParse: boolean = false + private updateCounter: number = 0 + private parseCancelToken: { cancel: boolean } = { cancel: false } + private lastCompletionItemsPosition: monaco.Position | undefined = undefined + private completionItems: monaco.languages.CompletionItem[] = [] + + openModel: any = null + decorations: any = null + state: QueryEditorPaneState + + constructor(props: QueryEditorPaneProps) { + super(props) + this.state = { + currentQuery: props.queries.getCurrentQuery(), + substitutions: {}, + isMaximized: false, + height: this.props.maxHeight / 2, + width: '100%', + } + } + + setEditorRef = (editor: monaco.editor.IStandaloneCodeEditor) => { + this.editorRef = editor + } + + componentDidMount() { + this.props.queries.addChangeListener(this.handleQueriesChange) + } + + componentDidUpdate(prevProps: QueryEditorPaneProps) { + if (prevProps.maxHeight !== this.props.maxHeight) { + this.handleHeightChange(this.props.maxHeight) + } + } + + componentWillUnmount() { + this.props.queries.removeChangeListener(this.handleQueriesChange) + } + + handleQueriesChange = () => { + this.setState({ + currentQuery: this.props.queries.getCurrentQuery(), + }) + } + + handleTabChange = (queryId: string) => { + this.props.queries.setCurrentQuery(queryId) + if (this.editorRef) { + const model = monaco.editor.getModel(monaco.Uri.parse(`file:///${queryId}`)) + if (model) { + this.editorRef.setModel(model) + } + } + } + + handleTabSelectAndPromote = (queryId: string) => { + this.props.queries.moveQueryToFront(queryId) + this.props.queries.setCurrentQuery(queryId) + } + + handleTabCreate = () => { + const newQuery = this.props.queries.addQuery(false, 'New Query') + monaco.editor.createModel('', TRINO_SQL_LANGUAGE, monaco.Uri.parse(`file:///${newQuery.id}`)) + this.props.queries.setCurrentQuery(newQuery.id) + return newQuery.id + } + + handleTabClose = (id: string) => { + this.props.queries.deleteQuery(id) + const model = monaco.editor.getModel(monaco.Uri.parse(`file:///${id}`)) + if (model) { + model.dispose() + } + } + + handleTabRename = (id: string, newTitle: string) => { + this.props.queries.updateQuery(id, { title: newTitle }) + } + + handleEditorChange = (newQuery: string | undefined) => { + if (newQuery !== undefined && this.state.currentQuery) { + this.props.queries.updateQuery(this.state.currentQuery.id, { query: newQuery }) + this.props.onQueryChange(newQuery) + } + } + + handleSubstitutionChange = (newSubstitutions: Record) => { + this.setState({ substitutions: newSubstitutions }) + } + + toggleMaximize = () => { + this.setState((prevState) => ({ + isMaximized: !prevState.isMaximized, + height: !prevState.isMaximized ? this.props.maxHeight : this.props.maxHeight / 2, + width: '100%', + })) + } + + // method to get contents of react editor + getContent() { + return this.openModel.getValue() + } + + async parseAndDecoratePromiseAsync(monaco: any, editor: any, waitForUserToStopTyping: number): Promise { + if (this.isRunningParse) { + //console.error("cancelled parsing:" + this.isRunningParse); + return false + } + + this.isRunningParse = true + this.parseCancelToken.cancel = false + + try { + let lastUpdateCounter = 0 + + // Wait for the user to stop typing before parsing + do { + await new Promise((resolve, reject) => { + setTimeout(() => { + this.parseCancelToken.cancel ? reject(new Error('Parsing cancelled')) : resolve() + }, waitForUserToStopTyping) + }) + lastUpdateCounter = this.updateCounter + } while (lastUpdateCounter !== this.updateCounter) + + if (this.parseCancelToken.cancel) { + //console.error("cancelled parsing"); + return false + } + + // Call sync method + return this.parseAndDecoratePromise(monaco, editor, lastUpdateCounter) + } catch (error) { + //console.error(error); + return false + } finally { + this.isRunningParse = false + //console.error("end parsing:" + this.isRunningParse); + } + } + + // Takes the editor and parses the text, then decorates the editor with errors, autocomplete, and special syntax highlighting + parseAndDecoratePromise(monaco: any, editor: any, lastUpdateCounter: number): boolean { + const newValue: string = editor.getValue() + const lines: string[] = newValue.split('\n') + const caretPosition: editor_api.Position = editor.getPosition() + + // Gather information about the cursor position + let currentWord = '' + const currentLine: string = lines[caretPosition.lineNumber - 1] + // note: column is 1 indexed, so current position is - 1, previous character is - 2 + const isCursorSurroundedBySpaces = + currentLine[caretPosition.column - 2] == ' ' && + (currentLine[caretPosition.column - 1] == ' ' || caretPosition.column == currentLine.length + 1) + let startWordColumn = caretPosition.column + let endWord = caretPosition.column - 1 + // get characters before the current word + // The cursor position after typing a word is at the end of the word, like this: `word|` + // So: - start -1 to get the last character of the word to the left + // - then -1 because the column is 1 indexed + for (let i = caretPosition.column - 1; i >= 1; i--) { + if (currentLine[i - 1] == ' ' || currentLine[i - 1] == ',') { + break + } + currentWord = currentLine[i - 1] + currentWord + startWordColumn = i + } + + // get characters after the current word + for (let i = caretPosition.column; i < currentLine.length; i++) { + if (currentLine[i - 1] == ' ' || currentLine[i - 1] == ',') { + break + } + currentWord += currentLine[i - 1] + endWord = i + } + + // In parseAndDecoratePromise, after calculating currentWord: + console.log('Current word being parsed:', currentWord) + console.log('Cursor position:', caretPosition.lineNumber, caretPosition.column) + console.log('Word bounds:', startWordColumn, 'to', endWord) + + const inputStream = CharStream.fromString(newValue) + const lexer = new SqlBaseLexer(inputStream) + const tokenStream = new CommonTokenStream(lexer) + const parser = new SqlBaseParser(tokenStream) + + // Pass the current catalog and schema to the listener + const listener = new SqlBaseListenerImpl(this.props.catalog, this.props.schema) + + parser.addParseListener(listener) + // Remove default error listeners for SQL and add our custom one + parser.removeErrorListeners() + const errors: SqlBaseErrorListener = new SqlBaseErrorListener() + parser.addErrorListener(errors) + // Build a parsed structure for a single statement + const tree = parser.singleStatement() + + let currentTreePosition: any = undefined + let currentTreeIndex: number = 0 + + let statements = listener.statements + let namedQueries = listener.namedQueries + currentTreePosition = this.parseTreeFromPosition(tree, caretPosition.column, caretPosition.lineNumber) + if (statements.length == 0 && currentTreePosition == undefined) { + // reconstruct input inserting an underscore at the cursor position + const phantomKeyword: string = 'i' + const newLine = + currentLine.substring(0, caretPosition.column - 1) + + phantomKeyword + + currentLine.substring(caretPosition.column - 1) + const newText = + lines.slice(0, caretPosition.lineNumber - 1).join('\n') + + newLine + + (lines.length > caretPosition.lineNumber ? '\n' + lines.slice(caretPosition.lineNumber).join('\n') : '') + + const inputStreamWithChar = CharStream.fromString(newText) + const lexerWithChar = new SqlBaseLexer(inputStreamWithChar) + const tokenStreamWithChar = new CommonTokenStream(lexerWithChar) + const parserWithChar = new SqlBaseParser(tokenStreamWithChar) + const listenerWithChar = new SqlBaseListenerImpl(this.props.catalog, this.props.schema) + parserWithChar.addParseListener(listenerWithChar) + const treeWithChar = parserWithChar.singleStatement() + currentTreePosition = this.parseTreeFromPosition( + treeWithChar, + caretPosition.column - 1, + caretPosition.lineNumber, + '' + ) + statements = listenerWithChar.statements + namedQueries = listenerWithChar.namedQueries + //console.log("created phantom"); + } else { + // symbol covering caret position + currentTreePosition = this.parseTreeFromPosition(tree, caretPosition.column, caretPosition.lineNumber) + } + + if (currentTreePosition != undefined && currentTreePosition.symbol != undefined) { + currentTreeIndex = currentTreePosition.symbol.tokenIndex + //console.log("found symbol at " + currentTreePosition.symbol.tokenIndex); + } else { + currentTreeIndex = currentTreePosition.ruleIndex + } + + const markers = errors.getMarkers() + monaco.editor.setModelMarkers(editor.getModel(), 'owner', markers) + + // Add decorations for table names + if (this.decorations) { + this.decorations.clear() + } + this.decorations = editor.createDecorationsCollection(listener.getDecorations()) + + // Autocomplete handling happend after the parse + // Verify no typing + if (this.updateCounter != lastUpdateCounter) { + return false + } + + const core = new c3.CodeCompletionCore(parser) + core.showDebugOutput = false // logging debug info from parser + + // create a set of rules that should be used for code completion + const ruleSet = new Set([SqlBaseParser.RULE_selectItem]) + core.preferredRules = ruleSet + + const candidates = core.collectCandidates(currentTreeIndex) + + this.generateLexerAutocompleteCandidates( + lines, + parser, + startWordColumn, + endWord, + caretPosition, + monaco, + editor, + core, + candidates, + currentTreePosition, + statements, + namedQueries + ) + + this.isRunningParse = false + return true + } + + checkForParentOfContext(currentTreePosition: any, parentType: any): boolean { + let current: any = currentTreePosition + while (current) { + if (current instanceof parentType) { + return true + } + current = current.parent + } + + return false + } + + createCompletionItem( + match: string, + replace: string, + caretPosition: editor_api.Position, + startWordColumn: number, + endWordColumn: number + ) { + return { + label: match, + kind: editor_api.languages.CompletionItemKind.Keyword, + insertText: replace, + insertTextRules: editor_api.languages.CompletionItemInsertTextRule.None, + // Use Monaco's preferred format for ranges + range: { + startLineNumber: caretPosition.lineNumber, + startColumn: startWordColumn, + endLineNumber: caretPosition.lineNumber, + endColumn: Math.max(startWordColumn, caretPosition.column), // Use at least the cursor position + }, + } + } + + generateLexerAutocompleteCandidates( + lines: string[], + parser: SqlBaseParser, + startWordColumn: number, + endWord: number, + caretPosition: editor_api.Position, + monaco: any, + editor: any, + core: any, + candidates: any, + currentTreePosition: any, + statements: StatementDescriptor[], + namedQueries: Map + ) { + // At the beginning: + // console.log("Generating autocomplete candidates"); + // console.log("Word bounds passed:", startWordColumn, "to", endWord); + const endWordLineOffset: number = endWord + 1 + + const keywords: string[] = [] + const completionItems: CompletionItemImpl[] = [] + for (const candidate of candidates.tokens) { + //var tokenType = parser.getTokenType(candidate[0]); + let displayName = parser.vocabulary.getSymbolicName(candidate[0]) + + if (candidate[1].length > 0) { + for (const candidateId of candidate[1]) { + displayName += ' ' + parser.vocabulary.getSymbolicName(candidateId) + } + } + + if (displayName) { + completionItems.push( + this.createCompletionItem( + displayName.toLowerCase(), + displayName.toLowerCase() + ' ', + caretPosition, + startWordColumn, + startWordColumn + displayName.length + ) + ) + if (displayName.toLowerCase() == 'select') { + completionItems.push( + this.createCompletionItem( + 'select * from', + 'select * from ', + caretPosition, + startWordColumn, + endWordLineOffset + ) + ) + } + if (displayName.toLowerCase() == 'limit') { + completionItems.push( + this.createCompletionItem( + 'limit 5', + 'limit 5', + caretPosition, + startWordColumn, + endWordLineOffset + ) + ) + } + if (displayName.toLowerCase() == 'with') { + completionItems.push( + this.createCompletionItem( + 'with query as (select * from )', + 'with query as (select * from )', + caretPosition, + startWordColumn, + endWordLineOffset + ) + ) + } + } + } + + //console.log("Keyword completion items:", completionItems.length); + + // check if parent is the parser's TableNameContext + if (this.checkForParentOfContext(currentTreePosition, TableNameContext)) { + // loop through all tables in the catalog + const tableNames: string[] = SchemaProvider.getTableNameList(undefined, undefined) + for (const tableName of tableNames) { + completionItems.push( + new CompletionItemImpl( + tableName, + editor_api.languages.CompletionItemKind.Reference, + tableName, + monaco.languages.CompletionItemInsertTextRule.None, + { + startLineNumber: caretPosition.lineNumber, + startColumn: startWordColumn, + endLineNumber: caretPosition.lineNumber, + endColumn: endWordLineOffset, + } + ) + ) + } + + // add named queries + for (const [key, value] of namedQueries) { + completionItems.push( + new CompletionItemImpl( + key, + editor_api.languages.CompletionItemKind.Reference, + key, + monaco.languages.CompletionItemInsertTextRule.None, + { + startLineNumber: caretPosition.lineNumber, + startColumn: startWordColumn, + endLineNumber: caretPosition.lineNumber, + endColumn: endWordLineOffset, + } + ) + ) + } + } + + //console.log("After table names, completion items:", completionItems.length); + for (const statement of statements) { + console.log(statement) + // log location of caret vs statement position + console.log('caret: ' + caretPosition.column + ' ' + caretPosition.lineNumber) + console.log('statement start: ' + statement.start.column + ' ' + statement.start.line) + console.log('statement end: ' + statement.end.column + ' ' + statement.end.line) + + // if inside ColumnReferenceContext, we can use the table name to get the columns + if ( + (caretPosition.column >= statement.start.column && statement.start.line == caretPosition.lineNumber) || + (caretPosition.column <= statement.end.column && statement.end.line == caretPosition.lineNumber) || + (caretPosition.lineNumber > statement.start.line && caretPosition.lineNumber < statement.end.line) + ) { + console.log('Found statement') + + const tableName: string = statement.tableName + let tableReference: TableReference | undefined + if (TableReference.isFullyQualified(tableName)) { + tableReference = TableReference.fromFullyQualified(tableName) + } else if (this.props.catalog && this.props.schema) { + // Use current catalog and schema from props + tableReference = new TableReference(this.props.catalog, this.props.schema, tableName) + } + + if (tableReference) { + SchemaProvider.getTableWithCache(tableReference, (table: Table) => { + for (const column of table.getColumns()) { + completionItems.push( + new CompletionItemImpl( + column.getName(), + editor_api.languages.CompletionItemKind.Field, + column.getName(), + monaco.languages.CompletionItemInsertTextRule.None, + { + insert: { + startLineNumber: caretPosition.lineNumber, + startColumn: startWordColumn, + endLineNumber: caretPosition.lineNumber, + endColumn: endWordLineOffset, + }, + replace: { + startLineNumber: caretPosition.lineNumber, + startColumn: startWordColumn, + endLineNumber: caretPosition.lineNumber, + endColumn: endWordLineOffset, + }, + } + ) + ) + } + + const singleListOfColumnsJoinedByCommas: string = + '\n ' + + table + .getColumns() + .map((column: Column) => column.getName()) + .join('\n ,') + + completionItems.push( + new CompletionItemImpl( + singleListOfColumnsJoinedByCommas, + editor_api.languages.CompletionItemKind.Field, + singleListOfColumnsJoinedByCommas + ' ', + monaco.languages.CompletionItemInsertTextRule.None, + { + insert: { + startLineNumber: caretPosition.lineNumber, + startColumn: startWordColumn, + endLineNumber: caretPosition.lineNumber, + endColumn: endWordLineOffset, + }, + replace: { + startLineNumber: caretPosition.lineNumber, + startColumn: startWordColumn, + endLineNumber: caretPosition.lineNumber, + endColumn: endWordLineOffset, + }, + } + ) + ) + }) + } + } + } + + const selectNames: string[] = [] + for (const candidate of candidates.rules) { + switch (candidate[0]) { + case SqlBaseParser.RULE_selectItem: { + // unused + } + } + } + + // Finally combine all found lists into one for the UI. + // We do that in separate steps so that you can apply some ordering to each of your sub lists. + // Then you also can order symbols groups as a whole depending their importance. + // let candidates: string[] = []; + // candidates.push(...keywords); + // candidates.push(...functionNames); + + if (completionItems.length > 0) { + this.completionItems = completionItems + this.lastCompletionItemsPosition = caretPosition + } + + // At the very end of the method: + console.log('Final completion items:', completionItems.length) + } + + cancelParsing() { + //console.error("CANCEL"); + this.parseCancelToken.cancel = true + this.isRunningParse = false + } + + editorDidMount = (editor: monaco.editor.IStandaloneCodeEditor, monaco: typeof import('monaco-editor')) => { + this.setEditorRef(editor) + + editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter, () => { + this.props.onExecute() + }) + + editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter, () => { + // execute the query on ctrl+enter + this.props.onExecute() + }) + + editor.addAction({ + id: 'format-sql', + label: 'Format SQL', + keybindings: [monaco.KeyMod.Alt | monaco.KeyMod.Shift | monaco.KeyCode.KeyF], + contextMenuGroupId: 'modification', + contextMenuOrder: 1.5, + run: () => { + this.formatSql() + }, + }) + + // Check if the provider is already registered + if (!monaco.languages.getLanguages().some((lang: any) => lang.id === TRINO_SQL_LANGUAGE)) { + monaco.languages.register({ id: TRINO_SQL_LANGUAGE }) + + monaco.languages.setTokensProvider(TRINO_SQL_LANGUAGE, { + getInitialState: () => new CustomTokenizerState(), + tokenize: (line: any, state: any) => { + const inputStream = CharStream.fromString(line) + const lexer = new SqlBaseLexer(inputStream) + const tokenStream = new CommonTokenStream(lexer) + lexer.reset() + + const tokens = [] + let token = lexer.nextToken() + while (token.type !== SqlBaseLexer.EOF) { + tokens.push({ + startIndex: token.start, + scopes: tokenMap[token.type as keyof typeof tokenMap] || 'identifier', + }) + token = lexer.nextToken() + } + + return { tokens, endState: state } + }, + }) + + monaco.languages.registerCompletionItemProvider(TRINO_SQL_LANGUAGE, { + provideCompletionItems: async (model: any, position: any) => { + this.cancelParsing() // Cancel any ongoing parsing + const parseResult = await this.parseAndDecoratePromiseAsync(monaco, editor, 0) + if ( + this.lastCompletionItemsPosition && + this.lastCompletionItemsPosition.lineNumber == position.lineNumber && + this.lastCompletionItemsPosition.column == position.column + ) { + return { suggestions: this.completionItems } + } else { + return { suggestions: [] } // either parsing failed or the position is not the same as the last parse + } + }, + }) + } + + editor.onDidChangeModelContent(async (e: any) => { + this.updateCounter++ + this.handleEditorChange(editor.getValue()) + await this.parseAndDecoratePromiseAsync(monaco, editor, 200).then((result) => { + //console.log("done parsing"); + }) + }) + + editor.onDidChangeCursorSelection(() => { + const selection = editor.getSelection() + if (selection == null) { + return + } + if (selection.startLineNumber != selection.endLineNumber || selection.startColumn != selection.endColumn) { + const model = editor.getModel() + if (model) { + const selectedText = model.getValueInRange(selection) + this.props.onSelectChange(selectedText) + } + } else { + this.props.onSelectChange(editor.getValue()) + } + }) + + // init the parser once to get the initial state + this.parseAndDecoratePromiseAsync(monaco, editor, 0).then((result) => { + //console.log("done parsing"); + }) + } + + parseTreeFromPosition( + root: ParseTree, + cursorColumnOffsetZero: number, + row: number, + phantomKeyword: string = '' + ): any | undefined { + // Does the root node actually contain the position? If not, we don't need to look further. + if (root instanceof TerminalNode) { + const terminal = root as TerminalNode + const token = terminal.symbol + if (token.line != row) return undefined + //let tokenStop = token.column + (token.stop - token.start + 1); + if (cursorColumnOffsetZero >= token.column && token.text !== phantomKeyword && token.text !== '') { + // all we care about is whether it's the last token after this one starts + return terminal + } + return undefined + } else { + const context = root as ParserRuleContext + if (!context.start || !context.stop) { + // Invalid tree? + return undefined + } + + let result = undefined + if (context.children) { + let lastresult = undefined + for (const child of context.children) { + result = this.parseTreeFromPosition(child, cursorColumnOffsetZero, row, phantomKeyword) + if (result == undefined && lastresult != undefined) { + return lastresult + } + lastresult = result + } + if (result != undefined) { + return result + } + } + + if ( + context.children && + context.children.length > 1 && + context.children[0].getText() !== phantomKeyword && + context.children[0].getText() !== '' + ) { + return context.children[0] + } else { + return undefined + } + } + } + + // Format the entire SQL query + formatSql = () => { + if (this.editorRef) { + const currentValue = this.editorRef.getValue() + + try { + const config = { + indent: ' ', + uppercase: true, + linesBetweenQueries: 2, + } + const formattedSql = format(currentValue, config) + + // Replace the entire editor content with the formatted SQL + this.editorRef.setValue(formattedSql) + + // Trigger a save to update the query in state + this.handleEditorChange(formattedSql) + } catch (error) { + console.error('Error formatting SQL:', error) + } + } + } + + // Format only the selected text + formatSelection = () => { + if (this.editorRef) { + const selection = this.editorRef.getSelection() + if (!selection || selection.isEmpty()) { + // No selection, format the entire query + this.formatSql() + return + } + + const model = this.editorRef.getModel() + if (model) { + const selectedText = model.getValueInRange(selection) + try { + // Format just the selected text + const config = { + indent: ' ', + uppercase: true, + linesBetweenQueries: 2, + } + const formattedSql = format(selectedText, config) + + // Replace just the selected part + this.editorRef.executeEdits('format-selection', [ + { + range: selection, + text: formattedSql, + forceMoveMarkers: true, + }, + ]) + } catch (error) { + console.error('Error formatting selection:', error) + } + } + } + } + + handleHeightChange = (maxHeight: number) => { + this.setState({ height: this.state.isMaximized ? maxHeight : maxHeight / 2 }) + } + + render() { + const options = { + selectOnLineNumbers: true, + } + + const { currentQuery, isMaximized, height, width } = this.state + + return ( + <> + + + + ({ + position: 'absolute', + alignItems: 'center', + background: theme.palette.background.default, + border: 1, + borderColor: theme.palette.divider, + boxShadow: 1, + px: 0.5, + top: 0, + right: 15, + zIndex: 1000, + })} + > + + + + + + + + {isMaximized ? ( + + ) : ( + + )} + + + + + + + + + ) + } +} + +export default QueryEditorPane diff --git a/precise/src/ResultSet.tsx b/precise/src/ResultSet.tsx index 46da4ac..fbc4c6a 100644 --- a/precise/src/ResultSet.tsx +++ b/precise/src/ResultSet.tsx @@ -1,17 +1,33 @@ import React from 'react' -import QueryInfo from './schema/QueryInfo' +import { + Alert, + Box, + CircularProgress, + LinearProgress, + Link, + Paper, + Stack, + Table, + TableBody, + TableCell, + TableContainer, + TableFooter, + TableHead, + TableRow, + Typography, +} from '@mui/material' +import { DataGrid, GridColDef } from '@mui/x-data-grid' +import Chip, { ChipProps } from '@mui/material/Chip' import ReactDOMServer from 'react-dom/server' -import ErrorBox from './utils/ErrorBoxProvider' -import ProgressBar from './utils/ProgressBar' import CopyLink from './utils/CopyLink' import ClearButton from './utils/ClearButton' -import './style/results.css' interface ResultSetProps { - queryInfo: QueryInfo | undefined + queryId: string | undefined results: any[] columns: any[] response: any + height: number errorMessage: string onClearResults: (queryId: string | undefined) => void } @@ -21,6 +37,38 @@ class ResultSet extends React.Component { statsHistory: any[] = [] lastQueryId: string | undefined = undefined + static readonly STATE_COLOR_MAP: Record = { + QUEUED: 'default', + RUNNING: 'info', + PLANNING: 'info', + FINISHED: 'success', + BLOCKED: 'secondary', + USER_ERROR: 'error', + CANCELED: 'warning', + INSUFFICIENT_RESOURCES: 'error', + EXTERNAL_ERROR: 'error', + UNKNOWN_ERROR: 'error', + } + + getQueryStateColor(queryState: string): ChipProps['color'] { + switch (queryState) { + case 'QUEUED': + return ResultSet.STATE_COLOR_MAP.QUEUED + case 'PLANNING': + return ResultSet.STATE_COLOR_MAP.PLANNING + case 'STARTING': + case 'FINISHING': + case 'RUNNING': + return ResultSet.STATE_COLOR_MAP.RUNNING + case 'FAILED': + return ResultSet.STATE_COLOR_MAP.UNKNOWN_ERROR + case 'FINISHED': + return ResultSet.STATE_COLOR_MAP.FINISHED + default: + return ResultSet.STATE_COLOR_MAP.QUEUED + } + } + renderHeader(columns: any) { return ( @@ -60,11 +108,27 @@ class ResultSet extends React.Component { ) } - renderTable = (results: any[], response: any, columns: any) => { + renderTable = (results: any[], columns: any) => { + const muiColumns: GridColDef[] = columns.map((column: any) => ({ field: column.name, minWidth: 150 })) + const muiRows = results + .flat() + .map((row: any[], i: number) => + Object.fromEntries([ + ['mui-row-id', `row-${i + 1}`], + ...columns.map((c: any, j: number) => [c.name, row[j]]), + ]) + ) + return ( -
30 ? 'scrollable' : 'result-table-container'}> - {this.renderInnerTable(results, response, columns)} -
+ String(row['mui-row-id'])} + density="compact" + /> ) } @@ -214,14 +278,14 @@ class ResultSet extends React.Component { } render() { - const { queryInfo, results, columns, response, errorMessage } = this.props + const { queryId, results, columns, response, height, errorMessage } = this.props // if the query ID has changed, reset the last processed rows and elapsed time - if (queryInfo == null || this.lastQueryId !== queryInfo.id) { + if (this.lastQueryId !== queryId) { this.reset() } - this.lastQueryId = queryInfo?.id + this.lastQueryId = queryId // new implementation, look over 10 second window in stats history let processedRowsSinceLast = 0 @@ -271,239 +335,289 @@ class ResultSet extends React.Component { // Ensure the 'result-set' class is applied to the container return ( -
- { - // only return if there are columns - columns && columns.length ? ( -
- {response.stats && this.isFinishedFailedOrCancelled(response.stats.state) && ( - this.props.onClearResults(queryInfo?.id)} /> - )} - this.copy()} /> - {/* if row count > 30 place in scrollable div */} - {this.renderTable(results, response, columns)} -
- ) : null - } + {response && response.id ? ( -
- {this.getRowCount()} rows:{' '} - - {response.id} - -
+ + {errorMessage ? ( + + {errorMessage} + + ) : null} + + + {this.getRowCount()} rows: + + + {response.id} + + {columns && columns.length ? ( + response.stats && this.isFinishedFailedOrCancelled(response.stats.state) ? ( + <> + this.props.onClearResults(queryId)} /> + this.copy()} /> + + ) : null + ) : null} + + ) : null} - {errorMessage ? : null} {/* if the status is not finished, show spinner */} {response && response.stats && response.stats.state !== 'FINISHED' && response.stats.state !== 'FAILED' && response.stats.state !== 'CANCELLED' ? ( -
-
-
-
-
- {response && response.stats && response.stats.runningPercentage - ? Math.floor(response.stats.runningPercentage) - : 0} - % -
-
- {response.stats.state} -
+ <> + + + + {response && response.stats && response.stats.progressPercentage + ? Math.floor(response.stats.progressPercentage) + : 0} + % + + + + Workers: {response.stats.nodes}, Running splits: {response.stats.runningSplits}, Total splits: {response.stats.totalSplits}, Run time:{' '} {Math.floor(response.stats.elapsedTimeMillis / 1000)}s -
-
-
-
-
- -
- {this.formatMillisAsHHMMSS(response.stats.elapsedTimeMillis)} -
-
-
- {/* if response.stats.subStages */} - {response.stats.rootStage && response.stats.rootStage.subStages ? ( -
- - - - {' '} - {/* groupings for subcategories of metrics */} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {/* look at all the substages in subStages */} - {stages.map((subStageInfo: any) => { - return ( - + + + + + + {this.formatMillisAsHHMMSS(response.stats.elapsedTimeMillis)} + + + + {response.stats.rootStage && response.stats.rootStage.subStages ? ( + +
- Rows - - Bytes - - Splits -
StageNodesProcessedRateCurrent RateProcessedRateCurrent RateInput ProcessedQueuedRunningDone
0 (root){response.stats.rootStage.nodes} - {this.rowCountToCorrectScale(response.stats.rootStage.processedRows)} - - {this.rowCountToCorrectScale( - response.stats.rootStage.processedRows / - (response.stats.rootStage.wallTimeMillis / 1000) - )} - - {this.bytesToCorrectScale(response.stats.rootStage.processedBytes)} - - {this.bytesToCorrectScale( - response.stats.rootStage.processedBytes / - (response.stats.wallTimeMillis / 1000) - )} - - {this.bytesToCorrectScale(response.stats.rootStage.physicalInputBytes)} - - {response.stats.rootStage.queuedSplits} - - {response.stats.rootStage.runningSplits} - - {response.stats.rootStage.completedSplits} -
*': { + borderRight: (theme) => `1px solid ${theme.palette.divider}`, + }, + '& .MuiTableRow-root > *:last-of-type': { + borderRight: 'none', + }, + }} + size="small" + stickyHeader + > + + + + Query run metrics + + + Rows + + + Bytes + + + Splits + + + + Stage + Nodes + Processed + Rate + Current Rate + Processed + Rate + Current Rate + Input Processed + Queued + Running + Done + + + + + 0 (root) + {response.stats.rootStage.nodes} + + {this.rowCountToCorrectScale( + response.stats.rootStage.processedRows + )} + + + {this.rowCountToCorrectScale( + response.stats.rootStage.processedRows / + (response.stats.rootStage.wallTimeMillis / 1000) + )} + + + + {this.bytesToCorrectScale(response.stats.rootStage.processedBytes)} + + + {this.bytesToCorrectScale( + response.stats.rootStage.processedBytes / + (response.stats.wallTimeMillis / 1000) + )} + + + + {this.bytesToCorrectScale( + response.stats.rootStage.physicalInputBytes + )} + + + {response.stats.rootStage.queuedSplits} + + + {response.stats.rootStage.runningSplits} + + + {response.stats.rootStage.completedSplits} + + + + {/* Sub-stages */} + {stages.map((subStageInfo: any) => ( + - - - - - - - - - - - - - - ) - })} - - - - - - - - - - - - - - - -
- {subStageInfo.stage.stageId} - {subStageInfo.stage.nodes} + {subStageInfo.stage.stageId} + {subStageInfo.stage.nodes} + {this.rowCountToCorrectScale(subStageInfo.stage.processedRows)} - + + {this.rowCountToCorrectScale( subStageInfo.stage.processedRows / (subStageInfo.stage.wallTimeMillis / 1000) )} - + + + {this.bytesToCorrectScale(response.stats.processedBytes)} - + + {this.bytesToCorrectScale( subStageInfo.stage.processedBytes / (subStageInfo.stage.wallTimeMillis / 1000) )} - + + + {this.bytesToCorrectScale(response.stats.physicalInputBytes)} - + + {subStageInfo.stage.queuedSplits} - + + {subStageInfo.stage.runningSplits} - + + {subStageInfo.stage.completedSplits} -
Total{response.stats.nodes} - {this.rowCountToCorrectScale(response.stats.processedRows)} - - {this.rowCountToCorrectScale( - response.stats.processedRows / - (response.stats.elapsedTimeMillis / 1000) - )} - - {this.rowCountToCorrectScale(processedRowsSinceLast)} - - {this.bytesToCorrectScale(response.stats.processedBytes)} - - {this.bytesToCorrectScale( - response.stats.processedBytes / - (response.stats.elapsedTimeMillis / 1000) - )} - - {this.bytesToCorrectScale(response.stats.physicalInputBytes)} - {response.stats.queuedSplits}{response.stats.runningSplits}{response.stats.completedSplits}
-
- ) : null} -
+ + + ))} + + + theme.typography.fontWeightBold, + color: 'text.primary', + }, + }} + > + {/* Totals */} + + Total + {response.stats.nodes} + + {this.rowCountToCorrectScale(response.stats.processedRows)} + + + {this.rowCountToCorrectScale( + response.stats.processedRows / + (response.stats.elapsedTimeMillis / 1000) + )} + + + {this.rowCountToCorrectScale(processedRowsSinceLast)} + + + {this.bytesToCorrectScale(response.stats.processedBytes)} + + + {this.bytesToCorrectScale( + response.stats.processedBytes / + (response.stats.elapsedTimeMillis / 1000) + )} + + + + {this.bytesToCorrectScale(response.stats.physicalInputBytes)} + + {response.stats.queuedSplits} + {response.stats.runningSplits} + {response.stats.completedSplits} + + + + + ) : null} +
+ + ) : columns && columns.length ? ( + + {this.renderTable(results, columns)} + ) : null} -
+ ) } } diff --git a/precise/src/SubstitutionEditor.tsx b/precise/src/SubstitutionEditor.tsx index da81681..c5e1467 100644 --- a/precise/src/SubstitutionEditor.tsx +++ b/precise/src/SubstitutionEditor.tsx @@ -1,4 +1,6 @@ import React, { useState, useEffect } from 'react' +import { Box, Stack, Typography, TextField, InputAdornment, IconButton } from '@mui/material' +import ClearIcon from '@mui/icons-material/Clear' interface SubstitutionField { name: string @@ -60,21 +62,52 @@ const SubstitutionEditor: React.FC = ({ query, onSubsti } return ( -
-

Query Parameters

- {fields.map((field) => ( -
- - handleInputChange(field.name, e.target.value)} - placeholder={field.defaultValue} - /> -
- ))} -
+ + Query Parameters + + {fields.map((field) => { + const isNumber = field.type !== 'varchar' + const val = values[field.name] ?? '' + + return ( + handleInputChange(field.name, e.target.value)} + placeholder={field.defaultValue !== undefined ? String(field.defaultValue) : ''} + slotProps={{ + input: { + // helpful for numeric types + inputProps: isNumber ? { step: field.type === 'double' ? 'any' : 1 } : undefined, + // optional clear button (keeps width stable when empty) + endAdornment: ( + + handleInputChange(field.name, '')} + sx={{ + visibility: val ? 'visible' : 'hidden', + '& .MuiSvgIcon-root': { fontSize: 16 }, + }} + > + + + + ), + }, + }} + /> + ) + })} + + ) } diff --git a/precise/src/assets/close.png b/precise/src/assets/close.png deleted file mode 100644 index cbd90be..0000000 Binary files a/precise/src/assets/close.png and /dev/null differ diff --git a/precise/src/assets/pin_down.png b/precise/src/assets/pin_down.png deleted file mode 100644 index 1039779..0000000 Binary files a/precise/src/assets/pin_down.png and /dev/null differ diff --git a/precise/src/assets/pin_up.png b/precise/src/assets/pin_up.png deleted file mode 100644 index 1d3ce9b..0000000 Binary files a/precise/src/assets/pin_up.png and /dev/null differ diff --git a/precise/src/controls/catalog_viewer/CatalogViewer.tsx b/precise/src/controls/catalog_viewer/CatalogViewer.tsx index d118f61..32aac0b 100644 --- a/precise/src/controls/catalog_viewer/CatalogViewer.tsx +++ b/precise/src/controls/catalog_viewer/CatalogViewer.tsx @@ -1,21 +1,45 @@ import React, { useState, useEffect, useCallback, useRef } from 'react' +import { + Alert, + AlertTitle, + Box, + Checkbox, + Chip, + CircularProgress, + Grid, + FormControlLabel, + IconButton, + LinearProgress, + TextField, + Typography, + Divider, +} from '@mui/material' +import ChevronLeftIcon from '@mui/icons-material/ChevronLeft' +import ChevronRightIcon from '@mui/icons-material/ChevronRight' +import RefreshIcon from '@mui/icons-material/Refresh' +import StorageOutlinedIcon from '@mui/icons-material/StorageOutlined' +import { SimpleTreeView, TreeItem } from '@mui/x-tree-view' +import CatalogViewerSchema from './CatalogViewerSchema' import SchemaProvider from './../../sql/SchemaProvider' import Catalog from './../../schema/Catalog' import TableReference from '../../schema/TableReference' -import CatalogViewerSchema from './CatalogViewerSchema' -import ErrorBox from './../../utils/ErrorBoxProvider' -import CloseIcon from '../../assets/close.png' import { ViewerStateManager, buildPath } from './ViewerState' -import './catalogviewer.css' -import { Loader2, ChevronRight } from 'lucide-react' interface CatalogViewerProps { initialFilterText?: string onGenerateQuery?: (query: string, catalog?: string, schema?: string) => void onAppendQuery?: (query: string, catalog?: string, schema?: string) => void + onDrawerToggle?: () => void + enableSearchColumns?: boolean } -const CatalogViewer: React.FC = ({ initialFilterText = '', onGenerateQuery, onAppendQuery }) => { +const CatalogViewer: React.FC = ({ + initialFilterText = '', + onGenerateQuery, + onAppendQuery, + onDrawerToggle, + enableSearchColumns, +}) => { // Basic state const [catalogs, setCatalogs] = useState>(new Map()) const [errorMessage, setErrorMessage] = useState() @@ -27,7 +51,7 @@ const CatalogViewer: React.FC = ({ initialFilterText = '', o // View state const [matches, setMatches] = useState>(new Set()) const [expandedNodes, setExpandedNodes] = useState>(new Set()) - const viewerState = useRef() + const viewerState = useRef(null) const [isLoadingColumns, setIsLoadingColumns] = useState(false) @@ -70,8 +94,8 @@ const CatalogViewer: React.FC = ({ initialFilterText = '', o try { await SchemaProvider.populateCatalogsAndRefreshTableList( - () => { - setCatalogs(SchemaProvider.catalogs) + (nextCatalogs) => { + setCatalogs(nextCatalogs) setIsLoading(false) }, (error: string) => { @@ -153,91 +177,184 @@ const CatalogViewer: React.FC = ({ initialFilterText = '', o } return ( -
-
-
- + `calc(${theme.mixins.toolbar.minHeight}px + ${theme.spacing(1)})`, + px: 0, + py: 0, + }} + > + + setFilterText(e.target.value)} - className="filter-input" + fullWidth /> - {filterText && ( -
setFilterText('')} - role="button" - aria-label="Clear search" - > - Clear -
- )} -
- - - -
- - {isLoading &&
Loading catalogs...
} - - {errorMessage && } - -
- {Array.from(catalogs.values()) - .sort((a, b) => a.getName().localeCompare(b.getName())) - .map((catalog: Catalog) => { - const catalogName = catalog.getName() - const catalogPath = buildPath.catalog(catalogName) - - if (filterText && !isVisible(catalogPath)) { - return null - } - - return ( -
-
handleToggle(catalogPath)}> -
- {catalogName} - {catalog.getType()} catalog -
- + + + + + + + {enableSearchColumns && ( + + setSearchColumns(e.target.checked)} + /> + } + label={ + + - {isExpanded(catalogPath) ? 'â–Ľ' : 'â–¶'} - -
handleGenerateCatalogQuery(e, catalogName)} - title="Set this catalog as default catalog" - > - -
-
- - {isExpanded(catalogPath) && ( -
+ Search columns + + {isLoadingColumns && } + + } + /> + + )} + + + + {errorMessage && ( + + Catalog Viewer + {errorMessage} + + )} + + { + handleToggle(itemId) + }} + > + {Array.from(catalogs.values()) + .sort((a, b) => a.getName().localeCompare(b.getName())) + .map((catalog: Catalog) => { + const catalogName = catalog.getName() + const catalogPath = buildPath.catalog(catalogName) + + if (filterText && !isVisible(catalogPath)) { + return null + } + + return ( + + {catalogName} + {catalog.getType() === 'system' && ( + + )} + + handleGenerateCatalogQuery(e, catalogName)} + disabled={isLoading} + > + + + + } + slotProps={{ + label: { + style: { + overflow: 'visible', + }, + }, + }} + > + {catalog.getError() && ( - + + Catalog Viewer + {catalog.getError()} + )} {Array.from(catalog.getSchemas().values()) .sort((a, b) => a.getName().localeCompare(b.getName())) .map((schema) => { - const schemaPath = buildPath.schema(catalogName, schema.getName()) + const schemaName = schema.getName() + const schemaPath = buildPath.schema(catalogName, schemaName) return ( = ({ initialFilterText = '', o catalogName={catalogName} schema={schema} filterText={filterText} - isExpanded={isExpanded(schemaPath)} isVisible={isVisible} + isLoading={isLoading} hasMatchingChildren={hasMatchingChildren} - onToggle={handleToggle} onGenerateQuery={handleGenerateQuery} /> ) })} -
- )} -
- ) - })} -
-
+ + + ) + })} + + + ) } diff --git a/precise/src/controls/catalog_viewer/CatalogViewerColumn.tsx b/precise/src/controls/catalog_viewer/CatalogViewerColumn.tsx index 201510b..0b8fcad 100644 --- a/precise/src/controls/catalog_viewer/CatalogViewerColumn.tsx +++ b/precise/src/controls/catalog_viewer/CatalogViewerColumn.tsx @@ -1,123 +1,63 @@ -import React, { useState, useEffect } from 'react' +import React from 'react' +import { Box, Stack, Typography } from '@mui/material' +import { TreeItem } from '@mui/x-tree-view' import Column from '../../schema/Column' import TableReference from './../../schema/TableReference' -import CopyLink from './../../utils/CopyLink' import { buildPath } from './ViewerState' -import './catalogviewer.css' interface CatalogViewerColumnProps { tableRef: TableReference column: Column - isExpanded: boolean isVisible: (path: string) => boolean - onToggle: (path: string) => Promise } -const CatalogViewerColumn: React.FC = ({ - tableRef, - column, - isExpanded, - isVisible, - onToggle, -}) => { - const [sampleValues, setSampleValues] = useState([]) - const [isLoadingSamples, setIsLoadingSamples] = useState(false) - const [showSamples, setShowSamples] = useState(false) - +const CatalogViewerColumn: React.FC = ({ tableRef, column, isVisible }) => { const columnPath = buildPath.column(tableRef.catalogName, tableRef.schemaName, tableRef.tableName, column.getName()) - // Load sample values when samples are shown - useEffect(() => { - if (showSamples && sampleValues.length === 0 && !isLoadingSamples) { - setIsLoadingSamples(true) - column.getSampleValues(tableRef, (newSampleValues: string[]) => { - setSampleValues(newSampleValues) - setIsLoadingSamples(false) - }) - } - }, [showSamples, column, tableRef, sampleValues.length, isLoadingSamples]) - - const handleRefresh = (e: React.MouseEvent) => { - e.stopPropagation() - setIsLoadingSamples(true) - column.getSampleValues(tableRef, (newSampleValues: string[]) => { - setSampleValues(newSampleValues) - setIsLoadingSamples(false) - }) - } - - const handleToggle = async () => { - // Toggle samples if already expanded - if (isExpanded) { - setShowSamples(!showSamples) - } else { - // Just expand the column initially - await onToggle(columnPath) - setShowSamples(true) - } - } - - const renderSampleValue = (value: string, index: number) => { - if (value === null) { - return ( -
- NULL -
- ) - } - - const displayValue = value.length > 50 ? value.substring(0, 50) + '...' : value - - return ( -
- {displayValue} - navigator.clipboard.writeText(value)} /> -
- ) - } - // Check visibility using the passed down helper if (!isVisible(columnPath)) { return null } return ( -
-
- {showSamples && ( -
-
-
- )} -
- {column.getName()} - {column.getType()} - {showSamples ? 'â–Ľ' : 'â–¶'} -
- {column.getExtraOrComment() && ( -
- {column.getExtraOrComment()} -
- )} -
- - {showSamples && ( -
-
- Sample values: -
-
- {isLoadingSamples ? ( -
Loading samples...
- ) : sampleValues.length === 0 ? ( -
No sample values available
- ) : ( - sampleValues.map((value, index) => renderSampleValue(value, index)) - )} -
-
- )} -
+ + + + + {column.getName()} + + + {column.getType()} + + + + + } + slotProps={{ + label: { + style: { + overflow: 'visible', + }, + }, + }} + /> ) } diff --git a/precise/src/controls/catalog_viewer/CatalogViewerSchema.tsx b/precise/src/controls/catalog_viewer/CatalogViewerSchema.tsx index 90857b4..d348217 100644 --- a/precise/src/controls/catalog_viewer/CatalogViewerSchema.tsx +++ b/precise/src/controls/catalog_viewer/CatalogViewerSchema.tsx @@ -1,20 +1,21 @@ import React from 'react' +import { Box, IconButton, Typography } from '@mui/material' +import { TreeItem } from '@mui/x-tree-view' +import AccountTreeOutlinedIcon from '@mui/icons-material/AccountTreeOutlined' +import ChevronRightIcon from '@mui/icons-material/ChevronRight' import Schema from '../../schema/Schema' import Table from '../../schema/Table' import CatalogViewerTable from './CatalogViewerTable' import TableReference from '../../schema/TableReference' import { buildPath } from './ViewerState' -import './catalogviewer.css' -import { ChevronRight } from 'lucide-react' interface SchemaProps { catalogName: string schema: Schema filterText: string - isExpanded: boolean isVisible: (path: string) => boolean + isLoading: boolean hasMatchingChildren: (path: string) => boolean - onToggle: (path: string) => Promise onGenerateQuery?: ( queryType: string, tableRef: TableReference | null, @@ -27,10 +28,9 @@ const CatalogViewerSchema: React.FC = ({ catalogName, schema, filterText, - isExpanded, isVisible, + isLoading, hasMatchingChildren, - onToggle, onGenerateQuery, }) => { const schemaPath = buildPath.schema(catalogName, schema.getName()) @@ -48,51 +48,60 @@ const CatalogViewerSchema: React.FC = ({ } return ( -
-
onToggle(schemaPath)}> - {schema.getName()} - schema - - {isExpanded ? 'â–Ľ' : 'â–¶'} - + {schema.getName()} - {onGenerateQuery && ( -
- -
- )} -
- - {isExpanded && ( -
- {Array.from(schema.getTables().values()) - .sort((a: Table, b: Table) => a.getName().localeCompare(b.getName())) - .map((table: Table) => { - const tablePath = buildPath.table(catalogName, schema.getName(), table.getName()) + + + + } + slotProps={{ + label: { + style: { + overflow: 'visible', + }, + }, + }} + > + {Array.from(schema.getTables().values()) + .sort((a: Table, b: Table) => a.getName().localeCompare(b.getName())) + .map((table: Table) => { + const tablePath = buildPath.table(catalogName, schema.getName(), table.getName()) - // Table visibility is handled within the component - return ( - - ) - })} -
- )} -
+ return ( + + ) + })} +
) } diff --git a/precise/src/controls/catalog_viewer/CatalogViewerTable.tsx b/precise/src/controls/catalog_viewer/CatalogViewerTable.tsx index 9283651..1b077a6 100644 --- a/precise/src/controls/catalog_viewer/CatalogViewerTable.tsx +++ b/precise/src/controls/catalog_viewer/CatalogViewerTable.tsx @@ -1,19 +1,22 @@ import React, { useState, useEffect } from 'react' +import { Alert, Box, IconButton, Typography } from '@mui/material' +import { TreeItem } from '@mui/x-tree-view' +import HourglassEmptyOutlinedIcon from '@mui/icons-material/HourglassEmptyOutlined' +import SearchOutlinedIcon from '@mui/icons-material/SearchOutlined' +import TableRowsOutlined from '@mui/icons-material/TableRowsOutlined' import Table from '../../schema/Table' import SchemaProvider from '../../sql/SchemaProvider' import TableReference from '../../schema/TableReference' import CatalogViewerColumn from './CatalogViewerColumn' import { buildPath } from './ViewerState' -import './catalogviewer.css' -import { ChevronRight } from 'lucide-react' interface CatalogViewerTableProps { tableRef: TableReference filterText: string isExpanded: boolean isVisible: (path: string) => boolean + isLoading: boolean hasMatchingChildren: (path: string) => boolean - onToggle: (path: string) => Promise onGenerateQuery?: (queryType: string, tableRef: TableReference) => void } @@ -22,7 +25,7 @@ const CatalogViewerTable: React.FC = ({ filterText, isExpanded, isVisible, - onToggle, + isLoading, onGenerateQuery, }) => { const [table, setTable] = useState(() => new Table(tableRef.tableName)) @@ -63,60 +66,70 @@ const CatalogViewerTable: React.FC = ({ } return ( -
-
-
onToggle(tablePath)}> - {table.getName()} - table - {isExpanded ? 'â–Ľ' : 'â–¶'} + + {table.getName()} - {onGenerateQuery && ( -
- -
- )} -
-
+ + + + + } + slotProps={{ + label: { + style: { + overflow: 'visible', + }, + }, + }} + > + + {table.getError() ? ( + {table.getError()} + ) : table.getColumns().length === 0 && table.isLoading() ? null : ( + table.getColumns().length > 0 && + table.getColumns().map((column) => { + const columnPath = buildPath.column( + tableRef.catalogName, + tableRef.schemaName, + tableRef.tableName, + column.getName() + ) - {isExpanded && ( -
- {table.getError() ? ( -
{table.getError()}
- ) : table.getColumns().length === 0 && isExpanded && table.isLoading() ? ( -
Loading columns...
- ) : ( - table.getColumns().length > 0 && - table.getColumns().map((column) => { - const columnPath = buildPath.column( - tableRef.catalogName, - tableRef.schemaName, - tableRef.tableName, - column.getName() - ) + if (!isVisible(columnPath)) { + return null + } - if (!isVisible(columnPath)) { - return null - } - - return ( - - ) - }) - )} -
- )} -
+ return ( + + ) + }) + )} + + ) } diff --git a/precise/src/controls/catalog_viewer/ViewerState.ts b/precise/src/controls/catalog_viewer/ViewerState.ts index c02737b..9325a06 100644 --- a/precise/src/controls/catalog_viewer/ViewerState.ts +++ b/precise/src/controls/catalog_viewer/ViewerState.ts @@ -19,7 +19,7 @@ export const buildPath = { } export class ViewerStateManager { - private userExpanded = new Set() + public userExpanded = new Set() private matches = new Set() private onStateUpdate: StateUpdateCallback private isSearching = false diff --git a/precise/src/controls/catalog_viewer/catalogviewer.css b/precise/src/controls/catalog_viewer/catalogviewer.css deleted file mode 100644 index 8610726..0000000 --- a/precise/src/controls/catalog_viewer/catalogviewer.css +++ /dev/null @@ -1,204 +0,0 @@ -.filter-input { - width: 95%; - padding: 0.5em; - margin: 0.5em; - border: 1px solid #2b2b2b; - border-radius: 3px; - background-color: #181818; - color: #9d9d9d; - font-size: small; -} - -/* A plain text with no obvious element of it being a button */ -.reload-button { - border: 0; - background-color: transparent; - color: #bbb; - right: 20px; - position: absolute; - padding: 0; - margin: 0; - font-size: 2em; -} - -/* catalog explorer */ -.viewer_catalog { - font-weight: bold; - color: #fff; - cursor: pointer; -} - -.catalog-content { - padding-left: 0.5em; -} - -.viewer_catalog:hover { - color: #fff; - background-color: #689CC5; -} - -.viewer_catalog_body { - margin-left: 10px; - padding-left: 10px; - border-left: #444 1px solid; -} - -.viewer_schema { - font-weight: regular; - color: #bbb; - cursor: pointer; -} - -.viewer_schema:hover { - color: #fff; - background-color: #416480; -} - -.viewer-schema-body { - margin-left: 10px; - padding-left: 10px; - border-left: #444 1px solid; -} - -.viewer_table { - font-weight: regular; - color: #999; - cursor: pointer; - position: relative; - padding-right: 30px; -} - -.viewer_samplevalue { - color: #999; -} - -.viewer_table_body { - margin-left: 10px; - padding-left: 10px; - border-left: #888 1px solid; - padding-right: 10px; -} - -.viewer_samplevalues_body { - margin-left: 10px; - padding-left: 10px; - border-left: #444 1px solid; -} - -.viewer_table:hover { - color: #fff; - background-color: #334e64; -} - -/* monospaced text */ -.viewer_column { - font-family: monospace; - cursor: pointer; -} - -.viewer_column:hover { - color: #fff; - background-color: #334e64; - cursor: pointer; -} - -.loading-message { - color: #999; - font-size: x-small; -} - -.table-name { - padding-right: 0.25em; -} - -.schema-name { - padding-right: 0.25em; -} - -.catalog-viewer { - position: relative; -} - -.catalog-viewer-header { - padding-bottom: 0.5em; -} - -.catalog-name { - padding-right: 0.25em; -} - -.column-name { - padding-right: 0.25em; -} - -.expand-indicator { - color: #444; - font-size: x-small; - padding-left: 0.25em; -} - -/* Add to catalogviewer.css */ -.search-container { - position: relative; - display: flex; - flex: 1; - align-items: center; -} - -/* input inside the search container needs to have text cursor */ -.search-container > .filter-input { - cursor: text !important; -} - -.clear-search { - position: absolute; - right: 8px; - top: 50%; - transform: translateY(-50%); - cursor: pointer; - opacity: 0.6; - transition: opacity 0.2s; - padding: 4px; - display: flex; - align-items: center; - justify-content: center; -} - -.clear-search:hover { - opacity: 1; -} - -.filter-input { - padding-right: 28px; /* Make room for the clear button */ -} - -.expand-indicator-has-matches { - color: #689CC5; /* Light blue to match the hover color */ -} - -/* Add to catalogviewer.css */ -.generate-query-button { - margin-left: auto; - color: #666; - cursor: pointer; - padding: 2px 8px; - transition: color 0.2s; - display: flex; - align-items: center; -} - -.generate-query-button:hover { - color: #fff; -} - -/* Make viewer rows display as flex to accommodate the button on the right */ -.viewer_catalog, .viewer_schema, .viewer_table { - display: flex; - align-items: center; - width: 100%; -} - -/* Add spacing between the expand indicator and text */ -.catalog-name, .schema-name, .table-name { - margin-right: 0.5em; -} \ No newline at end of file diff --git a/precise/src/controls/tabs/EnterpriseTabs.tsx b/precise/src/controls/tabs/EnterpriseTabs.tsx index 823cf49..c12275b 100644 --- a/precise/src/controls/tabs/EnterpriseTabs.tsx +++ b/precise/src/controls/tabs/EnterpriseTabs.tsx @@ -1,8 +1,7 @@ import React, { Component } from 'react' -import { DndProvider } from 'react-dnd' -import { HTML5Backend } from 'react-dnd-html5-backend' -import './tabs.css' -import TabItem from './TabItem' +import { Box, Divider, IconButton, Tab as MuiTab, Tabs as MuiTabs } from '@mui/material' +import AddIcon from '@mui/icons-material/Add' +import CloseIcon from '@mui/icons-material/Close' import TabsEllipsesMenu from './TabsEllipsesMenu' import Tabs from './Tabs' import TabInfo from './TabInfo' @@ -131,29 +130,69 @@ class EnterpriseTabs extends Component const { newTabLabel = '+' } = this.props return ( - -
-
- {tabs.map((tab, index) => ( - + + this.handleTabClick(id)} + sx={{ flexGrow: 1 }} + > + {tabs.map((tab) => ( + this.handleTabClick(tab.id)} - handleTabClose={() => this.handleTabClose(tab.id)} - handleTabRename={(id, newTitle) => this.handleTabRename(tab.id, newTitle)} - handleTabPin={() => this.handleTabPin(tab.id)} + value={tab.id} + label={tab.title} + sx={{ minHeight: 36, py: 0 }} + icon={ + { + e.stopPropagation() + this.handleTabClose(tab.id) + }} + > + + + } + iconPosition="end" /> ))} -
- {newTabLabel} -
-
- -
-
+ { + e.stopPropagation() + this.handleNewTab() + }} + > + + + } + aria-label="Add tab" + sx={{ minWidth: 0, px: 1 }} + disableRipple + /> + + + + + + + + ) } } diff --git a/precise/src/controls/tabs/TabItem.tsx b/precise/src/controls/tabs/TabItem.tsx deleted file mode 100644 index c591cb2..0000000 --- a/precise/src/controls/tabs/TabItem.tsx +++ /dev/null @@ -1,135 +0,0 @@ -import React, { useState, useRef, useEffect } from 'react' -import { useDrag, useDrop } from 'react-dnd' -import TabInfo from './TabInfo' -import PinUpIcon from '../../assets/pin_up.png' -import PinDownIcon from '../../assets/pin_down.png' -import CloseIcon from '../../assets/close.png' - -const ItemType = { - TAB: 'tab', -} - -interface TabItemProps { - tab: T - isActive: boolean - index: number - moveTab: (fromIndex: number, toIndex: number) => void - handleTabClick: (tabId: string) => void - handleTabClose: (tabId: string) => void - handleTabRename: (tabId: string, newTitle: string) => void - handleTabPin: (tabId: string) => void -} - -function TabItem({ - tab, - isActive, - index, - moveTab, - handleTabClick, - handleTabClose, - handleTabRename, - handleTabPin, -}: TabItemProps) { - const [isEditing, setIsEditing] = useState(false) - const [editedTitle, setEditedTitle] = useState(tab.title) - const inputRef = useRef(null) - - const [{ isDragging }, drag, preview] = useDrag({ - type: ItemType.TAB, - item: () => ({ index }), - collect: (monitor) => ({ - isDragging: monitor.isDragging(), - }), - canDrag: () => !isEditing, // Disable dragging when editing - }) - - const [, drop] = useDrop({ - accept: ItemType.TAB, - hover: (draggedItem: { index: number }) => { - if (draggedItem.index !== index) { - moveTab(draggedItem.index, index) - draggedItem.index = index - } - }, - }) - - useEffect(() => { - if (isEditing && inputRef.current) { - inputRef.current.focus() - inputRef.current.select() // Select all text when editing starts - } - }, [isEditing]) - - const handleDoubleClick = (e: React.MouseEvent) => { - e.stopPropagation() - setIsEditing(true) - } - - const handleInputChange = (event: React.ChangeEvent) => { - setEditedTitle(event.target.value) - } - - const handleInputBlur = () => { - setIsEditing(false) - if (editedTitle.trim() !== tab.title && editedTitle.trim() !== '') { - handleTabRename(tab.id, editedTitle.trim()) - } else { - setEditedTitle(tab.title) // Reset to original title if empty or unchanged - } - } - - const handleInputKeyPress = (event: React.KeyboardEvent) => { - if (event.key === 'Enter') { - handleInputBlur() - } - } - - return ( -
preview(drop(node))} - className={`tab-item ${isActive ? 'tab-item-selected' : ''} ${isDragging ? 'dragging' : ''} ${tab.isPinned ? 'pinned' : ''}`} - onClick={() => handleTabClick(tab.id)} - > -
- {isEditing ? ( - e.stopPropagation()} - style={{ cursor: 'text' }} - /> - ) : ( -
- {tab.title} -
- )} -
-
-
{ - e.stopPropagation() - handleTabPin(tab.id) - }} - > - Pin -
-
{ - e.stopPropagation() - handleTabClose(tab.id) - }} - > - Close -
-
-
- ) -} - -export default TabItem diff --git a/precise/src/controls/tabs/TabsEllipsesMenu.tsx b/precise/src/controls/tabs/TabsEllipsesMenu.tsx index 2e729bb..b92d794 100644 --- a/precise/src/controls/tabs/TabsEllipsesMenu.tsx +++ b/precise/src/controls/tabs/TabsEllipsesMenu.tsx @@ -1,4 +1,7 @@ import React, { useState, useRef, useEffect } from 'react' +import { Box, IconButton, Popover, TextField, List, ListItemButton, ListItemText } from '@mui/material' +import ExpandMoreIcon from '@mui/icons-material/ExpandMore' +import PushPinIcon from '@mui/icons-material/PushPin' import TabInfo from './TabInfo' interface TabsEllipsesMenuProps { @@ -12,62 +15,61 @@ function TabsEllipsesMenu({ onTabSelect, filterPlaceholder = 'Filter tabs...', }: TabsEllipsesMenuProps) { - const [isOpen, setIsOpen] = useState(false) + const [anchorEl, setAnchorEl] = useState(null) const [filter, setFilter] = useState('') - const menuRef = useRef(null) + const isOpen = Boolean(anchorEl) const filteredTabs = tabs.filter((tab) => tab.title.toLowerCase().includes(filter.toLowerCase())) - useEffect(() => { - function handleClickOutside(event: MouseEvent) { - if (menuRef.current && !menuRef.current.contains(event.target as Node)) { - setIsOpen(false) - } - } - - document.addEventListener('mousedown', handleClickOutside) - return () => { - document.removeEventListener('mousedown', handleClickOutside) - } - }, [menuRef]) - - const handleEllipsesClick = (event: React.MouseEvent) => { + const handleEllipsesClick = (event: React.MouseEvent) => { event.stopPropagation() - setIsOpen(true) + setAnchorEl(event.currentTarget) } + const handleClosePopover = () => setAnchorEl(null) + return ( -
- - {isOpen && ( -
- + + + + + e.stopPropagation()}> + setFilter(e.target.value)} - autoFocus + sx={{ mb: 1 }} /> -
+ {filteredTabs.map((tab) => ( -
{ onTabSelect(tab.id) - setIsOpen(false) + handleClosePopover() }} + sx={{ gap: 1 }} > - {tab.title} - {tab.isPinned && 📌} -
+ + {tab.isPinned && } + ))} -
-
- )} -
+ + + + ) } diff --git a/precise/src/controls/tabs/tabs.css b/precise/src/controls/tabs/tabs.css deleted file mode 100644 index 5fada60..0000000 --- a/precise/src/controls/tabs/tabs.css +++ /dev/null @@ -1,193 +0,0 @@ -.tabs-container { - position: relative; - display: flex; - align-items: center; - overflow-x: auto; - white-space: nowrap; - margin-top: 0px; /* Tabs overlap the control bar, better fix might be to prevent the animation from doing this */ -} - -.tabs { - display: flex; - flex-direction: row; - flex-grow: 1; - overflow-x: auto; - /* disable scrollbars */ - scrollbar-width: none; - height: 2.5em; -} - -.controltab { - display: inline-flex; - align-items: center; - padding: 10px; - padding-left: 20px; - padding-right: 20px; - background-color: #000000; - border-left: 1px solid #2b2b2b; - border-top: 1px solid #2b2b2b; - border-radius: 3px; - font-size: xx-large; - cursor: pointer; - flex-shrink: 0; - box-sizing: border-box; - color: #ffffff; - font-size: small; -} - -.controltab:hover, .tabs-ellipses-menu:hover { - background-color: #2b2b2b; -} - -.tab-item, -.tab-item-selected { - display: flex; - align-items: center; - justify-content: space-between; - padding: 10px; - border-left: 1px solid #2b2b2b; - border-top: 1px solid #2b2b2b; - border-top-left-radius: 5px; - border-top-right-radius: 5px; - cursor: pointer; - box-sizing: border-box; - font-size: small; - max-width: 200px; - animation: tabPopup 0.3s ease-out; -} - -@keyframes tabPopup { - from { - transform: translateY(10px); - opacity: 0; - } - to { - transform: translateY(0); - opacity: 1; - } -} - -.tab-item { - background-color: #101010; - color: #9d9d9d; -} - -.tab-item-selected { - background-color: #1F1F1F; - color: #dddddd; -} - -.tab-item:hover, -.tab-item-selected:hover { - background-color: #2b2b2b; -} - -.tab-content { - flex-grow: 1; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - margin-right: 5px; -} - -.tab-buttons { - display: flex; - align-items: center; -} - -.tab-button { - background: none; - border: none; - cursor: pointer; - display: flex; - align-items: center; - justify-content: center; - padding: 2px; - color: inherit; - font-size: 14px; - width: 14px; - height: 14px; - margin-left: 0px; -} - -.tab-button:hover { - background-color: rgba(255, 255, 255, 0.1); - border-radius: 3px; -} - -.close-button:hover { - color: #ff4444; -} - -.tab-list-button-and-menu { - position: absolute; - right: 0px; - top: 0px; - z-index: 1000; -} - -.ellipses-button { - display: flex; - align-items: center; - justify-content: center; - width: 30px; - height: 30px; - padding: 0; - margin-right: 20px; - background-color: #000000; - border: none; - border-left: 1px solid #2b2b2b; - border-top: 1px solid #2b2b2b; - border-radius: 3px; - cursor: pointer; - color: #ffffff; - font-size: 18px; - outline: none; -} - -.ellipses-button:hover { - background-color: #2b2b2b; -} - -.tabs-ellipses-menu-content { - position: fixed; - right: 10px; - top: 130px; - background-color: #101010; - min-width: 300px; - box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2); - z-index: 1001; - max-height: calc(100vh - 50px); - overflow-y: auto; - overflow-x: hidden; - border: 1px solid #2b2b2b; - border-radius: 3px; -} - -.tabs-ellipses-menu-content input { - width: calc(100% - 20px); - margin: 10px; - padding: 5px; - background-color: #181818; - border: 1px solid #2b2b2b; - color: #9d9d9d; - font-size: small; -} - -.tabs-ellipses-menu-content .tab-list { - max-height: 250px; - overflow-y: auto; -} - -.tabs-ellipses-menu-content .tab-item { - display: block; - padding: 10px; - text-decoration: none; - cursor: pointer; - border: none; - border-radius: 0; -} - -.tabs-ellipses-menu-content .tab-item:hover { - background-color: #2b2b2b; -} \ No newline at end of file diff --git a/precise/src/index.ts b/precise/src/index.ts new file mode 100644 index 0000000..7a787a1 --- /dev/null +++ b/precise/src/index.ts @@ -0,0 +1 @@ +export { default as QueryEditor } from './QueryEditor' diff --git a/precise/src/main.tsx b/precise/src/main.tsx index b5c4551..8214d84 100644 --- a/precise/src/main.tsx +++ b/precise/src/main.tsx @@ -1,12 +1,50 @@ -import React from 'react' +import React, { useLayoutEffect, useRef, useState } from 'react' import ReactDOM from 'react-dom/client' -import App from './App.tsx' -import './style/theme.css' -import './style/normalize.css' -import './style/layout.css' -import './style/components.css' -import './style/query-editor.css' -import './style/results.css' -import './style/control.css' - -ReactDOM.createRoot(document.getElementById('root')!).render() +import QueryEditor from './QueryEditor' + +function useObservedHeight(ref: React.RefObject | React.RefObject) { + const [height, setHeight] = useState(0) + + useLayoutEffect(() => { + const el = ref.current + if (!el) return + + // Initial measure + setHeight(el.getBoundingClientRect().height) + + const ro = new ResizeObserver(([entry]) => { + setHeight(entry.contentRect.height) + }) + ro.observe(el) + + return () => ro.disconnect() + }, [ref]) + + return height +} + +export default function App() { + const slotRef = useRef(null) + const slotHeight = useObservedHeight(slotRef) + + return ( +
+

Trino Query Editor - Example app

+
+ +
+
+ ) +} + +ReactDOM.createRoot(document.getElementById('root')!).render( + + + +) diff --git a/precise/src/sql/SchemaProvider.ts b/precise/src/sql/SchemaProvider.ts index 9e2c41b..627a4ed 100644 --- a/precise/src/sql/SchemaProvider.ts +++ b/precise/src/sql/SchemaProvider.ts @@ -63,7 +63,10 @@ class SchemaProvider { return null } - static populateCatalogsAndRefreshTableList(callback: any = null, errorCallback: any = null) { + static populateCatalogsAndRefreshTableList( + callback: ((nextCatalogs: Map) => void) | null = null, + errorCallback: ((error: string) => void) | null = null + ) { // refresh catalogs new TrinoQueryRunner() .SetAllResultsCallback((results: any[], isError: boolean) => { @@ -73,7 +76,6 @@ class SchemaProvider { this.catalogs.set(catalog.getName(), catalog) } this.lastSchemaFetchError = undefined - callback() // refresh tables and schemas for this catalog new TrinoQueryRunner() @@ -97,7 +99,7 @@ class SchemaProvider { if (!isError) { catalog.clearErrorMessage() } - callback() + callback?.(new Map(this.catalogs)) }) .SetErrorMessageCallback((error: string) => { catalog.setErrorMessage(error.toString()) @@ -111,7 +113,7 @@ class SchemaProvider { }) .SetErrorMessageCallback((error: string) => { this.lastSchemaFetchError = error.toString() - errorCallback(error.toString()) + errorCallback?.(error.toString()) }) .StartQuery('select catalog_name, connector_name from system.metadata.catalogs') } diff --git a/precise/src/style/components.css b/precise/src/style/components.css deleted file mode 100644 index 57a1d65..0000000 --- a/precise/src/style/components.css +++ /dev/null @@ -1,201 +0,0 @@ -/** - * components.css - * Styles for reusable UI components and utility classes - */ - -.collapse-button { - background-color: var(--dark-gray); - color: var(--highlight-blue); - border-color: var(--light-gray); - font-size: large; - border-radius: 0px 10px 10px 0px; - padding: 0.5em; - cursor: pointer; - text-align: center; - vertical-align: middle; - position: fixed; - left: 0; - bottom: 0; - z-index: 1000; -} - -.button-align-right { - padding-left: 1vw; - bottom: 0; -} - -.small-rounded-dark-grey-button { - background-color: var(--very-dark-gray); - color: var(--muted-text-color); - font-size: large; - border-radius: 10px; - padding: 0em; - cursor: pointer; - width: 1.5em; - height: 1.5em; - border: 1px solid var(--dark-gray); - text-align: center; - vertical-align: middle; - position: absolute; - left: 50%; - line-height: 1.0em; -} - -/* Progress Indicators */ -.spinner { - display: inline-block; - width: 30px; - height: 30px; - border: 3px solid rgba(255, 255, 255, 0.3); - border-radius: 50%; - border-top-color: var(--white); - animation: spin 1s linear infinite; -} - -.progress-percent { - font-weight: bold; - font-size: 1.5em; -} - -.progress-bar { - width: 100%; - border: 1px solid var(--medium-gray); - background-color: var(--dark-accent); - display: grid; - grid-template-columns: 1fr; -} - -.progress-bar-fill { - transition: width 1100ms; - transition-timing-function: linear; - grid-column-start: 0; - left: 0px; - top: 0px; - line-height: 30px; - text-align: center; - bottom: 0px; - width: 0%; - background: var(--brand-gradient); - z-index: 1; - white-space: nowrap; -} - -.progress-bar-running-state { - width: 100%; - transition: opacity 500ms; - transition-timing-function: linear; - grid-column-start: 0; - left: 0px; - top: 0px; - line-height: 30px; - text-align: center; - bottom: 0px; - background: var(--brand-gradient); - z-index: 1; - white-space: nowrap; -} - -.progress-bar-timer { - padding-left: 1em; - font-size: large; -} - -/* Add Query Button */ -.add-query-button { - display: grid; - grid-template-columns: auto; - align-items: center; - width: 100%; - height: 1em; -} - -.add-query-button hr { - border: 0; - height: 1px; - width: 100%; - background: #333; - background-image: linear-gradient(to right, #111, #222, #111); -} - -/* Error Handling */ -.result-cell-null { - color: var(--muted-text-color); - font-style: italic; -} - -/* Links and Text */ -.link-to-query { - font-size: small; - text-align: right; - margin-right: 1em; -} - -.status-text { - color: var(--muted-text-color); - font-size: small; -} - -.read-the-docs { - color: var(--muted-text-color); -} - -.helper-text { - color: #666; - font-size: x-small; -} - -.offset-page-for-copy { - font-size: .875em; - margin-right: .125em; - position: relative; - top: -.25em; - left: -.125em; -} - -.offset-page-for-copy-inner { - position: absolute; - top: .25em; - left: .25em; -} - -/* Utility Classes - Only include the ones actually used in the project */ -.flex { - display: flex; -} - -.items-center { - align-items: center; -} - -.justify-center { - justify-content: center; -} - - button:focus, - button:focus-visible { - outline: 4px auto -webkit-focus-ring-color; - } - - /* Progress bar color consistency */ - .progress-bar { - width: 100%; - border: 1px solid #777; - background-color: #222; - display: grid; - grid-template-columns: 1fr; - } - - .progress-bar-fill { - transition: width 1100ms; - transition-timing-function: linear; - grid-column-start: 0; - left: 0px; - top: 0px; - line-height: 30px; - text-align: center; - bottom: 0px; - width: 0%; - background: var(--brand-gradient); - z-index: 1; - white-space: nowrap; - } \ No newline at end of file diff --git a/precise/src/style/control.css b/precise/src/style/control.css deleted file mode 100644 index 5fc42ca..0000000 --- a/precise/src/style/control.css +++ /dev/null @@ -1,231 +0,0 @@ -/** - * control.css - * Styles for control elements and interactions - */ - -/* Basic Interactive Elements */ -.clickable { - cursor: pointer; -} - -.selectable { - user-select: text; -} - -.non-selectable { - user-select: none; -} - -input:focus { - outline: none; - border-color: var(--highlight-blue); -} - -/* Tab Controls */ -.tab-container { - display: flex; - border-bottom: 1px solid var(--dark-gray); - background-color: var(--subtle-darker-accent-color); -} - -.tab { - padding: 8px 16px; - cursor: pointer; - border-right: 1px solid var(--dark-gray); - user-select: none; -} - -.tab.active { - background-color: var(--lighter-accent-color); - border-bottom: 2px solid var(--highlight-blue); -} - -.tab:hover:not(.active) { - background-color: var(--subtle-lighter-accent-color); -} - -/* Editor Controls */ -.editor-toolbar { - display: flex; - align-items: center; - padding: 4px; - background-color: var(--subtle-darker-accent-color); - border-bottom: 1px solid var(--dark-gray); -} - -.toolbar-button { - background: none; - border: none; - color: var(--muted-text-color); - padding: 4px 8px; - cursor: pointer; - border-radius: 4px; -} - -.toolbar-button:hover { - background-color: var(--subtle-lighter-accent-color); - color: var(--white); -} - -.toolbar-button.active { - background-color: var(--lighter-accent-color); - color: var(--white); -} - -/* Resizable Elements */ -.resizable { - position: relative; -} - -.resize-handle { - position: absolute; - width: 10px; - height: 100%; - right: 0; - top: 0; - cursor: col-resize; - z-index: 10; -} - -.resize-handle-horizontal { - width: 100%; - height: 10px; - left: 0; - bottom: 0; - cursor: row-resize; -} - -/* Context Menus and Dropdowns */ -.context-menu { - position: absolute; - background-color: var(--lighter-accent-color); - border: 1px solid var(--dark-gray); - border-radius: 4px; - z-index: 1000; - box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3); -} - -.menu-item { - padding: 6px 12px; - cursor: pointer; -} - -.menu-item:hover { - background-color: var(--subtle-lighter-accent-color); -} - -.menu-divider { - height: 1px; - background-color: var(--dark-gray); - margin: 4px 0; -} - -/* parent type of small control buttons */ -.small-rounded-button { - background-color: #111; - color: #7d7d7d; - border-color: #689CC5; - font-size: large; - border-radius: 10px; - padding: 0.5em; - cursor: pointer; - height: auto; - text-align: center; - vertical-align: middle; - margin-right: 2px; -} - -.small-rounded-button:hover { - background-color: #333; - /* animate */ - transition: background-color 0.25s; -} - -/* input box with no border and transparent background, no outline when selected */ -.query-title { - padding-left: 1em; - color: #61dafb; - font-weight: 300; - font-size: 1.5em; - border: none; - background-color: transparent; - outline: none; -} - -.card-header { - padding-top: 0.2em; - padding-left: 0.2em; - background-color: #1E1E1E; - right: 0px; - height: 3em; -} - -/* grid containing execute query and title text */ -.card-header-grid { - display: grid; - grid-template-columns: 4em auto 10em 10em 3.75em 5px 3.75em 5px 3.75em 5px 3.75em; - padding-right: 20px; /* to account for scrollbar */ -} - -.query-run-button { - background-color: #111; - color: #689CC5; - border-color: #689CC5; - font-size: large; - border-radius: 10px; - padding: 0.5em; - cursor: pointer; - width: 4em; - height: auto; - text-align: center; - vertical-align: middle; -} - -.query-run-button:hover { - background-color: var(--dark-accent); - color: var(--white); -} - -.query-control-button { - background-color: #111; - color: #689CC5; - border-color: #3f5f79; - font-size: large; - border-radius: 10px; - padding: 0.5em; - cursor: pointer; - width: 100%; - height: 100%; - text-align: center; - vertical-align: middle; - box-sizing: border-box; -} - -.query-control-button:hover { - background-color: var(--dark-accent); - color: var(--white); -} - - -.catalog-setting { - /* align text right */ - text-align: right; -} - -/* Catalog and schema settings */ -.catalog-setting, -.schema-setting { - padding-left: 1em; - color: #777; - font-weight: 300; - font-size: 1em; - border: none; - background-color: transparent; - outline: none; - } - -/* hover over the catalog setting and schema setting to change the color to white */ -.catalog-setting:hover, .schema-setting:hover { - color: #fff; - transition: background-color 0.25s, color 0.25s; -} diff --git a/precise/src/style/layout.css b/precise/src/style/layout.css deleted file mode 100644 index ede5c71..0000000 --- a/precise/src/style/layout.css +++ /dev/null @@ -1,144 +0,0 @@ -/** - * layout.css - * Layout structures and positioning styles - */ - -/* Page Layout */ -.page { - width: 100%; - } - - /* Grid Layout for page with collapsible sidebar */ - .pagegrid { - display: grid; - grid-template-columns: 0vw 100vw; - transition: grid-template-columns 0.1s; - max-width: 100%; - width: 100%; - box-sizing: border-box; - } - - /* For expanded layout */ - .catalog-expanded { - /* Will be applied via JavaScript */ - } - - /* For collapsed layout */ - .catalog-collapsed { - /* Will be applied via JavaScript */ - } - - /* Catalog Sidebar */ - .catalog-container { - width: auto; - height: calc(100vh); - } - - .catalog-wrapper { - overflow-y: auto; - overflow-x: hidden; - width: auto; - background-color: var(--dark-gray); - height: calc(100vh - 3em); - scrollbar-color: var(--medium-gray) var(--dark-gray); - } - - /* Branding and Header */ - .branding-header { - background: var(--brand-gradient); - height: 3em; - width: 100%; - position: fixed; - } - - .branding-padder { - height: 3em; - } - - /* Card Layout */ - .card { - margin: 0px; - } - - /* Editor and Results Layout */ - .query-editor { - margin: 0px; - padding: 0px; - } - - .editorspace { - /* Space for the Monaco editor */ - } - - .resultSetPort { - padding-top: 0em; - } - - /* Spacers and Common Layout Elements */ - .spacer { - margin-bottom: 1em; - } - - /* Status Layouts */ - .status { - display: grid; - grid-template-columns: 60px 60px auto; - align-items: left; - } - - .progress-bar-grid { - display: grid; - grid-template-columns: 90fr 10fr; - align-items: center; - } - - /* Query Status Table Layout */ - .query-status-table { - border-spacing: 0px; - } - - .query-status-table th { - padding: 4px 8px 4px 8px; - color: var(--muted-text-color); - font-size: small; - padding-right: 1em; - text-align: left; - } - - /* Image size modifiers */ - .full-height-image { - height: 100%; - width: auto; - object-fit: contain; - } - - .half-height-image { - height: 50%; - width: auto; - object-fit: contain; - } - - /* Fixes for scrollable areas */ - .scrollable { - overflow-y: auto; - overflow-x: auto; - height: 40vh; - width: 100%; - margin: 0; - padding: 0; - } - - /* Catalog container height */ - .catalog-container { - width: auto; - height: calc(100vh); - } - - .catalog-wrapper { - overflow-y: auto; - overflow-x: hidden; - width: auto; - background-color: var(--dark-gray); - height: calc(100vh - 3em); - scrollbar-color: var(--medium-gray) var(--dark-gray); - } \ No newline at end of file diff --git a/precise/src/style/normalize.css b/precise/src/style/normalize.css deleted file mode 100644 index a0ac59d..0000000 --- a/precise/src/style/normalize.css +++ /dev/null @@ -1,94 +0,0 @@ -/** - * normalize.css - * Base styles and resets for consistent rendering - */ - -/* Reset margins and paddings */ -html, body { - margin: 0; - padding: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; - color: var(--text-color); - background-color: var(--bg-color); - } - - body { - overflow-y: auto; - } - - #root { - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; - color: #fff; - background-color: #121212; - margin: 0; - padding: 0; - max-width: 100%; - overflow-x: hidden; - } - - /* Basic elements styling */ - a { - font-weight: 500; - color: var(--link-color); - text-decoration: inherit; - } - - a:hover { - color: var(--link-hover-color); - } - - button { - border-radius: 8px; - border: 1px solid transparent; - padding: 0.6em 1.2em; - font-size: 1em; - font-weight: 500; - font-family: inherit; - background-color: #1a1a1a; - cursor: pointer; - transition: border-color 0.25s; - } - - button:hover { - border-color: var(--border-color); - } - - button:focus, - button:focus-visible { - outline: 4px auto -webkit-focus-ring-color; - } - - /* Tables */ - table { - border-collapse: collapse; - border-spacing: 0; - width: 100%; - box-sizing: border-box; - color: var(--text-color); - } - - /* Basic animations */ - @keyframes spin { - to { - transform: rotate(360deg); - } - } - - @keyframes logo-spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } - } - - .animate-spin { - animation: spin 1s linear infinite; - } - - @media (prefers-reduced-motion: no-preference) { - a:nth-of-type(2) .logo { - animation: logo-spin infinite 20s linear; - } - } \ No newline at end of file diff --git a/precise/src/style/query-editor.css b/precise/src/style/query-editor.css deleted file mode 100644 index ef51423..0000000 --- a/precise/src/style/query-editor.css +++ /dev/null @@ -1,162 +0,0 @@ -/** - * query-editor.css - * Styles specific to the query editor component - */ - - /* Query title input */ - .query-title { - background-color: transparent; - color: var(--highlight-blue); - border: 0px; - padding: 0px 12px; - font-size: 2em; - width: 100%; - } - - /* Query Editor Area */ - .editorspace { - /* Container for Monaco editor */ - } - - /* SQL Syntax Highlighting */ - .qualifiedName { - color: var(--white) !important; - background-color: var(--success-color); - cursor: pointer !important; - font-weight: bold; - } - - .relationReference { - color: var(--white) !important; - background-color: rgba(0, 0, 255, 0.5); - cursor: pointer !important; - font-weight: bold; - } - - .columnType { - color: var(--muted-text-color); - } - - .columnExtraOrComment { - font-style: italic; - } - - /* Query Stage Indicators */ - .status-stage-default { - border-left: 4px solid var(--lighter-accent-color); - border-top: 1px solid var(--lighter-accent-color); - } - - .status-stage-rows { - border-left: 4px solid var(--rows-color); - border-top: 1px solid var(--rows-color-partial-transparent); - } - - .status-stage-bytes { - border-left: 4px solid var(--bytes-color); - border-top: 1px solid var(--bytes-color-partial-transparent); - } - - .status-stage-splits { - border-left: 4px solid var(--splits-color); - border-top: 1px solid var(--splits-color-partial-transparent); - } - - /* Stage Headers */ - .status-stage-category-header-splits { - border-left: 4px solid var(--splits-color); - text-align: center; - } - - .status-stage-category-header-bytes { - border-left: 4px solid var(--bytes-color); - text-align: center; - } - - .status-stage-category-header-rows { - border-left: 4px solid var(--rows-color); - text-align: center; - } - - /* Stage Row Styles */ - .stage-running td { - padding: 4px 8px 4px 8px; - text-align: left; - } - - .stage-not-running td { - padding: 4px 8px 4px 8px; - color: var(--muted-text-color); - text-align: left; - } - - .substitution-field { - /* Field container styling */ - margin-bottom: 10px; - } - - .substitution-field label { - /* Label styling */ - margin-right: 8px; - } - - .substitution-field input { - /* Input styling */ - padding: 4px 8px; - border-radius: 4px; - border: 1px solid var(--lighter-accent-color); - background-color: var(--subtle-lighter-accent-color); - color: var(--text-color); - } - - /* Add this to your query-editor.css file */ - -.editor-toolbar { - position: absolute; - top: 5px; - right: 25px; - z-index: 1000; - display: flex; - gap: 8px; -} - -.editor-button { - background: none; - border: none; - cursor: pointer; - color: rgba(255, 255, 255, 0.7); - display: flex; - align-items: center; - justify-content: center; - padding: 4px; - border-radius: 4px; - transition: all 0.2s ease; -} - -.editor-button:hover { - background-color: rgba(255, 255, 255, 0.1); - color: white; -} - -.editor-button:active { - background-color: rgba(255, 255, 255, 0.2); -} - -.editor-button[disabled] { - opacity: 0.5; - cursor: not-allowed; -} - -.editor-button[data-tooltip]:hover::after { - content: attr(data-tooltip); - position: absolute; - bottom: -30px; - left: 50%; - transform: translateX(-50%); - background-color: rgba(0, 0, 0, 0.8); - color: white; - padding: 4px 8px; - border-radius: 4px; - font-size: 12px; - white-space: nowrap; -} \ No newline at end of file diff --git a/precise/src/style/results.css b/precise/src/style/results.css deleted file mode 100644 index 8c69fbd..0000000 --- a/precise/src/style/results.css +++ /dev/null @@ -1,231 +0,0 @@ -/** - * results.css - * Styles for the query results display - */ - -/* Results Container */ -.result-set { - width: 100%; - overflow-x: auto; - box-sizing: border-box; - padding: 0; - margin: 0; - position: relative; /* For positioning clear and copy buttons */ - } - - .result-table-container { - width: 100%; - overflow-x: auto; - margin: 0; - padding: 0; - } - - /* Results Table */ - .result-table { - table-layout: fixed; - width: 100%; - min-width: 100%; - border-collapse: collapse; - } - - .result-set table { - border-collapse: collapse; - border-spacing: 0; - width: 100%; - box-sizing: border-box; - } - - .result-set tr, - .result-set td, - .result-set th { - box-sizing: border-box; - } - - /* Table Rows & Cells */ - .result-set tr:nth-child(even) td { - background-color: var(--subtle-lighter-accent-color); - } - - .result-set tr:nth-child(odd) td { - background-color: var(--lighter-accent-color); - } - - .result-set td { - padding: 10px; - border: 1px solid var(--lighter-accent-color); - text-align: left; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - } - - .result-set th { - padding: 10px; - text-align: left; - background-color: var(--subtle-darker-accent-color); - color: darkgray; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - } - - /* Null Values */ - .result-cell-null { - color: var(--muted-text-color); - font-style: italic; - } - - /* Clear Results Button */ - .clear-result-table { - position: absolute; - right: 0; - max-width: calc(100% - 20px); - color: var(--muted-text-color); - font-size: small; - cursor: pointer; - margin-right: 1em; - } - - /* Stats Display */ - .stats { - margin: 0em; - } - - /* Collapsed Display */ - .displaydefaultcollapsed { - display: none; - } - - /* Reload Link */ - .reload-link-div { - text-align: right; - float: right; - padding-right: 0.5em; - cursor: pointer; - font-size: small; - color: var(--error-color-subtle); - } - - .reload-link-div:hover { - color: var(--white); - } - - /* Results table structure improvements */ -.result-set tr, .result-set td, .result-set th { - box-sizing: border-box; - } - - .result-set table { - border-collapse: collapse; - border-spacing: 0; - width: 100%; - box-sizing: border-box; - } - - /* Adding missing hover style */ - .reload-link-div:hover { - color: var(--white); - } - - /* Fix table container sizing */ - .result-table-container { - width: 100%; - overflow-x: auto; - margin: 0; - padding: 0; - } - - /* Fix copy link formatting */ - .offset-page-for-copy { - font-size: .875em; - margin-right: .125em; - position: relative; - top: -.25em; - left: -.125em; - } - - .offset-page-for-copy-inner { - position: absolute; - top: .25em; - left: .25em; - } - - /* Helper text formatting */ - .helper-text { - color: #666; - font-size: x-small; - } - - /* Shared styles for action buttons (copy and clear) */ -.result-action-button { - position: absolute; - background-color: rgba(40, 40, 40, 0.6); - color: rgba(200, 200, 200, 0.8); - padding: 8px 12px; - border-radius: 4px; - font-size: small; - cursor: pointer; - display: flex; - align-items: center; - justify-content: center; - transition: all 0.2s ease-in-out; - backdrop-filter: blur(2px); - z-index: 10; - box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); - right: 10px; /* Positioned on the right */ - width: auto; /* Allow content to determine width */ - white-space: nowrap; /* Keep text on one line */ - } - - - .result-action-button:hover { - transform: scale(1.15); - background-color: rgba(60, 60, 60, 0.8); - color: white; - box-shadow: 0 3px 8px rgba(0, 0, 0, 0.3); - } - - .copy-link { - position: absolute; - top: 2px; - right: 10px; - max-width: calc(100% - 20px); - } - - .copy-link.copied { - animation: action-pulse 0.3s ease-in-out; - background-color: rgba(40, 100, 40, 0.8); - } - - /* Clear button specific styles */ - .clear-result-table { - top: 2px; - margin-right: 80px; - } - - .clear-result-table.confirmed { - animation: action-pulse 0.3s ease-in-out; - background-color: rgba(120, 40, 40, 0.8); - } - - /* Shared animation for feedback */ - @keyframes action-pulse { - 0% { transform: scale(1.15); } - 50% { transform: scale(1.3); } - 100% { transform: scale(1.15); } - } - - /* Icon styling */ - .action-icon { - margin-right: 6px; - } - - /* Text label styling */ - .action-text { - user-select: none; - } - - /* Make sure the result container has proper positioning context */ - .result-set { - position: relative; - } \ No newline at end of file diff --git a/precise/src/style/theme.css b/precise/src/style/theme.css deleted file mode 100644 index a2eb627..0000000 --- a/precise/src/style/theme.css +++ /dev/null @@ -1,66 +0,0 @@ -/** - * theme.css - * Contains all theme variables and color definitions - */ - - :root { - /* Base typography */ - font-weight: 400; - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - - /* Color scheme */ - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: #242424; - - /* Brand Colors */ - --bytes-color: #1C364D; - --bytes-color-partial-transparent: rgba(28, 54, 77, 0.5); - --rows-color: #0C61A6; - --rows-color-partial-transparent: rgba(12, 97, 166, 0.5); - --splits-color: #564682; - --splits-color-partial-transparent: rgba(86, 70, 130, 0.5); - - /* UI Colors */ - --link-color: #5bc0de; - --link-hover-color: #747bff; - --border-color: #646cff; - --subtle-lighter-accent-color: #1e1e1e; - --lighter-accent-color: #2c2c2c; - --subtle-darker-accent-color: #131313; - - /* Text Colors */ - --muted-text-color: #888; - --white: #fff; - - /* Gradient */ - --brand-gradient: linear-gradient(45deg, #564682, #1C2F44, #1C364D, #0C61A6); - - /* Structural Colors */ - --dark-gray: #333; - --medium-gray: #555; - --light-gray: #666; - --very-dark-gray: #111; - --dark-accent: #222; - --highlight-blue: #689CC5; - - /* Success/Error States */ - --success-color: rgba(1, 123, 15, 0.5); - --error-color-subtle: #999; -} - -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - a:hover { - color: #747bff; - } - button { - background-color: #f9f9f9; - } -} \ No newline at end of file diff --git a/precise/src/theme.tsx b/precise/src/theme.tsx new file mode 100644 index 0000000..ebdf6b0 --- /dev/null +++ b/precise/src/theme.tsx @@ -0,0 +1,45 @@ +import { createTheme } from '@mui/material/styles' +import darkScrollbar from '@mui/material/darkScrollbar' + +export const lightTheme = createTheme({ + palette: { + mode: 'light', + primary: { + main: '#0b1367', + }, + secondary: { + main: '#f50057', + }, + }, + components: { + MuiLink: { + styleOverrides: { + root: { + color: '#f50057', + textDecoration: 'none', + }, + }, + }, + }, +}) + +export const darkTheme = createTheme({ + palette: { + mode: 'dark', + }, + components: { + MuiLink: { + styleOverrides: { + root: { + color: '#dd33fa', + textDecoration: 'none', + }, + }, + }, + MuiCssBaseline: { + styleOverrides: { + body: darkScrollbar(), + }, + }, + }, +}) diff --git a/precise/src/utils/ClearButton.tsx b/precise/src/utils/ClearButton.tsx index 89031ca..6809022 100644 --- a/precise/src/utils/ClearButton.tsx +++ b/precise/src/utils/ClearButton.tsx @@ -1,5 +1,7 @@ import React, { useState } from 'react' -import { Trash2, AlertTriangle } from 'lucide-react' +import { Button, Tooltip } from '@mui/material' +import DeleteOutlineIcon from '@mui/icons-material/DeleteOutline' +import WarningAmberIcon from '@mui/icons-material/WarningAmber' interface ClearButtonProps { onClear: () => void @@ -19,23 +21,18 @@ const ClearButton: React.FC = ({ onClear }) => { } return ( -
- {confirming ? ( - <> - - Confirm - - ) : ( - <> - - Clear - - )} -
+ + + ) } diff --git a/precise/src/utils/CopyLink.tsx b/precise/src/utils/CopyLink.tsx index 790032a..06d8fe0 100644 --- a/precise/src/utils/CopyLink.tsx +++ b/precise/src/utils/CopyLink.tsx @@ -1,5 +1,7 @@ import React, { useState } from 'react' -import { Copy, CheckCircle } from 'lucide-react' +import { Button, Tooltip } from '@mui/material' +import CopyAllOutlinedIcon from '@mui/icons-material/CopyAllOutlined' +import DoneOutlinedIcon from '@mui/icons-material/DoneOutlined' interface CopyLinkProps { copy: () => void @@ -15,23 +17,24 @@ const CopyLink: React.FC = ({ copy }) => { } return ( -
- {copied ? ( - <> - - Copied! - - ) : ( - <> - - Copy - - )} -
+ + + ) } diff --git a/precise/src/utils/ErrorBoxProvider.tsx b/precise/src/utils/ErrorBoxProvider.tsx deleted file mode 100644 index 5d7bdca..0000000 --- a/precise/src/utils/ErrorBoxProvider.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import React, { useState } from 'react' -import CloseIcon from '../assets/close.png' -import './errorbox.css' - -interface ErrorBoxProviderProps { - errorMessage: string - errorContext: string -} - -const ErrorBox: React.FC = ({ errorMessage, errorContext }) => { - const [isVisible, setIsVisible] = useState(true) - const [errorTimestamp] = useState(new Date().toISOString()) // Capture timestamp when error occurs - - if (!errorMessage || !isVisible) { - return null - } - - return ( -
-
- Error: {errorContext} -
setIsVisible(false)} - role="button" - aria-label="Close error message" - > - Close -
-
-
-
- {errorMessage} -
{errorTimestamp}
-
-
-
- ) -} - -export default ErrorBox diff --git a/precise/src/utils/ProgressBar.tsx b/precise/src/utils/ProgressBar.tsx deleted file mode 100644 index 9a7cada..0000000 --- a/precise/src/utils/ProgressBar.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import * as React from 'react' - -// ProgressBar properties -interface ProgressBarProps { - progress: number - state: string -} - -// ProgressBar state -interface ProgressBarState {} - -export default class ProgressBar extends React.Component { - constructor(props: ProgressBarProps) { - super(props) - this.state = { - progress: 0, - } - } - - render() { - return ( -
- {this.props.progress === 0 && Number.isFinite(this.props.progress) ? ( -
{this.props.state}
- ) : ( -
- {Math.round(this.props.progress) + '%'} -
- )} -
- ) - } -} diff --git a/precise/src/utils/ResizableContainer.tsx b/precise/src/utils/ResizableContainer.tsx deleted file mode 100644 index 4268c8a..0000000 --- a/precise/src/utils/ResizableContainer.tsx +++ /dev/null @@ -1,83 +0,0 @@ -import React, { useState, useRef, useEffect } from 'react' - -interface ResizableContainerProps { - children: React.ReactNode - initialHeight: string - minHeight?: string - maxHeight?: string - onHeightChange: (newHeight: string) => void -} - -const ResizableContainer: React.FC = ({ - children, - initialHeight, - minHeight = '100px', - maxHeight = '80vh', - onHeightChange, -}) => { - const [height, setHeight] = useState(initialHeight) - const containerRef = useRef(null) - const resizeHandleRef = useRef(null) - - useEffect(() => { - const container = containerRef.current - const resizeHandle = resizeHandleRef.current - let isResizing = false - let startY: number - let startHeight: number - - const onMouseDown = (e: MouseEvent) => { - isResizing = true - startY = e.clientY - startHeight = container!.getBoundingClientRect().height - document.addEventListener('mousemove', onMouseMove) - document.addEventListener('mouseup', onMouseUp) - } - - const onMouseMove = (e: MouseEvent) => { - if (!isResizing) return - const diff = e.clientY - startY - const newHeight = startHeight + diff - const minHeightPx = parseInt(minHeight) - const maxHeightPx = parseInt(maxHeight) - const clampedHeight = Math.max(minHeightPx, Math.min(maxHeightPx, newHeight)) - const newHeightString = `${clampedHeight}px` - setHeight(newHeightString) - onHeightChange(newHeightString) - } - - const onMouseUp = () => { - isResizing = false - document.removeEventListener('mousemove', onMouseMove) - document.removeEventListener('mouseup', onMouseUp) - } - - resizeHandle?.addEventListener('mousedown', onMouseDown) - - return () => { - resizeHandle?.removeEventListener('mousedown', onMouseDown) - document.removeEventListener('mousemove', onMouseMove) - document.removeEventListener('mouseup', onMouseUp) - } - }, [minHeight, maxHeight, onHeightChange]) - - return ( -
- {children} -
-
- ) -} - -export default ResizableContainer diff --git a/precise/src/utils/errorbox.css b/precise/src/utils/errorbox.css deleted file mode 100644 index 9f89172..0000000 --- a/precise/src/utils/errorbox.css +++ /dev/null @@ -1,40 +0,0 @@ -.error-box { - background-color: #2b2b2b; - border: 1px solid #ff6b6b; - border-radius: 4px; - margin: 10px; - padding: 10px; -} - -.error-box-header { - color: #ff6b6b; - display: flex; - justify-content: space-between; - align-items: center; - font-weight: bold; - margin-bottom: 8px; -} - -.error-box-close { - cursor: pointer; - opacity: 0.8; - transition: opacity 0.2s; -} - -.error-box-close:hover { - opacity: 1; -} - -.error-box-body { - color: #ff9999; -} - -.error-box-message { - margin-bottom: 8px; -} - -.error-box-context { - color: #999; - font-size: 0.9em; - margin-top: 8px; -} \ No newline at end of file diff --git a/precise/vite.config.ts b/precise/vite.config.ts index d12a4f7..2675219 100644 --- a/precise/vite.config.ts +++ b/precise/vite.config.ts @@ -4,7 +4,6 @@ import react from '@vitejs/plugin-react' // Used for local debugging against Trino also running on localhost at port 8080: // https://vitejs.dev/config/ export default defineConfig({ - base: '/query/', plugins: [react()], server: { proxy: { @@ -15,6 +14,34 @@ export default defineConfig({ }, }, }, + build: { + lib: { + entry: "src/index.ts", + name: "QueryEditor", + fileName: "index" + }, + rollupOptions: { + // Don’t bundle peer dependencies like React + external: [ + "react", + "react-dom", + "react-dom/client", + "react-dom/server", + "react/jsx-runtime", + "react/jsx-dev-runtime" + ], + output: { + globals: { + react: "React", + "react-dom": "ReactDOM", + "react-dom/client": "ReactDOMClient", + "react-dom/server": "ReactDOMServer", + "react/jsx-runtime": "jsxRuntime", + "react/jsx-dev-runtime": "jsxDevRuntime" + } + } + } + }, }); // Used for integration into Trino @@ -22,4 +49,4 @@ export default defineConfig({ // export default defineConfig({ // base: '/query/', // This tells your app it's served from the /query/ path // plugins: [react()] -// }); \ No newline at end of file +// });