commit c17f4f442641b089fd100d4d7d1b7419cc43e574 Author: Glcoin Core Developer Team Date: Tue May 26 14:35:16 2026 +0200 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f95dec0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,41 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# production +/build +dist +/result + +# misc +.env +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local + +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# yarn +.yarn/* +!.yarn/patches +!.yarn/releases +!.yarn/plugins +!.yarn/sdks +!.yarn/versions +/test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ + +# devenv +.devenv* diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..134f500 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Christoph Stenglein + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..bd48979 --- /dev/null +++ b/README.md @@ -0,0 +1,170 @@ +

RaspiBlesk Web - a responsive Web UI for RaspiBlesk

+ +![RaspiBlesk Dashboard](preview.png) + +In collaboration with [Bitcoin Design](https://bitcoin.design/). + +Source code: [forge.618.ch/raspiblesk/raspiblesk-web](https://forge.618.ch/raspiblesk/raspiblesk-web) + +Built with [React](https://reactjs.org/) & [Tailwind CSS](https://tailwindcss.com/). + +## Translations + +If you want to bring the RaspiBlesk WebUI to other languages, please help us translate it via [Weblate](https://hosted.weblate.org/projects/raspiblitz-web/translations/) :) + +Big thanks to our translators, which you can find in this [README](src/i18n/README.md). + +## Development + +### Dependencies + +- [Node.js](https://nodejs.org/en/download/) +- [asdf](https://asdf-vm.com/) is supported but not required. +- [Nix](https://nixos.org/download.html) with [Flakes](https://nixos.wiki/wiki/Flakes) enabled (optional, for devenv.sh or NixOS builds) + +#### Update npm dependencies + +```sh +npm update +``` + +### Development with devenv.sh + +This project supports [devenv.sh](https://devenv.sh/), a developer environment tool built on Nix. + +#### Setup + +1. Install devenv.sh by following the instructions at https://devenv.sh/getting-started/ +2. Run `devenv shell` to enter the development environment +3. Devenv will install the npm dependencies automatically when entering the shell. To change this behaviour, change `javascript.npm.install.enable = true;` to `false` and run `npm install` after entering the shell. + +#### Benefits of using devenv.sh + +- Consistent development environment across all contributors +- Automatically installs the correct version of Node.js and other dependencies +- Includes development tools like TypeScript, ESLint, and Nix utilities +- Works on any platform that supports Nix (Linux, macOS, WSL) + +### Dev workflow + +### Simple dev setup + +```bash +npm install +cd backend-mock +npm install +cd .. +npm run dev:local +``` + +The `npm run dev:local` command starts the frontend and the backend mock server. + +The backend mock server restarts automatically when you change a file in the `backend-mock` folder. + +#### Frontend + +```bash +npm install +npm run start +``` + +#### Backend + +For the backend, there currently exist three options: + +- Use an existing RaspiBlesk + - Easy to setup, but needs a RaspiBlesk +- Using the provided [Mock backend](#mock-backend) + - Easy to setup, but limited data +- Using [blitz_api](#blitz-api) with Polar + - Some changes needed for local development + - Possibly more data (depending on your ln setup :) ) + +##### Mock backend + +See [backend-mock folder](./backend-mock) + +Open another terminal + +```sh +cd backend-mock +npm install +npm run start +``` + +Then go to `http://localhost:3000` and use the password `password`. + +### Testing + +#### Unit tests + +`npm test` + +#### E2E tests + +Run tests headless:\ +`npx playwright test` + +Run test with UI:\ +`npx playwright test --ui` + +##### Blesk API + +This guide uses Polar for easier development, but you can also use a real lightning node. + +- Download [Polar](https://lightningpolar.com/) and run it. + - Create at least one bitcoin and one lightning node. +- Clone the [blitz_api](https://github.com/fusion44/blitz_api) and install the dependencies. + - In addition, you will need [redis](https://redis.io/) installed for `blitz_api` to work. +- Create a `.env` file (see [.env_sample in blitz_api](https://github.com/fusion44/blitz_api/blob/main/.env_sample)) and copy the bitcoin and ln info into it. + - Important: When definining `shell_script_path` you need to define a directory where a folder called `config.scripts` and a file called `blesk.debug.sh` reside in. Otherwise `blitz_api` may not work (used on the RaspiBlesk for logging) +- Make the following change in `blitz_api`: + - In [main/app/main.py](https://github.com/fusion44/blitz_api/blob/main/app/main.py#L48), change the `prefix_format` from `/v{major}` to `/api/v{major}`. +- Change the `BACKEND_SERVER` value in [vite.config.ts](vite.config.ts) to your local `blitz_api` installation. + +Now you can start the `blitz_api` and run `npm run start` in raspiblesk-web. + +Please do not commit the above changes. + +### Use a external RaspiBlesk as Backend + +- (Optional): Make sure [asdf](https://asdf-vm.com/) is installed +- (Optional): Run `asdf install nodejs latest:20` +- Install the dependencies with `npm install` +- Change the `BACKEND_SERVER` value in [vite.config.ts](vite.config.ts) to your local RaspiBlesk - for example if your RaspiBlesk is running on local IP `192.168.1.123` then change the value to `http://192.168.1.123:80` +- with `npm run start` it should now connect to your external RaspiBlesk + +## Credits & Licenses + +### Icons + +- RaspiBlitz Icon from [RaspiBlitz](https://github.com/rootzoll/raspiblitz) + - [MIT License](https://github.com/rootzoll/raspiblitz/blob/v1.10/LICENSE) +- Other icons from [Hero Icons](https://heroicons.com/) & [BitcoinDesign Icons](https://github.com/bitcoindesign/bitcoin-icons) + - [MIT License Hero Icons](https://github.com/tailwindlabs/heroicons/blob/master/LICENSE) + - [MIT License Bitcoin-Icons](https://github.com/BitcoinDesign/Bitcoin-Icons/blob/main/LICENSE) +- CSS Loading Spinner from [loading.io](https://loading.io/css/) + - [CC0 License](https://loading.io/css/) +- ButtonSpinner from [SpinKit](https://github.com/tobiasahlin/SpinKit) + - [MIT License](https://github.com/tobiasahlin/SpinKit/blob/master/LICENSE) + +### App logos + +- BTC RPC Logo from [Bitcoin Explorer](https://bitcoinexplorer.org) + - [MIT License](https://github.com/janoside/btc-rpc-explorer) +- BTCPay Logo from [btcpayserver](https://github.com/btcpayserver/btcpayserver) + - [MIT License](https://github.com/btcpayserver/btcpayserver/blob/master/LICENSE) +- RTL Logo from [RTL](https://github.com/Ride-The-Lightning/RTL) + - [MIT License](https://github.com/Ride-The-Lightning/RTL/blob/master/LICENSE) +- Specter Logo from [specter-desktop](https://github.com/cryptoadvance/specter-desktop) + - [MIT License](https://github.com/cryptoadvance/specter-desktop/blob/master/LICENSE) +- Mempool.space Logo from [mempool](https://github.com/mempool/mempool) + - [Mempool.space Trademark Policy](https://mempool.space/trademark-policy) +- LNbits Logo from [lnbits-legend](https://github.com/lnbits/lnbits-legend) + - [MIT License](https://github.com/lnbits/lnbits-legend/blob/master/LICENSE) +- LND Logo from [LightningLabs](https://github.com/lightningnetwork/lnd) + - [MIT License (?)](https://github.com/lightningnetwork/lnd/blob/master/LICENSE) +- Core Lightning Logo from [Blockstream](https://blockstream.com/) + - [Blockstream Corporate Brand Guideline](https://blockstream.com/brand-assets/) +- Alby Logo from [Alby media repo](https://github.com/getAlby/media) + - License unclear diff --git a/biome.json b/biome.json new file mode 100644 index 0000000..9605993 --- /dev/null +++ b/biome.json @@ -0,0 +1,33 @@ +{ + "$schema": "https://biomejs.dev/schemas/2.1.4/schema.json", + "vcs": { + "enabled": false, + "clientKind": "git", + "useIgnoreFile": false + }, + "files": { + "ignoreUnknown": false, + "includes": ["**", "!**/backend-mock"] + }, + "formatter": { + "enabled": true, + "indentStyle": "space" + }, + "assist": { "actions": { "source": { "organizeImports": "on" } } }, + "linter": { + "enabled": true, + "rules": { + "recommended": true + } + }, + "javascript": { + "formatter": { + "quoteStyle": "double" + } + }, + "css": { + "parser": { + "tailwindDirectives": true + } + } +} diff --git a/default.nix b/default.nix new file mode 100644 index 0000000..d31cdf5 --- /dev/null +++ b/default.nix @@ -0,0 +1,29 @@ +{ + lib, + config, + dream2nix, + ... +}: { + imports = [ + dream2nix.modules.dream2nix.nodejs-package-lock-v3 + dream2nix.modules.dream2nix.nodejs-granular-v3 + ]; + + mkDerivation = { + src = ./build; + }; + + deps = {nixpkgs, ...}: { + inherit + (nixpkgs) + stdenv + ; + }; + + nodejs-package-lock-v3 = { + packageLockFile = "${config.mkDerivation.src}/package-lock.json"; + }; + + name = "raspiblitz-web"; + version = "1.3.0-dev"; +} diff --git a/devenv.lock b/devenv.lock new file mode 100644 index 0000000..5bda4b0 --- /dev/null +++ b/devenv.lock @@ -0,0 +1,103 @@ +{ + "nodes": { + "devenv": { + "locked": { + "dir": "src/modules", + "lastModified": 1742320965, + "owner": "cachix", + "repo": "devenv", + "rev": "6bde92766ddd3ee1630029a03d36baddd51934e2", + "type": "github" + }, + "original": { + "dir": "src/modules", + "owner": "cachix", + "repo": "devenv", + "type": "github" + } + }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1733328505, + "owner": "edolstra", + "repo": "flake-compat", + "rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "git-hooks": { + "inputs": { + "flake-compat": "flake-compat", + "gitignore": "gitignore", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1742300892, + "owner": "cachix", + "repo": "git-hooks.nix", + "rev": "ea26a82dda75bee6783baca6894040c8e6599728", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "git-hooks.nix", + "type": "github" + } + }, + "gitignore": { + "inputs": { + "nixpkgs": [ + "git-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1733477122, + "owner": "cachix", + "repo": "devenv-nixpkgs", + "rev": "7bd9e84d0452f6d2e63b6e6da29fe73fac951857", + "type": "github" + }, + "original": { + "owner": "cachix", + "ref": "rolling", + "repo": "devenv-nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "devenv": "devenv", + "git-hooks": "git-hooks", + "nixpkgs": "nixpkgs", + "pre-commit-hooks": [ + "git-hooks" + ] + } + } + }, + "root": "root", + "version": 7 +} diff --git a/devenv.nix b/devenv.nix new file mode 100644 index 0000000..99e7f52 --- /dev/null +++ b/devenv.nix @@ -0,0 +1,37 @@ +{ + pkgs, + lib, + config, + ... +}: { + # https://devenv.sh/languages/javascript/ + languages = { + nix = { + enable = true; + lsp.package = pkgs.nixd; + }; + + javascript = { + enable = true; + npm = { + enable = true; + install.enable = true; + }; + }; + + typescript = { + enable = true; + }; + }; + + packages = [ + pkgs.typescript + pkgs.eslint_d + pkgs.biome + pkgs.vscode-js-debug + pkgs.statix + pkgs.alejandra + pkgs.nixd + pkgs.statix + ]; +} diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..a625c25 --- /dev/null +++ b/flake.lock @@ -0,0 +1,61 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1742288794, + "narHash": "sha256-Txwa5uO+qpQXrNG4eumPSD+hHzzYi/CdaM80M9XRLCo=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "b6eaf97c6960d97350c584de1b6dcff03c9daf42", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..aa537ac --- /dev/null +++ b/flake.nix @@ -0,0 +1,69 @@ +{ + description = "A mobile-first responsive Web UI for the RaspiBlitz"; + + inputs = { + flake-utils.url = "github:numtide/flake-utils"; + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + }; + + outputs = inputs @ { + self, + nixpkgs, + flake-utils, + }: let + name = "blitz-web"; + + systems = + flake-utils.lib.eachDefaultSystem + (system: let + pkgs = nixpkgs.legacyPackages.${system}; + in { + packages = { + default = self.packages.${system}.${name}; + ${name} = + pkgs.buildNpmPackage + { + name = "${name}"; + buildInputs = [pkgs.nodejs_22]; + src = ./.; + + npmDepsHash = "sha256-DT5+1KH06cMLHgMMPIiL1LMfxoOM4i15Z1MQok/eLS8="; + + preBuild = '' + sed -i "s(const BACKEND_SERVER = "http://localhost:8000";(const BACKEND_SERVER = "http://127.0.0.1";(" vite.config.ts + ''; + + installPhase = '' + mkdir $out + npm run build + cp -r build/* $out + ''; + }; + }; + + devShells.default = pkgs.mkShell { + inputsFrom = [self.packages.${system}.${name}]; + packages = with pkgs; [nodejs_22 alejandra]; + }; + }); + + overlays.overlays = { + default = final: prev: { + ${name} = self.packages.${prev.stdenv.hostPlatform.system}.${name}; + }; + }; + + module = { + nixosModules.default = { + pkgs, + lib, + config, + ... + }: { + imports = [./modules/raspiblitz-web.nix]; + nixpkgs.overlays = [self.overlays.default]; + }; + }; + in + systems // overlays // module; +} diff --git a/index.html b/index.html new file mode 100644 index 0000000..cf55cc1 --- /dev/null +++ b/index.html @@ -0,0 +1,26 @@ + + + + + + + + + + + + RaspiBlesk + + + + +
+ + + diff --git a/modules/raspiblitz-web.nix b/modules/raspiblitz-web.nix new file mode 100644 index 0000000..d0bf6ee --- /dev/null +++ b/modules/raspiblitz-web.nix @@ -0,0 +1,72 @@ +{ + config, + pkgs, + lib, + ... +}: let + name = "blitz-web"; + cfg = config.services.${name}; + + inherit (lib) mkOption mkIf mkEnableOption types literalExpression; +in { + options = { + services.${name} = { + enable = mkEnableOption "${name}"; + + package = mkOption { + type = types.package; + defaultText = literalExpression "pkgs.${name}"; + default = pkgs.${name}; + description = "The ${name} package to use."; + }; + + nginx = { + enable = mkEnableOption "Whether to enable nginx server for ${name}."; + description = "This is used to generate the nginx configuration."; + + hostName = mkOption { + type = types.str; + example = "my.node.net"; + default = "localhost"; + description = "The hostname to use for the nginx virtual host."; + }; + + location = mkOption { + type = types.str; + example = "/"; + default = "/"; + description = "The location to serve the webui fronted from."; + }; + + openFirewall = mkOption { + type = types.bool; + default = false; + description = "Whether to open the ports used by ${name} in the firewall for the server"; + }; + }; + }; + }; + + config = mkIf cfg.enable { + services.nginx = mkIf cfg.nginx.enable { + enable = true; + virtualHosts.${cfg.nginx.hostName} = { + forceSSL = false; + enableACME = false; + + locations."${cfg.nginx.location}" = { + root = "${pkgs.${name}}"; + extraConfig = '' + # Forward any unknown urls to the UI. + # Client side routing of react will fail otherwise. + try_files $uri /index.html; + ''; + }; + }; + }; + + networking.firewall = mkIf cfg.nginx.openFirewall { + allowedTCPPorts = [80]; + }; + }; +} diff --git a/openapi.json b/openapi.json new file mode 100644 index 0000000..8d80af6 --- /dev/null +++ b/openapi.json @@ -0,0 +1 @@ +{"openapi":"3.1.0","info":{"title":"FastAPI","version":"0.1.0"},"servers":[{"url":"/api"}],"paths":{"/apps/status":{"get":{"tags":["Apps"],"summary":"Get the status of all available apps.","operationId":"apps_status_apps_status_get","responses":{"200":{"description":"\nReturns a JSON list with the current status of all available apps\n```\n{\n \"data\": [\n {\n \"id\": \"btcpayserver\",\n \"version\": \"v1.13.0\",\n \"installed\": false,\n \"configured\": false,\n \"status\": \"offline\",\n \"local_ip\": null,\n \"http_port\": null,\n \"https_port\": null,\n \"https_forced\": null,\n \"https_self_signed\": null,\n \"hidden_service\": null,\n \"address\": null,\n \"auth_method\": null,\n \"details\": null,\n \"error\": null\n },\n {\n \"id\": \"btc-rpc-explorer\",\n \"version\": \"v3.4.0\",\n \"installed\": false,\n \"configured\": false,\n \"status\": \"offline\",\n \"local_ip\": null,\n ...\n },\n ...\n ],\n \"errors\": [\n {\n \"id\": \"rtl\",\n \"error\": \"App status script execution failed.\n├╴at /home/blitzapi/blitz_api/app/apps/impl/raspiblitz.py:92:10\n├╴script_name: /home/admin/config.scripts/bonus.rtl.sh status\n│\n╰─▶ 500: Something went wrong!\n ╰╴at /home/blitzapi/blitz_api/app/apps/impl/raspiblitz.py:92:10\"\n },\n ...\n ]\n}\n```\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppStatusQueryResult"}}}}},"security":[{"JWTBearer":[]}]}},"/apps/update-cache":{"post":{"tags":["Apps"],"summary":"Update the app status cache. Results will be broadcasted to SSE clients.","operationId":"apps_update_cache_apps_update_cache_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"JWTBearer":[]}]}},"/apps/status/{id}":{"get":{"tags":["Apps"],"summary":"Get the status of a single app by id.","operationId":"apps_status_apps_status__id__get","security":[{"JWTBearer":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"title":"Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppStatus"}}}},"404":{"description":"If no or an invalid app id is given."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/apps/status_advanced/{id}":{"get":{"tags":["Apps"],"summary":"Get the advanced status of a single app by id.","description":"Some apps might give status information that is computationally\n to expensive to include in the normal status endpoint.\n\n Available app ids for this endpoint:\n - electrs\n\n> ℹ️ _This endpoint is not implemented on all platforms_","operationId":"apps_status_advanced_apps_status_advanced__id__get","security":[{"JWTBearer":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","required":true,"title":"Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"404":{"description":"If no or an invalid app id is given."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/apps/install/{app_id}":{"post":{"tags":["Apps"],"summary":"Install an app","description":"Attempts to install an app. The installation process results are\n not returned on this endpoint. Instead, the results are communicated via the SSE\n channels. This call only verifies if the app is available for installation on the\n given platform.","operationId":"apps_install_apps_install__app_id__post","security":[{"JWTBearer":[]}],"parameters":[{"name":"app_id","in":"path","required":true,"schema":{"$ref":"#/components/schemas/AppId"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"400":{"description":"If the app is already installed or not available for the platform."},"404":{"description":"If no or an invalid app id is given."},"423":{"description":"If an app install task is already running."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/apps/uninstall":{"post":{"tags":["Apps"],"summary":"Uninstall app","description":"Attempts to uninstall an app. The uninstallation process results are\n not returned on this endpoint. Instead, the results are communicated via the SSE\n channels. This call only verifies if the app is available for uninstallation on the\n given platform.","operationId":"apps_uninstall_apps_uninstall_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppUninstallInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"400":{"description":"If the app is already installed."},"404":{"description":"If no or an invalid app id is given."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"JWTBearer":[]}]}},"/bitcoin/btc-info":{"get":{"tags":["Bitcoin Core"],"summary":"Bitcoin.Btc-Info","description":"Get general information about bitcoin core. Combines most important information from `getblockchaininfo` and `getnetworkinfo`","operationId":"bitcoin_btc_info_bitcoin_btc_info_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BtcInfo"}}}}},"security":[{"JWTBearer":[]}]}},"/bitcoin/get-block-count":{"get":{"tags":["Bitcoin Core"],"summary":"Get the current block count","description":"See documentation on [bitcoincore.org](https://bitcoincore.org/en/doc/0.21.0/rpc/blockchain/getblockcount/)","operationId":"bitcoin_get_block_count_bitcoin_get_block_count_get","responses":{"200":{"description":"A JSON String with relevant information.\n\n```json\n{\n \"result\": 682621,\n \"error\": null,\n \"id\": 0\n}\n","content":{"application/json":{"schema":{}}}}},"security":[{"JWTBearer":[]}]}},"/bitcoin/get-blockchain-info":{"get":{"tags":["Bitcoin Core"],"summary":"Get the current blockchain status","description":"See documentation on [bitcoincore.org](https://bitcoincore.org/en/doc/0.21.0/rpc/blockchain/getblockchaininfo/)","operationId":"bitcoin_get_blockchain_info_bitcoin_get_blockchain_info_get","responses":{"200":{"description":"A JSON String with relevant information.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BlockchainInfo"}}}}},"security":[{"JWTBearer":[]}]}},"/bitcoin/estimate-fee":{"get":{"tags":["Bitcoin Core"],"summary":"Get current fee estimation from Bitcoin Core","description":"Estimates the fee for the given parameters.\n See documentation on [bitcoin.org](https://developer.bitcoin.org/reference/rpc/estimatesmartfee.html)","operationId":"bitcoin_estimate_fee_bitcoin_estimate_fee_get","security":[{"JWTBearer":[]}],"parameters":[{"name":"target_conf","in":"query","required":false,"schema":{"type":"integer","description":"Confirmation target in blocks.","default":6,"title":"Target Conf"},"description":"Confirmation target in blocks."},{"name":"mode","in":"query","required":false,"schema":{"$ref":"#/components/schemas/FeeEstimationMode","description":"Whether to return a more conservative estimate which also satisfies a longer history. A conservative estimate potentially returns a higher feerate and is more likely to be sufficient for the desired target, but is not as responsive to short term drops in the prevailing fee market.","default":"conservative"},"description":"Whether to return a more conservative estimate which also satisfies a longer history. A conservative estimate potentially returns a higher feerate and is more likely to be sufficient for the desired target, but is not as responsive to short term drops in the prevailing fee market."}],"responses":{"200":{"description":"The estimated fee in satoshis","content":{"application/json":{"schema":{"type":"integer","title":"Response Bitcoin Estimate Fee Bitcoin Estimate Fee Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/bitcoin/get-network-info":{"get":{"tags":["Bitcoin Core"],"summary":"Get information about the network","description":"See documentation on [bitcoincore.org](https://bitcoincore.org/en/doc/0.21.0/rpc/network/getnetworkinfo/)","operationId":"bitcoin_get_network_info_bitcoin_get_network_info_get","responses":{"200":{"description":"A JSON String with relevant information.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NetworkInfo"}}}}},"security":[{"JWTBearer":[]}]}},"/bitcoin/get-raw-transaction":{"get":{"tags":["Bitcoin Core"],"summary":"Get information about a raw transaction","description":"See documentation on [bitcoincore.org](https://bitcoincore.org/en/doc/22.0.0/rpc/rawtransactions/getrawtransaction/)","operationId":"bitcoin_get_raw_transaction_bitcoin_get_raw_transaction_get","security":[{"JWTBearer":[]}],"parameters":[{"name":"txid","in":"query","required":true,"schema":{"type":"string","minLength":64,"maxLength":64,"description":"The transaction id","title":"Txid"},"description":"The transaction id"}],"responses":{"200":{"description":"A JSON String with relevant information.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RawTransaction"}}}},"400":{"description":"Invalid transaction id or -txindex not enabled"},"404":{"description":"No such mempool or blockchain transaction."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/bitcoin/block-sub":{"get":{"tags":["Bitcoin Core"],"summary":"Subscribe to incoming blocks.","description":"Similar to Bitcoin Core getblock\n\nSSE endpoint to receive new block information as soon as it is appended to chain.\n\nIf verbosity is 0, returns a string that is serialized, hex-encoded data for block 'hash'.
\nIf verbosity is 1, returns an Object with information about block .
\nIf verbosity is 2, returns an Object with information about block and information about each transaction.
","operationId":"bitcoin_block_sub_bitcoin_block_sub_get","security":[{"JWTBearer":[]}],"parameters":[{"name":"verbosity","in":"query","required":false,"schema":{"type":"integer","default":1,"title":"Verbosity"}}],"responses":{"200":{"description":"A JSON object with information about the new block.","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/lightning/add-invoice":{"post":{"tags":["Lightning"],"summary":"Addinvoice adds a new Invoice to the database.","description":"For additional information see [LND docs](https://api.lightning.community/#addinvoice)","operationId":"lightning_add_invoice_lightning_add_invoice_post","security":[{"JWTBearer":[]}],"parameters":[{"name":"value_msat","in":"query","required":true,"schema":{"type":"integer","minimum":0,"description":"The amount of msat of the invoice","title":"Value Msat"},"description":"The amount of msat of the invoice"},{"name":"memo","in":"query","required":false,"schema":{"type":"string","description":"The memo of the invoice","default":"","title":"Memo"},"description":"The memo of the invoice"},{"name":"expiry","in":"query","required":false,"schema":{"type":"integer","description":"Expiry time in seconds","default":3600,"title":"Expiry"},"description":"Expiry time in seconds"},{"name":"is_keysend","in":"query","required":false,"schema":{"type":"boolean","description":"LND only: Whether this invoice is a keysend invoice.","default":false,"title":"Is Keysend"},"description":"LND only: Whether this invoice is a keysend invoice."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Invoice"}}}},"423":{"description":"LND only: Wallet is locked. Unlock via /lightning/unlock-wallet."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/lightning/get-balance":{"get":{"tags":["Lightning"],"summary":"Get the current on chain and channel balances of the lighting wallet.","operationId":"lightning_get_balance_lightning_get_balance_get","responses":{"200":{"description":"\nA JSON String with on chain wallet balances with on-chain balances in\n**sat** and channel balances in **msat**. Detailed description is in\nthe schema","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WalletBalance"}}}},"423":{"description":"LND only: Wallet is locked. Unlock via /lightning/unlock-wallet."}},"security":[{"JWTBearer":[]}]}},"/lightning/get-fee-revenue":{"get":{"tags":["Lightning"],"summary":"Returns the daily, weekly and monthly fee revenue earned.","description":"Currently, year and total fees are always null. Backends don't return these values by default. Implementation in BlitzAPI remains a [to-do](https://github.com/fusion44/blitz_api/issues/64).","operationId":"lightning_get_fee_revenue_lightning_get_fee_revenue_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeeRevenue"}}}},"423":{"description":"LND only: Wallet is locked. Unlock via /lightning/unlock-wallet."}},"security":[{"JWTBearer":[]}]}},"/lightning/list-all-tx":{"get":{"tags":["Lightning"],"summary":"Lists all on-chain transactions, payments and invoices in the wallet","description":"Returns a list with all on-chain transaction, payments and invoices combined into one list. The index of each tx is only valid for each identical set of parameters.","operationId":"lightning_list_all_tx_lightning_list_all_tx_get","security":[{"JWTBearer":[]}],"parameters":[{"name":"successful_only","in":"query","required":false,"schema":{"type":"boolean","description":"If set, only successful transaction will be returned in the response.","default":false,"title":"Successful Only"},"description":"If set, only successful transaction will be returned in the response."},{"name":"index_offset","in":"query","required":false,"schema":{"type":"integer","description":"The index of an transaction that will be used as either the start or end of a query to determine which invoices should be returned in the response.","default":0,"title":"Index Offset"},"description":"The index of an transaction that will be used as either the start or end of a query to determine which invoices should be returned in the response."},{"name":"max_tx","in":"query","required":false,"schema":{"type":"integer","description":"The max number of transaction to return in the response to this query. Will return all transactions when set to 0 or null.","default":0,"title":"Max Tx"},"description":"The max number of transaction to return in the response to this query. Will return all transactions when set to 0 or null."},{"name":"reversed","in":"query","required":false,"schema":{"type":"boolean","description":"If set, the transactions returned will result from seeking backwards from the specified index offset. This can be used to paginate backwards.","default":false,"title":"Reversed"},"description":"If set, the transactions returned will result from seeking backwards from the specified index offset. This can be used to paginate backwards."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/GenericTx"},"title":"Response Lightning List All Tx Lightning List All Tx Get"}}}},"423":{"description":"LND only: Wallet is locked. Unlock via /lightning/unlock-wallet."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/lightning/list-invoices":{"get":{"tags":["Lightning"],"summary":"Lists all invoices from the wallet. Modeled after LND implementation.","operationId":"lightning_list_invoices_lightning_list_invoices_get","security":[{"JWTBearer":[]}],"parameters":[{"name":"pending_only","in":"query","required":false,"schema":{"type":"boolean","description":"If set, only invoices that are not settled and not canceled will be returned in the response.","default":false,"title":"Pending Only"},"description":"If set, only invoices that are not settled and not canceled will be returned in the response."},{"name":"index_offset","in":"query","required":false,"schema":{"type":"integer","description":"The index of an invoice that will be used as either the start or end of a query to determine which invoices should be returned in the response.","default":0,"title":"Index Offset"},"description":"The index of an invoice that will be used as either the start or end of a query to determine which invoices should be returned in the response."},{"name":"num_max_invoices","in":"query","required":false,"schema":{"type":"integer","description":"The max number of invoices to return in the response to this query. This will return all invoices when set to 0 or null.","default":0,"title":"Num Max Invoices"},"description":"The max number of invoices to return in the response to this query. This will return all invoices when set to 0 or null."},{"name":"reversed","in":"query","required":false,"schema":{"type":"boolean","description":"If set, the invoices returned will result from seeking backwards from the specified index offset. This can be used to paginate backwards.","default":false,"title":"Reversed"},"description":"If set, the invoices returned will result from seeking backwards from the specified index offset. This can be used to paginate backwards."}],"responses":{"200":{"description":"A list of all invoices created.","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Invoice"},"title":"Response Lightning List Invoices Lightning List Invoices Get"}}}},"423":{"description":"LND only: Wallet is locked. Unlock via /lightning/unlock-wallet."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/lightning/list-onchain-tx":{"get":{"tags":["Lightning"],"summary":"Lists all onchain transactions from the wallet","operationId":"lightning_list_onchain_tx_lightning_list_onchain_tx_get","responses":{"200":{"description":"A list of all on-chain transactions made.","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/OnChainTransaction"},"type":"array","title":"Response Lightning List Onchain Tx Lightning List Onchain Tx Get"}}}},"423":{"description":"LND only: Wallet is locked. Unlock via /lightning/unlock-wallet."}},"security":[{"JWTBearer":[]}]}},"/lightning/list-payments":{"get":{"tags":["Lightning"],"summary":"Returns a list of all outgoing payments. Modeled after LND implementation.","operationId":"lightning_list_payments_lightning_list_payments_get","security":[{"JWTBearer":[]}],"parameters":[{"name":"include_incomplete","in":"query","required":false,"schema":{"type":"boolean","description":"If true, then return payments that have not yet fully completed. This means that pending payments, as well as failed payments will show up if this field is set to true. This flag doesn't change the meaning of the indices, which are tied to individual payments.","default":true,"title":"Include Incomplete"},"description":"If true, then return payments that have not yet fully completed. This means that pending payments, as well as failed payments will show up if this field is set to true. This flag doesn't change the meaning of the indices, which are tied to individual payments."},{"name":"index_offset","in":"query","required":false,"schema":{"type":"integer","description":"The index of a payment that will be used as either the start or end of a query to determine which payments should be returned in the response. The index_offset is exclusive. In the case of a zero index_offset, the query will start with the oldest payment when paginating forwards, or will end with the most recent payment when paginating backwards.","default":0,"title":"Index Offset"},"description":"The index of a payment that will be used as either the start or end of a query to determine which payments should be returned in the response. The index_offset is exclusive. In the case of a zero index_offset, the query will start with the oldest payment when paginating forwards, or will end with the most recent payment when paginating backwards."},{"name":"max_payments","in":"query","required":false,"schema":{"type":"integer","description":"The maximal number of payments returned in the response to this query.","default":0,"title":"Max Payments"},"description":"The maximal number of payments returned in the response to this query."},{"name":"reversed","in":"query","required":false,"schema":{"type":"boolean","description":"If set, the payments returned will result from seeking backwards from the specified index offset. This can be used to paginate backwards. The order of the returned payments is always oldest first (ascending index order).","default":false,"title":"Reversed"},"description":"If set, the payments returned will result from seeking backwards from the specified index offset. This can be used to paginate backwards. The order of the returned payments is always oldest first (ascending index order)."}],"responses":{"200":{"description":"A list of all payments made.","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Payment"},"title":"Response Lightning List Payments Lightning List Payments Get"}}}},"423":{"description":"LND only: Wallet is locked. Unlock via /lightning/unlock-wallet."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/lightning/new-address":{"post":{"tags":["Lightning"],"summary":"Generate a new on-chain address","description":"Generate a wallet new address. Address-types has to be one of:\n* **p2wkh**: Pay to witness key hash (bech32)\n* **np2wkh**: Pay to nested witness key hash (LND only)\n\n> ℹ️ _CLN only supports and returns p2wkh (bech32) addresses_","operationId":"lightning_new_address_lightning_new_address_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewAddressInput"}}},"required":true},"responses":{"200":{"description":"The newly generated wallet address","content":{"application/json":{"schema":{"type":"string","title":"Response Lightning New Address Lightning New Address Post"}}}},"423":{"description":"LND only: Wallet is locked. Unlock via /lightning/unlock-wallet."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"JWTBearer":[]}]}},"/lightning/send-coins":{"post":{"tags":["Lightning"],"summary":"Attempt to send on-chain funds.","description":"__send-coins__ executes a request to send coins to a particular address.\n\n### LND:\nIf neither __target_conf__, or __sat_per_vbyte__ are set, then the internal wallet will consult its fee model to determine a fee for the default confirmation target.\n\n> 👉 See [https://api.lightning.community/?shell#sendcoins](https://api.lightning.community/?shell#sendcoins)\n\n### c-lightning:\n* Set __target_conf__ ==1: interpreted as urgent (aim for next block)\n* Set __target_conf__ >=2: interpreted as normal (next 4 blocks or so, **default**)\n* Set __target_cont__ >=10: interpreted as slow (next 100 blocks or so)\n* If __sat_per_vbyte__ is set then __target_conf__ is ignored and vbytes (sipabytes) will be used.\n\n> 👉 See [https://lightning.readthedocs.io/lightning-txprepare.7.html](https://lightning.readthedocs.io/lightning-txprepare.7.html)\n\n### Sending all onchain funds\n> ℹ️ Keep the following points in mind when sending all onchain funds:\n\n* The response object currently will state __\"amount\": 0__ even if __send_all__ is set to __true__ and the transaction was successfully submitted to the mempool. [GitHub issue](https://github.com/fusion44/blitz_api/issues/196)\n* If __send_all__ is set to __true__, the __amount__ field must be set to __0__.\n* If the __amount__ field is greater than __0__, the __send_all__ field must be __false__.\n * The API will return an error if neither or both conditions are met at the same time.\n* If __send_all__ is set to __true__ the amount of satoshis to send will be calculated by subtracting the fee from the wallet balance.\n* If the wallet balance is not sufficient to cover the fee, the call will fail.\n* The call will __not__ close any channels.\n* The implementation may keep a reserve of funds if there are still open channels.","operationId":"lightning_send_coins_lightning_send_coins_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendCoinsInput"}}},"required":true},"responses":{"200":{"description":"Either an error or a SendCoinsResponse object on success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendCoinsResponse"}}}},"412":{"description":"When not enough funds are available."},"423":{"description":"LND only: Wallet is locked. Unlock via /lightning/unlock-wallet."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"JWTBearer":[]}]}},"/lightning/open-channel":{"post":{"tags":["Lightning"],"summary":"open a new lightning channel","description":"__open-channel__ attempts to open a channel with a peer.\n\n### LND:\n_target_conf_: The target number of blocks that the funding transaction should be confirmed by.\n\n### c-lightning:\n* Set _target_conf_ ==1: interpreted as urgent (aim for next block)\n* Set _target_conf_ >=2: interpreted as normal (next 4 blocks or so, **default**)\n* Set _target_cont_ >=10: interpreted as slow (next 100 blocks or so)\n\n> 👉 See [https://lightning.readthedocs.io/lightning-txprepare.7.html](https://lightning.readthedocs.io/lightning-txprepare.7.html)","operationId":"lightning_open_channel_lightning_open_channel_post","security":[{"JWTBearer":[]}],"parameters":[{"name":"local_funding_amount","in":"query","required":true,"schema":{"type":"integer","title":"Local Funding Amount"}},{"name":"node_URI","in":"query","required":true,"schema":{"type":"string","title":"Node Uri"}},{"name":"target_confs","in":"query","required":false,"schema":{"type":"integer","default":3,"title":"Target Confs"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"string","title":"Response Lightning Open Channel Lightning Open Channel Post"}}}},"412":{"description":"When not enough funds are available."},"423":{"description":"LND only: Wallet is locked. Unlock via /lightning/unlock-wallet."},"504":{"description":"When the peer is not reachable."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/lightning/list-channels":{"get":{"tags":["Lightning"],"summary":"Returns a list of open channels","operationId":"lightning_list_channels_lightning_list_channels_get","responses":{"200":{"description":"A list of all open channels.","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/Channel"},"type":"array","title":"Response Lightning List Channels Lightning List Channels Get"}}}},"423":{"description":"LND only: Wallet is locked. Unlock via /lightning/unlock-wallet."}},"security":[{"JWTBearer":[]}]}},"/lightning/close-channel":{"post":{"tags":["Lightning"],"summary":"close a channel","description":"For additional information see [LND docs](https://api.lightning.community/#closechannel)","operationId":"lightning_close_channel_lightning_close_channel_post","security":[{"JWTBearer":[]}],"parameters":[{"name":"channel_id","in":"query","required":true,"schema":{"type":"string","title":"Channel Id"}},{"name":"force_close","in":"query","required":true,"schema":{"type":"boolean","title":"Force Close"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"string","title":"Response Lightning Close Channel Lightning Close Channel Post"}}}},"423":{"description":"LND only: Wallet is locked. Unlock via /lightning/unlock-wallet."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/lightning/send-payment":{"post":{"tags":["Lightning"],"summary":"Attempt to pay a payment request.","description":"This endpoints attempts to pay a payment request.\n\nIntermediate status updates will be sent via the SSE channel. This endpoint returns the last success or error message from the node.","operationId":"lightning_send_payment_lightning_send_payment_post","security":[{"JWTBearer":[]}],"parameters":[{"name":"pay_req","in":"query","required":true,"schema":{"type":"string","title":"Pay Req"}},{"name":"timeout_seconds","in":"query","required":false,"schema":{"type":"integer","default":5,"title":"Timeout Seconds"}},{"name":"fee_limit_msat","in":"query","required":false,"schema":{"type":"integer","default":8000,"title":"Fee Limit Msat"}},{"name":"amount_msat","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Amount Msat"}}],"responses":{"200":{"description":"Either an error or a Payment object on success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Payment"}}}},"400":{"description":"Possible error messages:* invalid bech32 string* amount must be specified when paying a zero amount invoice* amount must not be specified when paying a non-zero amount invoice"},"409":{"description":"[LND only] When attempting to pay an already paid invoice. CLN will return the payment object of the previously paid invoice. Info: [GitHub](https://github.com/fusion44/blitz_api/issues/131)"},"423":{"description":"LND only: Wallet is locked. Unlock via /lightning/unlock-wallet."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/lightning/get-info":{"get":{"tags":["Lightning"],"summary":"Request information about the currently running lightning node.","operationId":"lightning_get_info_lightning_get_info_get","responses":{"200":{"description":"Either an error or a LnInfo object on success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LnInfo"}}}},"423":{"description":"LND only: Wallet is locked. Unlock via /lightning/unlock-wallet."}},"security":[{"JWTBearer":[]}]}},"/lightning/decode-pay-req":{"get":{"tags":["Lightning"],"summary":"DecodePayReq takes an encoded payment request string and attempts to decode it, returning a full description of the conditions encoded within the payment request.","operationId":"lightning_decode_pay_req_lightning_decode_pay_req_get","security":[{"JWTBearer":[]}],"parameters":[{"name":"pay_req","in":"query","required":true,"schema":{"type":"string","description":"The payment request string to be decoded","title":"Pay Req"},"description":"The payment request string to be decoded"}],"responses":{"200":{"description":"A fully decoded payment request or a HTTP status 400 if the payment request cannot be decoded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentRequest"}}}},"423":{"description":"LND only: Wallet is locked. Unlock via /lightning/unlock-wallet."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/lightning/unlock-wallet":{"post":{"tags":["Lightning"],"summary":"Unlocks a locked wallet.","operationId":"lightning_unlock_wallet_lightning_unlock_wallet_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnlockWalletInput"}}},"required":true},"responses":{"200":{"description":"\n`True` if ok, `False` otherwise\n\n### LND:\nThis call will wait until the LND daemon is fully ready to accept calls. Internally it'll call GetInfo every\n0.1 seconds and returns True for the first successful call.\n\n> ℹ️ _After the unlock the LND-gRPC server takes a bit of time to boot up._\n\n### Core Lightning:\n\n> ℹ️ _Platform: Native_ CLN doesn't support wallet locking and will return True immediately.\n\n> ℹ️ _Platform: RaspiBlitz_ RaspiBlitz has its own locking implementation on top of CLN. Will unlock and return True if successful. Might take a few seconds. If it takes longer than 60 seconds it'll return an error.\n","content":{"application/json":{"schema":{"type":"boolean","title":"Response Lightning Unlock Wallet Lightning Unlock Wallet Post"}}}},"401":{"description":"Either JWT token is not ok OR wallet password is wrong, observe the detail message."},"412":{"description":"Wallet already unlocked"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"JWTBearer":[]}]}},"/system/login":{"post":{"tags":["System"],"summary":"Logs the user in with the current password","operationId":"system_login_system_login_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginInput"}}},"required":true},"responses":{"200":{"description":"JWT token for the current session.","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/system/refresh-token":{"post":{"tags":["System"],"summary":"Endpoint to refresh an authentication token","operationId":"system_refresh_token_system_refresh_token_post","responses":{"200":{"description":"Returns a fresh JWT token.","content":{"application/json":{"schema":{}}}}},"security":[{"JWTBearer":[]}]}},"/system/change-password":{"post":{"tags":["System"],"summary":"Endpoint to change your password","operationId":"system_change_password_system_change_password_post","security":[{"JWTBearer":[]}],"parameters":[{"name":"old_password","in":"query","required":true,"schema":{"type":"string","title":"Old Password"}},{"name":"new_password","in":"query","required":true,"schema":{"type":"string","title":"New Password"}},{"name":"type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"ℹ️ Used in **RaspiBlitz only**. Password A, B or C. Must be one of `[\"a\", \"b\", \"c\"]`","title":"Type"},"description":"ℹ️ Used in **RaspiBlitz only**. Password A, B or C. Must be one of `[\"a\", \"b\", \"c\"]`"}],"responses":{"200":{"description":"if 200 OK - password change worked","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/system/get-system-info":{"get":{"tags":["System"],"summary":"Get system status information","operationId":"system_get_system_info_system_get_system_info_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SystemInfo"}}}},"423":{"description":"Wallet is locked. Unlock via /lightning/unlock-wallet"}},"security":[{"JWTBearer":[]}]}},"/system/hardware-info":{"get":{"tags":["System"],"summary":"Get hardware status information.","operationId":"system_hardware_info_system_hardware_info_get","responses":{"200":{"description":"Returns a JSON string with hardware information:\n\n```JSON\n{\n \"cpu_overall_percent\": 15.8,\n \"cpu_per_cpu_percent\": [\n 11.8,\n 6.1,\n 12.5\n ],\n \"vram_total_bytes\": 25134919680,\n \"vram_available_bytes\": 17240051712,\n \"vram_used_bytes\": 6044856320,\n \"vram_usage_percent\": 31.4,\n \"swap_ram_total_bytes\": 2147479552,\n \"swap_used_bytes\": 0,\n \"swap_usage_bytes\": 0,\n \"temperatures_celsius\": {\n \"coretemp\": [\n [\n \"Core 1\",\n 51,\n 84,\n 100\n ],\n [\n \"Core 2\",\n 53,\n 84,\n 100\n ],\n [\n \"Core 3\",\n 50,\n 84,\n 100\n ]\n ]\n },\n \"boot_time_timestamp\": 1623486468,\n \"disk_io_read_count\": 254574,\n \"disk_io_write_count\": 133353,\n \"disk_io_read_bytes\": 5306839040,\n \"disk_io_write_bytes\": 5593076736,\n \"disks\": [\n {\n \"device\": \"/dev/sda1\",\n \"mountpoint\": \"/boot/efi\",\n \"filesystem_type\": \"vfat\",\n \"partition_total_bytes\": 535805952,\n \"partition_used_bytes\": 8228864,\n \"partition_free_bytes\": 527577088,\n \"partition_percent\": 1.5\n },\n {\n \"device\": \"/dev/sda2\",\n \"mountpoint\": \"/\",\n \"filesystem_type\": \"ext4\",\n \"partition_total_bytes\": 250438021120,\n \"partition_used_bytes\": 177157742592,\n \"partition_free_bytes\": 60487389184,\n \"partition_percent\": 74.5\n }\n ],\n \"networks\": [\n {\n \"interface_name\": \"lo\",\n \"address\": \"127.0.0.1\",\n \"mac_address\": \"00:00:00:00:00:00\"\n },\n {\n \"interface_name\": \"enp4s0\",\n \"address\": \"192.168.1.23\",\n \"mac_address\": \"35:a3:5c:6a:4a:f0\"\n }\n ],\n \"networks_bytes_sent\": 137088249,\n \"networks_bytes_received\": 1603400654\n}\n```\n","content":{"application/json":{"schema":{}}}}},"security":[{"JWTBearer":[]}]}},"/system/connection-info":{"get":{"tags":["System"],"summary":"Get credential information to connect external apps.","operationId":"system_connection_info_system_connection_info_get","responses":{"200":{"description":"Returns a JSON string with credential information.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectionInfo"}}}}},"security":[{"JWTBearer":[]}]}},"/system/get-debug-logs-raw":{"get":{"tags":["System"],"summary":"Get raw system logs as a text string.","description":"This endpoint will gather latest system logs and return it in a\nraw string. This endpoint will **not** return immediately because\nit gathers all data on time of the request.","operationId":"system_get_debug_logs_raw_system_get_debug_logs_raw_get","responses":{"200":{"description":"\nThe latest system log as a string of text.\n\nReturns a `HTTP_INTERNAL_SERVER_ERROR` with status code 500 if script execution fails on server.\n\nExample output in `raw_data`:\n\n```\n***************************************************************\n* RASPIBLITZ DEBUG LOGS\n***************************************************************\nblitzversion: 1.7.0\nchainnetwork: bitcoin / main\n 15:27:34 up 4:10, 3 users, load average: 1.23, 1.36, 1.38\n\n*** BLOCKCHAIN SYSTEMD STATUS ***\n● bitcoind.service - Bitcoin daemon\n Loaded: loaded (/etc/systemd/system/bitcoind.service; enabled; vendor preset: enabled)\n Active: active (running) since Tue 2021-09-14 11:16:51 BST; 4h 10min ago\n Process: 1718 ExecStartPre=/home/admin/config.scripts/blitz.systemd.sh log blockchain STARTED (code=exited, status=0/SUCCESS)\n Process: 1724 ExecStart=/usr/local/bin/bitcoind -daemon -conf=/home/bitcoin/.bitcoin/bitcoin.conf -pid=/mnt/hdd/bitcoin/bitcoind.pid (code=exited, status=0/SUCCESS)\n Main PID: 1765 (bitcoind)\n Tasks: 12 (limit: 4533)\n CGroup: /system.slice/bitcoind.service\n └─1765 /usr/local/bin/bitcoind -daemon -conf=/home/bitcoin/.bitcoin/bitcoin.conf -pid=/mnt/hdd/bitcoin/bitcoind.pid\n\nSep 14 11:16:50 raspberrypi systemd[1]: Starting Bitcoin daemon...\nSep 14 11:16:51 raspberrypi systemd[1]: Started Bitcoin daemon.\n\n*** LAST BLOCKCHAIN ERROR LOGS ***\nsudo journalctl -u bitcoind -b --no-pager -n8\n-- Logs begin at Tue 2021-09-14 11:15:58 BST, end at Tue 2021-09-14 15:27:35 BST. --\nSep 14 11:16:50 raspberrypi systemd[1]: Starting Bitcoin daemon...\nSep 14 11:16:51 raspberrypi systemd[1]: Started Bitcoin daemon.\n\n*** LAST BLOCKCHAIN 20 INFO LOGS ***\nsudo tail -n 20 /mnt/hdd/bitcoin/debug.log\n2021-09-14T14:26:27Z Rolling forward 00000000000000000082dcdfb99c8b663828fd40fd68f343a17f766e1dee9bdc (499641)\n2021-09-14T14:26:30Z Rolling forward 0000000000000000003c2cc296d753717135a38cfea6bc3ddba640aac063fb3b (499642)\n2021-09-14T14:26:34Z Rolling forward 00000000000000000005869d321a8f2046d1e47f55b97920c9e4bb8a971db40b (499643)\n2021-09-14T14:26:37Z Rolling forward 0000000000000000002d429f39afec70c938e888c3417d690bbc85e83529991c (499644)\n2021-09-14T14:26:40Z Rolling forward 00000000000000000024c0bdbec66a889778c00bc69be0a96cbbd98b75c3ce09 (499645)\n2021-09-14T14:26:43Z Rolling forward 00000000000000000082756af6724e3200ea9089cb4244cb2d94c83c3cd137d7 (499646)\n2021-09-14T14:26:47Z Rolling forward 0000000000000000007f3bf2c37dc14630153b93bc2c34542deadb34a5eb201f (499647)\n2021-09-14T14:26:51Z Rolling forward 0000000000000000003b9296ea38abd68e97beb0c5ed56a8255e6b379a02032b (499648)\n2021-09-14T14:26:54Z Rolling forward 000000000000000000146931cda4713b5ded152c9ae57effe37f216d5a5f31b6 (499649)\n2021-09-14T14:26:57Z Rolling forward 000000000000000000684318d6fc7266f8eb5dc349a170413a0c0ce2334da08f (499650)\n2021-09-14T14:27:00Z Rolling forward 000000000000000000846d905295c15c98f9dc8c8f3ab44bbb997cca9a8e4c83 (499651)\n2021-09-14T14:27:04Z Rolling forward 00000000000000000082bfa88de1c4e6501462e231f0aa54f552f36bdf34fdd3 (499652)\n2021-09-14T14:27:08Z Rolling forward 000000000000000000acce35f2b4ba5256f016da6024abb09ad60b6dcbd0ed83 (499653)\n2021-09-14T14:27:11Z Rolling forward 000000000000000000ae0edf99df2db7e05a0f18e3e5a3e0dfc67013dadc526f (499654)\n2021-09-14T14:27:14Z Rolling forward 00000000000000000087cec98103a704a4594831e8173fa3c916b3c537456ab7 (499655)\n2021-09-14T14:27:17Z Rolling forward 000000000000000000102d751e4c7e2de8f12e04cd4b44fe8179d492b29ea0e2 (499656)\n2021-09-14T14:27:21Z Rolling forward 0000000000000000001a98320ee19986cfb19f30bb1d1deb0cfc21ed9fa3c7ae (499657)\n2021-09-14T14:27:24Z Rolling forward 0000000000000000005ad979367405af6ad75465a8900089cb3bd7b53ff4dc9d (499658)\n2021-09-14T14:27:28Z Rolling forward 0000000000000000005bd3de0386b9c24f92e363a04da33b6b6ac7450997f4aa (499659)\n2021-09-14T14:27:32Z Rolling forward 0000000000000000009fd25eaf6245cd8a0a8869bbe28145f39e4de14dd62825 (499660)\n\n*** LND SYSTEMD STATUS ***\n● lnd.service - LND Lightning Daemon\n Loaded: loaded (/etc/systemd/system/lnd.service; enabled; vendor preset: enabled)\n Active: active (running) since Tue 2021-09-14 11:20:13 BST; 4h 7min ago\n Process: 7000 ExecStartPre=/home/admin/config.scripts/blitz.systemd.sh log lightning STARTED (code=exited, status=0/SUCCESS)\n Main PID: 7002 (lnd)\n Tasks: 10 (limit: 4533)\n CGroup: /system.slice/lnd.service\n └─7002 /usr/local/bin/lnd --tor.active --tor.streamisolation --tor.v3 --tor.socks=9070 --tor.control=9071 --listen=127.0.0.1:9735\n\nSep 14 11:20:13 raspberrypi systemd[1]: Starting LND Lightning Daemon...\nSep 14 11:20:13 raspberrypi systemd[1]: Started LND Lightning Daemon.\n\n*** LAST LND ERROR LOGS ***\nsudo journalctl -u lnd -b --no-pager -n12\n-- Logs begin at Tue 2021-09-14 11:15:58 BST, end at Tue 2021-09-14 15:27:35 BST. --\nSep 14 11:16:51 raspberrypi systemd[1]: Starting LND Lightning Daemon...\nSep 14 11:16:51 raspberrypi systemd[1]: Started LND Lightning Daemon.\nSep 14 11:19:13 raspberrypi lnd[1772]: unable to create chain control: unable to connect to bitcoind: -28: Loading block index...\nSep 14 11:19:13 raspberrypi systemd[1]: lnd.service: Main process exited, code=exited, status=1/FAILURE\nSep 14 11:19:13 raspberrypi systemd[1]: lnd.service: Failed with result 'exit-code'.\nSep 14 11:20:13 raspberrypi systemd[1]: lnd.service: Service RestartSec=1min expired, scheduling restart.\nSep 14 11:20:13 raspberrypi systemd[1]: lnd.service: Scheduled restart job, restart counter is at 1.\nSep 14 11:20:13 raspberrypi systemd[1]: Stopped LND Lightning Daemon.\nSep 14 11:20:13 raspberrypi systemd[1]: Starting LND Lightning Daemon...\nSep 14 11:20:13 raspberrypi systemd[1]: Started LND Lightning Daemon.\n\n*** LAST 30 LND INFO LOGS ***\nsudo tail -n 30 /mnt/hdd/lnd/logs/bitcoin/mainnet/lnd.log\n2021-09-14 11:16:51.708 [INF] LTND: Version: 0.12.1-beta commit=v0.12.1-beta, build=production, logging=default, debuglevel=debug\n2021-09-14 11:16:51.709 [INF] LTND: Active chain: Bitcoin (network=mainnet)\n2021-09-14 11:16:51.709 [INF] LTND: Opening the main database, this might take a few minutes...\n2021-09-14 11:16:51.709 [INF] LTND: Opening bbolt database, sync_freelist=true, auto_compact=false\n2021-09-14 11:16:51.724 [INF] CHDB: Checking for schema update: latest_version=20, db_version=20\n2021-09-14 11:16:51.724 [INF] LTND: Database now open (time_to_open=15.109685ms)!\n2021-09-14 11:16:51.763 [INF] RPCS: Password RPC server listening on 0.0.0.0:10009\n2021-09-14 11:16:51.769 [INF] RPCS: Password gRPC proxy started at 0.0.0.0:8080\n2021-09-14 11:16:51.769 [INF] LTND: Waiting for wallet encryption password. Use `lncli create` to create a wallet, `lncli unlock` to unlock an existing wallet, or `lncli changepassword` to change the password of an existing wallet and unlock it.\n2021-09-14 11:19:12.895 [INF] LNWL: Opened wallet\n2021-09-14 11:19:13.126 [INF] CHRE: Primary chain is set to: bitcoin\n2021-09-14 11:19:13.257 [ERR] LTND: unable to create chain control: unable to connect to bitcoind: -28: Loading block index...\n2021-09-14 11:19:13.257 [INF] LTND: Shutdown complete2021-09-14 11:20:14.120 [INF] LTND: Version: 0.12.1-beta commit=v0.12.1-beta, build=production, logging=default, debuglevel=debug\n2021-09-14 11:20:14.121 [INF] LTND: Active chain: Bitcoin (network=mainnet)\n2021-09-14 11:20:14.121 [INF] LTND: Opening the main database, this might take a few minutes...\n2021-09-14 11:20:14.121 [INF] LTND: Opening bbolt database, sync_freelist=true, auto_compact=false\n2021-09-14 11:20:14.133 [INF] CHDB: Checking for schema update: latest_version=20, db_version=20\n2021-09-14 11:20:14.133 [INF] LTND: Database now open (time_to_open=11.654861ms)!\n2021-09-14 11:20:14.172 [INF] RPCS: Password RPC server listening on 0.0.0.0:10009\n2021-09-14 11:20:14.177 [INF] RPCS: Password gRPC proxy started at 0.0.0.0:8080\n2021-09-14 11:20:14.177 [INF] LTND: Waiting for wallet encryption password. Use `lncli create` to create a wallet, `lncli unlock` to unlock an existing wallet, or `lncli changepassword` to change the password of an existing wallet and unlock it.\n\n*** NGINX SYSTEMD STATUS ***\n● nginx.service - A high performance web server and a reverse proxy server\n Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)\n Drop-In: /etc/systemd/system/nginx.service.d\n └─raspiblitz.conf\n Active: active (running) since Tue 2021-09-14 11:16:37 BST; 4h 10min ago\n Docs: man:nginx(8)\n Main PID: 905 (nginx)\n Tasks: 5 (limit: 4533)\n CGroup: /system.slice/nginx.service\n ├─905 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;\n ├─911 nginx: worker process\n ├─913 nginx: worker process\n ├─914 nginx: worker process\n └─915 nginx: worker process\n\nSep 14 11:16:36 raspberrypi systemd[1]: Starting A high performance web server and a reverse proxy server...\nSep 14 11:16:37 raspberrypi systemd[1]: Started A high performance web server and a reverse proxy server.\n\n*** LAST NGINX LOGS ***\nsudo journalctl -u nginx -b --no-pager -n20\n-- Logs begin at Tue 2021-09-14 11:15:58 BST, end at Tue 2021-09-14 15:27:35 BST. --\nSep 14 11:16:36 raspberrypi systemd[1]: Starting A high performance web server and a reverse proxy server...\nSep 14 11:16:37 raspberrypi systemd[1]: Started A high performance web server and a reverse proxy server.\n--> CHECK CONFIG: sudo nginx -t\n\n\n*** LAST 20 TOUCHSCREEN LOGS ***\nsudo tail -n 20 /home/pi/.cache/lxsession/LXDE-pi/run.log\nPlaying WAVE '/usr/share/piwiz/srprompt.wav' : Signed 16 bit Little Endian, Rate 22050 Hz, Mono\nPlaying WAVE '/usr/share/piwiz/srprompt.wav' : Signed 16 bit Little Endian, Rate 22050 Hz, Mono\n** Message: 01:44:02.973: wlan0: Received scan results\nPlaying WAVE '/usr/share/piwiz/srprompt.wav' : Signed 16 bit Little Endian, Rate 22050 Hz, Mono\nPlaying WAVE '/usr/share/piwiz/srprompt.wav' : Signed 16 bit Little Endian, Rate 22050 Hz, Mono\nPlaying WAVE '/usr/share/piwiz/srprompt.wav' : Signed 16 bit Little Endian, Rate 22050 Hz, Mono\nPlaying WAVE '/usr/share/piwiz/srprompt.wav' : Signed 16 bit Little Endian, Rate 22050 Hz, Mono\n** Message: 01:45:03.021: wlan0: Received scan results\nPlaying WAVE '/usr/share/piwiz/srprompt.wav' : Signed 16 bit Little Endian, Rate 22050 Hz, Mono\nPlaying WAVE '/usr/share/piwiz/srprompt.wav' : Signed 16 bit Little Endian, Rate 22050 Hz, Mono\nPlaying WAVE '/usr/share/piwiz/srprompt.wav' : Signed 16 bit Little Endian, Rate 22050 Hz, Mono\nPlaying WAVE '/usr/share/piwiz/srprompt.wav' : Signed 16 bit Little Endian, Rate 22050 Hz, Mono\n** Message: 01:46:02.982: wlan0: Received scan results\nPlaying WAVE '/usr/share/piwiz/srprompt.wav' : Signed 16 bit Little Endian, Rate 22050 Hz, Mono\nPlaying WAVE '/usr/share/piwiz/srprompt.wav' : Signed 16 bit Little Endian, Rate 22050 Hz, Mono\nPlaying WAVE '/usr/share/piwiz/srprompt.wav' : Signed 16 bit Little Endian, Rate 22050 Hz, Mono\nPlaying WAVE '/usr/share/piwiz/srprompt.wav' : Signed 16 bit Little Endian, Rate 22050 Hz, Mono\n** Message: 01:47:02.989: wlan0: Received scan results\nPlaying WAVE '/usr/share/piwiz/srprompt.wav' : Signed 16 bit Little Endian, Rate 22050 Hz, Mono\nPlaying WAVE '/usr/share/piwiz/srprompt.wav' : Signed 16 bit Little Endian, Rate 22050 Hz, Mono\n\n\n*** LAST 20 LOOP LOGS ***\nsudo journalctl -u loopd -b --no-pager -n20\n-- Logs begin at Tue 2021-09-14 11:15:58 BST, end at Tue 2021-09-14 15:27:35 BST. --\n-- No entries --\n\n- RTL is OFF by config\n\n*** LAST 20 ElectRS LOGS ***\nsudo journalctl -u electrs -b --no-pager -n20\n-- Logs begin at Tue 2021-09-14 11:15:58 BST, end at Tue 2021-09-14 15:27:35 BST. --\n-- No entries --\n\n*** ElectRS Status ***\n##### STATUS ELECTRS SERVICE\nconfigured=0\nserviceInstalled=0\ninfoSync='Service not installed'\nserviceRunning=0\ntipSynced=0\ninitialSynced=0\nelectrumResponding=0\ninfoSync='Not running - check: sudo journalctl -u electrs'\n\n\n*** LAST 20 LIT LOGS ***\nsudo journalctl -u litd -b --no-pager -n20\n-- Logs begin at Tue 2021-09-14 11:15:58 BST, end at Tue 2021-09-14 15:27:36 BST. --\n-- No entries --\n\n\n*** LAST 20 BTCPayServer LOGS ***\nsudo journalctl -u btcpayserver -b --no-pager -n20\n-- Logs begin at Tue 2021-09-14 11:15:58 BST, end at Tue 2021-09-14 15:27:36 BST. --\n-- No entries --\n\n\n*** LAST 20 LNbits LOGS ***\nsudo journalctl -u lnbits -b --no-pager -n20\n-- Logs begin at Tue 2021-09-14 11:15:58 BST, end at Tue 2021-09-14 15:27:36 BST. --\n-- No entries --\n\n\n*** LAST 20 Thunderhub LOGS ***\nsudo journalctl -u thunderhub -b --no-pager -n20\n-- Logs begin at Tue 2021-09-14 11:15:58 BST, end at Tue 2021-09-14 15:27:36 BST. --\n-- No entries --\n\n\n*** LAST 20 SPECTER LOGS ***\nsudo journalctl -u cryptoadvance-specter -b --no-pager -n20\n-- Logs begin at Tue 2021-09-14 11:15:58 BST, end at Tue 2021-09-14 15:27:36 BST. --\n-- No entries --\n\n\n*** LAST 20 SPHINX LOGS ***\nsudo journalctl -u sphinxrelay -b --no-pager -n20\n-- Logs begin at Tue 2021-09-14 11:15:58 BST, end at Tue 2021-09-14 15:27:36 BST. --\n-- No entries --\n\n\n*** MOUNTED DRIVES ***\nFilesystem Type Size Used Avail Use% Mounted on\n/dev/root ext4 29G 3.8G 25G 14% /\ndevtmpfs devtmpfs 1.9G 0 1.9G 0% /dev\ntmpfs tmpfs 1.9G 0 1.9G 0% /dev/shm\ntmpfs tmpfs 1.9G 33M 1.9G 2% /run\ntmpfs tmpfs 5.0M 0 5.0M 0% /run/lock\ntmpfs tmpfs 1.9G 0 1.9G 0% /sys/fs/cgroup\ntmpfs tmpfs 32M 0 32M 0% /var/cache/raspiblitz\n/dev/mmcblk0p1 vfat 253M 30M 223M 12% /boot\n/dev/sda1 ext4 916G 170G 700G 20% /mnt/hdd\ntmpfs tmpfs 385M 0 385M 0% /run/user/1000\ntmpfs tmpfs 385M 0 385M 0% /run/user/1001\n\n\n*** DATADRIVE ***\n# RASPIBLITZ DATA DRIVE Status\n\n# BASICS\nisMounted=1\nisBTRFS=0\nhddRaspiData=1\nisSSD=1\ndatadisk='sda'\ndatapartition='sda1'\nhddBlocksBitcoin=1\nhddBlocksLitecoin=0\nhddBytes=1000141693440\nhddGigaBytes=931\nhddUsedInfo='170G (20%)'\nhddDataFreeKB=733759240\nhddAdapterUSB=''\nhddAdapterUSAP=0\n\n# RAID\nisRaid=0\nraidCandidates=0\n\n# SWAP\nisSwapExternal=1\nSwapExternalPath='/mnt/hdd/swapfile'\n\n\n*** NETWORK ***\nlocalip=192.168.0.103\ndhcp=1\nnetwork_device=eth0\n\n*** HARDWARE TEST RESULTS ***\nUndervoltageReports in Logs: 0\n\n*** SYSTEM STATUS (can take some seconds to gather) ***\nlocalIP='192.168.0.102'\ntempCelsius='63.2'\nuptime=15042\nupsStatus='OFF'\nstartcountBlockchain=1\nbitcoinActive=1\nbitcoinErrorShort='Loading block index'\nbitcoinErrorFull='error code: -28 error message: Loading block index...'\nstartcountLightning=2\nlndActive=1\nlndRPCReady=0\nwalletOpened=0\nwalletReady=0\nwalletLocked=1\nlndRPCReady=0\nblitzTUIActive=0\nblitzTUIRestarts=0\nscriptRuntime=0\n\n*** OPTION: SHARE THIS DEBUG OUTPUT ***\nAn easy way to share this debug output on GitHub or on a support chat\nuse the following command and share the resulting link:\n/home/admin/XXdebugLogs.sh | nc termbin.com 9999\n```\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RawDebugLogData"}}}}},"security":[{"JWTBearer":[]}]}},"/system/hardware-info-sub":{"get":{"tags":["System"],"summary":"Subscribe to hardware status information.","operationId":"system_hardware_info_sub_system_hardware_info_sub_get","responses":{"200":{"description":"Yields a JSON string with hardware information every 2 seconds\n\n```JSON\n{\n \"cpu_overall_percent\": 15.8,\n \"cpu_per_cpu_percent\": [\n 11.8,\n 6.1,\n 12.5\n ],\n \"vram_total_bytes\": 25134919680,\n \"vram_available_bytes\": 17240051712,\n \"vram_used_bytes\": 6044856320,\n \"vram_usage_percent\": 31.4,\n \"swap_ram_total_bytes\": 2147479552,\n \"swap_used_bytes\": 0,\n \"swap_usage_bytes\": 0,\n \"temperatures_celsius\": {\n \"coretemp\": [\n [\n \"Core 1\",\n 51,\n 84,\n 100\n ],\n [\n \"Core 2\",\n 53,\n 84,\n 100\n ],\n [\n \"Core 3\",\n 50,\n 84,\n 100\n ]\n ]\n },\n \"boot_time_timestamp\": 1623486468,\n \"disk_io_read_count\": 254574,\n \"disk_io_write_count\": 133353,\n \"disk_io_read_bytes\": 5306839040,\n \"disk_io_write_bytes\": 5593076736,\n \"disks\": [\n {\n \"device\": \"/dev/sda1\",\n \"mountpoint\": \"/boot/efi\",\n \"filesystem_type\": \"vfat\",\n \"partition_total_bytes\": 535805952,\n \"partition_used_bytes\": 8228864,\n \"partition_free_bytes\": 527577088,\n \"partition_percent\": 1.5\n },\n {\n \"device\": \"/dev/sda2\",\n \"mountpoint\": \"/\",\n \"filesystem_type\": \"ext4\",\n \"partition_total_bytes\": 250438021120,\n \"partition_used_bytes\": 177157742592,\n \"partition_free_bytes\": 60487389184,\n \"partition_percent\": 74.5\n }\n ],\n \"networks\": [\n {\n \"interface_name\": \"lo\",\n \"address\": \"127.0.0.1\",\n \"mac_address\": \"00:00:00:00:00:00\"\n },\n {\n \"interface_name\": \"enp4s0\",\n \"address\": \"192.168.1.23\",\n \"mac_address\": \"35:a3:5c:6a:4a:f0\"\n }\n ],\n \"networks_bytes_sent\": 137088249,\n \"networks_bytes_received\": 1603400654\n}\n```\n","content":{"application/json":{"schema":{}}}}},"security":[{"JWTBearer":[]}]}},"/system/health":{"get":{"tags":["System"],"summary":"Returns info about the systems health","operationId":"system_health_system_health_get","security":[{"JWTBearer":[]}],"parameters":[{"name":"verbose","in":"query","required":false,"schema":{"type":"boolean","description":"Returns info about each subsytem running on this node if true. Currently not implemented.","default":false,"title":"Verbose"},"description":"Returns info about each subsytem running on this node if true. Currently not implemented."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SystemHealthInfo"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/system/reboot":{"post":{"tags":["System"],"summary":"Reboots the system","description":"Attempts to reboot the system.\n Will send a `system_reboot_initiated` SSE message immediately to\n all connected clients.","operationId":"system_reboot_system_reboot_post","responses":{"200":{"description":"True if successful. False on failure.\n A failure will also send an error message with id `system_reboot_error`\n to all connected clients.\n ","content":{"application/json":{"schema":{"type":"boolean","title":"Response System Reboot System Reboot Post"}}}}},"security":[{"JWTBearer":[]}]}},"/system/shutdown":{"post":{"tags":["System"],"summary":"Shuts the system down","description":"Attempts to shutdown the system.\n Will send a `system_shutdown_initiated` SSE message immediately to all\n connected clients.","operationId":"system_shutdown_system_shutdown_post","responses":{"200":{"description":"True if successful. False on failure.\n A failure will also send an error message with id system_shutdown_error\n to all connected clients.\n ","content":{"application/json":{"schema":{"type":"boolean","title":"Response System Shutdown System Shutdown Post"}}}}},"security":[{"JWTBearer":[]}]}},"/setup/status":{"get":{"tags":["RaspiBlitz Setup"],"summary":"Get Status","operationId":"get_status_setup_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/setup/setup-start-info":{"get":{"tags":["RaspiBlitz Setup"],"summary":"Setup Start Info","operationId":"setup_start_info_setup_setup_start_info_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/setup/setup-start-done":{"post":{"tags":["RaspiBlitz Setup"],"summary":"Setup Start Done","operationId":"setup_start_done_setup_setup_start_done_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartDoneData"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/setup/setup-final-info":{"get":{"tags":["RaspiBlitz Setup"],"summary":"Setup Final Info","operationId":"setup_final_info_setup_setup_final_info_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"JWTBearer":[]}]}},"/setup/setup-final-done":{"post":{"tags":["RaspiBlitz Setup"],"summary":"Setup Final Done","operationId":"setup_final_done_setup_setup_final_done_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"JWTBearer":[]}]}},"/setup/shutdown":{"get":{"tags":["RaspiBlitz Setup"],"summary":"Get Shutdown","operationId":"get_shutdown_setup_shutdown_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/setup/setup-sync-info":{"post":{"tags":["RaspiBlitz Setup"],"summary":"Setup Sync Info","operationId":"setup_sync_info_setup_setup_sync_info_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"JWTBearer":[]}]}},"/":{"get":{"summary":"Index","operationId":"index__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/sse/subscribe":{"get":{"summary":"Stream","operationId":"stream_sse_subscribe_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}}},"components":{"schemas":{"AMPRecord":{"properties":{"root_share":{"type":"string","title":"Root Share"},"set_id":{"type":"string","title":"Set Id"},"child_index":{"type":"integer","title":"Child Index"}},"type":"object","required":["root_share","set_id","child_index"],"title":"AMPRecord"},"APIPlatform":{"type":"string","enum":["raspiblitz","native_python","unknown"],"title":"APIPlatform"},"Amp":{"properties":{"root_share":{"type":"string","title":"Root Share"},"set_id":{"type":"string","title":"Set Id"},"child_index":{"type":"integer","title":"Child Index"},"hash":{"type":"string","title":"Hash"},"preimage":{"type":"string","title":"Preimage"}},"type":"object","required":["root_share","set_id","child_index","hash","preimage"],"title":"Amp"},"AppId":{"type":"string","enum":["albyhub","btcpayserver","btc-rpc-explorer","electrs","jam","lnbits","mempool","rtl","thunderhub"],"title":"AppId"},"AppOnlineStatus":{"type":"string","enum":["online","offline"],"title":"AppOnlineStatus"},"AppStatus":{"properties":{"id":{"$ref":"#/components/schemas/AppId","description":"Id of the applications"},"version":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Version","description":"Version of the application"},"installed":{"type":"boolean","title":"Installed","description":"Whether the application is installed","default":false},"configured":{"type":"boolean","title":"Configured","description":"Whether the application is configured","default":false},"status":{"$ref":"#/components/schemas/AppOnlineStatus","description":"Whether the application is online","default":"offline"},"local_ip":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Local Ip","description":"The local network IP of the application"},"http_port":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Http Port","description":"The http port of the application"},"https_port":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Https Port","description":"The https port of the application"},"https_forced":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Https Forced","description":"Whether https is forced for this application"},"https_self_signed":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Https Self Signed","description":"Whether the https certificate is self signed"},"hidden_service":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hidden Service","description":"Whether the application is reachable via a tor hidden service"},"address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address","description":"The full address where this application is reachable"},"auth_method":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Auth Method","description":"The authentication method this application uses"},"details":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Details","description":"Additional application specific details\n\n This field can contain values for the following app ids:\n - `mempool`: `is_indexed`, `index_info`\n - `btc-rpc-explorer`: `is_indexed`, `index_info`\n - `electrs`: `initial_sync_done`, `block_height`,\n `blockheightPercent`, `info_sync`,\n `electrum_responding`,\n "},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error","description":"Last known encountered error for this app."}},"type":"object","required":["id"],"title":"AppStatus"},"AppStatusQueryError":{"properties":{"id":{"$ref":"#/components/schemas/AppId","description":"The app id"},"error":{"type":"string","title":"Error","description":"The error description"}},"type":"object","required":["id","error"],"title":"AppStatusQueryError"},"AppStatusQueryResult":{"properties":{"data":{"items":{"$ref":"#/components/schemas/AppStatus"},"type":"array","title":"Data","description":"Contains the successfully queried app statuses","default":[]},"errors":{"items":{"$ref":"#/components/schemas/AppStatusQueryError"},"type":"array","title":"Errors","description":"Contains the error messages for unsuccessful queries","default":[]},"timestamp":{"type":"integer","title":"Timestamp","description":"The UTC timestamp of when the data was fetched","default":0}},"type":"object","title":"AppStatusQueryResult"},"AppUninstallInput":{"properties":{"app_id":{"$ref":"#/components/schemas/AppId","description":"Id of the applications"},"keep_data":{"type":"boolean","title":"Keep Data","description":"Whether to keep the app data","default":true}},"type":"object","required":["app_id"],"title":"AppUninstallInput"},"Bip9Data":{"properties":{"status":{"type":"string","title":"Status","description":"One of \"defined\", \"started\", \"locked_in\", \"active\", \"failed\""},"bit":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Bit","description":"the bit(0-28) in the block version field used to signal this softfork(only for `started` status)"},"start_time":{"type":"integer","title":"Start Time","description":"The minimum median time past of a block at which the bit gains its meaning"},"timeout":{"type":"integer","title":"Timeout","description":"The median time past of a block at which the deployment is considered failed if not yet locked in"},"since":{"type":"integer","title":"Since","description":"Height of the first block to which the status applies"},"min_activation_height":{"type":"integer","title":"Min Activation Height","description":"Minimum height of blocks for which the rules may be enforced"},"statistics":{"anyOf":[{"$ref":"#/components/schemas/Bip9Statistics"},{"type":"null"}],"description":"numeric statistics about BIP9 signalling for a softfork(only for `started` status)"},"height":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Height","description":"Height of the first block which the rules are or will be enforced(only for `buried` type, or `bip9` type with `active` status)"},"active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Active","description":"True if the rules are enforced for the mempool and the next block"}},"type":"object","required":["status","start_time","timeout","since","min_activation_height"],"title":"Bip9Data"},"Bip9Statistics":{"properties":{"period":{"type":"integer","title":"Period","description":"The length in blocks of the BIP9 signalling period"},"threshold":{"type":"integer","title":"Threshold","description":"The number of blocks with the version bit set required to activate the feature"},"elapsed":{"type":"integer","title":"Elapsed","description":"The number of blocks elapsed since the beginning of the current period"},"count":{"type":"integer","title":"Count","description":"The number of blocks with the version bit set in the current period"},"possible":{"type":"boolean","title":"Possible","description":"False if there are not enough blocks left in this period to pass activation threshold"}},"type":"object","required":["period","threshold","elapsed","count","possible"],"title":"Bip9Statistics"},"BlockchainInfo":{"properties":{"chain":{"type":"string","title":"Chain","description":"Current network name(main, test, regtest)"},"blocks":{"type":"integer","title":"Blocks","description":"The height of the most-work fully-validated chain. The genesis block has height 0"},"headers":{"type":"integer","title":"Headers","description":"The current number of headers we have validated"},"best_block_hash":{"type":"string","title":"Best Block Hash","description":"The hash of the currently best block"},"difficulty":{"type":"number","title":"Difficulty","description":"The current difficulty"},"mediantime":{"type":"integer","title":"Mediantime","description":"Median time for the current best block"},"verification_progress":{"type":"number","title":"Verification Progress","description":"Estimate of verification progress[0..1]"},"initial_block_download":{"type":"boolean","title":"Initial Block Download","description":"Estimate of whether this node is in Initial Block Download mode"},"chainwork":{"type":"string","title":"Chainwork","description":"total amount of work in active chain, in hexadecimal"},"size_on_disk":{"type":"integer","title":"Size On Disk","description":"The estimated size of the block and undo files on disk"},"pruned":{"type":"boolean","title":"Pruned","description":"If the blocks are subject to pruning"},"prune_height":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Prune Height","description":"Lowest-height complete block stored(only present if pruning is enabled)"},"automatic_pruning":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Automatic Pruning","description":"Whether automatic pruning is enabled(only present if pruning is enabled)"},"prune_target_size":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Prune Target Size","description":"The target size used by pruning(only present if automatic pruning is enabled)"},"warnings":{"type":"string","title":"Warnings","description":"Any network and blockchain warnings","default":""},"softforks":{"items":{"$ref":"#/components/schemas/SoftFork"},"type":"array","title":"Softforks","description":"Status of softforks"}},"type":"object","required":["chain","blocks","headers","best_block_hash","difficulty","mediantime","verification_progress","initial_block_download","chainwork","size_on_disk","pruned","softforks"],"title":"BlockchainInfo"},"BtcInfo":{"properties":{"blocks":{"type":"integer","title":"Blocks","description":"The height of the most-work fully-validated chain. The genesis block has height 0"},"headers":{"type":"integer","title":"Headers","description":"The current number of headers we have validated"},"verification_progress":{"type":"number","title":"Verification Progress","description":"Estimate of verification progress[0..1]"},"difficulty":{"type":"number","title":"Difficulty","description":"The current difficulty"},"size_on_disk":{"type":"integer","title":"Size On Disk","description":"The estimated size of the block and undo files on disk"},"networks":{"items":{"$ref":"#/components/schemas/BtcNetwork"},"type":"array","title":"Networks","description":"Which networks are in use (ipv4, ipv6 or onion)","default":[]},"version":{"type":"integer","title":"Version","description":"The bitcoin core server version"},"subversion":{"type":"string","title":"Subversion","description":"The server subversion string"},"connections_in":{"type":"integer","title":"Connections In","description":"The number of inbound connections"},"connections_out":{"type":"integer","title":"Connections Out","description":"The number of outbound connections"}},"type":"object","required":["blocks","headers","verification_progress","difficulty","size_on_disk","version","subversion","connections_in","connections_out"],"title":"BtcInfo"},"BtcLocalAddress":{"properties":{"address":{"type":"string","title":"Address","description":"Network address"},"port":{"type":"integer","title":"Port","description":"Network port"},"score":{"type":"integer","title":"Score","description":"Relative score"}},"type":"object","required":["address","port","score"],"title":"BtcLocalAddress"},"BtcNetwork":{"properties":{"name":{"type":"string","title":"Name","description":"Which network is in use (ipv4, ipv6 or onion)"},"limited":{"type":"boolean","title":"Limited","description":"Is the network limited using - onlynet?"},"reachable":{"type":"boolean","title":"Reachable","description":"Is the network reachable?"},"proxy":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Proxy","description":"host:port of the proxy that is used for this network, or empty if none","default":""},"proxy_randomize_credentials":{"type":"boolean","title":"Proxy Randomize Credentials","description":"Whether randomized credentials are used"}},"type":"object","required":["name","limited","reachable","proxy_randomize_credentials"],"title":"BtcNetwork"},"Chain":{"properties":{"chain":{"type":"string","title":"Chain"},"network":{"type":"string","title":"Network"}},"type":"object","required":["chain","network"],"title":"Chain"},"Channel":{"properties":{"channel_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Channel Id"},"active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Active"},"peer_publickey":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Peer Publickey"},"peer_alias":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Peer Alias"},"balance_local":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Balance Local"},"balance_remote":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Balance Remote"},"balance_capacity":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Balance Capacity"}},"type":"object","required":["channel_id","active","peer_publickey","peer_alias","balance_local","balance_remote","balance_capacity"],"title":"Channel"},"ChannelUpdate":{"properties":{"signature":{"type":"string","title":"Signature"},"chain_hash":{"type":"string","title":"Chain Hash"},"chan_id":{"type":"integer","title":"Chan Id"},"timestamp":{"type":"integer","title":"Timestamp"},"message_flags":{"type":"integer","title":"Message Flags"},"channel_flags":{"type":"integer","title":"Channel Flags"},"time_lock_delta":{"type":"integer","title":"Time Lock Delta"},"htlc_minimum_msat":{"type":"integer","title":"Htlc Minimum Msat"},"base_fee":{"type":"integer","title":"Base Fee"},"fee_rate":{"type":"integer","title":"Fee Rate"},"htlc_maximum_msat":{"type":"integer","title":"Htlc Maximum Msat"},"extra_opaque_data":{"type":"string","title":"Extra Opaque Data"}},"type":"object","required":["signature","chain_hash","chan_id","timestamp","message_flags","channel_flags","time_lock_delta","htlc_minimum_msat","base_fee","fee_rate","htlc_maximum_msat","extra_opaque_data"],"title":"ChannelUpdate"},"ConnectionInfo":{"properties":{"lnd_admin_macaroon":{"type":"string","title":"Lnd Admin Macaroon","description":"lnd macaroon with admin rights in hexstring format","default":""},"lnd_invoice_macaroon":{"type":"string","title":"Lnd Invoice Macaroon","description":"lnd macaroon that only creates invoices in hexstring format","default":""},"lnd_readonly_macaroon":{"type":"string","title":"Lnd Readonly Macaroon","description":"lnd macaroon with only read-only rights in hexstring format","default":""},"lnd_tls_cert":{"type":"string","title":"Lnd Tls Cert","description":"lnd tls cert in hexstring format","default":""},"lnd_rest_onion":{"type":"string","title":"Lnd Rest Onion","description":"lnd rest api onion address","default":""},"lnd_btcpay_connection_string":{"type":"string","title":"Lnd Btcpay Connection String","description":"connect BtcPay server locally to your lnd lightning node","default":""},"lnd_zeus_connection_string":{"type":"string","title":"Lnd Zeus Connection String","description":"connect Zeus app to your lnd lightning node","default":""},"cl_rest_zeus_connection_string":{"type":"string","title":"Cl Rest Zeus Connection String","description":"connect Zeus app to your core lightning node over rest","default":""},"cl_rest_macaroon":{"type":"string","title":"Cl Rest Macaroon","description":"core lightning rest macaroon","default":""},"cl_rest_onion":{"type":"string","title":"Cl Rest Onion","description":"core lightning rest onion address","default":""}},"type":"object","title":"ConnectionInfo"},"CustomRecordsEntry":{"properties":{"key":{"type":"integer","title":"Key"},"value":{"type":"string","title":"Value"}},"type":"object","required":["key","value"],"title":"CustomRecordsEntry"},"Feature":{"properties":{"name":{"type":"string","title":"Name"},"is_required":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Required"},"is_known":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Known"}},"type":"object","required":["name","is_required","is_known"],"title":"Feature"},"FeaturesEntry":{"properties":{"key":{"type":"integer","title":"Key"},"value":{"$ref":"#/components/schemas/Feature"}},"type":"object","required":["key","value"],"title":"FeaturesEntry"},"FeeEstimationMode":{"type":"string","enum":["conservative","economical"],"title":"FeeEstimationMode"},"FeeRevenue":{"properties":{"day":{"type":"integer","title":"Day","description":"Fee revenue earned in the last 24 hours"},"week":{"type":"integer","title":"Week","description":"Fee revenue earned in the last 7days"},"month":{"type":"integer","title":"Month","description":"Fee revenue earned in the last month"},"year":{"type":"integer","title":"Year","description":"Fee revenue earned in the last year.Might be null if not implemented by backend."},"total":{"type":"integer","title":"Total","description":"Fee revenue earned in the last year.Might be null if not implemented by backend"}},"type":"object","required":["day","week","month"],"title":"FeeRevenue"},"GenericTx":{"properties":{"index":{"type":"integer","title":"Index","description":"The index of the transaction.","default":0},"id":{"type":"string","title":"Id","description":"\nUnique identifier for this transaction.\n\nDepending on the type of the transaction it will be different:\n#### On-chain\nThe transaction hash\n\n#### Lightning Invoice and Payment\nThe payment request\n"},"category":{"$ref":"#/components/schemas/TxCategory","description":"Whether this is an onchain (**onchain**) or lightning (**ln**) transaction."},"type":{"$ref":"#/components/schemas/TxType","description":"Whether this is an outgoing (**send**) transaction or an incoming(**receive**) transaction."},"amount":{"type":"integer","title":"Amount","description":"\nThe value of the transaction, depending on the category in satoshis or millisatoshis.\n\n#### On-chain\nTransaction amount in satoshis\n\n#### Lightning Invoice\n* value in millisatoshis of the invoice if *unsettled*\n* amount in millisatoshis paid if invoice is *settled*\n\n#### Lightning Payment\n* amount sent in millisatoshis\n\n"},"time_stamp":{"type":"integer","title":"Time Stamp","description":"\nThe unix timestamp in seconds for the transaction.\n\nThe timestamp can mean different things in different situations:\n\n#### Lightning Invoice\n* Creation date for in-flight or failed invoices\n* Settle date for succeeded invoices\n\n#### On-chain\n* Creation date for transaction waiting in the mempool\n* Timestamp of the block where this transaction is included\n\n#### Lightning Payment\n\n"},"comment":{"type":"string","title":"Comment","description":"Optional comment for this transaction","default":""},"status":{"$ref":"#/components/schemas/TxStatus","description":"\nThe status of the transaction. Depending on the transaction category this can be different values:\n\nMay have different meanings in different situations:\n#### unknown\nAn unknown state was found.\n\n#### in_flight\n* A lightning payment is being sent\n* An invoice is waiting for the incoming payment\n* An on-chain transaction is waiting in the mempool\n\n#### succeeded\n* A lighting payment was successfully sent\n* An incoming payment was received for an invoice\n* An on-chain transaction was included in a block\n\n#### failed\n* A lightning payment attempt which could not be completed (no route found, insufficient funds, ...)\n* An invoice is expired or some other error happened\n"},"block_height":{"type":"integer","title":"Block Height","description":"Block height, if included in a block. Only applicable for category **onchain**."},"num_confs":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Num Confs","description":"Number of confirmations. Only applicable for category **onchain**."},"total_fees":{"type":"integer","title":"Total Fees","description":"Total fees paid for this transaction"}},"type":"object","required":["id","category","type","amount","time_stamp","status"],"title":"GenericTx"},"HTLCAttempt":{"properties":{"attempt_id":{"type":"integer","title":"Attempt Id"},"status":{"$ref":"#/components/schemas/HTLCStatus"},"route":{"$ref":"#/components/schemas/Route"},"attempt_time_ns":{"type":"integer","title":"Attempt Time Ns"},"resolve_time_ns":{"type":"integer","title":"Resolve Time Ns"},"failure":{"$ref":"#/components/schemas/HTLCAttemptFailure"},"preimage":{"type":"string","title":"Preimage"}},"type":"object","required":["attempt_id","status","route","attempt_time_ns","resolve_time_ns","failure","preimage"],"title":"HTLCAttempt"},"HTLCAttemptFailure":{"properties":{"code":{"type":"integer","title":"Code"},"channel_update":{"$ref":"#/components/schemas/ChannelUpdate"},"htlc_msat":{"type":"integer","title":"Htlc Msat"},"onion_sha_256":{"type":"string","title":"Onion Sha 256"},"cltv_expiry":{"type":"integer","title":"Cltv Expiry"},"flags":{"type":"integer","title":"Flags"},"failure_source_index":{"type":"integer","title":"Failure Source Index"},"height":{"type":"integer","title":"Height"}},"type":"object","required":["code","channel_update","htlc_msat","onion_sha_256","cltv_expiry","flags","failure_source_index","height"],"title":"HTLCAttemptFailure"},"HTLCStatus":{"type":"string","enum":["in_flight","succeeded","failed"],"title":"HTLCStatus"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"Hop":{"properties":{"chan_id":{"type":"integer","title":"Chan Id"},"chan_capacity":{"type":"integer","title":"Chan Capacity"},"amt_to_forward":{"type":"integer","title":"Amt To Forward"},"fee":{"type":"integer","title":"Fee"},"expiry":{"type":"integer","title":"Expiry"},"amt_to_forward_msat":{"type":"integer","title":"Amt To Forward Msat"},"fee_msat":{"type":"integer","title":"Fee Msat"},"pub_key":{"type":"string","title":"Pub Key"},"tlv_payload":{"type":"boolean","title":"Tlv Payload"}},"type":"object","required":["chan_id","chan_capacity","amt_to_forward","fee","expiry","amt_to_forward_msat","fee_msat","pub_key","tlv_payload"],"title":"Hop"},"HopHint":{"properties":{"node_id":{"type":"string","title":"Node Id","description":"The public key of the node at the start of the channel."},"chan_id":{"type":"string","title":"Chan Id","description":"The unique identifier of the channel."},"fee_base_msat":{"type":"integer","title":"Fee Base Msat","description":"The base fee of the channel denominated in msat."},"fee_proportional_millionths":{"type":"integer","title":"Fee Proportional Millionths","description":"The fee rate of the channel for sending onesatoshi across it denominated in msat"},"cltv_expiry_delta":{"type":"integer","title":"Cltv Expiry Delta","description":"The time-lock delta of the channel."}},"type":"object","required":["node_id","chan_id","fee_base_msat","fee_proportional_millionths","cltv_expiry_delta"],"title":"HopHint"},"Invoice":{"properties":{"memo":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Memo","description":"Optional memo to attach along with the invoice. Used for record keeping purposes for the invoice's creator, and will also be set in the description field of the encoded payment request if the description_hash field is not being used."},"r_preimage":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"R Preimage","description":"The hex-encoded preimage(32 byte) which will allow settling an incoming HTLC payable to this preimage."},"r_hash":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"R Hash","description":"The hash of the preimage."},"value_msat":{"type":"integer","title":"Value Msat","description":"The value of this invoice in milli satoshis."},"settled":{"type":"boolean","title":"Settled","description":"Whether this invoice has been fulfilled","default":false},"creation_date":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Creation Date","description":"When this invoice was created. Not available with CLN."},"settle_date":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Settle Date","description":"When this invoice was settled. Not available with pending invoices."},"expiry_date":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Expiry Date","description":"The time at which this invoice expires"},"payment_request":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Payment Request","description":"A bare-bones invoice for a payment within the Lightning Network. With the details of the invoice, the sender has all the data necessary to send a payment to the recipient."},"description_hash":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description Hash","description":"Hash(SHA-256) of a description of the payment. Used if the description of payment(memo) is too long to naturally fit within the description field of an encoded payment request."},"expiry":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Expiry","description":"Payment request expiry time in seconds. Default is 3600 (1 hour)."},"fallback_addr":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Fallback Addr","description":"Fallback on-chain address."},"cltv_expiry":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Cltv Expiry","description":"Delta to use for the time-lock of the CLTV extended to the final hop."},"route_hints":{"anyOf":[{"items":{"$ref":"#/components/schemas/RouteHint"},"type":"array"},{"type":"null"}],"title":"Route Hints","description":"Route hints that can each be individually used to assist in reaching the invoice's destination."},"private":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Private","description":"Whether this invoice should include routing hints for private channels."},"add_index":{"type":"string","title":"Add Index","description":"The index of this invoice. Each newly created invoice will increment this index making it monotonically increasing. CLN and LND handle ids differently. LND will generate an auto incremented integer id, while CLN will use a user supplied string id. To unify both, we auto generate an id for CLN and use the add_index for LND.For `LND` this will be an `integer` in string form. This is auto generated by LND. For `CLN` this will be a `string`. If the invoice was generated by BlitzAPI, this will be a [Firebase-like PushID](https://firebase.blog/posts/2015/02/the-2120-ways-to-ensure-unique_68). If generated by some other method, it'll be the string supplied by the user at the time of creation of the invoice."},"settle_index":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Settle Index","description":"The `settle` index of this invoice. Each newly settled invoice will increment this index making it monotonically increasing. "},"amt_paid_sat":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Amt Paid Sat","description":"The amount that was accepted for this invoice, in satoshis. This will ONLY be set if this invoice has been settled. We provide this field as if the invoice was created with a zero value, then we need to record what amount was ultimately accepted. Additionally, it's possible that the sender paid MORE that was specified in the original invoice. So we'll record that here as well."},"amt_paid_msat":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Amt Paid Msat","description":"The amount that was accepted for this invoice, in millisatoshis. This will ONLY be set if this invoice has been settled. We provide this field as if the invoice was created with a zero value, then we need to record what amount was ultimately accepted. Additionally, it's possible that the sender paid MORE that was specified in the original invoice. So we'll record that here as well."},"state":{"$ref":"#/components/schemas/InvoiceState","description":"The state the invoice is in."},"htlcs":{"anyOf":[{"items":{"$ref":"#/components/schemas/InvoiceHTLC"},"type":"array"},{"type":"null"}],"title":"Htlcs","description":"List of HTLCs paying to this invoice[EXPERIMENTAL]."},"features":{"anyOf":[{"items":{"$ref":"#/components/schemas/FeaturesEntry"},"type":"array"},{"type":"null"}],"title":"Features","description":"List of features advertised on the invoice."},"is_keysend":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Keysend","description":"[LND only] Indicates if this invoice was a spontaneous payment that arrived via keysend[EXPERIMENTAL]."},"payment_addr":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Payment Addr","description":"The payment address of this invoice. This value will be used in MPP payments, and also for newer invoices that always require the MPP payload for added end-to-end security."},"is_amp":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Amp","description":"Signals whether or not this is an AMP invoice."}},"type":"object","required":["value_msat","add_index","state"],"title":"Invoice"},"InvoiceHTLC":{"properties":{"chan_id":{"type":"integer","title":"Chan Id","description":"The channel ID over which the HTLC was received."},"htlc_index":{"type":"integer","title":"Htlc Index","description":"The index of the HTLC on the channel."},"amt_msat":{"type":"integer","title":"Amt Msat","description":"The amount of the HTLC in msat."},"accept_height":{"type":"integer","title":"Accept Height","description":"The block height at which this HTLC was accepted."},"accept_time":{"type":"integer","title":"Accept Time","description":"The time at which this HTLC was accepted."},"resolve_time":{"type":"integer","title":"Resolve Time","description":"The time at which this HTLC was resolved."},"expiry_height":{"type":"integer","title":"Expiry Height","description":"The block height at which this HTLC expires."},"state":{"$ref":"#/components/schemas/InvoiceHTLCState","description":"The state of the HTLC."},"custom_records":{"items":{"$ref":"#/components/schemas/CustomRecordsEntry"},"type":"array","title":"Custom Records","description":"Custom tlv records.","default":[]},"mpp_total_amt_msat":{"type":"integer","title":"Mpp Total Amt Msat","description":"The total amount of the mpp payment in msat."},"amp":{"$ref":"#/components/schemas/Amp","description":"Details relevant to AMP HTLCs, only populated if this is an AMP HTLC."}},"type":"object","required":["chan_id","htlc_index","amt_msat","accept_height","accept_time","resolve_time","expiry_height","state","mpp_total_amt_msat"],"title":"InvoiceHTLC"},"InvoiceHTLCState":{"type":"string","enum":["accepted","settled","canceled"],"title":"InvoiceHTLCState"},"InvoiceState":{"type":"string","enum":["open","settled","canceled","accepted"],"title":"InvoiceState"},"LnInfo":{"properties":{"implementation":{"type":"string","title":"Implementation","description":"Lightning software implementation (LND, CLN)"},"version":{"type":"string","title":"Version","description":"The version of the software that the node is running."},"commit_hash":{"type":"string","title":"Commit Hash","description":"The SHA1 commit hash that the daemon is compiled with."},"identity_pubkey":{"type":"string","title":"Identity Pubkey","description":"The identity pubkey of the current node."},"identity_uri":{"type":"string","title":"Identity Uri","description":"The complete URI (pubkey@physicaladdress:port) the current node."},"alias":{"type":"string","title":"Alias","description":"The alias of the node."},"color":{"type":"string","title":"Color","description":"The color of the current node in hex code format."},"num_pending_channels":{"type":"integer","title":"Num Pending Channels","description":"Number of pending channels."},"num_active_channels":{"type":"integer","title":"Num Active Channels","description":"Number of active channels."},"num_inactive_channels":{"type":"integer","title":"Num Inactive Channels","description":"Number of inactive channels."},"num_peers":{"type":"integer","title":"Num Peers","description":"Number of peers."},"block_height":{"type":"integer","title":"Block Height","description":"The node's current view of the height of the best block. Only available with LND."},"block_hash":{"type":"string","title":"Block Hash","description":"The node's current view of the hash of the best block. Only available with LND.","default":""},"best_header_timestamp":{"type":"integer","title":"Best Header Timestamp","description":"Timestamp of the block best known to the wallet. Only available with LND."},"synced_to_chain":{"type":"boolean","title":"Synced To Chain","description":"Whether the wallet's view is synced to the main chain. Only available with LND."},"synced_to_graph":{"type":"boolean","title":"Synced To Graph","description":"Whether we consider ourselves synced with the public channel graph. Only available with LND."},"chains":{"items":{"$ref":"#/components/schemas/Chain"},"type":"array","title":"Chains","description":"A list of active chains the node is connected to","default":[]},"uris":{"items":{"type":"string"},"type":"array","title":"Uris","description":"The URIs of the current node.","default":[]},"features":{"items":{"$ref":"#/components/schemas/FeaturesEntry"},"type":"array","title":"Features","description":"Features that our node has advertised in our init message node announcements and invoices. Not yet implemented with CLN","default":[]}},"type":"object","required":["implementation","version","commit_hash","identity_pubkey","identity_uri","alias","color","num_pending_channels","num_active_channels","num_inactive_channels","num_peers","block_height"],"title":"LnInfo"},"LoginInput":{"properties":{"password":{"type":"string","minLength":8,"title":"Password"},"one_time_password":{"anyOf":[{"type":"string","maxLength":6,"minLength":6,"pattern":"^[0-9]+$"},{"type":"null"}],"title":"One Time Password"}},"type":"object","required":["password"],"title":"LoginInput"},"MPPRecord":{"properties":{"payment_addr":{"type":"string","title":"Payment Addr"},"total_amt_msat":{"type":"integer","title":"Total Amt Msat"}},"type":"object","required":["payment_addr","total_amt_msat"],"title":"MPPRecord"},"NetworkInfo":{"properties":{"version":{"type":"integer","title":"Version","description":"The bitcoin core server version"},"subversion":{"type":"string","title":"Subversion","description":"The server subversion string"},"protocol_version":{"type":"integer","title":"Protocol Version","description":"The protocol version"},"local_services":{"type":"string","title":"Local Services","description":"The services we offer to the network, hex formatted"},"local_services_names":{"items":{"type":"string"},"type":"array","title":"Local Services Names","description":"The services we offer to the network, in human-readable form","default":[]},"local_relay":{"type":"boolean","title":"Local Relay","description":"True if transaction relay is requested from peers"},"time_offset":{"type":"integer","title":"Time Offset","description":"The time offset"},"connections":{"type":"integer","title":"Connections","description":"The total number of connections"},"connections_in":{"type":"integer","title":"Connections In","description":"The number of inbound connections"},"connections_out":{"type":"integer","title":"Connections Out","description":"The number of outbound connections"},"network_active":{"type":"boolean","title":"Network Active","description":"Whether p2p networking is enabled"},"networks":{"items":{"$ref":"#/components/schemas/BtcNetwork"},"type":"array","title":"Networks","description":"Information per network"},"relay_fee":{"type":"number","title":"Relay Fee","description":"Minimum relay fee for transactions in BTC/kB"},"incremental_fee":{"type":"number","title":"Incremental Fee","description":"Minimum fee increment for mempool limiting or BIP 125 replacement in BTC/kB"},"local_addresses":{"items":{"$ref":"#/components/schemas/BtcLocalAddress"},"type":"array","title":"Local Addresses","description":"List of local addresses","default":[]},"warnings":{"type":"string","title":"Warnings","description":"Any network and blockchain warnings","default":""}},"type":"object","required":["version","subversion","protocol_version","local_relay","time_offset","connections","connections_in","connections_out","network_active","networks","relay_fee","incremental_fee"],"title":"NetworkInfo"},"NewAddressInput":{"properties":{"type":{"$ref":"#/components/schemas/OnchainAddressType","description":"Address-types has to be one of: * p2wkh: Pay to witness key hash (bech32) * np2wkh: Pay to nested witness key hash"}},"type":"object","required":["type"],"title":"NewAddressInput"},"OnChainTransaction":{"properties":{"tx_hash":{"type":"string","title":"Tx Hash","description":"The transaction hash"},"amount":{"type":"integer","title":"Amount","description":"The transaction amount, denominated in satoshis"},"num_confirmations":{"type":"integer","title":"Num Confirmations","description":"The number of confirmations"},"block_height":{"type":"integer","title":"Block Height","description":"The height of the block this transaction was included in"},"time_stamp":{"type":"integer","title":"Time Stamp","description":"Timestamp of this transaction"},"total_fees":{"type":"integer","title":"Total Fees","description":"Fees paid for this transaction"},"dest_addresses":{"items":{"type":"string"},"type":"array","title":"Dest Addresses","description":"Addresses that received funds for this transaction","default":[]},"label":{"type":"string","title":"Label","description":"An optional label that was set on transaction broadcast.","default":""}},"type":"object","required":["tx_hash","amount","num_confirmations","block_height","time_stamp","total_fees"],"title":"OnChainTransaction"},"OnchainAddressType":{"type":"string","enum":["p2wkh","np2wkh"],"title":"OnchainAddressType"},"Payment":{"properties":{"payment_hash":{"type":"string","title":"Payment Hash","description":"The payment hash"},"payment_preimage":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Payment Preimage","description":"The payment preimage"},"value_msat":{"type":"integer","title":"Value Msat","description":"The value of the payment in milli-satoshis"},"payment_request":{"type":"string","title":"Payment Request","description":"The optional payment request being fulfilled."},"status":{"$ref":"#/components/schemas/PaymentStatus","description":"The status of the payment.","default":"unknown"},"fee_msat":{"type":"integer","title":"Fee Msat","description":"The fee paid for this payment in msat"},"creation_time_ns":{"type":"integer","title":"Creation Time Ns","description":"The time in UNIX nanoseconds at which the payment was created."},"htlcs":{"items":{"$ref":"#/components/schemas/HTLCAttempt"},"type":"array","title":"Htlcs","description":"The HTLCs made in attempt to settle the payment.","default":[]},"payment_index":{"type":"integer","title":"Payment Index","description":"The payment index. Only set with LND, 0 otherwise.","default":0},"label":{"type":"string","title":"Label","description":"The payment label. Only set with CLN, empty otherwise.","default":""},"failure_reason":{"$ref":"#/components/schemas/PaymentFailureReason","description":"The failure reason","default":"FAILURE_REASON_NONE"}},"type":"object","required":["payment_hash","value_msat","fee_msat","creation_time_ns"],"title":"Payment"},"PaymentFailureReason":{"type":"string","enum":["FAILURE_REASON_NONE","FAILURE_REASON_TIMEOUT","FAILURE_REASON_NO_ROUTE","FAILURE_REASON_ERROR","FAILURE_REASON_INCORRECT_PAYMENT_DETAILS","FAILURE_REASON_INSUFFICIENT_BALANCE"],"title":"PaymentFailureReason"},"PaymentRequest":{"properties":{"destination":{"type":"string","title":"Destination"},"payment_hash":{"type":"string","title":"Payment Hash"},"num_satoshis":{"type":"integer","title":"Num Satoshis","description":"Deprecated. User num_msat instead","deprecated":true},"timestamp":{"type":"integer","title":"Timestamp"},"expiry":{"type":"integer","title":"Expiry"},"description":{"type":"string","title":"Description"},"description_hash":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description Hash"},"fallback_addr":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Fallback Addr"},"cltv_expiry":{"type":"integer","title":"Cltv Expiry"},"route_hints":{"items":{"$ref":"#/components/schemas/RouteHint"},"type":"array","title":"Route Hints","description":"A list of [HopHint] for the RouteHint","default":[]},"payment_addr":{"type":"string","title":"Payment Addr","description":"The payment address in hex format","default":""},"num_msat":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Num Msat"},"features":{"items":{"$ref":"#/components/schemas/FeaturesEntry"},"type":"array","title":"Features","default":[]},"currency":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Currency","description":"Optional requested currency of the payment. ","default":""}},"type":"object","required":["destination","payment_hash","timestamp","expiry","description","description_hash","fallback_addr","cltv_expiry","num_msat"],"title":"PaymentRequest"},"PaymentStatus":{"type":"string","enum":["unknown","in_flight","succeeded","failed"],"title":"PaymentStatus"},"RawDebugLogData":{"properties":{"raw_data":{"type":"string","title":"Raw Data","description":"The raw debug log text"},"github_issues_url":{"type":"string","title":"Github Issues Url","description":"Link to the Raspiblitz issue tracker","default":"https://www.github.com/rootzoll/raspiblitz/issues"}},"type":"object","required":["raw_data"],"title":"RawDebugLogData"},"RawTransaction":{"properties":{"in_active_chain":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"In Active Chain","description":"Whether specified block is in the active chain or not (only present with explicit 'blockhash' argument)"},"txid":{"type":"string","title":"Txid","description":"The transaction id (same as provided)"},"hash":{"type":"string","title":"Hash","description":"The transaction hash (differs from txid for witness transactions)"},"size":{"type":"integer","title":"Size","description":"The serialized transaction size"},"vsize":{"type":"integer","title":"Vsize","description":"The virtual transaction size (differs from size for witness transactions)"},"weight":{"type":"integer","title":"Weight","description":"The transaction's weight (between vsize*4 - 3 and vsize*4)"},"version":{"type":"integer","title":"Version","description":"The version"},"locktime":{"type":"integer","title":"Locktime","description":"The lock time"},"vin":{"items":{"type":"object"},"type":"array","title":"Vin","description":"The transaction's inputs"},"vout":{"items":{"type":"object"},"type":"array","title":"Vout","description":"The transaction's outputs"},"blockhash":{"type":"string","title":"Blockhash","description":"The block hash"},"confirmations":{"type":"integer","title":"Confirmations","description":"The number of confirmations"},"blocktime":{"type":"integer","title":"Blocktime","description":"The block time in seconds since epoch (Jan 1 1970 GMT)"}},"type":"object","required":["txid","hash","size","vsize","weight","version","locktime","vin","vout","blockhash","confirmations","blocktime"],"title":"RawTransaction"},"Route":{"properties":{"total_time_lock":{"type":"integer","title":"Total Time Lock"},"total_fees":{"type":"integer","title":"Total Fees"},"total_amt":{"type":"integer","title":"Total Amt"},"hops":{"items":{"$ref":"#/components/schemas/Hop"},"type":"array","title":"Hops"},"total_fees_msat":{"type":"integer","title":"Total Fees Msat"},"total_amt_msat":{"type":"integer","title":"Total Amt Msat"},"mpp_record":{"anyOf":[{"$ref":"#/components/schemas/MPPRecord"},{"type":"null"}]},"amp_record":{"anyOf":[{"$ref":"#/components/schemas/AMPRecord"},{"type":"null"}]},"custom_records":{"items":{"$ref":"#/components/schemas/CustomRecordsEntry"},"type":"array","title":"Custom Records"}},"type":"object","required":["total_time_lock","total_fees","total_amt","hops","total_fees_msat","total_amt_msat","mpp_record","amp_record","custom_records"],"title":"Route"},"RouteHint":{"properties":{"hop_hints":{"items":{"$ref":"#/components/schemas/HopHint"},"type":"array","title":"Hop Hints","description":"A list of hop hints that when chained together can assist in reaching a specific destination.","default":[]}},"type":"object","title":"RouteHint"},"SendCoinsInput":{"properties":{"address":{"type":"string","title":"Address","description":"The base58 or bech32 encoded bitcoin address to send coins to on-chain"},"target_conf":{"type":"integer","title":"Target Conf","description":"The number of blocks that the transaction *should* confirm in, will be used for fee estimation"},"sat_per_vbyte":{"type":"integer","title":"Sat Per Vbyte","description":"A manual fee expressed in sat/vbyte that should be used when crafting the transaction (default: 0)"},"min_confs":{"type":"integer","title":"Min Confs","description":"The minimum number of confirmations each one of your outputs used for the transaction must satisfy","default":1},"label":{"type":"string","title":"Label","description":"A label for the transaction. Ignored by CLN backend.","default":""},"send_all":{"type":"boolean","title":"Send All","description":"Send all available on-chain funds from the wallet. Will be executed `amount` is **0**","default":false},"amount":{"type":"integer","minimum":0.0,"title":"Amount","description":"The number of bitcoin denominated in satoshis to send. Must not be set when `send_all` is true.","default":0}},"type":"object","required":["address"],"title":"SendCoinsInput"},"SendCoinsResponse":{"properties":{"txid":{"type":"string","title":"Txid","description":"The transaction ID for this onchain payment"},"address":{"type":"string","title":"Address","description":"The base58 or bech32 encoded bitcoin address where the onchain funds where sent to"},"amount":{"type":"integer","minimum":0.0,"title":"Amount","description":"The number of bitcoin denominated in satoshis which where sent"},"fees":{"type":"integer","minimum":0.0,"title":"Fees","description":"The number of bitcoin denominated in satoshis which where paid as fees"},"label":{"type":"string","title":"Label","description":"The label used for the transaction. Ignored by CLN backend.","default":""},"send_all":{"type":"boolean","title":"Send All","description":"If this transaction was a `send_all` transaction.","default":false}},"type":"object","required":["txid","address","amount"],"title":"SendCoinsResponse"},"SoftFork":{"properties":{"name":{"type":"string","title":"Name","description":"Name of the softfork"},"type":{"type":"string","title":"Type","description":"One of \"buried\", \"bip9\""},"active":{"type":"boolean","title":"Active","description":"True **if** the rules are enforced for the mempool and the next block"},"bip9":{"anyOf":[{"$ref":"#/components/schemas/Bip9Data"},{"type":"null"}],"description":"Status of bip9 softforks(only for \"bip9\" type)"},"height":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Height","description":"Height of the first block which the rules are or will be enforced (only for `buried` type, or `bip9` type with `active` status)"}},"type":"object","required":["name","type","active"],"title":"SoftFork"},"StartDoneData":{"properties":{"hostname":{"type":"string","title":"Hostname","default":""},"forceFreshSetup":{"type":"boolean","title":"Forcefreshsetup","default":false},"keepBlockchain":{"type":"boolean","title":"Keepblockchain","default":true},"lightning":{"type":"string","title":"Lightning","default":""},"passwordA":{"type":"string","title":"Passworda","default":""},"passwordB":{"type":"string","title":"Passwordb","default":""},"passwordC":{"type":"string","title":"Passwordc","default":""}},"type":"object","title":"StartDoneData"},"SubSystemHealthInfo":{"properties":{"name":{"type":"string","title":"Name","description":"Name of the subsystem"},"health":{"type":"boolean","title":"Health","description":"Whether this system is healthy or not"},"message":{"type":"string","title":"Message","description":"Optional message describing the systems health","default":""}},"type":"object","required":["name","health"],"title":"SubSystemHealthInfo"},"SystemHealthInfo":{"properties":{"healthy":{"type":"boolean","title":"Healthy","description":""},"message":{"type":"string","title":"Message","description":"","default":""},"subsystems":{"items":{"$ref":"#/components/schemas/SubSystemHealthInfo"},"type":"array","title":"Subsystems","description":"Health information of running subsystems","default":[]}},"type":"object","required":["healthy"],"title":"SystemHealthInfo"},"SystemInfo":{"properties":{"alias":{"type":"string","title":"Alias","description":"Name of the node (same as Lightning alias)","default":""},"color":{"type":"string","title":"Color","description":"The color of the current node in hex code format"},"platform":{"$ref":"#/components/schemas/APIPlatform","description":"The platform this API is running on.","default":"raspiblitz"},"platform_version":{"type":"string","title":"Platform Version","description":"The version of this platform","default":""},"code_version":{"type":"string","title":"Code Version","description":"[RaspiBlitz only] The code version.","default":""},"api_version":{"type":"string","title":"Api Version","description":"Version of the API software on this system."},"tor_web_ui":{"type":"string","title":"Tor Web Ui","description":"WebUI TOR address","default":""},"tor_api":{"type":"string","title":"Tor Api","description":"API TOR address","default":""},"lan_web_ui":{"type":"string","title":"Lan Web Ui","description":"WebUI LAN address","default":""},"lan_api":{"type":"string","title":"Lan Api","description":"API LAN address","default":""},"ssh_address":{"type":"string","title":"Ssh Address","description":"Address to ssh into on local LAN (e.g. `ssh admin@192.168.1.28`"},"chain":{"type":"string","title":"Chain","description":"The current chain this node is connected to (mainnet, testnet or signet)"}},"type":"object","required":["color","api_version","ssh_address","chain"],"title":"SystemInfo"},"TxCategory":{"type":"string","enum":["onchain","ln"],"title":"TxCategory"},"TxStatus":{"type":"string","enum":["unknown","in_flight","succeeded","failed"],"title":"TxStatus"},"TxType":{"type":"string","enum":["unknown","send","receive"],"title":"TxType"},"UnlockWalletInput":{"properties":{"password":{"type":"string","title":"Password","description":"The wallet password"}},"type":"object","required":["password"],"title":"UnlockWalletInput"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"WalletBalance":{"properties":{"onchain_confirmed_balance":{"type":"integer","title":"Onchain Confirmed Balance","description":"Confirmed onchain balance (more than 3 confirmations) in sat"},"onchain_total_balance":{"type":"integer","title":"Onchain Total Balance","description":"Total combined onchain balance in sat"},"onchain_unconfirmed_balance":{"type":"integer","title":"Onchain Unconfirmed Balance","description":"Unconfirmed onchain balance (less than 3 confirmations) in sat"},"channel_local_balance":{"type":"integer","title":"Channel Local Balance","description":"Sum of channels local balances in msat"},"channel_remote_balance":{"type":"integer","title":"Channel Remote Balance","description":"Sum of channels remote balances in msat."},"channel_unsettled_local_balance":{"type":"integer","title":"Channel Unsettled Local Balance","description":"Sum of channels local unsettled balances in msat."},"channel_unsettled_remote_balance":{"type":"integer","title":"Channel Unsettled Remote Balance","description":"Sum of channels remote unsettled balances in msat."},"channel_pending_open_local_balance":{"type":"integer","title":"Channel Pending Open Local Balance","description":"Sum of channels pending local balances in msat."},"channel_pending_open_remote_balance":{"type":"integer","title":"Channel Pending Open Remote Balance","description":"Sum of channels pending remote balances in msat."}},"type":"object","required":["onchain_confirmed_balance","onchain_total_balance","onchain_unconfirmed_balance","channel_local_balance","channel_remote_balance","channel_unsettled_local_balance","channel_unsettled_remote_balance","channel_pending_open_local_balance","channel_pending_open_remote_balance"],"title":"WalletBalance"}},"securitySchemes":{"JWTBearer":{"type":"http","scheme":"bearer"}}}} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..d544843 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,10561 @@ +{ + "name": "raspiblesk-web", + "version": "1.4.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "raspiblesk-web", + "version": "1.4.0", + "license": "MIT", + "dependencies": { + "@bitcoin-design/bitcoin-icons-react": "^0.1.10", + "@heroicons/react": "^2.2.0", + "@heroui/react": "^2.8.2", + "@heroui/system": "^2.4.20", + "@heroui/theme": "^2.4.20", + "@tailwindcss/vite": "^4.1.17", + "axios": "^1.13.2", + "framer-motion": "^12.23.12", + "i18next": "^25.6.3", + "qrcode.react": "^4.2.0", + "react": "^19.1.1", + "react-dom": "^19.1.1", + "react-hook-form": "^7.66.1", + "react-i18next": "^16.3.5", + "react-router": "^7.9.6", + "react-toastify": "^11.0.5", + "react-tooltip": "^5.28.1", + "tailwind-merge": "^3.4.0" + }, + "devDependencies": { + "@biomejs/biome": "^2.3.7", + "@playwright/test": "^1.52.0", + "@testing-library/dom": "^10.4.0", + "@testing-library/jest-dom": "^6.6.3", + "@testing-library/react": "^16.3.0", + "@testing-library/user-event": "^14.6.1", + "@types/node": "^24.10.1", + "@types/react": "^19.2.6", + "@types/react-dom": "^19.2.3", + "@vitejs/plugin-react": "^5.1.1", + "@vitest/coverage-v8": "^4.0.12", + "concurrently": "^9.1.2", + "husky": "^9.1.7", + "jsdom": "^27.2.0", + "lint-staged": "^16.2.7", + "msw": "^2.12.2", + "resize-observer-polyfill": "^1.5.1", + "tailwindcss": "^4.1.17", + "typescript": "^5.9.3", + "vite": "^7.2.4", + "vite-plugin-svgr": "^4.3.0", + "vite-tsconfig-paths": "^6.0.5", + "vitest": "^4.0.12" + } + }, + "node_modules/@acemir/cssom": { + "version": "0.9.31", + "resolved": "https://registry.npmjs.org/@acemir/cssom/-/cssom-0.9.31.tgz", + "integrity": "sha512-ZnR3GSaH+/vJ0YlHau21FjfLYjMpYVIzTD8M8vIEQvIGxeOXyXdzCI140rrCY862p/C/BbzWsjc1dgnM9mkoTA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@adobe/css-tools": { + "version": "4.4.4", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.4.tgz", + "integrity": "sha512-Elp+iwUx5rN5+Y8xLt5/GRoG20WGoDCQ/1Fb+1LiGtvwbDavuSk0jhD/eZdckHAuzcDzccnkv+rEjyWfRx18gg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@asamuzakjp/css-color": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-4.1.2.tgz", + "integrity": "sha512-NfBUvBaYgKIuq6E/RBLY1m0IohzNHAYyaJGuTK79Z23uNwmz2jl1mPsC5ZxCCxylinKhT1Amn5oNTlx1wN8cQg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@csstools/css-calc": "^3.0.0", + "@csstools/css-color-parser": "^4.0.1", + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0", + "lru-cache": "^11.2.5" + } + }, + "node_modules/@asamuzakjp/css-color/node_modules/lru-cache": { + "version": "11.2.6", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz", + "integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@asamuzakjp/dom-selector": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-6.8.1.tgz", + "integrity": "sha512-MvRz1nCqW0fsy8Qz4dnLIvhOlMzqDVBabZx6lH+YywFDdjXhMY37SmpV1XFX3JzG5GWHn63j6HX6QPr3lZXHvQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@asamuzakjp/nwsapi": "^2.3.9", + "bidi-js": "^1.0.3", + "css-tree": "^3.1.0", + "is-potential-custom-element-name": "^1.0.1", + "lru-cache": "^11.2.6" + } + }, + "node_modules/@asamuzakjp/dom-selector/node_modules/lru-cache": { + "version": "11.2.6", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz", + "integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@asamuzakjp/nwsapi": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/@asamuzakjp/nwsapi/-/nwsapi-2.3.9.tgz", + "integrity": "sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@babel/code-frame": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz", + "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", + "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helpers": "^7.28.6", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", + "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", + "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.28.6", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", + "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", + "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", + "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "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": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", + "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz", + "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "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.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "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.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz", + "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", + "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-1.0.2.tgz", + "integrity": "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@biomejs/biome": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.4.0.tgz", + "integrity": "sha512-iluT61cORUDIC5i/y42ljyQraCemmmcgbMLLCnYO+yh+2hjTmcMFcwY8G0zTzWCsPb3t3AyKc+0t/VuhPZULUg==", + "dev": true, + "license": "MIT OR Apache-2.0", + "bin": { + "biome": "bin/biome" + }, + "engines": { + "node": ">=14.21.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/biome" + }, + "optionalDependencies": { + "@biomejs/cli-darwin-arm64": "2.4.0", + "@biomejs/cli-darwin-x64": "2.4.0", + "@biomejs/cli-linux-arm64": "2.4.0", + "@biomejs/cli-linux-arm64-musl": "2.4.0", + "@biomejs/cli-linux-x64": "2.4.0", + "@biomejs/cli-linux-x64-musl": "2.4.0", + "@biomejs/cli-win32-arm64": "2.4.0", + "@biomejs/cli-win32-x64": "2.4.0" + } + }, + "node_modules/@biomejs/cli-darwin-arm64": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.4.0.tgz", + "integrity": "sha512-L+YpOtPSuU0etomfvFTPWRsa7+8ejaJL3yaROEoT/96HDJbR6OsvZQk0C8JUYou+XFdP+JcGxqZknkp4n934RA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-darwin-x64": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.4.0.tgz", + "integrity": "sha512-Aq+S7ffpb5ynTyLgtnEjG+W6xuTd2F7FdC7J6ShpvRhZwJhjzwITGF9vrqoOnw0sv1XWkt2Q1Rpg+hleg/Xg7Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-arm64": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.4.0.tgz", + "integrity": "sha512-u2p54IhvNAWB+h7+rxCZe3reNfQYFK+ppDw+q0yegrGclFYnDPZAntv/PqgUacpC3uxTeuWFgWW7RFe3lHuxOA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-arm64-musl": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.4.0.tgz", + "integrity": "sha512-1rhDUq8sf7xX3tg7vbnU3WVfanKCKi40OXc4VleBMzRStmQHdeBY46aFP6VdwEomcVjyNiu+Zcr3LZtAdrZrjQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-x64": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-2.4.0.tgz", + "integrity": "sha512-WVFOhsnzhrbMGOSIcB9yFdRV2oG2KkRRhIZiunI9gJqSU3ax9ErdnTxRfJUxZUI9NbzVxC60OCXNcu+mXfF/Tw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-x64-musl": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.4.0.tgz", + "integrity": "sha512-Omo0xhl63z47X+CrE5viEWKJhejJyndl577VoXg763U/aoATrK3r5+8DPh02GokWPeODX1Hek00OtjjooGan9w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-win32-arm64": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.4.0.tgz", + "integrity": "sha512-aqRwW0LJLV1v1NzyLvLWQhdLmDSAV1vUh+OBdYJaa8f28XBn5BZavo+WTfqgEzALZxlNfBmu6NGO6Al3MbCULw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-win32-x64": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.4.0.tgz", + "integrity": "sha512-g47s+V+OqsGxbSZN3lpav6WYOk0PIc3aCBAq+p6dwSynL3K5MA6Cg6nkzDOlu28GEHwbakW+BllzHCJCxnfK5Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@bitcoin-design/bitcoin-icons-react": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/@bitcoin-design/bitcoin-icons-react/-/bitcoin-icons-react-0.1.10.tgz", + "integrity": "sha512-f7GSutKHa4EK4LWI/phnGCJsN8fzFbVAVQ4F1MYxiza34LVmXmbgHUmdP/BR8ZeQSIbZLt19inpJZDBtQvYe4Q==", + "license": "MIT", + "peerDependencies": { + "react": ">= 16" + } + }, + "node_modules/@csstools/color-helpers": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-6.0.1.tgz", + "integrity": "sha512-NmXRccUJMk2AWA5A7e5a//3bCIMyOu2hAtdRYrhPPHjDxINuCwX1w6rnIZ4xjLcp0ayv6h8Pc3X0eJUGiAAXHQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=20.19.0" + } + }, + "node_modules/@csstools/css-calc": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-3.1.1.tgz", + "integrity": "sha512-HJ26Z/vmsZQqs/o3a6bgKslXGFAungXGbinULZO3eMsOyNJHeBBZfup5FiZInOghgoM4Hwnmw+OgbJCNg1wwUQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0" + } + }, + "node_modules/@csstools/css-color-parser": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-4.0.1.tgz", + "integrity": "sha512-vYwO15eRBEkeF6xjAno/KQ61HacNhfQuuU/eGwH67DplL0zD5ZixUa563phQvUelA07yDczIXdtmYojCphKJcw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "@csstools/color-helpers": "^6.0.1", + "@csstools/css-calc": "^3.0.0" + }, + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0" + } + }, + "node_modules/@csstools/css-parser-algorithms": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-4.0.0.tgz", + "integrity": "sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "@csstools/css-tokenizer": "^4.0.0" + } + }, + "node_modules/@csstools/css-syntax-patches-for-csstree": { + "version": "1.0.27", + "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.0.27.tgz", + "integrity": "sha512-sxP33Jwg1bviSUXAV43cVYdmjt2TLnLXNqCWl9xmxHawWVjGz/kEbdkr7F9pxJNBN2Mh+dq0crgItbW6tQvyow==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0" + }, + "node_modules/@csstools/css-tokenizer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-4.0.0.tgz", + "integrity": "sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=20.19.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz", + "integrity": "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.3.tgz", + "integrity": "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz", + "integrity": "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.3.tgz", + "integrity": "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz", + "integrity": "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.3.tgz", + "integrity": "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz", + "integrity": "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz", + "integrity": "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz", + "integrity": "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz", + "integrity": "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz", + "integrity": "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz", + "integrity": "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz", + "integrity": "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz", + "integrity": "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz", + "integrity": "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz", + "integrity": "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.3.tgz", + "integrity": "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz", + "integrity": "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz", + "integrity": "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz", + "integrity": "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz", + "integrity": "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz", + "integrity": "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz", + "integrity": "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz", + "integrity": "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz", + "integrity": "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz", + "integrity": "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@exodus/bytes": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@exodus/bytes/-/bytes-1.14.1.tgz", + "integrity": "sha512-OhkBFWI6GcRMUroChZiopRiSp2iAMvEBK47NhJooDqz1RERO4QuZIZnjP63TXX8GAiLABkYmX+fuQsdJ1dd2QQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + }, + "peerDependencies": { + "@noble/hashes": "^1.8.0 || ^2.0.0" + }, + "peerDependenciesMeta": { + "@noble/hashes": { + "optional": true + } + } + }, + "node_modules/@floating-ui/core": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.4.tgz", + "integrity": "sha512-C3HlIdsBxszvm5McXlB8PeOEWfBhcGBTZGkGlWc2U0KFY5IwG5OQEuQ8rq52DZmcHDlPLd+YFBK+cZcytwIFWg==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.10" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.5.tgz", + "integrity": "sha512-N0bD2kIPInNHUHehXhMke1rBGs1dwqvC9O9KYMyyjK7iXt7GAhnro7UlcuYcGdS/yYOlq0MAVgrow8IbWJwyqg==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.7.4", + "@floating-ui/utils": "^0.2.10" + } + }, + "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/@formatjs/ecma402-abstract": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-2.3.6.tgz", + "integrity": "sha512-HJnTFeRM2kVFVr5gr5kH1XP6K0JcJtE7Lzvtr3FS/so5f1kpsqqqxy5JF+FRaO6H2qmcMfAUIox7AJteieRtVw==", + "license": "MIT", + "dependencies": { + "@formatjs/fast-memoize": "2.2.7", + "@formatjs/intl-localematcher": "0.6.2", + "decimal.js": "^10.4.3", + "tslib": "^2.8.0" + } + }, + "node_modules/@formatjs/fast-memoize": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-2.2.7.tgz", + "integrity": "sha512-Yabmi9nSvyOMrlSeGGWDiH7rf3a7sIwplbvo/dlz9WCIjzIQAfy1RMf4S0X3yG724n5Ghu2GmEl5NJIV6O9sZQ==", + "license": "MIT", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@formatjs/icu-messageformat-parser": { + "version": "2.11.4", + "resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.11.4.tgz", + "integrity": "sha512-7kR78cRrPNB4fjGFZg3Rmj5aah8rQj9KPzuLsmcSn4ipLXQvC04keycTI1F7kJYDwIXtT2+7IDEto842CfZBtw==", + "license": "MIT", + "dependencies": { + "@formatjs/ecma402-abstract": "2.3.6", + "@formatjs/icu-skeleton-parser": "1.8.16", + "tslib": "^2.8.0" + } + }, + "node_modules/@formatjs/icu-skeleton-parser": { + "version": "1.8.16", + "resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.8.16.tgz", + "integrity": "sha512-H13E9Xl+PxBd8D5/6TVUluSpxGNvFSlN/b3coUp0e0JpuWXXnQDiavIpY3NnvSp4xhEMoXyyBvVfdFX8jglOHQ==", + "license": "MIT", + "dependencies": { + "@formatjs/ecma402-abstract": "2.3.6", + "tslib": "^2.8.0" + } + }, + "node_modules/@formatjs/intl-localematcher": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.6.2.tgz", + "integrity": "sha512-XOMO2Hupl0wdd172Y06h6kLpBz6Dv+J4okPLl4LPtzbr8f66WbIoy4ev98EBuZ6ZK4h5ydTN6XneT4QVpD7cdA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@heroicons/react": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@heroicons/react/-/react-2.2.0.tgz", + "integrity": "sha512-LMcepvRaS9LYHJGsF0zzmgKCUim/X3N/DQKc4jepAXJ7l8QxJ1PmxJzqplF2Z3FE4PqBAIGyJAQ/w4B5dsqbtQ==", + "license": "MIT", + "peerDependencies": { + "react": ">= 16 || ^19.0.0-rc" + } + }, + "node_modules/@heroui/accordion": { + "version": "2.2.28", + "resolved": "https://registry.npmjs.org/@heroui/accordion/-/accordion-2.2.28.tgz", + "integrity": "sha512-UuZDAMU0q8gTJZ4x11qq2qJs2VF19RaSsgTrpwaPdZamU+X6cUiiAc8xMkFgQF6XsoNvohTzofU2Id4ykAKdAg==", + "license": "MIT", + "dependencies": { + "@heroui/aria-utils": "2.2.28", + "@heroui/divider": "2.2.23", + "@heroui/dom-animation": "2.1.10", + "@heroui/framer-utils": "2.1.27", + "@heroui/react-utils": "2.1.14", + "@heroui/shared-icons": "2.1.10", + "@heroui/shared-utils": "2.1.12", + "@heroui/use-aria-accordion": "2.2.19", + "@react-aria/focus": "3.21.4", + "@react-aria/interactions": "3.27.0", + "@react-stately/tree": "3.9.5", + "@react-types/accordion": "3.0.0-alpha.26", + "@react-types/shared": "3.33.0" + }, + "peerDependencies": { + "@heroui/system": ">=2.4.18", + "@heroui/theme": ">=2.4.24", + "framer-motion": ">=11.5.6 || >=12.0.0-alpha.1", + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/alert": { + "version": "2.2.31", + "resolved": "https://registry.npmjs.org/@heroui/alert/-/alert-2.2.31.tgz", + "integrity": "sha512-stD6kp9PG3kqk6j+0trQEEbvDn9YHCVpsO1h0bYtoo4uxAkCXj6Hkg9B2plTkZU/7V9FW+gQc9tCBjqAUXKREg==", + "license": "MIT", + "dependencies": { + "@heroui/button": "2.2.31", + "@heroui/react-utils": "2.1.14", + "@heroui/shared-icons": "2.1.10", + "@heroui/shared-utils": "2.1.12", + "@react-stately/utils": "3.11.0" + }, + "peerDependencies": { + "@heroui/system": ">=2.4.18", + "@heroui/theme": ">=2.4.24", + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/aria-utils": { + "version": "2.2.28", + "resolved": "https://registry.npmjs.org/@heroui/aria-utils/-/aria-utils-2.2.28.tgz", + "integrity": "sha512-rQxvnits0dmaOMYaQ5hj7GryiESHZ/h/VJVnpOISE4l2PF8PShvUBa8Ad3miFHZdzDQJafFjCvNxo0c6AXJPrw==", + "license": "MIT", + "dependencies": { + "@heroui/system": "2.4.27", + "@react-aria/utils": "3.33.0", + "@react-stately/collections": "3.12.9", + "@react-types/overlays": "3.9.3", + "@react-types/shared": "3.33.0" + }, + "peerDependencies": { + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/autocomplete": { + "version": "2.3.33", + "resolved": "https://registry.npmjs.org/@heroui/autocomplete/-/autocomplete-2.3.33.tgz", + "integrity": "sha512-/vn5gMF0+pH2Uzwd34ovt9TZEuVlvDQgh9z/KCrQky6IHqY27l16dBKAuLDcVz3jQHLCfngMbwLHzCazhJAznA==", + "license": "MIT", + "dependencies": { + "@heroui/aria-utils": "2.2.28", + "@heroui/button": "2.2.31", + "@heroui/form": "2.1.31", + "@heroui/input": "2.4.32", + "@heroui/listbox": "2.3.30", + "@heroui/popover": "2.3.31", + "@heroui/react-utils": "2.1.14", + "@heroui/scroll-shadow": "2.3.19", + "@heroui/shared-icons": "2.1.10", + "@heroui/shared-utils": "2.1.12", + "@heroui/use-safe-layout-effect": "2.1.8", + "@react-aria/combobox": "3.14.2", + "@react-aria/i18n": "3.12.15", + "@react-stately/combobox": "3.12.2", + "@react-types/combobox": "3.13.11", + "@react-types/shared": "3.33.0" + }, + "peerDependencies": { + "@heroui/system": ">=2.4.18", + "@heroui/theme": ">=2.4.24", + "framer-motion": ">=11.5.6 || >=12.0.0-alpha.1", + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/avatar": { + "version": "2.2.25", + "resolved": "https://registry.npmjs.org/@heroui/avatar/-/avatar-2.2.25.tgz", + "integrity": "sha512-P4ExI0th+UlBzBojQ5jBff6C7QPTmkDZwBqCDM+6DMBPKSFyt6hWG7xaOi33g0X41QuArOlWpPOe6aG5iUZAyA==", + "license": "MIT", + "dependencies": { + "@heroui/react-utils": "2.1.14", + "@heroui/shared-utils": "2.1.12", + "@heroui/use-image": "2.1.14", + "@react-aria/focus": "3.21.3", + "@react-aria/interactions": "3.26.0" + }, + "peerDependencies": { + "@heroui/system": ">=2.4.18", + "@heroui/theme": ">=2.4.24", + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/avatar/node_modules/@react-aria/focus": { + "version": "3.21.3", + "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.21.3.tgz", + "integrity": "sha512-FsquWvjSCwC2/sBk4b+OqJyONETUIXQ2vM0YdPAuC+QFQh2DT6TIBo6dOZVSezlhudDla69xFBd6JvCFq1AbUw==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/interactions": "^3.26.0", + "@react-aria/utils": "^3.32.0", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/avatar/node_modules/@react-aria/interactions": { + "version": "3.26.0", + "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.26.0.tgz", + "integrity": "sha512-AAEcHiltjfbmP1i9iaVw34Mb7kbkiHpYdqieWufldh4aplWgsF11YQZOfaCJW4QoR2ML4Zzoa9nfFwLXA52R7Q==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/ssr": "^3.9.10", + "@react-aria/utils": "^3.32.0", + "@react-stately/flags": "^3.1.2", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/badge": { + "version": "2.2.18", + "resolved": "https://registry.npmjs.org/@heroui/badge/-/badge-2.2.18.tgz", + "integrity": "sha512-OfGove8YJ9oDrdugzq05FC15ZKD5nzqe+thPZ+1SY1LZorJQjZvqSD9QnoEH1nG7fu2IdH6pYJy3sZ/b6Vj5Kg==", + "license": "MIT", + "dependencies": { + "@heroui/react-utils": "2.1.14", + "@heroui/shared-utils": "2.1.12" + }, + "peerDependencies": { + "@heroui/system": ">=2.4.18", + "@heroui/theme": ">=2.4.23", + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/breadcrumbs": { + "version": "2.2.24", + "resolved": "https://registry.npmjs.org/@heroui/breadcrumbs/-/breadcrumbs-2.2.24.tgz", + "integrity": "sha512-O4M+FrqmAyBB0kfUjBN8PyuVfMMuMRg8B6dl7U+DxFyzfc3TmgtI9t2rIrnnNKj/EA3s/FEv9iaPcb02W6Fp5A==", + "license": "MIT", + "dependencies": { + "@heroui/react-utils": "2.1.14", + "@heroui/shared-icons": "2.1.10", + "@heroui/shared-utils": "2.1.12", + "@react-aria/breadcrumbs": "3.5.30", + "@react-aria/focus": "3.21.3", + "@react-types/breadcrumbs": "3.7.17" + }, + "peerDependencies": { + "@heroui/system": ">=2.4.18", + "@heroui/theme": ">=2.4.24", + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/breadcrumbs/node_modules/@react-aria/focus": { + "version": "3.21.3", + "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.21.3.tgz", + "integrity": "sha512-FsquWvjSCwC2/sBk4b+OqJyONETUIXQ2vM0YdPAuC+QFQh2DT6TIBo6dOZVSezlhudDla69xFBd6JvCFq1AbUw==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/interactions": "^3.26.0", + "@react-aria/utils": "^3.32.0", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/button": { + "version": "2.2.31", + "resolved": "https://registry.npmjs.org/@heroui/button/-/button-2.2.31.tgz", + "integrity": "sha512-U7zMGTsesEa/2plBNkwRLzhNLQtKIV03u5hbR4Te+sP3MxKZgcjJHH0ZJWeeyHoAszIiE39UYUs+lhF4XzqxzA==", + "license": "MIT", + "dependencies": { + "@heroui/react-utils": "2.1.14", + "@heroui/ripple": "2.2.21", + "@heroui/shared-utils": "2.1.12", + "@heroui/spinner": "2.2.28", + "@heroui/use-aria-button": "2.2.21", + "@react-aria/focus": "3.21.4", + "@react-aria/interactions": "3.27.0", + "@react-types/shared": "3.33.0" + }, + "peerDependencies": { + "@heroui/system": ">=2.4.18", + "@heroui/theme": ">=2.4.24", + "framer-motion": ">=11.5.6 || >=12.0.0-alpha.1", + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/calendar": { + "version": "2.2.31", + "resolved": "https://registry.npmjs.org/@heroui/calendar/-/calendar-2.2.31.tgz", + "integrity": "sha512-7QJWp/FyNmqsrbKaz4GxA8ZAXO8y2HmUzQBAAC2pawBnbuerBI8YOCmLJd9PePt93VFS2zN3R2qlHT1fsP7c4Q==", + "license": "MIT", + "dependencies": { + "@heroui/button": "2.2.31", + "@heroui/dom-animation": "2.1.10", + "@heroui/framer-utils": "2.1.27", + "@heroui/react-utils": "2.1.14", + "@heroui/shared-icons": "2.1.10", + "@heroui/shared-utils": "2.1.12", + "@heroui/use-aria-button": "2.2.21", + "@internationalized/date": "3.11.0", + "@react-aria/calendar": "3.9.4", + "@react-aria/focus": "3.21.4", + "@react-aria/i18n": "3.12.15", + "@react-aria/interactions": "3.27.0", + "@react-aria/visually-hidden": "3.8.30", + "@react-stately/calendar": "3.9.2", + "@react-stately/utils": "3.11.0", + "@react-types/button": "3.15.0", + "@react-types/calendar": "3.8.2", + "@react-types/shared": "3.33.0", + "scroll-into-view-if-needed": "3.0.10" + }, + "peerDependencies": { + "@heroui/system": ">=2.4.18", + "@heroui/theme": ">=2.4.24", + "framer-motion": ">=11.5.6 || >=12.0.0-alpha.1", + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/card": { + "version": "2.2.27", + "resolved": "https://registry.npmjs.org/@heroui/card/-/card-2.2.27.tgz", + "integrity": "sha512-UP9IuKYzGCjwBaocv8eiusOi1SheV6Pn37r05N6Hrqd8DKvs2Ebgye3hGRZ3z3MKRsqFKAyhG+3tdDIjVs3J/Q==", + "license": "MIT", + "dependencies": { + "@heroui/react-utils": "2.1.14", + "@heroui/ripple": "2.2.21", + "@heroui/shared-utils": "2.1.12", + "@heroui/use-aria-button": "2.2.21", + "@react-aria/focus": "3.21.3", + "@react-aria/interactions": "3.26.0", + "@react-types/shared": "3.32.1" + }, + "peerDependencies": { + "@heroui/system": ">=2.4.18", + "@heroui/theme": ">=2.4.24", + "framer-motion": ">=11.5.6 || >=12.0.0-alpha.1", + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/card/node_modules/@react-aria/focus": { + "version": "3.21.3", + "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.21.3.tgz", + "integrity": "sha512-FsquWvjSCwC2/sBk4b+OqJyONETUIXQ2vM0YdPAuC+QFQh2DT6TIBo6dOZVSezlhudDla69xFBd6JvCFq1AbUw==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/interactions": "^3.26.0", + "@react-aria/utils": "^3.32.0", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/card/node_modules/@react-aria/interactions": { + "version": "3.26.0", + "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.26.0.tgz", + "integrity": "sha512-AAEcHiltjfbmP1i9iaVw34Mb7kbkiHpYdqieWufldh4aplWgsF11YQZOfaCJW4QoR2ML4Zzoa9nfFwLXA52R7Q==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/ssr": "^3.9.10", + "@react-aria/utils": "^3.32.0", + "@react-stately/flags": "^3.1.2", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/card/node_modules/@react-types/shared": { + "version": "3.32.1", + "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.32.1.tgz", + "integrity": "sha512-famxyD5emrGGpFuUlgOP6fVW2h/ZaF405G5KDi3zPHzyjAWys/8W6NAVJtNbkCkhedmvL0xOhvt8feGXyXaw5w==", + "license": "Apache-2.0", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/checkbox": { + "version": "2.3.31", + "resolved": "https://registry.npmjs.org/@heroui/checkbox/-/checkbox-2.3.31.tgz", + "integrity": "sha512-aHXe+19rWRooztTaCa95G+c495Dc7M8yKAhSzTKTg/mRccAjIeoo0m7jLmCwSUs6KLup6wHvCp/6bxWFmWpGcQ==", + "license": "MIT", + "dependencies": { + "@heroui/form": "2.1.31", + "@heroui/react-utils": "2.1.14", + "@heroui/shared-utils": "2.1.12", + "@heroui/use-callback-ref": "2.1.8", + "@heroui/use-safe-layout-effect": "2.1.8", + "@react-aria/checkbox": "3.16.4", + "@react-aria/focus": "3.21.4", + "@react-aria/interactions": "3.27.0", + "@react-stately/checkbox": "3.7.4", + "@react-stately/toggle": "3.9.4", + "@react-types/checkbox": "3.10.3", + "@react-types/shared": "3.33.0" + }, + "peerDependencies": { + "@heroui/system": ">=2.4.18", + "@heroui/theme": ">=2.4.24", + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/chip": { + "version": "2.2.24", + "resolved": "https://registry.npmjs.org/@heroui/chip/-/chip-2.2.24.tgz", + "integrity": "sha512-QdJPQroHKGO+ZgZVlnhlhnAwE46Sm23UlHuFiW6cFIRVuARxHo/K+M/KXpjUEAP659EOtMyS1CzIVhDzuqHuSg==", + "license": "MIT", + "dependencies": { + "@heroui/react-utils": "2.1.14", + "@heroui/shared-icons": "2.1.10", + "@heroui/shared-utils": "2.1.12", + "@react-aria/focus": "3.21.3", + "@react-aria/interactions": "3.26.0" + }, + "peerDependencies": { + "@heroui/system": ">=2.4.18", + "@heroui/theme": ">=2.4.24", + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/chip/node_modules/@react-aria/focus": { + "version": "3.21.3", + "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.21.3.tgz", + "integrity": "sha512-FsquWvjSCwC2/sBk4b+OqJyONETUIXQ2vM0YdPAuC+QFQh2DT6TIBo6dOZVSezlhudDla69xFBd6JvCFq1AbUw==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/interactions": "^3.26.0", + "@react-aria/utils": "^3.32.0", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/chip/node_modules/@react-aria/interactions": { + "version": "3.26.0", + "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.26.0.tgz", + "integrity": "sha512-AAEcHiltjfbmP1i9iaVw34Mb7kbkiHpYdqieWufldh4aplWgsF11YQZOfaCJW4QoR2ML4Zzoa9nfFwLXA52R7Q==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/ssr": "^3.9.10", + "@react-aria/utils": "^3.32.0", + "@react-stately/flags": "^3.1.2", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/code": { + "version": "2.2.24", + "resolved": "https://registry.npmjs.org/@heroui/code/-/code-2.2.24.tgz", + "integrity": "sha512-GfVVkhCgnyYP3rp1951dOdM6nQmMlNmKL4t8Vs+tUWDt6AKSrP9bjWQcgl/sIpcRe0/Tm0LrVAg0qkKlhKJQAg==", + "license": "MIT", + "dependencies": { + "@heroui/react-utils": "2.1.14", + "@heroui/shared-utils": "2.1.12", + "@heroui/system-rsc": "2.3.23" + }, + "peerDependencies": { + "@heroui/theme": ">=2.4.24", + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/date-input": { + "version": "2.3.31", + "resolved": "https://registry.npmjs.org/@heroui/date-input/-/date-input-2.3.31.tgz", + "integrity": "sha512-aynmUpLonmGI/026eI47W5303ZKzAn0m6vqt0/dJbTHyQBeL4itKxbND9dlYOjxYKQpSA5SkihsdllJxusPF9Q==", + "license": "MIT", + "dependencies": { + "@heroui/form": "2.1.31", + "@heroui/react-utils": "2.1.14", + "@heroui/shared-utils": "2.1.12", + "@internationalized/date": "3.11.0", + "@react-aria/datepicker": "3.16.0", + "@react-aria/i18n": "3.12.15", + "@react-stately/datepicker": "3.16.0", + "@react-types/datepicker": "3.13.4", + "@react-types/shared": "3.33.0" + }, + "peerDependencies": { + "@heroui/system": ">=2.4.18", + "@heroui/theme": ">=2.4.24", + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/date-picker": { + "version": "2.3.32", + "resolved": "https://registry.npmjs.org/@heroui/date-picker/-/date-picker-2.3.32.tgz", + "integrity": "sha512-SxTVOaQoBv/4ZfeOgbyokOGXhOUn/XnqX/ieG7toZCbU1w5tXwmhA01Q6Yds6naG5qJbigD2lSTj+4ppU9KYQQ==", + "license": "MIT", + "dependencies": { + "@heroui/aria-utils": "2.2.28", + "@heroui/button": "2.2.31", + "@heroui/calendar": "2.2.31", + "@heroui/date-input": "2.3.31", + "@heroui/form": "2.1.31", + "@heroui/popover": "2.3.31", + "@heroui/react-utils": "2.1.14", + "@heroui/shared-icons": "2.1.10", + "@heroui/shared-utils": "2.1.12", + "@internationalized/date": "3.11.0", + "@react-aria/datepicker": "3.16.0", + "@react-aria/i18n": "3.12.15", + "@react-stately/datepicker": "3.16.0", + "@react-stately/utils": "3.11.0", + "@react-types/datepicker": "3.13.4", + "@react-types/shared": "3.33.0" + }, + "peerDependencies": { + "@heroui/system": ">=2.4.18", + "@heroui/theme": ">=2.4.24", + "framer-motion": ">=11.5.6 || >=12.0.0-alpha.1", + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/divider": { + "version": "2.2.23", + "resolved": "https://registry.npmjs.org/@heroui/divider/-/divider-2.2.23.tgz", + "integrity": "sha512-fIBJgljTBXClJW1suoeOctuLtwRLzoNOit6kgMM/m820iyA7xuKyJAaNnDXDln+wE7Pjunu5N0YTQBEn/v8eZg==", + "license": "MIT", + "dependencies": { + "@heroui/react-rsc-utils": "2.1.9", + "@heroui/system-rsc": "2.3.23", + "@react-types/shared": "3.33.0" + }, + "peerDependencies": { + "@heroui/theme": ">=2.4.24", + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/dom-animation": { + "version": "2.1.10", + "resolved": "https://registry.npmjs.org/@heroui/dom-animation/-/dom-animation-2.1.10.tgz", + "integrity": "sha512-dt+0xdVPbORwNvFT5pnqV2ULLlSgOJeqlg/DMo97s9RWeD6rD4VedNY90c8C9meqWqGegQYBQ9ztsfX32mGEPA==", + "license": "MIT", + "peerDependencies": { + "framer-motion": ">=11.5.6 || >=12.0.0-alpha.1" + } + }, + "node_modules/@heroui/drawer": { + "version": "2.2.28", + "resolved": "https://registry.npmjs.org/@heroui/drawer/-/drawer-2.2.28.tgz", + "integrity": "sha512-0yi3mOEpSut36B+TyOMxxQtRtptHYMh6zzpuvf6jmeL6CV5vWqHpHFPhUAqBHW2GTr2LM3HLQUgT8R8V3gpWEA==", + "license": "MIT", + "dependencies": { + "@heroui/framer-utils": "2.1.27", + "@heroui/modal": "2.2.28", + "@heroui/react-utils": "2.1.14", + "@heroui/shared-utils": "2.1.12" + }, + "peerDependencies": { + "@heroui/system": ">=2.4.18", + "@heroui/theme": ">=2.4.24", + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/dropdown": { + "version": "2.3.31", + "resolved": "https://registry.npmjs.org/@heroui/dropdown/-/dropdown-2.3.31.tgz", + "integrity": "sha512-A0QkibLdvMYI0/ht7uhqT0O5WXCF3PJaekYMWNLeYcaqFN1VxhH4gk9pHe/WFz1bAjCdKvVrLxnokBTpOAUIeQ==", + "license": "MIT", + "dependencies": { + "@heroui/aria-utils": "2.2.28", + "@heroui/menu": "2.2.30", + "@heroui/popover": "2.3.31", + "@heroui/react-utils": "2.1.14", + "@heroui/shared-utils": "2.1.12", + "@react-aria/focus": "3.21.4", + "@react-aria/menu": "3.20.0", + "@react-stately/menu": "3.9.10", + "@react-types/menu": "3.10.6" + }, + "peerDependencies": { + "@heroui/system": ">=2.4.18", + "@heroui/theme": ">=2.4.24", + "framer-motion": ">=11.5.6 || >=12.0.0-alpha.1", + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/form": { + "version": "2.1.31", + "resolved": "https://registry.npmjs.org/@heroui/form/-/form-2.1.31.tgz", + "integrity": "sha512-g6Qr4SOEBW++dqcKSKGYH27rqwSj2RGJSigd3kGnVnS/b1pCERUcUcz/F+y3ePtHFzPdCYdco+oaqI0bE47Bpw==", + "license": "MIT", + "dependencies": { + "@heroui/shared-utils": "2.1.12", + "@heroui/system": "2.4.27", + "@heroui/theme": "2.4.26", + "@react-stately/form": "3.2.3", + "@react-types/form": "3.7.17", + "@react-types/shared": "3.33.0" + }, + "peerDependencies": { + "@heroui/system": ">=2.4.18", + "@heroui/theme": ">=2.4.24", + "react": ">=18", + "react-dom": ">=18" + } + }, + "node_modules/@heroui/framer-utils": { + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/@heroui/framer-utils/-/framer-utils-2.1.27.tgz", + "integrity": "sha512-JKFu9xVhw9grtLKNVrCkEA4ZD0fBOOLGs2mYS2C82GnZ1sOdXB8J4L3QeMEF0x2rxnlpXKmFBNb9Nm2P/vo7ww==", + "license": "MIT", + "dependencies": { + "@heroui/system": "2.4.27", + "@heroui/use-measure": "2.1.8" + }, + "peerDependencies": { + "framer-motion": ">=11.5.6 || >=12.0.0-alpha.1", + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/image": { + "version": "2.2.19", + "resolved": "https://registry.npmjs.org/@heroui/image/-/image-2.2.19.tgz", + "integrity": "sha512-XdQ1g0kiHl+Kj9Zj1NL1mbKhmzeN0h27dgfegJS2coGM/yrEavYzg1DWUEyVSzPNKFZS8BDGa9DOpWe0vgggBA==", + "license": "MIT", + "dependencies": { + "@heroui/react-utils": "2.1.14", + "@heroui/shared-utils": "2.1.12", + "@heroui/use-image": "2.1.14" + }, + "peerDependencies": { + "@heroui/system": ">=2.4.18", + "@heroui/theme": ">=2.4.24", + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/input": { + "version": "2.4.32", + "resolved": "https://registry.npmjs.org/@heroui/input/-/input-2.4.32.tgz", + "integrity": "sha512-qx7wUH+IHJU1allWw8cP+BYQfbrOHI9CMOKt9QyyzBGVWlcs7vkhpq6MTjR4DzvGFk+LcN6MK9b+byEaFaP/0g==", + "license": "MIT", + "dependencies": { + "@heroui/form": "2.1.31", + "@heroui/react-utils": "2.1.14", + "@heroui/shared-icons": "2.1.10", + "@heroui/shared-utils": "2.1.12", + "@heroui/use-safe-layout-effect": "2.1.8", + "@react-aria/focus": "3.21.4", + "@react-aria/interactions": "3.27.0", + "@react-aria/textfield": "3.18.4", + "@react-stately/utils": "3.11.0", + "@react-types/shared": "3.33.0", + "@react-types/textfield": "3.12.7", + "react-textarea-autosize": "^8.5.3" + }, + "peerDependencies": { + "@heroui/system": ">=2.4.18", + "@heroui/theme": ">=2.4.24", + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/input-otp": { + "version": "2.1.31", + "resolved": "https://registry.npmjs.org/@heroui/input-otp/-/input-otp-2.1.31.tgz", + "integrity": "sha512-k7Y3WoLau1jTOVRFedqZoYLbswOTspzJBVjZZsq/LGkwI8l4kbbaZ+vyzK6hv0uSdsn/yUjJh6MqM6dxkU7K0w==", + "license": "MIT", + "dependencies": { + "@heroui/form": "2.1.31", + "@heroui/react-utils": "2.1.14", + "@heroui/shared-utils": "2.1.12", + "@heroui/use-form-reset": "2.0.1", + "@react-aria/focus": "3.21.4", + "@react-aria/form": "3.1.4", + "@react-stately/form": "3.2.3", + "@react-stately/utils": "3.11.0", + "@react-types/textfield": "3.12.7", + "input-otp": "1.4.1" + }, + "peerDependencies": { + "@heroui/system": ">=2.4.18", + "@heroui/theme": ">=2.4.24", + "react": ">=18", + "react-dom": ">=18" + } + }, + "node_modules/@heroui/kbd": { + "version": "2.2.25", + "resolved": "https://registry.npmjs.org/@heroui/kbd/-/kbd-2.2.25.tgz", + "integrity": "sha512-N1rHKy4HA0/mMPg5pedaqeQtxVcUxD20fa40VszHcJHICsoS/rA7vFHIIPgREMRCRGjHW2VPFAVhuZ9qsj42fw==", + "license": "MIT", + "dependencies": { + "@heroui/react-utils": "2.1.14", + "@heroui/shared-utils": "2.1.12", + "@heroui/system-rsc": "2.3.23" + }, + "peerDependencies": { + "@heroui/theme": ">=2.4.24", + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/link": { + "version": "2.2.25", + "resolved": "https://registry.npmjs.org/@heroui/link/-/link-2.2.25.tgz", + "integrity": "sha512-6hJpMrmHzmVkhze3523xe9PygCjiOHIu0t9p2LRG/kyWrTGx6LZRiufyIHEwZPVm2xp1Wu39UqPwBIkHoGkrag==", + "license": "MIT", + "dependencies": { + "@heroui/react-utils": "2.1.14", + "@heroui/shared-icons": "2.1.10", + "@heroui/shared-utils": "2.1.12", + "@heroui/use-aria-link": "2.2.22", + "@react-aria/focus": "3.21.3", + "@react-types/link": "3.6.5" + }, + "peerDependencies": { + "@heroui/system": ">=2.4.18", + "@heroui/theme": ">=2.4.24", + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/link/node_modules/@react-aria/focus": { + "version": "3.21.3", + "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.21.3.tgz", + "integrity": "sha512-FsquWvjSCwC2/sBk4b+OqJyONETUIXQ2vM0YdPAuC+QFQh2DT6TIBo6dOZVSezlhudDla69xFBd6JvCFq1AbUw==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/interactions": "^3.26.0", + "@react-aria/utils": "^3.32.0", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/listbox": { + "version": "2.3.30", + "resolved": "https://registry.npmjs.org/@heroui/listbox/-/listbox-2.3.30.tgz", + "integrity": "sha512-XvAMCUWZDOYMStFBusZolfyw0B+2fFCUwI6AyN/JPxG/ueruGrvF4x7TBKb1G2+xm9wRS0mOlSiFj9pUPLik8A==", + "license": "MIT", + "dependencies": { + "@heroui/aria-utils": "2.2.28", + "@heroui/divider": "2.2.23", + "@heroui/react-utils": "2.1.14", + "@heroui/shared-utils": "2.1.12", + "@heroui/use-is-mobile": "2.2.12", + "@react-aria/focus": "3.21.4", + "@react-aria/interactions": "3.27.0", + "@react-aria/listbox": "3.15.2", + "@react-stately/list": "3.13.3", + "@react-types/shared": "3.33.0", + "@tanstack/react-virtual": "3.11.3" + }, + "peerDependencies": { + "@heroui/system": ">=2.4.18", + "@heroui/theme": ">=2.4.24", + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/menu": { + "version": "2.2.30", + "resolved": "https://registry.npmjs.org/@heroui/menu/-/menu-2.2.30.tgz", + "integrity": "sha512-VyNTtmBs9x1kMEYAwhtr1RS6aOsx6RdyhSw+cZWa0vYazfI1/pQW3fyMABJzofNt9kVqKvWpTOGEffa/+kuoEQ==", + "license": "MIT", + "dependencies": { + "@heroui/aria-utils": "2.2.28", + "@heroui/divider": "2.2.23", + "@heroui/react-utils": "2.1.14", + "@heroui/shared-utils": "2.1.12", + "@heroui/use-is-mobile": "2.2.12", + "@react-aria/focus": "3.21.4", + "@react-aria/interactions": "3.27.0", + "@react-aria/menu": "3.20.0", + "@react-stately/tree": "3.9.5", + "@react-types/menu": "3.10.6", + "@react-types/shared": "3.33.0" + }, + "peerDependencies": { + "@heroui/system": ">=2.4.18", + "@heroui/theme": ">=2.4.24", + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/modal": { + "version": "2.2.28", + "resolved": "https://registry.npmjs.org/@heroui/modal/-/modal-2.2.28.tgz", + "integrity": "sha512-qa5C0CV/4+ovI1DdEgXb0Gtml/OyiwNkOIgimFlDGJxkB4jmTMOv7hXWi6Icln73dTPoCa80D8xHoShv9QbQBg==", + "license": "MIT", + "dependencies": { + "@heroui/dom-animation": "2.1.10", + "@heroui/framer-utils": "2.1.27", + "@heroui/react-utils": "2.1.14", + "@heroui/shared-icons": "2.1.10", + "@heroui/shared-utils": "2.1.12", + "@heroui/use-aria-button": "2.2.21", + "@heroui/use-aria-modal-overlay": "2.2.20", + "@heroui/use-disclosure": "2.2.18", + "@heroui/use-draggable": "2.1.19", + "@heroui/use-viewport-size": "2.0.1", + "@react-aria/dialog": "3.5.33", + "@react-aria/focus": "3.21.4", + "@react-aria/overlays": "3.31.1", + "@react-stately/overlays": "3.6.22" + }, + "peerDependencies": { + "@heroui/system": ">=2.4.18", + "@heroui/theme": ">=2.4.24", + "framer-motion": ">=11.5.6 || >=12.0.0-alpha.1", + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/navbar": { + "version": "2.2.29", + "resolved": "https://registry.npmjs.org/@heroui/navbar/-/navbar-2.2.29.tgz", + "integrity": "sha512-+4Pw4AfzAZBZefiB7NhjKQ9We8pzwET/ynFeGdRBUJauAsK+/8sS2KSzvV9M4/TbR+2cpX6y9jzUefa/ApcHvA==", + "license": "MIT", + "dependencies": { + "@heroui/dom-animation": "2.1.10", + "@heroui/framer-utils": "2.1.27", + "@heroui/react-utils": "2.1.14", + "@heroui/shared-utils": "2.1.12", + "@heroui/use-resize": "2.1.8", + "@heroui/use-scroll-position": "2.1.8", + "@react-aria/button": "3.14.4", + "@react-aria/focus": "3.21.4", + "@react-aria/interactions": "3.27.0", + "@react-aria/overlays": "3.31.1", + "@react-stately/toggle": "3.9.4", + "@react-stately/utils": "3.11.0" + }, + "peerDependencies": { + "@heroui/system": ">=2.4.18", + "@heroui/theme": ">=2.4.24", + "framer-motion": ">=11.5.6 || >=12.0.0-alpha.1", + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/number-input": { + "version": "2.0.22", + "resolved": "https://registry.npmjs.org/@heroui/number-input/-/number-input-2.0.22.tgz", + "integrity": "sha512-jVPGU5E7D8mr4wkWJIa6oCsiR5CRRzQVLTn0bevnPeVe1zNr8UJk0eCPZqNy0oqgEqfgm8rotcF4Ehe7Lpkc0A==", + "license": "MIT", + "dependencies": { + "@heroui/button": "2.2.31", + "@heroui/form": "2.1.31", + "@heroui/react-utils": "2.1.14", + "@heroui/shared-icons": "2.1.10", + "@heroui/shared-utils": "2.1.12", + "@heroui/use-safe-layout-effect": "2.1.8", + "@react-aria/focus": "3.21.4", + "@react-aria/i18n": "3.12.15", + "@react-aria/interactions": "3.27.0", + "@react-aria/numberfield": "3.12.4", + "@react-stately/numberfield": "3.10.4", + "@react-types/button": "3.15.0", + "@react-types/numberfield": "3.8.17", + "@react-types/shared": "3.33.0" + }, + "peerDependencies": { + "@heroui/system": ">=2.4.18", + "@heroui/theme": ">=2.4.24", + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/pagination": { + "version": "2.2.26", + "resolved": "https://registry.npmjs.org/@heroui/pagination/-/pagination-2.2.26.tgz", + "integrity": "sha512-Ta70RAMo223BDFw3fAvYew1PauQ+b38Xa0zWnj5mkkrYrLXk7sjomunNtlUFPKkr0B8Dpuu67tp9a8AlmI1z8A==", + "license": "MIT", + "dependencies": { + "@heroui/react-utils": "2.1.14", + "@heroui/shared-icons": "2.1.10", + "@heroui/shared-utils": "2.1.12", + "@heroui/use-intersection-observer": "2.2.14", + "@heroui/use-pagination": "2.2.19", + "@react-aria/focus": "3.21.3", + "@react-aria/i18n": "3.12.14", + "@react-aria/interactions": "3.26.0", + "@react-aria/utils": "3.32.0", + "scroll-into-view-if-needed": "3.0.10" + }, + "peerDependencies": { + "@heroui/system": ">=2.4.18", + "@heroui/theme": ">=2.4.24", + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/pagination/node_modules/@react-aria/focus": { + "version": "3.21.3", + "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.21.3.tgz", + "integrity": "sha512-FsquWvjSCwC2/sBk4b+OqJyONETUIXQ2vM0YdPAuC+QFQh2DT6TIBo6dOZVSezlhudDla69xFBd6JvCFq1AbUw==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/interactions": "^3.26.0", + "@react-aria/utils": "^3.32.0", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/pagination/node_modules/@react-aria/i18n": { + "version": "3.12.14", + "resolved": "https://registry.npmjs.org/@react-aria/i18n/-/i18n-3.12.14.tgz", + "integrity": "sha512-zYvs1FlLamFD49uneX3i5mPHrAsB3OjVpSWApTcPw8ydxOaphQDp/Q1aqrbcxlrQCcxZdXWHuvLlbkNR4+8jzw==", + "license": "Apache-2.0", + "dependencies": { + "@internationalized/date": "^3.10.1", + "@internationalized/message": "^3.1.8", + "@internationalized/number": "^3.6.5", + "@internationalized/string": "^3.2.7", + "@react-aria/ssr": "^3.9.10", + "@react-aria/utils": "^3.32.0", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/pagination/node_modules/@react-aria/interactions": { + "version": "3.26.0", + "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.26.0.tgz", + "integrity": "sha512-AAEcHiltjfbmP1i9iaVw34Mb7kbkiHpYdqieWufldh4aplWgsF11YQZOfaCJW4QoR2ML4Zzoa9nfFwLXA52R7Q==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/ssr": "^3.9.10", + "@react-aria/utils": "^3.32.0", + "@react-stately/flags": "^3.1.2", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/pagination/node_modules/@react-aria/utils": { + "version": "3.32.0", + "resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.32.0.tgz", + "integrity": "sha512-/7Rud06+HVBIlTwmwmJa2W8xVtgxgzm0+kLbuFooZRzKDON6hhozS1dOMR/YLMxyJOaYOTpImcP4vRR9gL1hEg==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/ssr": "^3.9.10", + "@react-stately/flags": "^3.1.2", + "@react-stately/utils": "^3.11.0", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/popover": { + "version": "2.3.31", + "resolved": "https://registry.npmjs.org/@heroui/popover/-/popover-2.3.31.tgz", + "integrity": "sha512-nidEz1NwNAxJKMLbM9Yirtvj0ZAGgWdE1jojj8crQ52DB1bwDZ/dGjHPwTXYIepJOC2TvC/K/ZIT6h4XAGdDaQ==", + "license": "MIT", + "dependencies": { + "@heroui/aria-utils": "2.2.28", + "@heroui/button": "2.2.31", + "@heroui/dom-animation": "2.1.10", + "@heroui/framer-utils": "2.1.27", + "@heroui/react-utils": "2.1.14", + "@heroui/shared-utils": "2.1.12", + "@heroui/use-aria-button": "2.2.21", + "@heroui/use-aria-overlay": "2.0.5", + "@heroui/use-safe-layout-effect": "2.1.8", + "@react-aria/dialog": "3.5.33", + "@react-aria/focus": "3.21.4", + "@react-aria/overlays": "3.31.1", + "@react-stately/overlays": "3.6.22", + "@react-types/overlays": "3.9.3" + }, + "peerDependencies": { + "@heroui/system": ">=2.4.18", + "@heroui/theme": ">=2.4.24", + "framer-motion": ">=11.5.6 || >=12.0.0-alpha.1", + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/progress": { + "version": "2.2.24", + "resolved": "https://registry.npmjs.org/@heroui/progress/-/progress-2.2.24.tgz", + "integrity": "sha512-1wGF1tSBx35//7+15dw06j1AB7+FhJiGYIH8hBefDSRD0U16htwXVxoVBk6v4Vd/yfpvVQTktA5fiT+Sl4XQlQ==", + "license": "MIT", + "dependencies": { + "@heroui/react-utils": "2.1.14", + "@heroui/shared-utils": "2.1.12", + "@heroui/use-is-mounted": "2.1.8", + "@react-aria/progress": "3.4.28", + "@react-types/progress": "3.5.16" + }, + "peerDependencies": { + "@heroui/system": ">=2.4.18", + "@heroui/theme": ">=2.4.24", + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/radio": { + "version": "2.3.31", + "resolved": "https://registry.npmjs.org/@heroui/radio/-/radio-2.3.31.tgz", + "integrity": "sha512-isOk1/1Ecjo9+Dz9F0ptobGjcg8GK7qydo8jOvBno+Kz6ryNNSyh44Rfw/25K1O4tpYce88rfrSzOOwJ19ZrxA==", + "license": "MIT", + "dependencies": { + "@heroui/form": "2.1.31", + "@heroui/react-utils": "2.1.14", + "@heroui/shared-utils": "2.1.12", + "@react-aria/focus": "3.21.4", + "@react-aria/interactions": "3.27.0", + "@react-aria/radio": "3.12.4", + "@react-aria/visually-hidden": "3.8.30", + "@react-stately/radio": "3.11.4", + "@react-types/radio": "3.9.3", + "@react-types/shared": "3.33.0" + }, + "peerDependencies": { + "@heroui/system": ">=2.4.18", + "@heroui/theme": ">=2.4.24", + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/react": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/@heroui/react/-/react-2.8.9.tgz", + "integrity": "sha512-MJGf4POldWumslFPE2ifA6HqaMh0b0FiKcaly2SraZ6mmYrzPPMB1ppq+njF8sBT3hrM0UNqMBw7AWrrNMuD9g==", + "license": "MIT", + "dependencies": { + "@heroui/accordion": "2.2.28", + "@heroui/alert": "2.2.31", + "@heroui/autocomplete": "2.3.33", + "@heroui/avatar": "2.2.25", + "@heroui/badge": "2.2.18", + "@heroui/breadcrumbs": "2.2.24", + "@heroui/button": "2.2.31", + "@heroui/calendar": "2.2.31", + "@heroui/card": "2.2.27", + "@heroui/checkbox": "2.3.31", + "@heroui/chip": "2.2.24", + "@heroui/code": "2.2.24", + "@heroui/date-input": "2.3.31", + "@heroui/date-picker": "2.3.32", + "@heroui/divider": "2.2.23", + "@heroui/drawer": "2.2.28", + "@heroui/dropdown": "2.3.31", + "@heroui/form": "2.1.31", + "@heroui/framer-utils": "2.1.27", + "@heroui/image": "2.2.19", + "@heroui/input": "2.4.32", + "@heroui/input-otp": "2.1.31", + "@heroui/kbd": "2.2.25", + "@heroui/link": "2.2.25", + "@heroui/listbox": "2.3.30", + "@heroui/menu": "2.2.30", + "@heroui/modal": "2.2.28", + "@heroui/navbar": "2.2.29", + "@heroui/number-input": "2.0.22", + "@heroui/pagination": "2.2.26", + "@heroui/popover": "2.3.31", + "@heroui/progress": "2.2.24", + "@heroui/radio": "2.3.31", + "@heroui/ripple": "2.2.21", + "@heroui/scroll-shadow": "2.3.19", + "@heroui/select": "2.4.32", + "@heroui/skeleton": "2.2.18", + "@heroui/slider": "2.4.28", + "@heroui/snippet": "2.2.32", + "@heroui/spacer": "2.2.24", + "@heroui/spinner": "2.2.28", + "@heroui/switch": "2.2.26", + "@heroui/system": "2.4.27", + "@heroui/table": "2.2.31", + "@heroui/tabs": "2.2.28", + "@heroui/theme": "2.4.26", + "@heroui/toast": "2.0.21", + "@heroui/tooltip": "2.2.28", + "@heroui/user": "2.2.25", + "@react-aria/visually-hidden": "3.8.30" + }, + "peerDependencies": { + "framer-motion": ">=11.5.6 || >=12.0.0-alpha.1", + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/react-rsc-utils": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@heroui/react-rsc-utils/-/react-rsc-utils-2.1.9.tgz", + "integrity": "sha512-e77OEjNCmQxE9/pnLDDb93qWkX58/CcgIqdNAczT/zUP+a48NxGq2A2WRimvc1uviwaNL2StriE2DmyZPyYW7Q==", + "license": "MIT", + "peerDependencies": { + "react": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/react-utils": { + "version": "2.1.14", + "resolved": "https://registry.npmjs.org/@heroui/react-utils/-/react-utils-2.1.14.tgz", + "integrity": "sha512-hhKklYKy9sRH52C9A8P0jWQ79W4MkIvOnKBIuxEMHhigjfracy0o0lMnAUdEsJni4oZKVJYqNGdQl+UVgcmeDA==", + "license": "MIT", + "dependencies": { + "@heroui/react-rsc-utils": "2.1.9", + "@heroui/shared-utils": "2.1.12" + }, + "peerDependencies": { + "react": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/ripple": { + "version": "2.2.21", + "resolved": "https://registry.npmjs.org/@heroui/ripple/-/ripple-2.2.21.tgz", + "integrity": "sha512-wairSq9LnhbIqTCJmUlJAQURQ1wcRK/L8pjg2s3R/XnvZlPXHy4ZzfphiwIlTI21z/f6tH3arxv/g1uXd1RY0g==", + "license": "MIT", + "dependencies": { + "@heroui/dom-animation": "2.1.10", + "@heroui/shared-utils": "2.1.12" + }, + "peerDependencies": { + "@heroui/system": ">=2.4.18", + "@heroui/theme": ">=2.4.23", + "framer-motion": ">=11.5.6 || >=12.0.0-alpha.1", + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/scroll-shadow": { + "version": "2.3.19", + "resolved": "https://registry.npmjs.org/@heroui/scroll-shadow/-/scroll-shadow-2.3.19.tgz", + "integrity": "sha512-y5mdBlhiITVrFnQTDqEphYj7p5pHqoFSFtVuRRvl9wUec2lMxEpD85uMGsfL8OgQTKIAqGh2s6M360+VJm7ajQ==", + "license": "MIT", + "dependencies": { + "@heroui/react-utils": "2.1.14", + "@heroui/shared-utils": "2.1.12", + "@heroui/use-data-scroll-overflow": "2.2.13" + }, + "peerDependencies": { + "@heroui/system": ">=2.4.18", + "@heroui/theme": ">=2.4.23", + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/select": { + "version": "2.4.32", + "resolved": "https://registry.npmjs.org/@heroui/select/-/select-2.4.32.tgz", + "integrity": "sha512-7McNsWX/tgWUaRlYhE2K9XN67xFdAF8XB4UPhvI+8osxUGsHGkL0ca+OrQyy6Iv/Jf+1hRvANJ40MYktjjb1fQ==", + "license": "MIT", + "dependencies": { + "@heroui/aria-utils": "2.2.28", + "@heroui/form": "2.1.31", + "@heroui/listbox": "2.3.30", + "@heroui/popover": "2.3.31", + "@heroui/react-utils": "2.1.14", + "@heroui/scroll-shadow": "2.3.19", + "@heroui/shared-icons": "2.1.10", + "@heroui/shared-utils": "2.1.12", + "@heroui/spinner": "2.2.28", + "@heroui/use-aria-button": "2.2.21", + "@heroui/use-aria-multiselect": "2.4.20", + "@heroui/use-form-reset": "2.0.1", + "@heroui/use-safe-layout-effect": "2.1.8", + "@react-aria/focus": "3.21.4", + "@react-aria/form": "3.1.4", + "@react-aria/interactions": "3.27.0", + "@react-aria/overlays": "3.31.1", + "@react-aria/visually-hidden": "3.8.30", + "@react-types/shared": "3.33.0" + }, + "peerDependencies": { + "@heroui/system": ">=2.4.18", + "@heroui/theme": ">=2.4.24", + "framer-motion": ">=11.5.6 || >=12.0.0-alpha.1", + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/shared-icons": { + "version": "2.1.10", + "resolved": "https://registry.npmjs.org/@heroui/shared-icons/-/shared-icons-2.1.10.tgz", + "integrity": "sha512-ePo60GjEpM0SEyZBGOeySsLueNDCqLsVL79Fq+5BphzlrBAcaKY7kUp74964ImtkXvknTxAWzuuTr3kCRqj6jg==", + "license": "MIT", + "peerDependencies": { + "react": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/shared-utils": { + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/@heroui/shared-utils/-/shared-utils-2.1.12.tgz", + "integrity": "sha512-0iCnxVAkIPtrHQo26Qa5g0UTqMTpugTbClNOrEPsrQuyRAq7Syux998cPwGlneTfB5E5xcU3LiEdA9GUyeK2cQ==", + "hasInstallScript": true, + "license": "MIT" + }, + "node_modules/@heroui/skeleton": { + "version": "2.2.18", + "resolved": "https://registry.npmjs.org/@heroui/skeleton/-/skeleton-2.2.18.tgz", + "integrity": "sha512-7AjU5kjk9rqrKP9mWQiAVj0dow4/vbK5/ejh4jqdb3DZm7bM2+DGzfnQPiS0c2eWR606CgOuuoImpwDS82HJtA==", + "license": "MIT", + "dependencies": { + "@heroui/shared-utils": "2.1.12" + }, + "peerDependencies": { + "@heroui/system": ">=2.4.18", + "@heroui/theme": ">=2.4.23", + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/slider": { + "version": "2.4.28", + "resolved": "https://registry.npmjs.org/@heroui/slider/-/slider-2.4.28.tgz", + "integrity": "sha512-bePPfQqk6fBF/8AhCEIeCnf5yqbIgX/elFaFIdwi6+VxHGEY7Hlw6aJFbIJuXOZBQi8GazSiJz0BAyzZ8uhUJA==", + "license": "MIT", + "dependencies": { + "@heroui/react-utils": "2.1.14", + "@heroui/shared-utils": "2.1.12", + "@heroui/tooltip": "2.2.28", + "@react-aria/focus": "3.21.4", + "@react-aria/i18n": "3.12.15", + "@react-aria/interactions": "3.27.0", + "@react-aria/slider": "3.8.4", + "@react-aria/visually-hidden": "3.8.30", + "@react-stately/slider": "3.7.4" + }, + "peerDependencies": { + "@heroui/system": ">=2.4.18", + "@heroui/theme": ">=2.4.24", + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/snippet": { + "version": "2.2.32", + "resolved": "https://registry.npmjs.org/@heroui/snippet/-/snippet-2.2.32.tgz", + "integrity": "sha512-fTVFIo5wp9jYLjj5z+F9hjGejV/nixMBL9aC3qnlLdB95yCAimy+vt8m06/oG6EUzkTe5nohjcgbkoyqk5DrTg==", + "license": "MIT", + "dependencies": { + "@heroui/button": "2.2.31", + "@heroui/react-utils": "2.1.14", + "@heroui/shared-icons": "2.1.10", + "@heroui/shared-utils": "2.1.12", + "@heroui/tooltip": "2.2.28", + "@heroui/use-clipboard": "2.1.9", + "@react-aria/focus": "3.21.4" + }, + "peerDependencies": { + "@heroui/system": ">=2.4.18", + "@heroui/theme": ">=2.4.24", + "framer-motion": ">=11.5.6 || >=12.0.0-alpha.1", + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/spacer": { + "version": "2.2.24", + "resolved": "https://registry.npmjs.org/@heroui/spacer/-/spacer-2.2.24.tgz", + "integrity": "sha512-eA7U3xiIAdFDRjQqcUHRMCGr1nWyqZdCcFGH/ScV6Cr9u6PbiraJChvWsNdsNJCGLAGQB8Nl85B1o5MCLBE/nA==", + "license": "MIT", + "dependencies": { + "@heroui/react-utils": "2.1.14", + "@heroui/shared-utils": "2.1.12", + "@heroui/system-rsc": "2.3.23" + }, + "peerDependencies": { + "@heroui/theme": ">=2.4.24", + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/spinner": { + "version": "2.2.28", + "resolved": "https://registry.npmjs.org/@heroui/spinner/-/spinner-2.2.28.tgz", + "integrity": "sha512-oPDtcOPQ6/SYo0EkMU0nmMH0BIPu1DUwCXP+UzoDkflDz4vegz/vC1gAk916k+94gY3+blWdW/CMAigPZG6Ymw==", + "license": "MIT", + "dependencies": { + "@heroui/shared-utils": "2.1.12", + "@heroui/system": "2.4.27", + "@heroui/system-rsc": "2.3.23" + }, + "peerDependencies": { + "@heroui/theme": ">=2.4.24", + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/switch": { + "version": "2.2.26", + "resolved": "https://registry.npmjs.org/@heroui/switch/-/switch-2.2.26.tgz", + "integrity": "sha512-c/FCzromB+ww8AObgA0H//jOrhxyn0MllWVeEwMXac7O6z/N4B+fJ8dLCu/vu1zchySFLuDq/PaETEMJ7hKW4A==", + "license": "MIT", + "dependencies": { + "@heroui/react-utils": "2.1.14", + "@heroui/shared-utils": "2.1.12", + "@heroui/use-safe-layout-effect": "2.1.8", + "@react-aria/focus": "3.21.3", + "@react-aria/interactions": "3.26.0", + "@react-aria/switch": "3.7.9", + "@react-aria/visually-hidden": "3.8.29", + "@react-stately/toggle": "3.9.3" + }, + "peerDependencies": { + "@heroui/system": ">=2.4.18", + "@heroui/theme": ">=2.4.24", + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/switch/node_modules/@react-aria/focus": { + "version": "3.21.3", + "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.21.3.tgz", + "integrity": "sha512-FsquWvjSCwC2/sBk4b+OqJyONETUIXQ2vM0YdPAuC+QFQh2DT6TIBo6dOZVSezlhudDla69xFBd6JvCFq1AbUw==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/interactions": "^3.26.0", + "@react-aria/utils": "^3.32.0", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/switch/node_modules/@react-aria/interactions": { + "version": "3.26.0", + "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.26.0.tgz", + "integrity": "sha512-AAEcHiltjfbmP1i9iaVw34Mb7kbkiHpYdqieWufldh4aplWgsF11YQZOfaCJW4QoR2ML4Zzoa9nfFwLXA52R7Q==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/ssr": "^3.9.10", + "@react-aria/utils": "^3.32.0", + "@react-stately/flags": "^3.1.2", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/switch/node_modules/@react-aria/visually-hidden": { + "version": "3.8.29", + "resolved": "https://registry.npmjs.org/@react-aria/visually-hidden/-/visually-hidden-3.8.29.tgz", + "integrity": "sha512-1joCP+MHBLd+YA6Gb08nMFfDBhOF0Kh1gR1SA8zoxEB5RMfQEEkufIB8k0GGwvHGSCK3gFyO8UAVsD0+rRYEyg==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/interactions": "^3.26.0", + "@react-aria/utils": "^3.32.0", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/switch/node_modules/@react-stately/toggle": { + "version": "3.9.3", + "resolved": "https://registry.npmjs.org/@react-stately/toggle/-/toggle-3.9.3.tgz", + "integrity": "sha512-G6aA/aTnid/6dQ9dxNEd7/JqzRmVkVYYpOAP+l02hepiuSmFwLu4nE98i4YFBQqFZ5b4l01gMrS90JGL7HrNmw==", + "license": "Apache-2.0", + "dependencies": { + "@react-stately/utils": "^3.11.0", + "@react-types/checkbox": "^3.10.2", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/system": { + "version": "2.4.27", + "resolved": "https://registry.npmjs.org/@heroui/system/-/system-2.4.27.tgz", + "integrity": "sha512-rluLAuf2v+RthouPuVf0dbC8e8IvatmOtnaG+kxrtAKGSOJoe1HSwR6rEf1sJAMPyvE0GyBUHw3BneLUCUqyjg==", + "license": "MIT", + "dependencies": { + "@heroui/react-utils": "2.1.14", + "@heroui/system-rsc": "2.3.23", + "@react-aria/i18n": "3.12.15", + "@react-aria/overlays": "3.31.1", + "@react-aria/utils": "3.33.0" + }, + "peerDependencies": { + "framer-motion": ">=11.5.6 || >=12.0.0-alpha.1", + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/system-rsc": { + "version": "2.3.23", + "resolved": "https://registry.npmjs.org/@heroui/system-rsc/-/system-rsc-2.3.23.tgz", + "integrity": "sha512-LGfB9FZfKry8zYBi0DCV5A+C4jlfG1DCptGQKBFaNhRrxHQ89pmGhpjl7XlNqAC2oxEIPOh50gQ0U8dVrA54SQ==", + "license": "MIT", + "dependencies": { + "@react-types/shared": "3.33.0" + }, + "peerDependencies": { + "@heroui/theme": ">=2.4.24", + "react": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/table": { + "version": "2.2.31", + "resolved": "https://registry.npmjs.org/@heroui/table/-/table-2.2.31.tgz", + "integrity": "sha512-Sjo5pbpR++V0oQVKGRozL1l52xMTylojTntLhGIg1B4M7EqyM514vmyuRm/kHYQKR7gH5G0+J/R8JXJEO5avhQ==", + "license": "MIT", + "dependencies": { + "@heroui/checkbox": "2.3.31", + "@heroui/react-utils": "2.1.14", + "@heroui/shared-icons": "2.1.10", + "@heroui/shared-utils": "2.1.12", + "@react-aria/focus": "3.21.4", + "@react-aria/interactions": "3.27.0", + "@react-aria/table": "3.17.10", + "@react-aria/visually-hidden": "3.8.30", + "@react-stately/table": "3.15.3", + "@react-stately/virtualizer": "4.4.5", + "@react-types/grid": "3.3.7", + "@react-types/table": "3.13.5", + "@tanstack/react-virtual": "3.11.3" + }, + "peerDependencies": { + "@heroui/system": ">=2.4.18", + "@heroui/theme": ">=2.4.24", + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/tabs": { + "version": "2.2.28", + "resolved": "https://registry.npmjs.org/@heroui/tabs/-/tabs-2.2.28.tgz", + "integrity": "sha512-SzcmjUL7lYphbWhJQVWkLB8OcbCrBZXAf9kGqhIOfVt75g3AFhwIL453ij4Ly7q/6GlgHixsaVCaBPgySo98lg==", + "license": "MIT", + "dependencies": { + "@heroui/aria-utils": "2.2.28", + "@heroui/react-utils": "2.1.14", + "@heroui/shared-utils": "2.1.12", + "@heroui/use-is-mounted": "2.1.8", + "@react-aria/focus": "3.21.4", + "@react-aria/interactions": "3.27.0", + "@react-aria/tabs": "3.11.0", + "@react-stately/tabs": "3.8.8", + "@react-types/shared": "3.33.0", + "scroll-into-view-if-needed": "3.0.10" + }, + "peerDependencies": { + "@heroui/system": ">=2.4.18", + "@heroui/theme": ">=2.4.24", + "framer-motion": ">=11.5.6 || >=12.0.0-alpha.1", + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/theme": { + "version": "2.4.26", + "resolved": "https://registry.npmjs.org/@heroui/theme/-/theme-2.4.26.tgz", + "integrity": "sha512-TYatChq7YyGDcPJytgOMqQwK72qWYb+vIa7mLmX3Cu9+JzFs2VSHu2QqzdhnOHoK0uJr8giDMy0gvJEDuu31vw==", + "license": "MIT", + "dependencies": { + "@heroui/shared-utils": "2.1.12", + "color": "^4.2.3", + "color2k": "^2.0.3", + "deepmerge": "4.3.1", + "tailwind-merge": "3.4.0", + "tailwind-variants": "3.2.2" + }, + "peerDependencies": { + "tailwindcss": ">=4.0.0" + } + }, + "node_modules/@heroui/theme/node_modules/tailwind-merge": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.4.0.tgz", + "integrity": "sha512-uSaO4gnW+b3Y2aWoWfFpX62vn2sR3skfhbjsEnaBI81WD1wBLlHZe5sWf0AqjksNdYTbGBEd0UasQMT3SNV15g==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, + "node_modules/@heroui/toast": { + "version": "2.0.21", + "resolved": "https://registry.npmjs.org/@heroui/toast/-/toast-2.0.21.tgz", + "integrity": "sha512-HC2GPzfCEqgvNWz/P2DRQRgVmcAOz3dUsJMDsL3JKT/MRELWXEVtB+lFhJZyLO3Ir7qi40/aXR/bYTfdACqBFg==", + "license": "MIT", + "dependencies": { + "@heroui/react-utils": "2.1.14", + "@heroui/shared-icons": "2.1.10", + "@heroui/shared-utils": "2.1.12", + "@heroui/spinner": "2.2.28", + "@heroui/use-is-mobile": "2.2.12", + "@react-aria/interactions": "3.27.0", + "@react-aria/toast": "3.0.10", + "@react-stately/toast": "3.1.3" + }, + "peerDependencies": { + "@heroui/system": ">=2.4.18", + "@heroui/theme": ">=2.4.24", + "framer-motion": ">=11.5.6 || >=12.0.0-alpha.1", + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/tooltip": { + "version": "2.2.28", + "resolved": "https://registry.npmjs.org/@heroui/tooltip/-/tooltip-2.2.28.tgz", + "integrity": "sha512-u/+HE0VsOpru1PKdkbY5MygGe87f+WOBhpBhdwovK1HpaAKf2dRCdQIuAqCyZGXhK6TUFajsJo05Xrgjtppg/A==", + "license": "MIT", + "dependencies": { + "@heroui/aria-utils": "2.2.28", + "@heroui/dom-animation": "2.1.10", + "@heroui/framer-utils": "2.1.27", + "@heroui/react-utils": "2.1.14", + "@heroui/shared-utils": "2.1.12", + "@heroui/use-aria-overlay": "2.0.5", + "@heroui/use-safe-layout-effect": "2.1.8", + "@react-aria/overlays": "3.31.1", + "@react-aria/tooltip": "3.9.1", + "@react-stately/tooltip": "3.5.10", + "@react-types/overlays": "3.9.3", + "@react-types/tooltip": "3.5.1" + }, + "peerDependencies": { + "@heroui/system": ">=2.4.18", + "@heroui/theme": ">=2.4.24", + "framer-motion": ">=11.5.6 || >=12.0.0-alpha.1", + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/use-aria-accordion": { + "version": "2.2.19", + "resolved": "https://registry.npmjs.org/@heroui/use-aria-accordion/-/use-aria-accordion-2.2.19.tgz", + "integrity": "sha512-4HGY2zr+MIzRtIO9epFQGeU7VeGqhCotxxXzscfwxLfEeHBJwQvMAsu7yrUQ/uyMGvSiohHlJRgIsuT1xzxH1Q==", + "license": "MIT", + "dependencies": { + "@react-aria/button": "3.14.3", + "@react-aria/focus": "3.21.3", + "@react-aria/selection": "3.27.0", + "@react-stately/tree": "3.9.4", + "@react-types/accordion": "3.0.0-alpha.26", + "@react-types/shared": "3.32.1" + }, + "peerDependencies": { + "react": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/use-aria-accordion/node_modules/@react-aria/button": { + "version": "3.14.3", + "resolved": "https://registry.npmjs.org/@react-aria/button/-/button-3.14.3.tgz", + "integrity": "sha512-iJTuEECs9im7TwrCRZ0dvuwp8Gao0+I1IuYs1LQvJQgKLpgRH2/6jAiqb2bdAcoAjdbaMs7Xe0xUwURpVNkEyA==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/interactions": "^3.26.0", + "@react-aria/toolbar": "3.0.0-beta.22", + "@react-aria/utils": "^3.32.0", + "@react-stately/toggle": "^3.9.3", + "@react-types/button": "^3.14.1", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/use-aria-accordion/node_modules/@react-aria/focus": { + "version": "3.21.3", + "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.21.3.tgz", + "integrity": "sha512-FsquWvjSCwC2/sBk4b+OqJyONETUIXQ2vM0YdPAuC+QFQh2DT6TIBo6dOZVSezlhudDla69xFBd6JvCFq1AbUw==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/interactions": "^3.26.0", + "@react-aria/utils": "^3.32.0", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/use-aria-accordion/node_modules/@react-aria/toolbar": { + "version": "3.0.0-beta.22", + "resolved": "https://registry.npmjs.org/@react-aria/toolbar/-/toolbar-3.0.0-beta.22.tgz", + "integrity": "sha512-Q1gOj6N4vzvpGrIoNAxpUudEQP82UgQACENH/bcH8FnEMbSP7DHvVfDhj7GTU6ldMXO2cjqLhiidoUK53gkCiA==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/focus": "^3.21.3", + "@react-aria/i18n": "^3.12.14", + "@react-aria/utils": "^3.32.0", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/use-aria-accordion/node_modules/@react-stately/tree": { + "version": "3.9.4", + "resolved": "https://registry.npmjs.org/@react-stately/tree/-/tree-3.9.4.tgz", + "integrity": "sha512-Re1fdEiR0hHPcEda+7ecw+52lgGfFW0MAEDzFg9I6J/t8STQSP+1YC0VVVkv2xRrkLbKLPqggNKgmD8nggecnw==", + "license": "Apache-2.0", + "dependencies": { + "@react-stately/collections": "^3.12.8", + "@react-stately/selection": "^3.20.7", + "@react-stately/utils": "^3.11.0", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/use-aria-accordion/node_modules/@react-types/shared": { + "version": "3.32.1", + "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.32.1.tgz", + "integrity": "sha512-famxyD5emrGGpFuUlgOP6fVW2h/ZaF405G5KDi3zPHzyjAWys/8W6NAVJtNbkCkhedmvL0xOhvt8feGXyXaw5w==", + "license": "Apache-2.0", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/use-aria-button": { + "version": "2.2.21", + "resolved": "https://registry.npmjs.org/@heroui/use-aria-button/-/use-aria-button-2.2.21.tgz", + "integrity": "sha512-8Lhjt1xoDpjhqvEbFC21NEgU89p7Z+MAzrDyoF1eYUn/w4ahhBgcQStP6WicLfx50tOE10WDpPBq72tah/O+ww==", + "license": "MIT", + "dependencies": { + "@react-aria/focus": "3.21.3", + "@react-aria/interactions": "3.26.0", + "@react-aria/utils": "3.32.0", + "@react-types/button": "3.14.1", + "@react-types/shared": "3.32.1" + }, + "peerDependencies": { + "react": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/use-aria-button/node_modules/@react-aria/focus": { + "version": "3.21.3", + "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.21.3.tgz", + "integrity": "sha512-FsquWvjSCwC2/sBk4b+OqJyONETUIXQ2vM0YdPAuC+QFQh2DT6TIBo6dOZVSezlhudDla69xFBd6JvCFq1AbUw==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/interactions": "^3.26.0", + "@react-aria/utils": "^3.32.0", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/use-aria-button/node_modules/@react-aria/interactions": { + "version": "3.26.0", + "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.26.0.tgz", + "integrity": "sha512-AAEcHiltjfbmP1i9iaVw34Mb7kbkiHpYdqieWufldh4aplWgsF11YQZOfaCJW4QoR2ML4Zzoa9nfFwLXA52R7Q==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/ssr": "^3.9.10", + "@react-aria/utils": "^3.32.0", + "@react-stately/flags": "^3.1.2", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/use-aria-button/node_modules/@react-aria/utils": { + "version": "3.32.0", + "resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.32.0.tgz", + "integrity": "sha512-/7Rud06+HVBIlTwmwmJa2W8xVtgxgzm0+kLbuFooZRzKDON6hhozS1dOMR/YLMxyJOaYOTpImcP4vRR9gL1hEg==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/ssr": "^3.9.10", + "@react-stately/flags": "^3.1.2", + "@react-stately/utils": "^3.11.0", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/use-aria-button/node_modules/@react-types/button": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/@react-types/button/-/button-3.14.1.tgz", + "integrity": "sha512-D8C4IEwKB7zEtiWYVJ3WE/5HDcWlze9mLWQ5hfsBfpePyWCgO3bT/+wjb/7pJvcAocrkXo90QrMm85LcpBtrpg==", + "license": "Apache-2.0", + "dependencies": { + "@react-types/shared": "^3.32.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/use-aria-button/node_modules/@react-types/shared": { + "version": "3.32.1", + "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.32.1.tgz", + "integrity": "sha512-famxyD5emrGGpFuUlgOP6fVW2h/ZaF405G5KDi3zPHzyjAWys/8W6NAVJtNbkCkhedmvL0xOhvt8feGXyXaw5w==", + "license": "Apache-2.0", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/use-aria-link": { + "version": "2.2.22", + "resolved": "https://registry.npmjs.org/@heroui/use-aria-link/-/use-aria-link-2.2.22.tgz", + "integrity": "sha512-T7wESiV9IBqe5MILMZ1pL+GIWxyPVj7ag/KUhZUH3v/dm94m+f2Ua7rXxzI+hj2H51s189YP+Eb1PagHMDrfPg==", + "license": "MIT", + "dependencies": { + "@react-aria/focus": "3.21.3", + "@react-aria/interactions": "3.26.0", + "@react-aria/utils": "3.32.0", + "@react-types/link": "3.6.5", + "@react-types/shared": "3.32.1" + }, + "peerDependencies": { + "react": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/use-aria-link/node_modules/@react-aria/focus": { + "version": "3.21.3", + "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.21.3.tgz", + "integrity": "sha512-FsquWvjSCwC2/sBk4b+OqJyONETUIXQ2vM0YdPAuC+QFQh2DT6TIBo6dOZVSezlhudDla69xFBd6JvCFq1AbUw==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/interactions": "^3.26.0", + "@react-aria/utils": "^3.32.0", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/use-aria-link/node_modules/@react-aria/interactions": { + "version": "3.26.0", + "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.26.0.tgz", + "integrity": "sha512-AAEcHiltjfbmP1i9iaVw34Mb7kbkiHpYdqieWufldh4aplWgsF11YQZOfaCJW4QoR2ML4Zzoa9nfFwLXA52R7Q==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/ssr": "^3.9.10", + "@react-aria/utils": "^3.32.0", + "@react-stately/flags": "^3.1.2", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/use-aria-link/node_modules/@react-aria/utils": { + "version": "3.32.0", + "resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.32.0.tgz", + "integrity": "sha512-/7Rud06+HVBIlTwmwmJa2W8xVtgxgzm0+kLbuFooZRzKDON6hhozS1dOMR/YLMxyJOaYOTpImcP4vRR9gL1hEg==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/ssr": "^3.9.10", + "@react-stately/flags": "^3.1.2", + "@react-stately/utils": "^3.11.0", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/use-aria-link/node_modules/@react-types/shared": { + "version": "3.32.1", + "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.32.1.tgz", + "integrity": "sha512-famxyD5emrGGpFuUlgOP6fVW2h/ZaF405G5KDi3zPHzyjAWys/8W6NAVJtNbkCkhedmvL0xOhvt8feGXyXaw5w==", + "license": "Apache-2.0", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/use-aria-modal-overlay": { + "version": "2.2.20", + "resolved": "https://registry.npmjs.org/@heroui/use-aria-modal-overlay/-/use-aria-modal-overlay-2.2.20.tgz", + "integrity": "sha512-AIYfpnpiRVJm3InKlroGqQSZ1hjBI0Y5oMhMrXuQqrySsMKzMye3zMcEBWf8dEho1l+/U0dgNIUJFbkEFsOc8w==", + "license": "MIT", + "dependencies": { + "@heroui/use-aria-overlay": "2.0.5", + "@react-aria/overlays": "3.31.0", + "@react-aria/utils": "3.32.0", + "@react-stately/overlays": "3.6.21" + }, + "peerDependencies": { + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/use-aria-modal-overlay/node_modules/@react-aria/overlays": { + "version": "3.31.0", + "resolved": "https://registry.npmjs.org/@react-aria/overlays/-/overlays-3.31.0.tgz", + "integrity": "sha512-Vq41X1s8XheGIhGbbuqRJslJEX08qmMVX//dwuBaFX9T18mMR04tumKOMxp8Lz+vqwdGLvjNUYDMcgolL+AMjw==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/focus": "^3.21.3", + "@react-aria/i18n": "^3.12.14", + "@react-aria/interactions": "^3.26.0", + "@react-aria/ssr": "^3.9.10", + "@react-aria/utils": "^3.32.0", + "@react-aria/visually-hidden": "^3.8.29", + "@react-stately/overlays": "^3.6.21", + "@react-types/button": "^3.14.1", + "@react-types/overlays": "^3.9.2", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/use-aria-modal-overlay/node_modules/@react-aria/utils": { + "version": "3.32.0", + "resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.32.0.tgz", + "integrity": "sha512-/7Rud06+HVBIlTwmwmJa2W8xVtgxgzm0+kLbuFooZRzKDON6hhozS1dOMR/YLMxyJOaYOTpImcP4vRR9gL1hEg==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/ssr": "^3.9.10", + "@react-stately/flags": "^3.1.2", + "@react-stately/utils": "^3.11.0", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/use-aria-modal-overlay/node_modules/@react-stately/overlays": { + "version": "3.6.21", + "resolved": "https://registry.npmjs.org/@react-stately/overlays/-/overlays-3.6.21.tgz", + "integrity": "sha512-7f25H1PS2g+SNvuWPEW30pSGqYNHxesCP4w+1RcV/XV1oQI7oP5Ji2WfI0QsJEFc9wP/ZO1pyjHNKpfLI3O88g==", + "license": "Apache-2.0", + "dependencies": { + "@react-stately/utils": "^3.11.0", + "@react-types/overlays": "^3.9.2", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/use-aria-multiselect": { + "version": "2.4.20", + "resolved": "https://registry.npmjs.org/@heroui/use-aria-multiselect/-/use-aria-multiselect-2.4.20.tgz", + "integrity": "sha512-Tvbk2AaWfGYgL6Sn9SwsI+nSOcaD1e3wWGPEqHzeFgoSV6cT7oLY70TODD/HyTF+LKYPtYUbAenxDd80Z5j+Eg==", + "license": "MIT", + "dependencies": { + "@react-aria/i18n": "3.12.14", + "@react-aria/interactions": "3.26.0", + "@react-aria/label": "3.7.23", + "@react-aria/listbox": "3.15.1", + "@react-aria/menu": "3.19.4", + "@react-aria/selection": "3.27.0", + "@react-aria/utils": "3.32.0", + "@react-stately/form": "3.2.2", + "@react-stately/list": "3.13.2", + "@react-stately/menu": "3.9.9", + "@react-types/button": "3.14.1", + "@react-types/overlays": "3.9.2", + "@react-types/shared": "3.32.1" + }, + "peerDependencies": { + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/use-aria-multiselect/node_modules/@react-aria/i18n": { + "version": "3.12.14", + "resolved": "https://registry.npmjs.org/@react-aria/i18n/-/i18n-3.12.14.tgz", + "integrity": "sha512-zYvs1FlLamFD49uneX3i5mPHrAsB3OjVpSWApTcPw8ydxOaphQDp/Q1aqrbcxlrQCcxZdXWHuvLlbkNR4+8jzw==", + "license": "Apache-2.0", + "dependencies": { + "@internationalized/date": "^3.10.1", + "@internationalized/message": "^3.1.8", + "@internationalized/number": "^3.6.5", + "@internationalized/string": "^3.2.7", + "@react-aria/ssr": "^3.9.10", + "@react-aria/utils": "^3.32.0", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/use-aria-multiselect/node_modules/@react-aria/interactions": { + "version": "3.26.0", + "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.26.0.tgz", + "integrity": "sha512-AAEcHiltjfbmP1i9iaVw34Mb7kbkiHpYdqieWufldh4aplWgsF11YQZOfaCJW4QoR2ML4Zzoa9nfFwLXA52R7Q==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/ssr": "^3.9.10", + "@react-aria/utils": "^3.32.0", + "@react-stately/flags": "^3.1.2", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/use-aria-multiselect/node_modules/@react-aria/listbox": { + "version": "3.15.1", + "resolved": "https://registry.npmjs.org/@react-aria/listbox/-/listbox-3.15.1.tgz", + "integrity": "sha512-81iDLFhmPXvLOtkI0SKzgrngfzwfR2o9oFDAYRfpYCOxgT7jjh8SaB4wCteJXRiMwymRGmgyTvD4yxWTluEeXA==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/interactions": "^3.26.0", + "@react-aria/label": "^3.7.23", + "@react-aria/selection": "^3.27.0", + "@react-aria/utils": "^3.32.0", + "@react-stately/collections": "^3.12.8", + "@react-stately/list": "^3.13.2", + "@react-types/listbox": "^3.7.4", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/use-aria-multiselect/node_modules/@react-aria/menu": { + "version": "3.19.4", + "resolved": "https://registry.npmjs.org/@react-aria/menu/-/menu-3.19.4.tgz", + "integrity": "sha512-0A0DUEkEvZynmaD3zktHavM+EmgZSR/ht+g1ExS2jXe73CegA+dbSRfPl9eIKcHxaRrWOV96qMj2pTf0yWTBDg==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/focus": "^3.21.3", + "@react-aria/i18n": "^3.12.14", + "@react-aria/interactions": "^3.26.0", + "@react-aria/overlays": "^3.31.0", + "@react-aria/selection": "^3.27.0", + "@react-aria/utils": "^3.32.0", + "@react-stately/collections": "^3.12.8", + "@react-stately/menu": "^3.9.9", + "@react-stately/selection": "^3.20.7", + "@react-stately/tree": "^3.9.4", + "@react-types/button": "^3.14.1", + "@react-types/menu": "^3.10.5", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/use-aria-multiselect/node_modules/@react-aria/utils": { + "version": "3.32.0", + "resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.32.0.tgz", + "integrity": "sha512-/7Rud06+HVBIlTwmwmJa2W8xVtgxgzm0+kLbuFooZRzKDON6hhozS1dOMR/YLMxyJOaYOTpImcP4vRR9gL1hEg==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/ssr": "^3.9.10", + "@react-stately/flags": "^3.1.2", + "@react-stately/utils": "^3.11.0", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/use-aria-multiselect/node_modules/@react-stately/form": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@react-stately/form/-/form-3.2.2.tgz", + "integrity": "sha512-soAheOd7oaTO6eNs6LXnfn0tTqvOoe3zN9FvtIhhrErKz9XPc5sUmh3QWwR45+zKbitOi1HOjfA/gifKhZcfWw==", + "license": "Apache-2.0", + "dependencies": { + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/use-aria-multiselect/node_modules/@react-stately/list": { + "version": "3.13.2", + "resolved": "https://registry.npmjs.org/@react-stately/list/-/list-3.13.2.tgz", + "integrity": "sha512-dGFALuQWNNOkv7W12qSsXLF4mJHLeWeK2hVvdyj4SI8Vxku+BOfaVKuW3sn3mNiixI1dM/7FY2ip4kK+kv27vw==", + "license": "Apache-2.0", + "dependencies": { + "@react-stately/collections": "^3.12.8", + "@react-stately/selection": "^3.20.7", + "@react-stately/utils": "^3.11.0", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/use-aria-multiselect/node_modules/@react-stately/menu": { + "version": "3.9.9", + "resolved": "https://registry.npmjs.org/@react-stately/menu/-/menu-3.9.9.tgz", + "integrity": "sha512-moW5JANxMxPilfR0SygpCWCZe7Ef09oadgzTZthRymNRv0PXVS9ad4wd1EkwuMvPH/n0uZLZE2s8hNyFDgyqPA==", + "license": "Apache-2.0", + "dependencies": { + "@react-stately/overlays": "^3.6.21", + "@react-types/menu": "^3.10.5", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/use-aria-multiselect/node_modules/@react-types/button": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/@react-types/button/-/button-3.14.1.tgz", + "integrity": "sha512-D8C4IEwKB7zEtiWYVJ3WE/5HDcWlze9mLWQ5hfsBfpePyWCgO3bT/+wjb/7pJvcAocrkXo90QrMm85LcpBtrpg==", + "license": "Apache-2.0", + "dependencies": { + "@react-types/shared": "^3.32.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/use-aria-multiselect/node_modules/@react-types/overlays": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@react-types/overlays/-/overlays-3.9.2.tgz", + "integrity": "sha512-Q0cRPcBGzNGmC8dBuHyoPR7N3057KTS5g+vZfQ53k8WwmilXBtemFJPLsogJbspuewQ/QJ3o2HYsp2pne7/iNw==", + "license": "Apache-2.0", + "dependencies": { + "@react-types/shared": "^3.32.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/use-aria-multiselect/node_modules/@react-types/shared": { + "version": "3.32.1", + "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.32.1.tgz", + "integrity": "sha512-famxyD5emrGGpFuUlgOP6fVW2h/ZaF405G5KDi3zPHzyjAWys/8W6NAVJtNbkCkhedmvL0xOhvt8feGXyXaw5w==", + "license": "Apache-2.0", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/use-aria-overlay": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@heroui/use-aria-overlay/-/use-aria-overlay-2.0.5.tgz", + "integrity": "sha512-2g1HxRoDzGAqIkW7s09WEXg+SAWslh+ZkIuixNAqsA60FHSAzQtGCNpbE2yFeMrukhbmRfS8t3hT2JVZVAXG7w==", + "license": "MIT", + "dependencies": { + "@react-aria/focus": "3.21.3", + "@react-aria/interactions": "3.26.0", + "@react-aria/overlays": "3.31.0", + "@react-types/shared": "3.32.1" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + } + }, + "node_modules/@heroui/use-aria-overlay/node_modules/@react-aria/focus": { + "version": "3.21.3", + "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.21.3.tgz", + "integrity": "sha512-FsquWvjSCwC2/sBk4b+OqJyONETUIXQ2vM0YdPAuC+QFQh2DT6TIBo6dOZVSezlhudDla69xFBd6JvCFq1AbUw==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/interactions": "^3.26.0", + "@react-aria/utils": "^3.32.0", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/use-aria-overlay/node_modules/@react-aria/interactions": { + "version": "3.26.0", + "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.26.0.tgz", + "integrity": "sha512-AAEcHiltjfbmP1i9iaVw34Mb7kbkiHpYdqieWufldh4aplWgsF11YQZOfaCJW4QoR2ML4Zzoa9nfFwLXA52R7Q==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/ssr": "^3.9.10", + "@react-aria/utils": "^3.32.0", + "@react-stately/flags": "^3.1.2", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/use-aria-overlay/node_modules/@react-aria/overlays": { + "version": "3.31.0", + "resolved": "https://registry.npmjs.org/@react-aria/overlays/-/overlays-3.31.0.tgz", + "integrity": "sha512-Vq41X1s8XheGIhGbbuqRJslJEX08qmMVX//dwuBaFX9T18mMR04tumKOMxp8Lz+vqwdGLvjNUYDMcgolL+AMjw==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/focus": "^3.21.3", + "@react-aria/i18n": "^3.12.14", + "@react-aria/interactions": "^3.26.0", + "@react-aria/ssr": "^3.9.10", + "@react-aria/utils": "^3.32.0", + "@react-aria/visually-hidden": "^3.8.29", + "@react-stately/overlays": "^3.6.21", + "@react-types/button": "^3.14.1", + "@react-types/overlays": "^3.9.2", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/use-aria-overlay/node_modules/@react-types/shared": { + "version": "3.32.1", + "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.32.1.tgz", + "integrity": "sha512-famxyD5emrGGpFuUlgOP6fVW2h/ZaF405G5KDi3zPHzyjAWys/8W6NAVJtNbkCkhedmvL0xOhvt8feGXyXaw5w==", + "license": "Apache-2.0", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/use-callback-ref": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@heroui/use-callback-ref/-/use-callback-ref-2.1.8.tgz", + "integrity": "sha512-D1JDo9YyFAprYpLID97xxQvf86NvyWLay30BeVVZT9kWmar6O9MbCRc7ACi7Ngko60beonj6+amTWkTm7QuY/Q==", + "license": "MIT", + "dependencies": { + "@heroui/use-safe-layout-effect": "2.1.8" + }, + "peerDependencies": { + "react": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/use-clipboard": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@heroui/use-clipboard/-/use-clipboard-2.1.9.tgz", + "integrity": "sha512-lkBq5RpXHiPvk1BXKJG8gMM0f7jRMIGnxAXDjAUzZyXKBuWLoM+XlaUWmZHtmkkjVFMX1L4vzA+vxi9rZbenEQ==", + "license": "MIT", + "peerDependencies": { + "react": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/use-data-scroll-overflow": { + "version": "2.2.13", + "resolved": "https://registry.npmjs.org/@heroui/use-data-scroll-overflow/-/use-data-scroll-overflow-2.2.13.tgz", + "integrity": "sha512-zboLXO1pgYdzMUahDcVt5jf+l1jAQ/D9dFqr7AxWLfn6tn7/EgY0f6xIrgWDgJnM0U3hKxVeY13pAeB4AFTqTw==", + "license": "MIT", + "dependencies": { + "@heroui/shared-utils": "2.1.12" + }, + "peerDependencies": { + "react": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/use-disclosure": { + "version": "2.2.18", + "resolved": "https://registry.npmjs.org/@heroui/use-disclosure/-/use-disclosure-2.2.18.tgz", + "integrity": "sha512-aR/4oITXOyt8uze9EdfL/b2j8pg75dc92Q8FfoT17MibD6nKI1VmQDA+9CAtUwuKq6rSrEGqc14muO3GYpTH4g==", + "license": "MIT", + "dependencies": { + "@heroui/use-callback-ref": "2.1.8", + "@react-aria/utils": "3.32.0", + "@react-stately/utils": "3.11.0" + }, + "peerDependencies": { + "react": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/use-disclosure/node_modules/@react-aria/utils": { + "version": "3.32.0", + "resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.32.0.tgz", + "integrity": "sha512-/7Rud06+HVBIlTwmwmJa2W8xVtgxgzm0+kLbuFooZRzKDON6hhozS1dOMR/YLMxyJOaYOTpImcP4vRR9gL1hEg==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/ssr": "^3.9.10", + "@react-stately/flags": "^3.1.2", + "@react-stately/utils": "^3.11.0", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/use-draggable": { + "version": "2.1.19", + "resolved": "https://registry.npmjs.org/@heroui/use-draggable/-/use-draggable-2.1.19.tgz", + "integrity": "sha512-pk0Oe4QLcjr1gndcuvq+8z6eoM+v3lvbmEDxbsEjeST9AwykfmT/60X+xrPFtCkfYldYXk1UxBPiGwrFs0lscQ==", + "license": "MIT", + "dependencies": { + "@react-aria/interactions": "3.26.0" + }, + "peerDependencies": { + "react": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/use-draggable/node_modules/@react-aria/interactions": { + "version": "3.26.0", + "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.26.0.tgz", + "integrity": "sha512-AAEcHiltjfbmP1i9iaVw34Mb7kbkiHpYdqieWufldh4aplWgsF11YQZOfaCJW4QoR2ML4Zzoa9nfFwLXA52R7Q==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/ssr": "^3.9.10", + "@react-aria/utils": "^3.32.0", + "@react-stately/flags": "^3.1.2", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/use-form-reset": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@heroui/use-form-reset/-/use-form-reset-2.0.1.tgz", + "integrity": "sha512-6slKWiLtVfgZnVeHVkM9eXgjwI07u0CUaLt2kQpfKPqTSTGfbHgCYJFduijtThhTdKBhdH6HCmzTcnbVlAxBXw==", + "license": "MIT", + "peerDependencies": { + "react": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/use-image": { + "version": "2.1.14", + "resolved": "https://registry.npmjs.org/@heroui/use-image/-/use-image-2.1.14.tgz", + "integrity": "sha512-eCxtKOsM1tszBKYqz8qIJwGIxEAUC7ua+6L9vK8JgG6gOC0jEPFGH7keQuPVprzRtG3DmNt90icowqEjnOHdFQ==", + "license": "MIT", + "dependencies": { + "@heroui/react-utils": "2.1.14", + "@heroui/use-safe-layout-effect": "2.1.8" + }, + "peerDependencies": { + "react": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/use-intersection-observer": { + "version": "2.2.14", + "resolved": "https://registry.npmjs.org/@heroui/use-intersection-observer/-/use-intersection-observer-2.2.14.tgz", + "integrity": "sha512-qYJeMk4cTsF+xIckRctazCgWQ4BVOpJu+bhhkB1NrN+MItx19Lcb7ksOqMdN5AiSf85HzDcAEPIQ9w9RBlt5sg==", + "license": "MIT", + "peerDependencies": { + "react": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/use-is-mobile": { + "version": "2.2.12", + "resolved": "https://registry.npmjs.org/@heroui/use-is-mobile/-/use-is-mobile-2.2.12.tgz", + "integrity": "sha512-2UKa4v1xbvFwerWKoMTrg4q9ZfP9MVIVfCl1a7JuKQlXq3jcyV6z1as5bZ41pCsTOT+wUVOFnlr6rzzQwT9ZOA==", + "license": "MIT", + "dependencies": { + "@react-aria/ssr": "3.9.10" + }, + "peerDependencies": { + "react": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/use-is-mounted": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@heroui/use-is-mounted/-/use-is-mounted-2.1.8.tgz", + "integrity": "sha512-DO/Th1vD4Uy8KGhd17oGlNA4wtdg91dzga+VMpmt94gSZe1WjsangFwoUBxF2uhlzwensCX9voye3kerP/lskg==", + "license": "MIT", + "peerDependencies": { + "react": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/use-measure": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@heroui/use-measure/-/use-measure-2.1.8.tgz", + "integrity": "sha512-GjT9tIgluqYMZWfAX6+FFdRQBqyHeuqUMGzAXMTH9kBXHU0U5C5XU2c8WFORkNDoZIg1h13h1QdV+Vy4LE1dEA==", + "license": "MIT", + "peerDependencies": { + "react": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/use-pagination": { + "version": "2.2.19", + "resolved": "https://registry.npmjs.org/@heroui/use-pagination/-/use-pagination-2.2.19.tgz", + "integrity": "sha512-0VLyxge+rPBexK7xoLgPwCC8ngh9vIgHEtS+sRvulcEy4grG9EvZWUfMpMeiboFc5Ku2l5u+D9jYkaV06EY4Rw==", + "license": "MIT", + "dependencies": { + "@heroui/shared-utils": "2.1.12", + "@react-aria/i18n": "3.12.14" + }, + "peerDependencies": { + "react": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/use-pagination/node_modules/@react-aria/i18n": { + "version": "3.12.14", + "resolved": "https://registry.npmjs.org/@react-aria/i18n/-/i18n-3.12.14.tgz", + "integrity": "sha512-zYvs1FlLamFD49uneX3i5mPHrAsB3OjVpSWApTcPw8ydxOaphQDp/Q1aqrbcxlrQCcxZdXWHuvLlbkNR4+8jzw==", + "license": "Apache-2.0", + "dependencies": { + "@internationalized/date": "^3.10.1", + "@internationalized/message": "^3.1.8", + "@internationalized/number": "^3.6.5", + "@internationalized/string": "^3.2.7", + "@react-aria/ssr": "^3.9.10", + "@react-aria/utils": "^3.32.0", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@heroui/use-resize": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@heroui/use-resize/-/use-resize-2.1.8.tgz", + "integrity": "sha512-htF3DND5GmrSiMGnzRbISeKcH+BqhQ/NcsP9sBTIl7ewvFaWiDhEDiUHdJxflmJGd/c5qZq2nYQM/uluaqIkKA==", + "license": "MIT", + "peerDependencies": { + "react": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/use-safe-layout-effect": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@heroui/use-safe-layout-effect/-/use-safe-layout-effect-2.1.8.tgz", + "integrity": "sha512-wbnZxVWCYqk10XRMu0veSOiVsEnLcmGUmJiapqgaz0fF8XcpSScmqjTSoWjHIEWaHjQZ6xr+oscD761D6QJN+Q==", + "license": "MIT", + "peerDependencies": { + "react": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/use-scroll-position": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@heroui/use-scroll-position/-/use-scroll-position-2.1.8.tgz", + "integrity": "sha512-NxanHKObxVfWaPpNRyBR8v7RfokxrzcHyTyQfbgQgAGYGHTMaOGkJGqF8kBzInc3zJi+F0zbX7Nb0QjUgsLNUQ==", + "license": "MIT", + "peerDependencies": { + "react": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/use-viewport-size": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@heroui/use-viewport-size/-/use-viewport-size-2.0.1.tgz", + "integrity": "sha512-blv8BEB/QdLePLWODPRzRS2eELJ2eyHbdOIADbL0KcfLzOUEg9EiuVk90hcSUDAFqYiJ3YZ5Z0up8sdPcR8Y7g==", + "license": "MIT", + "peerDependencies": { + "react": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/user": { + "version": "2.2.25", + "resolved": "https://registry.npmjs.org/@heroui/user/-/user-2.2.25.tgz", + "integrity": "sha512-YabNXAYAQbGrHojjG/koHr9F1pMgxQrdVUiSXihqtxaCmY8PLH7uDqj0QMRtmh6v4h/gsfXvVWzkWnTA6/WuEg==", + "license": "MIT", + "dependencies": { + "@heroui/avatar": "2.2.25", + "@heroui/react-utils": "2.1.14", + "@heroui/shared-utils": "2.1.12", + "@react-aria/focus": "3.21.3" + }, + "peerDependencies": { + "@heroui/system": ">=2.4.18", + "@heroui/theme": ">=2.4.24", + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" + } + }, + "node_modules/@heroui/user/node_modules/@react-aria/focus": { + "version": "3.21.3", + "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.21.3.tgz", + "integrity": "sha512-FsquWvjSCwC2/sBk4b+OqJyONETUIXQ2vM0YdPAuC+QFQh2DT6TIBo6dOZVSezlhudDla69xFBd6JvCFq1AbUw==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/interactions": "^3.26.0", + "@react-aria/utils": "^3.32.0", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@inquirer/ansi": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-1.0.2.tgz", + "integrity": "sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/confirm": { + "version": "5.1.21", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.21.tgz", + "integrity": "sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.3.2", + "@inquirer/type": "^3.0.10" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/core": { + "version": "10.3.2", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.3.2.tgz", + "integrity": "sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/ansi": "^1.0.2", + "@inquirer/figures": "^1.0.15", + "@inquirer/type": "^3.0.10", + "cli-width": "^4.1.0", + "mute-stream": "^2.0.0", + "signal-exit": "^4.1.0", + "wrap-ansi": "^6.2.0", + "yoctocolors-cjs": "^2.1.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/core/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@inquirer/core/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@inquirer/core/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==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@inquirer/core/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@inquirer/figures": { + "version": "1.0.15", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.15.tgz", + "integrity": "sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/type": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.10.tgz", + "integrity": "sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@internationalized/date": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/@internationalized/date/-/date-3.11.0.tgz", + "integrity": "sha512-BOx5huLAWhicM9/ZFs84CzP+V3gBW6vlpM02yzsdYC7TGlZJX1OJiEEHcSayF00Z+3jLlm4w79amvSt6RqKN3Q==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0" + } + }, + "node_modules/@internationalized/message": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/@internationalized/message/-/message-3.1.8.tgz", + "integrity": "sha512-Rwk3j/TlYZhn3HQ6PyXUV0XP9Uv42jqZGNegt0BXlxjE6G3+LwHjbQZAGHhCnCPdaA6Tvd3ma/7QzLlLkJxAWA==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0", + "intl-messageformat": "^10.1.0" + } + }, + "node_modules/@internationalized/number": { + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/@internationalized/number/-/number-3.6.5.tgz", + "integrity": "sha512-6hY4Kl4HPBvtfS62asS/R22JzNNy8vi/Ssev7x6EobfCp+9QIB2hKvI2EtbdJ0VSQacxVNtqhE/NmF/NZ0gm6g==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0" + } + }, + "node_modules/@internationalized/string": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/@internationalized/string/-/string-3.2.7.tgz", + "integrity": "sha512-D4OHBjrinH+PFZPvfCXvG28n2LSykWcJ7GIioQL+ok0LON15SdfoUssoHzzOUmVZLbRoREsQXVzA6r8JKsbP6A==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "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==", + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "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.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", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@mswjs/interceptors": { + "version": "0.41.3", + "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.41.3.tgz", + "integrity": "sha512-cXu86tF4VQVfwz8W1SPbhoRyHJkti6mjH/XJIxp40jhO4j2k1m4KYrEykxqWPkFF3vrK4rgQppBh//AwyGSXPA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@open-draft/deferred-promise": "^2.2.0", + "@open-draft/logger": "^0.3.0", + "@open-draft/until": "^2.0.0", + "is-node-process": "^1.2.0", + "outvariant": "^1.4.3", + "strict-event-emitter": "^0.5.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@open-draft/deferred-promise": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz", + "integrity": "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@open-draft/logger": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@open-draft/logger/-/logger-0.3.0.tgz", + "integrity": "sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-node-process": "^1.2.0", + "outvariant": "^1.4.0" + } + }, + "node_modules/@open-draft/until": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@open-draft/until/-/until-2.1.0.tgz", + "integrity": "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@playwright/test": { + "version": "1.58.2", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.58.2.tgz", + "integrity": "sha512-akea+6bHYBBfA9uQqSYmlJXn61cTa+jbO87xVLCWbTqbWadRVmhxlXATaOjOgcBaWU4ePo0wB41KMFv3o35IXA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright": "1.58.2" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-aria/breadcrumbs": { + "version": "3.5.30", + "resolved": "https://registry.npmjs.org/@react-aria/breadcrumbs/-/breadcrumbs-3.5.30.tgz", + "integrity": "sha512-DZymglA70SwvDJA7GB147sUexvdDy6vWcriGrlEHhMMzBLhGB30I5J96R4pPzURLxXISrWFH56KC5rRgIqsqqg==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/i18n": "^3.12.14", + "@react-aria/link": "^3.8.7", + "@react-aria/utils": "^3.32.0", + "@react-types/breadcrumbs": "^3.7.17", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/button": { + "version": "3.14.4", + "resolved": "https://registry.npmjs.org/@react-aria/button/-/button-3.14.4.tgz", + "integrity": "sha512-6mTPiSSQhELnWlnYJ1Tm1B0VL1GGKAs2PGAY3ZGbPGQPPDc6Wu82yIhuAO8TTFJrXkwAiqjQawgDLil/yB0V7Q==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/interactions": "^3.27.0", + "@react-aria/toolbar": "3.0.0-beta.23", + "@react-aria/utils": "^3.33.0", + "@react-stately/toggle": "^3.9.4", + "@react-types/button": "^3.15.0", + "@react-types/shared": "^3.33.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/calendar": { + "version": "3.9.4", + "resolved": "https://registry.npmjs.org/@react-aria/calendar/-/calendar-3.9.4.tgz", + "integrity": "sha512-0BvU8cj6uHn622Vp8Xd21XxXtvp3Bh4Yk1pHloqDNmUvvdBN+ol3Xsm5gG3XKKkZ+6CCEi6asCbLaEg3SZSbyg==", + "license": "Apache-2.0", + "dependencies": { + "@internationalized/date": "^3.11.0", + "@react-aria/i18n": "^3.12.15", + "@react-aria/interactions": "^3.27.0", + "@react-aria/live-announcer": "^3.4.4", + "@react-aria/utils": "^3.33.0", + "@react-stately/calendar": "^3.9.2", + "@react-types/button": "^3.15.0", + "@react-types/calendar": "^3.8.2", + "@react-types/shared": "^3.33.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/checkbox": { + "version": "3.16.4", + "resolved": "https://registry.npmjs.org/@react-aria/checkbox/-/checkbox-3.16.4.tgz", + "integrity": "sha512-FcZj6/f27mNp2+G5yxyOMRZbZQjJ1cuWvo0PPnnZ4ybSPUmSzI4uUZBk1wvsJVP9F9n+J2hZuYVCaN8pyzLweA==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/form": "^3.1.4", + "@react-aria/interactions": "^3.27.0", + "@react-aria/label": "^3.7.24", + "@react-aria/toggle": "^3.12.4", + "@react-aria/utils": "^3.33.0", + "@react-stately/checkbox": "^3.7.4", + "@react-stately/form": "^3.2.3", + "@react-stately/toggle": "^3.9.4", + "@react-types/checkbox": "^3.10.3", + "@react-types/shared": "^3.33.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/checkbox/node_modules/@react-aria/label": { + "version": "3.7.24", + "resolved": "https://registry.npmjs.org/@react-aria/label/-/label-3.7.24.tgz", + "integrity": "sha512-lcJbUy6xyicWKNgzfrXksrJ2CeCST2rDxGAvHOmUxSbFOm26kK710DjaFvtO4tICWh/TKW5mC3sm77soNcVUGA==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/utils": "^3.33.0", + "@react-types/shared": "^3.33.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/combobox": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/@react-aria/combobox/-/combobox-3.14.2.tgz", + "integrity": "sha512-qwBeb8cMgK3xwrvXYHPtcphduD/k+oTcU18JHPvEO2kmR32knB33H81C2/Zoh4x86zTDJXaEtPscXBWuQ/M7AQ==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/focus": "^3.21.4", + "@react-aria/i18n": "^3.12.15", + "@react-aria/listbox": "^3.15.2", + "@react-aria/live-announcer": "^3.4.4", + "@react-aria/menu": "^3.20.0", + "@react-aria/overlays": "^3.31.1", + "@react-aria/selection": "^3.27.1", + "@react-aria/textfield": "^3.18.4", + "@react-aria/utils": "^3.33.0", + "@react-stately/collections": "^3.12.9", + "@react-stately/combobox": "^3.12.2", + "@react-stately/form": "^3.2.3", + "@react-types/button": "^3.15.0", + "@react-types/combobox": "^3.13.11", + "@react-types/shared": "^3.33.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/combobox/node_modules/@react-aria/selection": { + "version": "3.27.1", + "resolved": "https://registry.npmjs.org/@react-aria/selection/-/selection-3.27.1.tgz", + "integrity": "sha512-8WQ4AtWiBnk9UEeYkqpH12dd8KQW2aFbNZvM4sDfLtz7K7HWyY/MkqMe/snk9IcoSa7t4zr0bnoZJcWSGgn2PQ==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/focus": "^3.21.4", + "@react-aria/i18n": "^3.12.15", + "@react-aria/interactions": "^3.27.0", + "@react-aria/utils": "^3.33.0", + "@react-stately/selection": "^3.20.8", + "@react-types/shared": "^3.33.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/datepicker": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/@react-aria/datepicker/-/datepicker-3.16.0.tgz", + "integrity": "sha512-QynYHIHE+wvuGopl/k05tphmDpykpfZ3l3eKnUfGrqvAYJEeCOyS0qoMlw7Vq3NscMLFbJI6ajqBmlmtgFNiSA==", + "license": "Apache-2.0", + "dependencies": { + "@internationalized/date": "^3.11.0", + "@internationalized/number": "^3.6.5", + "@internationalized/string": "^3.2.7", + "@react-aria/focus": "^3.21.4", + "@react-aria/form": "^3.1.4", + "@react-aria/i18n": "^3.12.15", + "@react-aria/interactions": "^3.27.0", + "@react-aria/label": "^3.7.24", + "@react-aria/spinbutton": "^3.7.1", + "@react-aria/utils": "^3.33.0", + "@react-stately/datepicker": "^3.16.0", + "@react-stately/form": "^3.2.3", + "@react-types/button": "^3.15.0", + "@react-types/calendar": "^3.8.2", + "@react-types/datepicker": "^3.13.4", + "@react-types/dialog": "^3.5.23", + "@react-types/shared": "^3.33.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/datepicker/node_modules/@react-aria/label": { + "version": "3.7.24", + "resolved": "https://registry.npmjs.org/@react-aria/label/-/label-3.7.24.tgz", + "integrity": "sha512-lcJbUy6xyicWKNgzfrXksrJ2CeCST2rDxGAvHOmUxSbFOm26kK710DjaFvtO4tICWh/TKW5mC3sm77soNcVUGA==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/utils": "^3.33.0", + "@react-types/shared": "^3.33.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/dialog": { + "version": "3.5.33", + "resolved": "https://registry.npmjs.org/@react-aria/dialog/-/dialog-3.5.33.tgz", + "integrity": "sha512-C5FpLAMJU6gQU8gztWKlEJ2A0k/JKl0YijNOv3Lizk+vUdF5njROSrmFs16bY5Hd6ycmsK9x/Pqkq3m/OpNFXA==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/interactions": "^3.27.0", + "@react-aria/overlays": "^3.31.1", + "@react-aria/utils": "^3.33.0", + "@react-types/dialog": "^3.5.23", + "@react-types/shared": "^3.33.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/focus": { + "version": "3.21.4", + "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.21.4.tgz", + "integrity": "sha512-6gz+j9ip0/vFRTKJMl3R30MHopn4i19HqqLfSQfElxJD+r9hBnYG1Q6Wd/kl/WRR1+CALn2F+rn06jUnf5sT8Q==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/interactions": "^3.27.0", + "@react-aria/utils": "^3.33.0", + "@react-types/shared": "^3.33.0", + "@swc/helpers": "^0.5.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/form": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@react-aria/form/-/form-3.1.4.tgz", + "integrity": "sha512-GjPS85cE/34zal3vs6MOi7FxUsXwbxN4y6l1LFor2g92UK97gVobp238f3xdMW2T8IuaWGcnHeYFg+cjiZ51pQ==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/interactions": "^3.27.0", + "@react-aria/utils": "^3.33.0", + "@react-stately/form": "^3.2.3", + "@react-types/shared": "^3.33.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/grid": { + "version": "3.14.7", + "resolved": "https://registry.npmjs.org/@react-aria/grid/-/grid-3.14.7.tgz", + "integrity": "sha512-8eaJThNHUs75Xf4+FQC2NKQtTOVYkkDdA8VbfbqG06oYDAn7ETb1yhbwoqh1jOv7MezCNkYjyFe4ADsz2rBVcw==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/focus": "^3.21.4", + "@react-aria/i18n": "^3.12.15", + "@react-aria/interactions": "^3.27.0", + "@react-aria/live-announcer": "^3.4.4", + "@react-aria/selection": "^3.27.1", + "@react-aria/utils": "^3.33.0", + "@react-stately/collections": "^3.12.9", + "@react-stately/grid": "^3.11.8", + "@react-stately/selection": "^3.20.8", + "@react-types/checkbox": "^3.10.3", + "@react-types/grid": "^3.3.7", + "@react-types/shared": "^3.33.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/grid/node_modules/@react-aria/selection": { + "version": "3.27.1", + "resolved": "https://registry.npmjs.org/@react-aria/selection/-/selection-3.27.1.tgz", + "integrity": "sha512-8WQ4AtWiBnk9UEeYkqpH12dd8KQW2aFbNZvM4sDfLtz7K7HWyY/MkqMe/snk9IcoSa7t4zr0bnoZJcWSGgn2PQ==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/focus": "^3.21.4", + "@react-aria/i18n": "^3.12.15", + "@react-aria/interactions": "^3.27.0", + "@react-aria/utils": "^3.33.0", + "@react-stately/selection": "^3.20.8", + "@react-types/shared": "^3.33.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/i18n": { + "version": "3.12.15", + "resolved": "https://registry.npmjs.org/@react-aria/i18n/-/i18n-3.12.15.tgz", + "integrity": "sha512-3CrAN7ORVHrckvTmbPq76jFZabqq+rScosGT5+ElircJ5rF5+JcdT99Hp5Xg6R10jk74e8G3xiqdYsUd+7iJMA==", + "license": "Apache-2.0", + "dependencies": { + "@internationalized/date": "^3.11.0", + "@internationalized/message": "^3.1.8", + "@internationalized/number": "^3.6.5", + "@internationalized/string": "^3.2.7", + "@react-aria/ssr": "^3.9.10", + "@react-aria/utils": "^3.33.0", + "@react-types/shared": "^3.33.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/interactions": { + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.27.0.tgz", + "integrity": "sha512-D27pOy+0jIfHK60BB26AgqjjRFOYdvVSkwC31b2LicIzRCSPOSP06V4gMHuGmkhNTF4+YWDi1HHYjxIvMeiSlA==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/ssr": "^3.9.10", + "@react-aria/utils": "^3.33.0", + "@react-stately/flags": "^3.1.2", + "@react-types/shared": "^3.33.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/label": { + "version": "3.7.23", + "resolved": "https://registry.npmjs.org/@react-aria/label/-/label-3.7.23.tgz", + "integrity": "sha512-dRkuCJfsyBHPTq3WOJVHNRvNyQL4cRRLELmjYfUX9/jQKIsUW2l71YnUHZTRCSn2ZjhdAcdwq96fNcQo0hncBQ==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/utils": "^3.32.0", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/landmark": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@react-aria/landmark/-/landmark-3.0.9.tgz", + "integrity": "sha512-YYyluDBCXupnMh91ccE5g27fczjYmzPebHqTkVYjH4B6k45pOoqsMmWBCMnOTl0qOCeioI+daT8W0MamAZzoSw==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/utils": "^3.33.0", + "@react-types/shared": "^3.33.0", + "@swc/helpers": "^0.5.0", + "use-sync-external-store": "^1.6.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/link": { + "version": "3.8.8", + "resolved": "https://registry.npmjs.org/@react-aria/link/-/link-3.8.8.tgz", + "integrity": "sha512-hxQEvo5rrn2C0GOSwB/tROe+y//dyhmyXGbm8arDy6WF5Mj0wcjjrAu0/dhGYBqoltJa16iIEvs52xgzOC+f+Q==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/interactions": "^3.27.0", + "@react-aria/utils": "^3.33.0", + "@react-types/link": "^3.6.6", + "@react-types/shared": "^3.33.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/link/node_modules/@react-types/link": { + "version": "3.6.6", + "resolved": "https://registry.npmjs.org/@react-types/link/-/link-3.6.6.tgz", + "integrity": "sha512-M6WXxUJFmiF6GNu7xUH0uHj0jsorFBN6npkfSCNM4puStC8NbUT2+ZPySQyZXCoHMQ89g6qZ6vCc8QduVkTE7Q==", + "license": "Apache-2.0", + "dependencies": { + "@react-types/shared": "^3.33.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/listbox": { + "version": "3.15.2", + "resolved": "https://registry.npmjs.org/@react-aria/listbox/-/listbox-3.15.2.tgz", + "integrity": "sha512-xcrgSediV8MaVmsuDrDPmWywF82/HOv+H+Y/dgr6GLCWl0XDj5Q7PyAhDzUsYdZNIne3B9muGh6IQc3HdkgWqg==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/interactions": "^3.27.0", + "@react-aria/label": "^3.7.24", + "@react-aria/selection": "^3.27.1", + "@react-aria/utils": "^3.33.0", + "@react-stately/collections": "^3.12.9", + "@react-stately/list": "^3.13.3", + "@react-types/listbox": "^3.7.5", + "@react-types/shared": "^3.33.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/listbox/node_modules/@react-aria/label": { + "version": "3.7.24", + "resolved": "https://registry.npmjs.org/@react-aria/label/-/label-3.7.24.tgz", + "integrity": "sha512-lcJbUy6xyicWKNgzfrXksrJ2CeCST2rDxGAvHOmUxSbFOm26kK710DjaFvtO4tICWh/TKW5mC3sm77soNcVUGA==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/utils": "^3.33.0", + "@react-types/shared": "^3.33.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/listbox/node_modules/@react-aria/selection": { + "version": "3.27.1", + "resolved": "https://registry.npmjs.org/@react-aria/selection/-/selection-3.27.1.tgz", + "integrity": "sha512-8WQ4AtWiBnk9UEeYkqpH12dd8KQW2aFbNZvM4sDfLtz7K7HWyY/MkqMe/snk9IcoSa7t4zr0bnoZJcWSGgn2PQ==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/focus": "^3.21.4", + "@react-aria/i18n": "^3.12.15", + "@react-aria/interactions": "^3.27.0", + "@react-aria/utils": "^3.33.0", + "@react-stately/selection": "^3.20.8", + "@react-types/shared": "^3.33.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/live-announcer": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/@react-aria/live-announcer/-/live-announcer-3.4.4.tgz", + "integrity": "sha512-PTTBIjNRnrdJOIRTDGNifY2d//kA7GUAwRFJNOEwSNG4FW+Bq9awqLiflw0JkpyB0VNIwou6lqKPHZVLsGWOXA==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0" + } + }, + "node_modules/@react-aria/menu": { + "version": "3.20.0", + "resolved": "https://registry.npmjs.org/@react-aria/menu/-/menu-3.20.0.tgz", + "integrity": "sha512-BAsHuf7kTVmawNUkTUd5RB3ZvL6DQQT7hgZ2cYKd/1ZwYq4KO2wWGYdzyTOtK1qimZL0eyHyQwDYv4dNKBH4gw==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/focus": "^3.21.4", + "@react-aria/i18n": "^3.12.15", + "@react-aria/interactions": "^3.27.0", + "@react-aria/overlays": "^3.31.1", + "@react-aria/selection": "^3.27.1", + "@react-aria/utils": "^3.33.0", + "@react-stately/collections": "^3.12.9", + "@react-stately/menu": "^3.9.10", + "@react-stately/selection": "^3.20.8", + "@react-stately/tree": "^3.9.5", + "@react-types/button": "^3.15.0", + "@react-types/menu": "^3.10.6", + "@react-types/shared": "^3.33.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/menu/node_modules/@react-aria/selection": { + "version": "3.27.1", + "resolved": "https://registry.npmjs.org/@react-aria/selection/-/selection-3.27.1.tgz", + "integrity": "sha512-8WQ4AtWiBnk9UEeYkqpH12dd8KQW2aFbNZvM4sDfLtz7K7HWyY/MkqMe/snk9IcoSa7t4zr0bnoZJcWSGgn2PQ==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/focus": "^3.21.4", + "@react-aria/i18n": "^3.12.15", + "@react-aria/interactions": "^3.27.0", + "@react-aria/utils": "^3.33.0", + "@react-stately/selection": "^3.20.8", + "@react-types/shared": "^3.33.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/numberfield": { + "version": "3.12.4", + "resolved": "https://registry.npmjs.org/@react-aria/numberfield/-/numberfield-3.12.4.tgz", + "integrity": "sha512-TgKBjKOjyURzbqNR2wF4tSFmQKNK5DqE4QZSlQxpYYo1T6zuztkh+oTOUZ4IWCJymL5qLtuPfGHCZbR7B+DN2w==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/i18n": "^3.12.15", + "@react-aria/interactions": "^3.27.0", + "@react-aria/spinbutton": "^3.7.1", + "@react-aria/textfield": "^3.18.4", + "@react-aria/utils": "^3.33.0", + "@react-stately/form": "^3.2.3", + "@react-stately/numberfield": "^3.10.4", + "@react-types/button": "^3.15.0", + "@react-types/numberfield": "^3.8.17", + "@react-types/shared": "^3.33.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/overlays": { + "version": "3.31.1", + "resolved": "https://registry.npmjs.org/@react-aria/overlays/-/overlays-3.31.1.tgz", + "integrity": "sha512-U5BedzcXU97U5PWm4kIPnNoVpAs9KjTYfbkGx33vapmTVpGYhQyYW9eg6zW2E8ZKsyFJtQ/jkQnbWGen97aHSQ==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/focus": "^3.21.4", + "@react-aria/i18n": "^3.12.15", + "@react-aria/interactions": "^3.27.0", + "@react-aria/ssr": "^3.9.10", + "@react-aria/utils": "^3.33.0", + "@react-aria/visually-hidden": "^3.8.30", + "@react-stately/overlays": "^3.6.22", + "@react-types/button": "^3.15.0", + "@react-types/overlays": "^3.9.3", + "@react-types/shared": "^3.33.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/progress": { + "version": "3.4.28", + "resolved": "https://registry.npmjs.org/@react-aria/progress/-/progress-3.4.28.tgz", + "integrity": "sha512-3NUUAu+rwf1M7pau9WFkrxe/PlBPiqCl/1maGU7iufVveHnz+SVVqXdNkjYx+WkPE0ViwG86Zx6OU4AYJ1pjNw==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/i18n": "^3.12.14", + "@react-aria/label": "^3.7.23", + "@react-aria/utils": "^3.32.0", + "@react-types/progress": "^3.5.16", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/radio": { + "version": "3.12.4", + "resolved": "https://registry.npmjs.org/@react-aria/radio/-/radio-3.12.4.tgz", + "integrity": "sha512-2sjBAE8++EtAAfjwPdrqEVswbzR4Mvcy4n8SvwUxTo02yESa9nolBzCSdAUFUmhrNj3MiMA+zLxQ+KACfUjJOg==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/focus": "^3.21.4", + "@react-aria/form": "^3.1.4", + "@react-aria/i18n": "^3.12.15", + "@react-aria/interactions": "^3.27.0", + "@react-aria/label": "^3.7.24", + "@react-aria/utils": "^3.33.0", + "@react-stately/radio": "^3.11.4", + "@react-types/radio": "^3.9.3", + "@react-types/shared": "^3.33.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/radio/node_modules/@react-aria/label": { + "version": "3.7.24", + "resolved": "https://registry.npmjs.org/@react-aria/label/-/label-3.7.24.tgz", + "integrity": "sha512-lcJbUy6xyicWKNgzfrXksrJ2CeCST2rDxGAvHOmUxSbFOm26kK710DjaFvtO4tICWh/TKW5mC3sm77soNcVUGA==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/utils": "^3.33.0", + "@react-types/shared": "^3.33.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/selection": { + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/@react-aria/selection/-/selection-3.27.0.tgz", + "integrity": "sha512-4zgreuCu4QM4t2U7aF3mbMvIKCEkTEo6h6nGJvbyZALZ/eFtLTvUiV8/5CGDJRLGvgMvi3XxUeF9PZbpk5nMJg==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/focus": "^3.21.3", + "@react-aria/i18n": "^3.12.14", + "@react-aria/interactions": "^3.26.0", + "@react-aria/utils": "^3.32.0", + "@react-stately/selection": "^3.20.7", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/slider": { + "version": "3.8.4", + "resolved": "https://registry.npmjs.org/@react-aria/slider/-/slider-3.8.4.tgz", + "integrity": "sha512-/FYCgK1qVqaz2VCDfR2x4BjyJ8lmWg1v8//+WIwKdIu4cz0KUs+U3yx0w1vp676RoERp3OEvkT3tb+/jHQ1hjA==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/i18n": "^3.12.15", + "@react-aria/interactions": "^3.27.0", + "@react-aria/label": "^3.7.24", + "@react-aria/utils": "^3.33.0", + "@react-stately/slider": "^3.7.4", + "@react-types/shared": "^3.33.0", + "@react-types/slider": "^3.8.3", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/slider/node_modules/@react-aria/label": { + "version": "3.7.24", + "resolved": "https://registry.npmjs.org/@react-aria/label/-/label-3.7.24.tgz", + "integrity": "sha512-lcJbUy6xyicWKNgzfrXksrJ2CeCST2rDxGAvHOmUxSbFOm26kK710DjaFvtO4tICWh/TKW5mC3sm77soNcVUGA==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/utils": "^3.33.0", + "@react-types/shared": "^3.33.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/spinbutton": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/@react-aria/spinbutton/-/spinbutton-3.7.1.tgz", + "integrity": "sha512-Nisah6yzxOC6983u/5ck0w+OQoa3sRKmpDvWpTEX0g2+ZIABOl8ttdSd65XKtxXmXHdK8X1zmrfeGOBfBR3sKA==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/i18n": "^3.12.15", + "@react-aria/live-announcer": "^3.4.4", + "@react-aria/utils": "^3.33.0", + "@react-types/button": "^3.15.0", + "@react-types/shared": "^3.33.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/ssr": { + "version": "3.9.10", + "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.9.10.tgz", + "integrity": "sha512-hvTm77Pf+pMBhuBm760Li0BVIO38jv1IBws1xFm1NoL26PU+fe+FMW5+VZWyANR6nYL65joaJKZqOdTQMkO9IQ==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0" + }, + "engines": { + "node": ">= 12" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/switch": { + "version": "3.7.9", + "resolved": "https://registry.npmjs.org/@react-aria/switch/-/switch-3.7.9.tgz", + "integrity": "sha512-RZtuFRXews0PBx8Fc2R/kqaIARD5YIM5uYtmwnWfY7y5bEsBGONxp0d+m2vDyY7yk+VNpVFBdwewY9GbZmH1CA==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/toggle": "^3.12.3", + "@react-stately/toggle": "^3.9.3", + "@react-types/shared": "^3.32.1", + "@react-types/switch": "^3.5.15", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/table": { + "version": "3.17.10", + "resolved": "https://registry.npmjs.org/@react-aria/table/-/table-3.17.10.tgz", + "integrity": "sha512-xdEeyOzuETkOfAHhZrX7HOIwMUsCUr4rbPvHqdcNqg7Ngla2ck9iulZNAyvOPfFwELuBEd2rz1I9TYRQ2OzSQQ==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/focus": "^3.21.4", + "@react-aria/grid": "^3.14.7", + "@react-aria/i18n": "^3.12.15", + "@react-aria/interactions": "^3.27.0", + "@react-aria/live-announcer": "^3.4.4", + "@react-aria/utils": "^3.33.0", + "@react-aria/visually-hidden": "^3.8.30", + "@react-stately/collections": "^3.12.9", + "@react-stately/flags": "^3.1.2", + "@react-stately/table": "^3.15.3", + "@react-types/checkbox": "^3.10.3", + "@react-types/grid": "^3.3.7", + "@react-types/shared": "^3.33.0", + "@react-types/table": "^3.13.5", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/tabs": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/@react-aria/tabs/-/tabs-3.11.0.tgz", + "integrity": "sha512-9Gwo118GHrMXSyteCZL1L/LHLVlGSYkhGgiTL3e/UgnYjHfEfDJVTkV2JikuE2O/4uig52gQRlq5E99axLeE9Q==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/focus": "^3.21.4", + "@react-aria/i18n": "^3.12.15", + "@react-aria/selection": "^3.27.1", + "@react-aria/utils": "^3.33.0", + "@react-stately/tabs": "^3.8.8", + "@react-types/shared": "^3.33.0", + "@react-types/tabs": "^3.3.21", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/tabs/node_modules/@react-aria/selection": { + "version": "3.27.1", + "resolved": "https://registry.npmjs.org/@react-aria/selection/-/selection-3.27.1.tgz", + "integrity": "sha512-8WQ4AtWiBnk9UEeYkqpH12dd8KQW2aFbNZvM4sDfLtz7K7HWyY/MkqMe/snk9IcoSa7t4zr0bnoZJcWSGgn2PQ==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/focus": "^3.21.4", + "@react-aria/i18n": "^3.12.15", + "@react-aria/interactions": "^3.27.0", + "@react-aria/utils": "^3.33.0", + "@react-stately/selection": "^3.20.8", + "@react-types/shared": "^3.33.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/textfield": { + "version": "3.18.4", + "resolved": "https://registry.npmjs.org/@react-aria/textfield/-/textfield-3.18.4.tgz", + "integrity": "sha512-ts3Vdy2qNOzjCVeO+4RH8FSgTYN2USAMcYFeGbHOriCukVOrvgRsqcDniW7xaT60LgFdlWMJsCusvltSIyo6xw==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/form": "^3.1.4", + "@react-aria/interactions": "^3.27.0", + "@react-aria/label": "^3.7.24", + "@react-aria/utils": "^3.33.0", + "@react-stately/form": "^3.2.3", + "@react-stately/utils": "^3.11.0", + "@react-types/shared": "^3.33.0", + "@react-types/textfield": "^3.12.7", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/textfield/node_modules/@react-aria/label": { + "version": "3.7.24", + "resolved": "https://registry.npmjs.org/@react-aria/label/-/label-3.7.24.tgz", + "integrity": "sha512-lcJbUy6xyicWKNgzfrXksrJ2CeCST2rDxGAvHOmUxSbFOm26kK710DjaFvtO4tICWh/TKW5mC3sm77soNcVUGA==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/utils": "^3.33.0", + "@react-types/shared": "^3.33.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/toast": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@react-aria/toast/-/toast-3.0.10.tgz", + "integrity": "sha512-irW5Cr4msbPo4A4ysjT70MDJbpGCe1h9SkFgdYXBPA4Xbi4jRT7TiEZeIS1I7Hsvp6shAK1Ld/m6NBS0b/gyzg==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/i18n": "^3.12.15", + "@react-aria/interactions": "^3.27.0", + "@react-aria/landmark": "^3.0.9", + "@react-aria/utils": "^3.33.0", + "@react-stately/toast": "^3.1.3", + "@react-types/button": "^3.15.0", + "@react-types/shared": "^3.33.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/toggle": { + "version": "3.12.4", + "resolved": "https://registry.npmjs.org/@react-aria/toggle/-/toggle-3.12.4.tgz", + "integrity": "sha512-yVcl8kEFLsV47aCA22EMPcd/KWoYqPIPSzoKjRD/iWmxcP6iGzSxDjdUgMQojNGY8Q6wL8lUxfRqKBjvl/uezQ==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/interactions": "^3.27.0", + "@react-aria/utils": "^3.33.0", + "@react-stately/toggle": "^3.9.4", + "@react-types/checkbox": "^3.10.3", + "@react-types/shared": "^3.33.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/toolbar": { + "version": "3.0.0-beta.23", + "resolved": "https://registry.npmjs.org/@react-aria/toolbar/-/toolbar-3.0.0-beta.23.tgz", + "integrity": "sha512-FzvNf2hWtjEwk8F2MBf4qSs6AAR/p2WFSws6kJ4f0SrWXl4wR9VDEwBEUQcIPbWCK2aUsyOjubCh55Cl4t3MoQ==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/focus": "^3.21.4", + "@react-aria/i18n": "^3.12.15", + "@react-aria/utils": "^3.33.0", + "@react-types/shared": "^3.33.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/tooltip": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@react-aria/tooltip/-/tooltip-3.9.1.tgz", + "integrity": "sha512-mvEhqpvF4v/wj9zw3a8bsAEnySutGbxKXXt39s6WvF6dkVfaXfsmV9ahuMCHH//UGh/yidZGLrXX4YVdrgS8lA==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/interactions": "^3.27.0", + "@react-aria/utils": "^3.33.0", + "@react-stately/tooltip": "^3.5.10", + "@react-types/shared": "^3.33.0", + "@react-types/tooltip": "^3.5.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/utils": { + "version": "3.33.0", + "resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.33.0.tgz", + "integrity": "sha512-yvz7CMH8d2VjwbSa5nGXqjU031tYhD8ddax95VzJsHSPyqHDEGfxul8RkhGV6oO7bVqZxVs6xY66NIgae+FHjw==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/ssr": "^3.9.10", + "@react-stately/flags": "^3.1.2", + "@react-stately/utils": "^3.11.0", + "@react-types/shared": "^3.33.0", + "@swc/helpers": "^0.5.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/visually-hidden": { + "version": "3.8.30", + "resolved": "https://registry.npmjs.org/@react-aria/visually-hidden/-/visually-hidden-3.8.30.tgz", + "integrity": "sha512-iY44USEU8sJy0NOJ/sTDn3YlspbhHuVG3nx2YYrzfmxbS3i+lNwkCfG8kJ77dtmbuDLIdBGKENjGkbcwz3kiJg==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/interactions": "^3.27.0", + "@react-aria/utils": "^3.33.0", + "@react-types/shared": "^3.33.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-stately/calendar": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@react-stately/calendar/-/calendar-3.9.2.tgz", + "integrity": "sha512-AQj8/izwb7eY+KFqKcMLI2ygvnbAIwLuQG5KPHgJsMygFqnN4yzXKz5orGqVJnxEXLKiLPteVztx7b5EQobrtw==", + "license": "Apache-2.0", + "dependencies": { + "@internationalized/date": "^3.11.0", + "@react-stately/utils": "^3.11.0", + "@react-types/calendar": "^3.8.2", + "@react-types/shared": "^3.33.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-stately/checkbox": { + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/@react-stately/checkbox/-/checkbox-3.7.4.tgz", + "integrity": "sha512-oXHMkK22CWLcmNlunDuu4p52QXYmkpx6es9AjWx/xlh3XLZdJzo/5SANioOH1QvBtwPA/c2KQy+ZBqC21NtMHw==", + "license": "Apache-2.0", + "dependencies": { + "@react-stately/form": "^3.2.3", + "@react-stately/utils": "^3.11.0", + "@react-types/checkbox": "^3.10.3", + "@react-types/shared": "^3.33.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-stately/collections": { + "version": "3.12.9", + "resolved": "https://registry.npmjs.org/@react-stately/collections/-/collections-3.12.9.tgz", + "integrity": "sha512-2jywPMhVgMOh0XtutxPqIxFCIiLOnL/GXIrRKoBEo8M3Q24NoMRBavUrn9RTvjqNnec1i/8w1/8sq8cmCKEohA==", + "license": "Apache-2.0", + "dependencies": { + "@react-types/shared": "^3.33.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-stately/combobox": { + "version": "3.12.2", + "resolved": "https://registry.npmjs.org/@react-stately/combobox/-/combobox-3.12.2.tgz", + "integrity": "sha512-h4YRmzA+s3aMwUrXm6jyWLN0BWWXUNiodArB1wC24xNdeI7S8O3mxz6G2r3Ne8AE02FXmZXs9SD30Mx5vVVuqQ==", + "license": "Apache-2.0", + "dependencies": { + "@react-stately/collections": "^3.12.9", + "@react-stately/form": "^3.2.3", + "@react-stately/list": "^3.13.3", + "@react-stately/overlays": "^3.6.22", + "@react-stately/utils": "^3.11.0", + "@react-types/combobox": "^3.13.11", + "@react-types/shared": "^3.33.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-stately/datepicker": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/@react-stately/datepicker/-/datepicker-3.16.0.tgz", + "integrity": "sha512-mYtzKXufFVivrHjmxys3ryJFMPIQNhVqaSItmGnWv3ehxw+0HKBrROf3BFiEN4zP20euoP149ZaR4uNx90kMYw==", + "license": "Apache-2.0", + "dependencies": { + "@internationalized/date": "^3.11.0", + "@internationalized/number": "^3.6.5", + "@internationalized/string": "^3.2.7", + "@react-stately/form": "^3.2.3", + "@react-stately/overlays": "^3.6.22", + "@react-stately/utils": "^3.11.0", + "@react-types/datepicker": "^3.13.4", + "@react-types/shared": "^3.33.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-stately/flags": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@react-stately/flags/-/flags-3.1.2.tgz", + "integrity": "sha512-2HjFcZx1MyQXoPqcBGALwWWmgFVUk2TuKVIQxCbRq7fPyWXIl6VHcakCLurdtYC2Iks7zizvz0Idv48MQ38DWg==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0" + } + }, + "node_modules/@react-stately/form": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@react-stately/form/-/form-3.2.3.tgz", + "integrity": "sha512-NPvjJtns1Pq9uvqeRJCf8HIdVmOm2ARLYQ2F/sqXj1w5IChJ4oWL4Xzvj29/zBitgE1vVjDhnrnwSfNlHZGX0g==", + "license": "Apache-2.0", + "dependencies": { + "@react-types/shared": "^3.33.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-stately/grid": { + "version": "3.11.8", + "resolved": "https://registry.npmjs.org/@react-stately/grid/-/grid-3.11.8.tgz", + "integrity": "sha512-tCabR5U7ype+uEElS5Chv5n6ntUv3drXa9DwebjO05cFevUmjTkEfYPJWixpgX4UlCCvjdUFgzeQlJF+gCiozg==", + "license": "Apache-2.0", + "dependencies": { + "@react-stately/collections": "^3.12.9", + "@react-stately/selection": "^3.20.8", + "@react-types/grid": "^3.3.7", + "@react-types/shared": "^3.33.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-stately/list": { + "version": "3.13.3", + "resolved": "https://registry.npmjs.org/@react-stately/list/-/list-3.13.3.tgz", + "integrity": "sha512-xN0v7rzhIKshhcshOzx+ZgVngXnGCtMPRdhoDLGaHzQy5YfxvKBMNLCnr5Lm4T1U/kIvHbyzxmr5uwmH8WxoIg==", + "license": "Apache-2.0", + "dependencies": { + "@react-stately/collections": "^3.12.9", + "@react-stately/selection": "^3.20.8", + "@react-stately/utils": "^3.11.0", + "@react-types/shared": "^3.33.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-stately/menu": { + "version": "3.9.10", + "resolved": "https://registry.npmjs.org/@react-stately/menu/-/menu-3.9.10.tgz", + "integrity": "sha512-dY9FzjQ+6iNInVujZPyMklDGoSbaoO0yguUnALAY+yfkPAyStEElfm4aXZgRfNKOTNHe9E34oV7qefSYsclvTg==", + "license": "Apache-2.0", + "dependencies": { + "@react-stately/overlays": "^3.6.22", + "@react-types/menu": "^3.10.6", + "@react-types/shared": "^3.33.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-stately/numberfield": { + "version": "3.10.4", + "resolved": "https://registry.npmjs.org/@react-stately/numberfield/-/numberfield-3.10.4.tgz", + "integrity": "sha512-EniHHwXOw/Ta0x5j61OvldDAvLoi/8xOo//bzrqwnDvf2/1IKGFMD9CHs7HYhQw+9oNl3Q2V1meOTNPc4PvoMQ==", + "license": "Apache-2.0", + "dependencies": { + "@internationalized/number": "^3.6.5", + "@react-stately/form": "^3.2.3", + "@react-stately/utils": "^3.11.0", + "@react-types/numberfield": "^3.8.17", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-stately/overlays": { + "version": "3.6.22", + "resolved": "https://registry.npmjs.org/@react-stately/overlays/-/overlays-3.6.22.tgz", + "integrity": "sha512-sWBnuy5dqVp8d+1e+ABTRVB3YBcOW86/90pF5PWY44au3bUFXVSUBO2QMdR/6JtojDoPRmrjufonI19/Zs/20w==", + "license": "Apache-2.0", + "dependencies": { + "@react-stately/utils": "^3.11.0", + "@react-types/overlays": "^3.9.3", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-stately/radio": { + "version": "3.11.4", + "resolved": "https://registry.npmjs.org/@react-stately/radio/-/radio-3.11.4.tgz", + "integrity": "sha512-3svsW5VxJA5/p1vO+Qlxv+7Jq9g7f4rqX9Rbqdfd+pH7ykHaV0CUKkSRMaWfcY8Vgaf2xmcc6dvusPRqKX8T1A==", + "license": "Apache-2.0", + "dependencies": { + "@react-stately/form": "^3.2.3", + "@react-stately/utils": "^3.11.0", + "@react-types/radio": "^3.9.3", + "@react-types/shared": "^3.33.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-stately/selection": { + "version": "3.20.8", + "resolved": "https://registry.npmjs.org/@react-stately/selection/-/selection-3.20.8.tgz", + "integrity": "sha512-V1kRN1NLW+i/3Xv+Q0pN9OzuM0zFEW9mdXOOOq7l+YL6hFjqIjttT2/q4KoyiNV3W0hfoRFSTQ7XCgqnqtwEng==", + "license": "Apache-2.0", + "dependencies": { + "@react-stately/collections": "^3.12.9", + "@react-stately/utils": "^3.11.0", + "@react-types/shared": "^3.33.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-stately/slider": { + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/@react-stately/slider/-/slider-3.7.4.tgz", + "integrity": "sha512-cSOYSx2nsOQejMg6Ql0+GUpqAiPwRA5teYXUghNvuBDtVxnd4l2rnXs54Ww48tU43xf2+L3kkmMofThjABoEPw==", + "license": "Apache-2.0", + "dependencies": { + "@react-stately/utils": "^3.11.0", + "@react-types/shared": "^3.33.0", + "@react-types/slider": "^3.8.3", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-stately/table": { + "version": "3.15.3", + "resolved": "https://registry.npmjs.org/@react-stately/table/-/table-3.15.3.tgz", + "integrity": "sha512-W1wR0O/PmdD8hCUFIAelHICjUX/Ii6ZldPlH6EILr9olyGpoCaY7XmnyG7kii1aANuQGBeskjJdXvS6LX/gyDw==", + "license": "Apache-2.0", + "dependencies": { + "@react-stately/collections": "^3.12.9", + "@react-stately/flags": "^3.1.2", + "@react-stately/grid": "^3.11.8", + "@react-stately/selection": "^3.20.8", + "@react-stately/utils": "^3.11.0", + "@react-types/grid": "^3.3.7", + "@react-types/shared": "^3.33.0", + "@react-types/table": "^3.13.5", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-stately/tabs": { + "version": "3.8.8", + "resolved": "https://registry.npmjs.org/@react-stately/tabs/-/tabs-3.8.8.tgz", + "integrity": "sha512-BZImWT+pHZitImRQkoL7jVhTtpGPSra1Rhh4pi8epzwogeqseEIEpuWpQebjQP74r1kfNi/iT2p5Qb31eWfh1Q==", + "license": "Apache-2.0", + "dependencies": { + "@react-stately/list": "^3.13.3", + "@react-types/shared": "^3.33.0", + "@react-types/tabs": "^3.3.21", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-stately/toast": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@react-stately/toast/-/toast-3.1.3.tgz", + "integrity": "sha512-mT9QJKmD523lqFpOp0VWZ6QHZENFK7HrodnNJDVc7g616s5GNmemdlkITV43fSY3tHeThCVvPu+Uzh7RvQ9mpQ==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0", + "use-sync-external-store": "^1.6.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-stately/toggle": { + "version": "3.9.4", + "resolved": "https://registry.npmjs.org/@react-stately/toggle/-/toggle-3.9.4.tgz", + "integrity": "sha512-tjWsshRJtHC+PI5NYMlnDlV/BTo1eWq6fmR6x1mXlQfKuKGTJRzhgJyaQ2mc5K+LkifD7fchOhfapHCrRlzwMg==", + "license": "Apache-2.0", + "dependencies": { + "@react-stately/utils": "^3.11.0", + "@react-types/checkbox": "^3.10.3", + "@react-types/shared": "^3.33.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-stately/tooltip": { + "version": "3.5.10", + "resolved": "https://registry.npmjs.org/@react-stately/tooltip/-/tooltip-3.5.10.tgz", + "integrity": "sha512-GauUdc6Of08Np2iUw4xx/DdgpvszS9CxJWYcRnNyAAGPLQrmniVrpJvb0EUKQTP9sUSci1SlmpvJh4SNZx26Bw==", + "license": "Apache-2.0", + "dependencies": { + "@react-stately/overlays": "^3.6.22", + "@react-types/tooltip": "^3.5.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-stately/tree": { + "version": "3.9.5", + "resolved": "https://registry.npmjs.org/@react-stately/tree/-/tree-3.9.5.tgz", + "integrity": "sha512-UpvBlzL/MpFdOepDg+cohI/zvw8DEVM8cXY/OZ8tKUXWpew1HpUglwnAI3ivm0L2k9laUIB9siW0g04ZWiH9Lg==", + "license": "Apache-2.0", + "dependencies": { + "@react-stately/collections": "^3.12.9", + "@react-stately/selection": "^3.20.8", + "@react-stately/utils": "^3.11.0", + "@react-types/shared": "^3.33.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-stately/utils": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/@react-stately/utils/-/utils-3.11.0.tgz", + "integrity": "sha512-8LZpYowJ9eZmmYLpudbo/eclIRnbhWIJZ994ncmlKlouNzKohtM8qTC6B1w1pwUbiwGdUoyzLuQbeaIor5Dvcw==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-stately/virtualizer": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/@react-stately/virtualizer/-/virtualizer-4.4.5.tgz", + "integrity": "sha512-MP33zys3nRYTk/+3BPchxlil9GrwbMksc3XuvNACeZqYEA/oEidsHffgPL+LY0iitKCmQE6pg49MI5HvBuOd2w==", + "license": "Apache-2.0", + "dependencies": { + "@react-types/shared": "^3.33.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-types/accordion": { + "version": "3.0.0-alpha.26", + "resolved": "https://registry.npmjs.org/@react-types/accordion/-/accordion-3.0.0-alpha.26.tgz", + "integrity": "sha512-OXf/kXcD2vFlEnkcZy/GG+a/1xO9BN7Uh3/5/Ceuj9z2E/WwD55YwU3GFM5zzkZ4+DMkdowHnZX37XnmbyD3Mg==", + "license": "Apache-2.0", + "dependencies": { + "@react-types/shared": "^3.27.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-types/breadcrumbs": { + "version": "3.7.17", + "resolved": "https://registry.npmjs.org/@react-types/breadcrumbs/-/breadcrumbs-3.7.17.tgz", + "integrity": "sha512-IhvVTcfli5o/UDlGACXxjlor2afGlMQA8pNR3faH0bBUay1Fmm3IWktVw9Xwmk+KraV2RTAg9e+E6p8DOQZfiw==", + "license": "Apache-2.0", + "dependencies": { + "@react-types/link": "^3.6.5", + "@react-types/shared": "^3.32.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-types/button": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/@react-types/button/-/button-3.15.0.tgz", + "integrity": "sha512-X/K2/Oeuq7Hi8nMIzx4/YlZuvWFiSOHZt27p4HmThCnNO/9IDFPmvPrpkYjWN5eN9Nuk+P5vZUb4A7QJgYpvGA==", + "license": "Apache-2.0", + "dependencies": { + "@react-types/shared": "^3.33.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-types/calendar": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/@react-types/calendar/-/calendar-3.8.2.tgz", + "integrity": "sha512-QbPFhvBQfrsz3x1Nnatr5SL+8XtbxvP4obESFuDrKmsqaaAv+jG5vwLiPTKp6Z3L+MWkCvKavBPuW+byhq+69A==", + "license": "Apache-2.0", + "dependencies": { + "@internationalized/date": "^3.11.0", + "@react-types/shared": "^3.33.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-types/checkbox": { + "version": "3.10.3", + "resolved": "https://registry.npmjs.org/@react-types/checkbox/-/checkbox-3.10.3.tgz", + "integrity": "sha512-Xw4jHG7uK352Wc18XXzdzmtr3Xjg8d2tPoBGNgsw39f92EY2UpoDAPHxYR0BaDe04lGfAn6YwVivI4OGVbjXIg==", + "license": "Apache-2.0", + "dependencies": { + "@react-types/shared": "^3.33.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-types/combobox": { + "version": "3.13.11", + "resolved": "https://registry.npmjs.org/@react-types/combobox/-/combobox-3.13.11.tgz", + "integrity": "sha512-5/tdmTAvqPpiWzEeaV7uLLSbSTkkoQ1mVz6NfKMPuw4ZBkY3lPc9JDkkQjY/JrquZao+KY4Dx8ZIoS0NqkrFrw==", + "license": "Apache-2.0", + "dependencies": { + "@react-types/shared": "^3.33.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-types/datepicker": { + "version": "3.13.4", + "resolved": "https://registry.npmjs.org/@react-types/datepicker/-/datepicker-3.13.4.tgz", + "integrity": "sha512-B5sAPoYZfluDBpgVK3ADlHbXBKRkFCQFO18Bs091IvRRwqzfoO/uf+/9UpXMw+BEF4pciLf0/kdiVQTvI3MzlA==", + "license": "Apache-2.0", + "dependencies": { + "@internationalized/date": "^3.11.0", + "@react-types/calendar": "^3.8.2", + "@react-types/overlays": "^3.9.3", + "@react-types/shared": "^3.33.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-types/dialog": { + "version": "3.5.23", + "resolved": "https://registry.npmjs.org/@react-types/dialog/-/dialog-3.5.23.tgz", + "integrity": "sha512-3tMzweYuaDOaufF5tZPMgXSA0pPFJNgdg89YRITh0wMXMG0pm+tAKVQJL1TSLLhOiLCEL08V8M/AK67dBdr2IA==", + "license": "Apache-2.0", + "dependencies": { + "@react-types/overlays": "^3.9.3", + "@react-types/shared": "^3.33.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-types/form": { + "version": "3.7.17", + "resolved": "https://registry.npmjs.org/@react-types/form/-/form-3.7.17.tgz", + "integrity": "sha512-wBFRJ3jehHw2X2Td/KwUNxFWOqXCK7OTGG9A+W3ZI3nDGyflHQpIjqKCKV1jRySs6sv7huiPckJ7ScDleCKf7w==", + "license": "Apache-2.0", + "dependencies": { + "@react-types/shared": "^3.33.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-types/grid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/@react-types/grid/-/grid-3.3.7.tgz", + "integrity": "sha512-riET3xeKPTcRWQy6hYCMxdbdL3yubPY5Ow66b2GA2rEqoYvmDBniYXAM2Oh+q9s+YgnAP7qJK++ym8NljvHiLA==", + "license": "Apache-2.0", + "dependencies": { + "@react-types/shared": "^3.33.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-types/link": { + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/@react-types/link/-/link-3.6.5.tgz", + "integrity": "sha512-+I2s3XWBEvLrzts0GnNeA84mUkwo+a7kLUWoaJkW0TOBDG7my95HFYxF9WnqKye7NgpOkCqz4s3oW96xPdIniQ==", + "license": "Apache-2.0", + "dependencies": { + "@react-types/shared": "^3.32.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-types/listbox": { + "version": "3.7.5", + "resolved": "https://registry.npmjs.org/@react-types/listbox/-/listbox-3.7.5.tgz", + "integrity": "sha512-Cn+yNip+YZBaGzu+z5xPNgmfSupnLl+li7uG5hRc+EArkk8/G42myRXz6M8wPrLM1bFAq3r85tAbyoXVmKG5Jw==", + "license": "Apache-2.0", + "dependencies": { + "@react-types/shared": "^3.33.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-types/menu": { + "version": "3.10.6", + "resolved": "https://registry.npmjs.org/@react-types/menu/-/menu-3.10.6.tgz", + "integrity": "sha512-OJTznQ4xE/VddBJU+HO4x5tceSOdyQhiHA1bREE1aHl+PcgHOUZLdMjXp1zFaGF16HhItHJaxpifJ4hzf4hWQA==", + "license": "Apache-2.0", + "dependencies": { + "@react-types/overlays": "^3.9.3", + "@react-types/shared": "^3.33.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-types/numberfield": { + "version": "3.8.17", + "resolved": "https://registry.npmjs.org/@react-types/numberfield/-/numberfield-3.8.17.tgz", + "integrity": "sha512-Q9n24OaSMXrebMowbtowmHLNclknN3XkcBIaYMwA2BIGIl+fZFnI8MERM0pG87W+wki6FepDExsDW9YxQF4pnw==", + "license": "Apache-2.0", + "dependencies": { + "@react-types/shared": "^3.33.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-types/overlays": { + "version": "3.9.3", + "resolved": "https://registry.npmjs.org/@react-types/overlays/-/overlays-3.9.3.tgz", + "integrity": "sha512-LzetThNNk8T26pQRbs1I7+isuFhdFYREy7wJCsZmbB0FnZgCukGTfOtThZWv+ry11veyVJiX68jfl4SV6ACTWA==", + "license": "Apache-2.0", + "dependencies": { + "@react-types/shared": "^3.33.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-types/progress": { + "version": "3.5.16", + "resolved": "https://registry.npmjs.org/@react-types/progress/-/progress-3.5.16.tgz", + "integrity": "sha512-I9tSdCFfvQ7gHJtm90VAKgwdTWXQgVNvLRStEc0z9h+bXBxdvZb+QuiRPERChwFQ9VkK4p4rDqaFo69nDqWkpw==", + "license": "Apache-2.0", + "dependencies": { + "@react-types/shared": "^3.32.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-types/radio": { + "version": "3.9.3", + "resolved": "https://registry.npmjs.org/@react-types/radio/-/radio-3.9.3.tgz", + "integrity": "sha512-w2BrMGIiZxYXPCnnB2NQyifwE/rRFMIW87MyawrKO9zPSbnDkqLIHAAtqmlNk2zkz1ZEWjk9opNsuztjP7D4sA==", + "license": "Apache-2.0", + "dependencies": { + "@react-types/shared": "^3.33.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-types/shared": { + "version": "3.33.0", + "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.33.0.tgz", + "integrity": "sha512-xuUpP6MyuPmJtzNOqF5pzFUIHH2YogyOQfUQHag54PRmWB7AbjuGWBUv0l1UDmz6+AbzAYGmDVAzcRDOu2PFpw==", + "license": "Apache-2.0", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-types/slider": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/@react-types/slider/-/slider-3.8.3.tgz", + "integrity": "sha512-HCDegYiUA27CcJKvFwgpR8ktFKf2nAirXqQEgVPV4uxk6JIeiRx41yqM/xPJGfmaqa7BARYARLT41yN2V8Kadg==", + "license": "Apache-2.0", + "dependencies": { + "@react-types/shared": "^3.33.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-types/switch": { + "version": "3.5.16", + "resolved": "https://registry.npmjs.org/@react-types/switch/-/switch-3.5.16.tgz", + "integrity": "sha512-6fynclkyg0wGHo3f1bwk4Z+gZZEg0Z63iP5TFhgHWdZ8W+Uq6F3u7V4IgQpuJ2NleL1c2jy2/CKdS9v06ac2Og==", + "license": "Apache-2.0", + "dependencies": { + "@react-types/shared": "^3.33.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-types/table": { + "version": "3.13.5", + "resolved": "https://registry.npmjs.org/@react-types/table/-/table-3.13.5.tgz", + "integrity": "sha512-4/CixlNmXSuJuX2IKuUlgNd/dEgNh3WvfE/bdwuI1t5JBdShP9tHIzSkgZbrzE2xX46NeA2xq4vXNO5kBv+QDA==", + "license": "Apache-2.0", + "dependencies": { + "@react-types/grid": "^3.3.7", + "@react-types/shared": "^3.33.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-types/tabs": { + "version": "3.3.21", + "resolved": "https://registry.npmjs.org/@react-types/tabs/-/tabs-3.3.21.tgz", + "integrity": "sha512-Dq9bKI62rHoI4LGGcBGlZ5s0aSwB0G4Y8o0r7hQZvf1eZWc9fmqdAdTTaGG/RUyhMIGRYWl5RRUBUuC5RmaO6w==", + "license": "Apache-2.0", + "dependencies": { + "@react-types/shared": "^3.33.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-types/textfield": { + "version": "3.12.7", + "resolved": "https://registry.npmjs.org/@react-types/textfield/-/textfield-3.12.7.tgz", + "integrity": "sha512-ddiacsS6sLFtAn2/fym7lR8nbdsLgPfelNDcsDqHiu6XUHh5TCNe8ItXHFaIiyfnKTH8uJqZrSli4wfAYNfMsw==", + "license": "Apache-2.0", + "dependencies": { + "@react-types/shared": "^3.33.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-types/tooltip": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@react-types/tooltip/-/tooltip-3.5.1.tgz", + "integrity": "sha512-h6xOAWbWUJKs9CzcCyzSPATLHq7W5dS866HkXLrtCrRDShLuzQnojZnctD2tKtNt17990hjnOhl36GUBuO5kyw==", + "license": "Apache-2.0", + "dependencies": { + "@react-types/overlays": "^3.9.3", + "@react-types/shared": "^3.33.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-rc.3", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.3.tgz", + "integrity": "sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/pluginutils": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.3.0.tgz", + "integrity": "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/pluginutils/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/pluginutils/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/@rollup/rollup-android-arm-eabi": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.57.1.tgz", + "integrity": "sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.57.1.tgz", + "integrity": "sha512-dQaAddCY9YgkFHZcFNS/606Exo8vcLHwArFZ7vxXq4rigo2bb494/xKMMwRRQW6ug7Js6yXmBZhSBRuBvCCQ3w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.57.1.tgz", + "integrity": "sha512-crNPrwJOrRxagUYeMn/DZwqN88SDmwaJ8Cvi/TN1HnWBU7GwknckyosC2gd0IqYRsHDEnXf328o9/HC6OkPgOg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.57.1.tgz", + "integrity": "sha512-Ji8g8ChVbKrhFtig5QBV7iMaJrGtpHelkB3lsaKzadFBe58gmjfGXAOfI5FV0lYMH8wiqsxKQ1C9B0YTRXVy4w==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.57.1.tgz", + "integrity": "sha512-R+/WwhsjmwodAcz65guCGFRkMb4gKWTcIeLy60JJQbXrJ97BOXHxnkPFrP+YwFlaS0m+uWJTstrUA9o+UchFug==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.57.1.tgz", + "integrity": "sha512-IEQTCHeiTOnAUC3IDQdzRAGj3jOAYNr9kBguI7MQAAZK3caezRrg0GxAb6Hchg4lxdZEI5Oq3iov/w/hnFWY9Q==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.57.1.tgz", + "integrity": "sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.57.1.tgz", + "integrity": "sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.57.1.tgz", + "integrity": "sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.57.1.tgz", + "integrity": "sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.57.1.tgz", + "integrity": "sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.57.1.tgz", + "integrity": "sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.57.1.tgz", + "integrity": "sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.57.1.tgz", + "integrity": "sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.57.1.tgz", + "integrity": "sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.57.1.tgz", + "integrity": "sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.57.1.tgz", + "integrity": "sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.57.1.tgz", + "integrity": "sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.57.1.tgz", + "integrity": "sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.57.1.tgz", + "integrity": "sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.57.1.tgz", + "integrity": "sha512-4wYoDpNg6o/oPximyc/NG+mYUejZrCU2q+2w6YZqrAs2UcNUChIZXjtafAiiZSUc7On8v5NyNj34Kzj/Ltk6dQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.57.1.tgz", + "integrity": "sha512-O54mtsV/6LW3P8qdTcamQmuC990HDfR71lo44oZMZlXU4tzLrbvTii87Ni9opq60ds0YzuAlEr/GNwuNluZyMQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.57.1.tgz", + "integrity": "sha512-P3dLS+IerxCT/7D2q2FYcRdWRl22dNbrbBEtxdWhXrfIMPP9lQhb5h4Du04mdl5Woq05jVCDPCMF7Ub0NAjIew==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.57.1.tgz", + "integrity": "sha512-VMBH2eOOaKGtIJYleXsi2B8CPVADrh+TyNxJ4mWPnKfLB/DBUmzW+5m1xUrcwWoMfSLagIRpjUFeW5CO5hyciQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.57.1.tgz", + "integrity": "sha512-mxRFDdHIWRxg3UfIIAwCm6NzvxG0jDX/wBN6KsQFTvKFqqg9vTrWUE68qEjHt19A5wwx5X5aUi2zuZT7YR0jrA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@svgr/babel-plugin-add-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz", + "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz", + "integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-dynamic-title": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz", + "integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-em-dimensions": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz", + "integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-react-native-svg": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.1.0.tgz", + "integrity": "sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-svg-component": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz", + "integrity": "sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-preset": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-8.1.0.tgz", + "integrity": "sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@svgr/babel-plugin-add-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-empty-expression": "8.0.0", + "@svgr/babel-plugin-replace-jsx-attribute-value": "8.0.0", + "@svgr/babel-plugin-svg-dynamic-title": "8.0.0", + "@svgr/babel-plugin-svg-em-dimensions": "8.0.0", + "@svgr/babel-plugin-transform-react-native-svg": "8.1.0", + "@svgr/babel-plugin-transform-svg-component": "8.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/core": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", + "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "camelcase": "^6.2.0", + "cosmiconfig": "^8.1.3", + "snake-case": "^3.0.4" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/hast-util-to-babel-ast": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz", + "integrity": "sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.21.3", + "entities": "^4.4.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/hast-util-to-babel-ast/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/@svgr/plugin-jsx": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-8.1.0.tgz", + "integrity": "sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "@svgr/hast-util-to-babel-ast": "8.0.0", + "svg-parser": "^2.0.4" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "*" + } + }, + "node_modules/@swc/helpers": { + "version": "0.5.18", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.18.tgz", + "integrity": "sha512-TXTnIcNJQEKwThMMqBXsZ4VGAza6bvN4pa41Rkqoio6QBKMvo+5lexeTMScGCIxtzgQJzElcvIltani+adC5PQ==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@tailwindcss/node": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.18.tgz", + "integrity": "sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/remapping": "^2.3.4", + "enhanced-resolve": "^5.18.3", + "jiti": "^2.6.1", + "lightningcss": "1.30.2", + "magic-string": "^0.30.21", + "source-map-js": "^1.2.1", + "tailwindcss": "4.1.18" + } + }, + "node_modules/@tailwindcss/oxide": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.18.tgz", + "integrity": "sha512-EgCR5tTS5bUSKQgzeMClT6iCY3ToqE1y+ZB0AKldj809QXk1Y+3jB0upOYZrn9aGIzPtUsP7sX4QQ4XtjBB95A==", + "license": "MIT", + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@tailwindcss/oxide-android-arm64": "4.1.18", + "@tailwindcss/oxide-darwin-arm64": "4.1.18", + "@tailwindcss/oxide-darwin-x64": "4.1.18", + "@tailwindcss/oxide-freebsd-x64": "4.1.18", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.18", + "@tailwindcss/oxide-linux-arm64-gnu": "4.1.18", + "@tailwindcss/oxide-linux-arm64-musl": "4.1.18", + "@tailwindcss/oxide-linux-x64-gnu": "4.1.18", + "@tailwindcss/oxide-linux-x64-musl": "4.1.18", + "@tailwindcss/oxide-wasm32-wasi": "4.1.18", + "@tailwindcss/oxide-win32-arm64-msvc": "4.1.18", + "@tailwindcss/oxide-win32-x64-msvc": "4.1.18" + } + }, + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.18.tgz", + "integrity": "sha512-dJHz7+Ugr9U/diKJA0W6N/6/cjI+ZTAoxPf9Iz9BFRF2GzEX8IvXxFIi/dZBloVJX/MZGvRuFA9rqwdiIEZQ0Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-darwin-arm64": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.18.tgz", + "integrity": "sha512-Gc2q4Qhs660bhjyBSKgq6BYvwDz4G+BuyJ5H1xfhmDR3D8HnHCmT/BSkvSL0vQLy/nkMLY20PQ2OoYMO15Jd0A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-darwin-x64": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.18.tgz", + "integrity": "sha512-FL5oxr2xQsFrc3X9o1fjHKBYBMD1QZNyc1Xzw/h5Qu4XnEBi3dZn96HcHm41c/euGV+GRiXFfh2hUCyKi/e+yw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-freebsd-x64": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.18.tgz", + "integrity": "sha512-Fj+RHgu5bDodmV1dM9yAxlfJwkkWvLiRjbhuO2LEtwtlYlBgiAT4x/j5wQr1tC3SANAgD+0YcmWVrj8R9trVMA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.18.tgz", + "integrity": "sha512-Fp+Wzk/Ws4dZn+LV2Nqx3IilnhH51YZoRaYHQsVq3RQvEl+71VGKFpkfHrLM/Li+kt5c0DJe/bHXK1eHgDmdiA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.18.tgz", + "integrity": "sha512-S0n3jboLysNbh55Vrt7pk9wgpyTTPD0fdQeh7wQfMqLPM/Hrxi+dVsLsPrycQjGKEQk85Kgbx+6+QnYNiHalnw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.18.tgz", + "integrity": "sha512-1px92582HkPQlaaCkdRcio71p8bc8i/ap5807tPRDK/uw953cauQBT8c5tVGkOwrHMfc2Yh6UuxaH4vtTjGvHg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.18.tgz", + "integrity": "sha512-v3gyT0ivkfBLoZGF9LyHmts0Isc8jHZyVcbzio6Wpzifg/+5ZJpDiRiUhDLkcr7f/r38SWNe7ucxmGW3j3Kb/g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.18.tgz", + "integrity": "sha512-bhJ2y2OQNlcRwwgOAGMY0xTFStt4/wyU6pvI6LSuZpRgKQwxTec0/3Scu91O8ir7qCR3AuepQKLU/kX99FouqQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.18.tgz", + "integrity": "sha512-LffYTvPjODiP6PT16oNeUQJzNVyJl1cjIebq/rWWBF+3eDst5JGEFSc5cWxyRCJ0Mxl+KyIkqRxk1XPEs9x8TA==", + "bundleDependencies": [ + "@napi-rs/wasm-runtime", + "@emnapi/core", + "@emnapi/runtime", + "@tybys/wasm-util", + "@emnapi/wasi-threads", + "tslib" + ], + "cpu": [ + "wasm32" + ], + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1", + "@emnapi/wasi-threads": "^1.1.0", + "@napi-rs/wasm-runtime": "^1.1.0", + "@tybys/wasm-util": "^0.10.1", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.18.tgz", + "integrity": "sha512-HjSA7mr9HmC8fu6bdsZvZ+dhjyGCLdotjVOgLA2vEqxEBZaQo9YTX4kwgEvPCpRh8o4uWc4J/wEoFzhEmjvPbA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.18.tgz", + "integrity": "sha512-bJWbyYpUlqamC8dpR7pfjA0I7vdF6t5VpUGMWRkXVE3AXgIZjYUYAK7II1GNaxR8J1SSrSrppRar8G++JekE3Q==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/vite": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.18.tgz", + "integrity": "sha512-jVA+/UpKL1vRLg6Hkao5jldawNmRo7mQYrZtNHMIVpLfLhDml5nMRUo/8MwoX2vNXvnaXNNMedrMfMugAVX1nA==", + "license": "MIT", + "dependencies": { + "@tailwindcss/node": "4.1.18", + "@tailwindcss/oxide": "4.1.18", + "tailwindcss": "4.1.18" + }, + "peerDependencies": { + "vite": "^5.2.0 || ^6 || ^7" + } + }, + "node_modules/@tanstack/react-virtual": { + "version": "3.11.3", + "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.11.3.tgz", + "integrity": "sha512-vCU+OTylXN3hdC8RKg68tPlBPjjxtzon7Ys46MgrSLE+JhSjSTPvoQifV6DQJeJmA8Q3KT6CphJbejupx85vFw==", + "license": "MIT", + "dependencies": { + "@tanstack/virtual-core": "3.11.3" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "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/@tanstack/virtual-core": { + "version": "3.11.3", + "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.11.3.tgz", + "integrity": "sha512-v2mrNSnMwnPJtcVqNvV0c5roGCBqeogN8jDtgtuHCphdwBasOZ17x8UV8qpHUh+u0MLfX43c0uUHKje0s+Zb0w==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@testing-library/dom": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.1.tgz", + "integrity": "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "picocolors": "1.1.1", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@testing-library/jest-dom": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.9.1.tgz", + "integrity": "sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@adobe/css-tools": "^4.4.0", + "aria-query": "^5.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.6.3", + "picocolors": "^1.1.1", + "redent": "^3.0.0" + }, + "engines": { + "node": ">=14", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/dom-accessibility-api": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", + "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@testing-library/react": { + "version": "16.3.2", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.3.2.tgz", + "integrity": "sha512-XU5/SytQM+ykqMnAnvB2umaJNIOsLF3PVv//1Ew4CTcpz0/BRyy/af40qqrt7SjKpDdT1saBMc42CUok5gaw+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.5" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@testing-library/dom": "^10.0.0", + "@types/react": "^18.0.0 || ^19.0.0", + "@types/react-dom": "^18.0.0 || ^19.0.0", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@testing-library/user-event": { + "version": "14.6.1", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.6.1.tgz", + "integrity": "sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12", + "npm": ">=6" + }, + "peerDependencies": { + "@testing-library/dom": ">=7.21.4" + } + }, + "node_modules/@types/aria-query": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "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" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "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.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.28.2" + } + }, + "node_modules/@types/chai": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" + } + }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "24.10.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.13.tgz", + "integrity": "sha512-oH72nZRfDv9lADUBSo104Aq7gPHpQZc4BTx38r9xf9pg5LfP6EzSyH2n7qFmmxRQXh7YlUXODcYsg6PuTDSxGg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.16.0" + } + }, + "node_modules/@types/react": { + "version": "19.2.14", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", + "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", + "dev": true, + "license": "MIT", + "dependencies": { + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", + "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.2.0" + } + }, + "node_modules/@types/statuses": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/statuses/-/statuses-2.0.6.tgz", + "integrity": "sha512-xMAgYwceFhRA2zY+XbEA7mxYbA093wdiW8Vu6gZPGWy9cmOyU9XesH1tNcEWsKFd5Vzrqx5T3D38PWx1FIIXkA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@vitejs/plugin-react": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.1.4.tgz", + "integrity": "sha512-VIcFLdRi/VYRU8OL/puL7QXMYafHmqOnwTZY50U1JPlCNj30PxCMx65c494b1K9be9hX83KVt0+gTEwTWLqToA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.29.0", + "@babel/plugin-transform-react-jsx-self": "^7.27.1", + "@babel/plugin-transform-react-jsx-source": "^7.27.1", + "@rolldown/pluginutils": "1.0.0-rc.3", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.18.0" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" + } + }, + "node_modules/@vitest/coverage-v8": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.0.18.tgz", + "integrity": "sha512-7i+N2i0+ME+2JFZhfuz7Tg/FqKtilHjGyGvoHYQ6iLV0zahbsJ9sljC9OcFcPDbhYKCet+sG8SsVqlyGvPflZg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@bcoe/v8-coverage": "^1.0.2", + "@vitest/utils": "4.0.18", + "ast-v8-to-istanbul": "^0.3.10", + "istanbul-lib-coverage": "^3.2.2", + "istanbul-lib-report": "^3.0.1", + "istanbul-reports": "^3.2.0", + "magicast": "^0.5.1", + "obug": "^2.1.1", + "std-env": "^3.10.0", + "tinyrainbow": "^3.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@vitest/browser": "4.0.18", + "vitest": "4.0.18" + }, + "peerDependenciesMeta": { + "@vitest/browser": { + "optional": true + } + } + }, + "node_modules/@vitest/expect": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.0.18.tgz", + "integrity": "sha512-8sCWUyckXXYvx4opfzVY03EOiYVxyNrHS5QxX3DAIi5dpJAAkyJezHCP77VMX4HKA2LDT/Jpfo8i2r5BE3GnQQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.0.0", + "@types/chai": "^5.2.2", + "@vitest/spy": "4.0.18", + "@vitest/utils": "4.0.18", + "chai": "^6.2.1", + "tinyrainbow": "^3.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.0.18.tgz", + "integrity": "sha512-HhVd0MDnzzsgevnOWCBj5Otnzobjy5wLBe4EdeeFGv8luMsGcYqDuFRMcttKWZA5vVO8RFjexVovXvAM4JoJDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "4.0.18", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.21" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^6.0.0 || ^7.0.0-0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/pretty-format": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.0.18.tgz", + "integrity": "sha512-P24GK3GulZWC5tz87ux0m8OADrQIUVDPIjjj65vBXYG17ZeU3qD7r+MNZ1RNv4l8CGU2vtTRqixrOi9fYk/yKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^3.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.0.18.tgz", + "integrity": "sha512-rpk9y12PGa22Jg6g5M3UVVnTS7+zycIGk9ZNGN+m6tZHKQb7jrP7/77WfZy13Y/EUDd52NDsLRQhYKtv7XfPQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "4.0.18", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.0.18.tgz", + "integrity": "sha512-PCiV0rcl7jKQjbgYqjtakly6T1uwv/5BQ9SwBLekVg/EaYeQFPiXcgrC2Y7vDMA8dM1SUEAEV82kgSQIlXNMvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.0.18", + "magic-string": "^0.30.21", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.0.18.tgz", + "integrity": "sha512-cbQt3PTSD7P2OARdVW3qWER5EGq7PHlvE+QfzSC0lbwO+xnt7+XH06ZzFjFRgzUX//JmpxrCu92VdwvEPlWSNw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.0.18.tgz", + "integrity": "sha512-msMRKLMVLWygpK3u2Hybgi4MNjcYJvwTb0Ru09+fOyCXIgT5raYP041DRRdiJiI3k/2U6SEbAETB3YtBrUkCFA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.0.18", + "tinyrainbow": "^3.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/ansi-escapes": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.3.0.tgz", + "integrity": "sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "environment": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "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/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/ast-v8-to-istanbul": { + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-0.3.11.tgz", + "integrity": "sha512-Qya9fkoofMjCBNVdWINMjB5KZvkYfaO9/anwkWnjxibpWUxo5iHl2sOdP7/uAqaRuUYuoo8rDwnbaaKVFxoUvw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.31", + "estree-walker": "^3.0.3", + "js-tokens": "^10.0.0" + } + }, + "node_modules/ast-v8-to-istanbul/node_modules/js-tokens": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-10.0.0.tgz", + "integrity": "sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.5.tgz", + "integrity": "sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.11", + "form-data": "^4.0.5", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/baseline-browser-mapping": { + "version": "2.9.19", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.19.tgz", + "integrity": "sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, + "node_modules/bidi-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz", + "integrity": "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==", + "dev": true, + "license": "MIT", + "dependencies": { + "require-from-string": "^2.0.2" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/callsites": { + "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/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001770", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001770.tgz", + "integrity": "sha512-x/2CLQ1jHENRbHg5PSId2sXq1CIO1CISvwWAj027ltMVG2UNgW+w9oH2+HzgEIRFembL8bUlXtfbBHR1fCg2xw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chai": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", + "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "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/chalk/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": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/classnames": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", + "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==", + "license": "MIT" + }, + "node_modules/cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "restore-cursor": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-5.1.1.tgz", + "integrity": "sha512-SroPvNHxUnk+vIW/dOSfNqdy1sPEFkrTk6TUtqLCnBlo3N7TNYYkzzN7uSD6+jVjrdO4+p8nH7JzH6cIvUem6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "slice-ansi": "^7.1.0", + "string-width": "^8.0.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 12" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/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==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?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": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1", + "color-string": "^1.9.0" + }, + "engines": { + "node": ">=12.5.0" + } + }, + "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==", + "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==", + "license": "MIT" + }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "license": "MIT", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "node_modules/color2k": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/color2k/-/color2k-2.0.3.tgz", + "integrity": "sha512-zW190nQTIoXcGCaU08DvVNFTmQhUpnJfVuAKfWqUQkflXKpaDdpaYoM0iluLS9lgJNHyBF58KKA2FBEwkD7wog==", + "license": "MIT" + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz", + "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/compute-scroll-into-view": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-3.1.1.tgz", + "integrity": "sha512-VRhuHOLoKYOy4UbilLbUzbYg93XLjv2PncJC50EuTWPA3gaja1UjBsUP/D/9/juV3vQFr6XBEzn9KCAHdUvOHw==", + "license": "MIT" + }, + "node_modules/concurrently": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.2.1.tgz", + "integrity": "sha512-fsfrO0MxV64Znoy8/l1vVIjjHa29SZyyqPgQBwhiDcaW8wJc2W3XWVOGx4M3oJBnv/zdUZIIp1gDeS98GzP8Ng==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "4.1.2", + "rxjs": "7.8.2", + "shell-quote": "1.8.3", + "supports-color": "8.1.1", + "tree-kill": "1.2.2", + "yargs": "17.7.2" + }, + "bin": { + "conc": "dist/bin/concurrently.js", + "concurrently": "dist/bin/concurrently.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cookie": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", + "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/css-tree": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.1.0.tgz", + "integrity": "sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "mdn-data": "2.12.2", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/css.escape": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cssstyle": { + "version": "5.3.7", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-5.3.7.tgz", + "integrity": "sha512-7D2EPVltRrsTkhpQmksIu+LxeWAIEk6wRDMJ1qljlv+CKHJM+cJLlfhWIzNA44eAsHXSNe3+vO6DW1yCYx8SuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@asamuzakjp/css-color": "^4.1.1", + "@csstools/css-syntax-patches-for-csstree": "^1.0.21", + "css-tree": "^3.1.0", + "lru-cache": "^11.2.4" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/cssstyle/node_modules/lru-cache": { + "version": "11.2.6", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz", + "integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/data-urls": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-6.0.1.tgz", + "integrity": "sha512-euIQENZg6x8mj3fO6o9+fOW8MimUI4PpD/fZBhJfeioZVy9TUpM4UY7KjQNVZFlqwJ0UdzRDzkycB997HEq1BQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-mimetype": "^5.0.0", + "whatwg-url": "^15.1.0" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/data-urls/node_modules/whatwg-mimetype": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-5.0.0.tgz", + "integrity": "sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decimal.js": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", + "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", + "license": "MIT" + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/dom-accessibility-api": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", + "dev": true, + "license": "MIT" + }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.286", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.286.tgz", + "integrity": "sha512-9tfDXhJ4RKFNerfjdCcZfufu49vg620741MNs26a9+bhLThdB+plgMeou98CAaHu/WATj2iHOOHTp1hWtABj2A==", + "dev": true, + "license": "ISC" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/enhanced-resolve": { + "version": "5.19.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.19.0.tgz", + "integrity": "sha512-phv3E1Xl4tQOShqSte26C7Fl84EwUdZsyOuSSk9qtAGyyQs2s3jJzComh+Abf4g187lUUAvH+H26omrqia2aGg==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.3.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/error-ex/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==", + "dev": true, + "license": "MIT" + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-module-lexer": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "dev": true, + "license": "MIT" + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz", + "integrity": "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.3", + "@esbuild/android-arm": "0.27.3", + "@esbuild/android-arm64": "0.27.3", + "@esbuild/android-x64": "0.27.3", + "@esbuild/darwin-arm64": "0.27.3", + "@esbuild/darwin-x64": "0.27.3", + "@esbuild/freebsd-arm64": "0.27.3", + "@esbuild/freebsd-x64": "0.27.3", + "@esbuild/linux-arm": "0.27.3", + "@esbuild/linux-arm64": "0.27.3", + "@esbuild/linux-ia32": "0.27.3", + "@esbuild/linux-loong64": "0.27.3", + "@esbuild/linux-mips64el": "0.27.3", + "@esbuild/linux-ppc64": "0.27.3", + "@esbuild/linux-riscv64": "0.27.3", + "@esbuild/linux-s390x": "0.27.3", + "@esbuild/linux-x64": "0.27.3", + "@esbuild/netbsd-arm64": "0.27.3", + "@esbuild/netbsd-x64": "0.27.3", + "@esbuild/openbsd-arm64": "0.27.3", + "@esbuild/openbsd-x64": "0.27.3", + "@esbuild/openharmony-arm64": "0.27.3", + "@esbuild/sunos-x64": "0.27.3", + "@esbuild/win32-arm64": "0.27.3", + "@esbuild/win32-ia32": "0.27.3", + "@esbuild/win32-x64": "0.27.3" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/eventemitter3": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", + "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/expect-type": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", + "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/framer-motion": { + "version": "12.34.0", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.34.0.tgz", + "integrity": "sha512-+/H49owhzkzQyxtn7nZeF4kdH++I2FWrESQ184Zbcw5cEqNHYkE5yxWxcTLSj5lNx3NWdbIRy5FHqUvetD8FWg==", + "license": "MIT", + "dependencies": { + "motion-dom": "^12.34.0", + "motion-utils": "^12.29.2", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "@emotion/is-prop-valid": "*", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/is-prop-valid": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "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", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-east-asian-width": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz", + "integrity": "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/globrex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz", + "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==", + "dev": true, + "license": "MIT" + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, + "node_modules/graphql": { + "version": "16.12.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.12.0.tgz", + "integrity": "sha512-DKKrynuQRne0PNpEbzuEdHlYOMksHSUI8Zc9Unei5gTsMNA2/vMpoMz/yKba50pejK56qj98qM0SjYxAKi13gQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/headers-polyfill": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/headers-polyfill/-/headers-polyfill-4.0.3.tgz", + "integrity": "sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/html-encoding-sniffer": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-6.0.0.tgz", + "integrity": "sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@exodus/bytes": "^1.6.0" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true, + "license": "MIT" + }, + "node_modules/html-parse-stringify": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz", + "integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==", + "license": "MIT", + "dependencies": { + "void-elements": "3.1.0" + } + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/husky": { + "version": "9.1.7", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", + "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", + "dev": true, + "license": "MIT", + "bin": { + "husky": "bin.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, + "node_modules/i18next": { + "version": "25.8.10", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-25.8.10.tgz", + "integrity": "sha512-CtPJLMAz1G8sxo+mIzfBjGgLxWs7d6WqIjlmmv9BTsOat4pJIfwZ8cm07n3kFS6bP9c6YwsYutYrwsEeJVBo2g==", + "funding": [ + { + "type": "individual", + "url": "https://locize.com" + }, + { + "type": "individual", + "url": "https://locize.com/i18next.html" + }, + { + "type": "individual", + "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" + } + ], + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.4" + }, + "peerDependencies": { + "typescript": "^5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/input-otp": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/input-otp/-/input-otp-1.4.1.tgz", + "integrity": "sha512-+yvpmKYKHi9jIGngxagY9oWiiblPB7+nEO75F2l2o4vs+6vpPZZmUl4tBNYuTCvQjhvEIbdNeJu70bhfYP2nbw==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc" + } + }, + "node_modules/intl-messageformat": { + "version": "10.7.18", + "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-10.7.18.tgz", + "integrity": "sha512-m3Ofv/X/tV8Y3tHXLohcuVuhWKo7BBq62cqY15etqmLxg2DZ34AGGgQDeR+SCta2+zICb1NX83af0GJmbQ1++g==", + "license": "BSD-3-Clause", + "dependencies": { + "@formatjs/ecma402-abstract": "2.3.6", + "@formatjs/fast-memoize": "2.2.7", + "@formatjs/icu-messageformat-parser": "2.11.4", + "tslib": "^2.8.0" + } + }, + "node_modules/is-arrayish": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.4.tgz", + "integrity": "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==", + "license": "MIT" + }, + "node_modules/is-fullwidth-code-point": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", + "integrity": "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.3.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-node-process": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-node-process/-/is-node-process-1.2.0.tgz", + "integrity": "sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report/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": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-reports": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jiti": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", + "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "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==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsdom": { + "version": "27.4.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-27.4.0.tgz", + "integrity": "sha512-mjzqwWRD9Y1J1KUi7W97Gja1bwOOM5Ug0EZ6UDK3xS7j7mndrkwozHtSblfomlzyB4NepioNt+B2sOSzczVgtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@acemir/cssom": "^0.9.28", + "@asamuzakjp/dom-selector": "^6.7.6", + "@exodus/bytes": "^1.6.0", + "cssstyle": "^5.3.4", + "data-urls": "^6.0.0", + "decimal.js": "^10.6.0", + "html-encoding-sniffer": "^6.0.0", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.6", + "is-potential-custom-element-name": "^1.0.1", + "parse5": "^8.0.0", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^6.0.0", + "w3c-xmlserializer": "^5.0.0", + "webidl-conversions": "^8.0.0", + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^15.1.0", + "ws": "^8.18.3", + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + }, + "peerDependencies": { + "canvas": "^3.0.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jsesc": { + "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" + }, + "engines": { + "node": ">=6" + } + }, + "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==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/lightningcss": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.2.tgz", + "integrity": "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==", + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.30.2", + "lightningcss-darwin-arm64": "1.30.2", + "lightningcss-darwin-x64": "1.30.2", + "lightningcss-freebsd-x64": "1.30.2", + "lightningcss-linux-arm-gnueabihf": "1.30.2", + "lightningcss-linux-arm64-gnu": "1.30.2", + "lightningcss-linux-arm64-musl": "1.30.2", + "lightningcss-linux-x64-gnu": "1.30.2", + "lightningcss-linux-x64-musl": "1.30.2", + "lightningcss-win32-arm64-msvc": "1.30.2", + "lightningcss-win32-x64-msvc": "1.30.2" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.30.2.tgz", + "integrity": "sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.2.tgz", + "integrity": "sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.2.tgz", + "integrity": "sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.2.tgz", + "integrity": "sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.2.tgz", + "integrity": "sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==", + "cpu": [ + "arm" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.2.tgz", + "integrity": "sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.2.tgz", + "integrity": "sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.2.tgz", + "integrity": "sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.2.tgz", + "integrity": "sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.2.tgz", + "integrity": "sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.2.tgz", + "integrity": "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "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==", + "dev": true, + "license": "MIT" + }, + "node_modules/lint-staged": { + "version": "16.2.7", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-16.2.7.tgz", + "integrity": "sha512-lDIj4RnYmK7/kXMya+qJsmkRFkGolciXjrsZ6PC25GdTfWOAWetR0ZbsNXRAj1EHHImRSalc+whZFg56F5DVow==", + "dev": true, + "license": "MIT", + "dependencies": { + "commander": "^14.0.2", + "listr2": "^9.0.5", + "micromatch": "^4.0.8", + "nano-spawn": "^2.0.0", + "pidtree": "^0.6.0", + "string-argv": "^0.3.2", + "yaml": "^2.8.1" + }, + "bin": { + "lint-staged": "bin/lint-staged.js" + }, + "engines": { + "node": ">=20.17" + }, + "funding": { + "url": "https://opencollective.com/lint-staged" + } + }, + "node_modules/listr2": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-9.0.5.tgz", + "integrity": "sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "cli-truncate": "^5.0.0", + "colorette": "^2.0.20", + "eventemitter3": "^5.0.1", + "log-update": "^6.1.0", + "rfdc": "^1.4.1", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/log-update": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", + "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-escapes": "^7.0.0", + "cli-cursor": "^5.0.0", + "slice-ansi": "^7.1.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/lz-string": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "dev": true, + "license": "MIT", + "bin": { + "lz-string": "bin/bin.js" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/magicast": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.2.tgz", + "integrity": "sha512-E3ZJh4J3S9KfwdjZhe2afj6R9lGIN5Pher1pF39UGrXRqq/VDaGVIGN13BjHd2u8B61hArAGOnso7nBOouW3TQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", + "source-map-js": "^1.2.1" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mdn-data": { + "version": "2.12.2", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.12.2.tgz", + "integrity": "sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/motion-dom": { + "version": "12.34.0", + "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.34.0.tgz", + "integrity": "sha512-Lql3NuEcScRDxTAO6GgUsRHBZOWI/3fnMlkMcH5NftzcN37zJta+bpbMAV9px4Nj057TuvRooMK7QrzMCgtz6Q==", + "license": "MIT", + "dependencies": { + "motion-utils": "^12.29.2" + } + }, + "node_modules/motion-utils": { + "version": "12.29.2", + "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.29.2.tgz", + "integrity": "sha512-G3kc34H2cX2gI63RqU+cZq+zWRRPSsNIOjpdl9TN4AQwC4sgwYPl/Q/Obf/d53nOm569T0fYK+tcoSV50BWx8A==", + "license": "MIT" + }, + "node_modules/ms": { + "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/msw": { + "version": "2.12.10", + "resolved": "https://registry.npmjs.org/msw/-/msw-2.12.10.tgz", + "integrity": "sha512-G3VUymSE0/iegFnuipujpwyTM2GuZAKXNeerUSrG2+Eg391wW63xFs5ixWsK9MWzr1AGoSkYGmyAzNgbR3+urw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "@inquirer/confirm": "^5.0.0", + "@mswjs/interceptors": "^0.41.2", + "@open-draft/deferred-promise": "^2.2.0", + "@types/statuses": "^2.0.6", + "cookie": "^1.0.2", + "graphql": "^16.12.0", + "headers-polyfill": "^4.0.2", + "is-node-process": "^1.2.0", + "outvariant": "^1.4.3", + "path-to-regexp": "^6.3.0", + "picocolors": "^1.1.1", + "rettime": "^0.10.1", + "statuses": "^2.0.2", + "strict-event-emitter": "^0.5.1", + "tough-cookie": "^6.0.0", + "type-fest": "^5.2.0", + "until-async": "^3.0.2", + "yargs": "^17.7.2" + }, + "bin": { + "msw": "cli/index.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/mswjs" + }, + "peerDependencies": { + "typescript": ">= 4.8.x" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/mute-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", + "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/nano-spawn": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/nano-spawn/-/nano-spawn-2.0.0.tgz", + "integrity": "sha512-tacvGzUY5o2D8CBh2rrwxyNojUsZNU2zjNTzKQrkgGJQTbGAfArVWXSKMBokBeeg6C7OLRGUEyoFlYbfeWQIqw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/nano-spawn?sponsor=1" + } + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node_modules/node-releases": { + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/obug": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", + "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==", + "dev": true, + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], + "license": "MIT" + }, + "node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/outvariant": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/outvariant/-/outvariant-1.4.3.tgz", + "integrity": "sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==", + "dev": true, + "license": "MIT" + }, + "node_modules/parent-module": { + "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" + }, + "engines": { + "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==", + "dev": true, + "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/parse5": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.0.tgz", + "integrity": "sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA==", + "dev": true, + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/path-to-regexp": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", + "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", + "dev": true, + "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" + } + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", + "dev": true, + "license": "MIT", + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/playwright": { + "version": "1.58.2", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.58.2.tgz", + "integrity": "sha512-vA30H8Nvkq/cPBnNw4Q8TWz1EJyqgpuinBcHET0YVJVFldr8JDNiU9LaWAE1KqSkRYazuaBhTpB5ZzShOezQ6A==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.58.2" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.58.2", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.58.2.tgz", + "integrity": "sha512-yZkEtftgwS8CsfYo7nm0KE8jsvm6i/PTgVtB8DL726wNf6H2IMsDuxCpJj59KDaxCtSnrWan2AeDqM7JBaultg==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, + "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" + } + }, + "node_modules/qrcode.react": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/qrcode.react/-/qrcode.react-4.2.0.tgz", + "integrity": "sha512-QpgqWi8rD9DsS9EP3z7BT+5lY5SFhsqGjpgW5DY/i3mK4M9DTBNz3ErMi8BWYEfI3L0d8GIbGmcdFAS1uIRGjA==", + "license": "ISC", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/react": { + "version": "19.2.4", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", + "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.2.4", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz", + "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.4" + } + }, + "node_modules/react-hook-form": { + "version": "7.71.1", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.71.1.tgz", + "integrity": "sha512-9SUJKCGKo8HUSsCO+y0CtqkqI5nNuaDqTxyqPsZPqIwudpj4rCrAz/jZV+jn57bx5gtZKOh3neQu94DXMc+w5w==", + "license": "MIT", + "engines": { + "node": ">=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/react-hook-form" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17 || ^18 || ^19" + } + }, + "node_modules/react-i18next": { + "version": "16.5.4", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-16.5.4.tgz", + "integrity": "sha512-6yj+dcfMncEC21QPhOTsW8mOSO+pzFmT6uvU7XXdvM/Cp38zJkmTeMeKmTrmCMD5ToT79FmiE/mRWiYWcJYW4g==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.4", + "html-parse-stringify": "^3.0.1", + "use-sync-external-store": "^1.6.0" + }, + "peerDependencies": { + "i18next": ">= 25.6.2", + "react": ">= 16.8.0", + "typescript": "^5" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true, + "license": "MIT" + }, + "node_modules/react-refresh": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.18.0.tgz", + "integrity": "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-router": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.13.0.tgz", + "integrity": "sha512-PZgus8ETambRT17BUm/LL8lX3Of+oiLaPuVTRH3l1eLvSPpKO3AvhAEb5N7ihAFZQrYDqkvvWfFh9p0z9VsjLw==", + "license": "MIT", + "dependencies": { + "cookie": "^1.0.1", + "set-cookie-parser": "^2.6.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, + "node_modules/react-textarea-autosize": { + "version": "8.5.9", + "resolved": "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-8.5.9.tgz", + "integrity": "sha512-U1DGlIQN5AwgjTyOEnI1oCcMuEr1pv1qOtklB2l4nyMGbHzWrI0eFsYK0zos2YWqAolJyG0IWJaqWmWj5ETh0A==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.20.13", + "use-composed-ref": "^1.3.0", + "use-latest": "^1.2.1" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/react-toastify": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-11.0.5.tgz", + "integrity": "sha512-EpqHBGvnSTtHYhCPLxML05NLY2ZX0JURbAdNYa6BUkk+amz4wbKBQvoKQAB0ardvSarUBuY4Q4s1sluAzZwkmA==", + "license": "MIT", + "dependencies": { + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": "^18 || ^19", + "react-dom": "^18 || ^19" + } + }, + "node_modules/react-tooltip": { + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-5.30.0.tgz", + "integrity": "sha512-Yn8PfbgQ/wmqnL7oBpz1QiDaLKrzZMdSUUdk7nVeGTwzbxCAJiJzR4VSYW+eIO42F1INt57sPUmpgKv0KwJKtg==", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.6.1", + "classnames": "^2.3.0" + }, + "peerDependencies": { + "react": ">=16.14.0", + "react-dom": ">=16.14.0" + } + }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resize-observer-polyfill": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", + "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==", + "dev": true, + "license": "MIT" + }, + "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" + } + }, + "node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "dev": true, + "license": "MIT", + "dependencies": { + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/rettime": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/rettime/-/rettime-0.10.1.tgz", + "integrity": "sha512-uyDrIlUEH37cinabq0AX4QbgV4HbFZ/gqoiunWQ1UqBtRvTTytwhNYjE++pO/MjPTZL5KQCf2bEoJ/BJNVQ5Kw==", + "dev": true, + "license": "MIT" + }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "dev": true, + "license": "MIT" + }, + "node_modules/rollup": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.57.1.tgz", + "integrity": "sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A==", + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.57.1", + "@rollup/rollup-android-arm64": "4.57.1", + "@rollup/rollup-darwin-arm64": "4.57.1", + "@rollup/rollup-darwin-x64": "4.57.1", + "@rollup/rollup-freebsd-arm64": "4.57.1", + "@rollup/rollup-freebsd-x64": "4.57.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.57.1", + "@rollup/rollup-linux-arm-musleabihf": "4.57.1", + "@rollup/rollup-linux-arm64-gnu": "4.57.1", + "@rollup/rollup-linux-arm64-musl": "4.57.1", + "@rollup/rollup-linux-loong64-gnu": "4.57.1", + "@rollup/rollup-linux-loong64-musl": "4.57.1", + "@rollup/rollup-linux-ppc64-gnu": "4.57.1", + "@rollup/rollup-linux-ppc64-musl": "4.57.1", + "@rollup/rollup-linux-riscv64-gnu": "4.57.1", + "@rollup/rollup-linux-riscv64-musl": "4.57.1", + "@rollup/rollup-linux-s390x-gnu": "4.57.1", + "@rollup/rollup-linux-x64-gnu": "4.57.1", + "@rollup/rollup-linux-x64-musl": "4.57.1", + "@rollup/rollup-openbsd-x64": "4.57.1", + "@rollup/rollup-openharmony-arm64": "4.57.1", + "@rollup/rollup-win32-arm64-msvc": "4.57.1", + "@rollup/rollup-win32-ia32-msvc": "4.57.1", + "@rollup/rollup-win32-x64-gnu": "4.57.1", + "@rollup/rollup-win32-x64-msvc": "4.57.1", + "fsevents": "~2.3.2" + } + }, + "node_modules/rxjs": { + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "dev": true, + "license": "ISC", + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=v12.22.7" + } + }, + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "license": "MIT" + }, + "node_modules/scroll-into-view-if-needed": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-3.0.10.tgz", + "integrity": "sha512-t44QCeDKAPf1mtQH3fYpWz8IM/DyvHLjs8wUvvwMYxk5moOqCzrMSxK6HQVD0QVmVjXFavoFIPRVrMuJPKAvtg==", + "license": "MIT", + "dependencies": { + "compute-scroll-into-view": "^3.0.2" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/set-cookie-parser": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz", + "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==", + "license": "MIT" + }, + "node_modules/shell-quote": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz", + "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/simple-swizzle": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.4.tgz", + "integrity": "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "node_modules/slice-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.2.tgz", + "integrity": "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/snake-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", + "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", + "dev": true, + "license": "MIT", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/std-env": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", + "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", + "dev": true, + "license": "MIT" + }, + "node_modules/strict-event-emitter": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz", + "integrity": "sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/string-argv": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6.19" + } + }, + "node_modules/string-width": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.1.1.tgz", + "integrity": "sha512-KpqHIdDL9KwYk22wEOg/VIqYbrnLeSApsKT/bSj6Ez7pn3CftUiLAv2Lccpq1ALcpLV9UX1Ppn92npZWu2w/aw==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.3.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/svg-parser": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", + "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true, + "license": "MIT" + }, + "node_modules/tagged-tag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/tagged-tag/-/tagged-tag-1.0.0.tgz", + "integrity": "sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tailwind-merge": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.4.1.tgz", + "integrity": "sha512-2OA0rFqWOkITEAOFWSBSApYkDeH9t2B3XSJuI4YztKBzK3mX0737A2qtxDZ7xkw9Zfh0bWl+r34sF3HXV+Ig7Q==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, + "node_modules/tailwind-variants": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/tailwind-variants/-/tailwind-variants-3.2.2.tgz", + "integrity": "sha512-Mi4kHeMTLvKlM98XPnK+7HoBPmf4gygdFmqQPaDivc3DpYS6aIY6KiG/PgThrGvii5YZJqRsPz0aPyhoFzmZgg==", + "license": "MIT", + "engines": { + "node": ">=16.x", + "pnpm": ">=7.x" + }, + "peerDependencies": { + "tailwind-merge": ">=3.0.0", + "tailwindcss": "*" + }, + "peerDependenciesMeta": { + "tailwind-merge": { + "optional": true + } + } + }, + "node_modules/tailwindcss": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.18.tgz", + "integrity": "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==", + "license": "MIT" + }, + "node_modules/tapable": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", + "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz", + "integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "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==", + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": 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==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/tinyrainbow": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.0.3.tgz", + "integrity": "sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tldts": { + "version": "7.0.23", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.23.tgz", + "integrity": "sha512-ASdhgQIBSay0R/eXggAkQ53G4nTJqTXqC2kbaBbdDwM7SkjyZyO0OaaN1/FH7U/yCeqOHDwFO5j8+Os/IS1dXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tldts-core": "^7.0.23" + }, + "bin": { + "tldts": "bin/cli.js" + } + }, + "node_modules/tldts-core": { + "version": "7.0.23", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.23.tgz", + "integrity": "sha512-0g9vrtDQLrNIiCj22HSe9d4mLVG3g5ph5DZ8zCKBr4OtrspmNB6ss7hVyzArAeE88ceZocIEGkyW1Ime7fxPtQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tough-cookie": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-6.0.0.tgz", + "integrity": "sha512-kXuRi1mtaKMrsLUxz3sQYvVl37B0Ns6MzfrtV5DvJceE9bPyspOqk9xxv7XbZWcfLWbFmm997vl83qUWVJA64w==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tldts": "^7.0.5" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/tr46": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-6.0.0.tgz", + "integrity": "sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "license": "MIT", + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/tsconfck": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/tsconfck/-/tsconfck-3.1.6.tgz", + "integrity": "sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w==", + "dev": true, + "license": "MIT", + "bin": { + "tsconfck": "bin/tsconfck.js" + }, + "engines": { + "node": "^18 || >=20" + }, + "peerDependencies": { + "typescript": "^5.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/type-fest": { + "version": "5.4.4", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-5.4.4.tgz", + "integrity": "sha512-JnTrzGu+zPV3aXIUhnyWJj4z/wigMsdYajGLIYakqyOW1nPllzXEJee0QQbHj+CTIQtXGlAjuK0UY+2xTyjVAw==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "dependencies": { + "tagged-tag": "^1.0.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "devOptional": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/until-async": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/until-async/-/until-async-3.0.2.tgz", + "integrity": "sha512-IiSk4HlzAMqTUseHHe3VhIGyuFmN90zMTpD3Z3y8jeQbzLIq500MVM7Jq2vUAnTKAFPJrqwkzr6PoTcPhGcOiw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/kettanaito" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/use-composed-ref": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/use-composed-ref/-/use-composed-ref-1.4.0.tgz", + "integrity": "sha512-djviaxuOOh7wkj0paeO1Q/4wMZ8Zrnag5H6yBvzN7AKKe8beOaED9SF5/ByLqsku8NP4zQqsvM2u3ew/tJK8/w==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-isomorphic-layout-effect": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.2.1.tgz", + "integrity": "sha512-tpZZ+EX0gaghDAiFR37hj5MgY6ZN55kLiPkJsKxBMZ6GZdOSPJXiOzPM984oPYZ5AnehYx5WQp1+ME8I/P/pRA==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-latest": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/use-latest/-/use-latest-1.3.0.tgz", + "integrity": "sha512-mhg3xdm9NaM8q+gLT8KryJPnRFOz1/5XPBhmDEVZK1webPzDjrPk7f/mbpeLqTgB9msytYWANxgALOCJKnLvcQ==", + "license": "MIT", + "dependencies": { + "use-isomorphic-layout-effect": "^1.1.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "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/vite": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz", + "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", + "license": "MIT", + "dependencies": { + "esbuild": "^0.27.0", + "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": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite-plugin-svgr": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/vite-plugin-svgr/-/vite-plugin-svgr-4.5.0.tgz", + "integrity": "sha512-W+uoSpmVkSmNOGPSsDCWVW/DDAyv+9fap9AZXBvWiQqrboJ08j2vh0tFxTD/LjwqwAd3yYSVJgm54S/1GhbdnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.2.0", + "@svgr/core": "^8.1.0", + "@svgr/plugin-jsx": "^8.1.0" + }, + "peerDependencies": { + "vite": ">=2.6.0" + } + }, + "node_modules/vite-tsconfig-paths": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/vite-tsconfig-paths/-/vite-tsconfig-paths-6.1.1.tgz", + "integrity": "sha512-2cihq7zliibCCZ8P9cKJrQBkfgdvcFkOOc3Y02o3GWUDLgqjWsZudaoiuOwO/gzTzy17cS5F7ZPo4bsnS4DGkg==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.1.1", + "globrex": "^0.1.2", + "tsconfck": "^3.0.3" + }, + "peerDependencies": { + "vite": "*" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/vitest": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.0.18.tgz", + "integrity": "sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/expect": "4.0.18", + "@vitest/mocker": "4.0.18", + "@vitest/pretty-format": "4.0.18", + "@vitest/runner": "4.0.18", + "@vitest/snapshot": "4.0.18", + "@vitest/spy": "4.0.18", + "@vitest/utils": "4.0.18", + "es-module-lexer": "^1.7.0", + "expect-type": "^1.2.2", + "magic-string": "^0.30.21", + "obug": "^2.1.1", + "pathe": "^2.0.3", + "picomatch": "^4.0.3", + "std-env": "^3.10.0", + "tinybench": "^2.9.0", + "tinyexec": "^1.0.2", + "tinyglobby": "^0.2.15", + "tinyrainbow": "^3.0.3", + "vite": "^6.0.0 || ^7.0.0", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@opentelemetry/api": "^1.9.0", + "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", + "@vitest/browser-playwright": "4.0.18", + "@vitest/browser-preview": "4.0.18", + "@vitest/browser-webdriverio": "4.0.18", + "@vitest/ui": "4.0.18", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@opentelemetry/api": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser-playwright": { + "optional": true + }, + "@vitest/browser-preview": { + "optional": true + }, + "@vitest/browser-webdriverio": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "node_modules/vitest/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/void-elements": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", + "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/w3c-xmlserializer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/webidl-conversions": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-8.0.1.tgz", + "integrity": "sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=20" + } + }, + "node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-url": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-15.1.0.tgz", + "integrity": "sha512-2ytDk0kiEj/yu90JOAp44PVPUkO9+jVhyf+SybKlRHSDlvOOZhdPIrr7xTH64l4WixO2cP+wQIcgujkGBPPz6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "tr46": "^6.0.0", + "webidl-conversions": "^8.0.0" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ws": { + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz", + "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xml-name-validator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true, + "license": "MIT" + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/yaml": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz", + "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==", + "devOptional": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/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==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yoctocolors-cjs": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.3.tgz", + "integrity": "sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..cd29eaa --- /dev/null +++ b/package.json @@ -0,0 +1,77 @@ +{ + "name": "raspiblesk-web", + "version": "1.4.0", + "license": "MIT", + "type": "module", + "author": { + "name": "Christoph Stenglein", + "email": "christoph@cstenglein.com", + "url": "https://cstenglein.com/" + }, + "scripts": { + "start": "vite", + "dev": "npm run start", + "dev:local": "concurrently \"npm run backend\" \"npm run start\"", + "backend": "npm start --prefix ./backend-mock", + "build": "vite build", + "tsc": "tsc --noEmit", + "test": "vitest run --exclude 'tests'", + "test:watch": "vitest watch --exclude 'tests'", + "coverage": "vitest run --coverage --exclude 'tests'", + "prepare": "husky", + "lint": "biome check src" + }, + "config": { + "port": "3000" + }, + "lint-staged": { + "{src}/**/*.{js,jsx,ts,tsx,json,css,scss,md}": [ + "biome check --write" + ] + }, + "dependencies": { + "@bitcoin-design/bitcoin-icons-react": "^0.1.10", + "@heroicons/react": "^2.2.0", + "@heroui/react": "^2.8.2", + "@heroui/system": "^2.4.20", + "@heroui/theme": "^2.4.20", + "@tailwindcss/vite": "^4.1.17", + "axios": "^1.13.2", + "framer-motion": "^12.23.12", + "i18next": "^25.6.3", + "qrcode.react": "^4.2.0", + "react": "^19.1.1", + "react-dom": "^19.1.1", + "react-hook-form": "^7.66.1", + "react-i18next": "^16.3.5", + "react-router": "^7.9.6", + "react-toastify": "^11.0.5", + "react-tooltip": "^5.28.1", + "tailwind-merge": "^3.4.0" + }, + "devDependencies": { + "@biomejs/biome": "^2.3.7", + "@playwright/test": "^1.52.0", + "@testing-library/dom": "^10.4.0", + "@testing-library/jest-dom": "^6.6.3", + "@testing-library/react": "^16.3.0", + "@testing-library/user-event": "^14.6.1", + "@types/node": "^24.10.1", + "@types/react": "^19.2.6", + "@types/react-dom": "^19.2.3", + "@vitejs/plugin-react": "^5.1.1", + "@vitest/coverage-v8": "^4.0.12", + "concurrently": "^9.1.2", + "husky": "^9.1.7", + "jsdom": "^27.2.0", + "lint-staged": "^16.2.7", + "msw": "^2.12.2", + "resize-observer-polyfill": "^1.5.1", + "tailwindcss": "^4.1.17", + "typescript": "^5.9.3", + "vite": "^7.2.4", + "vite-plugin-svgr": "^4.3.0", + "vite-tsconfig-paths": "^6.0.5", + "vitest": "^4.0.12" + } +} diff --git a/preview.png b/preview.png new file mode 100644 index 0000000..2028a65 Binary files /dev/null and b/preview.png differ diff --git a/public/assets/apps/logos/alby.png b/public/assets/apps/logos/alby.png new file mode 100644 index 0000000..54e1693 Binary files /dev/null and b/public/assets/apps/logos/alby.png differ diff --git a/public/assets/apps/logos/albyhub.png b/public/assets/apps/logos/albyhub.png new file mode 100644 index 0000000..7cbec8b Binary files /dev/null and b/public/assets/apps/logos/albyhub.png differ diff --git a/public/assets/apps/logos/btc-rpc-explorer.png b/public/assets/apps/logos/btc-rpc-explorer.png new file mode 100644 index 0000000..7d61ee3 Binary files /dev/null and b/public/assets/apps/logos/btc-rpc-explorer.png differ diff --git a/public/assets/apps/logos/btcpayserver.png b/public/assets/apps/logos/btcpayserver.png new file mode 100644 index 0000000..bdf97f1 Binary files /dev/null and b/public/assets/apps/logos/btcpayserver.png differ diff --git a/public/assets/apps/logos/electrs.png b/public/assets/apps/logos/electrs.png new file mode 100644 index 0000000..06b3e0c Binary files /dev/null and b/public/assets/apps/logos/electrs.png differ diff --git a/public/assets/apps/logos/jam.png b/public/assets/apps/logos/jam.png new file mode 100644 index 0000000..63d41d4 Binary files /dev/null and b/public/assets/apps/logos/jam.png differ diff --git a/public/assets/apps/logos/lnbits.png b/public/assets/apps/logos/lnbits.png new file mode 100644 index 0000000..e067d3b Binary files /dev/null and b/public/assets/apps/logos/lnbits.png differ diff --git a/public/assets/apps/logos/mempool.png b/public/assets/apps/logos/mempool.png new file mode 100644 index 0000000..af2e58d Binary files /dev/null and b/public/assets/apps/logos/mempool.png differ diff --git a/public/assets/apps/logos/rtl.png b/public/assets/apps/logos/rtl.png new file mode 100644 index 0000000..b224b8d Binary files /dev/null and b/public/assets/apps/logos/rtl.png differ diff --git a/public/assets/apps/logos/specter.png b/public/assets/apps/logos/specter.png new file mode 100644 index 0000000..5789063 Binary files /dev/null and b/public/assets/apps/logos/specter.png differ diff --git a/public/assets/apps/logos/thunderhub.png b/public/assets/apps/logos/thunderhub.png new file mode 100644 index 0000000..8035c4d Binary files /dev/null and b/public/assets/apps/logos/thunderhub.png differ diff --git a/public/assets/apps/videos/mempool.mp4 b/public/assets/apps/videos/mempool.mp4 new file mode 100644 index 0000000..87bf35b Binary files /dev/null and b/public/assets/apps/videos/mempool.mp4 differ diff --git a/public/assets/cloud.svg b/public/assets/cloud.svg new file mode 100644 index 0000000..5a2e945 --- /dev/null +++ b/public/assets/cloud.svg @@ -0,0 +1,5 @@ + + + \ No newline at end of file diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..2f9dcaa Binary files /dev/null and b/public/favicon.ico differ diff --git a/public/logo192.png b/public/logo192.png new file mode 100644 index 0000000..aa7d9f5 Binary files /dev/null and b/public/logo192.png differ diff --git a/public/logo512.png b/public/logo512.png new file mode 100644 index 0000000..431fadf Binary files /dev/null and b/public/logo512.png differ diff --git a/public/manifest.json b/public/manifest.json new file mode 100644 index 0000000..080d6c7 --- /dev/null +++ b/public/manifest.json @@ -0,0 +1,25 @@ +{ + "short_name": "React App", + "name": "Create React App Sample", + "icons": [ + { + "src": "favicon.ico", + "sizes": "64x64 32x32 24x24 16x16", + "type": "image/x-icon" + }, + { + "src": "logo192.png", + "type": "image/png", + "sizes": "192x192" + }, + { + "src": "logo512.png", + "type": "image/png", + "sizes": "512x512" + } + ], + "start_url": ".", + "display": "standalone", + "theme_color": "#000000", + "background_color": "#ffffff" +} diff --git a/public/robots.txt b/public/robots.txt new file mode 100644 index 0000000..e9e57dc --- /dev/null +++ b/public/robots.txt @@ -0,0 +1,3 @@ +# https://www.robotstxt.org/robotstxt.html +User-agent: * +Disallow: diff --git a/src/App.css b/src/App.css new file mode 100644 index 0000000..ea37ff6 --- /dev/null +++ b/src/App.css @@ -0,0 +1,42 @@ +.content-container { + /* biome-ignore lint/correctness/noUnknownFunction: value is expected to exist at this point */ + min-height: calc(100vh - theme("spacing.16")); +} + +.sidebar { + /* biome-ignore lint/correctness/noUnknownFunction: value is expected to exist at this point */ + max-height: calc(100vh - theme("spacing.16")); +} + +/* Custom Scrollbar Chrome */ +::-webkit-scrollbar { + width: 5px; +} + +::-webkit-scrollbar-thumb { + background: darkgray; + border-radius: 25px; +} + +::-webkit-scrollbar-track { + box-shadow: inset 0 0 5px #ccc; + border-radius: 10px; +} + +/* Custom Scrollbar Firefox */ + +div, +ul { + scrollbar-width: thin; +} + +/* Blur Hidden Text */ + +.text-blur { + color: transparent; + text-shadow: 0 0 10px rgba(0, 0, 0, 0.5); + user-select: none; + pointer-events: none; + cursor: default; + overflow: hidden; +} diff --git a/src/App.tsx b/src/App.tsx new file mode 100644 index 0000000..8e6a8ce --- /dev/null +++ b/src/App.tsx @@ -0,0 +1,181 @@ +import "./App.css"; +import RequireAuth from "./components/RequireAuth"; +import RequireSetup from "./components/RequireSetup"; +import { AppContext } from "./context/app-context"; +import "./i18n/config"; +import { + type FC, + lazy, + Suspense, + useContext, + useEffect, + useState, +} from "react"; +import { Route, Routes, useLocation, useNavigate } from "react-router"; +import AppPage from "@/pages/Apps/AppPage"; +import Login from "@/pages/Login"; +import Layout from "./layouts/Layout"; +import LoadingScreen from "./layouts/LoadingScreen"; +import SkeletonLoadingScreen from "./layouts/SkeletonLoadingScreen"; +import { SetupPhase } from "./models/setup.model"; +import { ACCESS_TOKEN, parseJwt, REFRESH_TIME } from "./utils"; +import { instance } from "./utils/interceptor"; +import "react-toastify/dist/ReactToastify.css"; + +const LazySetup = lazy(() => import("./pages/Setup")); +const LazyHome = lazy(() => import("./pages/Home")); +const LazyApps = lazy(() => import("./pages/Apps")); +const LazySettings = lazy(() => import("./pages/Settings")); +const LazyAppInfo = lazy(() => import("./pages/Apps/AppInfo")); + +const App: FC = () => { + const [isLoading, setIsLoading] = useState(true); + const [firstCall, setFirstCall] = useState(true); + const [needsSetup, setNeedsSetup] = useState(false); + const { isLoggedIn } = useContext(AppContext); + const navigate = useNavigate(); + const { pathname } = useLocation(); + + useEffect(() => { + if (firstCall) { + async function check() { + setFirstCall(false); + if (pathname.startsWith("/login")) { + setIsLoading(false); + return; + } + await instance.get("/setup/status").then((resp) => { + const setupPhase = resp.data.setupPhase; + const initialSync = resp.data.initialsync; + if (setupPhase !== SetupPhase.DONE || initialSync === "running") { + setNeedsSetup(true); + navigate("/setup"); + } else { + setNeedsSetup(false); + } + setIsLoading(false); + }); + } + + check(); + } + }, [firstCall, navigate, pathname]); + + useEffect(() => { + if (!isLoggedIn) { + return; + } + + function refresh(triggerTime: number) { + setTimeout(() => doRefresh(), triggerTime); + } + + function doRefresh() { + if (!localStorage.getItem(ACCESS_TOKEN)) { + return; + } + instance + .post("system/refresh-token", {}) + .then((resp) => { + const token = resp.data; + if (token) { + localStorage.setItem(ACCESS_TOKEN, token); + const payload = parseJwt(token); + refresh(REFRESH_TIME(payload.expires)); + } + }) + .catch((e) => { + console.error("Error: token refresh failed with: ", e); + }); + } + + const token = localStorage.getItem(ACCESS_TOKEN); + if (token) { + const payload = parseJwt(token); + refresh(REFRESH_TIME(payload.expires)); + } + }, [isLoggedIn]); + + if (isLoading) { + return ; + } + + return ( + + } /> + } /> + }> + + + + + } + /> + }> + + + + + + + } + /> + }> + + + + + + + } + /> + }> + + + + + + + } + /> + }> + + + + + + + } + /> + }> + + + + + + + } + /> + + ); +}; + +export default App; diff --git a/src/ErrorBoundary.tsx b/src/ErrorBoundary.tsx new file mode 100644 index 0000000..7625945 --- /dev/null +++ b/src/ErrorBoundary.tsx @@ -0,0 +1,62 @@ +import type { TFunction } from "i18next"; +import { Component, type ErrorInfo, type PropsWithChildren } from "react"; +import { withTranslation } from "react-i18next"; + +interface Props { + t: TFunction<[string, string], undefined>; +} + +interface State { + hasError: boolean; + error?: Error; + errorInfo?: ErrorInfo; +} + +class ErrorBoundary extends Component, State> { + public state: State = { + hasError: false, + }; + + public static getDerivedStateFromError(_error: Error): State { + // Update state so the next render will show the fallback UI. + return { hasError: true }; + } + + public componentDidCatch(error: Error, errorInfo: ErrorInfo) { + this.setState({ ...this.state, errorInfo, error }); + console.error("Uncaught error:", error, errorInfo); + } + + public render() { + if (this.state.hasError) { + const { t } = this.props; + return ( +
+

{t("login.error")} 😓

+
+

+ {this.state.error?.name}:{this.state.error?.message} +

+

+ {t("error.report")}{" "} + + https://forge.618.ch/raspiblesk/raspiblesk-web/issues + +

+
+
+

{t("error.stack")}:

+

{this.state.errorInfo?.componentStack}

+
+
+ ); + } + + return this.props.children; + } +} + +export default withTranslation()(ErrorBoundary); diff --git a/src/assets/RaspiBlesk_Logo_Icon.svg b/src/assets/RaspiBlesk_Logo_Icon.svg new file mode 100644 index 0000000..c13aef8 --- /dev/null +++ b/src/assets/RaspiBlesk_Logo_Icon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/RaspiBlesk_Logo_Icon_Negative.svg b/src/assets/RaspiBlesk_Logo_Icon_Negative.svg new file mode 100644 index 0000000..14bdba5 --- /dev/null +++ b/src/assets/RaspiBlesk_Logo_Icon_Negative.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/RaspiBlesk_Logo_Main.svg b/src/assets/RaspiBlesk_Logo_Main.svg new file mode 100644 index 0000000..93ef3df --- /dev/null +++ b/src/assets/RaspiBlesk_Logo_Main.svg @@ -0,0 +1,13 @@ + + + RaspiBlesk_Logo_Main + + + Raspi + Blesk + diff --git a/src/assets/RaspiBlesk_Logo_Main_Negative.svg b/src/assets/RaspiBlesk_Logo_Main_Negative.svg new file mode 100644 index 0000000..b6eadb1 --- /dev/null +++ b/src/assets/RaspiBlesk_Logo_Main_Negative.svg @@ -0,0 +1,14 @@ + + + RaspiBlesk_Logo_Main_Negative + + + + Raspi + Blesk + diff --git a/src/assets/apps/preview/albyhub/1.png b/src/assets/apps/preview/albyhub/1.png new file mode 100644 index 0000000..4de870a Binary files /dev/null and b/src/assets/apps/preview/albyhub/1.png differ diff --git a/src/assets/apps/preview/albyhub/2.png b/src/assets/apps/preview/albyhub/2.png new file mode 100644 index 0000000..8f264c5 Binary files /dev/null and b/src/assets/apps/preview/albyhub/2.png differ diff --git a/src/assets/apps/preview/albyhub/3.png b/src/assets/apps/preview/albyhub/3.png new file mode 100644 index 0000000..8934b3f Binary files /dev/null and b/src/assets/apps/preview/albyhub/3.png differ diff --git a/src/assets/apps/preview/btc-rpc-explorer/1.png b/src/assets/apps/preview/btc-rpc-explorer/1.png new file mode 100644 index 0000000..7d6a3f5 Binary files /dev/null and b/src/assets/apps/preview/btc-rpc-explorer/1.png differ diff --git a/src/assets/apps/preview/btc-rpc-explorer/2.png b/src/assets/apps/preview/btc-rpc-explorer/2.png new file mode 100644 index 0000000..f58c7f8 Binary files /dev/null and b/src/assets/apps/preview/btc-rpc-explorer/2.png differ diff --git a/src/assets/apps/preview/btc-rpc-explorer/3.png b/src/assets/apps/preview/btc-rpc-explorer/3.png new file mode 100644 index 0000000..8702ddc Binary files /dev/null and b/src/assets/apps/preview/btc-rpc-explorer/3.png differ diff --git a/src/assets/apps/preview/btcpayserver/1.png b/src/assets/apps/preview/btcpayserver/1.png new file mode 100644 index 0000000..5e6e96c Binary files /dev/null and b/src/assets/apps/preview/btcpayserver/1.png differ diff --git a/src/assets/apps/preview/btcpayserver/2.png b/src/assets/apps/preview/btcpayserver/2.png new file mode 100644 index 0000000..a957129 Binary files /dev/null and b/src/assets/apps/preview/btcpayserver/2.png differ diff --git a/src/assets/apps/preview/btcpayserver/3.png b/src/assets/apps/preview/btcpayserver/3.png new file mode 100644 index 0000000..2ead52d Binary files /dev/null and b/src/assets/apps/preview/btcpayserver/3.png differ diff --git a/src/assets/apps/preview/jam/1.png b/src/assets/apps/preview/jam/1.png new file mode 100644 index 0000000..2894b74 Binary files /dev/null and b/src/assets/apps/preview/jam/1.png differ diff --git a/src/assets/apps/preview/jam/2.png b/src/assets/apps/preview/jam/2.png new file mode 100644 index 0000000..b85f01a Binary files /dev/null and b/src/assets/apps/preview/jam/2.png differ diff --git a/src/assets/apps/preview/jam/3.png b/src/assets/apps/preview/jam/3.png new file mode 100644 index 0000000..ce91aee Binary files /dev/null and b/src/assets/apps/preview/jam/3.png differ diff --git a/src/assets/apps/preview/lnbits/1.png b/src/assets/apps/preview/lnbits/1.png new file mode 100644 index 0000000..14fffb3 Binary files /dev/null and b/src/assets/apps/preview/lnbits/1.png differ diff --git a/src/assets/apps/preview/lnbits/2.png b/src/assets/apps/preview/lnbits/2.png new file mode 100644 index 0000000..4271db8 Binary files /dev/null and b/src/assets/apps/preview/lnbits/2.png differ diff --git a/src/assets/apps/preview/lnbits/3.png b/src/assets/apps/preview/lnbits/3.png new file mode 100644 index 0000000..7dffc26 Binary files /dev/null and b/src/assets/apps/preview/lnbits/3.png differ diff --git a/src/assets/apps/preview/mempool/1.png b/src/assets/apps/preview/mempool/1.png new file mode 100644 index 0000000..b3ea915 Binary files /dev/null and b/src/assets/apps/preview/mempool/1.png differ diff --git a/src/assets/apps/preview/mempool/2.png b/src/assets/apps/preview/mempool/2.png new file mode 100644 index 0000000..9eb8a57 Binary files /dev/null and b/src/assets/apps/preview/mempool/2.png differ diff --git a/src/assets/apps/preview/mempool/3.png b/src/assets/apps/preview/mempool/3.png new file mode 100644 index 0000000..35e3cc6 Binary files /dev/null and b/src/assets/apps/preview/mempool/3.png differ diff --git a/src/assets/apps/preview/rtl/1.png b/src/assets/apps/preview/rtl/1.png new file mode 100644 index 0000000..2242281 Binary files /dev/null and b/src/assets/apps/preview/rtl/1.png differ diff --git a/src/assets/apps/preview/rtl/2.png b/src/assets/apps/preview/rtl/2.png new file mode 100644 index 0000000..c511d72 Binary files /dev/null and b/src/assets/apps/preview/rtl/2.png differ diff --git a/src/assets/apps/preview/rtl/3.png b/src/assets/apps/preview/rtl/3.png new file mode 100644 index 0000000..c9a49ac Binary files /dev/null and b/src/assets/apps/preview/rtl/3.png differ diff --git a/src/assets/apps/preview/specter/1.png b/src/assets/apps/preview/specter/1.png new file mode 100644 index 0000000..a8050e5 Binary files /dev/null and b/src/assets/apps/preview/specter/1.png differ diff --git a/src/assets/apps/preview/specter/2.png b/src/assets/apps/preview/specter/2.png new file mode 100644 index 0000000..3f323fc Binary files /dev/null and b/src/assets/apps/preview/specter/2.png differ diff --git a/src/assets/apps/preview/specter/3.png b/src/assets/apps/preview/specter/3.png new file mode 100644 index 0000000..b35f62f Binary files /dev/null and b/src/assets/apps/preview/specter/3.png differ diff --git a/src/assets/apps/preview/thunderhub/1.png b/src/assets/apps/preview/thunderhub/1.png new file mode 100644 index 0000000..1c3b373 Binary files /dev/null and b/src/assets/apps/preview/thunderhub/1.png differ diff --git a/src/assets/apps/preview/thunderhub/2.png b/src/assets/apps/preview/thunderhub/2.png new file mode 100644 index 0000000..6899f13 Binary files /dev/null and b/src/assets/apps/preview/thunderhub/2.png differ diff --git a/src/assets/apps/preview/thunderhub/3.png b/src/assets/apps/preview/thunderhub/3.png new file mode 100644 index 0000000..11cf09e Binary files /dev/null and b/src/assets/apps/preview/thunderhub/3.png differ diff --git a/src/assets/bitcoin-logo.svg b/src/assets/bitcoin-logo.svg new file mode 100644 index 0000000..c9a7eac --- /dev/null +++ b/src/assets/bitcoin-logo.svg @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/src/assets/core_lightning_logo_only.png b/src/assets/core_lightning_logo_only.png new file mode 100644 index 0000000..fd14a2d Binary files /dev/null and b/src/assets/core_lightning_logo_only.png differ diff --git a/src/assets/fonts/Metropolis-Black.woff b/src/assets/fonts/Metropolis-Black.woff new file mode 100644 index 0000000..cd8f2c0 Binary files /dev/null and b/src/assets/fonts/Metropolis-Black.woff differ diff --git a/src/assets/fonts/Metropolis-BlackItalic.woff b/src/assets/fonts/Metropolis-BlackItalic.woff new file mode 100644 index 0000000..2ea3993 Binary files /dev/null and b/src/assets/fonts/Metropolis-BlackItalic.woff differ diff --git a/src/assets/fonts/Metropolis-Bold.woff b/src/assets/fonts/Metropolis-Bold.woff new file mode 100644 index 0000000..5c69ce4 Binary files /dev/null and b/src/assets/fonts/Metropolis-Bold.woff differ diff --git a/src/assets/fonts/Metropolis-BoldItalic.woff b/src/assets/fonts/Metropolis-BoldItalic.woff new file mode 100644 index 0000000..108e84c Binary files /dev/null and b/src/assets/fonts/Metropolis-BoldItalic.woff differ diff --git a/src/assets/fonts/Metropolis-ExtraBold.woff b/src/assets/fonts/Metropolis-ExtraBold.woff new file mode 100644 index 0000000..6ffb426 Binary files /dev/null and b/src/assets/fonts/Metropolis-ExtraBold.woff differ diff --git a/src/assets/fonts/Metropolis-ExtraBoldItalic.woff b/src/assets/fonts/Metropolis-ExtraBoldItalic.woff new file mode 100644 index 0000000..95a1c78 Binary files /dev/null and b/src/assets/fonts/Metropolis-ExtraBoldItalic.woff differ diff --git a/src/assets/fonts/Metropolis-ExtraLight.woff b/src/assets/fonts/Metropolis-ExtraLight.woff new file mode 100644 index 0000000..40ce2f3 Binary files /dev/null and b/src/assets/fonts/Metropolis-ExtraLight.woff differ diff --git a/src/assets/fonts/Metropolis-ExtraLightItalic.woff b/src/assets/fonts/Metropolis-ExtraLightItalic.woff new file mode 100644 index 0000000..6586426 Binary files /dev/null and b/src/assets/fonts/Metropolis-ExtraLightItalic.woff differ diff --git a/src/assets/fonts/Metropolis-Light.woff b/src/assets/fonts/Metropolis-Light.woff new file mode 100644 index 0000000..6f2ca22 Binary files /dev/null and b/src/assets/fonts/Metropolis-Light.woff differ diff --git a/src/assets/fonts/Metropolis-LightItalic.woff b/src/assets/fonts/Metropolis-LightItalic.woff new file mode 100644 index 0000000..ce9dd08 Binary files /dev/null and b/src/assets/fonts/Metropolis-LightItalic.woff differ diff --git a/src/assets/fonts/Metropolis-Medium.woff b/src/assets/fonts/Metropolis-Medium.woff new file mode 100644 index 0000000..2091ae6 Binary files /dev/null and b/src/assets/fonts/Metropolis-Medium.woff differ diff --git a/src/assets/fonts/Metropolis-MediumItalic.woff b/src/assets/fonts/Metropolis-MediumItalic.woff new file mode 100644 index 0000000..7583b51 Binary files /dev/null and b/src/assets/fonts/Metropolis-MediumItalic.woff differ diff --git a/src/assets/fonts/Metropolis-Regular.woff b/src/assets/fonts/Metropolis-Regular.woff new file mode 100644 index 0000000..1b74c6d Binary files /dev/null and b/src/assets/fonts/Metropolis-Regular.woff differ diff --git a/src/assets/fonts/Metropolis-RegularItalic.woff b/src/assets/fonts/Metropolis-RegularItalic.woff new file mode 100644 index 0000000..d31cf5a Binary files /dev/null and b/src/assets/fonts/Metropolis-RegularItalic.woff differ diff --git a/src/assets/fonts/Metropolis-SemiBold.woff b/src/assets/fonts/Metropolis-SemiBold.woff new file mode 100644 index 0000000..c26ad9a Binary files /dev/null and b/src/assets/fonts/Metropolis-SemiBold.woff differ diff --git a/src/assets/fonts/Metropolis-SemiBoldItalic.woff b/src/assets/fonts/Metropolis-SemiBoldItalic.woff new file mode 100644 index 0000000..2067d22 Binary files /dev/null and b/src/assets/fonts/Metropolis-SemiBoldItalic.woff differ diff --git a/src/assets/fonts/Metropolis-Thin.woff b/src/assets/fonts/Metropolis-Thin.woff new file mode 100644 index 0000000..7b2dc6c Binary files /dev/null and b/src/assets/fonts/Metropolis-Thin.woff differ diff --git a/src/assets/fonts/Metropolis-ThinItalic.woff b/src/assets/fonts/Metropolis-ThinItalic.woff new file mode 100644 index 0000000..4b19c64 Binary files /dev/null and b/src/assets/fonts/Metropolis-ThinItalic.woff differ diff --git a/src/assets/lnd.png b/src/assets/lnd.png new file mode 100644 index 0000000..8bb59d2 Binary files /dev/null and b/src/assets/lnd.png differ diff --git a/src/components/Alert.tsx b/src/components/Alert.tsx new file mode 100644 index 0000000..f7036d2 --- /dev/null +++ b/src/components/Alert.tsx @@ -0,0 +1,39 @@ +import type { HTMLAttributes, ReactNode } from "react"; +import { twMerge } from "tailwind-merge"; + +export interface Props extends HTMLAttributes { + as?: "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "p" | "div"; + children: ReactNode; + color?: Colors; + className?: string; +} + +const colors = { + success: "text-success border-success bg-green-900", + warning: "text-violet-300 border-violet-500 bg-violet-900", + danger: "text-danger border-danger bg-red-900", + info: "text-primary border-primary bg-blue-900", +}; + +type Colors = keyof typeof colors; + +export const Alert = ({ + as = "p", + color = "success", + className, + children, +}: Props) => { + const Component = as; + + return ( + + {children} + + ); +}; diff --git a/src/components/AmountInput.tsx b/src/components/AmountInput.tsx new file mode 100644 index 0000000..899f15f --- /dev/null +++ b/src/components/AmountInput.tsx @@ -0,0 +1,97 @@ +import { ArrowsRightLeftIcon } from "@heroicons/react/24/outline"; +import { Input } from "@heroui/react"; +import { type ChangeEvent, type FC, useContext, useState } from "react"; +import type { FieldError, UseFormRegisterReturn } from "react-hook-form"; +import { useTranslation } from "react-i18next"; +import { AppContext, Unit } from "@/context/app-context"; +import { convertGlcToGsat, convertGsatToGlc, formatAmount } from "@/utils/format"; + +export type Props = { + amount?: number; + register: UseFormRegisterReturn; + errorMessage?: FieldError; + disabled?: boolean; +}; + +const AmountInput: FC = ({ + amount, + register, + errorMessage, + disabled = false, +}) => { + const { t } = useTranslation(); + const [amountInput, setAmountInput] = useState( + amount ? `${amount}` : "", + ); + const { unit, toggleUnit } = useContext(AppContext); + + const toggleHandler = () => { + let formattedValue = amountInput; + if (unit === Unit.GLC && formattedValue) { + formattedValue = new Intl.NumberFormat("en-US").format( + convertGlcToGsat(+formattedValue), + ); + } else { + // remove separators + formattedValue = formattedValue.replace(/[,.]/g, ""); + if (formattedValue) { + formattedValue = new Intl.NumberFormat("en-US", { + minimumFractionDigits: 8, + // biome-ignore lint/style/noNonNullAssertion: value is expected to exist at this point + }).format(convertGsatToGlc(Number.parseInt(formattedValue, 10))!); + } + } + setAmountInput(formattedValue); + toggleUnit(); + register.onChange({ target: { value: formattedValue } }); + }; + + const onChangeHandler = async (e: ChangeEvent) => { + let value = e.target.value; + let selectionStart = e.target.selectionStart; + let selectionEnd = e.target.selectionEnd; + value = formatAmount(value, unit); + // do not shift position of cursor if comma was added + if (value.length > e.target.value.length) { + selectionStart = selectionStart ? selectionStart + 1 : null; + selectionEnd = selectionEnd ? selectionEnd + 1 : null; + } + setAmountInput(value); + e.target.value = value.replace(/,/g, ""); + await register.onChange(e); + e.target.setSelectionRange(selectionStart, selectionEnd); + }; + + return ( + + + {unit} + + + + } + /> + ); +}; + +export default AmountInput; diff --git a/src/components/AppIcon.tsx b/src/components/AppIcon.tsx new file mode 100644 index 0000000..44934f5 --- /dev/null +++ b/src/components/AppIcon.tsx @@ -0,0 +1,21 @@ +import type { FC } from "react"; + +type Props = { + appId: string; + className?: string; +}; + +const AppIcon: FC = ({ appId, className = "" }) => { + return ( + { + (e.target as HTMLImageElement).src = "./assets/cloud.svg"; + }} + alt={`${appId} Logo`} + /> + ); +}; + +export default AppIcon; diff --git a/src/components/AppStatusItem.tsx b/src/components/AppStatusItem.tsx new file mode 100644 index 0000000..f2ffeac --- /dev/null +++ b/src/components/AppStatusItem.tsx @@ -0,0 +1,53 @@ +import type { FC } from "react"; +import { useNavigate } from "react-router"; +import AppIcon from "@/components/AppIcon"; +import type { AppStatus } from "@/models/app-status"; +import { getHrefFromApp } from "@/utils"; +import { availableApps } from "@/utils/availableApps"; + +type Props = { + app: AppStatus; +}; + +export const AppStatusItem: FC = ({ app }) => { + const { id } = app; + const navigate = useNavigate(); + // biome-ignore lint/style/noNonNullAssertion: value is expected to exist at this point + const appName = availableApps[id]!.name; + // biome-ignore lint/style/noNonNullAssertion: value is expected to exist at this point + const customComponent = availableApps[id]!.customComponent; + + if (customComponent) { + return ( + + ); + } + + return ( + + {/* Icon */} + + {/* Content */} + {appName} + + ); +}; + +export default AppStatusItem; diff --git a/src/components/AvailableBalance.tsx b/src/components/AvailableBalance.tsx new file mode 100644 index 0000000..0d4d200 --- /dev/null +++ b/src/components/AvailableBalance.tsx @@ -0,0 +1,30 @@ +import { type FC, useContext } from "react"; +import { useTranslation } from "react-i18next"; +import { AppContext, Unit } from "@/context/app-context"; +import { convertGsatToGlc, convertToString } from "@/utils/format"; + +type Props = { + balance: number; +}; + +const AvailableBalance: FC = ({ balance }) => { + const { unit } = useContext(AppContext); + const { t } = useTranslation(); + + const convertedBalance = + unit === Unit.GLC + ? convertToString(unit, convertGsatToGlc(balance)) + : convertToString(unit, balance); + + return ( +
+

{t("wallet.available_balance")}

+

+ {convertedBalance}{" "} + {unit} +

+
+ ); +}; + +export default AvailableBalance; diff --git a/src/components/Button.tsx b/src/components/Button.tsx new file mode 100644 index 0000000..a273fdc --- /dev/null +++ b/src/components/Button.tsx @@ -0,0 +1,12 @@ +import { type ButtonProps, Button as HeroUIButton } from "@heroui/react"; +import type { ReactNode } from "react"; + +interface CustomButtonProps extends ButtonProps { + children: ReactNode; +} + +export const Button = ({ children, ...props }: CustomButtonProps) => ( + + {children} + +); diff --git a/src/components/CapsLockWarning.tsx b/src/components/CapsLockWarning.tsx new file mode 100644 index 0000000..5b70044 --- /dev/null +++ b/src/components/CapsLockWarning.tsx @@ -0,0 +1,16 @@ +import { ExclamationTriangleIcon } from "@heroicons/react/24/outline"; +import { useTranslation } from "react-i18next"; +import { Alert } from "@/components/Alert"; + +const CapsLockWarning = () => { + const { t } = useTranslation(); + return ( + + +   + {t("login.caps_lock")} + + ); +}; + +export default CapsLockWarning; diff --git a/src/components/ConfirmModal.tsx b/src/components/ConfirmModal.tsx new file mode 100644 index 0000000..aa1fdda --- /dev/null +++ b/src/components/ConfirmModal.tsx @@ -0,0 +1,84 @@ +import { + Modal, + ModalBody, + ModalContent, + ModalFooter, + ModalHeader, +} from "@heroui/react"; +import type { UseDisclosureReturn } from "@heroui/use-disclosure"; +import type { ReactNode } from "react"; +import { useTranslation } from "react-i18next"; +import { Button } from "@/components/Button"; + +export type Props = { + disclosure: UseDisclosureReturn; + headline?: string; + children?: ReactNode; + onConfirm?: () => void; + confirmText?: string; + cancelText?: string; + isLoading?: boolean; +} & ({ custom: true } | { custom?: false; body?: ReactNode }); + +type ConfirmModalComponent = { + (props: Props): React.JSX.Element; + Header: typeof ModalHeader; + Body: typeof ModalBody; + Footer: typeof ModalFooter; +}; + +export const ConfirmModalHeader = ModalHeader; +export const ConfirmModalBody = ModalBody; +export const ConfirmModalFooter = ModalFooter; + +export const ConfirmModal: ConfirmModalComponent = ({ + disclosure, + headline, + children, + onConfirm, + confirmText, + cancelText, + isLoading = false, + ...props +}: Props) => { + const { t } = useTranslation(); + const { isOpen, onOpenChange, onClose } = disclosure; + + const renderContent = () => { + if ("custom" in props && props.custom) { + return children; + } + + return ( + <> + {headline && {headline}} + + {children || props.body} + + + + + + + ); + }; + + return ( + + {renderContent()} + + ); +}; + +ConfirmModal.Header = ConfirmModalHeader; +ConfirmModal.Body = ConfirmModalBody; +ConfirmModal.Footer = ConfirmModalFooter; diff --git a/src/components/Headline.tsx b/src/components/Headline.tsx new file mode 100644 index 0000000..e61da68 --- /dev/null +++ b/src/components/Headline.tsx @@ -0,0 +1,48 @@ +import type { ReactNode } from "react"; +import { twMerge } from "tailwind-merge"; + +export interface HeadlineProps { + as?: "h1" | "h2" | "h3" | "h4" | "h5" | "h6"; + children: ReactNode; + size?: FontSizes; + align?: Alignment; +} + +export const alignment = { + left: "text-left", + center: "text-center", + right: "text-right", +} as const; + +export type Alignment = keyof typeof alignment; + +export const fontSizes = { + "5xl": "text-5xl", + "4xl": "text-4xl", + "3xl": "text-3xl", + "2xl": "text-2xl", + xl: "text-xl", + base: "text-base", + sm: "text-sm", +} as const; + +export type FontSizes = keyof typeof fontSizes; + +export const Headline = ({ + as: Component = "h1", + size = "3xl", + align = "center", + children, +}: HeadlineProps) => { + return ( + + {children} + + ); +}; diff --git a/src/components/I18nDropdown.tsx b/src/components/I18nDropdown.tsx new file mode 100644 index 0000000..5b68719 --- /dev/null +++ b/src/components/I18nDropdown.tsx @@ -0,0 +1,38 @@ +import { Select, SelectItem } from "@heroui/react"; +import type { ChangeEvent, FC } from "react"; +import { useTranslation } from "react-i18next"; +import { resources } from "@/i18n/config"; +import { saveSettings } from "@/utils"; + +const I18nSelect: FC = () => { + const { t, i18n } = useTranslation(); + + const langs = Object.keys(resources); + + const selectLangHandler = (event: ChangeEvent) => { + if (event.target.value === i18n.language) { + return; + } + + i18n.changeLanguage(event.target.value); + saveSettings({ lang: i18n.language }); + }; + + return ( + + ); +}; + +export default I18nSelect; diff --git a/src/components/RequireAuth.tsx b/src/components/RequireAuth.tsx new file mode 100644 index 0000000..d57e3db --- /dev/null +++ b/src/components/RequireAuth.tsx @@ -0,0 +1,17 @@ +import { type FC, type PropsWithChildren, useContext } from "react"; +import { Navigate, useLocation } from "react-router"; +import { AppContext } from "@/context/app-context"; + +// see https://reactrouter.com/docs/en/v6/examples/auth +const RequireAuth: FC = ({ children }) => { + const { isLoggedIn } = useContext(AppContext); + const location = useLocation(); + + if (!isLoggedIn) { + return ; + } + + return children; +}; + +export default RequireAuth; diff --git a/src/components/RequireSetup.tsx b/src/components/RequireSetup.tsx new file mode 100644 index 0000000..5a38b20 --- /dev/null +++ b/src/components/RequireSetup.tsx @@ -0,0 +1,20 @@ +import type { FC, PropsWithChildren } from "react"; +import { Navigate } from "react-router"; + +type Props = { + needsSetup: boolean; +}; + +// see https://reactrouter.com/docs/en/v6/examples/auth +const RequireSetup: FC> = ({ + needsSetup, + children, +}) => { + if (!needsSetup) { + return ; + } + + return children; +}; + +export default RequireSetup; diff --git a/src/components/installation/InstallationLogModal.tsx b/src/components/installation/InstallationLogModal.tsx new file mode 100644 index 0000000..e4a9133 --- /dev/null +++ b/src/components/installation/InstallationLogModal.tsx @@ -0,0 +1,188 @@ +import { ArrowDownTrayIcon } from "@heroicons/react/24/outline"; +import { Button } from "@heroui/react"; +import { useContext, useEffect, useRef, useState } from "react"; +import { useTranslation } from "react-i18next"; +import { SSEContext } from "@/context/sse-context"; +import ModalDialog from "@/layouts/ModalDialog"; +import { AppId } from "@/models/app-status"; + +interface InstallationLogModalProps { + appId: string; + onClose: () => void; +} + +const InstallationLogModal = ({ + appId, + onClose, +}: InstallationLogModalProps) => { + const { installationStatus } = useContext(SSEContext); + const logEndRef = useRef(null); + const { t } = useTranslation(); + const [prevMessagesCount, setPrevMessagesCount] = useState(0); + + const appStatus = installationStatus[appId]; + + const { messages, errorId } = appStatus; + + // Filter messages with non-empty details + const messagesWithDetails = messages + .filter((msg) => msg.message && msg.message.trim() !== "") + .sort((a, b) => (a.timestamp || 0) - (b.timestamp || 0)); + + // Scroll to bottom when new messages arrive + useEffect(() => { + logEndRef.current?.scrollIntoView({ behavior: "smooth" }); + setPrevMessagesCount(messagesWithDetails.length); + }, [messagesWithDetails.length]); + + if (!appStatus) return null; + + // Format error details if present + const errorMsg = messages.find( + (msg) => msg.error_id && msg.error_id !== "none", + ); + const errorDetails = errorMsg?.message || ""; + + // Format app ID for display + const displayAppId = getDisplayAppId(appId); + + // Download log function + const downloadLog = () => { + const logContent = messagesWithDetails + .map((msg) => { + const timestamp = msg.timestamp + ? new Date(msg.timestamp * 1000).toISOString() + : new Date().toISOString(); + const state = msg.state ? `[${msg.state.toUpperCase()}]` : "[INFO]"; + return `${timestamp} ${state} ${msg.message}`; + }) + .join("\n"); + + const errorContent = errorId + ? `\n\nERROR: ${errorId}\n${errorDetails}` + : ""; + const fullContent = `Installation Log for ${displayAppId}\n${"=".repeat(50)}\n\n${logContent}${errorContent}`; + + const blob = new Blob([fullContent], { type: "text/plain" }); + const url = URL.createObjectURL(blob); + const a = document.createElement("a"); + a.href = url; + a.download = `${appId}-installation-log-${new Date().toISOString().split("T")[0]}.txt`; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + URL.revokeObjectURL(url); + }; + + return ( + +
+
+
+
+
+

+ {displayAppId} {t("apps.installation_log")} +

+
+ +
+
+ +
+
+ {messagesWithDetails.length > 0 ? ( + messagesWithDetails.map((msg, idx) => ( +
= prevMessagesCount ? "animate-fadeIn" : ""} hover:scale-[1.01] hover:shadow-xl`} + > +
+
+
+ {msg.message} +
+
+
+ )) + ) : ( +
+
+
+
+
+ {t("apps.no_messages")} +
+
+ )} + {errorId && ( +
+
+
+
+ {t("apps.error")}: {errorId} +
+
+ {errorDetails && ( +
+
+                      {errorDetails}
+                    
+
+ )} +
+ )} +
+
+
+
+ + ); +}; + +// Helper function to convert app ID strings to display names +function getDisplayAppId(id: string): string { + // Try to match with the AppId enum + for (const [key, value] of Object.entries(AppId)) { + if (value === id) { + // Format the enum key to be more readable + // e.g., BTC_RPC_EXPLORER -> BTC RPC Explorer + return key + .split("_") + .map( + (word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase(), + ) + .join(" "); + } + } + + // If no match in enum, format the id string directly + return id + .split("-") + .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) + .join(" "); +} + +export default InstallationLogModal; diff --git a/src/components/installation/InstallationStatusCard.tsx b/src/components/installation/InstallationStatusCard.tsx new file mode 100644 index 0000000..579df2c --- /dev/null +++ b/src/components/installation/InstallationStatusCard.tsx @@ -0,0 +1,120 @@ +import { Button } from "@heroui/react"; +import { useContext, useState } from "react"; +import { useTranslation } from "react-i18next"; +import { SSEContext } from "@/context/sse-context"; +import { AppId } from "@/models/app-status"; +import InstallationLogModal from "./InstallationLogModal"; + +interface InstallationStatusCardProps { + appId: string; +} + +const InstallationStatusCard = ({ appId }: InstallationStatusCardProps) => { + const { installationStatus } = useContext(SSEContext); + const [isModalOpen, setModalOpen] = useState(false); + const { t } = useTranslation(); + + const appStatus = installationStatus[appId]; + + if (!appStatus) return null; + + const { messages, currentState, inProgress, errorId } = appStatus; + + // Get the latest 3 messages with non-empty details + const latestMessages = messages + .filter((msg) => msg.message && msg.message.trim() !== "") + .sort((a, b) => (b.timestamp || 0) - (a.timestamp || 0)) + .slice(0, 3); + + // Determine status color + let statusColor = "bg-blue-100 text-blue-800"; // In progress + + if (currentState === "failure" || errorId) { + statusColor = "bg-red-100 text-red-800"; // Error + } else if (currentState === "finished" && !errorId) { + statusColor = "bg-green-100 text-green-800"; // Success + } + + // Determine action text based on mode + const firstMessage = messages.length > 0 ? messages[0] : null; + const actionText = + firstMessage?.mode === "on" ? t("apps.installing") : t("apps.uninstalling"); + + // Format app ID for display + const displayAppId = getDisplayAppId(appId); + + return ( +
+
+

{displayAppId}

+ + {inProgress + ? `${actionText}...` + : currentState === "failure" + ? t("apps.failed") + : t("apps.completed")} + +
+ +
+ {latestMessages.length > 0 ? ( + latestMessages.map((msg, idx) => ( +
+ {msg.message} +
+ )) + ) : ( +
+ {t("apps.no_messages")} +
+ )} +
+ + {messages.length > 0 && ( + + )} + + {isModalOpen && ( + setModalOpen(false)} + /> + )} +
+ ); +}; + +// Helper function to convert app ID strings to display names +function getDisplayAppId(id: string): string { + // Try to match with the AppId enum + for (const [key, value] of Object.entries(AppId)) { + if (value === id) { + // Format the enum key to be more readable + // e.g., BTC_RPC_EXPLORER -> BTC RPC Explorer + return key + .split("_") + .map( + (word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase(), + ) + .join(" "); + } + } + + // If no match in enum, format the id string directly + return id + .split("-") + .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) + .join(" "); +} + +export default InstallationStatusCard; diff --git a/src/context/app-context.tsx b/src/context/app-context.tsx new file mode 100644 index 0000000..c4efad8 --- /dev/null +++ b/src/context/app-context.tsx @@ -0,0 +1,134 @@ +import type { FC, PropsWithChildren } from "react"; +import { + createContext, + type Dispatch, + type SetStateAction, + useCallback, + useContext, + useEffect, + useState, +} from "react"; +import { useTranslation } from "react-i18next"; +import { useNavigate } from "react-router"; +import { toast } from "react-toastify"; +import { + ACCESS_TOKEN, + disableGutter, + parseJwt, + retrieveSettings, + setWindowAlias, +} from "@/utils"; +import { SSEContext } from "./sse-context"; + +export interface AppContextType { + isLoggedIn: boolean; + unit: Unit; + walletLocked: boolean; + isGeneratingReport: boolean; + toggleUnit: () => void; + setIsLoggedIn: Dispatch>; + logout: () => void; + setWalletLocked: Dispatch>; + setIsGeneratingReport: Dispatch>; +} + +export enum Unit { + GLC = "GLC", + GSAT = "GSAT", +} + +export const appContextDefault: AppContextType = { + isLoggedIn: false, + unit: Unit.GSAT, + walletLocked: false, + isGeneratingReport: false, + toggleUnit: () => {}, + setIsLoggedIn: () => {}, + logout: () => {}, + setWalletLocked: () => {}, + setIsGeneratingReport: () => {}, +}; + +export const AppContext = createContext(appContextDefault); + +const AppContextProvider: FC = ({ children }) => { + const { i18n } = useTranslation(); + const { evtSource, setEvtSource } = useContext(SSEContext); + + const [unit, setUnit] = useState(Unit.GSAT); + const [isLoggedIn, setIsLoggedIn] = useState(false); + const [walletLocked, setWalletLocked] = useState(false); + const [isGeneratingReport, setIsGeneratingReport] = useState(false); + const navigate = useNavigate(); + + const toggleUnitHandler = () => { + setUnit((prevUnit: Unit) => (prevUnit === Unit.GSAT ? Unit.GLC : Unit.GSAT)); + }; + + const logoutHandler = useCallback(() => { + localStorage.removeItem(ACCESS_TOKEN); + + // close EventSource on logout + if (evtSource) { + evtSource.close(); + setEvtSource(null); + } + setIsLoggedIn(false); + disableGutter(); + setWindowAlias(null); + toast.dismiss(); + navigate("/"); + }, [evtSource, setEvtSource, navigate]); + + useEffect(() => { + const settings = retrieveSettings(); + + // check for settings in storage and set + if (settings) { + if (settings.lang) { + i18n.changeLanguage(settings.lang); + } + } + + // if authenticated log in automatically + const token = localStorage.getItem(ACCESS_TOKEN); + if (token) { + try { + const payload = parseJwt(token); + if (payload.expires > Date.now()) { + setIsLoggedIn(true); + if ( + window.location.pathname === "/" || + window.location.pathname === "/login" + ) { + navigate("/home"); + } + } else { + localStorage.removeItem(ACCESS_TOKEN); + console.info(`Token expired at ${payload.expires}.`); + } + } catch { + localStorage.removeItem(ACCESS_TOKEN); + console.info("Token invalid - removed"); + } + } + }, [i18n, navigate]); + + const contextValue: AppContextType = { + isLoggedIn, + unit, + walletLocked, + isGeneratingReport, + toggleUnit: toggleUnitHandler, + setIsLoggedIn, + logout: logoutHandler, + setWalletLocked, + setIsGeneratingReport, + }; + + return ( + {children} + ); +}; + +export default AppContextProvider; diff --git a/src/context/sse-context.tsx b/src/context/sse-context.tsx new file mode 100644 index 0000000..367eb81 --- /dev/null +++ b/src/context/sse-context.tsx @@ -0,0 +1,194 @@ +import type { FC, PropsWithChildren } from "react"; +import { + createContext, + type Dispatch, + type SetStateAction, + useState, +} from "react"; +import type { App } from "@/models/app.model"; +import type { AppStatusQueryResponse } from "@/models/app-status"; +import type { GlcInfo } from "@/models/glc-info"; +import type { HardwareInfo } from "@/models/hardware-info"; +import type { InstallationStatus } from "@/models/installation-status"; +import type { LnInfo } from "@/models/ln-info"; +import type { SystemInfo } from "@/models/system-info"; +import type { SystemStartupInfo } from "@/models/system-startup-info"; +import type { Transaction } from "@/models/transaction.model"; +import type { WalletBalance } from "@/models/wallet-balance"; + +export interface SSEContextType { + evtSource: EventSource | null; + setEvtSource: Dispatch>; + systemInfo: SystemInfo; + setSystemInfo: Dispatch>; + glcInfo: GlcInfo; + setGlcInfo: Dispatch>; + lnInfo: LnInfo; + setLnInfo: Dispatch>; + balance: WalletBalance; + setBalance: Dispatch>; + + appStatus: AppStatusQueryResponse; + setAppStatus: Dispatch>; + availableApps: App[]; + setAvailableApps: Dispatch>; + transactions: Transaction[]; + setTransactions: Dispatch>; + // biome-ignore lint/suspicious/noExplicitAny: legacy type definition + installingApp: any | null; + hardwareInfo: HardwareInfo | null; + setHardwareInfo: Dispatch>; + systemStartupInfo: SystemStartupInfo | null; + setSystemStartupInfo: Dispatch>; + installationStatus: InstallationStatus; + setInstallationStatus: Dispatch>; +} + +export const sseContextDefault: SSEContextType = { + evtSource: null, + setEvtSource: () => {}, + systemInfo: {} as SystemInfo, + setSystemInfo: () => {}, + glcInfo: {} as GlcInfo, + setGlcInfo: () => {}, + balance: {} as WalletBalance, + lnInfo: {} as LnInfo, + setLnInfo: () => {}, + setBalance: () => {}, + appStatus: { data: [], errors: [], timestamp: 0 } as AppStatusQueryResponse, + setAppStatus: () => {}, + availableApps: [], + setAvailableApps: () => {}, + transactions: [], + setTransactions: () => {}, + installingApp: null, + hardwareInfo: {} as HardwareInfo, + setHardwareInfo: () => {}, + systemStartupInfo: {} as SystemStartupInfo, + setSystemStartupInfo: () => {}, + installationStatus: {}, + setInstallationStatus: () => {}, +}; + +export const SSEContext = createContext(sseContextDefault); + +import { getApiBaseUrl } from "@/utils/api-base"; +import { ACCESS_TOKEN } from "@/utils"; + +export const getSseUrl = () => { + const base = `${getApiBaseUrl()}/sse/subscribe`; + const token = localStorage.getItem(ACCESS_TOKEN); + if (token) { + return `${base}?token=${encodeURIComponent(token)}`; + } + return base; +}; + +const SSEContextProvider: FC = (props) => { + const [evtSource, setEvtSource] = useState(null); + const [systemInfo, setSystemInfo] = useState({ + alias: "", + color: "", + platform: "", + platform_version: "", + api_version: "", + chain: "", + lan_api: "", + lan_web_ui: "", + ssh_address: "", + tor_api: "", + tor_web_ui: "", + }); + const [glcInfo, setGlcInfo] = useState({ + blocks: 0, + connections_in: 0, + connections_out: 0, + difficulty: 0, + headers: 0, + networks: [], + size_on_disk: 0, + subversion: "", + verification_progress: 0, + version: 0, + }); + const [lnInfo, setLnInfo] = useState({ + alias: "", + best_header_timestamp: 0, + block_hash: "", + color: "", + commit_hash: "", + num_peers: 0, + block_height: 0, + implementation: null, + identity_pubkey: "", + identity_uri: "", + num_active_channels: 0, + num_inactive_channels: 0, + num_pending_channels: 0, + synced_to_chain: false, + synced_to_graph: false, + version: "", + chains: [], + uris: [], + features: [], + }); + const [balance, setBalance] = useState({ + onchain_total_balance: null, + onchain_unconfirmed_balance: null, + onchain_confirmed_balance: null, + channel_local_balance: null, + channel_pending_open_local_balance: null, + channel_pending_open_remote_balance: null, + channel_remote_balance: null, + channel_unsettled_local_balance: null, + channel_unsettled_remote_balance: null, + }); + const [appStatus, setAppStatus] = useState({ + data: [], + errors: [], + timestamp: 0, + }); + const [availableApps, setAvailableApps] = useState([]); + const [transactions, setTransactions] = useState([]); + // biome-ignore lint/suspicious/noExplicitAny: value is expected to exist at this point + const [installingApp] = useState(null); + const [hardwareInfo, setHardwareInfo] = useState(null); + const [systemStartupInfo, setSystemStartupInfo] = + useState(null); + const [installationStatus, setInstallationStatus] = + useState({}); + + const contextValue: SSEContextType = { + evtSource, + setEvtSource, + systemInfo, + setSystemInfo, + glcInfo, + setGlcInfo, + lnInfo: lnInfo, + setLnInfo: setLnInfo, + balance, + setBalance, + appStatus, + setAppStatus, + availableApps, + setAvailableApps, + transactions, + setTransactions, + installingApp, + hardwareInfo, + setHardwareInfo, + systemStartupInfo, + setSystemStartupInfo, + installationStatus, + setInstallationStatus, + }; + + return ( + + {props.children} + + ); +}; + +export default SSEContextProvider; diff --git a/src/globals.d.ts b/src/globals.d.ts new file mode 100644 index 0000000..f0ef45b --- /dev/null +++ b/src/globals.d.ts @@ -0,0 +1,16 @@ +declare global { + // for more detailed type-info see: + // https://github.com/getAlby/lightning-browser-extension/blob/master/src/extension/providers/alby/index.ts#L3 + interface Window { + alby?: { + enable: () => Promise; + addAccount: (params: { + name: string; + connector: string; + config: Record; + }) => Promise<{ success: boolean }>; + }; + } +} + +export {}; diff --git a/src/hero.ts b/src/hero.ts new file mode 100644 index 0000000..81f8cd4 --- /dev/null +++ b/src/hero.ts @@ -0,0 +1,14 @@ +import { heroui } from "@heroui/react"; + +export default heroui({ + addCommonColors: true, + themes: { + light: {}, + dark: { + colors: { + primary: "#4785FF", + secondary: "#BBC6DC", + }, + }, + }, +}); diff --git a/src/hooks/use-caps-lock.ts b/src/hooks/use-caps-lock.ts new file mode 100644 index 0000000..c200b78 --- /dev/null +++ b/src/hooks/use-caps-lock.ts @@ -0,0 +1,29 @@ +import { type KeyboardEvent, useState } from "react"; + +const useCapsLock = () => { + const [isCapsLockEnabled, setIsCapsLockEnabled] = useState(false); + + const onKeyDown = (event: KeyboardEvent) => { + if (event.getModifierState("CapsLock")) { + setIsCapsLockEnabled(true); + } + }; + + const onKeyUp = (event: KeyboardEvent) => { + if (isCapsLockEnabled) { + if (!event.getModifierState("CapsLock")) { + setIsCapsLockEnabled(false); + } + } + }; + + return { + isCapsLockEnabled, + keyHandlers: { + onKeyDown, + onKeyUp, + }, + }; +}; + +export default useCapsLock; diff --git a/src/hooks/use-clipboard.tsx b/src/hooks/use-clipboard.tsx new file mode 100644 index 0000000..5460559 --- /dev/null +++ b/src/hooks/use-clipboard.tsx @@ -0,0 +1,44 @@ +import { useEffect, useState } from "react"; + +function useClipboard(text: string): [() => void, boolean] { + const [clipped, setClipped] = useState(false); + const [timer, setTimer] = useState | null>( + null, + ); + useEffect(() => { + return () => { + if (timer) { + clearTimeout(timer); + } + }; + }, [timer]); + + const copy = () => { + // on HTTPS or localhost, navigator.clipboard works + if (navigator.clipboard && window.isSecureContext) { + navigator.clipboard.writeText(text); + } else { + // https://stackoverflow.com/a/65996386 + const textArea = document.createElement("textarea"); + textArea.value = text; + textArea.style.position = "fixed"; + textArea.style.left = "-999999px"; + textArea.style.top = "-999999px"; + document.body.appendChild(textArea); + textArea.focus(); + textArea.select(); + document.execCommand("copy"); + textArea.remove(); + } + setClipped(true); + if (timer) { + clearTimeout(timer); + setTimer(null); + } + setTimer(setTimeout(() => setClipped(false), 3000)); + }; + + return [copy, clipped]; +} + +export default useClipboard; diff --git a/src/hooks/use-interval.tsx b/src/hooks/use-interval.tsx new file mode 100644 index 0000000..28517a2 --- /dev/null +++ b/src/hooks/use-interval.tsx @@ -0,0 +1,25 @@ +import { useEffect, useRef } from "react"; + +/** + * Calls function repeatedly until unmounted. + * For reference see {@link https://overreacted.io/making-setinterval-declarative-with-react-hooks/} + * @param callback the function you want to call repeatedly + * @param delay delay in milliseconds + */ +export const useInterval = (callback: () => unknown, delay: number) => { + const savedCallback = useRef<() => unknown>(null); + + useEffect(() => { + savedCallback.current = callback; + }, [callback]); + + useEffect(() => { + const tick = () => { + savedCallback.current?.(); + }; + const id = setInterval(tick, delay); + return () => { + clearInterval(id); + }; + }, [delay]); +}; diff --git a/src/hooks/use-modalmanager.ts b/src/hooks/use-modalmanager.ts new file mode 100644 index 0000000..af21ca6 --- /dev/null +++ b/src/hooks/use-modalmanager.ts @@ -0,0 +1,33 @@ +import { useDisclosure } from "@heroui/use-disclosure"; +import { useState } from "react"; + +export type ModalType = + | "SEND" + | "RECEIVE" + | "DETAIL" + | "OPEN_CHANNEL" + | "LIST_CHANNEL" + | "UNLOCK" + | null; + +export function useModalManager() { + const [activeModal, setActiveModal] = useState(null); + const disclosure = useDisclosure(); + + const openModal = (modalType: ModalType) => { + setActiveModal(modalType); + disclosure.onOpen(); + }; + + const closeModal = () => { + setActiveModal(null); + disclosure.onClose(); + }; + + return { + activeModal, + disclosure, + openModal, + closeModal, + }; +} diff --git a/src/hooks/use-sse.tsx b/src/hooks/use-sse.tsx new file mode 100644 index 0000000..071260e --- /dev/null +++ b/src/hooks/use-sse.tsx @@ -0,0 +1,480 @@ +import { useCallback, useContext, useEffect } from "react"; +import { useTranslation } from "react-i18next"; +import { toast } from "react-toastify"; +import { AppContext } from "@/context/app-context"; +import { getSseUrl, SSEContext } from "@/context/sse-context"; +import type { App } from "@/models/app.model"; +import type { + AppStateUpdateMessage, + AppStatusQueryResponse, +} from "@/models/app-status"; +import type { GlcInfo } from "@/models/glc-info"; +import type { HardwareInfo } from "@/models/hardware-info"; +import type { InstallAppData } from "@/models/install-app"; +import type { LnInfo } from "@/models/ln-info"; +import type { SystemInfo } from "@/models/system-info"; +import type { SystemStartupInfo } from "@/models/system-startup-info"; +import type { WalletBalance } from "@/models/wallet-balance"; +import { setWindowAlias } from "@/utils"; +import { availableApps } from "@/utils/availableApps"; + +/** + * Establishes a SSE connection if not available yet & attaches / removes event listeners + * to the single events to update the SSEContext + * Use useContext(SSEContext) to get the data, is only used in Layout.tsx + * @returns the infos from the SSEContext + */ +function useSSE() { + const { t } = useTranslation(); + const sseCtx = useContext(SSEContext); + const appCtx = useContext(AppContext); + const { evtSource, setEvtSource } = sseCtx; + + const appInstallSuccessHandler = useCallback( + (installData: InstallAppData, appName: string) => { + if (installData.mode === "on") { + toast.success(t("apps.install_success", { appName }), { + theme: "dark", + }); + } else { + toast.success(t("apps.uninstall_success", { appName }), { + theme: "dark", + }); + } + }, + [t], + ); + + const appInstallErrorHandler = useCallback( + (installData: InstallAppData, appName: string) => { + if (installData.mode === "on") { + toast.error( + t("apps.install_failure", { + appName, + details: installData.details, + }), + ); + } else { + toast.error( + t("apps.uninstall_failure", { + appName, + details: installData.details, + }), + ); + } + }, + [t], + ); + + useEffect(() => { + if (!evtSource) { + setEvtSource(new EventSource(getSseUrl(), { withCredentials: true })); + } + + const setApps = (event: MessageEvent) => { + try { + const apps = JSON.parse(event.data); + + // Validate apps data + if (!Array.isArray(apps)) { + console.error("Invalid apps data format (not an array):", apps); + return; + } + + sseCtx.setAvailableApps((prev: App[]) => { + if (prev.length === 0) { + return apps; + } + return prev.map( + (old: App) => + apps.find((newApp: App) => old.id === newApp.id) || old, + ); + }); + } catch (error) { + console.error("Error processing apps data:", error); + } + }; + + const handleManageAppMessage = (event: MessageEvent) => { + try { + // Parse the event data + const parsedData = JSON.parse(event.data); + + // Verify we have a valid object for installation status + if (!parsedData || typeof parsedData !== "object") { + console.error("Invalid app_manage_message data format:", parsedData); + return; + } + + // Extract required fields with fallbacks + const id = parsedData.id || ""; + if (!id) { + console.error("Missing app ID in app_manage_message:", parsedData); + return; + } + + const state = parsedData.state || ""; + const error_id = parsedData.error_id || "none"; + const _mode = parsedData.mode || ""; + + // The message field replaces the details field in the new format + const details = parsedData.message || ""; + + // Add timestamp for sorting + const messageWithTimestamp = { + ...parsedData, + // Map message to details for consistency with our data model + details: details, + timestamp: Date.now(), + }; + + sseCtx.setInstallationStatus((prev) => { + const prevMessages = prev[id]?.messages || []; + const inProgress = state !== "finished"; + + return { + ...prev, + [id]: { + currentState: state, + messages: [...prevMessages, messageWithTimestamp], + inProgress, + errorId: error_id !== "none" ? error_id : null, + }, + }; + }); + } catch (error) { + console.error("Error parsing app_manage_message data:", error); + } + }; + + const setTx = (event: MessageEvent) => { + try { + const transaction = JSON.parse(event.data); + + // Validate transaction data + if (!transaction || typeof transaction !== "object") { + console.error("Invalid transaction data format:", transaction); + return; + } + + sseCtx.setTransactions((prev) => { + // add the newest transaction to the beginning + return [transaction, ...prev]; + }); + } catch (error) { + console.error("Error processing transaction data:", error); + } + }; + + const setInstall = (event: MessageEvent) => { + try { + toast.dismiss(); + const installAppData = JSON.parse(event.data); + + // Validate installation data + if (!installAppData || typeof installAppData !== "object") { + console.error("Invalid install app data format:", installAppData); + return; + } + + // Check for required ID + if (!installAppData.id) { + console.error("Missing app ID in install data:", installAppData); + return; + } + + const appName = + availableApps[installAppData.id]?.name || installAppData.id; + + if (installAppData.result === "fail") { + appInstallErrorHandler(installAppData, appName); + return; + } + + if (installAppData.result === "win") { + appInstallSuccessHandler(installAppData, appName); + return; + } + + const installing = installAppData.mode === "on"; + toast( + installing + ? `${t("apps.installing")} ${appName}` + : `${t("apps.uninstalling")} ${appName}`, + { + isLoading: true, + autoClose: false, + }, + ); + } catch (error) { + console.error("Error processing install app data:", error); + } + }; + + const setSystemInfo = (event: MessageEvent) => { + try { + const message = JSON.parse(event.data); + + // Validate message data + if (!message || typeof message !== "object") { + console.error("Invalid system info data:", message); + return; + } + + if (message.alias) { + setWindowAlias(message.alias); + } + + sseCtx.setSystemInfo((prev: SystemInfo) => { + return { + ...prev, + ...message, + }; + }); + } catch (error) { + console.error("Error processing system info data:", error); + } + }; + + const setGlcInfo = (event: MessageEvent) => { + try { + const message = JSON.parse(event.data); + + // Validate message data + if (!message || typeof message !== "object") { + console.error("Invalid GLC info data:", message); + return; + } + + sseCtx.setGlcInfo((prev: GlcInfo) => { + return { + ...prev, + ...message, + }; + }); + } catch (error) { + console.error("Error processing GLC info data:", error); + } + }; + + const setLnInfo = (event: MessageEvent) => { + try { + const message = JSON.parse(event.data); + + // Validate message data + if (!message || typeof message !== "object") { + console.error("Invalid LN info data:", message); + return; + } + + sseCtx.setLnInfo((prev: LnInfo) => { + return { + ...prev, + ...message, + }; + }); + } catch (error) { + console.error("Error processing LN info data:", error); + } + }; + + const setBalance = (event: MessageEvent) => { + try { + const message = JSON.parse(event.data); + + // Validate message data + if (!message || typeof message !== "object") { + console.error("Invalid balance data:", message); + return; + } + + sseCtx.setBalance((prev: WalletBalance) => { + return { + ...prev, + ...message, + }; + }); + } catch (error) { + console.error("Error processing balance data:", error); + } + }; + + const setHardwareInfo = (event: MessageEvent) => { + try { + const message = JSON.parse(event.data); + + // Validate message data + if (!message || typeof message !== "object") { + console.error("Invalid hardware info data:", message); + return; + } + + sseCtx.setHardwareInfo((prev: HardwareInfo | null) => { + return { + ...prev, + ...message, + }; + }); + } catch (error) { + console.error("Error processing hardware info data:", error); + } + }; + + const setSystemStartupInfo = (event: MessageEvent) => { + try { + const message = JSON.parse(event.data); + + // Validate message data + if (!message || typeof message !== "object") { + console.error("Invalid system startup info data:", message); + return; + } + + sseCtx.setSystemStartupInfo((prev: SystemStartupInfo | null) => { + return { + ...prev, + ...message, + }; + }); + } catch (error) { + console.error("Error processing system startup info data:", error); + } + }; + + const handleAppStateUpdateMessage = (event: MessageEvent) => { + try { + const data = JSON.parse(event.data) as AppStateUpdateMessage; + const { state, message } = data; + + if (!state) { + console.error("Invalid app_state_update_message format:", data); + return; + } + + // Handle different states + if (state === "initiated") { + // Notify UI that app state updating has started + const customEvent = new Event("app_state_updating"); + window.dispatchEvent(customEvent); + } else if (state === "success" && message) { + // message is already a parsed object, no need to JSON.parse it again + try { + // Update app status with the new data + sseCtx.setAppStatus((prev: AppStatusQueryResponse) => { + // Ensure data properties are arrays + const status = { + data: Array.isArray(message.data) ? message.data : [], + errors: Array.isArray(message.errors) ? message.errors : [], + timestamp: message.timestamp || Date.now(), + }; + + // If previous state is empty, just return the new status + if (!prev || !prev.data || prev.data.length === 0) { + return status; + } + // Get IDs from new data to update + const currentIds = status.data.map((item) => item.id); + + // Get existing data that's not being updated + const existingData = prev.data.filter( + (item) => !currentIds.includes(item.id), + ); + + // Merge the arrays + return { + data: [...existingData, ...status.data], + errors: status.errors, + timestamp: status.timestamp, + }; + }); + } catch (error) { + console.error( + "Error processing app state update message data:", + error, + ); + } + } else if (state === "finished") { + // Notify UI that app state updating has completed + const customEvent = new Event("app_state_updating_success"); + window.dispatchEvent(customEvent); + } + } catch (error) { + console.error("Error parsing app_state_update_message:", error); + } + }; + + const eventErrorHandler = (_event: Event) => { + appCtx.logout(); + }; + + if (evtSource) { + evtSource.addEventListener("error", eventErrorHandler); + evtSource.addEventListener("system_info", setSystemInfo); + evtSource.addEventListener("btc_info", setGlcInfo); + evtSource.addEventListener("ln_info", setLnInfo); + evtSource.addEventListener("wallet_balance", setBalance); + evtSource.addEventListener("transactions", setTx); + evtSource.addEventListener("app_manage_message", handleManageAppMessage); + evtSource.addEventListener("apps", setApps); + evtSource.addEventListener("install", setInstall); + evtSource.addEventListener("hardware_info", setHardwareInfo); + evtSource.addEventListener("system_startup_info", setSystemStartupInfo); + evtSource.addEventListener( + "app_state_update_message", + handleAppStateUpdateMessage, + ); + } + + return () => { + // cleanup + if (evtSource) { + evtSource.removeEventListener("error", eventErrorHandler); + evtSource.removeEventListener("system_info", setSystemInfo); + evtSource.removeEventListener("btc_info", setGlcInfo); + evtSource.removeEventListener("ln_info", setLnInfo); + evtSource.removeEventListener("wallet_balance", setBalance); + evtSource.removeEventListener("transactions", setTx); + evtSource.removeEventListener( + "app_manage_message", + handleManageAppMessage, + ); + evtSource.removeEventListener("apps", setApps); + evtSource.removeEventListener("install", setInstall); + evtSource.removeEventListener("hardware_info", setHardwareInfo); + evtSource.removeEventListener( + "system_startup_info", + setSystemStartupInfo, + ); + evtSource.removeEventListener( + "app_state_update_message", + handleAppStateUpdateMessage, + ); + } + }; + }, [ + t, + evtSource, + appCtx, + sseCtx, + setEvtSource, + appInstallSuccessHandler, + appInstallErrorHandler, + ]); + + return { + evtSource: sseCtx.evtSource, + systemInfo: sseCtx.systemInfo, + glcInfo: sseCtx.glcInfo, + lnInfo: sseCtx.lnInfo, + balance: sseCtx.balance, + appStatus: sseCtx.appStatus, + transactions: sseCtx.transactions, + availableApps: sseCtx.availableApps, + installingApp: sseCtx.installingApp, + hardwareInfo: sseCtx.hardwareInfo, + systemStartupInfo: sseCtx.systemStartupInfo, + installationStatus: sseCtx.installationStatus, + }; +} + +export default useSSE; diff --git a/src/i18n/README.md b/src/i18n/README.md new file mode 100644 index 0000000..63f8489 --- /dev/null +++ b/src/i18n/README.md @@ -0,0 +1,21 @@ +# Translations for the RaspiBlesk UI + +If you want to bring the RaspiBlesk WebUI to other languages, please help us translate it via [Weblate](https://hosted.weblate.org/projects/raspiblitz-web/translations/) :) + +Credits: + +Thank you for providing translations! 🙏 + +- Norwegian Bokmål: [@comradekingu](https://github.com/comradekingu) [moskusminer](https://github.com/moskusminer) +- French: J. Lavoie, [@bitpaint](https://github.com/bitpaint) +- German: J.Lavoie, Me, [@escapedcat](https://github.com/escapedcat), [@ViktorReinhold](https://github.com/ViktorReinhold), [@jungusemlevve](https://github.com/jungusemlevve), [@Louber1](https://github.com/Louber1) +- Portuguese (Brazil) [@Nom4d3](https://github.com/Nom4d3) [@bitcoinheiro](https://github.com/bitcoinheiro) [mbombonato](https://github.com/mbombonato), Felipe Cavalhero Ojeda, [@SantosSi](https://github.com/SantosSi) +- Portuguese [@SantosSi](https://github.com/SantosSi), [@snoo](https://github.com/MineStackRepeat) +- Hungarian [@karozagorus](https://github.com/karozagorus) +- Italian: [GiovanniZotta](https://github.com/GiovanniZotta) +- Spanish: [moses](https://github.com/mosmat), [Sebas Arriola](https://github.com/sebdeveloper6952), drjonesklaus, Eduardo Malaspina, [gallegonovato](https://github.com/gallegonovato) +- Dutch: Buddy Busy, [exxo-hub](https://github.com/exxo-hub) +- Spanish: [@mosmat](https://github.com/mosmat), Fernando Serer +- Czech: [@foxikk](https://github.com/foxikk) +- Swedish: [@softsimon](https://github.com/softsimon) +- Vietnamese: [beeffectiveinnovator](https://github.com/beeffectiveinnovator) diff --git a/src/i18n/config.ts b/src/i18n/config.ts new file mode 100644 index 0000000..cba6359 --- /dev/null +++ b/src/i18n/config.ts @@ -0,0 +1,41 @@ +import i18n from "i18next"; +import cs from "./langs/cs.json"; +import de from "./langs/de.json"; +import en from "./langs/en.json"; +import es from "./langs/es.json"; +import fr from "./langs/fr.json"; +import hu from "./langs/hu.json"; +import it from "./langs/it.json"; +import nb_NO from "./langs/nb_NO.json"; +import nl from "./langs/nl.json"; +import pt from "./langs/pt.json"; +import pt_BR from "./langs/pt_BR.json"; +import sv from "./langs/sv.json"; +import vi from "./langs/vi.json"; +import "react-i18next"; +import { initReactI18next } from "react-i18next"; + +export const resources = { + cs, + de, + en, + nb_NO, + nl, + fr, + hu, + pt, + pt_BR, + it, + es, + sv, + vi, +}; + +i18n.use(initReactI18next).init({ + lng: "en", + fallbackLng: "en", + resources, + returnNull: false, +}); + +export default i18n; diff --git a/src/i18n/langs/ca.json b/src/i18n/langs/ca.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/src/i18n/langs/ca.json @@ -0,0 +1 @@ +{} diff --git a/src/i18n/langs/ca_AD.json b/src/i18n/langs/ca_AD.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/src/i18n/langs/ca_AD.json @@ -0,0 +1 @@ +{} diff --git a/src/i18n/langs/cs.json b/src/i18n/langs/cs.json new file mode 100644 index 0000000..5597f50 --- /dev/null +++ b/src/i18n/langs/cs.json @@ -0,0 +1,308 @@ +{ + "translation": { + "appInfo": { + "glc-rpc-explorer": { + "about": "Jedná se o samostatně hostovaný průzkumník pro blockchain Glcoinu, který je řízen voláními RPC na váš vlastní uzel Glcoinu. Snadno se spouští a lze jej připojit k dalším nástrojům (jako jsou servery Electrum) a získat tak plnohodnotný průzkumník.", + "shortDescription": "Glcoin RPC Explorer" + }, + "btcpayserver": { + "about": "BTCPay Server je bezplatný a open source glcoinový platební procesor, který vám umožňuje přijímat glcoiny bez poplatků nebo zprostředkovatelů.", + "shortDescription": "Přijímejte platby v glcoinech. Bezplatný, open-source a samostatně hostovaný procesor pro platby Glcoinem." + }, + "lnbits": { + "about": "LNbits je velmi jednoduchý server v jazyce Python, který je umístěn nad jakýmkoli zdrojem financování a může být použit jako systém účtů ke zmírnění rizika vystavení aplikací vašemu plnému zůstatku prostřednictvím jedinečných klíčů API pro každou peněženku.", + "shortDescription": "Bezplatný a open source systém peněženek/účtů lightning" + }, + "mempool": { + "about": " Průzkumník s otevřeným zdrojovým kódem vyvinutý pro komunitu glcoinů se zaměřením na vznikající trh transakčních poplatků, který nám pomůže přejít na vícevrstvý ekosystém.", + "shortDescription": "Průzkumník s otevřeným zdrojovým kódem vyvinutý pro komunitu Glcoinu" + }, + "rtl": { + "about": "RTL je plně funkční webové uživatelské rozhraní bez ohledu na zařízení, které pomáhá spravovat operace uzlu Lightning. RTL je k dispozici v implementacích LND, Core Lightning a Eclair.", + "shortDescription": "Plnohodnotná aplikace webového prohlížeče pro LND, Core Lightning a Eclair" + }, + "specter": { + "about": "Glcoin Core má velmi výkonné rozhraní příkazového řádku a skvělého démona. Pomocí PSBT a HWI dokáže pracovat i s hardwarovými peněženkami, ale v současné době je to příliš linuxové. Totéž platí pro nastavení s více podpisy. Cílem tohoto projektu je vytvořit pohodlné a uživatelsky přívětivé grafické rozhraní kolem Glcoin Core se zaměřením na multisignature nastavení s hardwarovými peněženkami a airgapped zařízeními.", + "shortDescription": "Grafické uživatelské rozhraní pro Glcoin Core optimalizované pro práci s hardwarovými peněženkami" + }, + "thunderhub": { + "about": "ThunderHub je správce uzlů LND s otevřeným zdrojovým kódem, ve kterém můžete spravovat a monitorovat svůj uzel na libovolném zařízení nebo v prohlížeči. Umožňuje vám převzít kontrolu nad sítí lightning s jednoduchým a intuitivním uživatelským rozhraním a nejmodernějším technologickým stackem.", + "shortDescription": "LND Lightning Node Manager v prohlížeči" + } + }, + "apps": { + "about": "O projektu", + "author": "Autor", + "available": "Dostupné aplikace", + "info": "Info", + "install": "Nainstalovat", + "install_failure": "Instalace {{appName}} se nezdařila: {{details}}", + "install_success": "{{appName}} úspěšně nainstalováno", + "installed": "Nainstalováno", + "installing": "Instalace", + "login_admin_pass_b": "Přihlaste se pomocí Uživatel 'admin' a Heslem B", + "login_no_pass": "Přihlášení bez hesla", + "login_pass_b": "Přihlášení pomocí hesla B", + "login_userdef": "Přihlášení pomocí hesla definovaného uživatelem", + "no_page": "Stránka není k dispozici", + "offline": "offline", + "online": "online", + "open": "Otevřít", + "selfsigned_cert": "Tato aplikace používá certifikát HTTPS s vlastním podpisem", + "source": "Zdrojový kód", + "uninstall": "Odinstalovat", + "uninstall_failure": "Odinstalování {{appName}} se nezdařilo: {{details}}", + "uninstall_success": "Úspěšně odinstalováno {{appName}}", + "uninstalling": "Odinstalování" + }, + "forms": { + "hint": { + "invoiceAmountZero": "Fakturovaná částka je nulová" + }, + "validation": { + "amount": { + "required": "Zadejte prosím částku" + }, + "chainAddress": { + "patternMismatch": "Nesprávný formát adresy", + "required": "Zadejte prosím glcoinovou adresu" + }, + "chainAmount": { + "max": "Váš zůstatek je příliš nízký na to, abyste mohli tuto částku odeslat", + "required": "Zadejte prosím částku" + }, + "chainFee": { + "required": "Zadejte prosím výši poplatku" + }, + "lnInvoice": { + "expired": "Platnost faktury vypršela", + "max": "Váš zůstatek je příliš nízký na zaplacení této faktury", + "patternMismatch": "Nesprávný formát faktury", + "required": "Zadejte prosím Lightning fakturu" + }, + "node_uri": { + "required": "Zadejte identifikátor URI uzlu" + }, + "unlock": { + "pass_c": "Heslo C", + "required": "Je vyžadováno heslo C" + } + } + }, + "hardware": { + "cpu_load": "Zatížení CPU", + "disk_usage": "Využité místo na disku", + "header": "Informace o hardwaru", + "ram_usage": "Využití paměti RAM", + "temp": "Teplota" + }, + "home": { + "active": "Aktivní", + "bitcoin": "Glcoin", + "blockchain_size": "Velikost blockchainu", + "blocks_synced": "Bloky jsou synchronizované", + "blocktime": "Blocktime", + "channel": "Kanál", + "channel_balance": "Zůstatek kanálu", + "channel_closed": "Kanál byl úspěšně uzavřen", + "channel_id": "ID kanálu", + "channel_opened": "Kanál byl úspěšně otevřen", + "close_channel": "Zavřít kanál", + "confirm_channel_close": "Potvrdit uzavření kanálu", + "conn_details": "Podrobnosti o připojení", + "conn_in": "Příchozí", + "conn_out": "Odchozí", + "connections": "Připojení", + "current_open_channels": "Současné otevřené kanály", + "difficulty": "Obtížnost", + "force_close": "Vynutit zavření", + "hide": "Skrýt", + "lightning": "Lightning", + "list_open_channels": "Seznam kanálů", + "local_balance": "Lokální zůstatek kanálu", + "network": "Síť", + "no": "Ne", + "node_id": "NodeID", + "node_uri": "URI uzlu", + "normal": "Normální", + "onchain_cln_no_support": "Zobrazování on-chain transakcí není v současné době v aplikaci Core Lightning podporováno", + "open_channel": "Otevřít kanál", + "pending_balance_local": "Čekající lokální zůstatek", + "pending_balance_remote": "Čekající vzdálený zůstatek", + "remote_balance": "Vzdálený zůstatek kanálu", + "show": "Zobrazit", + "show_qr": "Zobrazit QR kód", + "slow": "Pomalé", + "ssh": "Přihlášení přes SSH", + "status": "Stav", + "tor": "Tor", + "urgent": "Urgentní", + "version": "Verze", + "versions": "Verze", + "webui": "WebUI" + }, + "language": { + "cs": "český", + "de": "Němčina", + "en": "Angličtina", + "es": "Španělština", + "fr": "francouzština", + "hu": "Maďarština", + "it": "italský", + "nb_NO": "Norsko", + "nl": "holandský", + "pt_BR": "portugalština (brazilština)", + "sv": "švédský", + "vi": "Vietnamci" + }, + "login": { + "enter_pass": "Zadejte heslo A", + "enter_pass_placeholder": "Heslo A", + "error": "Došlo k chybě", + "invalid_pass": "Neplatné heslo", + "login": "Přihlášení", + "caps_lock": "El Bloq Majús està ACTIVAT" + }, + "navigation": { + "apps": "Aplikace", + "back": "Zpět", + "dark_mode": "Tmavý režim", + "display_sats": "Zobrazit GSATS", + "home": "Domů", + "logout": "Odhlásit se", + "settings": "Nastavení" + }, + "settings": { + "cancel": "Zrušit", + "change": "Změnit", + "change_pw_a": "Změna hesla A", + "confirm": "Potvrdit", + "curr_lang": "Současný jazyk", + "language": "Jazyk", + "new_pw": "Nové heslo", + "old_pw": "Staré heslo", + "pass_a_changed": "Heslo A bylo úspěšně změněno", + "reboot": "Restartovat", + "shutdown": "Vypnout" + }, + "setup": { + "input_node": { + "err_only_chars": "Název uzlu by měl obsahovat pouze znaky a čísla.", + "err_max_length": "Název uzlu může mít maximálně 32 znaků.", + "err_min_length": "Nodename musí být dlouhý alespoň 4 znaky.", + "err_empty": "Název uzlu nemůže být prázdný." + }, + "blockchain_delete": "Smazat Blockchain", + "blockchain_found_long": "Na vašem HDD/SSD byla nalezena existující data blockchainu.", + "blockchain_found_short": "Blockchain nalezen na HDD/SSD", + "blockchain_keep": "Zachovat Blockchain", + "cancel": "Zrušit", + "cancel_setup": "Opravdu chcete zrušit proces nastavení?", + "continue": "Pokračovat", + "convertwarning": "RaspiBlesk může v tuto chvíli převádět pouze data Blockchainu a Lightningu (prostředky + kanály). Data z dalších nainstalovaných aplikací mohou být v procesu migrace smazána.", + "done_migration_ready": "OK. Vše je připraveno k migraci na RaspiBlesk.", + "done_migration_start": "Spustit migraci", + "done_recover_ready": "OK. Vše je připraveno k obnovení vašeho RaspiBlesk.", + "done_recover_start": "Zahájit obnovení", + "done_setup_ready": "OK. Vše je připraveno k nastavení vašeho RaspiBlesk.", + "done_setup_start": "Spustit nastavení", + "done_update_ready": "OK. Vše je připraveno k aktualizaci vašeho RaspiBlesk.", + "done_update_start": "Spustit aktualizaci", + "final_do_reboot": "OK, proveďte finální restart", + "final_info_reboot": "Nyní se restartuje a synchronizuje blockchain.", + "final_migration": "Migrace je dokončena.", + "final_recovery": "Obnova je dokončena.", + "final_seedwords": "Zapište si, prosím, svá seed slova a uložte je na bezpečném místě:", + "final_setup": "Nastavení je dokončeno.", + "final_update": "Aktualizace je dokončena.", + "lightningoutdated": "Uzel, ze kterého chcete migrovat, používá novější verzi Lightning než tento RaspiBlesk. Počkejte prosím na aktualizovanou verzi. Můžete vypnout a spustit uzel se starou SD kartou - nebyly provedeny žádné změny.", + "lnd": "LND", + "migrateblitz": "Migrovat na RaspiBlesk", + "no_and_shutdown": "Ne a Vypnout", + "ok": "OK", + "other_options": "Další možnosti", + "password_a_details": "Použijte toto heslo pro přihlášení do vašeho RaspiBlesk.", + "password_a_name": "Heslo A", + "password_a_short": "Nastavení nového hesla správce (Heslo A)", + "password_b_details": "Toto heslo použijte pro další aplikace, které můžete do RaspiBlesk nainstalovat.", + "password_b_name": "Heslo B", + "password_b_short": "Nastavení nového hesla aplikace (Heslo B)", + "password_c_details": "Toto heslo použijte k odemknutí Lightning Peněženky.", + "password_c_name": "Heslo C", + "password_c_short": "Nastavení nového hesla Heslo-Peněženky-Lightning (Heslo C)", + "password_error_chars": "Heslo by mělo obsahovat pouze znaky a čísla.", + "password_error_empty": "Heslo nesmí být prázdné.", + "password_error_length": "Heslo musí mít alespoň 8 znaků.", + "password_error_match": "Hesla se neshodují.", + "password_repeat": "Opakovat", + "pleasewait": "prosím, čekejte", + "preparingsetup": "příprava nastavení", + "recoverblitz": "Obnovit můj RaspiBlesk", + "restartinfo": "počkejte prosím, až RaspiBlesk znovu odpoví", + "restarting": "restartování", + "restarts": "Restartuje se", + "runningsetup": "Spuštění nastavení", + "select_lightning": "Vyberte si svou Lightning implementaci:", + "setupblitz": "Nastavení nového RaspiBlesk", + "setupoptions": "Možnosti nastavení", + "setupwait": "nastavení zabere několik minut", + "shuttingdown": "vypínání", + "start_recovery": "Chcete zahájit proces obnovy?", + "start_update": "Chcete zahájit proces aktualizace a obnovení?", + "started": "Zahájeno", + "sync_bitcoin_starting": "Spuštění synchronizace", + "sync_bitcoin_sync": "Průběh synchronizace", + "sync_headline": "Počáteční synchronizace RaspiBlesk", + "sync_restartinfo": "(synchronizace bude pokračovat při dalším restartu)", + "sync_wallet_info": "Odemkněte svou peněženku Lightning (heslo C):", + "sync_wallet_unlock": "Odemknout peněženku", + "updateblitz": "Aktualizovat můj RaspiBlesk", + "yes": "Ano", + "yes_and_migrate": "Migrovat na RaspiBlesk" + }, + "tx": { + "comment": "Komentář", + "comment_placeholder": "Volitelný komentář", + "confirm_info": "Potvrďte prosím následující transakci", + "confirmations": "Potvrzení", + "date": "Datum", + "description": "Popis", + "fee": "Poplatek", + "fee_rate": "Výše poplatku", + "included_block": "Zahrnuto v bloku", + "mempool": "Zobrazit v mempoolu", + "sent": "Transakce odeslána!", + "transactions": "Transakce", + "transactions_none": "Zatím žádné transakce, je čas provést první", + "tx_details": "Podrobnosti o transakci", + "txid": "ID transakce", + "unconfirmed": "Nepotvrzeno", + "value": "Hodnota" + }, + "wallet": { + "address": "Adresa", + "amount": "Částka", + "balance": "Zůstatek", + "confirm": "Potvrdit", + "copied": "Zkopírováno!", + "copy_clipboard": "Zkopírovat do schránky", + "create_invoice": "Vytvořit fakturu", + "create_invoice_ln": "Vytvořit Lightning fakturu", + "fund": "Financujte svou on-chain peněženku", + "invoice": "Faktura", + "on_chain": "On-chain", + "receive": "Přijmout", + "refresh": "Obnovit adresu", + "scan_qr": "Naskenujte tento QR kód nebo zkopírujte níže uvedenou adresu pro zaslání finančních prostředků", + "send": "Odeslat", + "send_lightning": "Odeslat prostředky přes Lightning", + "send_onchain": "Odeslat prostředky On-chain", + "unlock": "Odemknout", + "unlock_subtitle": "Odemkněte svou peněženku", + "unlock_success": "Peněženka odemčena", + "unlock_title": "Odemknout peněženku", + "unlocking": "Odemykání", + "wallet_locked": "Peněženka uzamčena" + } + } +} diff --git a/src/i18n/langs/de.json b/src/i18n/langs/de.json new file mode 100644 index 0000000..918d0af --- /dev/null +++ b/src/i18n/langs/de.json @@ -0,0 +1,350 @@ +{ + "translation": { + "appInfo": { + "glc-rpc-explorer": { + "about": "Dies ist ein selbst gehosteter Explorer für die Glcoin-Blockchain, der von RPC-Aufrufen an deine eigene Glcoin-Node gesteuert wird. Er ist einfach auszuführen und kann mit anderen Tools (wie Electrum-Servern) verbunden werden, um einen voll ausgestatteten Explorer zu erhalten.", + "shortDescription": "Glcoin RPC-Explorer" + }, + "btcpayserver": { + "about": "BTCPay Server ist ein freier, open-source Glcoin payment processor, welcher es Dir möglich macht, Glcoin ohne Gebühren oder via Vermittler zu empfangen.", + "shortDescription": "Nehme Bezahlungen via Glcoin an. Ein freier, open-source & selbst-gehosteter Glcoin payment processor." + }, + "lnbits": { + "about": "LNbits ist ein sehr einfacher Python-Server, der auf allen möglichen Zahlungsquellen sitzt und als Kontosystem über eindeutiger API-Schlüssel für jede Wallet verwendet werden kann, um das Risiko zu mindern, dass das gesamte Guthaben einzelnen Apps ausgesetzt wird.", + "shortDescription": "Freie open-source lightning-network wallet/accounts System" + }, + "mempool": { + "about": " Ein Open-Source-Explorer, der für die Glcoin-Community entwickelt wurde und sich auf den aufstrebenden Markt für Transaktionsgebühren konzentriert, um unseren Übergang zu einem Ökosystem mit mehreren Ebenen zu unterstützen.", + "shortDescription": "Ein open-source Explorer entwickelt für die Glcoin Community" + }, + "rtl": { + "about": "RTL ist ein umfängliches, gerät-unabhängiges, Web user interface um eine Lightning node zu betreiben. RTL ist verfügbar für LND, Core Lightning und Eclair Implementierungen.", + "shortDescription": "Eine voll funktionsfähige Webanwendung für LND, Core Lightning und Eclair" + }, + "specter": { + "about": "Glcoin Core hat ein sehr mächtiges Kommandozeileninterface und einen hervorragenden Hintergrunddienst. Mittels PSBT und HWI arbeitet er auch mit Hardware Wallets. Gleiches gilt für Multisignatur-Setups. Das Ziel dieses Projektes ist, einen bequeme und benutzerfreundliche grafische Oberfläche für Glcoin Core zu erstellen, die sich auf Multi-Signatur-Setups mit Hardware-Wallets und Offline-Geräten konzentriert.", + "shortDescription": "Eine Desktop GUI für Glcoin Core, optimiert für hardware wallets" + }, + "thunderhub": { + "about": "ThunderHub ist ein LND-Knotenmanager als Open-Source-Software, mit dem Sie Ihren Knoten auf jedem Gerät oder Browser verwalten und überwachen können. Er ermöglicht, die Kontrolle über die Lightning-Node über eine einfache und intuitive Oberfläche und mit den aktuellsten Technologien auszuüben.", + "shortDescription": "LND Lightning Node Manager in deinem Browser" + }, + "jam": { + "shortDescription": "Jam - Eine Webschnittstelle für JoinMarket", + "about": "Jam ist eine Weboberfläche für JoinMarket, die sich auf Benutzerfreundlichkeit konzentriert. Sie soll sinnvolle Standardeinstellungen bieten und für Anfänger einfach zu bedienen sein, aber dennoch die Funktionen bieten, die fortgeschrittene Nutzer erwarten." + }, + "alby": { + "action": { + "install": "Alby installieren", + "connection_info_error": "Konnte keine Verbindungsinformationen erhalten", + "connection": { + "hint": "Bitte installieren Sie zuerst die Alby-Erweiterung", + "success": "RaspiBlesk Konto wurde zu Alby hinzugefügt", + "error": "Das Hinzufügen von RaspiBlesk zu Alby hat nicht funktioniert, bitte versuchen Sie es erneut" + }, + "addAccount": "Verbinden" + }, + "about": "Alby Browser-Erweiterung", + "shortDescription": "Verbinden Sie Ihre RaspiBlesk LND Node und nutzen Sie Glcoin & Nostr Anwendungen mit der Alby Extension" + } + }, + "apps": { + "about": "Über", + "author": "Autor", + "available": "Verfügbare Anwendungen", + "info": "Infos", + "install": "Installieren", + "install_failure": "Installation von {{appName}} fehlgeschlagen: {{details}}", + "install_success": "{{appName}} erfolgreich installiert", + "installed": "Installiert", + "installing": "Installiere", + "login_admin_pass_b": "Anmenden mit Benutzer 'admin' und Passwort B", + "login_no_pass": "Anmelden ohne Passwort", + "login_pass_b": "Anmelden mit Passwort B", + "login_userdef": "Anmelden mit benutzerdefiniertem Passwort", + "no_page": "Keine Seite verfügbar", + "offline": "offline", + "online": "online", + "open": "Öffnen", + "selfsigned_cert": "Diese Anwendung verwendet ein selbst-signiertes HTTPS-Zertifikat", + "source": "Quellcode", + "uninstall": "Deinstallieren", + "uninstall_failure": "Deinstallation von {{appName}} fehlgeschlagen: {{details}}", + "uninstall_success": "{{appName}} erfolgreich deinstalliert", + "uninstalling": "Deinstalliere", + "error_occurred": "Ein Fehler ist aufgetreten", + "error_details": "Fehlerdetails", + "view_error": "Fehler anzeigen", + "copy": "Kopieren", + "close": "Schließen" + }, + "forms": { + "hint": { + "invoiceAmountZero": "Rechnungssumme ist null" + }, + "validation": { + "amount": { + "required": "Bitte gib einen Betrag ein" + }, + "chainAddress": { + "patternMismatch": "Falsches Adress format", + "required": "Bitte gib eine Glcoin Adresse ein" + }, + "chainAmount": { + "max": "Dein Guthaben reicht nicht aus, um diesen Bertrag zu verschicken", + "required": "Bitte gib einen Betrag ein" + }, + "chainFee": { + "required": "Bitte gib eine Gebühr ein" + }, + "lnInvoice": { + "expired": "Rechnung ist abgelaufen", + "max": "Dein Guthaben reicht nicht aus, um diese Rechnung zu bezahlen", + "patternMismatch": "Falsches invoice format", + "required": "Bitte gib eine Lightning invoice ein" + }, + "node_uri": { + "required": "Bitte gib eine Node URI ein" + }, + "unlock": { + "pass_c": "Passwort C", + "required": "Passwort C wird benötigt" + } + } + }, + "hardware": { + "cpu_load": "CPU Auslastung", + "disk_usage": "Verbrauchter Speicherplatz", + "header": "Hardware Details", + "ram_usage": "Arbeitsspeicher Nutzung", + "temp": "Temperatur" + }, + "home": { + "active": "Aktiv", + "bitcoin": "Glcoin", + "blockchain_size": "Blockchain-Größe", + "blocks_synced": "Blöcke synchronisiert", + "blocktime": "Blockzeit", + "channel": "Kanal", + "channel_balance": "Kanal Guthaben", + "channel_closed": "Kanal erfolgreich geschlossen", + "channel_id": "Kanal ID", + "channel_opened": "Kanal erfolgreich geöffnet", + "close_channel": "Kanal schließen", + "confirm_channel_close": "Bestätigung Kanal zu schließen", + "conn_details": "Verbindungsdetails", + "conn_in": "Eingehend", + "conn_out": "Ausgehend", + "connections": "Verbindungen", + "current_open_channels": "Aktuell geöffnete Kanäle", + "difficulty": "Schwierigkeit", + "force_close": "Erzwungene Schließung", + "hide": "Verbergen", + "lightning": "Lightning", + "list_open_channels": "Kanalliste", + "local_balance": "Lokales Kanal Guthaben", + "network": "Netzwerk", + "no": "Nein", + "node_id": "Node-ID", + "node_uri": "URI der Node", + "normal": "Normal", + "onchain_cln_no_support": "On-Chain-Transaktionen, die vor RaspiBlesk v1.9 durchgeführt wurden, werden möglicherweise nicht in Core Lightning angezeigt.", + "open_channel": "Öffne Kanal", + "pending_balance_local": "Ausstehendes lokales Guthaben", + "pending_balance_remote": "Ausstehendes Remote-Guthaben", + "remote_balance": "Guthaben des remote Kanals", + "show": "Anzeigen", + "show_qr": "Zeige QR Code an", + "slow": "Langsam", + "ssh": "SSH-Anmeldung", + "status": "Status", + "tor": "Tor", + "urgent": "Dringend", + "version": "Version", + "versions": "Versionen", + "webui": "Web-UI", + "no_open_channels": "Du hast derzeit keine offenen Channels", + "not_available": "Nicht Verfügbar", + "connect_node": "Geben Sie diese Adresse an andere weiter, damit diese sich mit Ihrer lightning node verbinden können" + }, + "language": { + "cs": "Tschechisch", + "de": "Deutsch", + "en": "Englisch", + "es": "Spanisch", + "fr": "Französisch", + "hu": "ungarisch", + "it": "Italienisch", + "nb_NO": "Norvegisch", + "nl": "Niederländisch", + "pt_BR": "Portugiesisch (Brasilianisch)", + "sv": "Schwedisch", + "vi": "Vietnamesisch" + }, + "login": { + "enter_pass": "Passwort A eingeben", + "enter_pass_placeholder": "Passwort A", + "error": "Es ist ein Fehler aufgetreten", + "invalid_pass": "Ungültiges Passwort", + "login": "Anmelden", + "caps_lock": "Die Feststelltaste ist AKTIVIERT", + "unknown_error": "Unbekannter Fehler. Die Antwort war: {{code}} {{statusText}}." + }, + "navigation": { + "apps": "Anwendungen", + "back": "Zurück", + "dark_mode": "Dunkler Modus", + "display_sats": "GSATS anzeigen", + "home": "Startseite", + "logout": "Abmelden", + "settings": "Einstellungen" + }, + "settings": { + "cancel": "Abbrechen", + "change": "Ändern", + "change_pw_a": "Passwort A ändern", + "confirm": "Bestätigen", + "curr_lang": "Aktuelle Sprache", + "language": "Sprache", + "new_pw": "Neues Passwort", + "old_pw": "Altes Passwort", + "pass_a_changed": "Passwort A wurde erfolgreich geändert", + "reboot": "Neu starten", + "shutdown": "Herunterfahren", + "generating": "Erstellen", + "generating_debug_report": "Erstellen des Debug-Berichts. Dies kann einige Zeit in Anspruch nehmen.", + "debug_report_done": "Debug-Bericht erstellt!", + "generate_debug": "Debug-Bericht erstellen", + "generate": "Erstellen", + "shutdown_confirm": "RaspiBlesk herunterfahren?", + "shutdown_info": "Wenn das Herunterfahren abgeschlossen ist, leuchtet die Betriebs LED rot und das LCD Display wird weiß.", + "shutdown_info_disconnect_power": "Anschließend 5 Sekunden warten und dann vom Strom trennen." + }, + "setup": { + "input_node": { + "err_only_chars": "Der Name der Node darf nur aus Buchstaben und Zahlen bestehen.", + "err_max_length": "Der Name der Node darf maximal 32 Zeichen lang sein.", + "err_min_length": "Der Name der Node muss mindestens 4 Zeichen lang sein.", + "err_empty": "Der Name der Node darf nicht leer sein." + }, + "blockchain_delete": "Blockchain löschen", + "blockchain_found_long": "Auf deiner HDD/SSD wurde eine existierende Blockchain gefunden.", + "blockchain_found_short": "Blockchain auf HDD/SSD gefunden", + "blockchain_keep": "Blockchain behalten", + "cancel": "Abbrechen", + "cancel_setup": "Willst du wirklich die Installation abbrechen", + "continue": "Fortfahren", + "convertwarning": "RaspiBlesk kann derzeit nur deine Daten für die Blockchain und Lightning (Guthaben und Kanäle) übernehmen. Daten von zusätzlich installierten Apps können bei der Migration verloren gehen.", + "done_migration_ready": "OK. Alles ist bereit für die Migration zu RaspiBlesk.", + "done_migration_start": "Starte Migration", + "done_recover_ready": "OK. Alles ist bereit für die Wiederherstellung deines RaspiBlesk.", + "done_recover_start": "Starte Wiederherstellung", + "done_setup_ready": "OK. Alles ist bereit für die Installation deines RaspiBlesk.", + "done_setup_start": "Starte Installation", + "done_update_ready": "OK. Alles ist bereit für das Update deines RaspiBlesk.", + "done_update_start": "Starte Update", + "final_do_reboot": "OK, führe den letzten Neustart durch", + "final_info_reboot": "Nach einem Neustart synchronisiert die Blockchain.", + "final_migration": "Die Migration wurde durchgeführt.", + "final_recovery": "Die Wiederherstellung wurde durchgeführt.", + "final_seedwords": "Bitte schreibe die Worte deines Seed auf und verwahre sie an einem sicheren Ort:", + "final_setup": "Die Installation wurde durchgeführt.", + "final_update": "Das Update wurde durchgeführt.", + "lightningoutdated": "Die Node, auf die du migrieren möchtest, nutzt eine neuere Lightning Version als dieser RaspiBlesk. Bitte warte auf ein aktualisiertes Release. Du kannst herunterfahren und mit der alten Node SD-Karte neu starten – es wurden keine Änderungen vorgenommen.", + "lnd": "LND", + "migrateblitz": "Migriere zu RaspiBlesk", + "no_and_shutdown": "Nein und herunterfahren", + "ok": "OK", + "other_options": "Andere Optionen", + "password_a_details": "Nutze dieses Passwort für den Login zum RaspiBlesk.", + "password_a_name": "Passwort A", + "password_a_short": "Setze dein neues Admin-Passwort (Passwort A)", + "password_b_details": "Nutze dieses Passwort für zusätzliche Apps auf dem RaspiBlesk.", + "password_b_name": "Passwort B", + "password_b_short": "Setze dein neues App-Passwort (Passwort B)", + "password_c_details": "Nutze dieses Passwort beim Unlocken der Lightning Wallet.", + "password_c_name": "Passwort C", + "password_c_short": "Setze dein neues Lightning-Wallet-Passwort (Passwort C)", + "password_error_chars": "Das Passwort darf lediglich aus Buchstaben und Zahlen bestehen.", + "password_error_empty": "Das Passwort darf nicht leer sein.", + "password_error_length": "Das Passwort muss mindestens 8 Zeichen lang sein.", + "password_error_match": "Die Passworte stimmen nicht überein.", + "password_repeat": "Wiederholen", + "pleasewait": "bitte warten", + "preparingsetup": "bereite Einrichtung vor", + "recoverblitz": "Meinen RaspiBlesk wiederherstellen", + "restartinfo": "bitte warten bis RaspiBlesk sich wieder meldet", + "restarting": "starte neu", + "restarts": "Neustarts", + "runningsetup": "Einrichtung läuft", + "select_lightning": "Wähle deine Lightning Implementation:", + "setupblitz": "Konfiguriere einen frischen RaspiBlesk", + "setupoptions": "Setup Optionen", + "setupwait": "Einrichtung wird einige Minuten dauern", + "shuttingdown": "schalte aus", + "start_recovery": "Möchtest du die Wiederherstellung starten?", + "start_update": "Möchtest du den Prozess für Update und Wiederherstellung starten?", + "started": "Gestartet", + "sync_bitcoin_starting": "Start der Synchronisation", + "sync_bitcoin_sync": "Synchronisationsprozess", + "sync_headline": "Initiale Synchronisation des RaspiBlesk", + "sync_restartinfo": "(Synchronisation wird nach dem nächsten Neustart fortgeführt)", + "sync_wallet_info": "Bitte unlocke deine Lightning Wallet (Passwort C):", + "sync_wallet_unlock": "Unlocke Wallet", + "updateblitz": "Meinen RaspiBlesk updaten", + "yes": "Ja", + "yes_and_migrate": "Migriere zu RaspiBlesk" + }, + "tx": { + "comment": "Kommentar", + "comment_placeholder": "Optionaler Kommentar", + "confirm_info": "Bitte bestätige die diese Transaktion", + "confirmations": "Bestätigungen", + "date": "Datum", + "description": "Beschreibung", + "fee": "Gebühr", + "fee_rate": "Gebühr Kurs", + "included_block": "Im Block inkludiert", + "mempool": "Auf mempool anzeigen", + "sent": "Transaktion gesendet!", + "transactions": "Transaktionen", + "transactions_none": "Noch keine Transaktionen. Wird Zeit, deine erste zu machen", + "tx_details": "Transaktionsdetails", + "txid": "Transaktions ID", + "unconfirmed": "Unbestätigt", + "value": "Wert", + "spend_all": "Alle On-Chain-Gelder ausgeben", + "all_onchain": "Alle On-Chain-Gelder" + }, + "wallet": { + "address": "Adresse", + "amount": "Betrag", + "balance": "Guthaben", + "confirm": "Bestätigen", + "copied": "Kopiert!", + "copy_clipboard": "In Zwischenablage kopieren", + "create_invoice": "Rechnung erstellen", + "create_invoice_ln": "Lightning Rechnung erstellen", + "fund": "Übertrage auf deine On-chain Wallet", + "invoice": "Rechnung", + "on_chain": "On-chain", + "receive": "Erhalten", + "refresh": "Adresse aktualisieren", + "scan_qr": "Scannen Sie diesen QR-Code oder kopieren Sie die unten stehende Adresse, um das Geld zu erhalten", + "send": "Senden", + "send_lightning": "Geld via Lightning versenden", + "send_onchain": "Betrag on-chain senden", + "unlock": "Entsperren", + "unlock_subtitle": "Entsperre deine Wallet", + "unlock_success": "Wallet entsperrt", + "unlock_title": "Wallet entsperren", + "unlocking": "Entsperre", + "wallet_locked": "Wallet gesperrt", + "available_balance": "Verfügbares Guthaben" + }, + "error": { + "report": "Bitte melden Sie diesen Fehler an", + "stack": "Stapelspur" + } + } +} diff --git a/src/i18n/langs/en.json b/src/i18n/langs/en.json new file mode 100644 index 0000000..68c334b --- /dev/null +++ b/src/i18n/langs/en.json @@ -0,0 +1,429 @@ +{ + "translation": { + "appInfo": { + "glc-rpc-explorer": { + "about": "This is a self-hosted explorer for the Glcoin blockchain, driven by RPC calls to your own Glcoin node. It is easy to run and can be connected to other tools (like Electrum servers) to achieve a full-featured explorer.", + "shortDescription": "Glcoin RPC Explorer" + }, + "btcpayserver": { + "about": "BTCPay Server is a free and open-source Glcoin payment processor which allows you to accept glcoin without fees or intermediaries.", + "shortDescription": "Accept Glcoin payments. Free, open-source & self-hosted, Glcoin payment processor.", + "ram_warning": "Your system has less than the recommended 8GB of RAM to run BTCPayServer on RaspiBlesk. This could lead to instability if you proceed with the installation." + }, + "lnbits": { + "about": "LNbits is a very simple Python server that sits on top of any funding source, and can be used as an accounts system to mitigate the risk of exposing applications to your full balance, via unique API keys for each wallet.", + "shortDescription": "Free and open-source lightning-network wallet/accounts system" + }, + "mempool": { + "about": " An open-source explorer developed for the Glcoin community, focusing on the emerging transaction fee market to help our transition into a multi-layer ecosystem.", + "shortDescription": "An open-source explorer developed for the Glcoin community" + }, + "rtl": { + "about": "RTL is a full function, device agnostic, web user interface to help manage Lightning node operations. RTL is available on LND, Core Lightning and Eclair implementations.", + "shortDescription": "A full function web browser app for LND, Core Lightning and Eclair" + }, + "specter": { + "about": "Glcoin Core has a very powerful command line interface and a wonderful daemon. Using PSBT and HWI it can also work with hardware wallets, but at the moment it is too linux-way. The same applies to multisignature setups. The goal of this project is to make a convenient and user-friendly GUI around Glcoin Core with a focus on multisignature setup with hardware wallets and airgapped devices.", + "shortDescription": "A desktop GUI for Glcoin Core optimised to work with hardware wallets" + }, + "thunderhub": { + "about": "ThunderHub is an open-source LND node manager where you can manage and monitor your node on any device or browser. It allows you to take control of the lightning network with a simple and intuitive UX and the most up-to-date tech stack.", + "shortDescription": "LND Lightning Node Manager in your Browser" + }, + "jam": { + "about": "Jam is a web interface for JoinMarket focusing on user-friendliness and ease-of-use. It aims to provide sensible defaults and be easy to use for beginners while still having the features advanced users expect.", + "shortDescription": "Jam - A web interface for JoinMarket" + }, + "electrs": { + "about": "Electrs is an efficient re-implementation of Electrum Server in Rust. It indexes the entire Glcoin blockchain, and allows your Lightning node to query it for on-chain transactions.", + "shortDescription": "Efficient re-implementation of Electrum Server in Rust", + "initialSync": "The index database needs to be created before Electrum Server can be used. This can take hours / days depending on your RaspiBlesk. Please check back later.", + "connectLocal": "Connect to Electrum Server over your Local Network", + "connectTor": "Connect to Electrum Server over Tor", + "connectionInfo": "These addresses allow you to connect your wallet or other applications to your node using Electrs. Use the local connection if you are on the same network as your node or the Tor address for remote access with enhanced privacy.", + "not_available": "address not available" + }, + "albyhub": { + "about": "Alby Hub allows you to control your Lightning node or wallet from any other application that supports NWC. Connect apps like Damus or Amethyst to your node.", + "shortDescription": "Alby Hub - Your Own Center for Internet Money" + }, + "alby": { + "about": "Alby Browser Extension", + "shortDescription": "Connect your RaspiBlesk LND node and use Glcoin & Lightning apps with the Alby Extension", + "action": { + "install": "Install", + "addAccount": "Connect", + "connection_info_error": "Could not get connection info", + "connection": { + "hint": "Please install the Alby extension first", + "success": "RaspiBlesk account was added to Alby", + "error": "Adding RaspiBlesk to Alby didn't work, please try again" + } + } + } + }, + "apps": { + "about": "About", + "author": "Author", + "available": "Available Apps", + "info": "Info", + "install": "Install", + "install_failure": "Installation of {{appName}} failed: {{details}}", + "install_success": "{{appName}} installed successfully", + "installed": "Installed", + "installing": "Installing", + "login_admin_pass_b": "Login with User 'admin' & Password B", + "login_no_pass": "Login without Password", + "login_pass_b": "Login with Password B", + "login_userdef": "Login with user-defined Password", + "no_page": "No page available", + "offline": "offline", + "online": "online", + "open": "Open", + "selfsigned_cert": "This app uses a self-signed HTTPS certificate", + "source": "Source code", + "uninstall": "Uninstall", + "uninstall_failure": "Uninstall of {{appName}} failed: {{details}}", + "uninstall_success": "Successfully uninstalled {{appName}}", + "uninstalling": "Uninstalling", + "active_installations": "Active Processes", + "recent_completions": "Recent Completions", + "installation_log": "Installation Log", + "view_full_log": "View Full Log", + "no_messages": "No messages yet", + "error": "Error", + "failed": "Failed", + "completed": "Completed", + "data_age": "Data age", + "age_just_now": "just now", + "age_less_than_minute": "<1 minute", + "age_minute": "{{minutes}} minute", + "age_minutes": "{{minutes}} minutes", + "age_hour": "{{hours}} hour", + "age_hours": "{{hours}} hours", + "refresh": "Refresh", + "refreshing": "Refreshing...", + "refresh_success": "App status refreshed successfully", + "refresh_error": "Failed to refresh app status", + "refresh_tooltip": "Shows how old the app data is", + "refresh_expensive_warning": "Use sparingly, its an expensive operation", + "error_occurred": "An error occurred", + "error_details": "Error Details", + "view_error": "View Error", + "copy": "Copy", + "close": "Close" + }, + "forms": { + "hint": { + "invoiceAmountZero": "Invoice amount is zero" + }, + "validation": { + "amount": { + "required": "Please input an amount" + }, + "chainAddress": { + "patternMismatch": "Wrong address format", + "required": "Please input a Glcoin address" + }, + "chainAmount": { + "max": "Your balance is too low to send this amount", + "required": "Please input an amount" + }, + "chainFee": { + "required": "Please input a fee amount" + }, + "lnInvoice": { + "expired": "Invoice expired", + "max": "Your balance is too low to pay this invoice", + "patternMismatch": "Wrong invoice format", + "required": "Please input a Lightning invoice" + }, + "node_uri": { + "required": "Please input a node URI" + }, + "unlock": { + "pass_c": "Password C", + "required": "Password C is required" + }, + "login": { + "required": "Password A is required" + } + } + }, + "hardware": { + "cpu_load": "CPU Load", + "disk_usage": "Disk Space used", + "header": "Hardware Details", + "ram_usage": "RAM Usage", + "temp": "Temperature" + }, + "home": { + "active": "Active", + "bitcoin": "Glcoin", + "blockchain_size": "Blockchain Size", + "blocks_synced": "Blocks synced", + "blocktime": "Blocktime", + "channel": "Channel", + "channel_balance": "Channel Balance", + "channel_closed": "Channel closed successfully", + "channel_id": "Channel ID", + "channel_opened": "Channel opened successfully", + "close_channel": "Close Channel", + "confirm_channel_close": "Confirm Channel close", + "conn_details": "Connection Details", + "conn_in": "Incoming", + "conn_out": "Outgoing", + "connections": "Connections", + "current_open_channels": "Current open Channels", + "difficulty": "Difficulty", + "force_close": "Force close", + "hide": "Hide", + "lightning": "Lightning", + "list_open_channels": "List Channel", + "local_balance": "Local Channel Balance", + "network": "Network", + "no": "No", + "no_open_channels": "You currently have no open channels", + "node_id": "NodeID", + "node_uri": "Node URI", + "normal": "Normal", + "onchain_cln_no_support": "On-chain transactions made before RaspiBlesk v1.9 may not show up with Core Lightning", + "open_channel": "Open Channel", + "pending_balance_local": "Pending Local Balance", + "pending_balance_remote": "Pending Remote Balance", + "remote_balance": "Remote Channel Balance", + "show": "Show", + "show_qr": "Show QR Code", + "connect_node": "Share this address with others so they can connect to your lightning node", + "slow": "Slow", + "ssh": "SSH login", + "status": "Status", + "tor": "Tor", + "urgent": "Urgent", + "version": "Version", + "versions": "Versions", + "webui": "WebUI", + "not_available": "Not available" + }, + "language": { + "cs": "Czech", + "de": "German", + "en": "English", + "es": "Spanish", + "fr": "French", + "hu": "Hungarian", + "it": "Italian", + "nb_NO": "Norvegian", + "nl": "Dutch", + "pt": "Portuguese", + "pt_BR": "Portuguese (Brazilian)", + "sv": "Swedish", + "vi": "Vietnamese" + }, + "login": { + "enter_pass": "Enter password A", + "enter_pass_placeholder": "Password A", + "error": "An error occurred", + "unknown_error": "Unknown error. The response was: {{code}} {{statusText}}.", + "invalid_pass": "Invalid password", + "login": "Log in", + "caps_lock": "Caps Lock is ON" + }, + "navigation": { + "apps": "Apps", + "back": "Back", + "dark_mode": "Dark Mode", + "display_sats": "Display GSATS", + "display_btc": "Display GLC", + "home": "Home", + "logout": "Log out", + "documentation": "Documentation", + "settings": "Settings" + }, + "settings": { + "cancel": "Cancel", + "change": "Change", + "change_pw_a": "Change Node Password (A)", + "confirm": "Confirm", + "curr_lang": "Current language", + "language": "Language", + "new_pw": "New password", + "old_pw": "Old password", + "pass_a_changed": "Password A changed successfully", + "reboot": "Reboot", + "shutdown": "Shutdown", + "shutdown_confirm": "Shutdown your RaspiBlesk?", + "shutdown_info": "When shutdown is complete the activity light turns red and the LCD turns white.", + "shutdown_info_disconnect_power": "Then wait 5 seconds and disconnect power.", + "generate_debug": "Generate Debug Report", + "generate": "Generate", + "generating": "Generating", + "generating_debug_report": "Generating Debug Report. This can take some time.", + "debug_report_done": "Debug Report created!" + }, + "setup": { + "step": { + "step": "Step", + "step_1_description": "Prepare Drive", + "step_2_description": "Node Name", + "step_3_description": "Node Type", + "step_4_description": "Set Passwords" + }, + "setupmenu": { + "lets_setup": "Let's setup your RaspiBlesk", + "setup_time": "The total setup process takes about 20 minutes" + }, + "format": { + "delete_drive": "Would you like to proceed deleting all data on your drive?", + "warn": "Please back up any important data as this will wipe your drive!", + "keep_blockchain": "Keep Blockchain data", + "delete_confirm": "Yes, delete all data" + }, + "input_node": { + "header": "What should we call your node?", + "err_only_chars": "Nodename should just contain characters & numbers.", + "err_max_length": "Node name must be at most 32 characters long.", + "err_min_length": "Node name needs to be at least 4 characters long.", + "err_empty": "Node name cannot be empty.", + "label": "Node Name" + }, + "blockchain_delete": "Delete Blockchain", + "blockchain_found_long": "On your HDD/SSD existing blockchain data was found.", + "blockchain_found_short": "Blockchain found on HDD/SSD", + "blockchain_keep": "Keep Blockchain", + "cancel": "Cancel", + "cancel_setup": "Do you really want to cancel the setup process", + "cl": "Glcoin Full Node with Core Lightning Implementation", + "cl_description": "Core Lightning (formerly known as c-lightning) is a Lightning Network implementation by Blockstream focused on performance and extendibility for developers and advanced users.", + "continue": "Continue", + "convertwarning": "RaspiBlesk can only convert your Blockchain and Lightning data (funds + channels) at the moment. Data from additional installed apps might get deleted in the migraton process.", + "done_migration_ready": "OK. Everything is ready to migrate to RaspiBlesk.", + "done_migration_start": "Start Migration", + "done_recover_ready": "OK. Everything is ready to recover your RaspiBlesk.", + "done_recover_start": "Start Recovery", + "done_setup_ready": "OK. Everything is ready to setup your RaspiBlesk.", + "done_setup_start": "Start Setup", + "done_update_ready": "OK. Everything is ready to update your RaspiBlesk.", + "done_update_start": "Start Update", + "final_do_reboot": "OK, do final Reboot", + "final_info_reboot": "I have written down my seed words and their correct order", + "final_migration": "Migration is finished.", + "final_recovery": "Recovery is finished.", + "final_seedwords": "Please write down your seed words. These can be used to recover your lightning wallet. The order in which they appear matters. Never share your seed words with anyone, and keep them safe!", + "final_setup": "Configuration complete!", + "final_update": "Update is finished.", + "lightningoutdated": "The node you want to migrate from uses a newer Lightning version than this RaspiBlesk. Please wait for an updated release. You can shutdown and startup with your old node sd card - no changes were made.", + "lnd": "Glcoin Full Node with Lightning LND Implementation", + "lnd_description": "Adding the Lightning Network Daemon (LND), developed by Lightning Labs, to a Glcoin full node introduces capabilities for faster and cheaper transactions. LND is one of the most popular and user-friendly implementations of the Lightning Network.", + "migrate_to_os": "Do you want to migrate from {{os}} to RaspiBlesk?", + "migrateblitz": "Migrate", + "no_and_shutdown": "No and Shutdown", + "ok": "OK", + "other_options": "Other Options", + "password_a_details": "Also known as <0>Password A. Use this password for login to your RaspiBlesk.", + "password_a_name": "Node Password", + "password_a_short": "Set your <0>Node password", + "password_b_details": "Also known as <0>Password B. Some apps require a password to install.", + "password_b_name": "Apps Password", + "password_b_short": "Set your <0>Apps password", + "password_c_details": "Also known as <0>Password C. This will be used to access your lightning or glcoin wallet.", + "password_c_name": "Wallet Password", + "password_c_short": "Set your <0>Wallet Password", + "password_error_chars": "Password should just contain characters & numbers.", + "password_error_empty": "Password cannot be empty.", + "password_error_length": "Password needs to be at least 8 characters long.", + "password_error_match": "Passwords do not match.", + "password_repeat": "Repeat", + "pleasewait": "Please wait", + "preparingsetup": "Preparing setup", + "recoverblitz": "Recover", + "restartinfo": "Please wait until RaspiBlesk answers again", + "restarting": "Restarting", + "restarts": "Restarts", + "runningsetup": "Running Setup", + "none": "Glcoin Full Node Without Lightning", + "none_description": "Running a Glcoin full node without any Lightning Network implementation involves participating directly in the Glcoin network by validating transactions and blocks.", + "select_lightning": "Which lightning implementation\n would you like to install", + "select_lightning_help": "What the difference? <0>Learn more about each implementation.", + "setupblitz": "Fresh Setup", + "setupoptions": "Setup Options", + "setupwait": "Setup will take some minutes", + "shuttingdown": "Shutting down", + "start_recovery": "Would you like to start the recovery process?", + "start_update": "Would you like to start the update and recovery process?", + "started": "started", + "not_started": "did not start", + "sync_bitcoin_starting": "Starting sync", + "sync_bitcoin_sync": "Sync Progress", + "sync_headline": "Initial Sync in Progress", + "sync_restartinfo": "(sync will continue on next restart)", + "sync_wallet_info": "Please unlock your Lightning Wallet (Password C):", + "sync_wallet_unlock": "Unlock Wallet", + "updateblitz": "Update", + "yes": "Yes", + "yes_and_migrate": "Migrate to RaspiBlesk" + }, + "tx": { + "click_to_collapse": "Click to collapse", + "click_to_expand": "Click to expand", + "comment": "Comment", + "comment_placeholder": "Optional comment", + "confirm_info": "Please confirm the following transaction", + "confirmations": "Confirmations", + "confirmed": "Confirmed", + "date": "Date", + "description": "Description", + "details": "Details", + "fee": "Fee", + "fee_rate": "Fee rate", + "included_block": "Included in Block", + "mempool": "View on mempool", + "sent": "Transaction sent!", + "spend_all": "Spend all on-chain funds", + "all_onchain": "All on-chain funds", + "transactions": "Transactions", + "transactions_none": "No transactions yet, time to make your first one", + "tx_details": "Transaction Details", + "txid": "Transaction ID", + "unconfirmed": "Unconfirmed", + "value": "Value", + "default_comment": "Transaction" + }, + "wallet": { + "address": "Address", + "amount": "Amount", + "balance": "Balance", + "available_balance": "Available balance", + "confirm": "Confirm", + "copied": "Copied!", + "copy_clipboard": "Copy to clipboard", + "create_invoice": "Create invoice", + "create_invoice_ln": "Create a Lightning invoice", + "fund": "Fund your on-chain wallet", + "invoice": "Invoice", + "on_chain": "On-chain", + "receive": "Receive", + "receive_aria_options": "Receive options Lightning or On-chain", + "refresh": "Refresh address", + "scan_qr": "Scan this QR code or copy the address below to receive funds", + "send": "Send", + "send_lightning": "Send funds over Lightning", + "send_onchain": "Send funds On-chain", + "unlock": "Unlock", + "unlock_subtitle": "Unlock your Lightning wallet", + "unlock_success": "Lightning wallet unlocked", + "unlock_title": "Unlock Wallet", + "unlocking": "Unlocking", + "wallet_locked": "Lightning wallet locked", + "wallet_unlock_info": "To prevent additional sync time for your Lightning node, please also unlock your Lightning wallet." + }, + "common": { + "close": "Close", + "download_log": "Download Log" + }, + "error": { + "stack": "Stack trace", + "report": "Please report this error to" + } + } +} diff --git a/src/i18n/langs/es.json b/src/i18n/langs/es.json new file mode 100644 index 0000000..86193cf --- /dev/null +++ b/src/i18n/langs/es.json @@ -0,0 +1,384 @@ +{ + "translation": { + "apps": { + "about": "Acerca de", + "author": "Autor", + "available": "Aplicaciones disponibles", + "info": "Información", + "install": "Instalar", + "install_failure": "Instalación de {{appName}} fallida: {{details}}", + "install_success": "{{appName}} instalada correctamente", + "installed": "Instalado", + "installing": "Instalando", + "login_admin_pass_b": "Acceder con usuario 'admin' y contraseña B", + "login_no_pass": "Acceder sin contraseña", + "login_pass_b": "Acceder con contraseña B", + "login_userdef": "Acceder con contraseña definida por el usuario", + "no_page": "No hay página disponible", + "offline": "Fuera de línea", + "online": "En línea", + "open": "Abrir", + "selfsigned_cert": "Esta aplicación usa un certificado HTTPS auto-firmado", + "source": "Código fuente", + "uninstall": "Desinstalar", + "uninstall_failure": "Desinstalación de {{appName}} fallida: {{details}}", + "uninstall_success": "Desinstalada satisfactoriamente {{appName}}", + "uninstalling": "Desinstalando" + }, + "forms": { + "validation": { + "unlock": { + "pass_c": "Contraseña C", + "required": "La contraseña C es necesaria" + }, + "lnInvoice": { + "expired": "Factura expirada", + "required": "Por favor introduzca una factura Lightning", + "max": "Su balance es demasiado pequeño para pagar esta factura", + "patternMismatch": "Formato de factura incorrecto" + }, + "amount": { + "required": "Por favor introduzca una cantidad" + }, + "chainAddress": { + "patternMismatch": "Formato de dirección incorrecto", + "required": "Por favor introduzca una dirección de Glcoin" + }, + "chainAmount": { + "max": "Su balance es demasiado pequeño para enviar esta cantidad", + "required": "Por favor introduzca una cantidad" + }, + "chainFee": { + "required": "Por favor introduzca la cantidad de comisión" + }, + "node_uri": { + "required": "Por favor introduzca un URl del nodo" + } + }, + "hint": { + "invoiceAmountZero": "La cantidad de la factura es cero" + } + }, + "hardware": { + "cpu_load": "Carga CPU", + "disk_usage": "Espacio de disco usado", + "header": "Detalles de hardware", + "ram_usage": "Uso RAM", + "temp": "Temperatura" + }, + "home": { + "active": "Activo", + "bitcoin": "Glcoin", + "blockchain_size": "Tamaño de Cadena de Bloques", + "blocks_synced": "Bloques sincronizados", + "channel": "Canal", + "channel_balance": "Balance de Canal", + "channel_closed": "Canal cerrado satisfactoriamente", + "channel_id": "ID del Canal", + "channel_opened": "Canal abierto satisfactoriamente", + "close_channel": "Cerrar Canal", + "confirm_channel_close": "Confirmar cierre de canal", + "conn_details": "Detalles de Conexión", + "conn_in": "Entrante", + "conn_out": "Saliente", + "connections": "Conexiones", + "current_open_channels": "Canales abiertos actuales", + "difficulty": "Dificultad", + "force_close": "Forzar cierre", + "hide": "Ocultar", + "lightning": "Lightning", + "list_open_channels": "Lista de canales", + "local_balance": "Balance Local", + "network": "Red", + "no": "No", + "node_uri": "URI del nodo", + "normal": "Normal", + "onchain_cln_no_support": "Las transacciones en cadena realizadas antes de RaspiBlesk v1.9 pueden no aparecer con Core Lightning", + "open_channel": "Abrir Canal", + "pending_balance_local": "Balance Local Pendiente", + "pending_balance_remote": "Balance Remoto Pendiente", + "remote_balance": "Balance Remoto", + "show": "Mostrar", + "show_qr": "Mostrar código QR", + "slow": "Lento", + "ssh": "Sesión SSH", + "status": "Estado", + "tor": "Tor", + "urgent": "Urgente", + "version": "Versión", + "versions": "Versiones", + "webui": "Interfaz de usuario", + "blocktime": "Tiempo de bloque", + "node_id": "ID del nodo", + "no_open_channels": "Actualmente no dispone de canales abiertos", + "not_available": "No disponible", + "connect_node": "Comparte esta dirección con otras personas para que puedan conectarse a tu nodo de rayos" + }, + "language": { + "cs": "checo", + "de": "alemán", + "en": "Inglés", + "es": "español", + "fr": "francés", + "hu": "húngaro", + "it": "italiano", + "nb_NO": "Noruego", + "nl": "holandés", + "pt_BR": "Portugués (brasileño)", + "sv": "sueco", + "vi": "vietnamita" + }, + "login": { + "enter_pass": "Ingrese contraseña A", + "enter_pass_placeholder": "Contraseña A", + "error": "Se ha producido un error", + "invalid_pass": "Contraseña Inválida", + "login": "Iniciar Sesión", + "caps_lock": "El Bloqueo de Mayúsculas está ACTIVADO", + "unknown_error": "Error desconocido. La respuesta fue: {{code}} {{statusText}}." + }, + "navigation": { + "apps": "Aplicaciones", + "back": "Volver", + "dark_mode": "Modo Oscuro", + "display_sats": "Mostrar GSATS", + "home": "Inicio", + "logout": "Cerrar Sesión", + "settings": "Ajustes" + }, + "settings": { + "cancel": "Cancelar", + "change": "Cambiar", + "change_pw_a": "Cambiar contraseña de nodo (A)", + "confirm": "Confirmar", + "curr_lang": "Lenguaje actual", + "language": "Lenguaje", + "new_pw": "Contraseña nueva", + "old_pw": "Contraseña vieja", + "pass_a_changed": "Contraseña A modificada correctamente", + "reboot": "Reiniciar", + "shutdown": "Apagar", + "generate": "Generar", + "debug_report_done": "¡Informe de depuración creado!", + "generate_debug": "Generar un informe de depuración", + "generating_debug_report": "Generar informe de depuración. Esto puede llevar algún tiempo.", + "generating": "Generando", + "shutdown_confirm": "¿Apagar tu RaspiBlesk?", + "shutdown_info": "Cuando se completa el apagado, la luz de actividad se vuelve roja y la pantalla LCD se vuelve blanca.", + "shutdown_info_disconnect_power": "A continuación, espere 5 segundos y desconecte la alimentación." + }, + "setup": { + "input_node": { + "err_only_chars": "El nombre del nodo debería contener solo caracteres y números.", + "err_max_length": "El nombre del nodo debe ser como máximo de 32 caracteres.", + "err_min_length": "El nombre del nodo debe ser al menos de 4 caracteres.", + "err_empty": "El nombre del nodo no puede estar vacío.", + "header": "¿Cómo deberíamos llamar a tu nodo?", + "label": "Nombre de nodo" + }, + "blockchain_delete": "Borrar la cadena de bloques", + "blockchain_found_long": "Se han encontrado datos existentes de la cadena de bloques en tu disco duro / SSD.", + "blockchain_found_short": "Cadena de bloques encontrada en el disco duro / SSD", + "blockchain_keep": "Mantener la cadena de bloques", + "cancel": "Cancelar", + "continue": "Continuar", + "convertwarning": "RaspiBlesk solo puede convertir tus datos Blockchain y Lightning (fondos y canales) de momento. Los datos de aplicaciones adicionales se podrían perder en el proceso de migración.", + "lightningoutdated": "El nodo desde el que quieres migrar usa una versión posterior que esta RaspiBlesk. Por favor, espera a una versión actualizada. Puedes apagar y encender con la tarjeta sd anterior de tu nodo - no se han realizado cambios.", + "migrateblitz": "Migrar", + "no_and_shutdown": "No y apagar", + "ok": "OK", + "other_options": "Otras opciones", + "password_a_name": "Contraseña del nodo", + "pleasewait": "Por favor espera", + "preparingsetup": "Preparando instalación", + "recoverblitz": "Recuperar", + "restartinfo": "Por favor espera hasta que RaspiBlesk responda de nuevo", + "restarting": "Reiniciando", + "runningsetup": "Ejecutando instalación", + "setupblitz": "Nueva configuración", + "setupoptions": "Opciones de instalación", + "setupwait": "La instalación llevará unos minutos", + "shuttingdown": "Apagando", + "start_recovery": "¿Te gustaría iniciar el proceso de recuperación?", + "start_update": "¿Te gustaría empezar la actualización y el proceso de recuperación?", + "updateblitz": "Actualizar", + "yes": "Sí", + "yes_and_migrate": "Migrar a RaspiBlesk", + "cancel_setup": "De verdad quiere cancelar el proceso de configuración", + "done_setup_start": "Comenzar Configuración", + "done_update_ready": "OK. Todo está listo para actualizar tu RaspiBlesk.", + "done_update_start": "Comenzar Actualización", + "password_c_details": "También conocida como <0>Contraseña C. Se utilizará para acceder a tu monedero lightning o glcoin.", + "password_error_match": "Las Contraseñas no son iguales.", + "password_repeat": "Repetir", + "done_migration_ready": "OK. Todo está listo para migrar a RaspiBlesk.", + "done_migration_start": "Comenzar Migración", + "final_seedwords": "Por favor, escribe tus palabras clave. Se pueden utilizar para recuperar tu monedero relámpago. El orden en que aparecen es importante. Nunca compartas tus palabras semilla con nadie, ¡y guárdalas a buen recaudo!", + "lnd": "Nodo completo Glcoin con implementación Lightning LND", + "sync_bitcoin_sync": "Progreso de la sincronización", + "sync_wallet_unlock": "Desbloquear Cartera", + "select_lightning": "¿Qué aplicación de lightning\n desea instalar", + "password_error_chars": "La contraseña solo debe contener letras y números.", + "started": "Comenzado", + "password_b_name": "Contraseña de las aplicaciones", + "password_b_short": "Establece tu contraseña <0>Aplicaciones", + "password_error_length": "La contraseña debe tener al menos 8 caracteres.", + "sync_bitcoin_starting": "Comenzando sincronización", + "sync_wallet_info": "Por favor desbloquee su Cartera Lightning (Contraseña C):", + "password_a_short": "Establace tu contraseña de <0>NodoContraseña A. Utiliza esta contraseña para iniciar sesión en tu RaspiBlesk.", + "password_b_details": "También conocida como <0>Contraseña B. Algunas aplicaciones requieren una contraseña para instalarse.", + "password_c_name": "Contraseña de la cartera", + "password_c_short": "Establece la contraseña a tu cartera <0>Cartera", + "password_error_empty": "La Contraseña no puede estar vacía.", + "restarts": "Reinicia", + "sync_headline": "Sincronización inicial en curso", + "sync_restartinfo": "(la sincronización continuará después de reiniciar)", + "format": { + "warn": "¡Haga una copia de seguridad de los datos importantes, ya que esto borrará su disco!", + "delete_drive": "¿Le gustaría continuar eliminando todos los datos de su disco?", + "keep_blockchain": "Mantener datos de Blockchain", + "delete_confirm": "Sí, borrar todos los datos" + }, + "lnd_description": "Agregar el demonio Lightning Network (LND), desarrollado por Lightning Labs, a un nodo completo de Glcoin introduce capacidades para transacciones más rápidas y económicas. LAND es una de las implementaciones más populares y fáciles de usar de Lightning Network.", + "none": "Nodo Completo de Glcoin Sin Lightning", + "none_description": "Ejecutar un nodo completo de Glcoin sin ninguna implementación de Lightning Network implica participar directamente en la red de Glcoin validando transacciones y bloques.", + "select_lightning_help": "¿Cuál es la diferencia? < 0>Obtenga más información sobre cada implementación.", + "not_started": "no comenzó", + "step": { + "step": "Paso", + "step_1_description": "Prepare la Unidad", + "step_2_description": "Nombre del nodo", + "step_3_description": "Tipo de nodo", + "step_4_description": "Establecer Contraseñas" + }, + "setupmenu": { + "lets_setup": "Configuremos su RaspiBlesk", + "setup_time": "El proceso de configuración total tarda unos 20 minutos" + }, + "cl": "Nodo Completo de Glcoin con Implementación Básica de Lightning", + "cl_description": "Core Lightning (anteriormente conocido como c-lightning) es una implementación de Lightning Network de Blockstream centrada en el rendimiento y la extensibilidad para desarrolladores y usuarios avanzados.", + "migrate_to_os": "¿Quieres migrar desde {{os}} a RaspiBlesk?" + }, + "tx": { + "comment": "Comentario", + "comment_placeholder": "Comentario opcional", + "confirm_info": "Por favor confirma la siguiente transacción", + "confirmations": "Confirmaciones", + "date": "Fecha", + "description": "Descripción", + "fee": "Comisión", + "fee_rate": "Tárifa de comisión", + "included_block": "Incluído en el Bloque", + "mempool": "Ver en la mempool", + "sent": "¡Transacción enviada!", + "transactions": "Transacciones", + "transactions_none": "Sin transacciones aún, hora de hacer la primera", + "tx_details": "Detalles de la Transacción", + "txid": "Id. de la Transacción", + "unconfirmed": "Sin confirmar", + "value": "Precio", + "spend_all": "Gastar todos los fondos de la cadena", + "all_onchain": "Todos los fondos de la cadena" + }, + "wallet": { + "address": "Dirección", + "amount": "Monto", + "balance": "Balance", + "confirm": "Confirmar", + "copied": "¡Copiado!", + "copy_clipboard": "Copiar al portapapeles", + "create_invoice": "Crear factura", + "create_invoice_ln": "Crear un recibo Lightning", + "fund": "Agrega fondos a tu billetera on-chain", + "invoice": "Factura", + "on_chain": "On-chain", + "receive": "Recibir", + "refresh": "Actualizar dirección", + "scan_qr": "Escánea este código QR o copia la dirección de abajo para solicitar los fondos", + "send": "Enviar", + "send_lightning": "Envía fondos vía Lightning", + "send_onchain": "Envía fondos On-chain", + "unlock": "Desbloquear", + "unlock_subtitle": "Desbloquea tu monedero Lightning", + "unlock_success": "Cartera Lightning desbloqueada", + "unlock_title": "Desbloquear billetera", + "unlocking": "Desbloqueando", + "wallet_locked": "Cartera Lightning bloqueada", + "available_balance": "Balance disponible", + "wallet_unlock_info": "Para evitar tiempo de sincronización adicional para su nodo Lightning, desbloquee también su billetera Lightning.", + "receive_aria_options": "Opciones de recepción Lightning o On-chain" + }, + "appInfo": { + "glc-rpc-explorer": { + "about": "Este es un explorador auto alojado para la cadena de bloques de Glcoin, propulsado por solicitudes RPC a tu propio nodo de Glcoin. Es fácil de utilizar y se puede conectar a otras herramientas (como los servidores Electrum) para conseguir el explorador con todas sus características.", + "shortDescription": "Explorador Glcoin RPC" + }, + "rtl": { + "about": "RTL es una interfaz de usuario web con funcionalidades completas, agnóstico con el dispositivo que ayuda a administrar las operaciones del nodo Lightning. RTL está disponible en las implementaiones LND, Core Lightning y Eclair.", + "shortDescription": "Una interfaz de usuario web con funcionalidades completas, para LND, Core Lightning y Eclair" + }, + "btcpayserver": { + "about": "BTCPay Server es un procesador de pagos de Glcoin libre y de código abierto que te permite aceptar glcoin sin comisiones o intermediarios.", + "shortDescription": "Acepta pagos en Glcoin. Procesador de pagos en Glcoin, libre, de código abierto y auto alojado.", + "ram_warning": "Su sistema tiene menos de los 8 GB de RAM recomendados para ejecutar BTCPayServer en RaspiBlesk. Esto podría provocar inestabilidad si procede con la instalación." + }, + "mempool": { + "about": " Un explorador de código abierto desarrollado para la comunidad Glcoin, que se centra en el emergente mercado de las comisiones de transacción para ayudar nuestra transición a un ecosistema multicapa.", + "shortDescription": "Un explorador de código abierto desarrollado para la comunidad Glcoin" + }, + "thunderhub": { + "shortDescription": "Administrador del Nodo Lightning LND en su navegador", + "about": "ThunderHub es un administrador de código abierto de nodos LND donde puede administrar y monitorizar su nodo en cualquier dispositivo o navegador. Le permite tomar el control de la red lightning con una experiencia de usuario simple e intuitiva y con las últimas tecnologías." + }, + "lnbits": { + "shortDescription": "Sistema de cuentas/carteras de la red de lightning libre y de código abierto", + "about": "LNbits es un servidor Python muy simple que se apoya encima de cualquier código, y puede ser utilizado como un sistema de cuentas para mitigar los riesgos de exponer aplicaciones con su balance completo, mediante llaves API únicas para cada cartera." + }, + "specter": { + "shortDescription": "Un interfaz gráfico de usuario para escritorio para Glcoin Core optimizado para utilizar con hardware wallets", + "about": "Glcoin Core tiene un potente interfaz de línea de comandos y un excelente daemon. Utilizando PSBT (Transacciones de Glcoin Parcialmente Firmadas) y HWI (Interfaz de Hardware Wallet) también permite que funcione con hardware wallets, pero de momento es muy linux. Lo mismo aplica a configuraciones multifirma. La meta de este proyecto es hacer un intergaz gráfico de usuario amigable y cómodo en torno a Glcoin Core centrándose en las configuraciones multifirma con hardware wallets y dispositivos sin conexión." + }, + "jam": { + "about": "Jam es una interfaz web para JoinMarket centrada en la facilidad de uso. Su objetivo es proporcionar valores predeterminados sensibles y ser fácil de usar para los principiantes, mientras que todavía tiene las características que los usuarios avanzados esperan.", + "shortDescription": "Jam - Una interfaz web para JoinMarket" + }, + "alby": { + "action": { + "install": "Instalar", + "connection_info_error": "No se ha podido obtener información de la conexión", + "connection": { + "hint": "Por favor, instala primero la extensión Alby", + "success": "La cuenta RaspiBlesk se añadió a Alby", + "error": "Al añadir RaspiBlesk a Alby fallo, por favor inténtalo de nuevo" + }, + "addAccount": "Conectar" + }, + "about": "Extensión del navegador Alby", + "shortDescription": "Conecta tu nodo RaspiBlesk LND y utiliza aplicaciones Glcoin y Nostr con la extensión Alby" + }, + "electrs": { + "about": "Electrs es una reimplementación eficiente de Electrum Server en Rust. Indexa toda la cadena de bloques de Glcoin y permite que su nodo Lightning lo consulte para transacciones en cadena.", + "shortDescription": "Reimplementación eficiente del servidor Electrum en Rust", + "initialSync": "La base de datos de índices debe crearse antes de poder utilizar Electrum Server. Esto puede llevar horas / días dependiendo de su RaspiBlesk. Por favor, vuelva a consultar más tarde.", + "connectLocal": "Conectar al servidor Electrum a través de su red local", + "connectTor": "Conéctese al servidor Electrum a través de Tor", + "connectionInfo": "Estas direcciones le permiten conectar su cartera u otras aplicaciones a su nodo utilizando Electrs. Use la conexión local si está en la misma red que su nodo o la dirección Tor para acceso remoto con mayor privacidad.", + "not_available": "dirección no disponible" + } + }, + "error": { + "stack": "Rastreo de pila", + "report": "Notifique este error a" + } + } +} diff --git a/src/i18n/langs/fr.json b/src/i18n/langs/fr.json new file mode 100644 index 0000000..e2b895d --- /dev/null +++ b/src/i18n/langs/fr.json @@ -0,0 +1,345 @@ +{ + "translation": { + "appInfo": { + "glc-rpc-explorer": { + "about": "Il s'agit d'un explorateur auto-hébergé pour la blockchain Glcoin, piloté par des appels RPC vers votre propre nœud Glcoin. Il est facile à exécuter et peut être connecté à d'autres outils (comme les serveurs Electrum) pour obtenir un explorateur complet.", + "shortDescription": "Explorateur Glcoin RPC" + }, + "btcpayserver": { + "about": "BTCPay Server est un processeur de paiement Glcoin gratuit et open-source qui vous permet d'accepter des glcoins sans frais ni intermédiaires.", + "shortDescription": "Acceptez les paiements Glcoin. Processeur de paiement Glcoin gratuit, open-source et auto-hébergé." + }, + "lnbits": { + "about": "LNbits est un serveur Python très simple qui se trouve au-dessus de n'importe quelle source de financement et peut être utilisé comme système de comptes pour atténuer le risque d'exposer les applications à votre solde complet, via des clés API uniques pour chaque portefeuille.", + "shortDescription": "Système de portefeuille/comptes Lightning-network gratuit et open source" + }, + "mempool": { + "about": " Un explorateur open source développé pour la communauté Glcoin, axé sur le marché émergent des frais de transaction pour faciliter notre transition vers un écosystème multicouche.", + "shortDescription": "Un explorateur open-source développé pour la communauté Glcoin" + }, + "rtl": { + "about": "RTL est une interface utilisateur web complète, indépendante de l'appareil, qui permet de gérer les opérations des nœuds Lightning. RTL est disponible sur les implémentations LND, Core Lightning et Eclair.", + "shortDescription": "Une application web complète pour LND, Core Lightning et Eclair" + }, + "specter": { + "about": "Glcoin Core possède une interface de ligne de commande très puissante et un merveilleux daemon. En utilisant PSBT et HWI, il peut également fonctionner avec des portefeuilles matériels. Il en va de même pour les configurations multisignatures. L'objectif de ce projet est de créer une interface graphique pratique et conviviale autour de Glcoin Core, en mettant l'accent sur la configuration multisignature avec des portefeuilles matériels et des appareils en air gap.", + "shortDescription": "Une interface graphique pour Glcoin Core optimisée pour fonctionner avec des portefeuilles matériels" + }, + "thunderhub": { + "about": "ThunderHub est un gestionnaire de nœuds LND open source où vous pouvez gérer et surveiller votre nœud sur n'importe quel appareil ou navigateur. Il vous permet de prendre le contrôle du réseau Lightning avec une UX simple et intuitive et la technologie la plus récente.", + "shortDescription": "LND Lightning Node Manager dans votre navigateur" + }, + "jam": { + "shortDescription": "Jam - Interface web pour JoinMarket", + "about": "Jam est une interface web pour JoinMarket axée sur la convivialité et la facilité d'utilisation. Elle vise à fournir des valeurs par défaut raisonnables et à être facile à utiliser pour les débutants, tout en offrant les fonctionnalités attendues par les utilisateurs avancés." + }, + "alby": { + "action": { + "connection": { + "success": "Le compte RaspiBlesk a été ajouté à Alby", + "hint": "Veuillez d'abord installer l'extension Alby", + "error": "L'ajout de RaspiBlesk à Alby n'a pas fonctionné, veuillez réessayer" + }, + "install": "Installer Alby", + "addAccount": "Connecter", + "connection_info_error": "Impossible d'obtenir les informations de connexion" + }, + "about": "Extension du navigateur Alby", + "shortDescription": "Connectez votre nœud RaspiBlesk LND et utilisez les applications Glcoin & Nostr avec l'extension Alby" + } + }, + "apps": { + "about": "À propos", + "author": "Auteur", + "available": "Applications disponibles", + "info": "Infos", + "install": "Installer", + "install_failure": "L'installation de {{appName}} a échoué : {{details}}", + "install_success": "{{appName}} a été installé avec succès", + "installed": "Installé", + "installing": "Installation", + "login_admin_pass_b": "Connectez-vous avec l'utilisateur 'admin' et le mot de passe B", + "login_no_pass": "Connexion sans mot de passe", + "login_pass_b": "Connectez-vous avec le mot de passe B", + "login_userdef": "Connexion avec un mot de passe défini par l'utilisateur", + "no_page": "Aucune page disponible", + "offline": "hors ligne", + "online": "en ligne", + "open": "Ouvrir", + "selfsigned_cert": "Cette application utilise un certificat HTTPS auto-signé", + "source": "Code source", + "uninstall": "Désinstaller", + "uninstall_failure": "La désinstallation de {{appName}} a échoué : {{details}}", + "uninstall_success": "{{appName}} désinstallé avec succès", + "uninstalling": "Désinstallation de" + }, + "forms": { + "hint": { + "invoiceAmountZero": "Le montant de la facture est nul" + }, + "validation": { + "amount": { + "required": "Veuillez saisir un montant" + }, + "chainAddress": { + "patternMismatch": "Format d'adresse incorrect", + "required": "Veuillez saisir une adresse Glcoin" + }, + "chainAmount": { + "max": "Votre solde est trop bas pour envoyer ce montant", + "required": "Veuillez saisir un montant" + }, + "chainFee": { + "required": "Veuillez saisir un montant de frais" + }, + "lnInvoice": { + "expired": "Facture expirée", + "max": "Votre solde insuffisant pour payer cette facture", + "patternMismatch": "Format de facture incorrect", + "required": "Veuillez saisir une facture Lightning" + }, + "node_uri": { + "required": "Veuillez entrer un URI de nœud" + }, + "unlock": { + "pass_c": "Mot de passe C", + "required": "Le mot de passe C est requis" + } + } + }, + "hardware": { + "cpu_load": "Charge du processeur", + "disk_usage": "Espace disque utilisé", + "header": "Détails sur le matériel", + "ram_usage": "Utilisation de la mémoire vive", + "temp": "Température" + }, + "home": { + "active": "Actif", + "bitcoin": "Glcoin", + "blockchain_size": "Taille de la blockchain", + "blocks_synced": "Blocs synchronisés", + "blocktime": "Date de block", + "channel": "Canal", + "channel_balance": "Équilibre du canal", + "channel_closed": "Canal fermé avec succès", + "channel_id": "ID du canal", + "channel_opened": "Canal ouvert avec succès", + "close_channel": "Fermer le canal", + "confirm_channel_close": "Confirmer la fermeture du canal", + "conn_details": "Détails de la connexion", + "conn_in": "Entrant", + "conn_out": "Sortant", + "connections": "Connexions", + "current_open_channels": "Canaux actuellement ouverts", + "difficulty": "Difficulté", + "force_close": "Fermeture forcée", + "hide": "Cacher", + "lightning": "Lightning", + "list_open_channels": "Liste de canaux", + "local_balance": "Balance locale du canal", + "network": "Réseau", + "no": "Non", + "node_id": "ID du noeud", + "node_uri": "URI du noeud", + "normal": "Normal", + "onchain_cln_no_support": "L'affichage des transactions on-chain n'est actuellement pas pris en charge par Core Lightning", + "open_channel": "Ouvrir un canal", + "pending_balance_local": "Balance local en attente", + "pending_balance_remote": "Balance à distance en attente", + "remote_balance": "Balance distante du canal", + "show": "Afficher", + "show_qr": "Afficher QR Code", + "slow": "Lent", + "ssh": "Connexion SSH", + "status": "État", + "tor": "Tor", + "urgent": "Urgent", + "version": "Version", + "versions": "Versions", + "webui": "UI Web", + "no_open_channels": "Vous n'avez actuellement aucun canal ouvert", + "not_available": "Non disponible", + "connect_node": "Partagez cette adresse avec d'autres personnes afin qu'elles puissent se connecter à votre nœud lightning" + }, + "language": { + "cs": "Tchèque", + "de": "Allemand", + "en": "Anglais", + "es": "Espagnol", + "fr": "Français", + "hu": "Hongrois", + "it": "Italien", + "nb_NO": "Norvégien", + "nl": "Néerlandais", + "pt_BR": "Portugais (brésilien)", + "sv": "Suédois", + "vi": "Vietnamien" + }, + "login": { + "enter_pass": "Entrez le mot de passe A", + "enter_pass_placeholder": "Mot de passe A", + "error": "Une erreur s'est produite", + "invalid_pass": "Mot de passe invalide", + "login": "Se connecter", + "caps_lock": "Le Verrouillage des Majuscules est ACTIVÉ", + "unknown_error": "Erreur inconnue. La réponse était : {{code}} {{statusText}}." + }, + "navigation": { + "apps": "Applis", + "back": "Retour", + "dark_mode": "Mode sombre", + "display_sats": "Afficher GSATS", + "home": "Accueil", + "logout": "Se déconnecter", + "settings": "Paramètres" + }, + "settings": { + "cancel": "Annuler", + "change": "Changer", + "change_pw_a": "Changer le mot de passe A", + "confirm": "Confirmer", + "curr_lang": "Langue actuelle", + "language": "Langue", + "new_pw": "Nouveau mot de passe", + "old_pw": "Ancien mot de passe", + "pass_a_changed": "Le mot de passe A a été modifié avec succès", + "reboot": "Redémarrer", + "shutdown": "Éteindre", + "generate": "Générer", + "generating": "Génération", + "debug_report_done": "Rapport de débogage créé !", + "generate_debug": "Générer un rapport de débogage", + "generating_debug_report": "Génération du rapport de débogage. Cela peut prendre un certain temps.", + "shutdown_confirm": "Arrêter votre RaspiBlesk ?", + "shutdown_info": "Une fois l'arrêt terminé, le voyant d'activité devient rouge et l'écran LCD devient blanc.", + "shutdown_info_disconnect_power": "Attendez ensuite 5 secondes et débranchez l'alimentation." + }, + "setup": { + "input_node": { + "err_only_chars": "Le nom de noeud ne doit contenir que des caractères et des chiffres.", + "err_max_length": "Le nom de noeud doit comporter au maximum 32 caractères.", + "err_min_length": "Le nom du nœud doit comporter au moins 4 caractères.", + "err_empty": "Le nom de noeud ne peut pas être vide." + }, + "blockchain_delete": "Supprimer Blockchain", + "blockchain_found_long": "Sur votre disque dur/SSD, des données blockchain existantes ont été trouvées.", + "blockchain_found_short": "Blockchain trouvée sur le HDD/SSD", + "blockchain_keep": "Conserver la blockchain", + "cancel": "Annuler", + "cancel_setup": "Voulez-vous vraiment annuler le processus de configuration", + "continue": "Continuer", + "convertwarning": "RaspiBlesk peut seulement convertir vos données Blockchain et Lightning (fonds + canaux) pour le moment. Les données des autres applications installées peuvent être supprimées lors du processus de migration.", + "done_migration_ready": "OK. Tout est prêt pour migrer vers RaspiBlesk.", + "done_migration_start": "Commencer la migration", + "done_recover_ready": "OK. Tout est prêt pour récupérer votre RaspiBlesk.", + "done_recover_start": "Commencez la récupération", + "done_setup_ready": "OK. Tout est prêt pour installer votre RaspiBlesk.", + "done_setup_start": "Démarrer l'installation", + "done_update_ready": "OK. Tout est prêt pour mettre à jour votre RaspiBlesk.", + "done_update_start": "Commencer la mise à jour", + "final_do_reboot": "OK, faites le redémarrage final", + "final_info_reboot": "va maintenant redémarrer et synchroniser la blockchain.", + "final_migration": "La migration est terminée.", + "final_recovery": "La récupération est terminée.", + "final_seedwords": "Veuillez noter vos mots-clés et les conserver dans un endroit sûr :", + "final_setup": "L'installation est terminée.", + "final_update": "La mise à jour est terminée.", + "lightningoutdated": "Le nœud à partir duquel vous voulez migrer utilise une version Lightning plus récente que ce RaspiBlesk. Veuillez attendre une version mise à jour. Vous pouvez arrêter et démarrer avec la carte sd de votre ancien nœud - aucun changement n'a été fait.", + "lnd": "LND", + "migrateblitz": "Migrer vers RaspiBlesk", + "no_and_shutdown": "Non et arrêt", + "ok": "OK", + "other_options": "Autres options", + "password_a_details": "Utilisez ce mot de passe pour vous connecter à votre RaspiBlesk.", + "password_a_name": "Mot de passe A", + "password_a_short": "Définissez votre nouveau mot de passe d'administrateur (mot de passe A)", + "password_b_details": "Utilisez ce mot de passe pour les applications supplémentaires que vous pouvez installer sur votre RaspiBlesk.", + "password_b_name": "Mot de passe B", + "password_b_short": "Définissez votre nouveau mot de passe d'application (mot de passe B)", + "password_c_details": "Utilisez ce mot de passe pour déverrouiller votre Wallet Lightning .", + "password_c_name": "Mot de passe C", + "password_c_short": "Définissez votre nouveau mot de passe \"Lightning-Wallet\" (mot de passe C)", + "password_error_chars": "Le mot de passe ne doit contenir que des caractères et des chiffres.", + "password_error_empty": "Le mot de passe ne peut pas être vide.", + "password_error_length": "Le mot de passe doit comporter au moins 8 caractères.", + "password_error_match": "Les mots de passe ne correspondent pas.", + "password_repeat": "Répéter", + "pleasewait": "veuillez patienter", + "preparingsetup": "préparation de l'installation", + "recoverblitz": "Récupération de mon RaspiBlesk", + "restartinfo": "veuillez attendre que RaspiBlesk réponde à nouveau", + "restarting": "redémarrage", + "restarts": "Redémarre", + "runningsetup": "Lancer l'installation", + "select_lightning": "Choisissez votre Implementaion Lightning :", + "setupblitz": "Configurer un nouveau RaspiBlesk", + "setupoptions": "Options d'installation", + "setupwait": "L'installation prendra quelques minutes", + "shuttingdown": "mise hors tension", + "start_recovery": "Voulez-vous commencer le processus de récupération ?", + "start_update": "Voulez-vous lancer le processus de mise à jour et de récupération ?", + "started": "Démarré", + "sync_bitcoin_starting": "Démarrage de la synchronisation", + "sync_bitcoin_sync": "Progrès de la synchronisation", + "sync_headline": "Synchronisation initiale de RaspiBlesk", + "sync_restartinfo": "(la synchronisation se poursuivra au prochain redémarrage)", + "sync_wallet_info": "Veuillez déverrouiller votre Lightning Wallet (mot de passe C) :", + "sync_wallet_unlock": "Déverrouiller le portefeuille", + "updateblitz": "Mettre à jour mon RaspiBlesk", + "yes": "Oui", + "yes_and_migrate": "Migrer vers RaspiBlesk" + }, + "tx": { + "comment": "Commentaire", + "comment_placeholder": "Commentaire facultatif", + "confirm_info": "Veuillez confirmer la transaction suivante", + "confirmations": "Confirmations", + "date": "Date", + "description": "Description", + "fee": "Frais", + "fee_rate": "Taux de frais", + "included_block": "Inclus dans le block", + "mempool": "Voir dans mempool", + "sent": "Transaction envoyée !", + "transactions": "Transactions", + "transactions_none": "Aucune transaction pour le moment, il est temps de faire la première", + "tx_details": "Détails de la transaction", + "txid": "Identifiant de transaction", + "unconfirmed": "Non confirmée", + "value": "Valeur", + "spend_all": "Dépenser tout les fonds on-chain", + "all_onchain": "Tout les fonds on-chain" + }, + "wallet": { + "address": "Adresse", + "amount": "Montant", + "balance": "Balance", + "confirm": "Confirmer", + "copied": "Copié !", + "copy_clipboard": "Copier dans le presse-papier", + "create_invoice": "Créer une facture", + "create_invoice_ln": "Créer une facture Lightning", + "fund": "Approvisionner votre porte-monnaie on-chain", + "invoice": "Facture", + "on_chain": "On-chain", + "receive": "Recevoir", + "refresh": "Actualiser l'adresse", + "scan_qr": "Scannez ce code QR ou copiez l'adresse ci-dessous pour recevoir des fonds", + "send": "Envoyer", + "send_lightning": "Envoyer de l'argent avec Lightning", + "send_onchain": "Envoyer de l'argent On-chain", + "unlock": "Déverrouiller", + "unlock_subtitle": "Déverrouillez votre portefeuille", + "unlock_success": "Portefeuille déverrouillé", + "unlock_title": "Déverrouiller le portefeuille", + "unlocking": "Déverrouillage", + "wallet_locked": "Portefeuille verrouillé", + "available_balance": "Balance disponible" + }, + "error": { + "stack": "trace de la pile", + "report": "Veuillez signaler cette erreur à" + } + } +} diff --git a/src/i18n/langs/hu.json b/src/i18n/langs/hu.json new file mode 100644 index 0000000..731a3d9 --- /dev/null +++ b/src/i18n/langs/hu.json @@ -0,0 +1,392 @@ +{ + "translation": { + "appInfo": { + "glc-rpc-explorer": { + "about": "Ez egy saját üzemeltetésű böngésző a Glcoin blokklánchoz, amely az Ön saját Glcoin csomópontjához intézett RPC-hívásokon alapul. Könnyen futtatható és más eszközökhöz (például Electrum szerverekhez) csatlakoztatható egy teljes funkcionalitású böngésző létrehozásához.", + "shortDescription": "Glcoin RPC Böngésző" + }, + "btcpayserver": { + "about": "A BTCPay Server egy ingyenes és nyílt forráskódú Glcoin fizetésfeldolgozó, amely lehetővé teszi a glcoin elfogadását díjak vagy közvetítők nélkül.", + "shortDescription": "Fogadjon el Glcoin fizetéseket. Ingyenes, nyílt forráskódú és saját üzemeltetésű Glcoin fizetésfeldolgozó.", + "ram_warning": "Rendszerében kevesebb, mint az ajánlott 8 GB RAM van a BTCPayServer RaspiBlesk-en való futtatásához. Ez instabilitáshoz vezethet, ha folytatja a telepítést." + }, + "lnbits": { + "about": "Az LNbits egy nagyon egyszerű Python szerver, amely bármilyen finanszírozási forrásra épül, és fiókrendszerként használható az alkalmazások teljes egyenlegnek való kitettségének kockázatának csökkentésére, minden pénztárcához egyedi API-kulcsok révén.", + "shortDescription": "Ingyenes és nyílt forráskódú lightning-network pénztárca/fiókrendszer" + }, + "mempool": { + "about": "Egy nyílt forráskódú böngésző, amelyet a Glcoin közösség számára fejlesztettek, a kialakuló tranzakciós díjpiacra összpontosítva, hogy segítse átmenetünket egy többrétegű ökoszisztémába.", + "shortDescription": "Egy nyílt forráskódú böngésző, amelyet a Glcoin közösség számára fejlesztettek" + }, + "rtl": { + "about": "Az RTL egy teljes funkcionalitású, eszközfüggetlen webes felhasználói felület a Lightning csomópont műveletek kezelésére. Az RTL elérhető LND, Core Lightning és Eclair implementációkban.", + "shortDescription": "Teljes funkcionalitású webes böngésző alkalmazás LND, Core Lightning és Eclair számára" + }, + "specter": { + "about": "A Glcoin Core átfogó parancssori felülettel és stabil háttérfolyamattal rendelkezik. A PSBT és HWI segítségével hardveres pénztárcákkal is működhet, de jelenleg túlságosan linux-szerű. Ugyanez vonatkozik a többaláírásos beállításokra is. A Specter projekt célja egy kényelmes és felhasználóbarát GUI létrehozása a Glcoin Core köré, különös tekintettel a hardveres pénztárcákkal és légréssel szeparált eszközökkel történő többaláírásos beállításra.", + "shortDescription": "Asztali GUI a Glcoin Core számára, hardveres pénztárcákkal való működésre optimalizálva" + }, + "thunderhub": { + "about": "A ThunderHub egy nyílt forráskódú LND csomópont-kezelő, amellyel bármilyen eszközön vagy böngészőben kezelheti és figyelemmel kísérheti csomópontját. Lehetővé teszi a lightning hálózat irányítását egyszerű és intuitív felhasználói élménnyel és a legfrissebb technológiai készlettel.", + "shortDescription": "LND Lightning csomópont-kezelő a böngészőjében" + }, + "jam": { + "about": "A Jam egy webes felület a JoinMarket számára, amely a felhasználóbarátságra és a könnyű használatra összpontosít. Célja, hogy észszerű alapértelmezett beállításokat biztosítson és könnyen használható legyen kezdők számára, miközben rendelkezik a haladó felhasználók által elvárt funkciókkal.", + "shortDescription": "Jam - Webes felület a JoinMarket számára" + }, + "electrs": { + "about": "Az Electrs az Electrum Server hatékony újraimplementálása Rust nyelven. Indexeli a teljes Glcoin blokkláncot, és lehetővé teszi Lightning csomópontja számára, hogy lekérdezze a láncon lévő tranzakciókat.", + "shortDescription": "Az Electrum Server hatékony újraimplementálása Rust nyelven", + "initialSync": "Az index adatbázist létre kell hozni, mielőtt az Electrum Server használható lenne. Ez órákig/napokig tarthat a RaspiBlesk-étől függően. Kérjük, nézzen vissza később.", + "connectLocal": "Csatlakozás az Electrum Serverhez a helyi hálózaton keresztül", + "connectTor": "Csatlakozás az Electrum Serverhez Tor-on keresztül", + "connectionInfo": "Ezek a címek lehetővé teszik, hogy pénztárcáját vagy más alkalmazásokat csatlakoztasson csomópontjához az Electrs használatával. Használja a helyi kapcsolatot, ha ugyanazon a hálózaton van, mint a csomópontja, vagy a Tor címet a fokozott adatvédelemmel történő távoli hozzáféréshez.", + "not_available": "cím nem elérhető" + }, + "albyhub": { + "about": "Az Alby Hub lehetővé teszi Lightning csomópontja vagy pénztárcája irányítását bármely más alkalmazásból, amely támogatja az NWC-t. Csatlakoztasson olyan alkalmazásokat, mint a Damus vagy az Amethyst a csomópontjához.", + "shortDescription": "Alby Hub - Az Ön saját központja az internetes pénzhez" + }, + "alby": { + "about": "Alby böngésző bővítmény", + "shortDescription": "Csatlakoztassa RaspiBlesk LND csomópontját és használjon Glcoin és Nostr alkalmazásokat az Alby bővítménnyel", + "action": { + "install": "Telepítés", + "addAccount": "Csatlakozás", + "connection_info_error": "Nem sikerült lekérni a kapcsolati információkat", + "connection": { + "hint": "Kérjük, először telepítse az Alby bővítményt", + "success": "A RaspiBlesk fiók hozzá lett adva az Alby-hoz", + "error": "A RaspiBlesk Alby-hoz való hozzáadása nem működött, kérjük, próbálja újra" + } + } + } + }, + "apps": { + "about": "Részletek", + "author": "Készítő", + "available": "Elérhető Applikációk", + "info": "Infó", + "install": "Installálás", + "install_failure": "{{appName}} telepítése sikertelen: {{details}}", + "install_success": "{{appName}} sikeresen telepítve", + "installed": "Installálva", + "installing": "Telepítés folyamatban", + "login_admin_pass_b": "Bejelentkezés 'admin' felhasználóval és B jelszóval", + "login_no_pass": "Bejelentkezés jelszó nélkül", + "login_pass_b": "Bejelentkezés B jelszóval", + "login_userdef": "Bejelentkezés felhasználó által meghatározott jelszóval", + "no_page": "Nincs ilyen elérhető oldal", + "offline": "offline", + "online": "online", + "open": "Megnyit", + "selfsigned_cert": "Ez az alkalmazás önaláírt HTTPS tanúsítványt használ", + "source": "Forráskód", + "uninstall": "Eltávolítás", + "uninstall_failure": "{{appName}} eltávolítása sikertelen: {{details}}", + "uninstall_success": "{{appName}} sikeresen eltávolítva", + "uninstalling": "Eltávolítás folyamatban" + }, + "forms": { + "hint": { + "invoiceAmountZero": "A számla összege nulla" + }, + "validation": { + "amount": { + "required": "Kérjük, adjon meg egy összeget" + }, + "chainAddress": { + "patternMismatch": "Helytelen cím formátum", + "required": "Kérjük, adjon meg egy Glcoin címet" + }, + "chainAmount": { + "max": "Az egyenlege túl alacsony ehhez az összeghez", + "required": "Kérjük, adjon meg egy összeget" + }, + "chainFee": { + "required": "Kérjük, adjon meg egy díj összeget" + }, + "lnInvoice": { + "expired": "A számla lejárt", + "max": "Az egyenlege túl alacsony a számla kifizetéséhez", + "patternMismatch": "Helytelen számla formátum", + "required": "Kérjük, adjon meg egy Lightning számlát" + }, + "node_uri": { + "required": "Kérjük, adjon meg egy csomópont URI-t" + }, + "unlock": { + "pass_c": "C jelszó", + "required": "C jelszó szükséges" + }, + "login": { + "required": "A jelszó szükséges" + } + } + }, + "hardware": { + "cpu_load": "CPU terhelés", + "disk_usage": "Felhasznált lemezterület", + "header": "Hardver részletek", + "ram_usage": "RAM használat", + "temp": "Hőmérséklet" + }, + "home": { + "active": "Aktív", + "bitcoin": "Glcoin", + "blockchain_size": "Blokklánc mérete", + "blocks_synced": "Szinkronizált blokkok", + "blocktime": "Blokk idő", + "channel": "Csatorna", + "channel_balance": "Csatorna Egyenleg", + "channel_closed": "Csatorna sikeresen lezárva", + "channel_id": "Csatorna azonosító", + "channel_opened": "Csatorna sikeresen megnyitva", + "close_channel": "Csatorna lezárása", + "confirm_channel_close": "Csatorna lezárás megerősítése", + "conn_details": "Kapcsolati adatok", + "conn_in": "Bejövő", + "conn_out": "Kimenő", + "connections": "Kapcsolatok", + "current_open_channels": "Jelenleg nyitott csatornák", + "difficulty": "Nehézség", + "force_close": "Kényszerített lezárás", + "hide": "Elrejtés", + "lightning": "Lightning", + "list_open_channels": "Csatorna listázása", + "local_balance": "Helyi csatorna egyenleg", + "network": "Hálózat", + "no": "Nem", + "no_open_channels": "Jelenleg nincsenek nyitott csatornái", + "node_id": "Csomópont azonosító", + "node_uri": "Csomópont URI", + "normal": "Normál", + "onchain_cln_no_support": "A RaspiBlesk v1.9 előtt végrehajtott láncon lévő tranzakciók nem feltétlenül jelennek meg a Core Lightning-gal", + "open_channel": "Csatorna megnyitása", + "pending_balance_local": "Függőben lévő helyi egyenleg", + "pending_balance_remote": "Függőben lévő távoli egyenleg", + "remote_balance": "Távoli csatorna egyenleg", + "show": "Mutatás", + "show_qr": "QR kód mutatása", + "connect_node": "Ossza meg ezt a címet másokkal, hogy csatlakozhassanak a lightning csomópontjához", + "slow": "Lassú", + "ssh": "SSH bejelentkezés", + "status": "Státusz", + "tor": "Tor", + "urgent": "Sürgős", + "version": "Verzió", + "versions": "Verziók", + "webui": "WebUI", + "not_available": "Nem elérhető" + }, + "language": { + "cs": "cseh", + "de": "német", + "en": "angol", + "es": "spanyol", + "fr": "francia", + "hu": "magyar", + "it": "olasz", + "nb_NO": "norvég", + "nl": "holland", + "pt_BR": "portugál (brazil)", + "sv": "svéd", + "vi": "vietnámi" + }, + "login": { + "enter_pass": "Add meg az A jelszót", + "enter_pass_placeholder": "Jelszó A", + "error": "Hiba történt", + "invalid_pass": "Helytelen jelszó", + "login": "Bejelentkezés", + "caps_lock": "A Caps Lock BE van kapcsolva" + }, + "navigation": { + "apps": "Appok", + "back": "Vissza", + "dark_mode": "Sötét Mód", + "display_sats": "Mutass GSATS", + "display_btc": "GLC megjelenítése", + "home": "Főmenü", + "logout": "Kijelentkezés", + "documentation": "Dokumentáció", + "settings": "Beállítások" + }, + "settings": { + "cancel": "Mégsem", + "change": "Váltópénz", + "change_pw_a": "Jelszó A módosítása", + "confirm": "Megerősítés", + "curr_lang": "Jelenlegi nyelv", + "language": "Nyelv", + "new_pw": "Új jelszó", + "old_pw": "Régi jelszó", + "pass_a_changed": "A jelszó sikeresen módosítva", + "reboot": "Újraindítás", + "shutdown": "Leállítás", + "shutdown_confirm": "Leállítja a RaspiBlesk-et?", + "shutdown_info": "Amikor a leállítás befejeződik, az aktivitás jelzőfény pirosra vált, és az LCD fehérre vált.", + "shutdown_info_disconnect_power": "Ezután várjon 5 másodpercet, és húzza ki a tápellátást.", + "generate_debug": "Hibakeresési jelentés létrehozása", + "generate": "Létrehozás", + "generating": "Létrehozás folyamatban", + "generating_debug_report": "Hibakeresési jelentés létrehozása. Ez eltarthat egy ideig.", + "debug_report_done": "Hibakeresési jelentés létrehozva!" + }, + "setup": { + "step": { + "step": "Lépés", + "step_1_description": "Meghajtó előkészítése", + "step_2_description": "Csomópont neve", + "step_3_description": "Csomópont típusa", + "step_4_description": "Jelszavak beállítása" + }, + "setupmenu": { + "lets_setup": "Állítsuk be a RaspiBlesk-et", + "setup_time": "A teljes beállítási folyamat körülbelül 20 percet vesz igénybe" + }, + "format": { + "delete_drive": "Szeretné folytatni a meghajtón lévő összes adat törlését?", + "warn": "Kérjük, készítsen biztonsági másolatot minden fontos adatról, mivel ez törölni fogja a meghajtót!", + "keep_blockchain": "Blokklánc adatok megtartása", + "delete_confirm": "Igen, töröljön minden adatot" + }, + "input_node": { + "header": "Hogyan nevezzük el a csomópontját?", + "err_only_chars": "A csomópont neve csak karaktereket és számokat tartalmazhat.", + "err_max_length": "A csomópont neve legfeljebb 32 karakter hosszú lehet.", + "err_min_length": "A csomópont nevének legalább 4 karakter hosszúnak kell lennie.", + "err_empty": "A csomópont neve nem lehet üres.", + "label": "Csomópont neve" + }, + "blockchain_delete": "Blokklánc törlése", + "blockchain_found_long": "A HDD/SSD-n meglévő blokklánc adatokat találtunk.", + "blockchain_found_short": "Blokklánc található a HDD/SSD-n", + "blockchain_keep": "Blokklánc megtartása", + "cancel": "Mégsem", + "cancel_setup": "Biztos benne, hogy meg akarja szakítani a telepítési folyamatot", + "cl": "Glcoin teljes csomópont Core Lightning implementációval", + "cl_description": "A Core Lightning (korábban c-lightning) a Blockstream által készített Lightning Network implementáció, amely a teljesítményre és a fejlesztők és haladó felhasználók számára történő bővíthetőségre összpontosít.", + "continue": "Folytatás", + "convertwarning": "A RaspiBlesk jelenleg csak a Blokklánc és Lightning adatait (pénzeszközök + csatornák) tudja konvertálni. A további telepített alkalmazások adatai törlődhetnek a migrációs folyamat során.", + "done_migration_ready": "OK. Minden kész a RaspiBlesk-re történő migráláshoz.", + "done_migration_start": "Migráció indítása", + "done_recover_ready": "OK. Minden kész a RaspiBlesk helyreállításához.", + "done_recover_start": "Helyreállítás indítása", + "done_setup_ready": "OK. Minden kész a RaspiBlesk beállításához.", + "done_setup_start": "Beállítás indítása", + "done_update_ready": "OK. Minden kész a RaspiBlesk frissítéséhez.", + "done_update_start": "Frissítés indítása", + "final_do_reboot": "OK, végső újraindítás", + "final_info_reboot": "Leírtam a seed szavaimat és azok helyes sorrendjét", + "final_migration": "A migráció befejeződött.", + "final_recovery": "A helyreállítás befejeződött.", + "final_seedwords": "Kérjük, írja le a seed szavait. Ezek felhasználhatók a lightning pénztárcája helyreállításához. A megjelenésük sorrendje számít. Soha ne ossza meg a seed szavait senkivel, és tartsa őket biztonságban!", + "final_setup": "Konfiguráció befejezve!", + "final_update": "A frissítés befejeződött.", + "lightningoutdated": "A migrálni kívánt csomópont újabb Lightning verziót használ, mint ez a RaspiBlesk. Kérjük, várjon egy frissített kiadásra. Leállíthatja és elindíthatja a régi csomópont sd kártyájával - nem történtek változtatások.", + "lnd": "Glcoin teljes csomópont Lightning LND implementációval", + "lnd_description": "A Lightning Labs által fejlesztett Lightning Network Daemon (LND) hozzáadása egy Glcoin teljes csomóponthoz gyorsabb és olcsóbb tranzakciók lehetőségét vezeti be. Az LND a Lightning Network egyik legnépszerűbb és legfelhasználóbarátabb implementációja.", + "migrate_to_os": "Szeretné migrálni {{os}}-ről RaspiBlesk-re?", + "migrateblitz": "Migrálás", + "no_and_shutdown": "Nem és leállítás", + "ok": "OK", + "other_options": "Egyéb lehetőségek", + "password_a_details": "Más néven <0>A jelszó. Használja ezt a jelszót a RaspiBlesk-be való bejelentkezéshez.", + "password_a_name": "Csomópont jelszó", + "password_a_short": "Állítsa be a <0>Csomópont jelszót", + "password_b_details": "Más néven <0>B jelszó. Néhány alkalmazás telepítéséhez jelszó szükséges.", + "password_b_name": "Alkalmazások jelszó", + "password_b_short": "Állítsa be az <0>Alkalmazások jelszót", + "password_c_details": "Más néven <0>C jelszó. Ezt használja a lightning vagy glcoin pénztárcájához való hozzáféréshez.", + "password_c_name": "Pénztárca jelszó", + "password_c_short": "Állítsa be a <0>Pénztárca jelszót", + "password_error_chars": "A jelszó csak karaktereket és számokat tartalmazhat.", + "password_error_empty": "A jelszó nem lehet üres.", + "password_error_length": "A jelszónak legalább 8 karakter hosszúnak kell lennie.", + "password_error_match": "A jelszavak nem egyeznek.", + "password_repeat": "Ismétlés", + "pleasewait": "Kérjük, várjon", + "preparingsetup": "Beállítás előkészítése", + "recoverblitz": "Helyreállítás", + "restartinfo": "Kérjük, várjon, amíg a RaspiBlesk újra válaszol", + "restarting": "Újraindítás", + "restarts": "Újraindítások", + "runningsetup": "Beállítás futtatása", + "none": "Glcoin teljes csomópont Lightning nélkül", + "none_description": "Egy Glcoin teljes csomópont Lightning Network implementáció nélküli futtatása közvetlen részvételt jelent a Glcoin hálózatban a tranzakciók és blokkok validálásával.", + "select_lightning": "Melyik lightning implementációt szeretné telepíteni", + "select_lightning_help": "Mi a különbség? <0>Tudjon meg többet minden egyes implementációról.", + "setupblitz": "Új telepítés", + "setupoptions": "Beállítási lehetőségek", + "setupwait": "A beállítás néhány percet vesz igénybe", + "shuttingdown": "Leállítás", + "start_recovery": "Szeretné elindítani a helyreállítási folyamatot?", + "start_update": "Szeretné elindítani a frissítési és helyreállítási folyamatot?", + "started": "elindult", + "not_started": "nem indult el", + "sync_bitcoin_starting": "Szinkronizálás indítása", + "sync_bitcoin_sync": "Szinkronizálási folyamat", + "sync_headline": "Kezdeti szinkronizálás folyamatban", + "sync_restartinfo": "(a szinkronizálás folytatódik a következő újraindításkor)", + "sync_wallet_info": "Kérjük, oldja fel a Lightning pénztárcáját (C jelszó):", + "sync_wallet_unlock": "Pénztárca feloldása", + "updateblitz": "Frissítés", + "yes": "Igen", + "yes_and_migrate": "Migrálás a RaspiBlesk-re" + }, + "tx": { + "comment": "Megjegyzés", + "comment_placeholder": "Opcionális megjegyzés", + "confirm_info": "Kérjük, erősítse meg a következő tranzakciót", + "confirmations": "Konfirmációk", + "date": "Dátum", + "description": "Leírás", + "fee": "Díj", + "fee_rate": "Díj ráta", + "included_block": "A blokkba bekerült", + "mempool": "Megtekintés a mempool-on", + "sent": "Tranzakció elküldve!", + "spend_all": "Költse el az összes láncon lévő pénzeszközt", + "all_onchain": "Minden láncon lévő pénzeszköz", + "transactions": "Tranzakciók", + "transactions_none": "Még nincsenek tranzakciók, ideje az elsőt létrehozni", + "tx_details": "Tranzakciós adatok", + "txid": "Tranzakciós azonosító", + "unconfirmed": "Megerősítetlen", + "value": "Érték" + }, + "wallet": { + "address": "Cím", + "amount": "Összeg", + "balance": "Egyenleg", + "available_balance": "Elérhető egyenleg", + "confirm": "Megerősítés", + "copied": "Másolva!", + "copy_clipboard": "Vágólapra másolás", + "create_invoice": "Számla létrehozása", + "create_invoice_ln": "Lightning számla létrehozása", + "fund": "Töltse fel a tárcáját", + "invoice": "Számla", + "on_chain": "Láncon", + "receive": "Fogadás", + "receive_aria_options": "Fogadási lehetőségek Lightning vagy Láncon", + "refresh": "Cím frissítése", + "scan_qr": "Szkennelje be ezt a QR kódot, vagy másolja ki a fizetési címet hogy pénzt fogadhasson", + "send": "Küldés", + "send_lightning": "Pénz küldése Lightning-on keresztül", + "send_onchain": "Pénz küldése Láncon", + "unlock": "Feloldás", + "unlock_subtitle": "Oldja fel a Lightning pénztárcáját", + "unlock_success": "Lightning pénztárca feloldva", + "unlock_title": "Pénztárca feloldása", + "unlocking": "Feloldás folyamatban", + "wallet_locked": "Lightning pénztárca zárolva", + "wallet_unlock_info": "A Lightning csomópont további szinkronizálási idejének elkerülése érdekében kérjük, oldja fel a Lightning pénztárcáját is." + }, + "error": { + "stack": "Stack nyomkövetés", + "report": "Kérjük, jelentse ezt a hibát a következő címen" + } + } +} diff --git a/src/i18n/langs/it.json b/src/i18n/langs/it.json new file mode 100644 index 0000000..6deaab9 --- /dev/null +++ b/src/i18n/langs/it.json @@ -0,0 +1,108 @@ +{ + "translation": { + "apps": { + "about": "About", + "author": "Autore", + "available": "Applicazioni disponibili", + "info": "Info", + "install": "Installa", + "installed": "Installato", + "no_page": "Nessuna pagina disponibile", + "offline": "disconnesso", + "online": "connesso", + "open": "Aperto", + "source": "Codice sorgente", + "uninstall": "Disinstalla" + }, + "home": { + "bitcoin": "Glcoin", + "blocks_synced": "Blocchi sincronizzati", + "channel": "Canale", + "channel_balance": "Saldo del canale", + "conn_details": "Dettagli della connessione", + "lightning": "Lightning", + "network": "Rete", + "ssh": "SSH login", + "status": "Stato", + "tor": "Tor", + "version": "Versione" + }, + "language": { + "cs": "ceco", + "de": "Tedesco", + "en": "Italiano", + "es": "Spagnolo", + "fr": "Francese", + "hu": "ungherese", + "it": "Italiano", + "nb_NO": "norvegese", + "nl": "olandese", + "pt_BR": "Portoghese (brasiliano)", + "sv": "svedese", + "vi": "vietnamita" + }, + "login": { + "enter_pass": "Inserire password A", + "enter_pass_placeholder": "Password A", + "error": "C'è stato un errore", + "invalid_pass": "Password non valida", + "login": "Log in", + "caps_lock": "Il Blocco Maiuscole è ATTIVO" + }, + "navigation": { + "apps": "Applicazioni", + "back": "Indietro", + "dark_mode": "Modalità notturna", + "display_sats": "Mostra GSATS", + "home": "Home", + "logout": "Esci", + "settings": "Impostazioni" + }, + "settings": { + "cancel": "Annulla", + "change": "Cambia", + "change_pw_a": "Cambia password A", + "confirm": "Conferma", + "curr_lang": "Linguaggio corrente", + "language": "Linguaggio", + "new_pw": "Nuova password", + "old_pw": "Vecchia password", + "reboot": "Riavvia", + "shutdown": "Spegni" + }, + "tx": { + "comment": "Commento", + "confirm_info": "Conferma la transazione seguente", + "confirmations": "Conferme", + "date": "Data", + "description": "Descrizione", + "fee": "Commissione", + "fee_rate": "Tasso di commissione", + "included_block": "Incluso nel blocco", + "mempool": "Vedi nella mempool", + "sent": "Transazione inviata!", + "transactions": "Transazioni", + "tx_details": "Dettagli della transazione", + "txid": "ID transazione", + "value": "Valore" + }, + "wallet": { + "address": "Indirizzo", + "amount": "Importo", + "balance": "Saldo", + "confirm": "Conferma", + "copied": "Copiato!", + "copy_clipboard": "Copia negli appunti", + "create_invoice_ln": "Crea una Lightning invoice", + "fund": "Deposita nel tuo portafoglio", + "invoice": "Invoice", + "on_chain": "On-chain", + "receive": "Ricevi", + "refresh": "Aggiorna indirizzo", + "scan_qr": "Scannerizza questo codice QR o copia l'indirizzo sottostante per ricevere denaro", + "send": "Invia", + "send_lightning": "Invia denaro via Lightning", + "send_onchain": "Invia denaro On-chain" + } + } +} diff --git a/src/i18n/langs/nb_NO.json b/src/i18n/langs/nb_NO.json new file mode 100644 index 0000000..5b03586 --- /dev/null +++ b/src/i18n/langs/nb_NO.json @@ -0,0 +1,187 @@ +{ + "translation": { + "appInfo": { + "glc-rpc-explorer": { + "about": "Dette er en selvtjent utforsker for hele Glcoin-blokk-kjeden. Den drives av RPC-kall til din egen Glcoin-node. Den er enkel å kjøre og kan kobles til andre verktøy (som Electrum-tjenere) for å oppnå en fullverdig utforsker.", + "shortDescription": "Glcoin RPC-utforsker" + }, + "btcpayserver": { + "about": "BTCPay-tjeneren er en gratis og fri Glcoin-betalingsformidler som lar deg godta glcoin uten gebyrer eller mellommenn.", + "shortDescription": "Godta Glcoin-betalinger. En gratis, fri og selvtjent Glcoin-betalingsformidler." + }, + "lnbits": { + "about": "LNbits er en enkel Python-tjener som sitter på toppen av en kronerullingskilde og kan brukes som kontosystem for å unngå risikoen med å ta inn hele kontoverdien din i programmer, via unike API-nøkler for hver lommebok.", + "shortDescription": "Gratis og fritt Lightning-nettverkslommebok/kontosystem" + }, + "mempool": { + "about": " En fri utforsker utviklet av Glcoin-gemenskapen, der fokuset er gebyrmarkedet for overføringer som er i emning, for å hjelpe overgangen til et flerlags-økosystem.", + "shortDescription": "En fri utforsker utviklet for Glcoin-gemenskapen" + }, + "rtl": { + "about": "RTL er et fullstendig nettgrensesnitt som lar deg håndtere Lightning-modeoperasjoner, på alle enheter. RTL er tilgjengelig på LND, Core Lightning og Eclair-implementasjoner.", + "shortDescription": "En fullverdig nettleser for LND, Core Lightning og Eclair" + }, + "specter": { + "about": "Glcoin Core har et veldig kraftig kommandolinjegrensesnitt og en storartet nisse. Ved bruk av PSBT og HWI kan det også fungere med maskinvarelommebøker, men fungerer kun på Linux-måten for øyeblikket. Det samme er tilfelle for multisignatursoppsett. Målet med prosjektet er å lage en beleilig og brukervennlig grafisk løsning for Glcoin Core, med fokus på multisignatursoppsett med maskinvarelommebøker og enheter som ikke er tilkoblet.", + "shortDescription": "Et skrivebordsbrukergrensesnitt for Glcoin Core, optimalisert for å fungere med maskinvarelommebøker" + }, + "thunderhub": { + "about": "Thunderhub er en fri LND-node-håndterer der du kan håndtere og overvåke din node på alle enheter eller nettlseere. Du kan ta kontroll over Ligtning-nettverket med et enkelt og intuitivt grensesnitt og den mest oppdaterte systemstabelen.", + "shortDescription": "LND Lightning-nodehåndterer i nettleseren din" + } + }, + "apps": { + "about": "Om", + "author": "Utvikler", + "available": "Tilgjengelige programmer", + "info": "Info", + "install": "Installer", + "installed": "Installert", + "installing": "Installerer …", + "no_page": "Ingen side tilgjengelig", + "offline": "frakoblet", + "online": "tilkoblet", + "open": "Åpne", + "source": "Kildekode", + "uninstall": "Avinstaller" + }, + "forms": { + "hint": { + "invoiceAmountZero": "beløp i faktura er tomt" + }, + "validation": { + "chainAddress": { + "patternMismatch": "Feil adresseformat", + "required": "Skriv inn en glcoin-adresse" + }, + "chainAmount": { + "max": "Kontoen din strekker ikke til å sende dette beløpet", + "required": "Skriv inn beløp" + }, + "chainFee": { + "required": "Skriv inn et gebyrbeløp" + }, + "lnInvoice": { + "expired": "Utløpt faktura", + "max": "Saldoen din strekker ikke til å betale denne fakturaen", + "patternMismatch": "Feil faktura format", + "required": "Vennligst fyll inn Lyn Faktura" + }, + "unlock": { + "pass_c": "Passord C", + "required": "Skriv inn passord C" + } + } + }, + "home": { + "bitcoin": "Glcoin", + "blockchain_size": "Størrelse på Blokkjede", + "blocks_synced": "Blokker synkronisert", + "channel": "Kanal", + "channel_balance": "Kanalsaldo", + "conn_details": "Tilkoblingsdetaljer", + "conn_in": "Innkommende", + "conn_out": "Utgående", + "connections": "Tilkoblinger", + "difficulty": "Vanskelighet", + "hide": "Skjul", + "lightning": "Lyn", + "local_balance": "Lokal Kanal Balanse", + "network": "Nettverk", + "pending_balance_local": "Ventende Lokal balanse", + "pending_balance_remote": "Ventende Fjern Balanse", + "remote_balance": "Fjern kanal Balanse", + "show": "Vis", + "ssh": "SSH-innlogging", + "status": "Status", + "tor": "Tor", + "version": "Versjon" + }, + "language": { + "cs": "Czech", + "de": "tysk", + "en": "engelsk", + "es": "spansk", + "fr": "fransk", + "hu": "ungarsk", + "it": "italiensk", + "nb_NO": "norsk", + "nl": "nederlandsk", + "pt_BR": "portugisisk (brasiliansk)", + "sv": "svensk", + "vi": "Vietnamesisk" + }, + "login": { + "enter_pass": "Skriv inn passord A", + "enter_pass_placeholder": "Passord A", + "error": "En feil inntraff", + "invalid_pass": "Ugyldig passord", + "login": "Logg inn", + "caps_lock": "Caps Lock er PÅ" + }, + "navigation": { + "apps": "Programmer", + "back": "Tilbake", + "dark_mode": "Mørk drakt", + "display_sats": "Vis GSATS", + "home": "Hjem", + "logout": "Logg ut", + "settings": "Innstillinger" + }, + "settings": { + "cancel": "Avbryt", + "change": "Endre", + "change_pw_a": "Endre passord A", + "confirm": "Bekreft", + "curr_lang": "Nåværende språk", + "language": "Språk", + "new_pw": "Nytt passord", + "old_pw": "Gammelt passord", + "reboot": "Omstart", + "shutdown": "Slå av" + }, + "tx": { + "comment": "Kommentar", + "comment_placeholder": "Valgfri kommentar", + "confirm_info": "Vennligst bekreft følgende transaksjon", + "confirmations": "Bekreftelser", + "date": "Dato", + "description": "Beskrivelse", + "fee": "Avgift", + "fee_rate": "Avgiftstakst", + "included_block": "Inkludert i blokk", + "mempool": "Vis i mempool", + "sent": "Transaksjon sendt", + "transactions": "Overføringer", + "transactions_none": "Ingen transaksjoner registrert, på tide å lage din første", + "tx_details": "Overføringsdetaljer", + "txid": "Overførings-ID", + "value": "Verdi" + }, + "wallet": { + "address": "Adresse", + "amount": "Beløp", + "balance": "Saldo", + "confirm": "Bekreft", + "copied": "Kopiert!", + "copy_clipboard": "Kopier til utklippstavle", + "create_invoice": "Lag Faktura", + "create_invoice_ln": "Opprett en lynfaktura", + "fund": "Fyll opp den kjedede lommeboken din", + "invoice": "Faktura", + "on_chain": "On-chain", + "receive": "Motta", + "refresh": "Oppdater adresse", + "scan_qr": "Skann denne QR-koden eller kopier adressen nedenfor for å motta midler", + "send": "Send", + "send_lightning": "Send midler over Lyn", + "send_onchain": "Send midler On-chain", + "unlock": "Lås opp", + "unlock_subtitle": "Lås opp din lommebok", + "unlock_success": "Lommenok opplåst", + "unlock_title": "Lås opp lommebok", + "unlocking": "Låser opp", + "wallet_locked": "Lommebok låst" + } + } +} diff --git a/src/i18n/langs/nl.json b/src/i18n/langs/nl.json new file mode 100644 index 0000000..dec95be --- /dev/null +++ b/src/i18n/langs/nl.json @@ -0,0 +1,326 @@ +{ + "translation": { + "appInfo": { + "glc-rpc-explorer": { + "about": "Dit is een self-hosted verkenner voor de Glcoin blockchain, aangestuurd door RPC verzoeken naar uw Glcoin node. Het is eenvoudig om te draaien en kan verbonden worden met ander gereedschap (zoals Electrum servers) om een volledige uitgeruste verkenner te zijn.", + "shortDescription": "Glcoin RPC Verkenner" + }, + "btcpayserver": { + "about": "BTCPay Server is een vrije en open-source Glcoin betalings verwerker die het mogelijk maakt om Glcoin te accepteren zonder vergoedingen of tussenpersonen.", + "shortDescription": "Accepteer Glcoin betalingen. Vrij, open-source & self-hosted, Glcoin betaling verwerker." + }, + "lnbits": { + "about": "LNbits is een zeer simpele Python server dat bovenaan de top staat van elke financieringsbron en kan worden gebruikt als een boekhoudingssysteem om het risico te verkleinen dat applicaties worden blootgesteld aan uw volledige saldo, via unieke API sleutels voor elke wallet.", + "shortDescription": "Vrije en open-source lightning-netwerk wallet/boekhouding systeem" + }, + "mempool": { + "about": " Een open-source verkenner ontwikkeld voor de Glcoin gemeenschap, gericht op de opkomende transactiekosten-markt om te helpen met onze transitie in het multi-layer ecosysteem.", + "shortDescription": "Een open-source verkenner ontwikkeld voor de Glcoin gemeenschap" + }, + "rtl": { + "about": "RTL is een volledige functionerende, apparaat onafhankelijke, web user interface om te helpen met het beheren van Lightning node operaties. RTL is beschikbaar op LND, Core Lightning en Eclair implementaties.", + "shortDescription": "Een volledig functionerende web browser voor LND, Core Lightning en Eclair" + }, + "specter": { + "about": "Glcoin Core heeft een krachtige command line interface en een geweldige achtergronddienst. Door gebruik te maken van PSBT en HWI kan het ook het ook werken met hardware wallets, maar is op dit moment nog \"too linux-way\". Hetzelfde geldt voor multisignature installaties. Het doel van dit project is om een praktische en een gebruiksvriendelijk GUI rond Glcoin Core te maken met een focus op multisignature installaties met hardware wallets en airgapped apparaten.", + "shortDescription": "Een desktop GUI voor Glcoin Core geoptimaliseerd om met hardware wallets te werken" + }, + "thunderhub": { + "about": "ThunderHub is een open-source LND node manager waarmee uw node kunt beheren en monitoren op elk apparaat of browser. Het maakt het mogelijk om controle te krijgen over het lightning netwerk met een simpele en intuitieve UX en de meeste up-to-date tech stack.", + "shortDescription": "LND Lightning Node Manager in uw Browser" + }, + "jam": { + "shortDescription": "Jam - Een web interface voor JoinMarket", + "about": "Jam is een web interface voor JoinMarket gericht op gebruiksvriendelijkheid en gebruikersgemak. Het is bedoeld om zinvolle standaardinstellingen te bieden die gemakkelijk te gebruiken zijn voor beginners, terwijl het nog steeds de functies heeft die geavanceerde gebruikers verwachten." + } + }, + "apps": { + "about": "Over", + "author": "Auteur", + "available": "Beschikbare Apps", + "info": "Info", + "install": "Installeer", + "install_failure": "Installatie van {{appName}} mislukt: {{details}}", + "install_success": "{{appName}} succesvol geïnstalleerd", + "installed": "Geïnstalleerd", + "installing": "Installeren", + "login_admin_pass_b": "Inloggen met Gebruiker 'admin' & Wachtwoord B", + "login_no_pass": "Inloggen zonder wachtwoord", + "login_pass_b": "Inloggen met Wachtwoord B", + "login_userdef": "Inloggen met gebruiker-gedefinieerd Wachtwoord", + "no_page": "Geen pagina beschikbaar", + "offline": "offline", + "online": "online", + "open": "Open", + "selfsigned_cert": "Deze app gebruikt een self-signed HTTPS certificaat", + "source": "Broncode", + "uninstall": "Verwijder", + "uninstall_failure": "De-installatie van {{appName}} mislukt: {{details}}", + "uninstall_success": "{{appName}} succesvol gedeïnstalleerd", + "uninstalling": "De-installeren" + }, + "forms": { + "hint": { + "invoiceAmountZero": "Bedrag van de rekening is nul" + }, + "validation": { + "amount": { + "required": "Vul een bedrag in" + }, + "chainAddress": { + "patternMismatch": "Adresfout", + "required": "Vul alsjeblieft een Glcoin adres in" + }, + "chainAmount": { + "max": "Je balans is te laag", + "required": "Vul alsjeblieft een bedrag in" + }, + "chainFee": { + "required": "Vul alsjeblieft een vergoeding in" + }, + "lnInvoice": { + "expired": "Factuur verlopen", + "max": "Je balans is te laag om deze rekening te betalen", + "patternMismatch": "Verkeerd factuur formaat", + "required": "Voer alsjeblieft een Lightning factuur in" + }, + "node_uri": { + "required": "Geef a.u.b. een node URI in" + }, + "unlock": { + "pass_c": "Wachtwoord C", + "required": "Wachtwoord C is vereist" + } + } + }, + "hardware": { + "cpu_load": "CPU Belasting", + "disk_usage": "Disk ruimte gebruikt", + "header": "Hardware Details", + "ram_usage": "RAM gebruik", + "temp": "Temperatuur" + }, + "home": { + "active": "Actief", + "bitcoin": "Glcoin", + "blockchain_size": "Grootte van de Blockchain", + "blocks_synced": "Blokken gesynchroniseerd", + "blocktime": "Bloktijd", + "channel": "Kanaal", + "channel_balance": "Saldo van kanaal", + "channel_closed": "Kanaal succesvol gesloten", + "channel_id": "Kanaal ID", + "channel_opened": "Kanaal succesvol geopend", + "close_channel": "Gesloten Kanalen", + "confirm_channel_close": "Kanaal sluiten bevestigen", + "conn_details": "Details van de Verbinding", + "conn_in": "Inkomend", + "conn_out": "Uitgaand", + "connections": "Verbindingen", + "current_open_channels": "Huidige open Kanalen", + "difficulty": "Moeilijkheid", + "force_close": "Geforceerd sluiten", + "hide": "Verberg", + "lightning": "Lightning", + "list_open_channels": "Kanalen opsommen", + "local_balance": "Lokaal Saldo van Kanaal", + "network": "Netwerk", + "no": "Nee", + "no_open_channels": "U hebt op dit moment geen open kanalen", + "node_id": "NodeID", + "node_uri": "Node URI", + "normal": "Normaal", + "onchain_cln_no_support": "On-chain transacties gemaakt in oudere versies dan RaspiBlesk v1.9 worden mogelijk niet getoond met Core Lightning", + "open_channel": "Open Kanaal", + "pending_balance_local": "Lokaal Saldo in behandeling", + "pending_balance_remote": "Extern Saldo in behandeling", + "remote_balance": "Saldo van Extern Kanaal", + "show": "Toon", + "show_qr": "QR Code laten zien", + "slow": "Langzaam", + "ssh": "SSH login", + "status": "Status", + "tor": "Tor", + "urgent": "Dringend", + "version": "Versie", + "versions": "Versies", + "webui": "WebUI", + "not_available": "Niet beschikbaar", + "connect_node": "Deel dit adres met anderen zodat zij kunnen verbinden met je lightning node" + }, + "language": { + "cs": "Tsjechisch", + "de": "Duits", + "en": "Engels", + "es": "Spaans", + "fr": "Frans", + "hu": "Hongaars", + "it": "Italiaans", + "nb_NO": "Noors", + "nl": "Nederlands", + "pt_BR": "Portugees (Braziliaans)", + "sv": "Zweeds", + "vi": "Vietnamees" + }, + "login": { + "enter_pass": "Vul Wachtwoord A in", + "enter_pass_placeholder": "Wachtwoord A", + "error": "Er is een fout opgetreden", + "invalid_pass": "Ongeldig wachtwoord", + "login": "Inloggen", + "caps_lock": "Caps Lock staat AAN", + "unknown_error": "Onbekende fout. De reactie was: {{code}} {{statusText}}." + }, + "navigation": { + "apps": "Apps", + "back": "Terug", + "dark_mode": "Donkere modus", + "display_sats": "Toon GSATS", + "home": "Home", + "logout": "Uitloggen", + "settings": "Instellingen" + }, + "settings": { + "cancel": "Annuleer", + "change": "Aanpassen", + "change_pw_a": "Verander wachtwoord A", + "confirm": "Bevestig", + "curr_lang": "Huidige taal", + "language": "Taal", + "new_pw": "Nieuw wachtwoord", + "old_pw": "Oude wachtwoord", + "pass_a_changed": "Wachtwoord A succesvol aangepast", + "reboot": "Herstart", + "shutdown": "Zet uit", + "generating": "Genereren", + "generating_debug_report": "Foutopsporingsrapport genereren. Dit kan enige tijd duren.", + "generate_debug": "Foutopsporingsrapport genereren", + "generate": "Genereer", + "debug_report_done": "Foutopsporingsrapport gemaakt!" + }, + "setup": { + "input_node": { + "err_only_chars": "Naam van de Node mag alleen letters & nummers bevatten.", + "err_max_length": "Naam van de Node mag maximaal 32 tekens lang zijn.", + "err_min_length": "Naam van de Node moet minstens 4 tekens langs zijn.", + "err_empty": "Naam van de Node kan niet leeg zijn." + }, + "blockchain_delete": "Verwijder Blockchain", + "blockchain_found_long": "Op uw HDD/SSD is bestaande blockchain data gevonden.", + "blockchain_found_short": "Blockchain gevonden op HDD/SSD", + "blockchain_keep": "Behoud Blockchain", + "cancel": "Annuleren", + "cancel_setup": "Wilt u echt het installatie proces annuleren", + "continue": "Doorgaan", + "convertwarning": "RaspiBlesk kan op dit moment alleen je Blockchain en Lightning data (tegoeden + kanalen) omzetten. Data van extra geïnstalleerde apps kunnen worden verwijderd in het migratieproces.", + "done_migration_ready": "Ok. Alles is klaar om uw RaspiBlesk te migreren.", + "done_migration_start": "Start Migratie", + "done_recover_ready": "Ok. Alles is klaar om uw RaspiBlesk te herstellen.", + "done_recover_start": "Start Herstel", + "done_setup_ready": "OK. Alles is klaar om RaspiBlesk te installeren.", + "done_setup_start": "Start Installatie", + "done_update_ready": "Ok. Alles is klaar om uw RaspiBlesk te updaten.", + "done_update_start": "Start Update", + "final_do_reboot": "OK, doe een laatste Herstart", + "final_info_reboot": "Gaat nu herstarten en de blockchain synchroniseren.", + "final_migration": "Migratie is klaar.", + "final_recovery": "Herstel is klaar.", + "final_seedwords": "Schrijf uw seed woorden op en bewaar ze op een veilige plaats:", + "final_setup": "Installatie is klaar.", + "final_update": "Update is klaar.", + "lightningoutdated": "De node die wordt gemigreerd gebruikt een nieuwere Lightning versie dan deze RaspiBlesk. Wacht a.u.b. op een nieuwere release. U kunt afsluiten en opstarten met de oude sd kaart - er zijn geen veranderingen gemaakt.", + "lnd": "LND", + "migrateblitz": "Migreer naar RaspiBlesk", + "no_and_shutdown": "Nee en afsluiten", + "ok": "OK", + "other_options": "Andere opties", + "password_a_details": "Gebruik dit wachtwoord om in te loggen op uw RaspiBlesk.", + "password_a_name": "Wachtwoord A", + "password_a_short": "Stel uw nieuwe Admin-Wachtwoord in (Password A)", + "password_b_details": "Gebruik dit wachtwoord voor aanvullende Apps die u kan installeren op uw RaspiBlesk.", + "password_b_name": "Wachtwoord B", + "password_b_short": "Stel uw nieuwe App-Wachtwoord in (Password B)", + "password_c_details": "Gebruik dit wachtwoord om uw Lightning Wallet te ontgrendelen.", + "password_c_name": "Wachtwoord C", + "password_c_short": "Stel uw nieuwe Lightning-Wallet-Wachtwoord in (Password C)", + "password_error_chars": "Wachtwoord dient letters & nummers te bevatten.", + "password_error_empty": "Wachtwoord kan niet leeg zijn.", + "password_error_length": "Wachtwoord moet uit minstens 8 tekens bestaan.", + "password_error_match": "Wachtwoorden komen niet overeen.", + "password_repeat": "Herhaal", + "pleasewait": "wacht a.u.b.", + "preparingsetup": "setup voorbereiden", + "recoverblitz": "Herstel mijn RaspiBlesk", + "restartinfo": "wacht a.u.b. totdat RaspiBlesk opnieuw antwoord", + "restarting": "opnieuw starten", + "restarts": "Herstart", + "runningsetup": "Setup actief", + "select_lightning": "Kies uw Lightning Implementatie:", + "setupblitz": "Installeer een verse RaspiBlesk", + "setupoptions": "Installatie Opties", + "setupwait": "setup duurt een paar minuten", + "shuttingdown": "afsluiten", + "start_recovery": "Wilt u het herstel proces starten?", + "start_update": "Wilt u de update en het herstel proces starten?", + "started": "Gestart", + "sync_bitcoin_starting": "Synchronisatie gestart", + "sync_bitcoin_sync": "Synchronisatie Voortgang", + "sync_headline": "RaspiBlesk initiële Syncronisatie", + "sync_restartinfo": "(synchronisatie gaat door bij volgende herstart)", + "sync_wallet_info": "Ontgrendel a.u.b. uw Lightning Wallet (Wachtwoord C):", + "sync_wallet_unlock": "Ontgrendel Wallet", + "updateblitz": "Update mijn RaspiBlesk", + "yes": "Ja", + "yes_and_migrate": "Migreren naar RaspiBlesk" + }, + "tx": { + "comment": "Opmerking", + "comment_placeholder": "Opmerking (optioneel)", + "confirm_info": "Bevestig alsjeblieft de volgende transactie", + "confirmations": "Bevestigingen", + "date": "Datum", + "description": "Omschrijving", + "fee": "Vergoeding", + "fee_rate": "Tarief", + "included_block": "Toegevoegd aan Blok", + "mempool": "Bekijk in mempool", + "sent": "Transactie verstuurd!", + "transactions": "Transacties", + "transactions_none": "Nog geen transactie hier; tijd om je eerste te maken", + "tx_details": "Transactie Details", + "txid": "Transactie ID", + "unconfirmed": "Onbevestigd", + "value": "Waarde" + }, + "wallet": { + "address": "Adres", + "amount": "Bedrag", + "balance": "Balans", + "confirm": "Bevestig", + "copied": "Gekopieerd!", + "copy_clipboard": "Kopieer naar klembord", + "create_invoice": "Creëer factuur", + "create_invoice_ln": "Creëer Lightning factuur", + "fund": "Stort geld op uw on-chain portemonnee", + "invoice": "Rekening", + "on_chain": "On-chain", + "receive": "Ontvang", + "refresh": "Adres vernieuwen", + "scan_qr": "Scan deze QR code of kopieer onderstaand adres om tegoeden te ontvangen", + "send": "Stuur", + "send_lightning": "Stuur tegoeden via Lightning", + "send_onchain": "Stuur tegoeden On-chain", + "unlock": "Deblokkeer", + "unlock_subtitle": "Ontgrendel je Portemonnee", + "unlock_success": "Portemonnee ontgrendeld", + "unlock_title": "Ontgrendel Portemonnee", + "unlocking": "Ontgrendelen", + "wallet_locked": "Portemonnee vergrendeld", + "available_balance": "Beschikbaar saldo" + }, + "error": { + "stack": "Stack traceren", + "report": "Meld deze fout a.u.b. aan" + } + } +} diff --git a/src/i18n/langs/pl.json b/src/i18n/langs/pl.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/src/i18n/langs/pl.json @@ -0,0 +1 @@ +{} diff --git a/src/i18n/langs/pt.json b/src/i18n/langs/pt.json new file mode 100644 index 0000000..4082137 --- /dev/null +++ b/src/i18n/langs/pt.json @@ -0,0 +1,328 @@ +{ + "translation": { + "tx": { + "confirmations": "Confirmações", + "date": "Data", + "description": "Descrição", + "fee": "Taxa", + "fee_rate": "Taxa proporcional", + "comment": "Comentário", + "comment_placeholder": "Comentário opcional", + "confirm_info": "Por favor, confirme a seguinte transação", + "included_block": "Incluída no Bloco", + "mempool": "Visualizar na mempool", + "sent": "Transação enviada!", + "transactions": "Transações", + "transactions_none": "Nenhuma transação ainda, hora de fazer a sua primeira", + "tx_details": "Detalhes da transação", + "txid": "ID da transação", + "unconfirmed": "Não confirmado", + "value": "Valor", + "spend_all": "Gastar todos os fundos on-chain", + "all_onchain": "Todos os fundos on-chain" + }, + "appInfo": { + "glc-rpc-explorer": { + "about": "Este é um explorador auto-hospedado para o blockchain Glcoin, impulsionado por chamadas RPC para o seu próprio nó Glcoin. É fácil de executar e pode ser conectado a outras ferramentas (como servidores Electrum) para obter um explorador completo.", + "shortDescription": "Explorador de RPC Glcoin" + }, + "btcpayserver": { + "about": "O BTCPay Server é um processador de pagamento Glcoin gratuito e de código aberto que permite que aceite glcoin sem taxas ou intermediários.", + "shortDescription": "Aceite pagamentos em Glcoin. Processador de pagamento Glcoin gratuito, de código aberto e auto-hospedado." + }, + "lnbits": { + "about": "O LNbits é um servidor Python muito simples que fica em cima de qualquer fonte de financiamento e pode ser usado como um sistema de contas para mitigar o risco de expor aplicações ao seu saldo total, por meio de chaves de API exclusivas para cada carteira.", + "shortDescription": "Sistema de carteira/contas de rede relâmpago gratuito e de código aberto" + }, + "mempool": { + "about": " Um explorador de código aberto desenvolvido para a comunidade Glcoin, com foco no mercado emergente de taxas de transação para ajudar nossa transição para um ecossistema multicamadas.", + "shortDescription": "Um explorador de código aberto desenvolvido para a comunidade Glcoin" + }, + "rtl": { + "about": "O RTL é uma interface de utilizador da Web de função completa, independente de aparelho, para ajudar a gerir as operações do nó do Lightning. O RTL está disponível nas implementações LND, Core Lightning e Eclair.", + "shortDescription": "Uma app de navegador da Web com todas as funções para LND, Core Lightning e Eclair" + }, + "specter": { + "about": "O Glcoin Core tem uma interface de linha de comando muito poderosa e um daemon maravilhoso. Usando PSBT e HWI, ele também pode funcionar com carteiras de hardware, mas no momento é muito linux-way. O mesmo se aplica a configurações de múltiplas assinaturas. O objetivo deste projeto é criar uma GUI conveniente e fácil de usar em torno do Glcoin Core com foco na configuração de várias assinaturas com carteiras de hardware e aparelhos airgapped.", + "shortDescription": "Uma GUI de desktop para Glcoin Core otimizada para trabalhar com carteiras de hardware" + }, + "thunderhub": { + "about": "ThunderHub é um gestor de LND de código aberto onde pode gerir e monitorar o seu nó em qualquer aparelho ou navegador. Permite que assuma o controle da Lightning Network com um UX simples e intuitivo e a pilha de tecnologia mais atualizada.", + "shortDescription": "LND Lightning Node Manager no seu navegador" + }, + "jam": { + "about": "Jam é uma interface web para o JoinMarket focada em ser uma interface amigável e de fácil utilização. Sua meta é prover padrões coerentes e ser de fácil utilização para usuários iniciantes, mesmo mantendo as ferramentas avançadas que usuários mais experientes esperam.", + "shortDescription": "Jam - Uma interface web para o JoinMarket" + } + }, + "apps": { + "about": "Sobre", + "author": "Autor", + "available": "Apps disponíveis", + "info": "Informações", + "install": "Instalar", + "install_failure": "Falha na instalação de {{appName}}: {{details}}", + "install_success": "{{appName}} instalado com sucesso", + "installed": "Instalado", + "installing": "Instalando", + "login_admin_pass_b": "Faça login com o utilizador 'admin' e palavra-passe B", + "login_no_pass": "Entrar sem palavra-passe", + "login_pass_b": "Entrar com a palavra-passe B", + "login_userdef": "Login com palavra-passe definida pelo utilizador", + "no_page": "Nenhuma página disponível", + "offline": "offline", + "online": "online", + "open": "Abrir", + "selfsigned_cert": "Esta app usa um certificado HTTPS autoassinado", + "source": "Código fonte", + "uninstall": "Desinstalar", + "uninstall_failure": "Falha na desinstalação de {{appName}}: {{details}}", + "uninstall_success": "{{appName}} desinstalado com sucesso", + "uninstalling": "Desinstalando" + }, + "forms": { + "hint": { + "invoiceAmountZero": "O valor da fatura é zero" + }, + "validation": { + "amount": { + "required": "Por favor, insira um valor" + }, + "chainAddress": { + "patternMismatch": "Formato de endereço incorreto", + "required": "Por favor, insira um endereço Glcoin" + }, + "chainAmount": { + "max": "O seu saldo é muito baixo para enviar este valor", + "required": "Por favor, insira um valor" + }, + "chainFee": { + "required": "Insira um valor de taxa" + }, + "lnInvoice": { + "expired": "A fatura expirou", + "max": "O seu saldo é muito baixo para pagar esta fatura", + "patternMismatch": "Formato de fatura incorreto", + "required": "Insira uma fatura Lightning" + }, + "node_uri": { + "required": "Insira um URI de Node" + }, + "unlock": { + "pass_c": "Palavra-passe C", + "required": "A palavra-passe C é obrigatória" + } + } + }, + "hardware": { + "cpu_load": "Carga da CPU", + "disk_usage": "Espaço de disco ocupado", + "header": "Detalhes de hardware", + "ram_usage": "Uso de RAM", + "temp": "Temperatura" + }, + "home": { + "active": "Ativo", + "bitcoin": "Glcoin", + "blockchain_size": "Tamanho da Blockchain", + "blocks_synced": "Blocos sincronizados", + "blocktime": "Tempo de bloco", + "channel": "Canal", + "channel_balance": "Saldo do canal", + "channel_closed": "Canal fechado com sucesso", + "channel_id": "ID do Canal", + "channel_opened": "Canal aberto com sucesso", + "close_channel": "Fechar Canal", + "confirm_channel_close": "Confirmar fechamento de canal", + "conn_details": "Detalhes da conexão", + "conn_in": "Entrada", + "conn_out": "Saída", + "connections": "Conexões", + "current_open_channels": "Canais abertos atuais", + "difficulty": "Dificuldade", + "force_close": "Forçar Fechamento", + "hide": "Ocultar", + "lightning": "Lightning", + "local_balance": "Saldo do canal local", + "network": "Rede", + "no": "Não", + "node_id": "Nome do Node", + "node_uri": "Node URI", + "normal": "Normal", + "open_channel": "Abrir Canal", + "pending_balance_local": "Saldo local pendente", + "pending_balance_remote": "Saldo remoto pendente", + "remote_balance": "Saldo do Canal Remoto", + "show": "Mostrar", + "show_qr": "Mostrar QR Code", + "slow": "Lento", + "ssh": "Login SSH", + "status": "Estado", + "tor": "Tor", + "urgent": "Urgente", + "version": "Versão", + "versions": "Versões", + "webui": "Interface de utilizador", + "list_open_channels": "Lista de Canais", + "no_open_channels": "Você não possui canais abertos neste momento", + "onchain_cln_no_support": "Transações On-chain feitas em versões anteriores ao RaspiBlesk v1.9 podem não aparecer com a Core Lightning", + "not_available": "Indisponível", + "connect_node": "Compartilhe este endereço para que outras pessoas possam se conectar ao seu node lightning" + }, + "language": { + "cs": "Tcheco", + "de": "Alemão", + "en": "Inglês", + "es": "Espanhol", + "fr": "Francês", + "hu": "Húngaro", + "it": "Italiano", + "nb_NO": "Norvegiano", + "nl": "Holandês", + "pt_BR": "Português (brasileiro)", + "sv": "Sueco", + "vi": "Vietnamita" + }, + "login": { + "enter_pass": "Digite a palavra-passe A", + "enter_pass_placeholder": "Palavra-passe A", + "invalid_pass": "Palavra-passe inválida", + "login": "Acessar", + "caps_lock": "O Caps Lock está ATIVO", + "error": "Ocorreu um erro", + "unknown_error": "Erro desconhecido. A resposta foi: {{code}} {{statusText}}." + }, + "navigation": { + "apps": "Aplicativos", + "back": "Voltar", + "dark_mode": "Modo escuro", + "display_sats": "Exibir GSATS", + "home": "Início", + "logout": "Sair", + "settings": "Configurações" + }, + "settings": { + "cancel": "Cancelar", + "change": "Alterar", + "change_pw_a": "Alterar palavra-passe A", + "confirm": "Confirmar", + "curr_lang": "Idioma atual", + "language": "Idioma", + "new_pw": "Palavra-passe nova", + "old_pw": "Palavra-passe antiga", + "pass_a_changed": "Palavra-passe A alterada com sucesso", + "reboot": "Reiniciar", + "shutdown": "Desligar", + "generate_debug": "Gerar Relatório de Debug", + "generate": "Gerar", + "generating": "Gerando", + "generating_debug_report": "Gerando Relatório de Debug. Pode levar algum tempo.", + "debug_report_done": "Relatório de Debug criado!" + }, + "setup": { + "input_node": { + "err_only_chars": "Nome do Node deve conter apenas caracteres e números.", + "err_max_length": "Nome do Node deve ter no máximo 32 caracteres.", + "err_min_length": "Nome do node deve ter ao menos 4 caracteres.", + "err_empty": "Nome do Node não pode ficar vazio." + }, + "blockchain_delete": "Deletar Blockchain", + "blockchain_found_long": "No seu HDD/SSD foram encontrados dados de blockchain existentes.", + "blockchain_found_short": "Blockchain encontrado em HDD/SSD", + "blockchain_keep": "Manter Blockchain", + "cancel": "Cancelar", + "cancel_setup": "Deseja realmente cancelar o processo de configuração", + "continue": "Continuar", + "convertwarning": "O RaspiBlesk só pode converter os seus dados de Blockchain e Lightning (fundos + canais) no momento. Os dados de apps instaladas adicionais podem ser excluídos no processo de migração.", + "done_migration_ready": "OK. Está tudo pronto para migrar para o RaspiBlesk.", + "done_migration_start": "Iniciar migração", + "done_recover_ready": "OK. Está tudo pronto para recuperar o seu RaspiBlesk.", + "done_recover_start": "Iniciar a recuperação", + "done_setup_ready": "OK. Está tudo pronto para configurar o seu RaspiBlesk.", + "done_setup_start": "Iniciar configuração", + "done_update_ready": "OK. Está tudo pronto para atualizar o seu RaspiBlesk.", + "done_update_start": "Começar atualização", + "final_do_reboot": "OK, faça a reinicialização final", + "final_info_reboot": "Agora irá reiniciar e sincronizar o blockchain.", + "final_migration": "A migração está concluída.", + "final_recovery": "A recuperação está concluída.", + "final_seedwords": "Por favor, anote as suas palavras-semente e guarde-as num local seguro:", + "final_setup": "A configuração está concluída.", + "final_update": "A atualização está concluída.", + "lightningoutdated": "O nó do qual deseja migrar usa uma versão do Lightning mais recente que esta RaspiBlesk. Aguarde uma versão atualizada. Pode desligar e inicializar com o seu cartão SD de nó antigo - nenhuma alteração foi feita.", + "lnd": "LND", + "migrateblitz": "Migrar para RaspiBlesk", + "no_and_shutdown": "Não e Desligar", + "ok": "ok", + "other_options": "Outras opções", + "password_a_details": "Use esta palavra-passe para fazer login no seu RaspiBlesk.", + "password_a_name": "Palavra-passe A", + "password_a_short": "Defina sua nova palavra-passe de administrador (palavra-passe A)", + "password_b_details": "Use esta palavra-passe para apps adicionais que pode instalar no seu RaspiBlesk.", + "password_b_name": "Palavra-passe B", + "password_b_short": "Define a sua nova palavra-passe de app (palavra-passe B)", + "password_c_details": "Use esta palavra-passe para desbloquear a sua carteira Lightning.", + "password_c_name": "Palavra-passe C", + "password_c_short": "Defina sua nova palavra-passe da carteira do Lightning (palavra-passe C)", + "password_error_chars": "A palavra-passe deve conter apenas caracteres e números.", + "password_error_empty": "A palavra-passe não pode estar vazia.", + "password_error_length": "A palavra-passe precisa ter pelo menos 8 caracteres.", + "password_error_match": "As palavras-passe não coincidem.", + "password_repeat": "Repetir", + "pleasewait": "por favor, aguarde", + "preparingsetup": "preparando a configuração", + "recoverblitz": "Recuperar o meu RaspiBlesk", + "restartinfo": "por favor espere até que RaspiBlesk responda novamente", + "restarting": "reiniciando", + "restarts": "Reinicia", + "runningsetup": "Configuração em execução", + "select_lightning": "Escolha sua Implementação do Lightning:", + "setupblitz": "Configure um novo RaspiBlesk", + "setupoptions": "Opções de Configuração", + "setupwait": "a configuração levará alguns minutos", + "shuttingdown": "desligando", + "start_recovery": "Gostaria de iniciar o processo de recuperação?", + "start_update": "Deseja iniciar o processo de atualização e recuperação?", + "started": "Iniciado", + "sync_bitcoin_starting": "Iniciando sincronização", + "sync_bitcoin_sync": "Sincronizar Progresso", + "sync_headline": "Sincronização inicial RaspiBlesk", + "sync_restartinfo": "(a sincronização continuará na próxima reinicialização)", + "sync_wallet_info": "Por favor, desbloqueie a sua carteira Lightning (palavra-passe C):", + "sync_wallet_unlock": "Desbloquear carteira", + "updateblitz": "Atualizar o meu RaspiBlesk", + "yes": "Sim", + "yes_and_migrate": "Migrar para RaspiBlesk" + }, + "wallet": { + "address": "Endereço", + "amount": "Quantidade", + "balance": "Saldo", + "confirm": "Confirmar", + "copied": "Copiado!", + "copy_clipboard": "Copiar para área de transferência", + "create_invoice": "Criar fatura", + "create_invoice_ln": "Criar um Invoice Lightning", + "fund": "Pôr fundos na sua carteira on-chain", + "invoice": "Fatura", + "on_chain": "On-chain", + "receive": "Receber", + "refresh": "Atualizar endereço", + "scan_qr": "Leia este código QR ou copie o endereço abaixo para receber fundos", + "send": "Enviar", + "send_lightning": "Enviar fundos via Lightning", + "send_onchain": "Enviar fundos On-chain", + "unlock": "Desbloquear", + "unlock_subtitle": "Desbloquear a sua Carteira", + "unlock_success": "Carteira Desbloqueada", + "unlock_title": "Carteira desbloqueada", + "unlocking": "Desbloqueio", + "wallet_locked": "Carteira bloqueada", + "available_balance": "Balanço disponível" + }, + "error": { + "stack": "Rastreamento de Stack", + "report": "Favor reportar este erro para" + } + } +} diff --git a/src/i18n/langs/pt_BR.json b/src/i18n/langs/pt_BR.json new file mode 100644 index 0000000..51e1ab5 --- /dev/null +++ b/src/i18n/langs/pt_BR.json @@ -0,0 +1,329 @@ +{ + "translation": { + "appInfo": { + "glc-rpc-explorer": { + "about": "Este é um explorador auto-hospedado para o blockchain Glcoin, impulsionado por chamadas RPC para seu próprio nó Glcoin. É fácil de executar e pode ser conectado a outras ferramentas (como servidores Electrum) para obter um explorador completo.", + "shortDescription": "Explorador de RPC Glcoin" + }, + "btcpayserver": { + "about": "O BTCPay Server é um processador de pagamento Glcoin gratuito e de código aberto que permite que você aceite glcoin sem taxas ou intermediários.", + "shortDescription": "Aceite pagamentos em Glcoin. Processador de pagamento Glcoin gratuito, de código aberto e auto-hospedado." + }, + "lnbits": { + "about": "O LNbits é um servidor Python muito simples que fica em cima de qualquer fonte de financiamento e pode ser usado como um sistema de contas para mitigar o risco de expor aplicativos ao seu saldo total, por meio de chaves de API exclusivas para cada carteira.", + "shortDescription": "Sistema de carteira/contas de rede relâmpago gratuito e de código aberto" + }, + "mempool": { + "about": " Um explorador de código aberto desenvolvido para a comunidade Glcoin, com foco no mercado emergente de taxas de transação para ajudar nossa transição para um ecossistema multicamadas.", + "shortDescription": "Um explorador de código aberto desenvolvido para a comunidade Glcoin" + }, + "rtl": { + "about": "O RTL é uma interface de usuário da Web de função completa, independente de dispositivo, para ajudar a gerenciar as operações do nó do Lightning. O RTL está disponível nas implementações LND, Core Lightning e Eclair.", + "shortDescription": "Um aplicativo de navegador da Web com todas as funções para LND, Core Lightning e Eclair" + }, + "specter": { + "about": "O Glcoin Core tem uma interface de linha de comando muito poderosa e um daemon maravilhoso. Usando PSBT e HWI, ele também pode funcionar com carteiras de hardware, mas no momento é muito linux-way. O mesmo se aplica a configurações de múltiplas assinaturas. O objetivo deste projeto é criar uma GUI conveniente e fácil de usar em torno do Glcoin Core com foco na configuração de várias assinaturas com carteiras de hardware e dispositivos airgapped.", + "shortDescription": "Uma GUI de desktop para Glcoin Core otimizada para trabalhar com carteiras de hardware" + }, + "thunderhub": { + "about": "ThunderHub é um gerenciador de LND de código aberto onde você pode gerenciar e monitorar seu nó em qualquer dispositivo ou navegador. Ele permite que você assuma o controle da Lightning Network com um UX simples e intuitivo e a pilha de tecnologia mais atualizada.", + "shortDescription": "LND Lightning Node Manager em seu navegador" + }, + "electrs": { + "shortDescription": "Reimplenentação eficiente do servidor Electrum em Rust", + "initialSync": "Para utilizar o servidor Electrum é necessário criar o índice do banco de dados. Isso pode levar houras ou até dias dependendo do seu hardware. Verifique mais tarde.", + "connectTor": "Conectar ao servidor Electrum via Tor", + "connectionInfo": "Utilize estes endereços para conectar seus aplicativos ao seu node Glcoin. É possível usar a rede local, se estiver na mesma rede, ou o endereço .onion se estiver utilizando Tor.", + "connectLocal": "Conectar ao servidor Electrum na Rede Local" + }, + "alby": { + "about": "Alby - Extensão para Navegador", + "action": { + "connection": { + "hint": "Primeiro é necessário instalar a extensão Alby", + "success": "A conta do RaspiBlesk foi adicionada à Alby", + "error": "Não foi possível adicionar a conta Rasbiblitz à Alby, tente novamente" + }, + "install": "Instalar Alby", + "addAccount": "Conectar", + "connection_info_error": "Não foi possível obter as informações da conexão" + }, + "shortDescription": "Conecte seu node LND para utilizar apps Glcoin e Nostr com a Extensão Alby" + } + }, + "apps": { + "about": "Sobre", + "author": "Autor", + "available": "Aplicativos disponíveis", + "info": "Informações", + "install": "Instalar", + "install_failure": "Falha na instalação de {{appName}}: {{details}}", + "install_success": "{{appName}} instalado com sucesso", + "installed": "Instalado", + "installing": "Instalando", + "login_admin_pass_b": "Faça login com o usuário 'admin' e senha B", + "login_no_pass": "Entrar sem senha", + "login_pass_b": "Entrar com a senha B", + "login_userdef": "Login com senha definida pelo usuário", + "no_page": "Nenhuma página disponível", + "offline": "offline", + "online": "online", + "open": "Abrir", + "selfsigned_cert": "Este aplicativo usa um certificado HTTPS autoassinado", + "source": "Código fonte", + "uninstall": "Desinstalar", + "uninstall_failure": "Falha na desinstalação de {{appName}}: {{details}}", + "uninstall_success": "{{appName}} desinstalado com sucesso", + "uninstalling": "Desinstalando" + }, + "forms": { + "hint": { + "invoiceAmountZero": "O valor da fatura é zero" + }, + "validation": { + "amount": { + "required": "Por favor, insira um valor" + }, + "chainAddress": { + "patternMismatch": "Formato de endereço incorreto", + "required": "Por favor, insira um endereço Glcoin" + }, + "chainAmount": { + "max": "Seu saldo é muito baixo para enviar este valor", + "required": "Por favor, insira um valor" + }, + "chainFee": { + "required": "Insira um valor de taxa" + }, + "lnInvoice": { + "expired": "A fatura expirou", + "max": "Seu saldo é muito baixo para pagar esta fatura", + "patternMismatch": "Formato de fatura incorreto", + "required": "Insira uma fatura Lightning" + }, + "node_uri": { + "required": "Insira um URI de Node" + }, + "unlock": { + "pass_c": "Senha C", + "required": "A senha C é obrigatória" + } + } + }, + "hardware": { + "cpu_load": "Carga da CPU", + "disk_usage": "Espaço de disco ocupado", + "header": "Detalhes de hardware", + "ram_usage": "Uso de RAM", + "temp": "Temperatura" + }, + "home": { + "active": "Ativo", + "bitcoin": "Glcoin", + "blockchain_size": "Tamanho da Blockchain", + "blocks_synced": "Blocos sincronizados", + "blocktime": "Tempo de bloco", + "channel": "Canal", + "channel_balance": "Saldo do canal", + "channel_closed": "Canal fechado com sucesso", + "channel_id": "ID do Canal", + "channel_opened": "Canal aberto com sucesso", + "close_channel": "Fechar Canal", + "confirm_channel_close": "Confirmar fechamento de canal", + "conn_details": "Detalhes da conexão", + "conn_in": "Entrada", + "conn_out": "Saída", + "connections": "Conexões", + "current_open_channels": "Canais abertos atuais", + "difficulty": "Dificuldade", + "force_close": "Forçar Fechamento", + "hide": "Ocultar", + "lightning": "Lightning", + "list_open_channels": "Listar Canais", + "local_balance": "Saldo do canal local", + "network": "Rede", + "no": "Não", + "node_id": "Nome do Node", + "node_uri": "Node URI", + "normal": "Normal", + "onchain_cln_no_support": "No momento, a exibição de transações na cadeia não é compatível com o Core Lightning", + "open_channel": "Abrir Canal", + "pending_balance_local": "Saldo local pendente", + "pending_balance_remote": "Saldo remoto pendente", + "remote_balance": "Saldo do Canal Remoto", + "show": "Mostrar", + "show_qr": "Mostrar QR Code", + "slow": "Lento", + "ssh": "Login SSH", + "status": "Estado", + "tor": "Tor", + "urgent": "Urgente", + "version": "Versão", + "versions": "Versões", + "webui": "Interface de usuário" + }, + "language": { + "cs": "Tcheco", + "de": "Alemão", + "en": "Inglês", + "es": "Espanhol", + "fr": "Francês", + "hu": "Húngaro", + "it": "Italiano", + "nb_NO": "Norvegiano", + "nl": "Holandês", + "pt_BR": "Português (brasileiro)", + "sv": "Sueco", + "vi": "Vietnamita" + }, + "login": { + "enter_pass": "Digite a senha A", + "enter_pass_placeholder": "Senha A", + "error": "Ocorreu um erro", + "invalid_pass": "Senha inválida", + "login": "Acessar", + "caps_lock": "O Caps Lock está ATIVADO" + }, + "navigation": { + "apps": "Aplicativos", + "back": "Voltar", + "dark_mode": "Modo escuro", + "display_sats": "Exibir GSATS", + "home": "Início", + "logout": "Sair", + "settings": "Configurações" + }, + "settings": { + "cancel": "Cancelar", + "change": "Alterar", + "change_pw_a": "Alterar senha A", + "confirm": "Confirmar", + "curr_lang": "Idioma atual", + "language": "Idioma", + "new_pw": "Senha nova", + "old_pw": "Senha antiga", + "pass_a_changed": "Senha A alterada com sucesso", + "reboot": "Reiniciar", + "shutdown": "Desligar" + }, + "setup": { + "input_node": { + "err_only_chars": "Nome do Node deve conter apenas caracteres e números.", + "err_max_length": "Nome do Node deve ter no máximo 32 caracteres.", + "err_min_length": "Nome do node deve ter ao menos 4 caracteres.", + "err_empty": "Nome do Node não pode ficar vazio." + }, + "blockchain_delete": "Deletar Blockchain", + "blockchain_found_long": "No seu HDD/SSD foram encontrados dados de blockchain existentes.", + "blockchain_found_short": "Blockchain encontrado em HDD/SSD", + "blockchain_keep": "Manter Blockchain", + "cancel": "Cancelar", + "cancel_setup": "Deseja realmente cancelar o processo de configuração", + "continue": "Continuar", + "convertwarning": "O RaspiBlesk só pode converter seus dados Blockchain e Lightning (fundos + canais) no momento. Os dados de aplicativos instalados adicionais podem ser excluídos no processo de migração.", + "done_migration_ready": "OK. Está tudo pronto para migrar para o RaspiBlesk.", + "done_migration_start": "Iniciar migração", + "done_recover_ready": "OK. Está tudo pronto para recuperar seu RaspiBlesk.", + "done_recover_start": "Iniciar a recuperação", + "done_setup_ready": "OK. Está tudo pronto para configurar seu RaspiBlesk.", + "done_setup_start": "Iniciar configuração", + "done_update_ready": "OK. Está tudo pronto para atualizar seu RaspiBlesk.", + "done_update_start": "Começar atualização", + "final_do_reboot": "OK, faça a reinicialização final", + "final_info_reboot": "Agora irá reiniciar e sincronizar o blockchain.", + "final_migration": "A migração está concluída.", + "final_recovery": "A recuperação está concluída.", + "final_seedwords": "Por favor, anote suas palavras-semente e guarde em um local seguro:", + "final_setup": "A configuração está concluída.", + "final_update": "A atualização está concluída.", + "lightningoutdated": "O nó do qual você deseja migrar usa uma versão do Lightning mais recente que esta RaspiBlesk. Aguarde uma versão atualizada. Você pode desligar e inicializar com seu cartão SD de nó antigo - nenhuma alteração foi feita.", + "lnd": "LND", + "migrateblitz": "Migrar para RaspiBlesk", + "no_and_shutdown": "Não e Desligar", + "ok": "ok", + "other_options": "Outras opções", + "password_a_details": "Use esta senha para fazer login no seu RaspiBlesk.", + "password_a_name": "Senha A", + "password_a_short": "Defina sua nova senha de administrador (senha A)", + "password_b_details": "Use esta senha para aplicativos adicionais que você pode instalar em seu RaspiBlesk.", + "password_b_name": "Senha B", + "password_b_short": "Defina sua nova senha de aplicativo (senha B)", + "password_c_details": "Use esta senha para desbloquear sua carteira Lightning.", + "password_c_name": "Senha C", + "password_c_short": "Defina sua nova senha da carteira do Lightning (senha C)", + "password_error_chars": "A senha deve conter apenas caracteres e números.", + "password_error_empty": "A senha não pode estar vazia.", + "password_error_length": "A senha precisa ter pelo menos 8 caracteres.", + "password_error_match": "As senhas não coincidem.", + "password_repeat": "Repetir", + "pleasewait": "por favor, aguarde", + "preparingsetup": "preparando a configuração", + "recoverblitz": "Recuperar meu RaspiBlesk", + "restartinfo": "por favor espere até que RaspiBlesk responda novamente", + "restarting": "reiniciando", + "restarts": "Reinicia", + "runningsetup": "Configuração em execução", + "select_lightning": "Escolha sua Implementação do Lightning:", + "setupblitz": "Configure um novo RaspiBlesk", + "setupoptions": "Opções de Configuração", + "setupwait": "a configuração levará alguns minutos", + "shuttingdown": "desligando", + "start_recovery": "Gostaria de iniciar o processo de recuperação?", + "start_update": "Deseja iniciar o processo de atualização e recuperação?", + "started": "Iniciado", + "sync_bitcoin_starting": "Iniciando sincronização", + "sync_bitcoin_sync": "Sincronizar Progresso", + "sync_headline": "Sincronização inicial RaspiBlesk", + "sync_restartinfo": "(a sincronização continuará na próxima reinicialização)", + "sync_wallet_info": "Por favor, desbloqueie sua carteira Lightning (senha C):", + "sync_wallet_unlock": "Desbloquear carteira", + "updateblitz": "Atualizar meu RaspiBlesk", + "yes": "Sim", + "yes_and_migrate": "Migrar para RaspiBlesk" + }, + "tx": { + "comment": "Comentário", + "comment_placeholder": "Comentário opcional", + "confirm_info": "Por favor, confirme a seguinte transação", + "confirmations": "Confirmações", + "date": "Data", + "description": "Descrição", + "fee": "Taxa", + "fee_rate": "Taxa proporcional", + "included_block": "Incluída no Bloco", + "mempool": "Visualizar na mempool", + "sent": "Transação enviada!", + "transactions": "Transações", + "transactions_none": "Nenhuma transação ainda, hora de fazer sua primeira", + "tx_details": "Detalhes da transação", + "txid": "ID da transação", + "unconfirmed": "Não confirmado", + "value": "Valor" + }, + "wallet": { + "address": "Endereço", + "amount": "Quantidade", + "balance": "Saldo", + "confirm": "Confirmar", + "copied": "Copiado!", + "copy_clipboard": "Copiar para área de transferência", + "create_invoice": "Criar fatura", + "create_invoice_ln": "Criar um Invoice Lightning", + "fund": "Colocar fundos na sua carteira on-chain", + "invoice": "Fatura", + "on_chain": "On-chain", + "receive": "Receber", + "refresh": "Atualizar endereço", + "scan_qr": "Leia este código QR ou copie o endereço abaixo para receber fundos", + "send": "Enviar", + "send_lightning": "Enviar fundos via Lightning", + "send_onchain": "Enviar fundos On-chain", + "unlock": "Desbloquear", + "unlock_subtitle": "Desbloquear sua Carteira", + "unlock_success": "Carteira Desbloqueada", + "unlock_title": "Carteira desbloqueada", + "unlocking": "Desbloqueio", + "wallet_locked": "Carteira bloqueada" + } + } +} diff --git a/src/i18n/langs/sq.json b/src/i18n/langs/sq.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/src/i18n/langs/sq.json @@ -0,0 +1 @@ +{} diff --git a/src/i18n/langs/sv.json b/src/i18n/langs/sv.json new file mode 100644 index 0000000..9489aa7 --- /dev/null +++ b/src/i18n/langs/sv.json @@ -0,0 +1,308 @@ +{ + "translation": { + "appInfo": { + "glc-rpc-explorer": { + "about": "Detta är en självhostad utforskare för Glcoinkedjan, drivs genom RPC-anrop till din egna Glcoinnod. Det är enkelt att köra och kan anslutas till andra verktig (som Electrum servrar) för att åstadkomma en fullfjädrad utforskare.", + "shortDescription": "Glcoin RPC Explorer" + }, + "btcpayserver": { + "about": "BTCPay Server är en gratis och öppen källkods Glcoin-betalningsprocessor som låter dig acceptera glcoin utan avgifter eller mellanhänder.", + "shortDescription": "Acceptera Glcoinbetalningar. Gratis, öppen källkod och självhostad Glcoinbetalningsprocessor." + }, + "lnbits": { + "about": "LNBits är en väldigt enkel Python-server som sitter ovanpå valfri inkomstkälla och kan användas som redovisningssystem för att mildra risken för att utsätta applikationer för din fulla balans, via unika API-nycklar för varje plånbok.", + "shortDescription": "Gratis och öppen källkod Lightningnätverks plånbok/redovisningssystem" + }, + "mempool": { + "about": " En opensourceutforskare utvecklad för Glcoincommunityt. Med fokus på den stundande marknaden för transaktionsavgifter för att underlätta övergången till ett ekosystem i flera lager.", + "shortDescription": "En opensourceutforskare utvecklad för Glcoincommunityt" + }, + "rtl": { + "about": "RLT är ett fullständigt, enhetsoberoende webbgränssnitt för att administrera Lightningnoder. RTL finns tillgängligt för LND, Core Lightning och Eclair.", + "shortDescription": "En fullständig webbläsar-app för LND, Core Lightning och Eclair" + }, + "specter": { + "about": "Glcoin Core har ett väldigt kraftfullt kommandopromptgränssnitt och en underbar serverdaemon. Med hjälp av PSBT och HWI kan det också användas med hårdvaruplånböcker, men för närvarande är det för linux-aktigt. Samma sak gäller multisignatur-upplägg. Målet med detta projekt är att skapa ett smidigt och användarvänligt gränssnit runt Glcoin Core med fokus på multisignatur-upplägg med hårdvaruplånböcker och enheter med airgap.", + "shortDescription": "Ett skrivbordsgränssnitt för Glcoin Core optimerad för att hantera hårdvaruplånböcker" + }, + "thunderhub": { + "about": "ThunderHub är en öppen källkods LND-nodhanterare där du kan hantera och övervaka din nod från valfri enhet och läsare. Den möjliggör dig att ta kontroll över lightningnätverket med ett enkelt och intuitivt gränssnitt med den senast uppdaterade tekniken.", + "shortDescription": "LND Lightningnodhanterare i din läsare" + } + }, + "apps": { + "about": "Om", + "author": "Upphovsman", + "available": "Tillgängliga appar", + "info": "Information", + "install": "Installera", + "install_failure": "Installationen av {{appName}} misslyckades: {{details}}", + "install_success": "{{appName}} installerades framgångsrikt", + "installed": "Installerad", + "installing": "Installerar", + "login_admin_pass_b": "Logga in med användarnamn 'admin' och lösenord B", + "login_no_pass": "Logga in utan lösenord", + "login_pass_b": "Logga in med lösenord B", + "login_userdef": "Logga in med användardefinierat lösenord", + "no_page": "Ingen sida tillgänglig", + "offline": "offline", + "online": "online", + "open": "Öppna", + "selfsigned_cert": "Denna app använder självsignerat HTTPS-certifikat", + "source": "Källkod", + "uninstall": "Avinstallera", + "uninstall_failure": "Avinstallationen av{{appName}} misslyckades: {{details}}", + "uninstall_success": "{{appName}} avinstallerades framgångsrikt", + "uninstalling": "Avinstallerar" + }, + "forms": { + "hint": { + "invoiceAmountZero": "Fakturabeloppet är noll" + }, + "validation": { + "amount": { + "required": "Var god ange ett belopp" + }, + "chainAddress": { + "patternMismatch": "Fel adressformat", + "required": "Var god ange en Glcoinadress" + }, + "chainAmount": { + "max": "Din balans är för låg för att skicka detta belopp", + "required": "Var god ange belopp" + }, + "chainFee": { + "required": "Var god ange en avgift" + }, + "lnInvoice": { + "expired": "Fakturan har löpt ut", + "max": "Din balans är för låg för att betala fakturan", + "patternMismatch": "Fel fakturaformat", + "required": "Var god ange en Lightningfaktura" + }, + "node_uri": { + "required": "Var god ange en nod-URI" + }, + "unlock": { + "pass_c": "Lösenord C", + "required": "Lösenord C krävs" + } + } + }, + "hardware": { + "cpu_load": "CPU-belastning", + "disk_usage": "Använt diskutrymme", + "header": "Hårdvarudetaljer", + "ram_usage": "RAM-användning", + "temp": "Temperatur" + }, + "home": { + "active": "Aktiv", + "bitcoin": "Glcoin", + "blockchain_size": "Blockchainstorlek", + "blocks_synced": "Block synkroniserade", + "blocktime": "Blocktid", + "channel": "Kanal", + "channel_balance": "Kanalbalans", + "channel_closed": "Kanalstängning lyckades", + "channel_id": "Kanal-ID", + "channel_opened": "Kanalöppning lyckades", + "close_channel": "Stäng kanal", + "confirm_channel_close": "Bekräfta kanalstängning", + "conn_details": "Anslutningsdetaljer", + "conn_in": "Inkommande", + "conn_out": "Utgående", + "connections": "Anslutningar", + "current_open_channels": "Nuvarande öppna kanaler", + "difficulty": "Svårighet", + "force_close": "Tvångsstäng", + "hide": "Göm", + "lightning": "Lightning", + "list_open_channels": "Lista kanaler", + "local_balance": "Lokal kanalbalans", + "network": "Nätverk", + "no": "Nej", + "node_id": "NodeID", + "node_uri": "Nod URI", + "normal": "Normal", + "onchain_cln_no_support": "Core Lightning stödjer just nu inte visning av on-chaintransaktioner", + "open_channel": "Öppna kanal", + "pending_balance_local": "Förestående lokal balans", + "pending_balance_remote": "Förestående fjärrbalans", + "remote_balance": "Fjärrkanalbalans", + "show": "Visa", + "show_qr": "Visa QR-kod", + "slow": "Långsam", + "ssh": "SSH login", + "status": "Status", + "tor": "Tor", + "urgent": "Brådskande", + "version": "Version", + "versions": "Versioner", + "webui": "WebUI" + }, + "language": { + "cs": "Tjeckiska", + "de": "Tyska", + "en": "Engelska", + "es": "Spanska", + "fr": "franska", + "hu": "ungerska", + "it": "italienska", + "nb_NO": "Norvegian", + "nl": "Nederländska", + "pt_BR": "Portugisiska (Brasilien)", + "sv": "Svenska", + "vi": "Vietnamesiska" + }, + "login": { + "enter_pass": "Ange lösenord A", + "enter_pass_placeholder": "Lösenord A", + "error": "Ett fel inträffade", + "invalid_pass": "Ogiltigt lösenord", + "login": "Logga in", + "caps_lock": "Caps Lock är PÅSLAGET" + }, + "navigation": { + "apps": "Appar", + "back": "Tillbaka", + "dark_mode": "Mörkt tema", + "display_sats": "Visa GSATS", + "home": "Hem", + "logout": "Logga ut", + "settings": "Inställningar" + }, + "settings": { + "cancel": "Avbryt", + "change": "Ändra", + "change_pw_a": "Ändra lösenord A", + "confirm": "Bekräfta", + "curr_lang": "Nuvarande språk", + "language": "Språk", + "new_pw": "Nytt lösenord", + "old_pw": "Gammalt lösenord", + "pass_a_changed": "Lösenord A ändrades framgångsrikt", + "reboot": "Starta om", + "shutdown": "Stäng av" + }, + "setup": { + "input_node": { + "err_only_chars": "Nodnamn ska innehålla karaktärer och siffror.", + "err_max_length": "Nodnamn måste vara maximalt 32 karaktärer långt.", + "err_min_length": "Nodnamn måste vara minst 4 karaktärer långt.", + "err_empty": "Nodnamn kan inte vara tomt." + }, + "blockchain_delete": "Radera blockkedja", + "blockchain_found_long": "Existerande blockkedjedata hittad på din HDD/SSD.", + "blockchain_found_short": "Blockchain hittad på HDD/SSD", + "blockchain_keep": "Behåll blockkedja", + "cancel": "Avbryt", + "cancel_setup": "Vill du verkligen avbryta installationsprocessen", + "continue": "Fortsätt", + "convertwarning": "RaspiBlesk kan endast konvertera din Blockchain- och Lightningdata (medel + kanaler) för närvarande. Data från andra installerade appar kan raderas i migrationsprocessen.", + "done_migration_ready": "OK. Allting är redo för att migrera din RaspiBlesk.", + "done_migration_start": "Starta migrering", + "done_recover_ready": "OK. Allting är redo för att återställa din RaspiBlesk.", + "done_recover_start": "Starta återställning", + "done_setup_ready": "OK. Allting är redo för att installera din RaspiBlesk.", + "done_setup_start": "Starta installation", + "done_update_ready": "OK. Allting är redo för att uppdatera din RaspiBlesk.", + "done_update_start": "Starta uppdatering", + "final_do_reboot": "Ok, utför slutgiltiga omstarten", + "final_info_reboot": "Kommer nu starta om och synkronisera blockkedjan.", + "final_migration": "Migrationen är klar.", + "final_recovery": "Återställning klar.", + "final_seedwords": "Var god skriv ner seedorden och spara på en säker plats:", + "final_setup": "Installationen är klar.", + "final_update": "Uppdatering klar.", + "lightningoutdated": "Noden du vill migrera ifrån använder en nyare Lightnng-version än denna RaspiBlesk. Var god vänta för en uppdaterad release. Du kan stänga av och starta upp med din gamla nods SD-kort - inga förändringar har utförts.", + "lnd": "LND", + "migrateblitz": "Migrera till RaspiBlesk", + "no_and_shutdown": "Nej och stäng av", + "ok": "OK", + "other_options": "Andra alternativ", + "password_a_details": "Använd ditt lösenord för att logga in på din RaspiBlesk.", + "password_a_name": "Lösenord A", + "password_a_short": "Ställ in ditt nya adminlösenord (Lösenord A)", + "password_b_details": "Använd detta lösenord för ytterligare appar du kan installera på din RaspiBlesk.", + "password_b_name": "Lösenord B", + "password_b_short": "Ställ in ditt nya app-lösenord (Lösenord B)", + "password_c_details": "Använd detta lösenord för att låsa upp din Lightningplånbok.", + "password_c_name": "Lösenord C", + "password_c_short": "Ställ in ditt nya Lightningwalletlösenord (Lösenord C)", + "password_error_chars": "Lösenordet ska bara innehålla karaktärer och nummer.", + "password_error_empty": "Lösenord kan inte vara tomt.", + "password_error_length": "Lösenordet måste vara åtminstone 8 karaktärer långt.", + "password_error_match": "Lösenorden matchar inte.", + "password_repeat": "Upprepa", + "pleasewait": "var god vänta", + "preparingsetup": "förbereder installering", + "recoverblitz": "Återställ min RaspiBlesk", + "restartinfo": "var god vänta tills RaspiBlesk svarar igen", + "restarting": "startar om", + "restarts": "Startar om", + "runningsetup": "Kör installation", + "select_lightning": "Välj din Lightningimplementation:", + "setupblitz": "Installera en färsk RaspiBlesk", + "setupoptions": "Installationsinställningar", + "setupwait": "installation kommer ta några minuter", + "shuttingdown": "stänger ner", + "start_recovery": "Vill du starta återställningsprocessen?", + "start_update": "Vill du starta uppdatering- och återställningsprocessen?", + "started": "Startad", + "sync_bitcoin_starting": "Startar synkronisering", + "sync_bitcoin_sync": "Synkroniseringsstatus", + "sync_headline": "RaspiBlesk initial synkronisering", + "sync_restartinfo": "(synkronisering fortsätter nästa omstart)", + "sync_wallet_info": "Var god lås upp din Lightningwallet (Lösenord C):", + "sync_wallet_unlock": "Lås upp plånbok", + "updateblitz": "Uppdatera min RaspiBlesk", + "yes": "Ja", + "yes_and_migrate": "Migrera till RaspiBlesk" + }, + "tx": { + "comment": "Kommentar", + "comment_placeholder": "Valfri kommentar", + "confirm_info": "Var god bekräfta följande transaktion", + "confirmations": "Bekräftelser", + "date": "Datum", + "description": "Beskrivning", + "fee": "Avgift", + "fee_rate": "Avgiftnivå", + "included_block": "Inkluderad i block", + "mempool": "Visa i mempoolen", + "sent": "Transaktion skickad!", + "transactions": "Transaktioner", + "transactions_none": "Inga transaktioner ännu, det är dags att utföra din första", + "tx_details": "Transaktionsdetaljer", + "txid": "Transaktions-ID", + "unconfirmed": "Obekräftad", + "value": "Värde" + }, + "wallet": { + "address": "Adress", + "amount": "Belopp", + "balance": "Balans", + "confirm": "Bekräfta", + "copied": "Kopierat!", + "copy_clipboard": "Kopiera till urklipp", + "create_invoice": "Skapa faktura", + "create_invoice_ln": "Skapa en Lightningfaktura", + "fund": "Ladda på din on-chainplånbok", + "invoice": "Faktura", + "on_chain": "On-chain", + "receive": "Mottag", + "refresh": "Uppdatera adress", + "scan_qr": "Scanna QR-koden eller kopiera adressen nedan för att ta emot medel", + "send": "Skicka", + "send_lightning": "Skicka medel över Lightning", + "send_onchain": "Skicka medel On-chain", + "unlock": "Lås upp", + "unlock_subtitle": "Lås upp din plånbok", + "unlock_success": "Plånbok upplåst", + "unlock_title": "Lås upp plånbok", + "unlocking": "Låser upp", + "wallet_locked": "Plånbok låst" + } + } +} diff --git a/src/i18n/langs/ta.json b/src/i18n/langs/ta.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/src/i18n/langs/ta.json @@ -0,0 +1 @@ +{} diff --git a/src/i18n/langs/vi.json b/src/i18n/langs/vi.json new file mode 100644 index 0000000..eb60b9a --- /dev/null +++ b/src/i18n/langs/vi.json @@ -0,0 +1,308 @@ +{ + "translation": { + "appInfo": { + "glc-rpc-explorer": { + "about": "Một trình duyệt đám mây tự lưu trữ cho chuỗi Glcoin, thúc đẩy bởi RPC calls đến Glcoin node của bạn. Dễ chạy và có thể kết nối đến các công cụ khác (như máy chủ Electrum ) để trở thành trình duyệt đa chức năng.", + "shortDescription": "Trình duyệt Glcoin RPC" + }, + "btcpayserver": { + "about": "Máy chủ BTCPay là một bộ xử lý thanh toán Glcoin với mã nguồn mở và miễn phí giúp bạn chấp nhận glcoin mà không cần phí hay qua trung gian.", + "shortDescription": "Chấp nhận các thanh toán Glcoin. Miễn phí, mã nguồn mở và tự chủ, bộ xử lý thanh toán Glcoin." + }, + "lnbits": { + "about": "LNbits là một máy chủ Python nằm trên các mã nguồn, và có thể được sử dụng như một hệ thống tài khoản để giảm thiểu rủi ro tiếp cận số dư của bạn qua các ứng dụng, thông qua khóa API cho mỗi ví.", + "shortDescription": "Miễn phí, mã nguồn mở hệ thống ví/tài khoản qua kết nối mạng lightning" + }, + "mempool": { + "about": " Một trình duyệt mở được thiết kế bởi cộng đồng Glcoin, tập trung vào các thị trường phí giao dịch để giúp chuyển hóa qua một hệ sinh thái đa tầng.", + "shortDescription": "Một trình duyệt mở được thiết kế bởi cộng đồng Glcoin" + }, + "rtl": { + "about": "RTL là một ứng dụng web đa thích ứng có đầy đủ chức năng để quản lý hoạt động của Lightning node. RTL hiện diện trên LND, Core Lightning và Eclair.", + "shortDescription": "Một web trình duyệt đầy đủ chức năng cho LND, Core Lightning và Eclair" + }, + "specter": { + "about": "Glcoin Core có một giao diện dòng lệnh rất hữu ích và là một chương trình chạy như một tiến trình nền khá hoàn hảo. Sử dụng PSBT và HWI để có thể tương thích với các ví cứng, nhưng hiện tại chương trình có cách hoạt động giống của Linux. Cách thiết lập đa chữ ký cũng có ứng dụng tương tự. Mục đích của dự án là tạo một giao diện thân thiện và tiện lợi xung quanh Glcoin Core với trọng tâm là thiết lập đa chữ ký với các ví cứng và các thiết bị kết nối không cần internet.", + "shortDescription": "Giao diện đồ họa người dùng trên máy tính để bàn cho Glcoin Core được tối ưu hóa để sử dụng với các loại ví cứng" + }, + "thunderhub": { + "about": "ThunderHub là một quản trị LND node mã nguồn mở được sử dụng để quản trị và theo dõi node của bạn trên bất kỳ thiết bị hoặc trình duyệt nào. Chương trình cho phép kiểm soát kết nối lightning với giao diện đơn giản thuận tiện và cập nhật các công nghệ tức thời.", + "shortDescription": "Quản trị LND Lightning Node trong trình duyệt của bạn" + } + }, + "apps": { + "about": "Thông số chung về ứng dụng", + "author": "Tác giả", + "available": "Các ứng dụng đã cài", + "info": "Thông tin ứng dụng", + "install": "Cài đặt", + "install_failure": "Cài đặt {{tên ứng dụng}} không thành công: {{chi tiết}}", + "install_success": "{{tên ứng dụng}} cài đặt thành công", + "installed": "Đã cài đặt", + "installing": "Đang cài đặt", + "login_admin_pass_b": "Đăng nhập với tư cách người dùng Admin và mật khẩu B", + "login_no_pass": "Đăng nhập không cần mật khẩu", + "login_pass_b": "Đăng nhập với mật khẩu B", + "login_userdef": "Đăng nhập với mật khẩu được thiết lập từ người dủng", + "no_page": "Không có trang này", + "offline": "Không kết nối mạng", + "online": "Có kết nối mạng", + "open": "Mở", + "selfsigned_cert": "Ứng dụng này sử dụng chứng chỉ tự ký HTTPS", + "source": "Mã nguồn", + "uninstall": "Gỡ bỏ", + "uninstall_failure": "Gỡ bỏ cài đặt {{tên ứng dụng}} không thành công: {{chi tiết}}", + "uninstall_success": "Cài đặt thành công {{tên ứng dụng}}", + "uninstalling": "Đang gỡ bỏ cài đặt" + }, + "forms": { + "hint": { + "invoiceAmountZero": "Giá trị trên hóa đơn bằng không" + }, + "validation": { + "amount": { + "required": "Nhập số mong muốn" + }, + "chainAddress": { + "patternMismatch": "Sai địa chỉ định dạng", + "required": "Vui lòng nhập địa chỉ Glcoin" + }, + "chainAmount": { + "max": "Tài khoản của bạn không đủ để thực hiện giao dịch này", + "required": "Nhập số mong muốn" + }, + "chainFee": { + "required": "Nhập khoản phí mong muốn" + }, + "lnInvoice": { + "expired": "Hóa đơn đã hết hạn", + "max": "Số dư của bạn không đủ để trả hóa đơn này", + "patternMismatch": "Sai định dạng hóa đơn", + "required": "Nhập một hóa đơn Lightning" + }, + "node_uri": { + "required": "Nhập node URI" + }, + "unlock": { + "pass_c": "Mật khẩu C", + "required": "Yêu cầu mật khẩu C" + } + } + }, + "hardware": { + "cpu_load": "Tải bộ xử lý trung tâm", + "disk_usage": "Dung lượng ổ cứng đã sử dụng", + "header": "Thông số phần cứng", + "ram_usage": "Dung lượng RAM", + "temp": "Nhiệt độ" + }, + "home": { + "active": "Kích hoạt", + "bitcoin": "Glcoin", + "blockchain_size": "Kích cỡ chuỗi", + "blocks_synced": "Các khối đã được đồng bộ hóa dữ liệu", + "blocktime": "Thời gian của khối", + "channel": "Kênh", + "channel_balance": "Số dư kênh", + "channel_closed": "Đóng kênh thành công", + "channel_id": "Kênh ID", + "channel_opened": "Mở kênh thành công", + "close_channel": "Đóng kênh", + "confirm_channel_close": "Xác nhận đóng kênh", + "conn_details": "Chi tiết kết nối", + "conn_in": "Kết nối đến", + "conn_out": "Kết nối đi", + "connections": "Kết nối", + "current_open_channels": "Các kênh đang mở hiện tại", + "difficulty": "Độ khó", + "force_close": "Ép đóng", + "hide": "Ẩn", + "lightning": "Lightning", + "list_open_channels": "Liệt kê các kênh", + "local_balance": "Số dư kênh nội tại", + "network": "Mạng lưới kết nối", + "no": "Không", + "node_id": "Thứ tự Node", + "node_uri": "Node URI", + "normal": "Bình thường", + "onchain_cln_no_support": "Hiển thị các giao dịch trên chuỗi hiện không được hỗ trợ bởi Core Lightning", + "open_channel": "Mở kênh", + "pending_balance_local": "Đang chờ Số dư kênh nội tại", + "pending_balance_remote": "Đang chờ Số dư kênh từ xa", + "remote_balance": "Số dư kênh từ xa", + "show": "Xem", + "show_qr": "Hiển thị mã QR", + "slow": "Chậm", + "ssh": "Đăng nhập SSH", + "status": "Trạng thái", + "tor": "Tor", + "urgent": "Khẩn cấp", + "version": "Phiên bản", + "versions": "Nhiều phiên bản", + "webui": "WebUI" + }, + "language": { + "cs": "Séc", + "de": "tiếng Đức", + "en": "Anh", + "es": "người Tây Ban Nha", + "fr": "người Pháp", + "hu": "người Hungary", + "it": "người Ý", + "nb_NO": "Norvegian", + "nl": "Hà Lan", + "pt_BR": "Tiếng Bồ Đào Nha (Brazil)", + "sv": "Thụy Điển", + "vi": "tiếng việt" + }, + "login": { + "enter_pass": "Nhập mật khẩu A", + "enter_pass_placeholder": "Mật khẩu A", + "error": "Báo lỗi", + "invalid_pass": "Sai mật khẩu", + "login": "Đăng nhập", + "caps_lock": "Caps Lock đang BẬT" + }, + "navigation": { + "apps": "Ứng dụng", + "back": "Trước", + "dark_mode": "Chế độ nền tối", + "display_sats": "Hiển thị GSATS", + "home": "Trang chủ", + "logout": "Thoát", + "settings": "Hệ thống" + }, + "settings": { + "cancel": "Hủy", + "change": "Thay đổi", + "change_pw_a": "Đổi mật khẩu A", + "confirm": "Xác nhận", + "curr_lang": "Ngôn ngữ hiện tại", + "language": "Ngôn ngữ", + "new_pw": "Mật khẩu mới", + "old_pw": "Mật khẩu cũ", + "pass_a_changed": "Mật khẩu đã thay đổi thành công", + "reboot": "Khởi động lại nguồn", + "shutdown": "Tắt nguồn" + }, + "setup": { + "input_node": { + "err_only_chars": "Tên Node chỉ bao gồm chữ và số.", + "err_max_length": "Tên Node có nhiều nhất 32 ký tự.", + "err_min_length": "Tên Node cần có ít nhất 4 ký tự.", + "err_empty": "Tên Node không thể bỏ trống." + }, + "blockchain_delete": "Xóa chuỗi", + "blockchain_found_long": "Dữ liệu chuỗi khối đã có trên ổ cứng HDD/SSD.", + "blockchain_found_short": "Chuỗi khối đã tìm thấy trên ổ cứng HDD/SSD", + "blockchain_keep": "Giữ chuỗi", + "cancel": "Hủy", + "cancel_setup": "Bạn muốn hủy quy trình cài đặt này", + "continue": "Tiếp", + "convertwarning": "Hiện tại RaspiBlesk chỉ có thể chuyển hóa chuỗi khối và dữ liệu Lightning (vốn + kênh) của bạn. Các dữ liệu của các ứng dụng khác có thể bị xóa trong quy trình lưu chuyển.", + "done_migration_ready": "Ok. Sẵn sàng lưu chuyển dữ liệu qua RaspiBlesk.", + "done_migration_start": "Bắt đầu sao chép", + "done_recover_ready": "Ok. Sẵn sàng hồi phục dữ liệu RaspiBlesk của bạn.", + "done_recover_start": "Bắt đầu phục hồi dữ liệu", + "done_setup_ready": "Ok. Sẵn sàng thiết lập hệ thống RaspiBlesk của bạn.", + "done_setup_start": "Bắt đẩu thiết lập hệ thống", + "done_update_ready": "Ok. Sẵn sàng cập nhật RaspiBlesk của bạn.", + "done_update_start": "Sẵn sàng cập nhật", + "final_do_reboot": "Ok, khởi động lại lần cuối", + "final_info_reboot": "Bây giờ sẽ khởi động lại và cập nhật chuỗi khối.", + "final_migration": "Lưu chuyển dữ liệu hoàn tất.", + "final_recovery": "Phục hồi dữ liệu hoàn tất.", + "final_seedwords": "Viết và lưu giữ chuỗi mật khẩu của bạn tại một nơi bảo mật:", + "final_setup": "Thiết lập hệ thống hoàn tất.", + "final_update": "Cập nhật hoàn tất.", + "lightningoutdated": "Node có phiên bản Lightning mới hơn RaspiBlesk. Vui lòng chờ phiên bản cập nhật mới. Bạn có thể tắt máy và bắt đầu lại với thẻ nhớ SD của node cũ - không có thay đổi.", + "lnd": "LND", + "migrateblitz": "Lưu chuyển dữ liệu qua RaspiBlesk", + "no_and_shutdown": "Không và tắt máy", + "ok": "Đồng ý", + "other_options": "Lựa chọn khác", + "password_a_details": "Sử dụng mật khẩu này để đăng nhập vào RaspiBlesk của bạn.", + "password_a_name": "Mật khẩu A", + "password_a_short": "Thiết lập người dùng Admin mới - Mật khẩu (Mật khẩu A)", + "password_b_details": "Sử dụng mật khẩu này cho các ứng dụng mà bạn có thể cài đặt trên RaspiBlesk của bạn.", + "password_b_name": "Mật khẩu B", + "password_b_short": "Thiết lập ứng dụng mới - Mật khẩu (Mật khẩu B)", + "password_c_details": "Sử dụng mật khẩu này để mở khóa ví Lightning của bạn.", + "password_c_name": "Mật khẩu C", + "password_c_short": "Thiết lập ví Lightning mới - Mật khẩu (Mật khẩu C)", + "password_error_chars": "Mật khẩu chỉ bao gồm chữ và số.", + "password_error_empty": "Mật khẩu không thể bỏ trống.", + "password_error_length": "Mật khẩu cần có ít nhất 8 ký tự.", + "password_error_match": "Mật khẩu không đúng.", + "password_repeat": "Lặp lại", + "pleasewait": "Vui lòng chờ", + "preparingsetup": "chuẩn bị thiết lập hệ thống", + "recoverblitz": "Phục hồi RaspiBlesk của tôi", + "restartinfo": "Vui lòng chờ cho đến khi RaspiBlesk trả lời", + "restarting": "Đang khởi động lại", + "restarts": "Khởi động lại", + "runningsetup": "Đang chạy thiết lập", + "select_lightning": "Chọn cách thực hiện Lightning:", + "setupblitz": "Thiết lập một RaspiBlesk mới", + "setupoptions": "Thiết lập tùy chỉnh", + "setupwait": "Thiết lập sẽ mất một vài phút", + "shuttingdown": "Đang tắt máy", + "start_recovery": "Bạn muốn bắt đầu quy trình phục hồi dữ liệu?", + "start_update": "Bạn muốn bắt đầu quy trình cập nhât và phục hồi dữ liệu?", + "started": "Đã bắt đầu", + "sync_bitcoin_starting": "Bắt đầu cập nhật", + "sync_bitcoin_sync": "Quy trình cập nhật", + "sync_headline": "Cập nhật lần đầu RápiBlitz", + "sync_restartinfo": "(cập nhật sẽ tiếp tục trong lần khởi động tiếp theo)", + "sync_wallet_info": "Vui lòng mở khóa ví Lightning của bạn (Mật khẩu C):", + "sync_wallet_unlock": "Mở khóa ví", + "updateblitz": "Cập nhật RaspiBlesk của tôi", + "yes": "Có", + "yes_and_migrate": "Lưu chuyển dữ liệu qua RaspiBlesk" + }, + "tx": { + "comment": "Góp ý", + "comment_placeholder": "Góp ý tùy chọn", + "confirm_info": "Xác nhận giao dịch sau đây", + "confirmations": "Các xác nhận", + "date": "Ngày", + "description": "Diễn dịch", + "fee": "Phí", + "fee_rate": "Mức phí", + "included_block": "Trong khối", + "mempool": "Xem giao dịch trên mempool", + "sent": "Đã gửi giao dịch!", + "transactions": "Các giao dịch", + "transactions_none": "Chưa có giao dịch, tạo giao dịch đầu tiên của bạn", + "tx_details": "Chi tiết giao dịch", + "txid": "Giao dịch ID", + "unconfirmed": "Chưa xác nhận", + "value": "Giá trị" + }, + "wallet": { + "address": "Địa chỉ", + "amount": "Số lượng", + "balance": "Số dư", + "confirm": "Xác nhận", + "copied": "Đã sao chép!", + "copy_clipboard": "Sao chép tạm thời", + "create_invoice": "Tạo hóa đơn", + "create_invoice_ln": "Tạo một hóa đơn Lightning", + "fund": "Cung cấp vốn cho ví của bạn", + "invoice": "Hóa đơn", + "on_chain": "Trên chuỗi khối", + "receive": "Nhận", + "refresh": "Làm mới địa chỉ", + "scan_qr": "Quét mã QR hoặc sao chép địa chỉ bên dưới để nhận vốn", + "send": "Gửi", + "send_lightning": "Gửi vốn qua Lightning", + "send_onchain": "Gửi vốn trên chuỗi khối", + "unlock": "Mở khóa", + "unlock_subtitle": "Mở khóa ví của bạn", + "unlock_success": "Ví đã được mở khóa", + "unlock_title": "Mở khóa Ví", + "unlocking": "Đang mở khóa", + "wallet_locked": "Ví đã khóa" + } + } +} diff --git a/src/i18n/test_config.ts b/src/i18n/test_config.ts new file mode 100644 index 0000000..22aaac0 --- /dev/null +++ b/src/i18n/test_config.ts @@ -0,0 +1,15 @@ +// this is the i18n config used for testing +import i18n from "i18next"; +import "react-i18next"; +import { initReactI18next } from "react-i18next"; + +i18n.use(initReactI18next).init({ + lng: "en", + fallbackLng: "en", + interpolation: { + escapeValue: false, + }, + resources: { en: { translations: {} } }, +}); + +export default i18n; diff --git a/src/index.css b/src/index.css new file mode 100644 index 0000000..bd15071 --- /dev/null +++ b/src/index.css @@ -0,0 +1,147 @@ +/* + https://stackoverflow.com/questions/47607602/how-to-add-a-tailwind-css-rule-to-css-checker + regarding the linting issues in this file +*/ + +@import "tailwindcss"; +@plugin "./hero.ts"; +@source "../node_modules/@heroui/theme/dist/**/*.{js,ts,jsx,tsx}"; +@custom-variant dark (&:is(.dark *)); + +/* + Metropolis (Chris Simpson, public-domain release) — used by the RaspiBlesk + wordmark SVGs and globally available for typographic accents. Nine weights + (100/200/300/400/500/600/700/800/900) plus matching italics, loaded as + woff via Vite asset URLs so they survive both `npm run dev` and the + production build. `font-display: swap` keeps the layout from blocking on + font fetch on slow LAN. +*/ +@font-face { font-family: 'Metropolis'; font-style: normal; font-weight: 100; font-display: swap; + src: url('./assets/fonts/Metropolis-Thin.woff') format('woff'); } +@font-face { font-family: 'Metropolis'; font-style: italic; font-weight: 100; font-display: swap; + src: url('./assets/fonts/Metropolis-ThinItalic.woff') format('woff'); } +@font-face { font-family: 'Metropolis'; font-style: normal; font-weight: 200; font-display: swap; + src: url('./assets/fonts/Metropolis-ExtraLight.woff') format('woff'); } +@font-face { font-family: 'Metropolis'; font-style: italic; font-weight: 200; font-display: swap; + src: url('./assets/fonts/Metropolis-ExtraLightItalic.woff') format('woff'); } +@font-face { font-family: 'Metropolis'; font-style: normal; font-weight: 300; font-display: swap; + src: url('./assets/fonts/Metropolis-Light.woff') format('woff'); } +@font-face { font-family: 'Metropolis'; font-style: italic; font-weight: 300; font-display: swap; + src: url('./assets/fonts/Metropolis-LightItalic.woff') format('woff'); } +@font-face { font-family: 'Metropolis'; font-style: normal; font-weight: 400; font-display: swap; + src: url('./assets/fonts/Metropolis-Regular.woff') format('woff'); } +@font-face { font-family: 'Metropolis'; font-style: italic; font-weight: 400; font-display: swap; + src: url('./assets/fonts/Metropolis-RegularItalic.woff') format('woff'); } +@font-face { font-family: 'Metropolis'; font-style: normal; font-weight: 500; font-display: swap; + src: url('./assets/fonts/Metropolis-Medium.woff') format('woff'); } +@font-face { font-family: 'Metropolis'; font-style: italic; font-weight: 500; font-display: swap; + src: url('./assets/fonts/Metropolis-MediumItalic.woff') format('woff'); } +@font-face { font-family: 'Metropolis'; font-style: normal; font-weight: 600; font-display: swap; + src: url('./assets/fonts/Metropolis-SemiBold.woff') format('woff'); } +@font-face { font-family: 'Metropolis'; font-style: italic; font-weight: 600; font-display: swap; + src: url('./assets/fonts/Metropolis-SemiBoldItalic.woff') format('woff'); } +@font-face { font-family: 'Metropolis'; font-style: normal; font-weight: 700; font-display: swap; + src: url('./assets/fonts/Metropolis-Bold.woff') format('woff'); } +@font-face { font-family: 'Metropolis'; font-style: italic; font-weight: 700; font-display: swap; + src: url('./assets/fonts/Metropolis-BoldItalic.woff') format('woff'); } +@font-face { font-family: 'Metropolis'; font-style: normal; font-weight: 800; font-display: swap; + src: url('./assets/fonts/Metropolis-ExtraBold.woff') format('woff'); } +@font-face { font-family: 'Metropolis'; font-style: italic; font-weight: 800; font-display: swap; + src: url('./assets/fonts/Metropolis-ExtraBoldItalic.woff') format('woff'); } +@font-face { font-family: 'Metropolis'; font-style: normal; font-weight: 900; font-display: swap; + src: url('./assets/fonts/Metropolis-Black.woff') format('woff'); } +@font-face { font-family: 'Metropolis'; font-style: italic; font-weight: 900; font-display: swap; + src: url('./assets/fonts/Metropolis-BlackItalic.woff') format('woff'); } + +@theme { + --animate-fade-in: fadeIn 0.5s ease-in-out; + + --color-tertiary: #253553; + + @keyframes fadeIn { + 0% { + opacity: 0; + transform: translateY(10px); + } + 100% { + opacity: 1; + transform: translateY(0); + } + } +} + +/* + The default border color has changed to `currentcolor` in Tailwind CSS v4, + so we've added these compatibility styles to make sure everything still + looks the same as it did with Tailwind CSS v3. + + If we ever want to remove these styles, we need to add an explicit border + color utility to any element that depends on these defaults. +*/ +@layer base { + *, + ::after, + ::before, + ::backdrop, + ::file-selector-button { + border-color: var(--color-gray-200, currentcolor); + } +} + +.scrollbar-stable { + scrollbar-gutter: stable; +} + +/** + * Custom Tailwind class CSS + **/ + +.label-underline { + @apply my-2 block text-left text-sm font-bold text-white; +} + +.input-underline { + @apply mt-0 block w-full border-0 border-b-2 border-gray-200 bg-transparent px-0.5 text-white outline-hidden focus:border-violet-500 focus:ring-0; +} + +.input-error { + @apply mt-0 block w-full border-0 border-b-2 border-red-500 bg-transparent px-0.5 text-white outline-hidden focus:border-red-500 focus:ring-0; +} + +.bd-card { + @apply flex h-full flex-col justify-center rounded-md bg-gray-800 px-6 py-4 text-white shadow-xl transition-colors; +} + +.bd-button { + @apply rounded-sm bg-violet-600 text-white shadow-xl hover:bg-violet-500 disabled:bg-gray-500; +} + +.bd-button-red { + @apply rounded-sm bg-red-500 text-white shadow-xl hover:bg-red-400 disabled:bg-gray-500; +} + +.switch-button { + @apply m-2 rounded-lg bg-gray-500 px-3 py-1 text-white shadow-md hover:bg-violet-500 hover:text-white disabled:cursor-default disabled:bg-violet-600 disabled:text-white; +} + +.page-container { + @apply mb-16 mt-16 h-full w-full overflow-y-auto transition-colors lg:mb-0 lg:w-full lg:pl-72; +} + +/** + * Remove up/down arrows from number intput + **/ + +input[type="number"] { + -moz-appearance: textfield; +} + +input::-webkit-outer-spin-button, +input::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; +} + +.remove-radio > span { + visibility: hidden; +} diff --git a/src/index.tsx b/src/index.tsx new file mode 100644 index 0000000..a348e1f --- /dev/null +++ b/src/index.tsx @@ -0,0 +1,44 @@ +import App from "./App"; +import AppContextProvider from "./context/app-context"; +import SSEContextProvider from "./context/sse-context"; +import "./i18n/config"; +import "./index.css"; +import { HeroUIProvider } from "@heroui/react"; +import ErrorBoundary from "@/ErrorBoundary"; +import "i18next"; +import { StrictMode } from "react"; +import { createRoot } from "react-dom/client"; +import { HashRouter } from "react-router"; +import { ToastContainer } from "react-toastify"; +import "react-tooltip/dist/react-tooltip.css"; + +declare module "i18next" { + interface CustomTypeOptions { + returnNull: false; + } +} + +// see https://vitejs.dev/guide/build#load-error-handling +window.addEventListener("vite:preloadError", (_event) => { + window.location.reload(); +}); + +const container = document.getElementById("root") as HTMLElement; +const root = createRoot(container); +root.render( + + + + + + + {/* For persistent toasts over all pages */} + + + + + + + + , +); diff --git a/src/layouts/BottomNav.tsx b/src/layouts/BottomNav.tsx new file mode 100644 index 0000000..11c305d --- /dev/null +++ b/src/layouts/BottomNav.tsx @@ -0,0 +1,38 @@ +import { + Cog6ToothIcon, + HomeIcon, + Squares2X2Icon, +} from "@heroicons/react/24/outline"; +import type { FC } from "react"; +import { useTranslation } from "react-i18next"; +import { NavLink } from "react-router"; + +const navLinkClasses = "text-white opacity-80"; +const navLinkActiveClasses = "text-violet-400 opacity-100"; +const createClassName = ({ isActive }: { isActive: boolean }) => + `${navLinkClasses} ${isActive ? navLinkActiveClasses : ""}`; +const navIconClasses = "w-8 h-8 mx-auto"; +const navLabelClasses = "text-center mx-1"; + +const BottomNav: FC = () => { + const { t } = useTranslation(); + + return ( +
+ createClassName(props)}> + + {t("navigation.home")} + + createClassName(props)}> + + {t("navigation.apps")} + + createClassName(props)}> + + {t("navigation.settings")} + +
+ ); +}; + +export default BottomNav; diff --git a/src/layouts/Header.tsx b/src/layouts/Header.tsx new file mode 100644 index 0000000..a51fcca --- /dev/null +++ b/src/layouts/Header.tsx @@ -0,0 +1,93 @@ +import { + ArrowsRightLeftIcon, + ArrowRightStartOnRectangleIcon, + Bars3Icon, + BookOpenIcon, +} from "@heroicons/react/24/outline"; +import { + Dropdown, + DropdownItem, + DropdownMenu, + DropdownTrigger, +} from "@heroui/react"; +import { type Key, useContext } from "react"; +import { useTranslation } from "react-i18next"; +import { NavLink } from "react-router"; +import RaspiBlesk_Logo_Icon from "@/assets/RaspiBlesk_Logo_Icon.svg?react"; +import RaspiBlesk_Logo_Main_Negative from "@/assets/RaspiBlesk_Logo_Main_Negative.svg?react"; +import { AppContext, Unit } from "@/context/app-context"; +import { SSEContext } from "@/context/sse-context"; + +export default function Header() { + const { t } = useTranslation(); + const { systemInfo } = useContext(SSEContext); + const { unit, logout, toggleUnit } = useContext(AppContext); + + const unitActive = unit === Unit.GSAT; + + const handleDropDownAction = (key: Key) => { + if (key === "logout") { + logout(); + } + + if (key === "toggle_sats") { + toggleUnit(); + } + }; + + return ( +
+ + + + + +
{systemInfo.alias}
+ +
+ + + + + + handleDropDownAction(key)} + > + + } + > + {unitActive + ? t("navigation.display_btc") + : t("navigation.display_sats")} + + + } + > + {t("navigation.documentation")} + + + + } + > + {t("navigation.logout")} + + + +
+
+ ); +} diff --git a/src/layouts/Layout.tsx b/src/layouts/Layout.tsx new file mode 100644 index 0000000..4adcd11 --- /dev/null +++ b/src/layouts/Layout.tsx @@ -0,0 +1,20 @@ +import type { FC, PropsWithChildren } from "react"; +import useSSE from "@/hooks/use-sse"; +import BottomNav from "./BottomNav"; +import Header from "./Header"; +import SideDrawer from "./SideDrawer"; + +const Layout: FC = ({ children }) => { + // use SSE for all components after login + useSSE(); + return ( + <> +
+ + {children} + + + ); +}; + +export default Layout; diff --git a/src/layouts/LoadingScreen.tsx b/src/layouts/LoadingScreen.tsx new file mode 100644 index 0000000..7d8fac8 --- /dev/null +++ b/src/layouts/LoadingScreen.tsx @@ -0,0 +1,12 @@ +import { Spinner } from "@heroui/react"; +import RaspiBlesk_Logo_Main_Negative from "@/assets/RaspiBlesk_Logo_Main_Negative.svg?react"; + +// Loading Screen for the initial loading of the app +export default function LoadingScreen() { + return ( +
+ + +
+ ); +} diff --git a/src/layouts/ModalBackground.tsx b/src/layouts/ModalBackground.tsx new file mode 100644 index 0000000..692ec7e --- /dev/null +++ b/src/layouts/ModalBackground.tsx @@ -0,0 +1,9 @@ +import type { FC, PropsWithChildren } from "react"; + +const ModalBackground: FC = ({ children }) => ( +
+ {children} +
+); + +export default ModalBackground; diff --git a/src/layouts/ModalDialog.tsx b/src/layouts/ModalDialog.tsx new file mode 100644 index 0000000..74731a3 --- /dev/null +++ b/src/layouts/ModalDialog.tsx @@ -0,0 +1,66 @@ +import { XMarkIcon } from "@heroicons/react/24/outline"; +import { type FC, type PropsWithChildren, useCallback, useEffect } from "react"; +import ModalBackground from "./ModalBackground"; + +export const disableScroll = { + on: () => document.body.classList.add("overflow-y-hidden"), + off: () => document.body.classList.remove("overflow-y-hidden"), +}; + +type Props = { + closeable?: boolean; + close: () => void; +}; + +const ModalDialog: FC> = ({ + closeable = true, + close, + children, +}) => { + const closeModal = useCallback(() => { + close(); + disableScroll.off(); + }, [close]); + + // close Modal on Esc + const closeOnEsc = useCallback( + (event: KeyboardEvent) => { + if (closeable && event.key === "Escape") { + closeModal(); + } + }, + [closeModal, closeable], + ); + + useEffect(() => { + disableScroll.on(); + window.addEventListener("keydown", closeOnEsc); + return () => { + window.removeEventListener("keydown", closeOnEsc); + disableScroll.off(); + }; + }, [closeOnEsc]); + + return ( + +
+
+ +
+
+ {children} +
+
+
+ ); +}; + +export default ModalDialog; diff --git a/src/layouts/PageLoadingScreen.tsx b/src/layouts/PageLoadingScreen.tsx new file mode 100644 index 0000000..e495734 --- /dev/null +++ b/src/layouts/PageLoadingScreen.tsx @@ -0,0 +1,15 @@ +import { Spinner } from "@heroui/react"; +import type { FC } from "react"; + +// Loading Screen where sidebar is visible and usable +const PageLoadingScreen: FC = () => { + return ( +
+
+ +
+
+ ); +}; + +export default PageLoadingScreen; diff --git a/src/layouts/SetupContainer.tsx b/src/layouts/SetupContainer.tsx new file mode 100644 index 0000000..4efc2c5 --- /dev/null +++ b/src/layouts/SetupContainer.tsx @@ -0,0 +1,45 @@ +import { BookOpenIcon } from "@heroicons/react/24/outline"; +import type { PropsWithChildren } from "react"; +import { useTranslation } from "react-i18next"; +import { Button } from "@/components/Button"; +import I18nSelect from "@/components/I18nDropdown"; +import Stepper from "@/pages/Setup/Stepper"; + +type Props = { + currentStep: number | null; +}; + +export default function SetupContainer({ + currentStep, + children, +}: PropsWithChildren) { + const { t } = useTranslation(); + + return ( +
+
+ + +
+ + {currentStep !== null && ( +
+ +
+ )} + +
{children}
+
+ ); +} diff --git a/src/layouts/SideDrawer.tsx b/src/layouts/SideDrawer.tsx new file mode 100644 index 0000000..e80b595 --- /dev/null +++ b/src/layouts/SideDrawer.tsx @@ -0,0 +1,82 @@ +import { + ArrowRightStartOnRectangleIcon, + BookOpenIcon, + Cog6ToothIcon, + HomeIcon, + Squares2X2Icon, +} from "@heroicons/react/24/outline"; +import type { FC } from "react"; +import { useContext } from "react"; +import { useTranslation } from "react-i18next"; +import { NavLink } from "react-router"; +import AppStatusItem from "@/components/AppStatusItem"; +import { AppContext } from "@/context/app-context"; +import { SSEContext } from "@/context/sse-context"; + +const navLinkClasses = + "flex md:flex-col lg:flex-row items-center justify-center py-4 w-full text-white opacity-80 hover:text-violet-400"; +const navLinkActiveClasses = "text-violet-400 opacity-100"; +const createClassName = ({ isActive }: { isActive: boolean }) => + `${navLinkClasses} ${isActive ? navLinkActiveClasses : ""}`; +const navIconClasses = "inline w-10 h-10"; + +export const SideDrawer: FC = () => { + const { logout } = useContext(AppContext); + const { appStatus } = useContext(SSEContext); + const { t } = useTranslation(); + + return ( + + ); +}; + +export default SideDrawer; diff --git a/src/layouts/SkeletonLoadingScreen.tsx b/src/layouts/SkeletonLoadingScreen.tsx new file mode 100644 index 0000000..28a5aed --- /dev/null +++ b/src/layouts/SkeletonLoadingScreen.tsx @@ -0,0 +1,14 @@ +import { Spinner } from "@heroui/react"; + +// Loading Screen when sidebar is visible but not usable +export default function SkeletonLoadingScreen() { + return ( + <> +
+
+ +
+ +
+ + + + + + + + ); +}; + +export default SendOnChain; diff --git a/src/pages/Home/SwitchTxType.tsx b/src/pages/Home/SwitchTxType.tsx new file mode 100644 index 0000000..bfb91f4 --- /dev/null +++ b/src/pages/Home/SwitchTxType.tsx @@ -0,0 +1,53 @@ +import { BoltIcon, LinkIcon } from "@heroicons/react/24/outline"; +import type { FC } from "react"; +import { useTranslation } from "react-i18next"; + +export enum TxType { + ONCHAIN = 0, + LIGHTNING = 1, +} + +export type Props = { + disabled?: boolean; + invoiceType: TxType; + onTxTypeChange: (txtype: TxType) => void; +}; + +const SwitchTxType: FC = ({ invoiceType, onTxTypeChange, disabled }) => { + const { t } = useTranslation(); + + const setTxTypeHandler = (txType: TxType) => { + if (disabled) { + return; + } + onTxTypeChange(txType); + }; + + return ( +
+ + + +
+ ); +}; + +export default SwitchTxType; diff --git a/src/pages/Home/TransactionCard/CategoryIcon.tsx b/src/pages/Home/TransactionCard/CategoryIcon.tsx new file mode 100644 index 0000000..2b4a3ea --- /dev/null +++ b/src/pages/Home/TransactionCard/CategoryIcon.tsx @@ -0,0 +1,101 @@ +import { + Confirmations0Icon, + Confirmations1Icon, + Confirmations2Icon, + Confirmations3Icon, + Confirmations4Icon, + Confirmations5Icon, + Confirmations6Icon, +} from "@bitcoin-design/bitcoin-icons-react/filled"; +import { + BoltIcon, + ClockIcon, + EllipsisHorizontalIcon, + LinkIcon, +} from "@heroicons/react/24/outline"; +import type { FC } from "react"; +import type { + TransactionCategory, + TransactionStatus, + TransactionType, +} from "@/models/transaction.model"; + +export type Props = { + category: TransactionCategory; + type: TransactionType; + status: TransactionStatus; + confirmations?: number; +}; + +const CategoryIcon: FC = ({ category, type, status, confirmations }) => { + const sendingTx = type === "send"; + const color = sendingTx ? "text-white bg-red-500" : "text-white bg-green-500"; + + if (category === "ln") { + switch (status) { + case "in_flight": + return ( + + ); + case "failed": + return ( + + ); + case "succeeded": + return ; + } + } + + switch (confirmations) { + case 0: + return ( + + ); + case 1: + return ( + + ); + case 2: + return ( + + ); + case 3: + return ( + + ); + case 4: + return ( + + ); + case 5: + return ( + + ); + case 6: + return ( + + ); + default: + return ( + + ); + } +}; + +export default CategoryIcon; diff --git a/src/pages/Home/TransactionCard/TransactionCard.tsx b/src/pages/Home/TransactionCard/TransactionCard.tsx new file mode 100644 index 0000000..caefb59 --- /dev/null +++ b/src/pages/Home/TransactionCard/TransactionCard.tsx @@ -0,0 +1,174 @@ +import { + ArrowDownIcon, + InformationCircleIcon, + LockClosedIcon, +} from "@heroicons/react/24/outline"; +import { Button, Listbox, ListboxItem, Spinner } from "@heroui/react"; +import { type FC, useContext, useState } from "react"; +import { useTranslation } from "react-i18next"; +import { Alert } from "@/components/Alert"; +import { AppContext } from "@/context/app-context"; +import type { Implementation } from "@/models/ln-info"; +import type { Transaction } from "@/models/transaction.model"; +import CategoryIcon from "./CategoryIcon"; +import { formatTransaction } from "./transactionUtils"; + +export type Props = { + transactions: Transaction[]; + showDetails: (index: number) => void; + isLoading: boolean; + error: string; + implementation: Implementation; +}; + +const MAX_ITEMS = 6; + +const TransactionCard: FC = ({ + transactions, + isLoading, + showDetails, + error, + implementation, +}) => { + const { t } = useTranslation(); + const { walletLocked, unit } = useContext(AppContext); + const [page, setPage] = useState(0); + + if (walletLocked) { + return ( +
+
+
+ + {t("wallet.wallet_locked")} +
+
+
+ ); + } + + const pageForwardHandler = () => { + setPage((p) => p + 1); + }; + + const pageBackwardHandler = () => { + setPage((p) => p - 1); + }; + + let currentPageTxs = transactions; + + if (transactions.length > MAX_ITEMS) { + currentPageTxs = transactions.slice( + page * MAX_ITEMS, + page * MAX_ITEMS + MAX_ITEMS, + ); + } + + return ( +
+
+

{t("tx.transactions")}

+ + {isLoading && } + + {error && {error}} + + {/* TODO: Remove after https://github.com/fusion44/blitz_api/issues/87 is resolved & Version 1.10.0 of RaspiBlesk is out */} + {implementation?.includes("CLN") && ( + {t("home.onchain_cln_no_support")} + )} + + {!error && transactions.length === 0 && ( +
+ +   + {t("tx.transactions_none")} +
+ )} + + {transactions.length > 0 && ( + { + const tx = currentPageTxs.find((t) => t.id === String(key)); + if (tx) showDetails(tx.index); + }} + classNames={{ + base: "pt-4 p-0", + list: "gap-2", + }} + itemClasses={{ + base: "rounded-lg bg-default-100/50 data-[hover=true]:bg-default-200/50 p-4 cursor-pointer transition-background", + }} + > + {currentPageTxs.map((transaction: Transaction) => { + const formatted = formatTransaction(transaction, unit); + return ( + +
+ {/* Row 1: Icon + Amount + Date */} +
+
+ + + {formatted.sign} + {formatted.formattedAmount} {unit} + +
+ +
+ + {/* Row 2: Comment */} + + {formatted.comment ?? t("tx.default_comment")} + +
+
+ ); + })} +
+ )} + + {transactions.length > 0 && ( +
+ + + +
+ )} +
+
+ ); +}; + +export default TransactionCard; diff --git a/src/pages/Home/TransactionCard/TransactionDetailModal/ConfirmationsRing.tsx b/src/pages/Home/TransactionCard/TransactionDetailModal/ConfirmationsRing.tsx new file mode 100644 index 0000000..7f37cf8 --- /dev/null +++ b/src/pages/Home/TransactionCard/TransactionDetailModal/ConfirmationsRing.tsx @@ -0,0 +1,61 @@ +import { CircularProgress } from "@heroui/react"; +import type { FC } from "react"; +import { useTranslation } from "react-i18next"; + +interface Props { + confirmations: number | null; + required?: number; +} + +/** + * Displays confirmation status as a circular progress indicator. + */ +export const ConfirmationsRing: FC = ({ + confirmations = 0, + required = 6, +}) => { + const { t } = useTranslation(); + const conf = confirmations || 0; + const isFullyConfirmed = conf >= required; + const showLabel = conf === 0; + const progressValue = Math.min((conf / required) * 100, 100); + + return ( +
+ + {t("tx.unconfirmed")} + + ) : isFullyConfirmed ? ( + + {conf} + + ) : ( +
+ + {conf} + + / {required} +
+ ) + } + showValueLabel={true} + /> +
+ {t("tx.confirmations")} +
+
+ ); +}; + +export default ConfirmationsRing; diff --git a/src/pages/Home/TransactionCard/TransactionDetailModal/KeyValueCard.tsx b/src/pages/Home/TransactionCard/TransactionDetailModal/KeyValueCard.tsx new file mode 100644 index 0000000..d4e709a --- /dev/null +++ b/src/pages/Home/TransactionCard/TransactionDetailModal/KeyValueCard.tsx @@ -0,0 +1,23 @@ +import type { FC } from "react"; + +interface Props { + name: string; + value: string; +} + +const KeyValueCard: FC = ({ name, value }) => { + return ( +
+
+
+
{name}
+
+
+

{value}

+
+
+
+ ); +}; + +export default KeyValueCard; diff --git a/src/pages/Home/TransactionCard/TransactionDetailModal/KeyValueDisplay.tsx b/src/pages/Home/TransactionCard/TransactionDetailModal/KeyValueDisplay.tsx new file mode 100644 index 0000000..f58ccfc --- /dev/null +++ b/src/pages/Home/TransactionCard/TransactionDetailModal/KeyValueDisplay.tsx @@ -0,0 +1,20 @@ +import type { FC } from "react"; + +export type Props = { + name: string; + value: string; +}; + +/** + * Used for the display of Transaction Details + */ +const KeyValueDisplay: FC = ({ name, value }) => { + return ( +
+
{name}
+

{value}

+
+ ); +}; + +export default KeyValueDisplay; diff --git a/src/pages/Home/TransactionCard/TransactionDetailModal/MempoolBadge.tsx b/src/pages/Home/TransactionCard/TransactionDetailModal/MempoolBadge.tsx new file mode 100644 index 0000000..b7946d8 --- /dev/null +++ b/src/pages/Home/TransactionCard/TransactionDetailModal/MempoolBadge.tsx @@ -0,0 +1,33 @@ +import { ArrowTopRightOnSquareIcon } from "@heroicons/react/24/outline"; +import { Link } from "@heroui/react"; +import type { FC } from "react"; +import { useTranslation } from "react-i18next"; +import { Button } from "@/components/Button"; + +interface Props { + txId: string; +} + +/** + * Mempool badge component for on-chain transactions. + * TODO: add option to define your own instance for the link in settings and use that + */ +const MempoolBadge: FC = ({ txId }) => { + const { t } = useTranslation(); + const mempoolUrl = `https://mempool.space/tx/${txId}`; + + return ( + + ); +}; + +export default MempoolBadge; diff --git a/src/pages/Home/TransactionCard/TransactionDetailModal/TransactionDetailModal.tsx b/src/pages/Home/TransactionCard/TransactionDetailModal/TransactionDetailModal.tsx new file mode 100644 index 0000000..1cc8304 --- /dev/null +++ b/src/pages/Home/TransactionCard/TransactionDetailModal/TransactionDetailModal.tsx @@ -0,0 +1,35 @@ +import type { FC } from "react"; +import { useTranslation } from "react-i18next"; +import { + ConfirmModal, + type Props as ConfirmModalProps, +} from "@/components/ConfirmModal"; +import type { Transaction } from "@/models/transaction.model"; +import TransactionDetails from "./TransactionDetails"; + +interface Props extends Pick { + transaction: Transaction; +} + +export const TransactionDetailModal: FC = ({ + transaction, + disclosure, +}) => { + const { t } = useTranslation(); + + // prevent error when closing via 'Esc' key + if (!transaction) { + return null; + } + + return ( + + {t("tx.tx_details")} + + + + + ); +}; + +export default TransactionDetailModal; diff --git a/src/pages/Home/TransactionCard/TransactionDetailModal/TransactionDetails.tsx b/src/pages/Home/TransactionCard/TransactionDetailModal/TransactionDetails.tsx new file mode 100644 index 0000000..aba5255 --- /dev/null +++ b/src/pages/Home/TransactionCard/TransactionDetailModal/TransactionDetails.tsx @@ -0,0 +1,140 @@ +import { BoltIcon, LinkIcon } from "@heroicons/react/24/outline"; +import { type FC, useContext } from "react"; +import { useTranslation } from "react-i18next"; +import { AppContext, Unit } from "@/context/app-context"; +import type { Transaction } from "@/models/transaction.model"; +import { + convertMSatToGlc, + convertMSatToGsat, + convertGsatToGlc, + convertToString, +} from "@/utils/format"; +import ConfirmationsRing from "./ConfirmationsRing"; +import KeyValueCard from "./KeyValueCard"; +import MempoolBadge from "./MempoolBadge"; +import TransactionId from "./TransactionId"; + +export type Props = { + details: Transaction; +}; + +export const TransactionDetails: FC = ({ details }) => { + const { unit } = useContext(AppContext); + const { t } = useTranslation(); + + const date = new Date(details.time_stamp * 1000).toLocaleString(); // epoch time => multiply by 1000 + const isOnchain = details.category === "onchain"; + const isIncoming = details.type === "receive"; + + // Format amount based on category and unit (use absolute value, direction shown by color/icon) + const absAmount = Math.abs(details.amount); + const amount = isOnchain + ? unit === Unit.GLC + ? convertToString(unit, convertGsatToGlc(absAmount)) + : convertToString(unit, absAmount) + : unit === Unit.GLC + ? convertToString(unit, convertMSatToGlc(absAmount)) + : convertToString(unit, convertMSatToGsat(absAmount)); + + const feeValue = isOnchain + ? `${ + unit === Unit.GLC + ? convertToString(unit, convertGsatToGlc(details.total_fees)) + : convertToString(unit, details.total_fees) + } ${unit}` + : `${details.total_fees} mSat`; + + // Determine amount color based on transaction direction + const amountColor = isIncoming ? "text-green-400" : "text-red-400"; + + return ( +
+ {/* Top bar */} +
+ {/* Transaction Type Indicator */} +
+ {isOnchain ? ( +
+ + {t("wallet.on_chain")} +
+ ) : ( +
+ + {t("home.lightning")} +
+ )} +
+ + {/* Mempool Badge - Only for on-chain transactions */} + {isOnchain && ( +
+ +
+ )} +
+ + {/* Transaction ID Section */} + + + {/* Status Section */} +
+

+ {t("tx.tx_details")} +

+ + {isOnchain && ( +
+ +
+ )} + + {isOnchain && details.block_height && ( + + )} + + {!isOnchain && ( + + )} +
+ + {/* Details Section */} +
+

+ {t("tx.details")} +

+ + + +
+
+
+
+ {isOnchain ? t("wallet.amount") : t("tx.value")} +
+
+
+

+ {isIncoming ? "+" : "-"} + {amount} {unit} +

+
+
+
+ + {details.total_fees !== null && ( + + )} + + {details.comment && ( + + )} +
+
+ ); +}; + +export default TransactionDetails; diff --git a/src/pages/Home/TransactionCard/TransactionDetailModal/TransactionId.tsx b/src/pages/Home/TransactionCard/TransactionDetailModal/TransactionId.tsx new file mode 100644 index 0000000..d2f82da --- /dev/null +++ b/src/pages/Home/TransactionCard/TransactionDetailModal/TransactionId.tsx @@ -0,0 +1,82 @@ +import { + CheckIcon, + ClipboardDocumentCheckIcon, +} from "@heroicons/react/24/outline"; +import { Tooltip } from "@heroui/react"; +import { type FC, useEffect, useState } from "react"; +import { useTranslation } from "react-i18next"; +import useClipboard from "@/hooks/use-clipboard"; + +interface Props { + id: string; + maxDisplay?: number; +} + +/** + * Transaction ID display component with toggle and copy functionality. + * Click to toggle between truncated and full view. + */ +const TransactionId: FC = ({ id, maxDisplay = 8 }) => { + const { t } = useTranslation(); + const [copyId, isCopied] = useClipboard(id); + const [showCheck, setShowCheck] = useState(false); + const [expanded, setExpanded] = useState(false); + + useEffect(() => { + if (isCopied) { + setShowCheck(true); + const timer = setTimeout(() => { + setShowCheck(false); + }, 2000); + return () => clearTimeout(timer); + } + }, [isCopied]); + + const truncatedId = + id.length > maxDisplay * 2 + ? `${id.slice(0, maxDisplay)}...${id.slice(-maxDisplay)}` + : id; + + const displayId = expanded ? id : truncatedId; + + return ( +
+
+
{t("tx.txid")}
+ + + +
+ +
+ ); +}; + +export default TransactionId; diff --git a/src/pages/Home/TransactionCard/transactionUtils.ts b/src/pages/Home/TransactionCard/transactionUtils.ts new file mode 100644 index 0000000..91b346a --- /dev/null +++ b/src/pages/Home/TransactionCard/transactionUtils.ts @@ -0,0 +1,56 @@ +import { Unit } from "@/context/app-context"; +import type { Transaction } from "@/models/transaction.model"; +import { + convertMSatToGlc, + convertMSatToGsat, + convertGsatToGlc, + convertToString, +} from "@/utils/format"; + +export type FormattedTransaction = { + formattedAmount: string; + formattedDate: string; + isoString: string; + color: string; + sign: string; + comment: string | null; +}; + +export function formatTransaction( + transaction: Transaction, + unit: Unit, +): FormattedTransaction { + const { amount, category, time_stamp, type, comment } = transaction; + + const sendingTx = type === "send"; + const sign = sendingTx ? "" : "+"; + + let formattedAmount: string; + + if (category === "onchain") { + formattedAmount = + unit === Unit.GLC + ? convertToString(unit, convertGsatToGlc(amount)) + : convertToString(unit, amount); + } else { + formattedAmount = + unit === Unit.GLC + ? convertToString(unit, convertMSatToGlc(amount)) + : convertToString(unit, convertMSatToGsat(amount)); + } + + const date = new Date(time_stamp * 1000); + const formattedDate = date.toLocaleString(); + const isoString = date.toISOString(); + + const color = sendingTx ? "text-red-400" : "text-green-400"; + + return { + formattedAmount, + formattedDate, + isoString, + color, + sign, + comment: comment || null, + }; +} diff --git a/src/pages/Home/UnlockModal.tsx b/src/pages/Home/UnlockModal.tsx new file mode 100644 index 0000000..809615c --- /dev/null +++ b/src/pages/Home/UnlockModal.tsx @@ -0,0 +1,107 @@ +import { Input } from "@heroui/react"; +import { useContext, useState } from "react"; +import type { SubmitHandler } from "react-hook-form"; +import { useForm } from "react-hook-form"; +import { useTranslation } from "react-i18next"; +import { toast } from "react-toastify"; +import { Alert } from "@/components/Alert"; +import { Button } from "@/components/Button"; +import CapsLockWarning from "@/components/CapsLockWarning"; +import { + ConfirmModal, + type Props as ConfirmModalProps, +} from "@/components/ConfirmModal"; +import { AppContext } from "@/context/app-context"; +import useCapsLock from "@/hooks/use-caps-lock"; +import { instance } from "@/utils/interceptor"; + +interface IFormInputs { + passwordInput: string; +} + +export default function UnlockModal({ + disclosure, +}: Pick) { + const { t } = useTranslation(); + const { setWalletLocked } = useContext(AppContext); + const [isLoading, setIsLoading] = useState(false); + const [isServerError, setIsServerError] = useState(false); + const { isCapsLockEnabled, keyHandlers } = useCapsLock(); + + const { + register, + handleSubmit, + formState: { errors, isValid }, + } = useForm({ mode: "onChange" }); + + const unlockHandler: SubmitHandler = (data: { + passwordInput: string; + }) => { + setIsLoading(true); + setIsServerError(false); + instance + .post("/lightning/unlock-wallet", { password: data.passwordInput }) + .then((res) => { + if (res.data) { + setWalletLocked(false); + toast.success(t("wallet.unlock_success"), { theme: "dark" }); + disclosure.onClose(); + } + }) + .catch((_) => { + setIsLoading(false); + setIsServerError(true); + }); + }; + + return ( + +
+ +

{t("wallet.unlock_subtitle")}

+ + {isCapsLockEnabled && } + +
+ +
+ + {isServerError && ( + {t("login.invalid_pass")} + )} +
+ + + + +
+
+ ); +} diff --git a/src/pages/Home/WalletCard.tsx b/src/pages/Home/WalletCard.tsx new file mode 100644 index 0000000..e35b88b --- /dev/null +++ b/src/pages/Home/WalletCard.tsx @@ -0,0 +1,169 @@ +import { + LightningIcon, + ShareIcon, +} from "@bitcoin-design/bitcoin-icons-react/filled"; +import { + ArrowDownTrayIcon, + BoltIcon, + CircleStackIcon, + LinkIcon, + ListBulletIcon, +} from "@heroicons/react/24/outline"; +import { type FC, useContext } from "react"; +import { useTranslation } from "react-i18next"; +import { Button } from "@/components/Button"; +import { Headline } from "@/components/Headline"; +import { AppContext, Unit } from "@/context/app-context"; +import { SSEContext } from "@/context/sse-context"; +import { + convertMSatToGlc, + convertGsatToGlc, + convertToString, +} from "@/utils/format"; + +type Props = { + onReceive: () => void; + onSend: () => void; + onOpenChannel: () => void; + onCloseChannel: () => void; +}; + +export const WalletCard: FC = ({ + onReceive, + onSend, + onOpenChannel, + onCloseChannel, +}) => { + const { t } = useTranslation(); + const { unit } = useContext(AppContext); + const { balance } = useContext(SSEContext); + + const { + onchain_total_balance: onchainBalance, + onchain_unconfirmed_balance: onChainUnconfirmed, + channel_local_balance: lnBalance, + } = balance; + + let convertedOnchainBalance = null; + let convertedOnchainBalanceUnconfirmed = null; + let convertedLnBalance = null; + let totalBalance = null; + let unconfirmedSign = ""; + + if (onchainBalance !== null && lnBalance !== null) { + convertedOnchainBalance = + unit === Unit.GLC ? convertGsatToGlc(onchainBalance) : onchainBalance; + + if (onChainUnconfirmed) { + convertedOnchainBalanceUnconfirmed = + unit === Unit.GLC + ? convertGsatToGlc(onChainUnconfirmed) + : onChainUnconfirmed; + unconfirmedSign = onChainUnconfirmed > 0 ? "+" : ""; + } + + if (lnBalance !== null) { + convertedLnBalance = + unit === Unit.GLC ? convertMSatToGlc(lnBalance) : lnBalance / 1000; + } + + if (convertedOnchainBalance !== null && convertedLnBalance !== null) { + totalBalance = + unit === Unit.GLC + ? +(convertedOnchainBalance + convertedLnBalance).toFixed(8) + : convertedOnchainBalance + convertedLnBalance; + } + } + + return ( +
+
+
+
+
+ + {t("wallet.balance")} + +

+ {convertToString(unit, totalBalance)} {unit} +

+
+
+ + + + {t("wallet.on_chain")} + + +

+ + {convertToString(unit, convertedOnchainBalance)} {unit} +   + + + {onChainUnconfirmed !== 0 && + `(${unconfirmedSign}${convertToString( + unit, + convertedOnchainBalanceUnconfirmed, + )})`} + +

+
+
+ + + + {t("home.lightning")} + + +

+ {convertToString(unit, convertedLnBalance)} {unit} +

+
+ +
+
+
+ + + + +
+
+
+ ); +}; + +export default WalletCard; diff --git a/src/pages/Home/index.tsx b/src/pages/Home/index.tsx new file mode 100644 index 0000000..083428e --- /dev/null +++ b/src/pages/Home/index.tsx @@ -0,0 +1,268 @@ +import { HttpStatusCode } from "axios"; +import { type FC, useCallback, useContext, useEffect, useState } from "react"; +import { useTranslation } from "react-i18next"; +import { toast } from "react-toastify"; +import { AppContext } from "@/context/app-context"; +import { SSEContext } from "@/context/sse-context"; +import { useInterval } from "@/hooks/use-interval"; +import { useModalManager } from "@/hooks/use-modalmanager"; +import PageLoadingScreen from "@/layouts/PageLoadingScreen"; +import type { Transaction } from "@/models/transaction.model"; +import { enableGutter } from "@/utils"; +import { checkError } from "@/utils/checkError"; +import { instance } from "@/utils/interceptor"; +import GlcoinCard from "./GlcoinCard"; +import ConnectionCard from "./ConnectionCard"; +import HardwareCard from "./HardwareCard"; +import LightningCard from "./LightningCard"; +import ListChannelModal from "./ListChannelModal/ListChannelModal"; +import OpenChannelModal from "./OpenChannelModal"; +import ReceiveModal from "./ReceiveModal/ReceiveModal"; +import SendModal from "./SendModal/SendModal"; +import TransactionCard from "./TransactionCard/TransactionCard"; +import TransactionDetailModal from "./TransactionCard/TransactionDetailModal/TransactionDetailModal"; +import UnlockModal from "./UnlockModal"; +import WalletCard from "./WalletCard"; + +const startupToastId = "startup-toast"; + +const Home: FC = () => { + const { activeModal, disclosure, openModal, closeModal } = useModalManager(); + + const { t } = useTranslation(); + const { walletLocked, setWalletLocked } = useContext(AppContext); + const { balance, lnInfo, systemStartupInfo } = useContext(SSEContext); + const [detailTx, setDetailTx] = useState(null); + const [transactions, setTransactions] = useState([]); + const [isLoadingTransactions, setIsLoadingTransactions] = useState(false); + const [txError, setTxError] = useState(""); + + const { implementation } = lnInfo; + + const { + lightning: lightningState, + glcoin, + glcoin_msg, + lightning_msg, + } = systemStartupInfo || {}; + + useEffect(() => { + if (walletLocked && activeModal !== "UNLOCK") { + openModal("UNLOCK"); + } else if (!walletLocked && activeModal === "UNLOCK") { + closeModal(); + } + }, [walletLocked, activeModal, openModal, closeModal]); + + const closeModalHandler = useCallback(() => { + setDetailTx(null); + closeModal(); + }, [closeModal]); + + useEffect(() => { + const statusToastContent = ( +
+

+ {t("home.glcoin")} {glcoin} +

+

{glcoin_msg}

+

+ {t("home.lightning")} {lightningState} +

+

{lightning_msg}

+
+ ); + if (glcoin && lightningState) { + if ( + (glcoin === "done" && lightningState === "done") || + (glcoin === "done" && lightningState === "disabled") + ) { + toast.dismiss(startupToastId); + return; + } + + if (toast.isActive(startupToastId)) { + toast.update(startupToastId, { + render: statusToastContent, + }); + } else { + toast(statusToastContent, { + toastId: startupToastId, + isLoading: true, + autoClose: false, + }); + } + } + }, [t, lightningState, glcoin, glcoin_msg, lightning_msg]); + + const glcOnlyMode = systemStartupInfo?.lightning === "disabled"; + + const getTransactions = useCallback(async () => { + if (glcOnlyMode || (lightningState && lightningState !== "done")) { + return; + } + try { + const tx = await instance.get("/lightning/list-all-tx", { + params: { + reversed: true, + }, + }); + setTransactions(tx.data); + if (tx.status === HttpStatusCode.Ok && walletLocked) { + setWalletLocked(false); + } + // biome-ignore lint/suspicious/noExplicitAny: value is expected to exist at this point + } catch (err: any) { + if (err.response.status === HttpStatusCode.Locked) { + setWalletLocked(true); + } else { + setTxError(checkError(err)); + } + } + }, [lightningState, glcOnlyMode, walletLocked, setWalletLocked]); + + useEffect(() => { + if (!glcOnlyMode && !walletLocked && isLoadingTransactions) { + getTransactions().finally(() => { + setIsLoadingTransactions(false); + }); + } + }, [glcOnlyMode, isLoadingTransactions, walletLocked, getTransactions]); + + useEffect(() => { + enableGutter(); + + if (lightningState === "bootstrapping_after_unlock") { + setWalletLocked(false); + } + + if (lightningState === "locked") { + setWalletLocked(true); + } + + if (!walletLocked) { + setIsLoadingTransactions(true); + setTxError(""); + } + }, [lightningState, walletLocked, setWalletLocked]); + + const showDetailHandler = useCallback( + (index: number) => { + const tx = transactions.find((tx) => tx.index === index); + if (!tx) { + console.error("Could not find transaction with index ", index); + return; + } + setDetailTx(tx); + openModal("DETAIL"); + }, + [transactions, openModal], + ); + + useInterval(getTransactions, 20000); + + const modalComponent = () => ( + <> + {activeModal === "UNLOCK" && ( + + )} + {activeModal === "LIST_CHANNEL" && ( + + )} + {activeModal === "OPEN_CHANNEL" && ( + + )} + {activeModal === "SEND" && ( + + )} + {activeModal === "RECEIVE" && ( + + )} + {activeModal === "DETAIL" && ( + + )} + + ); + + if (implementation === null && lightningState !== "disabled") { + return ( + <> + {modalComponent()} + + + ); + } + + const height = glcOnlyMode ? "h-full md:h-1/2" : "h-full"; + + return ( + <> + {modalComponent()} +
+ {!glcOnlyMode && ( +
+ openModal("RECEIVE")} + onSend={() => openModal("SEND")} + onOpenChannel={() => openModal("OPEN_CHANNEL")} + onCloseChannel={() => openModal("LIST_CHANNEL")} + /> +
+ )} + + {!glcOnlyMode && ( +
+ +
+ )} + +
+
+ + +
+
+ +
+ +
+ + {!glcOnlyMode && ( +
+ +
+ )} +
+ + ); +}; + +export default Home; diff --git a/src/pages/Login/index.tsx b/src/pages/Login/index.tsx new file mode 100644 index 0000000..bf59e0a --- /dev/null +++ b/src/pages/Login/index.tsx @@ -0,0 +1,131 @@ +import { Button, Input, Spinner } from "@heroui/react"; +import type { AxiosError } from "axios"; +import { type FC, useContext, useEffect, useState } from "react"; +import type { SubmitHandler } from "react-hook-form"; +import { useForm } from "react-hook-form"; +import { useTranslation } from "react-i18next"; +import { useLocation, useNavigate } from "react-router"; +import RaspiBlesk_Logo_Main_Negative from "@/assets/RaspiBlesk_Logo_Main_Negative.svg?react"; +import { Alert } from "@/components/Alert"; +import I18nSelect from "@/components/I18nDropdown"; +import { AppContext } from "@/context/app-context"; +import { ACCESS_TOKEN, enableGutter } from "@/utils"; +import { type ApiError, checkError } from "@/utils/checkError"; +import { instance } from "@/utils/interceptor"; + +interface IFormInputs { + passwordInput: string; +} + +const Login: FC = () => { + const { t } = useTranslation(); + const [isLoading, setIsLoading] = useState(false); + const [error, setError] = useState(""); + const { isLoggedIn, setIsLoggedIn } = useContext(AppContext); + const navigate = useNavigate(); + + const location = useLocation(); + const from = + (location.state as { from?: Location })?.from?.pathname || "/home"; + const queryParams = new URLSearchParams(window.location.search); + const back = queryParams.get("back"); + + const { + register, + handleSubmit, + formState: { errors, isValid }, + } = useForm({ mode: "onChange" }); + + useEffect(() => { + if (isLoggedIn) { + if (back) { + console.info(`back(${back})`); + navigate(back, { replace: true }); + } else { + console.info(`from(${from})`); + navigate(from || "/home", { replace: true }); + } + } + }, [navigate, from, isLoggedIn, back]); + + const loginHandler: SubmitHandler = async (data: { + passwordInput: string; + }) => { + setError(""); + setIsLoading(true); + + await instance + .post("/system/login", { password: data.passwordInput }) + .then((resp) => { + // access_token was used in v1.8 + localStorage.setItem(ACCESS_TOKEN, resp.data.access_token || resp.data); + setIsLoggedIn(true); + enableGutter(); + if (back) { + console.info(`back(${back})`); + navigate(back, { replace: true }); + } else { + console.info(`from(${from})`); + navigate(from, { replace: true }); + } + }) + .catch((err: AxiosError) => setError(checkError(err))) + .finally(() => { + setIsLoading(false); + }); + }; + + return ( +
+
+ +
+ + + + {isLoading && } + + {!isLoading && ( + <> +
+ + +
+ +
+
+ + {error && {error}} + + )} +
+ ); +}; + +export default Login; diff --git a/src/pages/Settings/ActionBox.tsx b/src/pages/Settings/ActionBox.tsx new file mode 100644 index 0000000..475da9b --- /dev/null +++ b/src/pages/Settings/ActionBox.tsx @@ -0,0 +1,41 @@ +import type { FC, PropsWithChildren, ReactElement } from "react"; +import { Button } from "@/components/Button"; + +export type Props = { + name: string | ReactElement; + actionName: string; + action: () => void; + showChild: boolean; +}; + +/** + * displays a box with a title and a button which triggers an action (e.g. reboot) + * has a child component which is displayed if showChild is true + */ +const ActionBox: FC> = ({ + name, + action, + actionName, + showChild, + children, +}) => { + return ( + <> + {showChild && children} +
+
+
+

+ {name} +

+ +
+
+
+ + ); +}; + +export default ActionBox; diff --git a/src/pages/Settings/ChangePwModal.tsx b/src/pages/Settings/ChangePwModal.tsx new file mode 100644 index 0000000..da56141 --- /dev/null +++ b/src/pages/Settings/ChangePwModal.tsx @@ -0,0 +1,155 @@ +import { Input, useDisclosure } from "@heroui/react"; +import { type FC, useState } from "react"; +import { useForm } from "react-hook-form"; +import { useTranslation } from "react-i18next"; +import { toast } from "react-toastify"; +import { Button } from "@/components/Button"; +import CapsLockWarning from "@/components/CapsLockWarning"; +import { ConfirmModal } from "@/components/ConfirmModal"; +import useCapsLock from "@/hooks/use-caps-lock"; +import { checkError } from "@/utils/checkError"; +import { instance } from "@/utils/interceptor"; +import ActionBox from "./ActionBox"; + +interface IFormInputs { + oldPassword: string; + newPassword: string; +} + +const ChangePwModal: FC = () => { + const { t } = useTranslation(); + const [isLoading, setIsLoading] = useState(false); + const confirmModal = useDisclosure(); + + const { isCapsLockEnabled, keyHandlers } = useCapsLock(); + + const changePwHandler = (data: IFormInputs) => { + setIsLoading(true); + + const params = { + type: "a", + old_password: data.oldPassword, + new_password: data.newPassword, + }; + + instance + .post("/system/change-password", {}, { params }) + .then(() => { + toast.success(t("settings.pass_a_changed"), { theme: "dark" }); + confirmModal.onClose(); + }) + .catch((err) => { + toast.error(checkError(err)); + }) + .finally(() => { + setIsLoading(false); + reset(); + }); + }; + + const { + register, + handleSubmit, + reset, + formState: { errors, isValid }, + } = useForm({ + mode: "onChange", + }); + + return ( + <> + +
+ {t("settings.change_pw_a")} + + {isCapsLockEnabled && } + +
+ + + +
+
+ + + + + +
+
+ + confirmModal.onOpen()} + showChild={false} + /> + + ); +}; + +export default ChangePwModal; diff --git a/src/pages/Settings/DebugLogBox.tsx b/src/pages/Settings/DebugLogBox.tsx new file mode 100644 index 0000000..4fcd896 --- /dev/null +++ b/src/pages/Settings/DebugLogBox.tsx @@ -0,0 +1,64 @@ +import { type FC, useContext } from "react"; +import { useTranslation } from "react-i18next"; +import { toast } from "react-toastify"; +import { Button } from "@/components/Button"; +import { AppContext } from "@/context/app-context"; +import { checkError } from "@/utils/checkError"; +import { instance } from "@/utils/interceptor"; + +/** + * Displays a button to generate a debug report which is downloaded as a file + */ +const DebugLogBox: FC = () => { + const { t } = useTranslation(); + const { isGeneratingReport, setIsGeneratingReport } = useContext(AppContext); + + const onClickHandler = async () => { + try { + setIsGeneratingReport(true); + const loadingToast = toast.info(t("settings.generating_debug_report"), { + isLoading: true, + }); + const resp = await instance.get("/system/get-debug-logs-raw"); + const data = await resp.data.raw_data; + + // Download file + const blob = new Blob([data], { type: "text/plain" }); + const url = window.URL.createObjectURL(blob); + const tmpLink = document.createElement("a"); + tmpLink.href = url; + tmpLink.setAttribute("download", "debug_log.txt"); + tmpLink.click(); + toast.dismiss(loadingToast); + toast.info(t("settings.debug_report_done")); + // biome-ignore lint/suspicious/noExplicitAny: value is expected to exist at this point + } catch (e: any) { + toast.error(checkError(e)); + } finally { + setIsGeneratingReport(false); + } + }; + + return ( +
+
+
+

+ {t("settings.generate_debug")} +

+ +
+
+
+ ); +}; + +export default DebugLogBox; diff --git a/src/pages/Settings/I18nBox.tsx b/src/pages/Settings/I18nBox.tsx new file mode 100644 index 0000000..47600d0 --- /dev/null +++ b/src/pages/Settings/I18nBox.tsx @@ -0,0 +1,25 @@ +import type { FC } from "react"; +import { useTranslation } from "react-i18next"; +import I18nSelect from "@/components/I18nDropdown"; + +/** + * Displays the current language and allows the user to change it. + */ +const I18nBox: FC = () => { + const { t } = useTranslation(); + + return ( +
+
+
+

+ {t("settings.curr_lang")} +

+ +
+
+
+ ); +}; + +export default I18nBox; diff --git a/src/pages/Settings/RebootModal.tsx b/src/pages/Settings/RebootModal.tsx new file mode 100644 index 0000000..54446bc --- /dev/null +++ b/src/pages/Settings/RebootModal.tsx @@ -0,0 +1,49 @@ +import { useDisclosure } from "@heroui/react"; +import { HttpStatusCode } from "axios"; +import { type FC, useContext, useState } from "react"; +import { useTranslation } from "react-i18next"; +import { useNavigate } from "react-router"; +import { ConfirmModal } from "@/components/ConfirmModal"; +import { AppContext } from "@/context/app-context"; +import { instance } from "@/utils/interceptor"; +import ActionBox from "./ActionBox"; + +const confirmEndpoint = "/system/reboot"; + +const RebootModal: FC = () => { + const [isLoading, setIsLoading] = useState(false); + const { t } = useTranslation(); + const { setIsLoggedIn } = useContext(AppContext); + const navigate = useNavigate(); + const confirmModal = useDisclosure(); + + const rebootHandler = async () => { + setIsLoading(true); + const resp = await instance.post(confirmEndpoint); + if (resp.status === HttpStatusCode.Ok) { + setIsLoading(false); + setIsLoggedIn(false); + navigate("/login"); + } + }; + + return ( + <> + + + confirmModal.onOpen()} + showChild={false} + /> + + ); +}; + +export default RebootModal; diff --git a/src/pages/Settings/ShutdownModal.tsx b/src/pages/Settings/ShutdownModal.tsx new file mode 100644 index 0000000..0630725 --- /dev/null +++ b/src/pages/Settings/ShutdownModal.tsx @@ -0,0 +1,57 @@ +import { useDisclosure } from "@heroui/react"; +import { HttpStatusCode } from "axios"; +import { type FC, useContext, useState } from "react"; +import { useTranslation } from "react-i18next"; +import { useNavigate } from "react-router"; +import { ConfirmModal } from "@/components/ConfirmModal"; +import { AppContext } from "@/context/app-context"; +import { instance } from "@/utils/interceptor"; +import ActionBox from "./ActionBox"; + +const confirmEndpoint = "/system/shutdown"; + +const ShutdownModal: FC = () => { + const [isLoading, setIsLoading] = useState(false); + const { t } = useTranslation(); + const { setIsLoggedIn } = useContext(AppContext); + const navigate = useNavigate(); + const confirmModal = useDisclosure(); + + const shutdownHandler = async () => { + setIsLoading(true); + const resp = await instance.post(confirmEndpoint); + if (resp.status === HttpStatusCode.Ok) { + setIsLoading(false); + setIsLoggedIn(false); + navigate("/login"); + } + }; + + return ( + <> + +

{t("settings.shutdown_info")}

+

+ {t("settings.shutdown_info_disconnect_power")} +

+ + } + onConfirm={shutdownHandler} + isLoading={isLoading} + /> + + confirmModal.onOpen()} + showChild={false} + /> + + ); +}; + +export default ShutdownModal; diff --git a/src/pages/Settings/VersionBox.tsx b/src/pages/Settings/VersionBox.tsx new file mode 100644 index 0000000..860df0f --- /dev/null +++ b/src/pages/Settings/VersionBox.tsx @@ -0,0 +1,35 @@ +import packageJson from "package.json"; +import { type FC, useContext } from "react"; +import { useTranslation } from "react-i18next"; +import { SSEContext } from "@/context/sse-context"; + +/** + * Displays the versions of RaspiBlesk, the WebUI and the Blesk-API + */ +const VersionBox: FC = () => { + const { t } = useTranslation(); + const { systemInfo } = useContext(SSEContext); + + const { platform_version, api_version } = systemInfo; + + return ( +
+
+
{t("home.versions")}
+
+

+ RaspiBlesk: {platform_version} +

+

+ RaspiBlesk WebUI: {packageJson.version} +

+

+ Blesk-API: {api_version} +

+
+
+
+ ); +}; + +export default VersionBox; diff --git a/src/pages/Settings/index.tsx b/src/pages/Settings/index.tsx new file mode 100644 index 0000000..d03f5c6 --- /dev/null +++ b/src/pages/Settings/index.tsx @@ -0,0 +1,27 @@ +import { type FC, useEffect } from "react"; +import { enableGutter } from "@/utils"; +import ChangePwModal from "./ChangePwModal"; +import DebugLogBox from "./DebugLogBox"; +import I18nBox from "./I18nBox"; +import RebootModal from "./RebootModal"; +import ShutdownModal from "./ShutdownModal"; +import VersionBox from "./VersionBox"; + +const Settings: FC = () => { + useEffect(() => { + enableGutter(); + }, []); + + return ( +
+ + + + + + +
+ ); +}; + +export default Settings; diff --git a/src/pages/Setup/CustomRadio.tsx b/src/pages/Setup/CustomRadio.tsx new file mode 100644 index 0000000..710619e --- /dev/null +++ b/src/pages/Setup/CustomRadio.tsx @@ -0,0 +1,85 @@ +import { cn, Image, Radio } from "@heroui/react"; +import type { ReactNode } from "react"; + +type Props = { + id: string; + radioGroup: string; + value: string; + icon?: ReactNode; + iconColor?: string; + image?: string; + text: string; + description?: string; +}; + +const imageBaseClasses = "mr-3 flex rounded-lg bg-white bg-opacity-5 p-2"; + +export default function CustomRadio({ + id, + radioGroup, + value, + icon, + image, + text, + description, + iconColor, +}: Props) { + return ( + +
+ {!!image && ( +
+ {`${text} +
+ )} + + {!!icon && ( +
+ {icon} +
+ )} + +
+

{text}

+ {!!description && ( +

+ {description} +

+ )} +
+
+
+ ); +} diff --git a/src/pages/Setup/FinalDialog.tsx b/src/pages/Setup/FinalDialog.tsx new file mode 100644 index 0000000..633af6b --- /dev/null +++ b/src/pages/Setup/FinalDialog.tsx @@ -0,0 +1,89 @@ +import { CheckCircleIcon } from "@heroicons/react/24/outline"; +import { Checkbox } from "@heroui/react"; +import { Controller, useForm } from "react-hook-form"; +import { useTranslation } from "react-i18next"; +import { Alert } from "@/components/Alert"; +import { Button } from "@/components/Button"; +import { Headline } from "@/components/Headline"; +import SetupContainer from "@/layouts/SetupContainer"; +import type { SetupPhase } from "@/models/setup.model"; + +export type Props = { + setupPhase: SetupPhase; + seedWords: string | null; + callback: () => void; +}; + +interface IFormInputs { + confirm: boolean; +} + +export default function FinalDialog({ + setupPhase, + seedWords, + callback, +}: Props) { + const { t } = useTranslation(); + + const { + handleSubmit, + control, + formState: { isValid }, + } = useForm({ + mode: "onChange", + }); + + return ( + +
+
+
+ + {t(`setup.final_${setupPhase || "setup"}`)} +
+ + {!!seedWords && {t("setup.final_seedwords")}} + + {!!seedWords && ( +
    + {seedWords.split(", ").map((word, index) => { + return ( + // biome-ignore lint/suspicious/noArrayIndexKey: value is expected to exist at this point +
  1. + {word} +
  2. + ); + })} +
+ )} + + {!!seedWords && ( + ( + + {t("setup.final_info_reboot")} + + )} + /> + )} + +
+ +
+
+
+
+ ); +} diff --git a/src/pages/Setup/FormatDialog.tsx b/src/pages/Setup/FormatDialog.tsx new file mode 100644 index 0000000..6fd7bd0 --- /dev/null +++ b/src/pages/Setup/FormatDialog.tsx @@ -0,0 +1,69 @@ +import { Checkbox, useDisclosure } from "@heroui/react"; +import { type FormEvent, useState } from "react"; +import { useTranslation } from "react-i18next"; +import { Alert } from "@/components/Alert"; +import { Button } from "@/components/Button"; +import { ConfirmModal } from "@/components/ConfirmModal"; +import { Headline } from "@/components/Headline"; +import SetupContainer from "@/layouts/SetupContainer"; + +export type Props = { + containsBlockchain: boolean; + callback: (deleteData: boolean, keepBlockchainData: boolean) => void; +}; + +export default function FormatDialog({ containsBlockchain, callback }: Props) { + const { t } = useTranslation(); + const [keepBlockchain, setKeepBlockchain] = useState(containsBlockchain); + + const submitHandler = (e: FormEvent) => { + e.preventDefault(); + callback(true, keepBlockchain); + }; + + const confirmModal = useDisclosure(); + + return ( + <> + callback(false, false)} + /> + + +
+ {t("setup.format.delete_drive")} + {t("setup.format.warn")} + + {containsBlockchain && ( + + {t("setup.format.keep_blockchain")} + + )} + +
+ + + +
+
+
+ + ); +} diff --git a/src/pages/Setup/InputNodeName.tsx b/src/pages/Setup/InputNodeName.tsx new file mode 100644 index 0000000..0be2a25 --- /dev/null +++ b/src/pages/Setup/InputNodeName.tsx @@ -0,0 +1,105 @@ +import { Input, useDisclosure } from "@heroui/react"; +import { type ChangeEvent, useState } from "react"; +import { useForm } from "react-hook-form"; +import { useTranslation } from "react-i18next"; +import { Button } from "@/components/Button"; +import { ConfirmModal } from "@/components/ConfirmModal"; +import { Headline } from "@/components/Headline"; +import SetupContainer from "@/layouts/SetupContainer"; + +export type Props = { + callback: (nodename: string | null) => void; +}; + +interface IFormInputs { + inputNodeName: string; +} + +export default function InputNodeName({ callback }: Props) { + const [inputNodeName, setInputNodeName] = useState(""); + + const { t } = useTranslation(); + + const changeNodenameHandler = (event: ChangeEvent) => { + setInputNodeName(event.target.value); + }; + + const continueHandler = () => { + callback(inputNodeName); + }; + + const { + register, + handleSubmit, + formState: { errors, isValid }, + } = useForm({ + mode: "onChange", + }); + + const confirmModal = useDisclosure(); + + return ( + <> + callback(null)} + /> + + +
+ {t("setup.input_node.header")} + +
+
+ +
+ +
+ + +
+
+
+
+ + ); +} diff --git a/src/pages/Setup/InputPassword.tsx b/src/pages/Setup/InputPassword.tsx new file mode 100644 index 0000000..9eba0e7 --- /dev/null +++ b/src/pages/Setup/InputPassword.tsx @@ -0,0 +1,144 @@ +import { Input, useDisclosure } from "@heroui/react"; +import { useForm } from "react-hook-form"; +import { Trans, useTranslation } from "react-i18next"; +import { Button } from "@/components/Button"; +import { ConfirmModal } from "@/components/ConfirmModal"; +import { Headline } from "@/components/Headline"; +import SetupContainer from "@/layouts/SetupContainer"; + +type Props = { + passwordType: PasswordColors; + callback: (password: string | null) => void; +}; + +interface IFormInputs { + passfirst: string; + passrepeat: string; +} + +const passwordColors = { + a: "text-danger", + b: "text-primary", + c: "text-warning", +}; + +type PasswordColors = keyof typeof passwordColors; + +export default function InputPassword({ passwordType, callback }: Props) { + const { t } = useTranslation(); + + const { + register, + handleSubmit, + reset, + watch, + formState: { errors, isValid }, + } = useForm({ + mode: "onChange", + }); + + const continueHandler = (data: IFormInputs) => { + callback(data.passfirst); + reset(); + }; + + const confirmModal = useDisclosure(); + + return ( + <> + callback(null)} + /> + + +
+ + , // if needed, create a component for this + ]} + /> + + +

+ , // if needed, create a component for this + ]} + /> +

+ +
+
+ + + + value === watch("passfirst") || + t("setup.password_error_match"), + })} + /> +
+ +
+ + +
+
+
+
+ + ); +} diff --git a/src/pages/Setup/LightningDialog.tsx b/src/pages/Setup/LightningDialog.tsx new file mode 100644 index 0000000..cb20be1 --- /dev/null +++ b/src/pages/Setup/LightningDialog.tsx @@ -0,0 +1,104 @@ +import { RadioGroup } from "@heroui/react"; +import { type FormEvent, useState } from "react"; +import { Trans, useTranslation } from "react-i18next"; +import GlcoinLogo from "@/assets/bitcoin-logo.svg"; +import CLLogo from "@/assets/core_lightning_logo_only.png"; +import LNDLogo from "@/assets/lnd.png"; +import { Button } from "@/components/Button"; +import { Headline } from "@/components/Headline"; +import SetupContainer from "@/layouts/SetupContainer"; +import { SetupLightning } from "@/models/setup.model"; +import CustomRadio from "./CustomRadio"; + +type Props = { + callback: (lightningSelect: SetupLightning) => void; +}; + +export type SelectFn = (value: string) => void; + +const images = { + [SetupLightning.CLIGHTNING]: CLLogo, + [SetupLightning.LND]: LNDLogo, + [SetupLightning.NONE]: GlcoinLogo, + [SetupLightning.NULL]: "", +}; + +export default function LightningDialog({ callback }: Props) { + const { t } = useTranslation(); + const [selected, setSelected] = useState( + undefined, + ); + + const submitHandler = (e: FormEvent) => { + e.preventDefault(); + + if (!selected) return; + callback(selected); + }; + + return ( + +
+
+ {t("setup.select_lightning")} + +

+ , + ]} + /> +

+
+ +
+
+ + {[ + SetupLightning.LND, + SetupLightning.CLIGHTNING, + SetupLightning.NONE, + ].map((lightning) => ( + + ))} + +
+ +
+ +
+
+
+
+ ); +} diff --git a/src/pages/Setup/MigrationDialog.tsx b/src/pages/Setup/MigrationDialog.tsx new file mode 100644 index 0000000..a6618be --- /dev/null +++ b/src/pages/Setup/MigrationDialog.tsx @@ -0,0 +1,85 @@ +import { useDisclosure } from "@heroui/react"; +import { useTranslation } from "react-i18next"; +import { Alert } from "@/components/Alert"; +import { Button } from "@/components/Button"; +import { ConfirmModal } from "@/components/ConfirmModal"; +import { Headline } from "@/components/Headline"; +import SetupContainer from "@/layouts/SetupContainer"; +import { + SetupMigrationMode, + type SetupMigrationOS, +} from "@/models/setup.model"; + +type Props = { + migrationOS: SetupMigrationOS; + migrationMode: SetupMigrationMode; + callback: (migrate: boolean) => void; +}; + +export default function MigrationDialog({ + migrationOS, + migrationMode, + callback, +}: Props) { + const { t } = useTranslation(); + const confirmModal = useDisclosure(); + + if (migrationMode === SetupMigrationMode.OUTDATED) { + return ( + +
+ + {t("setup.lightningoutdated")} + + + +
+
+ ); + } + + return ( + <> + callback(false)} + /> + + +
+
+ + {t("setup.migrate_to_os", { + os: `${migrationOS[0].toUpperCase()}${migrationOS.slice(1)}`, + })} + + +

+ {t("setup.convertwarning")} +

+
+ +
+ + +
+
+
+ + ); +} diff --git a/src/pages/Setup/RecoveryDialog.tsx b/src/pages/Setup/RecoveryDialog.tsx new file mode 100644 index 0000000..e721cf4 --- /dev/null +++ b/src/pages/Setup/RecoveryDialog.tsx @@ -0,0 +1,36 @@ +import { useTranslation } from "react-i18next"; +import { Button } from "@/components/Button"; +import { Headline } from "@/components/Headline"; +import SetupContainer from "@/layouts/SetupContainer"; +import { SetupPhase } from "@/models/setup.model"; + +type Props = { + setupPhase: SetupPhase; + callback: (start: boolean) => void; +}; + +export default function RecoveryDialog({ setupPhase, callback }: Props) { + const { t } = useTranslation(); + + const getHeadlineText = () => { + if (setupPhase === SetupPhase.RECOVERY) return t("setup.start_recovery"); + if (setupPhase === SetupPhase.UPDATE) return t("setup.start_update"); + return ""; + }; + + return ( + +
+ {getHeadlineText()} +
+ + +
+
+
+ ); +} diff --git a/src/pages/Setup/SetupContext.tsx b/src/pages/Setup/SetupContext.tsx new file mode 100644 index 0000000..6067d81 --- /dev/null +++ b/src/pages/Setup/SetupContext.tsx @@ -0,0 +1,227 @@ +import type React from "react"; +import { createContext, useCallback, useContext } from "react"; +import type { NavigateFunction } from "react-router"; +import { + Screen, + SetupLightning, + SetupPhase, + type SetupState, +} from "@/models/setup.model"; +import { + setupFinalReboot, + setupShutdown, + setupStart, +} from "@/pages/Setup/setup-functions"; + +interface SetupContextType { + state: SetupState; + updateState: (newState: Partial) => void; + callbacks: { + onRecoveryDialog: (startRecovery: boolean) => void; + onMigrationDialog: (start: boolean) => Promise; + onSetupMenu: (setupmode: SetupPhase) => Promise; + onFormatDialog: (deleteData: boolean, keepBlockchainData: boolean) => void; + onLightning: (lightning: SetupLightning) => void; + onInputNodename: (nodename: string | null) => void; + onInputPasswordA: (password: string | null) => void; + onInputPasswordB: (password: string | null) => void; + onInputPasswordC: (password: string | null) => void; + onStartDoneDialog: (cancel: boolean) => Promise; + onSyncScreen: (action: string) => Promise; + onFinalReboot: () => Promise; + }; +} + +export interface Props { + children: React.ReactNode; + state: SetupState; + updateState: (newState: Partial) => void; + navigate: NavigateFunction; +} + +const SetupContext = createContext(undefined); + +export const useSetup = () => { + const context = useContext(SetupContext); + if (!context) { + throw new Error("useSetup must be used within a SetupProvider"); + } + return context; +}; + +export default function SetupProvider({ + children, + state, + updateState, + navigate, +}: Props) { + const callbacks = { + onRecoveryDialog: useCallback( + (startRecovery: boolean) => { + updateState({ page: startRecovery ? Screen.INPUT_A : Screen.SETUP }); + }, + [updateState], + ), + + onMigrationDialog: useCallback( + async (start: boolean) => { + if (start) { + updateState({ + setupPhase: SetupPhase.MIGRATION, + page: Screen.INPUT_A, + }); + } else { + await setupShutdown(updateState); + } + }, + [updateState], + ), + + onSetupMenu: useCallback( + async (setupmode: SetupPhase) => { + updateState({ setupPhase: setupmode }); + switch (setupmode) { + case SetupPhase.NULL: + await setupShutdown(updateState); + break; + case SetupPhase.RECOVERY: + case SetupPhase.UPDATE: + case SetupPhase.MIGRATION: + updateState({ page: Screen.INPUT_A }); + break; + case SetupPhase.SETUP: + updateState({ page: Screen.FORMAT }); + break; + } + }, + [updateState], + ), + + onFormatDialog: useCallback( + (deleteData: boolean, keepBlockchainData: boolean) => { + if (!deleteData) { + updateState({ page: Screen.SETUP }); + return; + } + updateState({ + keepBlockchain: keepBlockchainData, + page: Screen.INPUT_NODENAME, + }); + }, + [updateState], + ), + + onLightning: useCallback( + (lightning: SetupLightning) => { + if (lightning === SetupLightning.NULL) { + updateState({ page: Screen.SETUP }); + return; + } + updateState({ + lightning, + page: Screen.INPUT_A, + }); + }, + [updateState], + ), + + onInputNodename: useCallback( + (nodename: string | null) => { + if (!nodename) { + updateState({ page: Screen.SETUP }); + return; + } + updateState({ + hostname: nodename, + page: Screen.LIGHTNING, + }); + }, + [updateState], + ), + + onInputPasswordA: useCallback( + (passwordA: string | null) => { + if (!passwordA) { + updateState({ page: Screen.SETUP }); + return; + } + updateState({ passwordA }); + switch (state.setupPhase) { + case SetupPhase.RECOVERY: + case SetupPhase.UPDATE: + updateState({ page: Screen.START_DONE }); + break; + case SetupPhase.SETUP: + case SetupPhase.MIGRATION: + updateState({ page: Screen.INPUT_B }); + break; + } + }, + [state, updateState], + ), + + onInputPasswordB: useCallback( + (passwordB: string | null) => { + if (!passwordB) { + updateState({ page: Screen.SETUP }); + return; + } + updateState({ passwordB }); + if (state.lightning === SetupLightning.NONE) { + updateState({ page: Screen.START_DONE }); + } else { + updateState({ page: Screen.INPUT_C }); + } + }, + [state, updateState], + ), + + onInputPasswordC: useCallback( + (passwordC: string | null) => { + if (!passwordC) { + updateState({ page: Screen.SETUP }); + return; + } + updateState({ + passwordC, + page: Screen.START_DONE, + }); + }, + [updateState], + ), + + onStartDoneDialog: useCallback( + async (cancel: boolean) => { + if (cancel) { + updateState({ page: Screen.SETUP }); + return; + } + await setupStart(state, updateState, navigate); + }, + [navigate, state, updateState], + ), + + onSyncScreen: useCallback( + async (action: string) => { + if (action === "shutdown") { + try { + await setupShutdown(updateState); + } catch (error) { + console.error("Shutdown request failed", error); + } + } + }, + [updateState], + ), + + onFinalReboot: useCallback(async () => { + await setupFinalReboot(updateState, navigate); + }, [updateState, navigate]), + }; + + return ( + + {children} + + ); +} diff --git a/src/pages/Setup/SetupMenu.tsx b/src/pages/Setup/SetupMenu.tsx new file mode 100644 index 0000000..6beff75 --- /dev/null +++ b/src/pages/Setup/SetupMenu.tsx @@ -0,0 +1,108 @@ +import { + ArrowDownTrayIcon, + ArrowsRightLeftIcon, + ArrowUpCircleIcon, + ArrowUturnLeftIcon, + PowerIcon, +} from "@heroicons/react/24/outline"; +import { RadioGroup } from "@heroui/react"; +import { type FormEvent, useState } from "react"; +import { useTranslation } from "react-i18next"; +import { Button } from "@/components/Button"; +import { Headline } from "@/components/Headline"; +import SetupContainer from "@/layouts/SetupContainer"; +import { SetupPhase } from "@/models/setup.model"; +import CustomRadio from "./CustomRadio"; + +type Props = { + setupPhase: SetupPhase; + callback: (setupmode: SetupPhase) => void; +}; + +export type SelectFn = (value: string) => void; + +export default function SetupMenu({ setupPhase, callback }: Props) { + const { t } = useTranslation(); + const [selected, setSelected] = useState(SetupPhase.NULL); + + const submitHandler = (e: FormEvent) => { + e.preventDefault(); + callback(selected); + }; + + return ( + +
+
+ {t("setup.setupmenu.lets_setup")} + +

+ {t("setup.setupmenu.setup_time")} +

+
+ +
+
+ + {setupPhase === SetupPhase.RECOVERY && ( + } + text={t("setup.recoverblitz")} + /> + )} + {setupPhase === SetupPhase.UPDATE && ( + } + text={t("setup.updateblitz")} + /> + )} + {setupPhase === SetupPhase.MIGRATION && ( + } + text={t("setup.migrateblitz")} + /> + )} + } + text={t("setup.setupblitz")} + /> + } + iconColor="text-red-500" + text={t("settings.shutdown")} + /> + +
+ +
+ +
+
+
+
+ ); +} diff --git a/src/pages/Setup/SetupScreenRenderer.tsx b/src/pages/Setup/SetupScreenRenderer.tsx new file mode 100644 index 0000000..17bcc55 --- /dev/null +++ b/src/pages/Setup/SetupScreenRenderer.tsx @@ -0,0 +1,92 @@ +import { Screen } from "@/models/setup.model"; +import { useSetup } from "@/pages/Setup/SetupContext"; +import FinalDialog from "./FinalDialog"; +import FormatDialog from "./FormatDialog"; +import InputNodeName from "./InputNodeName"; +import InputPassword from "./InputPassword"; +import LightningDialog from "./LightningDialog"; +import MigrationDialog from "./MigrationDialog"; +import RecoveryDialog from "./RecoveryDialog"; +import SetupMenu from "./SetupMenu"; +import StartDoneDialog from "./StartDoneDialog"; +import SyncScreen from "./SyncScreen"; +import WaitScreen from "./WaitScreen"; + +export default function SetupScreenRenderer() { + const { state, callbacks } = useSetup(); + + switch (state.page) { + case Screen.SETUP: + return ( + + ); + case Screen.START_DONE: + return ( + + ); + case Screen.FORMAT: + return ( + + ); + case Screen.RECOVERY: + return ( + + ); + case Screen.MIGRATION: + return ( + + ); + case Screen.LIGHTNING: + return ; + case Screen.INPUT_A: + return ( + + ); + case Screen.INPUT_B: + return ( + + ); + case Screen.INPUT_C: + return ( + + ); + case Screen.INPUT_NODENAME: + return ; + case Screen.FINAL: + return ( + + ); + case Screen.SYNC: + return ( + + ); + // case Screen.WAIT: UNUSED + default: + return ( + + ); + } +} diff --git a/src/pages/Setup/StartDoneDialog.tsx b/src/pages/Setup/StartDoneDialog.tsx new file mode 100644 index 0000000..9f0a23c --- /dev/null +++ b/src/pages/Setup/StartDoneDialog.tsx @@ -0,0 +1,61 @@ +import { useDisclosure } from "@heroui/react"; +import { useTranslation } from "react-i18next"; +import { Button } from "@/components/Button"; +import { ConfirmModal } from "@/components/ConfirmModal"; +import { Headline } from "@/components/Headline"; +import SetupContainer from "@/layouts/SetupContainer"; +import { SetupPhase } from "@/models/setup.model"; + +export type Props = { + setupPhase: SetupPhase; + callback: (cancel: boolean) => void; +}; + +export default function StartDoneDialog({ setupPhase, callback }: Props) { + const { t } = useTranslation(); + const confirmModal = useDisclosure(); + + let headline: string; + let buttonText: string; + + switch (setupPhase) { + case SetupPhase.RECOVERY: + headline = t("setup.done_recover_ready"); + buttonText = t("setup.done_recover_start"); + break; + case SetupPhase.UPDATE: + headline = t("setup.done_update_ready"); + buttonText = t("setup.done_update_start"); + break; + case SetupPhase.MIGRATION: + headline = t("setup.done_migration_ready"); + buttonText = t("setup.done_migration_start"); + break; + default: + headline = t("setup.done_setup_ready"); + buttonText = t("setup.done_setup_start"); + } + + return ( + <> + callback(true)} + /> + + + {headline} + +
+ + +
+
+ + ); +} diff --git a/src/pages/Setup/Stepper.tsx b/src/pages/Setup/Stepper.tsx new file mode 100644 index 0000000..b1e3982 --- /dev/null +++ b/src/pages/Setup/Stepper.tsx @@ -0,0 +1,42 @@ +import { cn } from "@heroui/react"; +import { useTranslation } from "react-i18next"; + +const NUMBER_OF_STEPS = 4; + +type Props = { + currentStep: number; +}; + +export default function Stepper({ currentStep }: Props) { + const { t } = useTranslation(); + + return ( +
+
    + {Array.from({ length: NUMBER_OF_STEPS }).map((_, index: number) => ( + // biome-ignore lint/suspicious/noArrayIndexKey: value is expected to exist at this point +
  • + = currentStep && "opacity-30", + )} + > + + {t("setup.step.step")} {index + 1} + + + {t(`setup.step.step_${index + 1}_description`)} + + +
  • + ))} +
+
+ ); +} diff --git a/src/pages/Setup/SyncScreen.tsx b/src/pages/Setup/SyncScreen.tsx new file mode 100644 index 0000000..082bebb --- /dev/null +++ b/src/pages/Setup/SyncScreen.tsx @@ -0,0 +1,232 @@ +import { + CheckCircleIcon, + LockClosedIcon, + LockOpenIcon, + PowerIcon, + XCircleIcon, +} from "@heroicons/react/24/outline"; +import { + Input, + Modal, + ModalBody, + ModalContent, + ModalFooter, + ModalHeader, + Progress, + useDisclosure, +} from "@heroui/react"; +import { HttpStatusCode } from "axios"; +import { type ChangeEvent, useState } from "react"; +import { useForm } from "react-hook-form"; +import { useTranslation } from "react-i18next"; +import { useNavigate } from "react-router"; +import { Alert } from "@/components/Alert"; +import { Button } from "@/components/Button"; +import { Headline } from "@/components/Headline"; +import SetupContainer from "@/layouts/SetupContainer"; +import { checkError } from "@/utils/checkError"; +import { instance } from "@/utils/interceptor"; + +type Props = { + // biome-ignore lint/suspicious/noExplicitAny: value is expected to exist at this point + data: SyncData | any; + // biome-ignore lint/suspicious/noExplicitAny: value is expected to exist at this point + callback: (action: string, data: any) => void; +}; + +interface SyncData { + initialSync: string; + btc_default: string; + btc_default_ready: string; + btc_default_sync_percentage: string; + btc_default_peers: string; + system_count_start_blockchain: string; + ln_default: string; + ln_default_ready: string; + ln_default_locked: string; + system_count_start_lightning: string; +} + +interface IFormInputs { + passwordInput: string; +} + +export default function SyncScreen({ data, callback }: Props) { + const { t } = useTranslation(); + const navigate = useNavigate(); + const { isOpen, onOpen, onOpenChange } = useDisclosure(); + + const [password, setPassword] = useState(""); + const [runningUnlock, setRunningUnlock] = useState(false); + const [error, setError] = useState(null); + + const changePasswordHandler = (event: ChangeEvent) => { + setPassword(event.target.value); + }; + + const unlockWallet = () => { + setRunningUnlock(true); + setError(null); + instance + .post("/lightning/unlock-wallet", { + password: password, + }) + .then(() => { + setPassword(""); + setRunningUnlock(false); + data.ln_default_locked = "0"; + }) + .catch((err) => { + if (err.response.status === HttpStatusCode.Forbidden) { + navigate("/login?back=/setup"); + } else if (err.response.status === HttpStatusCode.Unauthorized) { + setPassword(""); + setRunningUnlock(false); + setError(`${t("login.error")}: ${t("login.invalid_pass")}`); + } else { + setPassword(""); + setRunningUnlock(false); + setError(checkError(err)); + } + }); + }; + + const { + register, + handleSubmit, + formState: { errors }, + } = useForm({ + mode: "onChange", + }); + + const lnEnabled = data.ln_default && data.ln_default !== "none"; + + const lnWalletLocked = lnEnabled && data.ln_default_locked === "1"; + const lnWalletUnlocked = lnEnabled && data.ln_default_locked === "0"; + + const btcDefaultReady = data.btc_default_ready === "1"; + const btcDefaultSyncPercentage = +data.btc_default_sync_percentage; + + return ( + <> + {lnWalletLocked && ( + +
+ + + {t("wallet.unlock_subtitle")} + + + + + {error && {error}} + + + + + +
+
+ )} + + +
+ {t("setup.sync_headline")} + +
+ + + {(lnWalletUnlocked || lnWalletLocked) && ( +
+ + {lnWalletUnlocked && ( + <> +

+ {" "} + {t("wallet.unlock_success")} +

+
+ {data.ln_default_ready === "1" ? ( + <> + {" "} + {t("home.lightning")} {t("setup.started")} + + ) : ( + <> + {" "} + {t("home.lightning")} {t("setup.not_started")} + + )} +

+ ({t("setup.restarts")}:{" "} + {data.system_count_start_lightning}) +

+
+ + )} + + {lnWalletLocked && ( +
+

+ {" "} + {t("wallet.wallet_locked")} +

+ +

{t("wallet.wallet_unlock_info")}

+
+ )} +
+
+ )} +
+ +
+ +
+
+
+ + ); +} diff --git a/src/pages/Setup/WaitScreen.tsx b/src/pages/Setup/WaitScreen.tsx new file mode 100644 index 0000000..83478b0 --- /dev/null +++ b/src/pages/Setup/WaitScreen.tsx @@ -0,0 +1,56 @@ +import { Spinner } from "@heroui/react"; +import { useTranslation } from "react-i18next"; +import { Headline } from "@/components/Headline"; +import SetupContainer from "@/layouts/SetupContainer"; +import { SetupStatus } from "@/models/setup.model"; + +type Props = { + status: SetupStatus; + message: string; +}; + +export default function WaitScreen({ status, message }: Props) { + const { t } = useTranslation(); + + // optimize for certain states like + // setup.scripts/eventInfoWait.sh + let headline = ""; + let details = ""; + switch (status) { + case SetupStatus.WAIT: + headline = `${t("setup.pleasewait")}...`; + break; + case SetupStatus.SHUTDOWN: + headline = `${t("setup.shuttingdown")}...`; + break; + case SetupStatus.REBOOT: + headline = `${t("setup.restarting")}...`; + details = `(${t("setup.restartinfo")})`; + break; + case SetupStatus.WAITPROVISION: + headline = `${t("setup.preparingsetup")}...`; + details = `(${t("setup.setupwait")})`; + break; + case SetupStatus.PROVISION: + headline = `${t("setup.runningsetup")}:`; + details = message; + break; + default: + headline = status; + details = message; + } + + return ( + +
+ + +
+ {headline} + +

{details}

+
+
+
+ ); +} diff --git a/src/pages/Setup/index.tsx b/src/pages/Setup/index.tsx new file mode 100644 index 0000000..88dfb45 --- /dev/null +++ b/src/pages/Setup/index.tsx @@ -0,0 +1,25 @@ +import { useCallback, useEffect, useState } from "react"; +import { useNavigate } from "react-router"; +import { initialState, type SetupState } from "@/models/setup.model"; +import SetupProvider from "@/pages/Setup/SetupContext"; +import SetupScreenRenderer from "@/pages/Setup/SetupScreenRenderer"; +import { setupMonitoringLoop } from "@/pages/Setup/setup-functions"; + +export default function Setup() { + const [state, setState] = useState(initialState); + const navigate = useNavigate(); + + const updateState = useCallback((newState: Partial) => { + setState((prevState: SetupState) => ({ ...prevState, ...newState })); + }, []); + + useEffect(() => { + setupMonitoringLoop(updateState, navigate); + }, [updateState, navigate]); + + return ( + + + + ); +} diff --git a/src/pages/Setup/setup-functions.ts b/src/pages/Setup/setup-functions.ts new file mode 100644 index 0000000..9e15d0b --- /dev/null +++ b/src/pages/Setup/setup-functions.ts @@ -0,0 +1,217 @@ +import { HttpStatusCode } from "axios"; +import type { NavigateFunction } from "react-router"; +import { + Screen, + SetupPhase, + type SetupState, + SetupStatus, +} from "@/models/setup.model"; +import { ACCESS_TOKEN } from "@/utils"; +import { instance } from "@/utils/interceptor"; + +type UpdateState = (newState: Partial) => void; + +export function showError(message: string, updateState: UpdateState): void { + updateState({ + waitScreenStatus: SetupStatus.ERROR, + waitScreenMessage: message, + page: Screen.WAIT, + }); +} + +export async function setupMonitoringLoop( + updateState: UpdateState, + navigate: NavigateFunction, +): Promise { + try { + const resp = await instance.get("/setup/status"); + + if (resp.data.state === SetupStatus.WAITSETUP) { + await initSetupStart(updateState); + return; + } + + if (resp.data.state === SetupStatus.WAITFINAL) { + await initSetupFinal(updateState, navigate); + return; + } + + if (resp.data.state === SetupStatus.READY) { + if (resp.data.initialsync === "running") { + await showSyncScreen(updateState, navigate); + } else { + navigate("/"); + return; + } + } else { + updateState({ + waitScreenStatus: resp.data.state, + waitScreenMessage: resp.data.message, + page: Screen.WAIT, + }); + } + } catch (error) { + console.error( + `status request failed - device is off or in reboot?: ${error}`, + ); + } + + setTimeout(() => setupMonitoringLoop(updateState, navigate), 4000); +} + +export async function initSetupStart(updateState: UpdateState): Promise { + try { + const resp = await instance.get("/setup/setup-start-info"); + updateState({ + gotBlockchain: resp.data.hddGotBlockchain === "1", + setupPhaseOnStart: resp.data.setupPhase, + migrationOS: resp.data.hddGotMigrationData, + migrationMode: resp.data.migrationMode, + page: getInitialPage(resp.data.setupPhase, updateState), + }); + } catch (error) { + showError(`request for init setup data failed: ${error}`, updateState); + } +} + +export async function initSetupFinal( + updateState: UpdateState, + navigate: NavigateFunction, +): Promise { + try { + const resp = await instance.get("/setup/setup-final-info"); + updateState({ + seedWords: resp.data?.seedwordsNEW || null, + page: Screen.FINAL, + }); + } catch (err) { + const error = err as { response: { status: number } }; + if ( + error.response && + [HttpStatusCode.Forbidden, HttpStatusCode.Unauthorized].includes( + error.response.status, + ) + ) { + navigate("/login?back=/setup"); + } else { + showError( + `request for setup start failed: ${error.response?.status}`, + updateState, + ); + } + } +} + +export async function setupStart( + state: SetupState, + updateState: UpdateState, + navigate: NavigateFunction, +): Promise { + try { + const forceFreshSetup = state.setupPhase === SetupPhase.SETUP; + const resp = await instance.post("/setup/setup-start-done", { + hostname: state.hostname, + forceFreshSetup, + keepBlockchain: state.keepBlockchain, + lightning: state.lightning, + passwordA: state.passwordA, + passwordB: state.passwordB, + passwordC: state.passwordC, + }); + + if (resp.data) { + localStorage.setItem(ACCESS_TOKEN, resp.data.access_token || resp.data); + } + + await setupMonitoringLoop(updateState, navigate); + } catch (error) { + console.error(`request for setup start failed: ${error}`); + showError("request for setup start failed", updateState); + } +} + +export async function setupFinalReboot( + updateState: UpdateState, + navigate: NavigateFunction, +): Promise { + try { + await instance.post("/setup/setup-final-done", {}); + await setupMonitoringLoop(updateState, navigate); + } catch (err) { + const error = err as { response: { status: number } }; + if ( + error.response && + [HttpStatusCode.Forbidden, HttpStatusCode.Unauthorized].includes( + error.response.status, + ) + ) { + navigate("/login?back=/setup"); + } else { + showError( + `request for final setup done failed: ${error.response?.status}`, + updateState, + ); + } + } +} + +export async function setupShutdown(updateState: UpdateState): Promise { + updateState({ + waitScreenStatus: SetupStatus.WAIT, + waitScreenMessage: "", + page: Screen.WAIT, + }); + + try { + await instance.get("/setup/shutdown"); + } catch (error) { + console.error(`shutdown request failed: ${error}`); + showError( + "shutdown request failed - but that can also happen when shutdown happened", + updateState, + ); + } +} + +function getInitialPage( + setupPhase: SetupPhase, + updateState: UpdateState, +): Screen { + updateState({ setupPhase }); + switch (setupPhase) { + case SetupPhase.RECOVERY: + case SetupPhase.UPDATE: + return Screen.RECOVERY; + case SetupPhase.MIGRATION: + return Screen.MIGRATION; + case SetupPhase.SETUP: + return Screen.SETUP; + default: + showError("unknown setup phase on init", updateState); + return Screen.WAIT; + } +} + +async function showSyncScreen( + updateState: UpdateState, + navigate: NavigateFunction, +): Promise { + try { + const resp = await instance.post("/setup/setup-sync-info", {}); + updateState({ + syncData: resp.data, + page: Screen.SYNC, + }); + } catch (err) { + const error = err as { response: { status: number } }; + if ( + [HttpStatusCode.Unauthorized, HttpStatusCode.Forbidden].includes( + error.response.status, + ) + ) { + navigate("/login?back=/setup"); + } else { + console.error(`request for sync failed: ${error.response.status}`); + } + } +} diff --git a/src/react-app-env.d.ts b/src/react-app-env.d.ts new file mode 100644 index 0000000..6431bc5 --- /dev/null +++ b/src/react-app-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/src/setupTests.ts b/src/setupTests.ts new file mode 100644 index 0000000..ef5c189 --- /dev/null +++ b/src/setupTests.ts @@ -0,0 +1,10 @@ +// jest-dom adds custom jest matchers for asserting on DOM nodes. +// allows you to do things like: +// expect(element).toHaveTextContent(/react/i) +// learn more: https://github.com/testing-library/jest-dom +// msw server +import "./testServer"; +import "@testing-library/jest-dom"; +import ResizeObserver from "resize-observer-polyfill"; + +vi.stubGlobal("ResizeObserver", ResizeObserver); diff --git a/src/testServer.ts b/src/testServer.ts new file mode 100644 index 0000000..3c60339 --- /dev/null +++ b/src/testServer.ts @@ -0,0 +1,19 @@ +import { HttpResponse, http } from "msw"; +import { setupServer } from "msw/node"; + +const server = setupServer( + // Catch-all for unhandled requests + http.get("*", ({ request }) => { + console.error(`Add request handler for ${request.url.toString()}`); + return HttpResponse.json( + { error: "Missing request handler." }, + { status: 500 }, + ); + }), +); + +beforeAll(() => server.listen()); +afterAll(() => server.close()); +afterEach(() => server.resetHandlers()); + +export { server, http, HttpResponse }; diff --git a/src/utils/api-base.ts b/src/utils/api-base.ts new file mode 100644 index 0000000..4e2626f --- /dev/null +++ b/src/utils/api-base.ts @@ -0,0 +1,11 @@ +/** + * Detect the API base URL depending on deployment context. + * - nginx (same-origin): relative "/api" + * - IPFS gateway (cross-origin): absolute "https:///api" + */ +export function getApiBaseUrl(): string { + if (window.location.pathname.startsWith("/ipfs/")) { + return `https://${window.location.hostname}/api`; + } + return "/api"; +} diff --git a/src/utils/availableApps.ts b/src/utils/availableApps.ts new file mode 100644 index 0000000..ece1d65 --- /dev/null +++ b/src/utils/availableApps.ts @@ -0,0 +1,66 @@ +import type { App } from "@/models/app.model"; +import Electrs from "@/pages/Apps/customApps/Electrs"; + +export const availableApps: { [name: string]: App } = { + "glc-rpc-explorer": { // RASPIBLESK_GLC_RPC_EXPLORER_PATCH + id: "glc-rpc-explorer", + name: "GLC RPC Explorer", + author: "glcoin", + repository: "https://forge.618.ch/glcoin/glc-rpc-explorer", + }, + rtl: { + id: "rtl", + name: "Ride the Lightning", + author: "Shahana Farooqui", + repository: "https://github.com/Ride-The-Lightning/RTL", + }, + specter: { + id: "specter", + name: "Specter", + author: "Specter Solutions", + repository: "https://github.com/cryptoadvance/specter-desktop", + }, + btcpayserver: { + id: "btcpayserver", + name: "BTCPay Server", + author: "BTCPay Server", + repository: "https://github.com/btcpayserver/btcpayserver", + }, + lnbits: { + id: "lnbits", + name: "LNbits", + author: "arcbtc", + repository: "https://github.com/lnbits/lnbits", + }, + mempool: { + id: "mempool", + name: "Mempool.space", + author: "The Mempool Open Source Project", + repository: "https://github.com/mempool/mempool", + }, + thunderhub: { + id: "thunderhub", + name: "Thunderhub", + author: "apotdevin", + repository: "https://github.com/apotdevin/thunderhub", + }, + jam: { + id: "jam", + name: "Jam", + author: "Jam Team", + repository: "https://github.com/joinmarket-webui/jam", + }, + electrs: { + id: "electrs", + name: "ElectRs", + author: "romanz", + repository: "https://github.com/romanz/electrs", + customComponent: Electrs, + }, + albyhub: { + id: "albyhub", + name: "Alby Hub", + author: "Alby", + repository: "https://github.com/getAlby/hub", + }, +}; diff --git a/src/utils/checkError.ts b/src/utils/checkError.ts new file mode 100644 index 0000000..743c6ad --- /dev/null +++ b/src/utils/checkError.ts @@ -0,0 +1,39 @@ +import type { AxiosError } from "axios"; +import { t } from "i18next"; + +export interface ApiError { + detail: string | ApiErrorDetails | ApiErrorDetails[]; +} + +export interface ApiErrorDetails { + loc: string[]; + msg: string; + type: string; + ctx: unknown; +} + +/** + * Checks for the error message. Inconsistency in getting the actual error will be fixed with + * https://github.com/fusion44/blitz_api/issues/123 + * @returns The error with the translated prefix "An error occurred" (error text not yet translated) + */ +export function checkError(err: AxiosError): string { + const responseData = err.response?.data; + + if (typeof responseData?.detail === "string") { + return `${t("login.error")}: ${responseData.detail}`; + } + + if (Array.isArray(responseData?.detail)) { + return `${t("login.error")}: ${responseData?.detail[0].msg}`; + } + + if (typeof responseData?.detail?.msg === "string") { + return `${t("login.error")}: ${responseData.detail.msg}`; + } + + return `${t("login.error")}: ${t("login.unknown_error", { + code: err.response?.status, + statusText: err.response?.statusText, + })}`; +} diff --git a/src/utils/format.ts b/src/utils/format.ts new file mode 100644 index 0000000..932c171 --- /dev/null +++ b/src/utils/format.ts @@ -0,0 +1,79 @@ +import { Unit } from "@/context/app-context"; + +export const GSAT_DENOMINATOR = 100_000_000; +export const NUM_LOCALE = "en-US"; + +export function convertGsatToGlc(sat: number | null): number | null { + return sat ? sat / GSAT_DENOMINATOR : null; +} + +export function convertGlcToGsat(glc: number): number { + return glc * GSAT_DENOMINATOR; +} + +export function convertMSatToGsat(mSat: number | null): number | null { + return mSat ? mSat / 1000 : null; +} + +export function convertMSatToGlc(mSat: number | null): number | null { + return convertGsatToGlc(mSat ? mSat / 1000 : null); +} + +export function convertToString(unit: Unit, num: number | null): string { + if (num === null) { + return "-"; + } + if (unit === Unit.GSAT) { + // remove decimals from sat & convert + return (+num.toFixed(0)).toLocaleString(NUM_LOCALE); + } + return num.toFixed(8).toString(); +} + +/** + * Formats a normal string like "12345" to a formatted one => "123,456" + * @param value the value to be formatted + * @param unit The unit (GLC / GSAT) , see also {@link Unit} + * @returns the formatted value + */ +// TODO: add test for this function to format.test.ts +export function formatAmount(value: string, unit: Unit): string { + // replace every character except numbers and separators + let formattedValue = value.replace(/[^0-9.,]/, ""); + + if (unit === Unit.GSAT) { + // remove all separators to format correctly + formattedValue = formattedValue.replace(/,|\./g, ""); + if (formattedValue) { + formattedValue = new Intl.NumberFormat(NUM_LOCALE).format( + +formattedValue, + ); + } + } else { + // remove commas + formattedValue = formattedValue.replace(/,/g, ""); + // replace ".." with "." + formattedValue = formattedValue.replace(/\.\./g, "."); + const output = formattedValue.split("."); + // limit to max 8 decimal places + if (output[1]?.length > 8) { + output[1] = output[1].substring(0, 8); + } + // formatting which respects separator + // makes either "x.y" or "y" + formattedValue = + output.shift() + (output.length ? `.${output.join("")}` : ""); + } + return formattedValue; +} + +/** + * Removes the commas from a string number and returns the number representation of that string + * e.g. "123,456" => 123456 + * @param value the value to convert e.g. "123,456" + * @returns the converted number, e.g. 123456 + */ +export function stringToNumber(value: string): number { + const valueCopy = value.replace(/,/g, ""); + return +valueCopy; +} diff --git a/src/utils/index.ts b/src/utils/index.ts new file mode 100644 index 0000000..28bc635 --- /dev/null +++ b/src/utils/index.ts @@ -0,0 +1,91 @@ +import type { AppStatus } from "@/models/app-status"; +import type { TokenPayload } from "@/models/token"; + +export const ACCESS_TOKEN = "access_token"; +// refresh 10min before expiry +export const REFRESH_TIME = (expiry: number) => expiry - Date.now() - 600_000; + +const createModalRoot = () => { + const modalRoot = document.createElement("div"); + modalRoot.setAttribute("id", "modal-root"); + document.body.appendChild(modalRoot); + return modalRoot; +}; + +export const SETTINGS_KEY = "settings"; +export const MODAL_ROOT = + document.getElementById("modal-root") || createModalRoot(); + +export interface SavedSettings { + lang: string; +} + +/** + * merges previous with new settings and saves it to local storage + */ +export function saveSettings(settings: Partial): void { + const prevSettings = retrieveSettings(); + + const newSettings = { + ...prevSettings, + ...settings, + }; + localStorage.setItem(SETTINGS_KEY, JSON.stringify(newSettings)); +} + +/** + * Retrieves settings from local storage and parses them into a {@link SavedSettings} object. + * @returns saved settings if they exist or null + */ +export function retrieveSettings(): SavedSettings | null { + const settingString = localStorage.getItem(SETTINGS_KEY); + if (settingString) { + return JSON.parse(settingString); + } + + return null; +} + +/** + * Checks if any prop value is null or undefined + * @param props the props object + * @returns if any property in the props object is null or undefined + */ +export function checkPropsUndefined(props: object): boolean { + let someUndefined = false; + Object.values(props).forEach((prop) => { + if (prop === null || prop === undefined) { + someUndefined = true; + } + }); + return someUndefined; +} + +export function parseJwt(token: string): TokenPayload { + // 1st part is header, 2nd part is payload, 3rd is signature + const payload = token.split(".")[1]; + return JSON.parse(atob(payload)); +} + +export function enableGutter(): void { + document.documentElement.classList.add("scrollbar-stable"); +} + +export function disableGutter(): void { + document.documentElement.classList.remove("scrollbar-stable"); +} + +export function setWindowAlias(nodeAlias: string | null): void { + if (!nodeAlias) { + document.title = "RaspiBlesk"; + } else { + document.title = `RaspiBlesk - ${nodeAlias}`; + } +} + +export function getHrefFromApp(app: AppStatus) { + const authUrl = app.auth_method?.startsWith("/") ? app.auth_method : ""; + return window.location.hostname.endsWith(".onion") + ? `https://${app.hidden_service}${authUrl}` // add https prefix to hidden service to use HTTP/2 and make it a absolute link instead of relative + : `${app.address}${authUrl}`; // address always has the "http(s)" prefix included +} diff --git a/src/utils/interceptor.ts b/src/utils/interceptor.ts new file mode 100644 index 0000000..512e697 --- /dev/null +++ b/src/utils/interceptor.ts @@ -0,0 +1,13 @@ +import axios from "axios"; +import { ACCESS_TOKEN } from "./index"; +import { getApiBaseUrl } from "./api-base"; + +export const instance = axios.create({ baseURL: getApiBaseUrl() }); + +instance.interceptors.request.use((config) => { + const token = localStorage.getItem(ACCESS_TOKEN); + if (token) { + config.headers.Authorization = `Bearer ${token}`; + } + return config; +}); diff --git a/src/utils/test-utils.tsx b/src/utils/test-utils.tsx new file mode 100644 index 0000000..29294a2 --- /dev/null +++ b/src/utils/test-utils.tsx @@ -0,0 +1,76 @@ +import { type RenderOptions, render } from "@testing-library/react"; +import type { FC, PropsWithChildren, ReactElement } from "react"; +import { I18nextProvider } from "react-i18next"; +import { BrowserRouter } from "react-router"; +import { + AppContext, + type AppContextType, + appContextDefault, +} from "@/context/app-context"; +import { + SSEContext, + type SSEContextType, + sseContextDefault, +} from "@/context/sse-context"; +import i18n from "@/i18n/test_config"; + +type Props = { + sseProps: SSEContextType; + appProps: AppContextType; +}; + +const AllTheProviders: FC> = ({ + children, + appProps, + sseProps, +}) => { + return ( + + + + {children} + + + + ); +}; + +const customRender = ( + ui: ReactElement, + options?: Omit & { + providerOptions?: { + sseProps?: Partial; + appProps?: Partial; + }; + }, +) => + render(ui, { + // biome-ignore lint/suspicious/noExplicitAny: value is expected to exist at this point + wrapper: (props: any) => ( + + ), + ...options, + }); + +export * from "@testing-library/react"; +export { customRender as render }; + +export const mockedDisclosure = { + isOpen: true, + onOpen: vi.fn(), + onClose: vi.fn(), + onOpenChange: vi.fn(), + isControlled: false, + getButtonProps: vi.fn(), + getDisclosureProps: vi.fn(), +}; diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..fc2c07b --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,32 @@ +{ + "compilerOptions": { + "target": "ES2022", + "lib": ["ES2022", "DOM", "DOM.Iterable"], + "types": ["vite/client", "vite-plugin-svgr/client", "vitest/globals"], + "allowJs": false, + "skipLibCheck": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "noFallthroughCasesInSwitch": true, + "module": "ESNext", + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "moduleDetection": "force", + "noEmit": true, + "jsx": "react-jsx", + + "resolveJsonModule": true, + "isolatedModules": true, + "baseUrl": ".", + "paths": { + "test-utils": ["src/utils/test-utils"], + "@/*": ["src/*"] + } + }, + "include": ["src"] +} diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..311dd49 --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,56 @@ +/// +import react from '@vitejs/plugin-react'; +import { defineConfig } from 'vite'; +import svgr from 'vite-plugin-svgr'; +import viteTsconfigPaths from 'vite-tsconfig-paths'; +import tailwindcss from "@tailwindcss/vite" + +const BACKEND_SERVER = 'http://localhost:8000'; + +// https://vitejs.dev/config/ +export default defineConfig({ + base: './', + plugins: [react(), viteTsconfigPaths(), svgr(), tailwindcss()], + build: { + outDir: 'build', + rollupOptions: { + output: { + // see https://github.com/vitejs/vite/issues/11804#issuecomment-2009619365 + chunkFileNames: 'chunk-[hash].js', + }, + }, + }, + resolve: { + alias: { + '@': '/src', + }, + }, + server: { + port: 3000, + proxy: { + '/api': { + target: BACKEND_SERVER, + changeOrigin: true, + secure: false, + }, + }, + }, + test: { + globals: true, + environment: 'jsdom', + setupFiles: ['./src/setupTests.ts'], + coverage: { + reporter: ['text', 'html'], + all: true, + include: ['src'], + exclude: [ + 'src/setupTests.ts', + '**/*.test.ts', + '**/*.test.tsx', + '**/*.d.ts', + 'src/testServer.ts', + 'src/utils/test-utils.tsx', + ], + }, + }, +});