Initial Commit

This commit is contained in:
2025-09-07 01:46:37 -04:00
commit 66986cca51
272 changed files with 15331 additions and 0 deletions

24
.gitignore vendored Normal file
View File

@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

3
.npmrc Normal file
View File

@@ -0,0 +1,3 @@
save-exact=true
package-lock=false
@techniker-me:registry=https://registry-node.techniker.me

1
.nvmrc Normal file
View File

@@ -0,0 +1 @@
20

12
.prettierrc Normal file
View File

@@ -0,0 +1,12 @@
{
"arrowParens": "avoid",
"bracketSameLine": true,
"bracketSpacing": false,
"printWidth": 160,
"semi": true,
"singleAttributePerLine": false,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "none",
"useTabs": false
}

28
README.md Normal file
View File

@@ -0,0 +1,28 @@
# Phenix Web Control Center
## Setup
```
nvm use
npm i
```
## Development
```
npm run start
```
## Build
### Development
```
npm run build
```
### Production
```
npm run build:prod
```

906
bun.lock Normal file
View File

@@ -0,0 +1,906 @@
{
"lockfileVersion": 1,
"workspaces": {
"": {
"name": "webcontrolcenter-zinn-2",
"dependencies": {
"@phenixrts/sdk": "2025.2.2",
"@reduxjs/toolkit": "2.9.0",
"@techniker-me/pcast-api": "2025.1.5",
"@techniker-me/tools": "2025.0.16",
"moment": "2.30.1",
"phenix-web-proto": "2020.0.3",
"react": "19.1.1",
"react-dom": "19.1.1",
"react-redux": "9.2.0",
"react-router-dom": "7.8.2",
"styled-components": "6.1.19",
"uuid": "11.1.0",
},
"devDependencies": {
"@eslint/js": "9.34.0",
"@fortawesome/fontawesome-svg-core": "7.0.1",
"@fortawesome/free-regular-svg-icons": "7.0.1",
"@fortawesome/free-solid-svg-icons": "7.0.1",
"@fortawesome/react-fontawesome": "3.0.2",
"@types/node": "24.3.0",
"@types/react": "19.1.12",
"@types/react-dom": "19.1.9",
"@vitejs/plugin-react-swc": "4.0.1",
"babel-plugin-styled-components": "2.1.4",
"babel-plugin-transform-amd-to-commonjs": "1.6.0",
"eslint": "9.34.0",
"eslint-plugin-react": "7.37.5",
"eslint-plugin-react-hooks": "5.2.0",
"eslint-plugin-react-refresh": "0.4.20",
"globals": "16.3.0",
"prettier": "3.6.2",
"react-datepicker": "8.7.0",
"react-toastify": "11.0.5",
"typescript": "5.9.2",
"typescript-eslint": "8.42.0",
"typescript-plugin-styled-components": "3.0.0",
"vite": "7.1.4",
"vite-plugin-babel": "1.3.2",
"vite-plugin-commonjs": "0.10.4",
},
},
},
"packages": {
"@babel/code-frame": ["@babel/code-frame@7.27.1", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg=="],
"@babel/compat-data": ["@babel/compat-data@7.28.4", "", {}, "sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw=="],
"@babel/core": ["@babel/core@7.28.4", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.3", "@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-module-transforms": "^7.28.3", "@babel/helpers": "^7.28.4", "@babel/parser": "^7.28.4", "@babel/template": "^7.27.2", "@babel/traverse": "^7.28.4", "@babel/types": "^7.28.4", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA=="],
"@babel/generator": ["@babel/generator@7.28.3", "", { "dependencies": { "@babel/parser": "^7.28.3", "@babel/types": "^7.28.2", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw=="],
"@babel/helper-annotate-as-pure": ["@babel/helper-annotate-as-pure@7.27.3", "", { "dependencies": { "@babel/types": "^7.27.3" } }, "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg=="],
"@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.27.2", "", { "dependencies": { "@babel/compat-data": "^7.27.2", "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ=="],
"@babel/helper-globals": ["@babel/helper-globals@7.28.0", "", {}, "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw=="],
"@babel/helper-module-imports": ["@babel/helper-module-imports@7.27.1", "", { "dependencies": { "@babel/traverse": "^7.27.1", "@babel/types": "^7.27.1" } }, "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w=="],
"@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.28.3", "", { "dependencies": { "@babel/helper-module-imports": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1", "@babel/traverse": "^7.28.3" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw=="],
"@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.27.1", "", {}, "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw=="],
"@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="],
"@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.27.1", "", {}, "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="],
"@babel/helper-validator-option": ["@babel/helper-validator-option@7.27.1", "", {}, "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg=="],
"@babel/helpers": ["@babel/helpers@7.28.4", "", { "dependencies": { "@babel/template": "^7.27.2", "@babel/types": "^7.28.4" } }, "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w=="],
"@babel/parser": ["@babel/parser@7.28.4", "", { "dependencies": { "@babel/types": "^7.28.4" }, "bin": "./bin/babel-parser.js" }, "sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg=="],
"@babel/plugin-syntax-jsx": ["@babel/plugin-syntax-jsx@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w=="],
"@babel/template": ["@babel/template@7.27.2", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/parser": "^7.27.2", "@babel/types": "^7.27.1" } }, "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw=="],
"@babel/traverse": ["@babel/traverse@7.28.4", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.3", "@babel/helper-globals": "^7.28.0", "@babel/parser": "^7.28.4", "@babel/template": "^7.27.2", "@babel/types": "^7.28.4", "debug": "^4.3.1" } }, "sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ=="],
"@babel/types": ["@babel/types@7.28.4", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q=="],
"@emotion/is-prop-valid": ["@emotion/is-prop-valid@1.2.2", "", { "dependencies": { "@emotion/memoize": "^0.8.1" } }, "sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw=="],
"@emotion/memoize": ["@emotion/memoize@0.8.1", "", {}, "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA=="],
"@emotion/unitless": ["@emotion/unitless@0.8.1", "", {}, "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ=="],
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.9", "", { "os": "aix", "cpu": "ppc64" }, "sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA=="],
"@esbuild/android-arm": ["@esbuild/android-arm@0.25.9", "", { "os": "android", "cpu": "arm" }, "sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ=="],
"@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.9", "", { "os": "android", "cpu": "arm64" }, "sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg=="],
"@esbuild/android-x64": ["@esbuild/android-x64@0.25.9", "", { "os": "android", "cpu": "x64" }, "sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw=="],
"@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.9", "", { "os": "darwin", "cpu": "arm64" }, "sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg=="],
"@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.9", "", { "os": "darwin", "cpu": "x64" }, "sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ=="],
"@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.9", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q=="],
"@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.9", "", { "os": "freebsd", "cpu": "x64" }, "sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg=="],
"@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.9", "", { "os": "linux", "cpu": "arm" }, "sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw=="],
"@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.9", "", { "os": "linux", "cpu": "arm64" }, "sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw=="],
"@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.9", "", { "os": "linux", "cpu": "ia32" }, "sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A=="],
"@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.9", "", { "os": "linux", "cpu": "none" }, "sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ=="],
"@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.9", "", { "os": "linux", "cpu": "none" }, "sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA=="],
"@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.9", "", { "os": "linux", "cpu": "ppc64" }, "sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w=="],
"@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.9", "", { "os": "linux", "cpu": "none" }, "sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg=="],
"@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.9", "", { "os": "linux", "cpu": "s390x" }, "sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA=="],
"@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.9", "", { "os": "linux", "cpu": "x64" }, "sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg=="],
"@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.9", "", { "os": "none", "cpu": "arm64" }, "sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q=="],
"@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.9", "", { "os": "none", "cpu": "x64" }, "sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g=="],
"@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.9", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ=="],
"@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.9", "", { "os": "openbsd", "cpu": "x64" }, "sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA=="],
"@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.9", "", { "os": "none", "cpu": "arm64" }, "sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg=="],
"@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.9", "", { "os": "sunos", "cpu": "x64" }, "sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw=="],
"@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.9", "", { "os": "win32", "cpu": "arm64" }, "sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ=="],
"@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.9", "", { "os": "win32", "cpu": "ia32" }, "sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww=="],
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.9", "", { "os": "win32", "cpu": "x64" }, "sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ=="],
"@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.8.0", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-MJQFqrZgcW0UNYLGOuQpey/oTN59vyWwplvCGZztn1cKz9agZPPYpJB7h2OMmuu7VLqkvEjN8feFZJmxNF9D+Q=="],
"@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.1", "", {}, "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ=="],
"@eslint/config-array": ["@eslint/config-array@0.21.0", "", { "dependencies": { "@eslint/object-schema": "^2.1.6", "debug": "^4.3.1", "minimatch": "^3.1.2" } }, "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ=="],
"@eslint/config-helpers": ["@eslint/config-helpers@0.3.1", "", {}, "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA=="],
"@eslint/core": ["@eslint/core@0.15.2", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg=="],
"@eslint/eslintrc": ["@eslint/eslintrc@3.3.1", "", { "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" } }, "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ=="],
"@eslint/js": ["@eslint/js@9.34.0", "", {}, "sha512-EoyvqQnBNsV1CWaEJ559rxXL4c8V92gxirbawSmVUOWXlsRxxQXl6LmCpdUblgxgSkDIqKnhzba2SjRTI/A5Rw=="],
"@eslint/object-schema": ["@eslint/object-schema@2.1.6", "", {}, "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA=="],
"@eslint/plugin-kit": ["@eslint/plugin-kit@0.3.5", "", { "dependencies": { "@eslint/core": "^0.15.2", "levn": "^0.4.1" } }, "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w=="],
"@floating-ui/core": ["@floating-ui/core@1.7.3", "", { "dependencies": { "@floating-ui/utils": "^0.2.10" } }, "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w=="],
"@floating-ui/dom": ["@floating-ui/dom@1.7.4", "", { "dependencies": { "@floating-ui/core": "^1.7.3", "@floating-ui/utils": "^0.2.10" } }, "sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA=="],
"@floating-ui/react": ["@floating-ui/react@0.27.16", "", { "dependencies": { "@floating-ui/react-dom": "^2.1.6", "@floating-ui/utils": "^0.2.10", "tabbable": "^6.0.0" }, "peerDependencies": { "react": ">=17.0.0", "react-dom": ">=17.0.0" } }, "sha512-9O8N4SeG2z++TSM8QA/KTeKFBVCNEz/AGS7gWPJf6KFRzmRWixFRnCnkPHRDwSVZW6QPDO6uT0P2SpWNKCc9/g=="],
"@floating-ui/react-dom": ["@floating-ui/react-dom@2.1.6", "", { "dependencies": { "@floating-ui/dom": "^1.7.4" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-4JX6rEatQEvlmgU80wZyq9RT96HZJa88q8hp0pBd+LrczeDI4o6uA2M+uvxngVHo4Ihr8uibXxH6+70zhAFrVw=="],
"@floating-ui/utils": ["@floating-ui/utils@0.2.10", "", {}, "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ=="],
"@fortawesome/fontawesome-common-types": ["@fortawesome/fontawesome-common-types@7.0.1", "", {}, "sha512-0VpNtO5cNe1/HQWMkl4OdncYK/mv9hnBte0Ew0n6DMzmo3Q3WzDFABHm6LeNTipt5zAyhQ6Ugjiu8aLaEjh1gg=="],
"@fortawesome/fontawesome-svg-core": ["@fortawesome/fontawesome-svg-core@7.0.1", "", { "dependencies": { "@fortawesome/fontawesome-common-types": "7.0.1" } }, "sha512-x0cR55ILVqFpUioSMf6ebpRCMXMcheGN743P05W2RB5uCNpJUqWIqW66Lap8PfL/lngvjTbZj0BNSUweIr/fHQ=="],
"@fortawesome/free-regular-svg-icons": ["@fortawesome/free-regular-svg-icons@7.0.1", "", { "dependencies": { "@fortawesome/fontawesome-common-types": "7.0.1" } }, "sha512-4V9fHbHjcx9Qu4O99AM5B4zuEDfB4zajk1I77hEzOxPN00f8g3484Aeq6WpfFcmookvjLE3Pr71Dhf/lqw7tbA=="],
"@fortawesome/free-solid-svg-icons": ["@fortawesome/free-solid-svg-icons@7.0.1", "", { "dependencies": { "@fortawesome/fontawesome-common-types": "7.0.1" } }, "sha512-esKuSrl1WMOTMDLNt38i16VfLe/gRZt2ZAJ3Yw7slfs7sj583MKqNFqO57zmhknk1Sya6f9Wys89aCzIJkcqlg=="],
"@fortawesome/react-fontawesome": ["@fortawesome/react-fontawesome@3.0.2", "", { "peerDependencies": { "@fortawesome/fontawesome-svg-core": "~6 || ~7", "react": "^18.0.0 || ^19.0.0" } }, "sha512-cmp/nT0pPC7HUALF8uc3+D5ECwEBWxYQbOIHwtGUWEu72sWtZc26k5onr920HWOViF0nYaC+Qzz6Ln56SQcaVg=="],
"@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="],
"@humanfs/node": ["@humanfs/node@0.16.7", "", { "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.4.0" } }, "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ=="],
"@humanwhocodes/module-importer": ["@humanwhocodes/module-importer@1.0.1", "", {}, "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA=="],
"@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="],
"@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
"@jridgewell/remapping": ["@jridgewell/remapping@2.3.5", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="],
"@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
"@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.30", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q=="],
"@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="],
"@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="],
"@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="],
"@phenixrts/sdk": ["@phenixrts/sdk@2025.2.2", "", {}, "sha512-thxg7IE3a8qE/hk1KM6zMZcZXww54/Hy8UdR4C4J43itp4r+JfD3jKLMqrHajPazbz7IaqX8ihiMDgrmRBGI7w=="],
"@reduxjs/toolkit": ["@reduxjs/toolkit@2.9.0", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "@standard-schema/utils": "^0.3.0", "immer": "^10.0.3", "redux": "^5.0.1", "redux-thunk": "^3.1.0", "reselect": "^5.1.0" }, "peerDependencies": { "react": "^16.9.0 || ^17.0.0 || ^18 || ^19", "react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0" }, "optionalPeers": ["react", "react-redux"] }, "sha512-fSfQlSRu9Z5yBkvsNhYF2rPS8cGXn/TZVrlwN1948QyZ8xMZ0JvP50S2acZNaf+o63u6aEeMjipFyksjIcWrog=="],
"@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-beta.32", "", {}, "sha512-QReCdvxiUZAPkvp1xpAg62IeNzykOFA6syH2CnClif4YmALN1XKpB39XneL80008UbtMShthSVDKmrx05N1q/g=="],
"@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.50.0", "", { "os": "android", "cpu": "arm" }, "sha512-lVgpeQyy4fWN5QYebtW4buT/4kn4p4IJ+kDNB4uYNT5b8c8DLJDg6titg20NIg7E8RWwdWZORW6vUFfrLyG3KQ=="],
"@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.50.0", "", { "os": "android", "cpu": "arm64" }, "sha512-2O73dR4Dc9bp+wSYhviP6sDziurB5/HCym7xILKifWdE9UsOe2FtNcM+I4xZjKrfLJnq5UR8k9riB87gauiQtw=="],
"@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.50.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-vwSXQN8T4sKf1RHr1F0s98Pf8UPz7pS6P3LG9NSmuw0TVh7EmaE+5Ny7hJOZ0M2yuTctEsHHRTMi2wuHkdS6Hg=="],
"@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.50.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-cQp/WG8HE7BCGyFVuzUg0FNmupxC+EPZEwWu2FCGGw5WDT1o2/YlENbm5e9SMvfDFR6FRhVCBePLqj0o8MN7Vw=="],
"@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.50.0", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-UR1uTJFU/p801DvvBbtDD7z9mQL8J80xB0bR7DqW7UGQHRm/OaKzp4is7sQSdbt2pjjSS72eAtRh43hNduTnnQ=="],
"@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.50.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-G/DKyS6PK0dD0+VEzH/6n/hWDNPDZSMBmqsElWnCRGrYOb2jC0VSupp7UAHHQ4+QILwkxSMaYIbQ72dktp8pKA=="],
"@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.50.0", "", { "os": "linux", "cpu": "arm" }, "sha512-u72Mzc6jyJwKjJbZZcIYmd9bumJu7KNmHYdue43vT1rXPm2rITwmPWF0mmPzLm9/vJWxIRbao/jrQmxTO0Sm9w=="],
"@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.50.0", "", { "os": "linux", "cpu": "arm" }, "sha512-S4UefYdV0tnynDJV1mdkNawp0E5Qm2MtSs330IyHgaccOFrwqsvgigUD29uT+B/70PDY1eQ3t40+xf6wIvXJyg=="],
"@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.50.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-1EhkSvUQXJsIhk4msxP5nNAUWoB4MFDHhtc4gAYvnqoHlaL9V3F37pNHabndawsfy/Tp7BPiy/aSa6XBYbaD1g=="],
"@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.50.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-EtBDIZuDtVg75xIPIK1l5vCXNNCIRM0OBPUG+tbApDuJAy9mKago6QxX+tfMzbCI6tXEhMuZuN1+CU8iDW+0UQ=="],
"@rollup/rollup-linux-loongarch64-gnu": ["@rollup/rollup-linux-loongarch64-gnu@4.50.0", "", { "os": "linux", "cpu": "none" }, "sha512-BGYSwJdMP0hT5CCmljuSNx7+k+0upweM2M4YGfFBjnFSZMHOLYR0gEEj/dxyYJ6Zc6AiSeaBY8dWOa11GF/ppQ=="],
"@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.50.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-I1gSMzkVe1KzAxKAroCJL30hA4DqSi+wGc5gviD0y3IL/VkvcnAqwBf4RHXHyvH66YVHxpKO8ojrgc4SrWAnLg=="],
"@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.50.0", "", { "os": "linux", "cpu": "none" }, "sha512-bSbWlY3jZo7molh4tc5dKfeSxkqnf48UsLqYbUhnkdnfgZjgufLS/NTA8PcP/dnvct5CCdNkABJ56CbclMRYCA=="],
"@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.50.0", "", { "os": "linux", "cpu": "none" }, "sha512-LSXSGumSURzEQLT2e4sFqFOv3LWZsEF8FK7AAv9zHZNDdMnUPYH3t8ZlaeYYZyTXnsob3htwTKeWtBIkPV27iQ=="],
"@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.50.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-CxRKyakfDrsLXiCyucVfVWVoaPA4oFSpPpDwlMcDFQvrv3XY6KEzMtMZrA+e/goC8xxp2WSOxHQubP8fPmmjOQ=="],
"@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.50.0", "", { "os": "linux", "cpu": "x64" }, "sha512-8PrJJA7/VU8ToHVEPu14FzuSAqVKyo5gg/J8xUerMbyNkWkO9j2ExBho/68RnJsMGNJq4zH114iAttgm7BZVkA=="],
"@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.50.0", "", { "os": "linux", "cpu": "x64" }, "sha512-SkE6YQp+CzpyOrbw7Oc4MgXFvTw2UIBElvAvLCo230pyxOLmYwRPwZ/L5lBe/VW/qT1ZgND9wJfOsdy0XptRvw=="],
"@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.50.0", "", { "os": "none", "cpu": "arm64" }, "sha512-PZkNLPfvXeIOgJWA804zjSFH7fARBBCpCXxgkGDRjjAhRLOR8o0IGS01ykh5GYfod4c2yiiREuDM8iZ+pVsT+Q=="],
"@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.50.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-q7cIIdFvWQoaCbLDUyUc8YfR3Jh2xx3unO8Dn6/TTogKjfwrax9SyfmGGK6cQhKtjePI7jRfd7iRYcxYs93esg=="],
"@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.50.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-XzNOVg/YnDOmFdDKcxxK410PrcbcqZkBmz+0FicpW5jtjKQxcW1BZJEQOF0NJa6JO7CZhett8GEtRN/wYLYJuw=="],
"@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.50.0", "", { "os": "win32", "cpu": "x64" }, "sha512-xMmiWRR8sp72Zqwjgtf3QbZfF1wdh8X2ABu3EaozvZcyHJeU0r+XAnXdKgs4cCAp6ORoYoCygipYP1mjmbjrsg=="],
"@standard-schema/spec": ["@standard-schema/spec@1.0.0", "", {}, "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA=="],
"@standard-schema/utils": ["@standard-schema/utils@0.3.0", "", {}, "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g=="],
"@swc/core": ["@swc/core@1.13.5", "", { "dependencies": { "@swc/counter": "^0.1.3", "@swc/types": "^0.1.24" }, "optionalDependencies": { "@swc/core-darwin-arm64": "1.13.5", "@swc/core-darwin-x64": "1.13.5", "@swc/core-linux-arm-gnueabihf": "1.13.5", "@swc/core-linux-arm64-gnu": "1.13.5", "@swc/core-linux-arm64-musl": "1.13.5", "@swc/core-linux-x64-gnu": "1.13.5", "@swc/core-linux-x64-musl": "1.13.5", "@swc/core-win32-arm64-msvc": "1.13.5", "@swc/core-win32-ia32-msvc": "1.13.5", "@swc/core-win32-x64-msvc": "1.13.5" }, "peerDependencies": { "@swc/helpers": ">=0.5.17" }, "optionalPeers": ["@swc/helpers"] }, "sha512-WezcBo8a0Dg2rnR82zhwoR6aRNxeTGfK5QCD6TQ+kg3xx/zNT02s/0o+81h/3zhvFSB24NtqEr8FTw88O5W/JQ=="],
"@swc/core-darwin-arm64": ["@swc/core-darwin-arm64@1.13.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-lKNv7SujeXvKn16gvQqUQI5DdyY8v7xcoO3k06/FJbHJS90zEwZdQiMNRiqpYw/orU543tPaWgz7cIYWhbopiQ=="],
"@swc/core-darwin-x64": ["@swc/core-darwin-x64@1.13.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-ILd38Fg/w23vHb0yVjlWvQBoE37ZJTdlLHa8LRCFDdX4WKfnVBiblsCU9ar4QTMNdeTBEX9iUF4IrbNWhaF1Ng=="],
"@swc/core-linux-arm-gnueabihf": ["@swc/core-linux-arm-gnueabihf@1.13.5", "", { "os": "linux", "cpu": "arm" }, "sha512-Q6eS3Pt8GLkXxqz9TAw+AUk9HpVJt8Uzm54MvPsqp2yuGmY0/sNaPPNVqctCX9fu/Nu8eaWUen0si6iEiCsazQ=="],
"@swc/core-linux-arm64-gnu": ["@swc/core-linux-arm64-gnu@1.13.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-aNDfeN+9af+y+M2MYfxCzCy/VDq7Z5YIbMqRI739o8Ganz6ST+27kjQFd8Y/57JN/hcnUEa9xqdS3XY7WaVtSw=="],
"@swc/core-linux-arm64-musl": ["@swc/core-linux-arm64-musl@1.13.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-9+ZxFN5GJag4CnYnq6apKTnnezpfJhCumyz0504/JbHLo+Ue+ZtJnf3RhyA9W9TINtLE0bC4hKpWi8ZKoETyOQ=="],
"@swc/core-linux-x64-gnu": ["@swc/core-linux-x64-gnu@1.13.5", "", { "os": "linux", "cpu": "x64" }, "sha512-WD530qvHrki8Ywt/PloKUjaRKgstQqNGvmZl54g06kA+hqtSE2FTG9gngXr3UJxYu/cNAjJYiBifm7+w4nbHbA=="],
"@swc/core-linux-x64-musl": ["@swc/core-linux-x64-musl@1.13.5", "", { "os": "linux", "cpu": "x64" }, "sha512-Luj8y4OFYx4DHNQTWjdIuKTq2f5k6uSXICqx+FSabnXptaOBAbJHNbHT/06JZh6NRUouaf0mYXN0mcsqvkhd7Q=="],
"@swc/core-win32-arm64-msvc": ["@swc/core-win32-arm64-msvc@1.13.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-cZ6UpumhF9SDJvv4DA2fo9WIzlNFuKSkZpZmPG1c+4PFSEMy5DFOjBSllCvnqihCabzXzpn6ykCwBmHpy31vQw=="],
"@swc/core-win32-ia32-msvc": ["@swc/core-win32-ia32-msvc@1.13.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-C5Yi/xIikrFUzZcyGj9L3RpKljFvKiDMtyDzPKzlsDrKIw2EYY+bF88gB6oGY5RGmv4DAX8dbnpRAqgFD0FMEw=="],
"@swc/core-win32-x64-msvc": ["@swc/core-win32-x64-msvc@1.13.5", "", { "os": "win32", "cpu": "x64" }, "sha512-YrKdMVxbYmlfybCSbRtrilc6UA8GF5aPmGKBdPvjrarvsmf4i7ZHGCEnLtfOMd3Lwbs2WUZq3WdMbozYeLU93Q=="],
"@swc/counter": ["@swc/counter@0.1.3", "", {}, "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ=="],
"@swc/types": ["@swc/types@0.1.25", "", { "dependencies": { "@swc/counter": "^0.1.3" } }, "sha512-iAoY/qRhNH8a/hBvm3zKj9qQ4oc2+3w1unPJa2XvTK3XjeLXtzcCingVPw/9e5mn1+0yPqxcBGp9Jf0pkfMb1g=="],
"@techniker-me/pcast-api": ["@techniker-me/pcast-api@2025.1.5", "https://registry-node.techniker.me/@techniker-me/pcast-api/-/pcast-api-2025.1.5.tgz", { "dependencies": { "phenix-edge-auth": "1.2.7" } }, "sha512-2e/ufy6rUx4fm9g8RMmzYXLUd+Tq8fQvpTCUQbgf7612u/tAZtmWujs3OUK4QzdIPF1W2GuPPWI3NzObb0paog=="],
"@techniker-me/tools": ["@techniker-me/tools@2025.0.16", "https://registry-node.techniker.me/@techniker-me/tools/-/tools-2025.0.16.tgz", {}, "sha512-Ul2yj1vd4lCO8g7IW2pHkAsdeRVEUMqGpiIvSedCc1joVXEWPbh4GESW83kMHtisjFjjlZIzb3EVlCE0BCiBWQ=="],
"@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
"@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="],
"@types/node": ["@types/node@24.3.0", "", { "dependencies": { "undici-types": "~7.10.0" } }, "sha512-aPTXCrfwnDLj4VvXrm+UUCQjNEvJgNA8s5F1cvwQU+3KNltTOkBm1j30uNLyqqPNe7gE3KFzImYoZEfLhp4Yow=="],
"@types/react": ["@types/react@19.1.12", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-cMoR+FoAf/Jyq6+Df2/Z41jISvGZZ2eTlnsaJRptmZ76Caldwy1odD4xTr/gNV9VLj0AWgg/nmkevIyUfIIq5w=="],
"@types/react-dom": ["@types/react-dom@19.1.9", "", { "peerDependencies": { "@types/react": "^19.0.0" } }, "sha512-qXRuZaOsAdXKFyOhRBg6Lqqc0yay13vN7KrIg4L7N4aaHN68ma9OK3NE1BoDFgFOTfM7zg+3/8+2n8rLUH3OKQ=="],
"@types/stylis": ["@types/stylis@4.2.5", "", {}, "sha512-1Xve+NMN7FWjY14vLoY5tL3BVEQ/n42YLwaqJIPYhotZ9uBHt87VceMwWQpzmdEt2TNXIorIFG+YeCUUW7RInw=="],
"@types/use-sync-external-store": ["@types/use-sync-external-store@0.0.6", "", {}, "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg=="],
"@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.42.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.42.0", "@typescript-eslint/type-utils": "8.42.0", "@typescript-eslint/utils": "8.42.0", "@typescript-eslint/visitor-keys": "8.42.0", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.42.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-Aq2dPqsQkxHOLfb2OPv43RnIvfj05nw8v/6n3B2NABIPpHnjQnaLo9QGMTvml+tv4korl/Cjfrb/BYhoL8UUTQ=="],
"@typescript-eslint/parser": ["@typescript-eslint/parser@8.42.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.42.0", "@typescript-eslint/types": "8.42.0", "@typescript-eslint/typescript-estree": "8.42.0", "@typescript-eslint/visitor-keys": "8.42.0", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-r1XG74QgShUgXph1BYseJ+KZd17bKQib/yF3SR+demvytiRXrwd12Blnz5eYGm8tXaeRdd4x88MlfwldHoudGg=="],
"@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.42.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.42.0", "@typescript-eslint/types": "^8.42.0", "debug": "^4.3.4" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-vfVpLHAhbPjilrabtOSNcUDmBboQNrJUiNAGoImkZKnMjs2TIcWG33s4Ds0wY3/50aZmTMqJa6PiwkwezaAklg=="],
"@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.42.0", "", { "dependencies": { "@typescript-eslint/types": "8.42.0", "@typescript-eslint/visitor-keys": "8.42.0" } }, "sha512-51+x9o78NBAVgQzOPd17DkNTnIzJ8T/O2dmMBLoK9qbY0Gm52XJcdJcCl18ExBMiHo6jPMErUQWUv5RLE51zJw=="],
"@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.42.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-kHeFUOdwAJfUmYKjR3CLgZSglGHjbNTi1H8sTYRYV2xX6eNz4RyJ2LIgsDLKf8Yi0/GL1WZAC/DgZBeBft8QAQ=="],
"@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.42.0", "", { "dependencies": { "@typescript-eslint/types": "8.42.0", "@typescript-eslint/typescript-estree": "8.42.0", "@typescript-eslint/utils": "8.42.0", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-9KChw92sbPTYVFw3JLRH1ockhyR3zqqn9lQXol3/YbI6jVxzWoGcT3AsAW0mu1MY0gYtsXnUGV/AKpkAj5tVlQ=="],
"@typescript-eslint/types": ["@typescript-eslint/types@8.42.0", "", {}, "sha512-LdtAWMiFmbRLNP7JNeY0SqEtJvGMYSzfiWBSmx+VSZ1CH+1zyl8Mmw1TT39OrtsRvIYShjJWzTDMPWZJCpwBlw=="],
"@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.42.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.42.0", "@typescript-eslint/tsconfig-utils": "8.42.0", "@typescript-eslint/types": "8.42.0", "@typescript-eslint/visitor-keys": "8.42.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-ku/uYtT4QXY8sl9EDJETD27o3Ewdi72hcXg1ah/kkUgBvAYHLwj2ofswFFNXS+FL5G+AGkxBtvGt8pFBHKlHsQ=="],
"@typescript-eslint/utils": ["@typescript-eslint/utils@8.42.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", "@typescript-eslint/scope-manager": "8.42.0", "@typescript-eslint/types": "8.42.0", "@typescript-eslint/typescript-estree": "8.42.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-JnIzu7H3RH5BrKC4NoZqRfmjqCIS1u3hGZltDYJgkVdqAezl4L9d1ZLw+36huCujtSBSAirGINF/S4UxOcR+/g=="],
"@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.42.0", "", { "dependencies": { "@typescript-eslint/types": "8.42.0", "eslint-visitor-keys": "^4.2.1" } }, "sha512-3WbiuzoEowaEn8RSnhJBrxSwX8ULYE9CXaPepS2C2W3NSA5NNIvBaslpBSBElPq0UGr0xVJlXFWOAKIkyylydQ=="],
"@vitejs/plugin-react-swc": ["@vitejs/plugin-react-swc@4.0.1", "", { "dependencies": { "@rolldown/pluginutils": "1.0.0-beta.32", "@swc/core": "^1.13.2" }, "peerDependencies": { "vite": "^4 || ^5 || ^6 || ^7" } }, "sha512-NQhPjysi5duItyrMd5JWZFf2vNOuSMyw+EoZyTBDzk+DkfYD8WNrsUs09sELV2cr1P15nufsN25hsUBt4CKF9Q=="],
"acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="],
"acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="],
"ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="],
"ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
"argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
"array-buffer-byte-length": ["array-buffer-byte-length@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "is-array-buffer": "^3.0.5" } }, "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw=="],
"array-includes": ["array-includes@3.1.9", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-abstract": "^1.24.0", "es-object-atoms": "^1.1.1", "get-intrinsic": "^1.3.0", "is-string": "^1.1.1", "math-intrinsics": "^1.1.0" } }, "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ=="],
"array.prototype.findlast": ["array.prototype.findlast@1.2.5", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "es-shim-unscopables": "^1.0.2" } }, "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ=="],
"array.prototype.flat": ["array.prototype.flat@1.3.3", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-shim-unscopables": "^1.0.2" } }, "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg=="],
"array.prototype.flatmap": ["array.prototype.flatmap@1.3.3", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-shim-unscopables": "^1.0.2" } }, "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg=="],
"array.prototype.tosorted": ["array.prototype.tosorted@1.1.4", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.3", "es-errors": "^1.3.0", "es-shim-unscopables": "^1.0.2" } }, "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA=="],
"arraybuffer.prototype.slice": ["arraybuffer.prototype.slice@1.0.4", "", { "dependencies": { "array-buffer-byte-length": "^1.0.1", "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "is-array-buffer": "^3.0.4" } }, "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ=="],
"async-function": ["async-function@1.0.0", "", {}, "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA=="],
"available-typed-arrays": ["available-typed-arrays@1.0.7", "", { "dependencies": { "possible-typed-array-names": "^1.0.0" } }, "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ=="],
"babel-plugin-styled-components": ["babel-plugin-styled-components@2.1.4", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", "@babel/helper-module-imports": "^7.22.5", "@babel/plugin-syntax-jsx": "^7.22.5", "lodash": "^4.17.21", "picomatch": "^2.3.1" }, "peerDependencies": { "styled-components": ">= 2" } }, "sha512-Xgp9g+A/cG47sUyRwwYxGM4bR/jDRg5N6it/8+HxCnbT5XNKSKDT9xm4oag/osgqjC2It/vH0yXsomOG6k558g=="],
"babel-plugin-transform-amd-to-commonjs": ["babel-plugin-transform-amd-to-commonjs@1.6.0", "", { "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-Dwvn+0BM6hdLMA5sfD9QzMICo8NnqqyqCyiNeKPruAuEZDdDVWbPkPh26ckJqfL/hYIkzAvK3Zj2H/7pBzIpig=="],
"balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
"brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="],
"braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
"browserslist": ["browserslist@4.25.4", "", { "dependencies": { "caniuse-lite": "^1.0.30001737", "electron-to-chromium": "^1.5.211", "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.3" }, "bin": { "browserslist": "cli.js" } }, "sha512-4jYpcjabC606xJ3kw2QwGEZKX0Aw7sgQdZCvIK9dhVSPh76BKo+C+btT1RRofH7B+8iNpEbgGNVWiLki5q93yg=="],
"call-bind": ["call-bind@1.0.8", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", "get-intrinsic": "^1.2.4", "set-function-length": "^1.2.2" } }, "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww=="],
"call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="],
"call-bound": ["call-bound@1.0.4", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" } }, "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg=="],
"callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="],
"camelize": ["camelize@1.0.1", "", {}, "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ=="],
"caniuse-lite": ["caniuse-lite@1.0.30001741", "", {}, "sha512-QGUGitqsc8ARjLdgAfxETDhRbJ0REsP6O3I96TAth/mVjh2cYzN2u+3AzPP3aVSm2FehEItaJw1xd+IGBXWeSw=="],
"chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
"clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="],
"color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
"color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
"concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="],
"convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="],
"cookie": ["cookie@1.0.2", "", {}, "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA=="],
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
"css-color-keywords": ["css-color-keywords@1.0.0", "", {}, "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg=="],
"css-to-react-native": ["css-to-react-native@3.2.0", "", { "dependencies": { "camelize": "^1.0.0", "css-color-keywords": "^1.0.0", "postcss-value-parser": "^4.0.2" } }, "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ=="],
"csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
"data-view-buffer": ["data-view-buffer@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-data-view": "^1.0.2" } }, "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ=="],
"data-view-byte-length": ["data-view-byte-length@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-data-view": "^1.0.2" } }, "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ=="],
"data-view-byte-offset": ["data-view-byte-offset@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-data-view": "^1.0.1" } }, "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ=="],
"date-fns": ["date-fns@4.1.0", "", {}, "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg=="],
"debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="],
"deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="],
"define-data-property": ["define-data-property@1.1.4", "", { "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "gopd": "^1.0.1" } }, "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A=="],
"define-properties": ["define-properties@1.2.1", "", { "dependencies": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" } }, "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg=="],
"doctrine": ["doctrine@2.1.0", "", { "dependencies": { "esutils": "^2.0.2" } }, "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw=="],
"dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
"electron-to-chromium": ["electron-to-chromium@1.5.214", "", {}, "sha512-TpvUNdha+X3ybfU78NoQatKvQEm1oq3lf2QbnmCEdw+Bd9RuIAY+hJTvq1avzHM0f7EJfnH3vbCnbzKzisc/9Q=="],
"es-abstract": ["es-abstract@1.24.0", "", { "dependencies": { "array-buffer-byte-length": "^1.0.2", "arraybuffer.prototype.slice": "^1.0.4", "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", "data-view-buffer": "^1.0.2", "data-view-byte-length": "^1.0.2", "data-view-byte-offset": "^1.0.1", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "es-set-tostringtag": "^2.1.0", "es-to-primitive": "^1.3.0", "function.prototype.name": "^1.1.8", "get-intrinsic": "^1.3.0", "get-proto": "^1.0.1", "get-symbol-description": "^1.1.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", "has-proto": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "internal-slot": "^1.1.0", "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", "is-data-view": "^1.0.2", "is-negative-zero": "^2.0.3", "is-regex": "^1.2.1", "is-set": "^2.0.3", "is-shared-array-buffer": "^1.0.4", "is-string": "^1.1.1", "is-typed-array": "^1.1.15", "is-weakref": "^1.1.1", "math-intrinsics": "^1.1.0", "object-inspect": "^1.13.4", "object-keys": "^1.1.1", "object.assign": "^4.1.7", "own-keys": "^1.0.1", "regexp.prototype.flags": "^1.5.4", "safe-array-concat": "^1.1.3", "safe-push-apply": "^1.0.0", "safe-regex-test": "^1.1.0", "set-proto": "^1.0.0", "stop-iteration-iterator": "^1.1.0", "string.prototype.trim": "^1.2.10", "string.prototype.trimend": "^1.0.9", "string.prototype.trimstart": "^1.0.8", "typed-array-buffer": "^1.0.3", "typed-array-byte-length": "^1.0.3", "typed-array-byte-offset": "^1.0.4", "typed-array-length": "^1.0.7", "unbox-primitive": "^1.1.0", "which-typed-array": "^1.1.19" } }, "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg=="],
"es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="],
"es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="],
"es-iterator-helpers": ["es-iterator-helpers@1.2.1", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-abstract": "^1.23.6", "es-errors": "^1.3.0", "es-set-tostringtag": "^2.0.3", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.6", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", "has-proto": "^1.2.0", "has-symbols": "^1.1.0", "internal-slot": "^1.1.0", "iterator.prototype": "^1.1.4", "safe-array-concat": "^1.1.3" } }, "sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w=="],
"es-module-lexer": ["es-module-lexer@1.7.0", "", {}, "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA=="],
"es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="],
"es-set-tostringtag": ["es-set-tostringtag@2.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="],
"es-shim-unscopables": ["es-shim-unscopables@1.1.0", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw=="],
"es-to-primitive": ["es-to-primitive@1.3.0", "", { "dependencies": { "is-callable": "^1.2.7", "is-date-object": "^1.0.5", "is-symbol": "^1.0.4" } }, "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g=="],
"esbuild": ["esbuild@0.25.9", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.9", "@esbuild/android-arm": "0.25.9", "@esbuild/android-arm64": "0.25.9", "@esbuild/android-x64": "0.25.9", "@esbuild/darwin-arm64": "0.25.9", "@esbuild/darwin-x64": "0.25.9", "@esbuild/freebsd-arm64": "0.25.9", "@esbuild/freebsd-x64": "0.25.9", "@esbuild/linux-arm": "0.25.9", "@esbuild/linux-arm64": "0.25.9", "@esbuild/linux-ia32": "0.25.9", "@esbuild/linux-loong64": "0.25.9", "@esbuild/linux-mips64el": "0.25.9", "@esbuild/linux-ppc64": "0.25.9", "@esbuild/linux-riscv64": "0.25.9", "@esbuild/linux-s390x": "0.25.9", "@esbuild/linux-x64": "0.25.9", "@esbuild/netbsd-arm64": "0.25.9", "@esbuild/netbsd-x64": "0.25.9", "@esbuild/openbsd-arm64": "0.25.9", "@esbuild/openbsd-x64": "0.25.9", "@esbuild/openharmony-arm64": "0.25.9", "@esbuild/sunos-x64": "0.25.9", "@esbuild/win32-arm64": "0.25.9", "@esbuild/win32-ia32": "0.25.9", "@esbuild/win32-x64": "0.25.9" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g=="],
"escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="],
"escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="],
"eslint": ["eslint@9.34.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.0", "@eslint/config-helpers": "^0.3.1", "@eslint/core": "^0.15.2", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "9.34.0", "@eslint/plugin-kit": "^0.3.5", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.4.0", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-RNCHRX5EwdrESy3Jc9o8ie8Bog+PeYvvSR8sDGoZxNFTvZ4dlxUB3WzQ3bQMztFrSRODGrLLj8g6OFuGY/aiQg=="],
"eslint-plugin-react": ["eslint-plugin-react@7.37.5", "", { "dependencies": { "array-includes": "^3.1.8", "array.prototype.findlast": "^1.2.5", "array.prototype.flatmap": "^1.3.3", "array.prototype.tosorted": "^1.1.4", "doctrine": "^2.1.0", "es-iterator-helpers": "^1.2.1", "estraverse": "^5.3.0", "hasown": "^2.0.2", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", "object.entries": "^1.1.9", "object.fromentries": "^2.0.8", "object.values": "^1.2.1", "prop-types": "^15.8.1", "resolve": "^2.0.0-next.5", "semver": "^6.3.1", "string.prototype.matchall": "^4.0.12", "string.prototype.repeat": "^1.0.0" }, "peerDependencies": { "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA=="],
"eslint-plugin-react-hooks": ["eslint-plugin-react-hooks@5.2.0", "", { "peerDependencies": { "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" } }, "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg=="],
"eslint-plugin-react-refresh": ["eslint-plugin-react-refresh@0.4.20", "", { "peerDependencies": { "eslint": ">=8.40" } }, "sha512-XpbHQ2q5gUF8BGOX4dHe+71qoirYMhApEPZ7sfhF/dNnOF1UXnCMGZf79SFTBO7Bz5YEIT4TMieSlJBWhP9WBA=="],
"eslint-scope": ["eslint-scope@8.4.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg=="],
"eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="],
"espree": ["espree@10.4.0", "", { "dependencies": { "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.1" } }, "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ=="],
"esquery": ["esquery@1.6.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg=="],
"esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="],
"estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="],
"esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="],
"fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="],
"fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="],
"fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="],
"fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="],
"fastq": ["fastq@1.19.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ=="],
"fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
"file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="],
"fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="],
"find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="],
"flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="],
"flatted": ["flatted@3.3.3", "", {}, "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg=="],
"for-each": ["for-each@0.3.5", "", { "dependencies": { "is-callable": "^1.2.7" } }, "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg=="],
"fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
"function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],
"function.prototype.name": ["function.prototype.name@1.1.8", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "functions-have-names": "^1.2.3", "hasown": "^2.0.2", "is-callable": "^1.2.7" } }, "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q=="],
"functions-have-names": ["functions-have-names@1.2.3", "", {}, "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ=="],
"gensync": ["gensync@1.0.0-beta.2", "", {}, "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="],
"get-intrinsic": ["get-intrinsic@1.3.0", "", { "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" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="],
"get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="],
"get-symbol-description": ["get-symbol-description@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6" } }, "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg=="],
"glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="],
"globals": ["globals@16.3.0", "", {}, "sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ=="],
"globalthis": ["globalthis@1.0.4", "", { "dependencies": { "define-properties": "^1.2.1", "gopd": "^1.0.1" } }, "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ=="],
"gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="],
"graphemer": ["graphemer@1.4.0", "", {}, "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag=="],
"has-bigints": ["has-bigints@1.1.0", "", {}, "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg=="],
"has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="],
"has-property-descriptors": ["has-property-descriptors@1.0.2", "", { "dependencies": { "es-define-property": "^1.0.0" } }, "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg=="],
"has-proto": ["has-proto@1.2.0", "", { "dependencies": { "dunder-proto": "^1.0.0" } }, "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ=="],
"has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="],
"has-tostringtag": ["has-tostringtag@1.0.2", "", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="],
"hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="],
"ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],
"ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],
"immer": ["immer@10.1.3", "", {}, "sha512-tmjF/k8QDKydUlm3mZU+tjM6zeq9/fFpPqH9SzWmBnVVKsPBg/V66qsMwb3/Bo90cgUN+ghdVBess+hPsxUyRw=="],
"import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="],
"imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="],
"internal-slot": ["internal-slot@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "hasown": "^2.0.2", "side-channel": "^1.1.0" } }, "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw=="],
"is-array-buffer": ["is-array-buffer@3.0.5", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "get-intrinsic": "^1.2.6" } }, "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A=="],
"is-async-function": ["is-async-function@2.1.1", "", { "dependencies": { "async-function": "^1.0.0", "call-bound": "^1.0.3", "get-proto": "^1.0.1", "has-tostringtag": "^1.0.2", "safe-regex-test": "^1.1.0" } }, "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ=="],
"is-bigint": ["is-bigint@1.1.0", "", { "dependencies": { "has-bigints": "^1.0.2" } }, "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ=="],
"is-boolean-object": ["is-boolean-object@1.2.2", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A=="],
"is-callable": ["is-callable@1.2.7", "", {}, "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA=="],
"is-core-module": ["is-core-module@2.16.1", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w=="],
"is-data-view": ["is-data-view@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "get-intrinsic": "^1.2.6", "is-typed-array": "^1.1.13" } }, "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw=="],
"is-date-object": ["is-date-object@1.1.0", "", { "dependencies": { "call-bound": "^1.0.2", "has-tostringtag": "^1.0.2" } }, "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg=="],
"is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="],
"is-finalizationregistry": ["is-finalizationregistry@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg=="],
"is-generator-function": ["is-generator-function@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "get-proto": "^1.0.0", "has-tostringtag": "^1.0.2", "safe-regex-test": "^1.1.0" } }, "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ=="],
"is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="],
"is-map": ["is-map@2.0.3", "", {}, "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw=="],
"is-negative-zero": ["is-negative-zero@2.0.3", "", {}, "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw=="],
"is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="],
"is-number-object": ["is-number-object@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw=="],
"is-regex": ["is-regex@1.2.1", "", { "dependencies": { "call-bound": "^1.0.2", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g=="],
"is-set": ["is-set@2.0.3", "", {}, "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg=="],
"is-shared-array-buffer": ["is-shared-array-buffer@1.0.4", "", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A=="],
"is-string": ["is-string@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA=="],
"is-symbol": ["is-symbol@1.1.1", "", { "dependencies": { "call-bound": "^1.0.2", "has-symbols": "^1.1.0", "safe-regex-test": "^1.1.0" } }, "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w=="],
"is-typed-array": ["is-typed-array@1.1.15", "", { "dependencies": { "which-typed-array": "^1.1.16" } }, "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ=="],
"is-weakmap": ["is-weakmap@2.0.2", "", {}, "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w=="],
"is-weakref": ["is-weakref@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew=="],
"is-weakset": ["is-weakset@2.0.4", "", { "dependencies": { "call-bound": "^1.0.3", "get-intrinsic": "^1.2.6" } }, "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ=="],
"isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="],
"isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
"iterator.prototype": ["iterator.prototype@1.1.5", "", { "dependencies": { "define-data-property": "^1.1.4", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.6", "get-proto": "^1.0.0", "has-symbols": "^1.1.0", "set-function-name": "^2.0.2" } }, "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g=="],
"js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
"js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="],
"jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="],
"json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="],
"json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="],
"json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="],
"json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="],
"jsx-ast-utils": ["jsx-ast-utils@3.3.5", "", { "dependencies": { "array-includes": "^3.1.6", "array.prototype.flat": "^1.3.1", "object.assign": "^4.1.4", "object.values": "^1.1.6" } }, "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ=="],
"keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="],
"levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="],
"locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="],
"lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="],
"lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="],
"loose-envify": ["loose-envify@1.4.0", "", { "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, "bin": { "loose-envify": "cli.js" } }, "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q=="],
"lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="],
"lxiv": ["lxiv@0.2.0", "", {}, "sha512-kZfRAqtw3M5iI0oe7sc3Xuo7BMVia5eDX7iodQqUM8cTUBuE0cAQsPXVOmxyD9a3ujAmgak3Dxw0f74aGGg2/w=="],
"magic-string": ["magic-string@0.30.18", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-yi8swmWbO17qHhwIBNeeZxTceJMeBvWJaId6dyvTSOwTipqeHhMhOrz6513r1sOKnpvQ7zkhlG8tPrpilwTxHQ=="],
"math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="],
"merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="],
"micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="],
"minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="],
"moment": ["moment@2.30.1", "", {}, "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how=="],
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
"nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
"natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="],
"node-releases": ["node-releases@2.0.20", "", {}, "sha512-7gK6zSXEH6neM212JgfYFXe+GmZQM+fia5SsusuBIUgnPheLFBmIPhtFoAQRj8/7wASYQnbDlHPVwY0BefoFgA=="],
"object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="],
"object-inspect": ["object-inspect@1.13.4", "", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="],
"object-keys": ["object-keys@1.1.1", "", {}, "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="],
"object.assign": ["object.assign@4.1.7", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0", "has-symbols": "^1.1.0", "object-keys": "^1.1.1" } }, "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw=="],
"object.entries": ["object.entries@1.1.9", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-object-atoms": "^1.1.1" } }, "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw=="],
"object.fromentries": ["object.fromentries@2.0.8", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2", "es-object-atoms": "^1.0.0" } }, "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ=="],
"object.values": ["object.values@1.2.1", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA=="],
"optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="],
"own-keys": ["own-keys@1.0.1", "", { "dependencies": { "get-intrinsic": "^1.2.6", "object-keys": "^1.1.1", "safe-push-apply": "^1.0.0" } }, "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg=="],
"p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="],
"p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="],
"parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="],
"path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="],
"path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
"path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="],
"pbf": ["pbf@3.1.0", "", { "dependencies": { "ieee754": "^1.1.6", "resolve-protobuf-schema": "^2.0.0" }, "bin": { "pbf": "bin/pbf" } }, "sha512-/hYJmIsTmh7fMkHAWWXJ5b8IKLWdjdlAFb3IHkRBn1XUhIYBChVGfVwmHEAV3UfXTxsP/AKfYTXTS/dCPxJd5w=="],
"phenix-edge-auth": ["phenix-edge-auth@1.2.7", "", {}, "sha512-hmIA4iKrR6Pf+EoIu/k7kxKYXkiD7I8PQL7iZb+9NkC676hCeGPZK+OsRc9uNW+fDZgZlN1qoQjBxDiT5JRe+A=="],
"phenix-web-assert": ["phenix-web-assert@2020.0.2", "", { "dependencies": { "phenix-web-lodash-light": "^2020.0.2" } }, "sha512-WRgWqXsL1Du/ty/dq/vkooOd3e2BhLCw24vVLWmWZjM/o5TjeOhxQSMSklrDuVRamVGiEkvuQpjL8lIeP/W4TQ=="],
"phenix-web-batch-http": ["phenix-web-batch-http@2020.0.2", "", { "dependencies": { "phenix-web-assert": "^2020.0.2", "phenix-web-disposable": "^2020.0.2", "phenix-web-event": "^2020.0.2", "phenix-web-global": "^2020.0.2", "phenix-web-http": "^2020.0.2", "phenix-web-lodash-light": "^2020.0.2", "phenix-web-network-connection-monitor": "^2020.0.2", "phenix-web-observable": "^2020.0.2" } }, "sha512-SG9/9RerkYcXIEH9Vk6DRosWF2229DXyeUa0hiU7jawj8xrOnAE7CMVdKcbaK4GGbZWMrT4HetIAMkqxSaHGFA=="],
"phenix-web-disposable": ["phenix-web-disposable@2020.0.2", "", { "dependencies": { "phenix-web-assert": "^2020.0.2", "phenix-web-lodash-light": "^2020.0.2" } }, "sha512-kW+x6ttFlEgjDB+d5sbqr+f72hTo95SgKLHZaW2LiLYiVNhGSiJT+AscyNWdK2uq4aNjwFVn7Wj3URuwzpudYQ=="],
"phenix-web-event": ["phenix-web-event@2020.0.2", "", { "dependencies": { "phenix-web-assert": "^2020.0.2", "phenix-web-disposable": "^2020.0.2", "phenix-web-lodash-light": "^2020.0.2" } }, "sha512-6DnrzoZ6Dfwdh5sLaAmeApxf2FgUG/7iQWJL1+IGhAcb2GJqW+JQEMQ8aWIP9lnhQTaoDP8xsAp7aieAALRmrw=="],
"phenix-web-global": ["phenix-web-global@2020.0.2", "", {}, "sha512-dBn6Ox6Nq79jx3zr/bI5K76yyCmMne/Br2XhRZ5XVXPKSYh5EMWdUBmtmaUub8Gi2Gc9gcJnq5NeiP7z8S1/6A=="],
"phenix-web-http": ["phenix-web-http@2020.0.2", "", { "dependencies": { "phenix-web-assert": "^2020.0.2", "phenix-web-disposable": "^2020.0.2", "phenix-web-lodash-light": "^2020.0.2" } }, "sha512-5/vev4Zeabmcfl6s4c5sGScGGF6qecGRyVvooex5kExDWkRpm3az04migm87+Nyb/94vYTEoRYqpwFhrrHs5pw=="],
"phenix-web-lodash-light": ["phenix-web-lodash-light@2020.0.4", "", {}, "sha512-E6xO/laCZXpmMKM/oLZrbB+uYteW4foTrybAoM82pRaLxYvevNUiZKD1xq4sIShMiWjqVv4GNOHlOp109GA/Pw=="],
"phenix-web-network-connection-monitor": ["phenix-web-network-connection-monitor@2020.0.2", "", { "dependencies": { "phenix-web-disposable": "^2020.0.2", "phenix-web-event": "^2020.0.2", "phenix-web-global": "^2020.0.2", "phenix-web-lodash-light": "^2020.0.2", "phenix-web-observable": "^2020.0.2" } }, "sha512-GizAKpSqsM48lYTAL7s/y5AKX8v3nbx2V75vTVCee2XTYV7b8SR0LnUYkkaefZXE9D+uV+WH+vXUXT9niQBJ/Q=="],
"phenix-web-observable": ["phenix-web-observable@2020.0.2", "", { "dependencies": { "phenix-web-assert": "^2020.0.2", "phenix-web-disposable": "^2020.0.2", "phenix-web-lodash-light": "^2020.0.2" } }, "sha512-HwdBUV9LFsCa5aov/I+zyD5uFsNcsxxUmjN+3F/0gbfLNRWJlNSRGzBFQrM3UWUE/YOFnEvsEiNg90ZlXpyoKA=="],
"phenix-web-proto": ["phenix-web-proto@2020.0.3", "", { "dependencies": { "lxiv": "0.2.0", "pbf": "3.1.0", "phenix-web-assert": "^2020.0.2", "phenix-web-batch-http": "^2020.0.2", "phenix-web-disposable": "^2020.0.2", "phenix-web-event": "^2020.0.2", "phenix-web-global": "^2020.0.2", "phenix-web-lodash-light": "^2020.0.2", "phenix-web-reconnecting-websocket": "^2020.0.2" } }, "sha512-79D05OVnKOCTE8mX8his0gEtSaxWgUOsCYzwfZfSEzBk0o80n37ups2T3EfAaoVG9R0rRzWKwg1SmKpmsymxlA=="],
"phenix-web-reconnecting-websocket": ["phenix-web-reconnecting-websocket@2020.0.2", "", { "dependencies": { "phenix-web-assert": "^2020.0.2", "phenix-web-lodash-light": "^2020.0.2", "phenix-web-network-connection-monitor": "^2020.0.2" } }, "sha512-5l8AvR+8BnQZNhiyz63tuH/xFh5i01YofU6woKHxPGV+HfhJUloHU4nVoUt7vRCfPKRuDTa7bh3hJEtBnOLYag=="],
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
"picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
"possible-typed-array-names": ["possible-typed-array-names@1.1.0", "", {}, "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg=="],
"postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
"postcss-value-parser": ["postcss-value-parser@4.2.0", "", {}, "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="],
"prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="],
"prettier": ["prettier@3.6.2", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ=="],
"prop-types": ["prop-types@15.8.1", "", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="],
"protocol-buffers-schema": ["protocol-buffers-schema@3.6.0", "", {}, "sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw=="],
"punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],
"queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="],
"react": ["react@19.1.1", "", {}, "sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ=="],
"react-datepicker": ["react-datepicker@8.7.0", "", { "dependencies": { "@floating-ui/react": "^0.27.15", "clsx": "^2.1.1", "date-fns": "^4.1.0" }, "peerDependencies": { "react": "^16.9.0 || ^17 || ^18 || ^19 || ^19.0.0-rc", "react-dom": "^16.9.0 || ^17 || ^18 || ^19 || ^19.0.0-rc" } }, "sha512-r5OJbiLWc3YiVNy69Kau07/aVgVGsFVMA6+nlqCV7vyQ8q0FUOnJ+wAI4CgVxHejG3i5djAEiebrF8/Eip4rIw=="],
"react-dom": ["react-dom@19.1.1", "", { "dependencies": { "scheduler": "^0.26.0" }, "peerDependencies": { "react": "^19.1.1" } }, "sha512-Dlq/5LAZgF0Gaz6yiqZCf6VCcZs1ghAJyrsu84Q/GT0gV+mCxbfmKNoGRKBYMJ8IEdGPqu49YWXD02GCknEDkw=="],
"react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="],
"react-redux": ["react-redux@9.2.0", "", { "dependencies": { "@types/use-sync-external-store": "^0.0.6", "use-sync-external-store": "^1.4.0" }, "peerDependencies": { "@types/react": "^18.2.25 || ^19", "react": "^18.0 || ^19", "redux": "^5.0.0" }, "optionalPeers": ["@types/react", "redux"] }, "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g=="],
"react-router": ["react-router@7.8.2", "", { "dependencies": { "cookie": "^1.0.1", "set-cookie-parser": "^2.6.0" }, "peerDependencies": { "react": ">=18", "react-dom": ">=18" }, "optionalPeers": ["react-dom"] }, "sha512-7M2fR1JbIZ/jFWqelpvSZx+7vd7UlBTfdZqf6OSdF9g6+sfdqJDAWcak6ervbHph200ePlu+7G8LdoiC3ReyAQ=="],
"react-router-dom": ["react-router-dom@7.8.2", "", { "dependencies": { "react-router": "7.8.2" }, "peerDependencies": { "react": ">=18", "react-dom": ">=18" } }, "sha512-Z4VM5mKDipal2jQ385H6UBhiiEDlnJPx6jyWsTYoZQdl5TrjxEV2a9yl3Fi60NBJxYzOTGTTHXPi0pdizvTwow=="],
"react-toastify": ["react-toastify@11.0.5", "", { "dependencies": { "clsx": "^2.1.1" }, "peerDependencies": { "react": "^18 || ^19", "react-dom": "^18 || ^19" } }, "sha512-EpqHBGvnSTtHYhCPLxML05NLY2ZX0JURbAdNYa6BUkk+amz4wbKBQvoKQAB0ardvSarUBuY4Q4s1sluAzZwkmA=="],
"redux": ["redux@5.0.1", "", {}, "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w=="],
"redux-thunk": ["redux-thunk@3.1.0", "", { "peerDependencies": { "redux": "^5.0.0" } }, "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw=="],
"reflect.getprototypeof": ["reflect.getprototypeof@1.0.10", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.9", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.7", "get-proto": "^1.0.1", "which-builtin-type": "^1.2.1" } }, "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw=="],
"regexp.prototype.flags": ["regexp.prototype.flags@1.5.4", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-errors": "^1.3.0", "get-proto": "^1.0.1", "gopd": "^1.2.0", "set-function-name": "^2.0.2" } }, "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA=="],
"reselect": ["reselect@5.1.1", "", {}, "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w=="],
"resolve": ["resolve@2.0.0-next.5", "", { "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA=="],
"resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="],
"resolve-protobuf-schema": ["resolve-protobuf-schema@2.1.0", "", { "dependencies": { "protocol-buffers-schema": "^3.3.1" } }, "sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ=="],
"reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="],
"rollup": ["rollup@4.50.0", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.50.0", "@rollup/rollup-android-arm64": "4.50.0", "@rollup/rollup-darwin-arm64": "4.50.0", "@rollup/rollup-darwin-x64": "4.50.0", "@rollup/rollup-freebsd-arm64": "4.50.0", "@rollup/rollup-freebsd-x64": "4.50.0", "@rollup/rollup-linux-arm-gnueabihf": "4.50.0", "@rollup/rollup-linux-arm-musleabihf": "4.50.0", "@rollup/rollup-linux-arm64-gnu": "4.50.0", "@rollup/rollup-linux-arm64-musl": "4.50.0", "@rollup/rollup-linux-loongarch64-gnu": "4.50.0", "@rollup/rollup-linux-ppc64-gnu": "4.50.0", "@rollup/rollup-linux-riscv64-gnu": "4.50.0", "@rollup/rollup-linux-riscv64-musl": "4.50.0", "@rollup/rollup-linux-s390x-gnu": "4.50.0", "@rollup/rollup-linux-x64-gnu": "4.50.0", "@rollup/rollup-linux-x64-musl": "4.50.0", "@rollup/rollup-openharmony-arm64": "4.50.0", "@rollup/rollup-win32-arm64-msvc": "4.50.0", "@rollup/rollup-win32-ia32-msvc": "4.50.0", "@rollup/rollup-win32-x64-msvc": "4.50.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-/Zl4D8zPifNmyGzJS+3kVoyXeDeT/GrsJM94sACNg9RtUE0hrHa1bNPtRSrfHTMH5HjRzce6K7rlTh3Khiw+pw=="],
"run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="],
"safe-array-concat": ["safe-array-concat@1.1.3", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", "get-intrinsic": "^1.2.6", "has-symbols": "^1.1.0", "isarray": "^2.0.5" } }, "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q=="],
"safe-push-apply": ["safe-push-apply@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "isarray": "^2.0.5" } }, "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA=="],
"safe-regex-test": ["safe-regex-test@1.1.0", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-regex": "^1.2.1" } }, "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw=="],
"scheduler": ["scheduler@0.26.0", "", {}, "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA=="],
"semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
"set-cookie-parser": ["set-cookie-parser@2.7.1", "", {}, "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ=="],
"set-function-length": ["set-function-length@1.2.2", "", { "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", "has-property-descriptors": "^1.0.2" } }, "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg=="],
"set-function-name": ["set-function-name@2.0.2", "", { "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "functions-have-names": "^1.2.3", "has-property-descriptors": "^1.0.2" } }, "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ=="],
"set-proto": ["set-proto@1.0.0", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0" } }, "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw=="],
"shallowequal": ["shallowequal@1.1.0", "", {}, "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ=="],
"shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
"shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
"side-channel": ["side-channel@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", "side-channel-list": "^1.0.0", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw=="],
"side-channel-list": ["side-channel-list@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3" } }, "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA=="],
"side-channel-map": ["side-channel-map@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3" } }, "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA=="],
"side-channel-weakmap": ["side-channel-weakmap@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3", "side-channel-map": "^1.0.1" } }, "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A=="],
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
"stop-iteration-iterator": ["stop-iteration-iterator@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "internal-slot": "^1.1.0" } }, "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ=="],
"string.prototype.matchall": ["string.prototype.matchall@4.0.12", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-abstract": "^1.23.6", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.6", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "internal-slot": "^1.1.0", "regexp.prototype.flags": "^1.5.3", "set-function-name": "^2.0.2", "side-channel": "^1.1.0" } }, "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA=="],
"string.prototype.repeat": ["string.prototype.repeat@1.0.0", "", { "dependencies": { "define-properties": "^1.1.3", "es-abstract": "^1.17.5" } }, "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w=="],
"string.prototype.trim": ["string.prototype.trim@1.2.10", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", "define-data-property": "^1.1.4", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-object-atoms": "^1.0.0", "has-property-descriptors": "^1.0.2" } }, "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA=="],
"string.prototype.trimend": ["string.prototype.trimend@1.0.9", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ=="],
"string.prototype.trimstart": ["string.prototype.trimstart@1.0.8", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg=="],
"strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="],
"styled-components": ["styled-components@6.1.19", "", { "dependencies": { "@emotion/is-prop-valid": "1.2.2", "@emotion/unitless": "0.8.1", "@types/stylis": "4.2.5", "css-to-react-native": "3.2.0", "csstype": "3.1.3", "postcss": "8.4.49", "shallowequal": "1.1.0", "stylis": "4.3.2", "tslib": "2.6.2" }, "peerDependencies": { "react": ">= 16.8.0", "react-dom": ">= 16.8.0" } }, "sha512-1v/e3Dl1BknC37cXMhwGomhO8AkYmN41CqyX9xhUDxry1ns3BFQy2lLDRQXJRdVVWB9OHemv/53xaStimvWyuA=="],
"stylis": ["stylis@4.3.2", "", {}, "sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg=="],
"supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
"supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="],
"tabbable": ["tabbable@6.2.0", "", {}, "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew=="],
"tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="],
"to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
"ts-api-utils": ["ts-api-utils@2.1.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ=="],
"tslib": ["tslib@2.6.2", "", {}, "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="],
"type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="],
"typed-array-buffer": ["typed-array-buffer@1.0.3", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-typed-array": "^1.1.14" } }, "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw=="],
"typed-array-byte-length": ["typed-array-byte-length@1.0.3", "", { "dependencies": { "call-bind": "^1.0.8", "for-each": "^0.3.3", "gopd": "^1.2.0", "has-proto": "^1.2.0", "is-typed-array": "^1.1.14" } }, "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg=="],
"typed-array-byte-offset": ["typed-array-byte-offset@1.0.4", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "for-each": "^0.3.3", "gopd": "^1.2.0", "has-proto": "^1.2.0", "is-typed-array": "^1.1.15", "reflect.getprototypeof": "^1.0.9" } }, "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ=="],
"typed-array-length": ["typed-array-length@1.0.7", "", { "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", "is-typed-array": "^1.1.13", "possible-typed-array-names": "^1.0.0", "reflect.getprototypeof": "^1.0.6" } }, "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg=="],
"typescript": ["typescript@5.9.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A=="],
"typescript-eslint": ["typescript-eslint@8.42.0", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.42.0", "@typescript-eslint/parser": "8.42.0", "@typescript-eslint/typescript-estree": "8.42.0", "@typescript-eslint/utils": "8.42.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-ozR/rQn+aQXQxh1YgbCzQWDFrsi9mcg+1PM3l/z5o1+20P7suOIaNg515bpr/OYt6FObz/NHcBstydDLHWeEKg=="],
"typescript-plugin-styled-components": ["typescript-plugin-styled-components@3.0.0", "", { "peerDependencies": { "typescript": "~4.8 || 5" } }, "sha512-QWlhTl6NqsFxtJyxn7pJjm3RhgzXSByUftZ3AoQClrMMpa4yAaHuJKTN1gFpH3Ti+Rwm56fNUfG9pXSBU+WW3A=="],
"unbox-primitive": ["unbox-primitive@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "has-bigints": "^1.0.2", "has-symbols": "^1.1.0", "which-boxed-primitive": "^1.1.1" } }, "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw=="],
"undici-types": ["undici-types@7.10.0", "", {}, "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag=="],
"update-browserslist-db": ["update-browserslist-db@1.1.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw=="],
"uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="],
"use-sync-external-store": ["use-sync-external-store@1.5.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A=="],
"uuid": ["uuid@11.1.0", "", { "bin": { "uuid": "dist/esm/bin/uuid" } }, "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A=="],
"vite": ["vite@7.1.4", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.14" }, "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" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-X5QFK4SGynAeeIt+A7ZWnApdUyHYm+pzv/8/A57LqSGcI88U6R6ipOs3uCesdc6yl7nl+zNO0t8LmqAdXcQihw=="],
"vite-plugin-babel": ["vite-plugin-babel@1.3.2", "", { "peerDependencies": { "@babel/core": "^7.0.0", "vite": "^2.7.0 || ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, "sha512-mEld4OVyuNs5+ISN+U5XyTnNcDwln/s2oER2m0PQ32YYPqPR25E3mfnhAA/RkZJxPuwFkprKWV405aZArE6kzA=="],
"vite-plugin-commonjs": ["vite-plugin-commonjs@0.10.4", "", { "dependencies": { "acorn": "^8.12.1", "magic-string": "^0.30.11", "vite-plugin-dynamic-import": "^1.6.0" } }, "sha512-eWQuvQKCcx0QYB5e5xfxBNjQKyrjEWZIR9UOkOV6JAgxVhtbZvCOF+FNC2ZijBJ3U3Px04ZMMyyMyFBVWIJ5+g=="],
"vite-plugin-dynamic-import": ["vite-plugin-dynamic-import@1.6.0", "", { "dependencies": { "acorn": "^8.12.1", "es-module-lexer": "^1.5.4", "fast-glob": "^3.3.2", "magic-string": "^0.30.11" } }, "sha512-TM0sz70wfzTIo9YCxVFwS8OA9lNREsh+0vMHGSkWDTZ7bgd1Yjs5RV8EgB634l/91IsXJReg0xtmuQqP0mf+rg=="],
"which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
"which-boxed-primitive": ["which-boxed-primitive@1.1.1", "", { "dependencies": { "is-bigint": "^1.1.0", "is-boolean-object": "^1.2.1", "is-number-object": "^1.1.1", "is-string": "^1.1.1", "is-symbol": "^1.1.1" } }, "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA=="],
"which-builtin-type": ["which-builtin-type@1.2.1", "", { "dependencies": { "call-bound": "^1.0.2", "function.prototype.name": "^1.1.6", "has-tostringtag": "^1.0.2", "is-async-function": "^2.0.0", "is-date-object": "^1.1.0", "is-finalizationregistry": "^1.1.0", "is-generator-function": "^1.0.10", "is-regex": "^1.2.1", "is-weakref": "^1.0.2", "isarray": "^2.0.5", "which-boxed-primitive": "^1.1.0", "which-collection": "^1.0.2", "which-typed-array": "^1.1.16" } }, "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q=="],
"which-collection": ["which-collection@1.0.2", "", { "dependencies": { "is-map": "^2.0.3", "is-set": "^2.0.3", "is-weakmap": "^2.0.2", "is-weakset": "^2.0.3" } }, "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw=="],
"which-typed-array": ["which-typed-array@1.1.19", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", "for-each": "^0.3.5", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" } }, "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw=="],
"word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="],
"yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="],
"yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="],
"@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="],
"@eslint/eslintrc/globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="],
"@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="],
"@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
"@typescript-eslint/typescript-estree/semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="],
"fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
"styled-components/postcss": ["postcss@8.4.49", "", { "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA=="],
"tinyglobby/picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
"vite/picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
"@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
}
}

29
eslint.config.js Normal file
View File

@@ -0,0 +1,29 @@
import js from '@eslint/js';
import globals from 'globals';
import reactHooks from 'eslint-plugin-react-hooks';
import reactRefresh from 'eslint-plugin-react-refresh';
import tseslint from 'typescript-eslint';
import {globalIgnores} from 'eslint/config';
export default tseslint.config([
globalIgnores(['dist']),
{
files: ['**/*.{ts,tsx}'],
extends: [js.configs.recommended, tseslint.configs.recommended, reactHooks.configs['recommended-latest'], reactRefresh.configs.vite],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser
},
rules: {
'no-unused-vars': 'off',
'@typescript-eslint/no-unused-vars': [
'error',
{
argsIgnorePattern: '^ignored',
varsIgnorePattern: '^ignored',
caughtErrorsIgnorePattern: '^ignored'
}
]
}
}
]);

15
index.html Normal file
View File

@@ -0,0 +1,15 @@
<!doctype html>
<html lang="en">
<head>
<script>
__phenixPageLoadTime = new Date().getTime();
</script>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>

57
package.json Normal file
View File

@@ -0,0 +1,57 @@
{
"name": "webcontrolcenter-zinn-2",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"format": "prettier --write ./",
"dev": "vite",
"build": "tsc -b && vite build",
"lint": "eslint --max-warnings 0 ./src",
"prelint:fix": "bun run format",
"lint:fix": "eslint --fix ./src",
"preview": "vite preview"
},
"dependencies": {
"@phenixrts/sdk": "2025.2.2",
"@reduxjs/toolkit": "2.9.0",
"@techniker-me/pcast-api": "2025.1.5",
"@techniker-me/tools": "2025.0.16",
"moment": "2.30.1",
"phenix-web-proto": "2020.0.3",
"react": "19.1.1",
"react-dom": "19.1.1",
"react-redux": "9.2.0",
"react-router-dom": "7.8.2",
"redux-persist": "6.0.0",
"styled-components": "6.1.19",
"uuid": "11.1.0"
},
"devDependencies": {
"@eslint/js": "9.34.0",
"@fortawesome/fontawesome-svg-core": "7.0.1",
"@fortawesome/free-regular-svg-icons": "7.0.1",
"@fortawesome/free-solid-svg-icons": "7.0.1",
"@fortawesome/react-fontawesome": "3.0.2",
"@types/node": "24.3.0",
"@types/react": "19.1.12",
"@types/react-dom": "19.1.9",
"@vitejs/plugin-react-swc": "4.0.1",
"babel-plugin-styled-components": "2.1.4",
"babel-plugin-transform-amd-to-commonjs": "1.6.0",
"eslint": "9.34.0",
"eslint-plugin-react": "7.37.5",
"eslint-plugin-react-hooks": "5.2.0",
"eslint-plugin-react-refresh": "0.4.20",
"globals": "16.3.0",
"prettier": "3.6.2",
"react-datepicker": "8.7.0",
"react-toastify": "11.0.5",
"typescript": "5.9.2",
"typescript-eslint": "8.42.0",
"typescript-plugin-styled-components": "3.0.0",
"vite": "7.1.4",
"vite-plugin-babel": "1.3.2",
"vite-plugin-commonjs": "0.10.4"
}
}

22
src/App.tsx Normal file
View File

@@ -0,0 +1,22 @@
import React from 'react';
import styled from 'styled-components';
import Router from './routers';
import Theme from './theme';
const AppContainer = styled.div`
height: 100vh;
background: ${Theme.backgrounds.defaultBackground};
background-attachment: fixed;
display: flex;
flex-direction: column;
`;
const App = (): React.JSX.Element => {
return (
<AppContainer>
<Router />
</AppContainer>
);
};
export default App;

Binary file not shown.

After

Width:  |  Height:  |  Size: 321 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 652 B

View File

@@ -0,0 +1 @@
<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'><svg enable-background="new 0 0 29 14" height="6px" id="Layer_1" version="1.1" viewBox="0 0 29 14" width="29px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><polygon fill="#F9F9F9" points="0.15,0 14.5,14.35 28.85,0 "/></svg>

After

Width:  |  Height:  |  Size: 400 B

View File

@@ -0,0 +1 @@
<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'><svg enable-background="new 0 0 29 14" height="8px" id="Layer_1" version="1.1" viewBox="0 0 29 14" width="29px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><polygon fill="#f9f9f9" points="0.15,14 14.5,-0.35 28.85,14 "/></svg>

After

Width:  |  Height:  |  Size: 402 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><!-- Generator: Gravit.io --><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="isolation:isolate" viewBox="0 0 206.751 186.399" width="206.751pt" height="186.399pt"><defs><clipPath id="_clipPath_Wy0NWkkA4mKqtolphxnGK0Cf0TrWZqlo"><rect width="206.751" height="186.399"/></clipPath></defs><g clip-path="url(#_clipPath_Wy0NWkkA4mKqtolphxnGK0Cf0TrWZqlo)"><g><path d=" M 179.102 178.898 L 103.306 178.559 L 27.51 178.22 C 9.581 178.14 2.36 165.502 11.394 150.015 L 49.585 84.544 L 87.777 19.072 C 96.811 3.586 111.366 3.651 120.261 19.218 L 157.865 85.028 L 195.469 150.839 C 204.364 166.406 197.03 178.979 179.102 178.898 Z " fill="none" vector-effect="non-scaling-stroke" stroke-width="5" stroke="rgb(247,13,26)" stroke-linejoin="miter" stroke-linecap="square" stroke-miterlimit="3"/><line x1="103.306" y1="47.028" x2="103.306" y2="120.028" vector-effect="non-scaling-stroke" stroke-width="5" stroke="rgb(247,13,26)" stroke-linejoin="miter" stroke-linecap="square" stroke-miterlimit="3"/><line x1="103.306" y1="138.028" x2="103.306" y2="143.028" vector-effect="non-scaling-stroke" stroke-width="5" stroke="rgb(247,13,26)" stroke-linejoin="miter" stroke-linecap="square" stroke-miterlimit="3"/></g></g></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="19px" height="18px" viewBox="0 0 19 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="01-home-copy-7" transform="translate(-1214.000000, -84.000000)" fill="#FFFFFF" fill-rule="nonzero">
<g id="icon/white/add-channel" transform="translate(1211.000000, 80.000000)">
<path d="M18,14 C18.5522847,14 19,14.4477153 19,15 L18.999068,17 L21,17 C21.5522847,17 22,17.4477153 22,18 C22,18.5522847 21.5522847,19 21,19 L18.999068,19 L19,21 C19,21.5522847 18.5522847,22 18,22 C17.4477153,22 17,21.5522847 17,21 L16.999068,18.999 L15,19 C14.4477153,19 14,18.5522847 14,18 C14,17.4477153 14.4477153,17 15,17 L16.999068,16.999 L17,15 C17,14.4477153 17.4477153,14 18,14 Z M14,4 C14.4287818,4 14.8254386,4.13754318 15.1482567,4.37091574 C15.4794061,4.13462978 15.8829334,4 16.3080311,4 L18,4 C19.0836085,4 19.9620467,4.87843824 19.9620467,5.96204672 C19.9620467,6.23272939 19.9060382,6.5004841 19.7975435,6.748472 L19.687068,6.999 L19.763932,7 C20.8685015,7 21.763932,7.8954305 21.763932,9 C21.763932,9.31049019 21.6916418,9.61671632 21.5527864,9.89442719 L20.5527864,11.8944272 C20.3949049,12.2101902 20.1601982,12.4717535 19.8778882,12.6610569 C19.3634108,12.2470293 18.7105538,12 18,12 C17.1114527,12 16.3131288,12.3862919 15.7638055,13.0000983 L15.083068,13 L15.916068,11 L18.381966,11 C18.7607381,11 19.1070012,10.7859976 19.2763932,10.4472136 L19.5,10 C19.6706654,9.65866925 19.5323138,9.24361439 19.190983,9.07294902 C19.0950363,9.02497564 18.9892377,9 18.881966,9 L16.750068,9 L17.6153846,6.92307692 C17.7569961,6.58320938 17.5962778,6.19289353 17.2564103,6.05128205 C17.1751635,6.01742923 17.0880173,6 17,6 L16.6666667,6 C16.2629658,6 15.8988593,6.24273768 15.7435897,6.61538462 L14.749068,9 L12.750068,9 L13.6153846,6.92307692 C13.7569961,6.58320938 13.5962778,6.19289353 13.2564103,6.05128205 C13.1751635,6.01742923 13.0880173,6 13,6 L12.6666667,6 C12.2629658,6 11.8988593,6.24273768 11.7435897,6.61538462 L10.749068,9 L8.61803399,9 C8.23926193,9 7.89299881,9.21400238 7.7236068,9.5527864 L7.5,10 C7.32933463,10.3413307 7.46768625,10.7563856 7.80901699,10.927051 C7.90496374,10.9750244 8.01076227,11 8.11803399,11 L9.91606798,11 L9.08206798,13 L6.61803399,13 C6.23926193,13 5.89299881,13.2140024 5.7236068,13.5527864 L5.5,14 C5.32933463,14.3413307 5.46768625,14.7563856 5.80901699,14.927051 C5.90496374,14.9750244 6.01076227,15 6.11803399,15 L8.24906798,15 L7.38461538,17.0769231 C7.24300391,17.4167906 7.40372221,17.8071065 7.74358974,17.9487179 C7.82483652,17.9825708 7.91198265,18 8,18 L8.33333333,18 C8.73703418,18 9.1011407,17.7572623 9.25641026,17.3846154 L10.249068,15 L12.249068,15 L11.3846154,17.0769231 C11.2430039,17.4167906 11.4037222,17.8071065 11.7435897,17.9487179 C11.8248365,17.9825708 11.9119827,18 12,18 L12.0354373,18.0000497 C12.0120835,18.1633354 12,18.3302566 12,18.5 C12,19.037207 12.1210295,19.5461461 12.3373087,20.0010375 L11,20 C10.5712182,20 10.1745614,19.8624568 9.85174329,19.6290843 C9.52059393,19.8653702 9.11706659,20 8.69196885,20 L7,20 C5.91639152,20 5.03795328,19.1215618 5.03795328,18.0379533 C5.03795328,17.7672706 5.09396179,17.4995159 5.2024565,17.251528 L5.31206798,17 L5.23606798,17 C4.13149848,17 3.23606798,16.1045695 3.23606798,15 C3.23606798,14.6895098 3.30835816,14.3832837 3.4472136,14.1055728 L4.4472136,12.1055728 C4.62888297,11.7422341 4.91227191,11.4506579 5.25285994,11.2583596 C5.24175599,11.1747423 5.23606798,11.0880354 5.23606798,11 C5.23606798,10.6895098 5.30835816,10.3832837 5.4472136,10.1055728 L6.4472136,8.10557281 C6.78599762,7.42800475 7.47852386,7 8.23606798,7 L9.68706798,6.999 L10.4757165,5.19836233 C10.7942054,4.47038768 11.5134355,4 12.3080311,4 L14,4 Z M15,15 L14.9990501,15.0355804 C14.6965332,15.0789368 14.406503,15.160979 14.1341327,15.276534 L14.249068,15 L15,15 Z M13.916068,11 L13.082068,13 L11.083068,13 L11.916068,11 L13.916068,11 Z" id="Combined-Shape"></path>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
<g>
<g>
<path style="fill:#F9F9F9" d="M501.333,96H10.667C4.779,96,0,100.779,0,106.667s4.779,10.667,10.667,10.667h490.667c5.888,0,10.667-4.779,10.667-10.667
S507.221,96,501.333,96z"/>
</g>
</g>
<g>
<g>
<path style="fill:#F9F9F9" d="M501.333,245.333H10.667C4.779,245.333,0,250.112,0,256s4.779,10.667,10.667,10.667h490.667
c5.888,0,10.667-4.779,10.667-10.667S507.221,245.333,501.333,245.333z"/>
</g>
</g>
<g>
<g>
<path style="fill:#F9F9F9" d="M501.333,394.667H10.667C4.779,394.667,0,399.445,0,405.333C0,411.221,4.779,416,10.667,416h490.667
c5.888,0,10.667-4.779,10.667-10.667C512,399.445,507.221,394.667,501.333,394.667z"/>
</g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1 @@
<svg fill="#00bc8c" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50" width="250px" height="250px"><path fill="none" stroke="#00bc8c" stroke-miterlimit="10" stroke-width="2" d="M25,3C12.85,3,3,12.85,3,25s9.85,22,22,22 s22-9.85,22-22S37.15,3,25,3z"/><path fill="none" stroke="#00bc8c" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" d="M16,24.444L24.143,32L35,16"/></svg>

After

Width:  |  Height:  |  Size: 390 B

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg width="19px" height="18px" version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 341.333 341.333" style="enable-background:new 0 0 341.333 341.333;" xml:space="preserve">
<g>
<g>
<path fill="#ffffff" d="M341.227,149.333V0l-50.133,50.133C260.267,19.2,217.707,0,170.56,0C76.267,0,0.107,76.373,0.107,170.667
s76.16,170.667,170.453,170.667c79.467,0,146.027-54.4,164.907-128h-44.373c-17.6,49.707-64.747,85.333-120.533,85.333
c-70.72,0-128-57.28-128-128s57.28-128,128-128c35.307,0,66.987,14.72,90.133,37.867l-68.8,68.8H341.227z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 796 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 374 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 563 B

View File

@@ -0,0 +1,15 @@
import React from 'react';
import {Navigate, useLocation} from 'react-router-dom';
import {useAppSelector} from 'store';
import {selectIsAuthenticated} from 'store/slices/Authentication.slice';
export function ProtectedRoute({component}: {component: React.JSX.Element}): React.JSX.Element {
const isAuthenticated = useAppSelector(selectIsAuthenticated);
const location = useLocation();
if (!isAuthenticated) {
return <Navigate to="/login" state={{from: location}} replace />;
}
return component;
}

View File

@@ -0,0 +1,28 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import React, {useState} from 'react';
import {faCopy, faCheck} from '@fortawesome/free-solid-svg-icons';
import IconButton from 'components/buttons/icon-button';
import {CopyButtonContainer} from './styles';
const iconChangeTimeout = 2000;
export const CopyIconButton = (props: {text: string; quoted?: boolean; displayText?: boolean; className?: string}): React.JSX.Element => {
const {text, quoted = false, displayText = true, className} = props;
const [copied, setCopied] = useState(false);
const copyToClipboard = (): void => {
navigator.clipboard.writeText(text);
setCopied(true);
setTimeout(() => setCopied(false), iconChangeTimeout);
};
return (
<CopyButtonContainer className={className}>
{displayText && (quoted ? `"${text}"` : text)}
<IconButton onClick={copyToClipboard} tooltipText="Copy" icon={copied ? faCheck : faCopy} />
</CopyButtonContainer>
);
};

View File

@@ -0,0 +1,9 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import * as styled from 'styled-components';
export const CopyButtonContainer = styled.default.div`
display: flex;
align-items: center;
`;

View File

@@ -0,0 +1,32 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import React from 'react';
import {theme} from 'components/shared/theme';
import {Button} from 'components/buttons';
const {colors} = theme;
interface IExportFileButton {
label?: string;
file: string;
fileName?: string;
}
export const ExportFileButton = ({label = 'Export File', file, fileName = 'file'}: IExportFileButton): React.JSX.Element => {
const handleExport = () => {
const downloadUrl = URL.createObjectURL(new Blob([file]));
const linkTag = document.createElement('a');
linkTag.href = downloadUrl;
linkTag.setAttribute('target', '_blank');
linkTag.setAttribute('download', fileName);
linkTag.click();
};
return (
<Button onClick={handleExport} className="testId-exportFile" backgroundColor={colors.red} borderColor={colors.red}>
{label}
</Button>
);
};

View File

@@ -0,0 +1,27 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import {IconProp} from '@fortawesome/fontawesome-svg-core';
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
import {Position, Tooltip} from 'components/tooltip';
import {IconButtonContainer} from './styles';
interface IIconButton {
onClick: () => void;
tooltipText: string;
icon: IconProp;
className?: string;
}
const IconButton = ({onClick, tooltipText, icon, className}: IIconButton) => (
<Tooltip position={Position.Bottom} message={tooltipText}>
<IconButtonContainer className={`icon-button ${className}`} role="link" tabIndex={-11} onKeyDown={undefined} onClick={onClick}>
<FontAwesomeIcon icon={icon} />
</IconButtonContainer>
</Tooltip>
);
export default IconButton;

View File

@@ -0,0 +1,5 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
export {default} from './icon-button';

View File

@@ -0,0 +1,30 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import * as styled from 'styled-components';
export const IconButtonContainer = styled.default.div`
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
&.disabled {
cursor: not-allowed;
pointer-events: none;
opacity: 0.5;
}
&.icon-button {
width: 2.5rem;
height: 2.5rem;
}
svg {
margin: 0;
}
&:hover {
background-color: rgba(255, 255, 255, 0.1);
}
`;

View File

@@ -0,0 +1,17 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import React from 'react';
import {IconButton} from './style';
import addIcon from 'assets/images/icon/hash-plus.svg';
interface IAddButton {
onClick: () => void;
className: string;
}
export const AddButton = ({onClick, className}: IAddButton): React.JSX.Element => (
<IconButton onClick={onClick} className={className}>
<img src={addIcon} alt={'Add'} />
</IconButton>
);

View File

@@ -0,0 +1,5 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
export * from './refresh-button';
export * from './add-button';

View File

@@ -0,0 +1,18 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import React from 'react';
import {IconButton} from './style';
import refreshIcon from 'assets/images/icon/refresh.svg';
interface IRefreshButton {
onClick: () => void;
disabled?: boolean;
}
export const RefreshButton = ({onClick, disabled = false}: IRefreshButton): React.JSX.Element => (
<IconButton onClick={onClick} disabled={disabled}>
<img src={refreshIcon} alt={'Refresh'} />
</IconButton>
);

View File

@@ -0,0 +1,20 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import * as styled from 'styled-components';
import {theme} from 'components/shared/theme';
const {
typography: {fontSizeL},
colors
} = theme;
export const IconButton = styled.default.button`
border: none;
background-color: transparent;
font-size: ${fontSizeL};
color: ${colors.white};
opacity: ${({disabled}) => (disabled ? 0.3 : 1)};
cursor: ${({disabled}) => (disabled ? 'not-allowed' : 'pointer')};
display: flex;
`;

View File

@@ -0,0 +1,57 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import * as styled from 'styled-components';
import Theme from 'theme';
export const Button = styled.default.button<{
backgroundColor?: string;
borderColor?: string;
textColor?: string;
disabled?: boolean;
}>`
${({backgroundColor, textColor, borderColor}) => styled.css`
color: ${textColor || Theme.colors.white};
background-color: ${backgroundColor || Theme.colors.white};
border-color: ${borderColor || backgroundColor || Theme.colors.lightRed};
`}
${({disabled}) => styled.css`
opacity: ${disabled ? 0.8 : 1};
cursor: ${disabled ? 'not-allowed' : 'pointer'};
`}
min-width: 120px;
text-align: center;
outline: none;
vertical-align: middle;
border-radius: ${Theme.primaryBorderRadius};
padding: ${Theme.spacing.small} ${Theme.spacing.medium};
font-size: ${Theme.typography.primaryFontSize};
transition: color .15s ease-in-out, background-color .15s ease-in-out;
`;
export const FilterButton = styled.default(Button)`
font-weight: bolder;
justify-self: center;
margin: 0 ${Theme.spacing.xSmall};
padding: ${Theme.spacing.small} ${Theme.spacing.xlarge};
`;
export const ConfirmButton = styled.default(Button)`
margin-right: 1rem;
display: flex;
align-items: center;
justify-content: center;
`;
export const CancelButton = styled.default(ConfirmButton)``;
export const CustomButton = styled.default(Button)`
background-color: ${Theme.dangerColor};
border-color: ${Theme.dangerColor};
color: ${Theme.colors.white};
font-weight: bolder;
justify-self: center;
margin: 0.75rem;
padding: ${Theme.spacing.small} ${Theme.spacing.xlarge};
overflow: visible;
`;

View File

@@ -0,0 +1,69 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import React, {Fragment} from 'react';
import {Tooltip, Position} from 'components/tooltip';
import {Label} from 'components/label';
import {RadioGroup, RadioWrapper, RadioButtonContainer, VisibleCheckBox} from './style';
interface IRadioItems {
label: string;
value: string;
tooltipMessage?: string;
tooltipPosition?: Position;
className?: string;
children?: React.JSX.Element;
disabled?: boolean;
}
interface IRadioButtonGroup {
items: IRadioItems[];
handleOnChange: (value: string) => void;
currentValue: string;
}
const RadioButton = (props: {currentValue: string; value: string}) => {
const {currentValue, value} = props;
return (
<RadioButtonContainer>
<input type="radio" readOnly={true} value={value} checked={currentValue === value} />
<VisibleCheckBox checked={currentValue === value}>
<div />
</VisibleCheckBox>
</RadioButtonContainer>
);
};
const RadioButtonGroup = (props: IRadioButtonGroup): React.JSX.Element => {
const {items, handleOnChange, currentValue} = props;
return (
<RadioGroup>
{items.map(({label, value, disabled, tooltipPosition, tooltipMessage, children, className}: IRadioItems, index: number) => (
<RadioWrapper
tabIndex={-1}
onKeyPress={() => null}
disabled={disabled}
className="button-container"
role="button"
key={label + index}
onClick={() => handleOnChange(value)}>
<RadioButton value={value} currentValue={currentValue} />
<Fragment>
{tooltipMessage ? (
<Tooltip position={tooltipPosition || Position.Top} message={tooltipMessage}>
<Label className={className} text={label} />
</Tooltip>
) : (
<Label className={className} text={label} />
)}
{children}
</Fragment>
</RadioWrapper>
))}
</RadioGroup>
);
};
export default RadioButtonGroup;

View File

@@ -0,0 +1,62 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import * as styled from 'styled-components';
import {theme, Theme} from 'components/shared/theme';
const {
spacing,
typography: {primaryFontSize},
colors
} = theme;
const paddings = Theme.paddings;
export const RadioGroup = styled.default.div`
display: flex;
`;
export const RadioWrapper = styled.default.div<{disabled?: boolean}>`
padding: ${paddings.small};
display: flex;
${({disabled}) =>
disabled &&
styled.css`
pointer-events: none;
opacity: 0.5;
`}
`;
export const RadioButtonContainer = styled.default.div`
margin-right: ${spacing.xSmall};
align-self: center;
input {
position: absolute;
visibility: hidden;
}
`;
export const VisibleCheckBox = styled.default.div<{checked?: boolean}>`
border: 2px solid ${colors.gray400};
display: flex;
align-items: center;
justify-content: center;
width: ${primaryFontSize};
height: ${primaryFontSize};
border-radius: 50%;
${({checked}) =>
checked &&
styled.css`
border: none;
background-color: ${colors.red};
div {
background-color: ${colors.black};
width: 5px;
height: 5px;
border-radius: 50%;
}
`}
`;

View File

@@ -0,0 +1,76 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import React from 'react';
import * as styled from 'styled-components';
import {theme} from 'components/shared/theme';
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
import {faBackward, faFastBackward, faFastForward, faForward} from '@fortawesome/free-solid-svg-icons';
const {colors, spacing} = theme;
const ScrollButton = styled.default.button`
border: none;
width: 25px;
height: 25px;
color: ${colors.white};
margin: ${spacing.xxSmall} 0;
background-color: ${colors.gray600};
cursor: pointer;
transform: rotate(90deg)
`;
const TwinButtons = styled.default.div`
display: flex;
position: absolute;
right: 64px;
bottom: 50px;
flex-direction: column;
`;
export const ScrollButtons = ({current}: {current: HTMLDivElement}): React.JSX.Element => {
const getScrollStep = (current: HTMLDivElement) => {
const tableViewHeight = current.offsetHeight;
return tableViewHeight / 2;
};
const scrollToTop = () => {
if (current) {
current.scrollTop = 0;
}
};
const scrollTop = () => {
if (current) {
current.scrollTop = current.scrollTop - getScrollStep(current);
}
};
const scrollBottom = () => {
if (current) {
current.scrollTop = current.scrollTop + getScrollStep(current);
}
};
const scrollToBottom = () => {
if (current) {
current.scrollTop = current.scrollHeight;
}
};
return (
<TwinButtons>
<ScrollButton onClick={scrollToTop}>
<FontAwesomeIcon icon={faFastBackward} />
</ScrollButton>
<ScrollButton onClick={scrollTop}>
<FontAwesomeIcon icon={faBackward} />
</ScrollButton>
<ScrollButton onClick={scrollBottom}>
<FontAwesomeIcon icon={faForward} />
</ScrollButton>
<ScrollButton onClick={scrollToBottom}>
<FontAwesomeIcon icon={faFastForward} />
</ScrollButton>
</TwinButtons>
);
};

View File

@@ -0,0 +1,67 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import React, {useState, useEffect, ChangeEvent, useCallback} from 'react';
import {faQuestionCircle} from '@fortawesome/free-solid-svg-icons';
import {documentationLinks} from 'constants/links';
import {NewTabLink} from 'components/new-tab-link';
import Input from 'components/forms/Input';
import {CopyIconButton} from 'components/buttons/copy-icon-button';
import {DialogForm, Error} from 'components/modal/modal-form-response/style';
const DeleteChannelForm = ({setIsValid, alias}: {setIsValid: (isValid: boolean) => void; alias: string}): React.JSX.Element => {
const [error, setError] = useState<string | null>(null);
const [enteredAlias, setEnteredAlias] = useState('');
const validate = useCallback((): boolean => {
if (!enteredAlias) {
setError('Please enter a channel alias');
setIsValid(false);
return false;
}
if (enteredAlias !== alias) {
setError('Entered alias does not match the channels alias');
setIsValid(false);
return false;
}
setError(null);
setIsValid(true);
return true;
}, [enteredAlias, alias, setIsValid]);
useEffect(() => {
if (enteredAlias.length) {
validate();
}
}, [enteredAlias, validate]);
const handleEnteredAlias = (event: ChangeEvent<HTMLInputElement>): void => {
if (error) {
setError(null);
}
setEnteredAlias(event.target.value);
};
return (
<DialogForm>
<h3 className="testId-deleteChannelForm">
Delete Channel <NewTabLink link={documentationLinks.deleteChannel} icon={faQuestionCircle} iconColor="black" />
</h3>
<p>To delete channel, please enter the channel alias:</p>
<strong>
<CopyIconButton text={alias} quoted />
</strong>
<Input name="alias" error={!!error} onChange={handleEnteredAlias} value={enteredAlias} />
{error && <Error className="error-text testId-displayMessage">{error}</Error>}
</DialogForm>
);
};
export default DeleteChannelForm;

View File

@@ -0,0 +1,111 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import React, {useState} from 'react';
import {useDispatch} from 'react-redux';
import LoggerFactory from 'services/logger/LoggerFactory';
import {deleteChannel} from 'services/Channel.service';
import {listChannels} from 'store/action/channels';
import {transformToPortalError} from 'utility/error-handler';
import {deleteChannelErrorMessages} from 'constants/error-messages';
import {MultiStepModal} from 'components/modal/multi-step-modal';
import DeleteChannelForm from './delete-channel-form';
import {FormResponse} from 'components/modal/modal-form-response';
interface IDeleteChannelModal {
isOpen: boolean;
setIsOpen: React.Dispatch<React.SetStateAction<boolean>>;
channelId: string;
alias: string;
redirect?: () => void;
}
export const DeleteChannelModal = ({isOpen, setIsOpen, channelId, alias, redirect}: IDeleteChannelModal): React.JSX.Element => {
const logger = LoggerFactory.getLogger('components/channel-icon-menu/delete-channel/DeleteChannelModal');
const dispatch = useDispatch();
const [isFormValid, setIsFormValid] = useState(false);
const [isFetching, setIsFetching] = useState(false);
const [deleteChannelResponse, setDeleteChannelResponse] = useState<{error: string | boolean | Error; status: string | number; data?: any} | null>(null);
const handleSubmit = async () => {
if (!isFormValid) {
return;
}
try {
setIsFetching(true);
logger.info('Deleting a channel [%s][%s]', alias, channelId);
const response = await deleteChannel({channelId, alias});
logger.info('Channel [%s][%s] was successfully deleted', alias, channelId);
setDeleteChannelResponse({status: 'ok', error: false, data: response});
setIsFetching(false);
} catch (e) {
const {status, message, requestPayload, statusCode} = transformToPortalError(e);
setIsFetching(false);
const errorMessage = (deleteChannelErrorMessages as Record<string, string>)[status] || message || deleteChannelErrorMessages['default'];
setDeleteChannelResponse({
status: statusCode || 'error',
error: errorMessage
});
logger.error(`${errorMessage} [%s]`, status, requestPayload);
}
};
const handleCloseModal = (): void => {
setIsOpen(false);
};
const onDeleteSuccess = async (): Promise<void> => {
setIsOpen(false);
logger.info('Updating the list of channels after the [%s][%s] channel was deleted', alias, channelId);
await dispatch(listChannels() as any);
logger.info('The list of channels was updated successfully');
if (redirect) {
redirect();
}
};
return (
<MultiStepModal
isOpen={isOpen}
closeModal={deleteChannelResponse?.status === 'ok' ? onDeleteSuccess : handleCloseModal}
steps={[
{
title: 'Delete Channel',
component: <DeleteChannelForm alias={alias} setIsValid={setIsFormValid} />,
saveButton: {
text: 'Delete Channel',
className: 'testId-deleteChannel',
disabled: !isFormValid || isFetching,
onClick: handleSubmit
}
},
{
title: 'Delete Channel',
component: <FormResponse response={deleteChannelResponse || {error: '', status: '', data: null}} />,
cancelDisabled: true,
saveButton: {
className: 'testId-doneButton',
onClick: onDeleteSuccess
}
}
]}
/>
);
};
export default DeleteChannelModal;

View File

@@ -0,0 +1,4 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
export {default} from './delete-channel-modal';

View File

@@ -0,0 +1,117 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import React, {useState, useEffect, useCallback} from 'react';
import {faQuestionCircle} from '@fortawesome/free-solid-svg-icons';
import {CapabilitiesType} from 'constants/capabilities';
import {documentationLinks} from 'constants/links';
import {Label} from 'components/forms/label';
import Checkbox from 'components/forms/Checkbox';
import {NewTabLink} from 'components/new-tab-link';
import {Dropdown} from 'components/drop-down';
import {InputWithTags} from 'components/ui/input-with-tags';
import {DialogForm, Error, Options} from 'components/modal/modal-form-response/style';
import {Capabilities} from 'components/create-token-components';
import Theme from 'theme';
const forkChannelOption = ['force', 'additive'];
const ForkChannelForm = ({
setFormData,
setIsValid,
channelList,
alias
}: {
setFormData: (data: any) => void;
setIsValid: (isValid: boolean) => void;
channelList: any[];
alias: string;
}): React.JSX.Element => {
const [error, setError] = useState<string | null>(null);
const [tags, setTags] = useState<string[]>([]);
const [forkOptions, setForkOptions] = useState<string[]>([]);
const [destinationChannelId, setDestinationChannelId] = useState('');
const [selectedCapabilities, setSelectedCapabilities] = useState<any[]>([]);
const [force, additive] = forkChannelOption;
const destinationChannelsList = channelList.filter(channel => channel.alias !== alias);
const validate = useCallback((): boolean => {
if (!destinationChannelId) {
setIsValid(false);
return false;
}
setError(null);
setIsValid(true);
setFormData({
streamCapabilities: selectedCapabilities.map(({value}) => value),
streamTags: tags,
options: forkOptions,
destinationChannelId
});
return true;
}, [destinationChannelId, selectedCapabilities, tags, forkOptions, setIsValid, setFormData]);
useEffect(() => {
validate();
}, [validate]);
const handleForkOptions = (value: string) => {
if (forkOptions.indexOf(value) > -1) {
const currentForkOptions = forkOptions.filter(item => item !== value);
setForkOptions(currentForkOptions);
} else {
setForkOptions([...forkOptions, value]);
}
};
const handleSetDestinationChannelId = (channelAlias: string): void => {
const channels = channelList.filter(channel => channel.alias === channelAlias);
if (channels[0]) {
const {channelId} = channels[0];
setDestinationChannelId(channelId);
setError(null);
}
};
return (
<DialogForm>
<h3 className="testId-forkChannelForm">
Fork Channel <NewTabLink link={documentationLinks.forkChannel} icon={faQuestionCircle} iconColor="black" />
</h3>
<p>
Fork <strong>"{alias}"</strong> to destination channel:
</p>
<Dropdown
name={'alias'}
label="Destination Channel Alias"
items={destinationChannelsList}
itemKey={'alias'}
onSelect={handleSetDestinationChannelId}
className="testId-destinationChannelAlias"
/>
{error && <Error>Please select a Channel from the list</Error>}
<Capabilities
label="Capabilities:"
labelColor={Theme.colors.gray900}
iconColor={Theme.colors.gray900}
capabilitiesSetTitle={CapabilitiesType.Forking}
selectedItems={selectedCapabilities}
setSelectedItems={setSelectedCapabilities}
/>
<Label text="Options" />
<Options>
<Checkbox value={force} id={force} onChange={() => handleForkOptions(force)} checked={forkOptions.indexOf(force) > -1} label={force} />
<Checkbox value={additive} id={additive} onChange={() => handleForkOptions(additive)} checked={forkOptions.indexOf(additive) > -1} label={additive} />
</Options>
<Label htmlFor="input-tag" text="Stream Tags" />
<InputWithTags id="input-tag" onTagListChange={setTags} defaultValue={tags} />
</DialogForm>
);
};
export default ForkChannelForm;

View File

@@ -0,0 +1,113 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import React, {useState} from 'react';
import {useSelector} from 'react-redux';
import LoggerFactory from 'services/logger/LoggerFactory';
import {forkChannel} from 'services/Channel.service';
import {AppStore} from 'store';
import {channelsSelector} from 'store/action/channels';
import {transformToPortalError} from 'utility/error-handler';
import {forkChannelErrorMessages} from 'constants/error-messages';
import {MultiStepModal} from 'components/modal/multi-step-modal';
import ForkChannelForm from './fork-channel-form';
import {FormResponse} from 'components/modal/modal-form-response';
interface IForkChannelModal {
isOpen: boolean;
setIsOpen: React.Dispatch<React.SetStateAction<boolean>>;
channelId: string;
alias: string;
}
export const ForkChannelModal = ({isOpen, setIsOpen, channelId, alias}: IForkChannelModal): React.JSX.Element => {
const logger = LoggerFactory.getLogger('components/channel-icon-menu/fork-channel/ForkChannelModal');
const channelsState = useSelector((state: AppStore) => channelsSelector(state));
const channelList = channelsState.channels || [];
const [formData, setFormData] = useState({
streamCapabilities: [] as string[],
streamTags: [] as string[],
options: [] as string[],
destinationChannelId: ''
});
const [isFormValid, setIsFormValid] = useState(false);
const [isFetching, setIsFetching] = useState(false);
const [forkResponse, setForkResponse] = useState<{error: string | boolean | Error; status: string | number; data?: any} | null>(null);
const handleSubmit = async () => {
if (!isFormValid) {
return;
}
try {
setIsFetching(true);
const {streamCapabilities, streamTags, options, destinationChannelId} = formData;
logger.info('Forking a channel [%s] to [%s]', channelId, destinationChannelId);
const response = await forkChannel({
sourceChannelId: channelId,
destinationChannelId,
streamCapabilities,
streamTags,
options
});
logger.info('The channel [%s] was successfully forked to [%s]', channelId, destinationChannelId);
setForkResponse({
status: 'ok',
error: false,
data: response
});
setIsFetching(false);
} catch (e) {
const {status, message, requestPayload, statusCode} = transformToPortalError(e);
setIsFetching(false);
const errorMessage = (forkChannelErrorMessages as Record<string, string>)[status] || message || forkChannelErrorMessages['default'];
setForkResponse({
status: statusCode || 'error',
error: errorMessage
});
logger.error(`${errorMessage} [%s]`, status, requestPayload);
}
};
const handleCloseModal = (): void => {
setIsOpen(false);
};
return (
<MultiStepModal
isOpen={isOpen}
closeModal={handleCloseModal}
steps={[
{
title: 'Fork Channel',
component: <ForkChannelForm alias={alias} channelList={channelList} setIsValid={setIsFormValid} setFormData={setFormData} />,
saveButton: {
text: 'Fork Channel',
className: 'testId-forkChannel',
disabled: !isFormValid || isFetching,
onClick: handleSubmit
}
},
{
title: 'Fork Channel',
component: <FormResponse response={forkResponse || {error: '', status: '', data: null}} />,
cancelDisabled: true,
saveButton: {className: 'testId-doneButton'}
}
]}
/>
);
};
export default ForkChannelModal;

View File

@@ -0,0 +1,4 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
export {default} from './fork-channel-modal';

View File

@@ -0,0 +1,65 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import React, {useState} from 'react';
import {IconDefinition} from '@fortawesome/free-solid-svg-icons';
import {IconMenu} from 'components/icon-menu';
import {IconMenuPosition} from 'components/icon-menu/types';
import ForkChannelModal from './fork-channel';
import DeleteChannelModal from './delete-channel';
import KillChannelModal from './kill-channel';
interface IChannelIconMenu {
data: {
name: string;
channelId: string;
applicationId: string;
alias: string;
};
redirect?: () => void;
showTail?: boolean;
position?: IconMenuPosition;
icon?: IconDefinition;
margin?: number;
}
export const ChannelIconMenu = (props: IChannelIconMenu): React.JSX.Element => {
const {data, icon, redirect, showTail, position, margin} = props;
const {alias, channelId} = data;
const [isForkModalOpen, setIsForkModalOpen] = useState(false);
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
const [isKillModalOpen, setIsKillModalOpen] = useState(false);
const items = [
{
value: 'delete',
title: 'Delete',
className: 'testId-deleteMenuItem',
onClick: () => setIsDeleteModalOpen(true)
},
{
value: 'kill',
title: 'Kill',
className: 'testId-killMenuItem',
onClick: () => setIsKillModalOpen(true)
},
{
value: 'fork',
title: 'Fork',
className: 'testId-forkMenuItem',
onClick: () => setIsForkModalOpen(true)
}
];
return (
<>
<IconMenu icon={icon} items={items} showTail={showTail} position={position} margin={margin} />
{isForkModalOpen && <ForkChannelModal isOpen={isForkModalOpen} setIsOpen={setIsForkModalOpen} channelId={channelId} alias={alias} />}
{isDeleteModalOpen && (
<DeleteChannelModal isOpen={isDeleteModalOpen} setIsOpen={setIsDeleteModalOpen} channelId={channelId} alias={alias} redirect={redirect} />
)}
{isKillModalOpen && <KillChannelModal isOpen={isKillModalOpen} setIsOpen={setIsKillModalOpen} channelId={channelId} alias={alias} />}
</>
);
};

View File

@@ -0,0 +1,4 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
export {default} from './kill-channel-modal';

View File

@@ -0,0 +1,137 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import React, {useState, useEffect, ChangeEvent, useCallback} from 'react';
import {faQuestionCircle} from '@fortawesome/free-solid-svg-icons';
import {documentationLinks} from 'constants/links';
import Checkbox from 'components/forms/Checkbox';
import {Label} from 'components/label';
import {NewTabLink} from 'components/new-tab-link';
import {DialogForm, Error, Options} from 'components/modal/modal-form-response/style';
import {CopyIconButton} from 'components/buttons/copy-icon-button';
import {Tooltip, Position} from 'components/tooltip';
import {Input} from 'components/ui';
const keepStreams = 'keep-streams';
const keepStreamsTooltipMessage = 'Keeps the removed streams alive';
const destroyRequired = 'destroy-required';
const destroyRequiredTooltipMessage = 'Returns an error if destroying of a stream fails';
const defaultReason = 'portal:killed';
const KillChannelForm = ({
setFormData,
setIsValid,
alias
}: {
setFormData: (data: any) => void;
setIsValid: (isValid: boolean) => void;
alias: string;
}): React.JSX.Element => {
const [error, setError] = useState<string | null>(null);
const [enteredAlias, setEnteredAlias] = useState('');
const [reason, setReason] = useState(defaultReason);
const [options, setOptions] = useState<string[]>([]);
const validate = useCallback((): boolean => {
if (!enteredAlias) {
setError('Please enter a channel alias');
setIsValid(false);
return false;
}
if (enteredAlias !== alias) {
setError('Entered alias does not match the channels alias');
setIsValid(false);
return false;
}
setError(null);
setIsValid(true);
setFormData({
reason,
options,
enteredAlias
});
return true;
}, [enteredAlias, alias, reason, options, setIsValid, setFormData, setError]);
useEffect(() => {
if (enteredAlias.length) {
validate();
}
}, [enteredAlias, validate]);
const handleAlias = (event: ChangeEvent<HTMLInputElement>): void => {
if (error) {
setError(null);
}
setEnteredAlias(event.target.value);
};
const handleKillOptions = (value: string) => {
if (options.indexOf(value) > -1) {
const currentOptions = options.filter(item => item !== value);
setOptions(currentOptions);
} else {
setOptions([...options, value]);
}
};
const handleReason = (event: ChangeEvent<HTMLInputElement>): void => {
if (error) {
setError(null);
}
setReason(event.target.value);
};
return (
<DialogForm>
<h3 className="testId-killChannelForm">
Kill Channel <NewTabLink link={documentationLinks.killChannel} icon={faQuestionCircle} iconColor="black" />
</h3>
<p>Terminates all streams and removes them from the channel.</p>
<p>To kill the channel, please enter the channel alias:</p>
<strong>
<CopyIconButton text={alias} quoted />
</strong>
<Input error={!!error} onChange={handleAlias} value={enteredAlias} name="alias" />
{error && (
<Error className="error-text">
Please enter the channel alias <i>{alias}</i>
</Error>
)}
<h5>Kill options:</h5>
<Options>
<Tooltip position={Position.Bottom} message={keepStreamsTooltipMessage}>
<Checkbox
value={keepStreams}
id={keepStreams}
onChange={() => handleKillOptions(keepStreams)}
checked={options.indexOf(keepStreams) > -1}
label={keepStreams}
/>
</Tooltip>
<Tooltip position={Position.Bottom} message={destroyRequiredTooltipMessage}>
<Checkbox
value={destroyRequired}
id={destroyRequired}
onChange={() => handleKillOptions(destroyRequired)}
checked={options.indexOf(destroyRequired) > -1}
label={destroyRequired}
/>
</Tooltip>
</Options>
<Label htmlFor="reason" text="Reason:" />
<Input id="reason" error={!!error} onChange={handleReason} value={reason} />
</DialogForm>
);
};
export default KillChannelForm;

View File

@@ -0,0 +1,106 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import React, {useState} from 'react';
import LoggerFactory from 'services/logger/LoggerFactory';
import {killChannel} from 'services/Channel.service';
import {transformToPortalError} from 'utility/error-handler';
import {killChannelErrorMessages} from 'constants/error-messages';
import {MultiStepModal} from 'components/modal/multi-step-modal';
import KillChannelForm from './kill-channel-form';
import {FormResponse} from 'components/modal/modal-form-response';
interface IKillChannelModal {
isOpen: boolean;
setIsOpen: React.Dispatch<React.SetStateAction<boolean>>;
channelId: string;
alias: string;
}
export const KillChannelModal = ({isOpen, setIsOpen, channelId, alias}: IKillChannelModal): React.JSX.Element => {
const logger = LoggerFactory.getLogger('components/channel-icon-menu/kill-channel/KillChannelModal');
const [formData, setFormData] = useState({
reason: '',
options: [] as string[],
enteredAlias: ''
});
const [isFormValid, setIsFormValid] = useState(false);
const [isFetching, setIsFetching] = useState(false);
const [killResponse, setKillResponse] = useState<{error: string | boolean | Error; status: string | number; data?: any} | null>(null);
const handleSubmit = async () => {
if (!isFormValid) {
return;
}
try {
setIsFetching(true);
const {reason, options} = formData;
logger.info('Killing a channel [%s] with reason [%s]', channelId, reason);
const response = await killChannel({
channelId,
reason,
options,
enteredAlias: formData.enteredAlias
});
logger.info('The channel [%s] was successfully killed', channelId);
setKillResponse({
status: 'ok',
error: false,
data: response
});
setIsFetching(false);
} catch (e) {
const {status, message, requestPayload, statusCode} = transformToPortalError(e);
setIsFetching(false);
const errorMessage = (killChannelErrorMessages as Record<string, string>)[status] || message || killChannelErrorMessages['default'];
setKillResponse({
status: statusCode || 'error',
error: errorMessage
});
logger.error(`${errorMessage} [%s]`, status, requestPayload);
}
};
const handleCloseModal = (): void => {
setIsOpen(false);
};
return (
<MultiStepModal
isOpen={isOpen}
closeModal={handleCloseModal}
steps={[
{
title: 'Kill Channel',
component: <KillChannelForm alias={alias} setIsValid={setIsFormValid} setFormData={setFormData} />,
saveButton: {
text: 'Kill Channel',
className: 'testId-killChannel',
disabled: !isFormValid || isFetching,
onClick: handleSubmit
}
},
{
title: 'Kill Channel',
component: <FormResponse response={killResponse || {error: '', status: '', data: null}} />,
cancelDisabled: true,
saveButton: {className: 'testId-doneButton'}
}
]}
/>
);
};
export default KillChannelModal;

View File

@@ -0,0 +1,66 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import {JSX, useEffect, useState} from 'react';
import {faQuestionCircle} from '@fortawesome/free-solid-svg-icons';
import {documentationLinks} from 'constants/links';
import {CapabilitiesType, capabilities} from 'constants/capabilities';
import {AdvancedSelect, IAdvancedSelectItem} from 'components/ui/advanced-select';
import {NewTabLink} from 'components/new-tab-link';
import Theme from 'theme';
interface ICapabilities {
selectedItems: IAdvancedSelectItem[];
setSelectedItems: (items: IAdvancedSelectItem[]) => void;
data?: IAdvancedSelectItem[];
label?: string;
labelColor?: string;
iconColor?: string;
capabilitiesSetTitle?: string;
className?: string;
allowMultiple?: boolean;
}
export const Capabilities = ({
label,
labelColor = Theme.colors.white,
iconColor = Theme.colors.white,
data = capabilities,
selectedItems,
setSelectedItems,
capabilitiesSetTitle = '',
className,
allowMultiple = true
}: ICapabilities): JSX.Element => {
const [capabilitiesSet, setCapabilitiesSet] = useState(data);
useEffect(() => {
const filteredCapabilities = data.filter(capability => {
return capabilitiesSetTitle ? capability.type.includes(capabilitiesSetTitle) : true;
});
setCapabilitiesSet(filteredCapabilities);
}, [capabilitiesSetTitle]);
return (
<AdvancedSelect
allowMultiple={allowMultiple}
label={label}
labelColor={labelColor}
labelIcon={
capabilitiesSetTitle !== CapabilitiesType.Quality ? (
<NewTabLink link={documentationLinks.supportedStreamCapabilities} icon={faQuestionCircle} iconColor={iconColor} />
) : undefined
}
data={capabilitiesSet}
selectedItems={selectedItems}
setSelectedItems={setSelectedItems}
className={className}
/>
);
};
export default Capabilities;

View File

@@ -0,0 +1,8 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
export {default as Capabilities} from './capabilities';
export {default as ValidityTimeComponent} from './validity-time';
export * from './validity-time';
export {default as LabelIconTooltip} from './label-icon-tooltip';
export * from './styles';

View File

@@ -0,0 +1,37 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import React from 'react';
import {AdvancedSelect, IAdvancedSelectItem} from '../ui/advanced-select';
import {Label} from '../forms/label';
interface CapabilitiesProps {
label: string;
labelColor?: string;
iconColor?: string;
capabilitiesSetTitle: string;
selectedItems: IAdvancedSelectItem[];
setSelectedItems: (items: IAdvancedSelectItem[]) => void;
}
export const Capabilities: React.FC<CapabilitiesProps> = ({label, labelColor, iconColor, capabilitiesSetTitle, selectedItems, setSelectedItems}) => {
// Mock capabilities data - in a real app this would come from constants/capabilities
const mockCapabilities: IAdvancedSelectItem[] = [
{value: 'streaming', text: 'Streaming'},
{value: 'recording', text: 'Recording'},
{value: 'analytics', text: 'Analytics'},
{value: 'transcoding', text: 'Transcoding'}
];
return (
<div>
<Label text={label} />
<AdvancedSelect
items={mockCapabilities}
selectedItems={selectedItems}
setSelectedItems={setSelectedItems}
placeholder={`Select ${capabilitiesSetTitle} capabilities...`}
/>
</div>
);
};

View File

@@ -0,0 +1,22 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import React from 'react';
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
import {faQuestionCircle, IconDefinition} from '@fortawesome/free-solid-svg-icons';
import {Tooltip, Position} from 'components/tooltip';
interface ILabelIconTooltip {
message: string;
icon?: IconDefinition;
position?: Position;
}
export const LabelIconTooltip = ({message, icon, position}: ILabelIconTooltip): React.JSX.Element => (
<Tooltip position={position || Position.Right} message={message} width={300}>
<FontAwesomeIcon icon={icon || faQuestionCircle} />
</Tooltip>
);
export default LabelIconTooltip;

View File

@@ -0,0 +1,57 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import * as styled from 'styled-components';
import {theme} from 'components/shared/theme';
import {RadioGroup} from 'components/buttons/radio-button/style';
// import Input from 'components/forms/Input';
const {spacing, colors} = theme;
export const CreateTokenContainer = styled.default.div`
margin: 0.5rem 0 0;
`;
export const FormWell = styled.default.div`
display: flex;
flex-wrap: wrap;
width: 100%;
`;
export const RadioButtonContainer = styled.default.div`
display: flex;
flex-direction: column;
margin-top: ${spacing.small} 0;
label {
font-size: 14px;
color: ${colors.white};
}
${RadioGroup}{
flex-direction: column;
.reason-input {
display: flex;
flex-grow: 1;
}
}
`;
export const InputGroup = styled.default.div`
margin: 0 1rem 1rem 0;
input {
width: 200px;
padding-left: ${spacing.small};
}
> label {
display: block;
}
select {
width: 200px;
}
`;
export const RowsWrapper = styled.default.div`
width: 100%;
display: flex;
justify-content: space-between;
`;

View File

@@ -0,0 +1,56 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import React, {Fragment} from 'react';
import moment from 'moment';
import {ISelectItemWithClassOptions} from 'interfaces';
import RadioButtonGroup from 'components/buttons/radio-button';
import {Label} from 'components/label';
import {RadioButtonContainer} from '.';
export const validityTimeOptions: ISelectItemWithClassOptions<string> = {
hour: {
label: '1 Hour',
value: `${moment.duration(1, 'hour').asSeconds()}`
},
day: {
label: '1 Day',
value: `${moment.duration(1, 'day').asSeconds()}`
},
week: {
label: '1 Week',
value: `${moment.duration(1, 'week').asSeconds()}`
},
month: {
label: '1 Month',
value: `${moment.duration(1, 'month').asSeconds()}`
},
year: {
label: '1 Year',
value: `${moment.duration(1, 'year').asSeconds()}`
},
decade: {
label: '10 Years',
value: `${moment.duration(10, 'year').asSeconds()}`
}
};
interface IValidityTimeComponent {
onChange: (value: string) => void;
currentValue: string;
}
export const ValidityTimeComponent = ({currentValue, onChange}: IValidityTimeComponent): React.JSX.Element => (
<Fragment>
<Label text="Valid For:" color="white" />
<RadioButtonContainer className="testId-expirationTime">
<RadioButtonGroup items={Object.values(validityTimeOptions)} currentValue={currentValue} handleOnChange={onChange} />
</RadioButtonContainer>
</Fragment>
);
export default ValidityTimeComponent;

View File

@@ -0,0 +1,40 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import {JSX, useEffect, useState} from 'react';
import {useSelector} from 'react-redux';
import {Moment} from 'moment';
import {AppStore} from 'store';
import {getTimezoneAbbreviation, isoTimeFormat} from 'utility/date';
export const DateComponent = ({date, className}: {date: Moment; className?: string}): JSX.Element => {
const preferredTimeFormat = useSelector((state: AppStore) => state.preferredTimeFormat.timeFormat);
const isUTC = preferredTimeFormat === 'utc';
const utcDate = date.isValid() ? date.format(`${isoTimeFormat} UTC`) : '';
const localDate = date.isValid() ? `${date.clone().local().format(isoTimeFormat)} ${getTimezoneAbbreviation(date.toDate())}` : '';
const defaultDate = isUTC ? utcDate : localDate;
const hoverDate = isUTC ? localDate : utcDate;
const [currentDate, setCurrentDate] = useState(defaultDate);
useEffect(() => {
setCurrentDate(defaultDate);
}, [date, preferredTimeFormat]);
const onMouseEnter = () => {
setCurrentDate(hoverDate);
};
const onMouseOut = () => {
setCurrentDate(defaultDate);
};
const onBlur = () => {
setCurrentDate(defaultDate);
};
return (
<p onMouseEnter={onMouseEnter} onMouseOut={onMouseOut} onBlur={onBlur} className={className}>
{currentDate}
</p>
);
};

View File

@@ -0,0 +1,206 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import React, {useState, useEffect, useRef} from 'react';
import {IChannel} from 'interfaces';
import {Label} from 'components/label';
import {DropdownContainer, DropdownInput, DropdownMenu, DropdownMenuItem} from './style';
const keys = ['ArrowDown', 'ArrowUp', 'Enter', 'Escape'];
interface IDropdown {
itemKey: string;
searchTerm?: string;
onSelect: (key: string) => void;
items: IChannel[];
label: string;
name: string;
className?: string;
}
const maxNumOfItemsShown = 30;
export const Dropdown = (props: IDropdown): React.JSX.Element => {
const {itemKey, searchTerm, onSelect, items, label, name, className} = props;
const [showDropdownMenu, setShowDropdownMenu] = useState(false);
const [input, setInput] = useState(searchTerm || '');
const [filteredItems, setFilteredItems] = useState(items);
const [selectedIndex, setSelectedIndex] = useState(0);
const allItemsRef = useRef<any[]>([]);
const parentElementRef = useRef<HTMLDivElement | null>(null);
const scrollSelectedItemInView = (index: number) => {
if (!parentElementRef.current) {
return;
}
const dropdownMenu = parentElementRef.current;
const menuItems = allItemsRef.current;
if (!menuItems) {
return;
}
const menuItem = menuItems[index];
if (!menuItem) {
return;
}
const isOutOfUpperView = menuItem.offsetTop < dropdownMenu.scrollTop;
const isOutOfLowerView = menuItem.offsetTop + menuItem.clientHeight > dropdownMenu.scrollTop + dropdownMenu.clientHeight;
if (isOutOfUpperView) {
dropdownMenu.scrollTop = menuItem.offsetTop;
} else if (isOutOfLowerView) {
dropdownMenu.scrollTop = menuItem.offsetTop + menuItem.clientHeight - dropdownMenu.clientHeight;
}
};
const setSelectInput = (value: string) => {
setInput(value);
onSelect(value);
};
const handleClickOutside = (event: MouseEvent) => {
if (!parentElementRef.current || parentElementRef.current.contains(event.target as Node)) {
return;
}
if (!filteredItems.length) {
setSelectInput('');
}
setShowDropdownMenu(false);
onSelect(input);
};
useEffect(() => {
scrollSelectedItemInView(selectedIndex);
}, [selectedIndex]);
useEffect(() => {
document.addEventListener('click', handleClickOutside, true);
return () => {
document.removeEventListener('click', handleClickOutside, true);
};
});
useEffect(() => {
const filteredItems = items.filter(item => {
if ((item as any)[itemKey].toLowerCase().indexOf(input.toLowerCase()) > -1) {
return true;
}
return false;
});
if (filteredItems.length > 0) {
setSelectedIndex(0);
}
setFilteredItems(filteredItems);
}, [input, items, itemKey]);
const selectItemInFocusBy = (offset: number) => {
const lastIndex = filteredItems.length - 1;
const nextIndex = selectedIndex + offset;
if (nextIndex > lastIndex) {
setSelectedIndex(0);
} else if (nextIndex < 0) {
setSelectedIndex(lastIndex);
} else {
setSelectedIndex(nextIndex);
}
};
const handleOnKeyDown = (event: React.KeyboardEvent) => {
if (keys.indexOf(event.key) === -1) {
return;
}
const [arrDown, arrUp, enter, escape] = keys;
const moves = {
[arrDown]: 1,
[arrUp]: -1
};
const move = moves[event.key];
if (move !== undefined) {
event.preventDefault();
selectItemInFocusBy(move);
}
if (event.key === enter) {
if (filteredItems[selectedIndex]) {
setSelectInput((filteredItems[selectedIndex] as any)[itemKey]);
setShowDropdownMenu(false);
}
}
if (event.key === escape) {
event.preventDefault();
setShowDropdownMenu(false);
}
};
const selectItem = (index: number) => {
setSelectInput((filteredItems[index] as any)[itemKey]);
setSelectedIndex(index);
setShowDropdownMenu(false);
};
const generateMenuOptions = () => {
return filteredItems.length ? (
filteredItems.slice(0, maxNumOfItemsShown).map((item, index) => {
return (
<DropdownMenuItem
ref={ref => {
allItemsRef.current[index] = ref;
}}
selected={selectedIndex === index}
key={`dropdown-menu-item-${index}`}
onClick={() => selectItem(index)}>
{(item as any)[itemKey]}
</DropdownMenuItem>
);
})
) : (
<DropdownMenuItem disabled={true}>No results found</DropdownMenuItem>
);
};
const handleInput = (event: React.ChangeEvent<HTMLInputElement>) => {
const {target} = event;
setInput(target.value);
if (!showDropdownMenu) {
setShowDropdownMenu(true);
}
};
const toggleDropdownMenu = () => setShowDropdownMenu(!showDropdownMenu);
return (
<DropdownContainer>
<Label htmlFor="autocomplete" text={label} />
<DropdownInput
onKeyDown={handleOnKeyDown}
showMenu={showDropdownMenu}
autoComplete="off"
name={name}
onChange={handleInput}
value={input}
onClick={toggleDropdownMenu}
className={className}
/>
{showDropdownMenu && (
<DropdownMenu ref={parentElementRef} className="testId-generatedMenuOptions">
{generateMenuOptions()}
</DropdownMenu>
)}
</DropdownContainer>
);
};

View File

@@ -0,0 +1,61 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import * as styled from 'styled-components';
import Input from 'components/forms/Input';
import Theme from 'theme';
const {spacing, colors, typography, primaryBorderRadius} = Theme;
export const DropdownContainer = styled.default.div`
width: 100%;
position: relative;
margin: ${spacing.xSmall} 0;
`;
export const DropdownInput = styled.default(Input)<{showMenu?: boolean}>`
${({showMenu}) =>
showMenu &&
styled.css`
border-bottom-left-radius: 0px;
border-bottom-right-radius: 0px;
border-bottom-width: 0;
`}
`;
export const DropdownMenu = styled.default.div`
width: 100%;
overflow-x: hidden;
overflow-y: auto;
top: calc(100% - 4px);
position: absolute;
height: auto;
max-height: 210px;
border: 1px solid ${colors.gray400};
border-top-width: 0;
z-index: 4;
background-color: ${colors.white};
border-bottom-left-radius: ${primaryBorderRadius};
border-bottom-right-radius: ${primaryBorderRadius};
`;
export const DropdownMenuItem = styled.default.div<{
active?: boolean;
disabled?: boolean;
selected?: boolean;
}>`
line-height: ${spacing.large};
padding: ${spacing.xsmall} ${spacing.medium};
font-size: ${typography.fontSizeS};
word-wrap: break-word;
${({active, selected, disabled}) => styled.css`
background-color: ${active || selected ? colors.gray300 : 'transparent'};
font-weight: ${selected ? 'bold' : 'normal'};
color: ${disabled ? colors.gray500 : colors.gray900}
:hover{
background-color: ${disabled ? colors.white : colors.gray300};
cursor: ${disabled ? 'text' : 'pointer'};
}
`}
`;

View File

@@ -0,0 +1,12 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import {toast} from 'react-toastify';
export const toastErrorRenderer = (error: string): void => {
toast.error(String(error), {
autoClose: 10000,
draggable: false,
hideProgressBar: true
});
};

View File

@@ -0,0 +1,23 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import * as styled from 'styled-components';
import Theme from 'theme';
const {headerAllowance, dangerColor, typography} = Theme;
export const Error = styled.default.div`
height: ${window.innerHeight - headerAllowance}px;
width: 100%;
display: grid;
align-content: center;
justify-content: center;
text-align: center;
color: ${dangerColor};
font-size: ${typography.fontSizeL};
`;
export const ErrorSubMessage = styled.default.div`
font-size: ${typography.fontSizeS};
color: ${dangerColor};
`;

View File

@@ -0,0 +1,81 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import React, {ChangeEvent, MouseEvent} from 'react';
import styled from 'styled-components';
import {Label} from 'components/label';
import {theme} from 'components/shared/theme';
const {colors, spacing} = theme;
const Container = styled.div`
display: flex;
flex-direction: row;
align-items: center;
label {
margin-left: ${spacing.xxSmall};
margin-right: ${spacing.xxSmall};
}
`;
const CheckboxContainer = styled.div`
display: inline-block;
vertical-align: middle;
outline: none;
height: 1rem;
`;
const Icon = styled.svg`
fill: none;
stroke: ${colors.black};
stroke-width: 2px;
`;
const HiddenCheckbox = styled.input.attrs({type: 'checkbox'})`
border: 0;
clip: rect(0 0 0 0);
clip-path: inset(50%);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
white-space: nowrap;
width: 1px;
`;
const StyledCheckbox = styled.div<{checked?: boolean}>`
display: inline-block;
width: 1rem;
height: 1rem;
background: ${({checked}) => (checked ? colors.red : colors.transparent)};
border-radius: 3px;
transition: all 150ms;
outline: none;
border: 1px solid ${({checked}) => (checked ? 'none' : colors.gray400)};
${Icon} {
visibility: ${({checked}) => (checked ? 'visible' : 'hidden')};
}
`;
const Checkbox = (props: {
value: string;
id?: string;
checked?: boolean;
onChange: (event: ChangeEvent<HTMLInputElement> | MouseEvent<HTMLDivElement>) => void;
label?: string;
}): React.JSX.Element => {
const {checked, onChange, label, id} = props;
return (
<Container>
<CheckboxContainer>
<HiddenCheckbox {...props} />
<StyledCheckbox onClick={onChange} checked={checked}>
<Icon viewBox="0 0 24 24">
<polyline points="20 6 9 17 4 12" />
</Icon>
</StyledCheckbox>
</CheckboxContainer>
{label && <Label htmlFor={id || label} text={label} />}
</Container>
);
};
export default Checkbox;

View File

@@ -0,0 +1,74 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import React, {ChangeEvent} from 'react';
import styled from 'styled-components';
import {theme} from 'components/shared/theme';
const CheckboxContainer = styled.div`
display: flex;
align-items: center;
margin-bottom: ${theme.spacing.small};
`;
const HiddenCheckbox = styled.input.attrs({type: 'checkbox'})`
position: absolute;
opacity: 0;
cursor: pointer;
height: 0;
width: 0;
`;
const StyledCheckbox = styled.div<{checked: boolean}>`
display: inline-block;
width: 16px;
height: 16px;
background: ${props => (props.checked ? theme.colors.red : theme.colors.white)};
border: 2px solid ${theme.colors.gray400};
border-radius: 3px;
transition: all 150ms;
cursor: pointer;
margin-right: ${theme.spacing.small};
&::after {
content: '';
position: relative;
display: ${props => (props.checked ? 'block' : 'none')};
left: 3px;
top: 0px;
width: 4px;
height: 8px;
border: solid ${theme.colors.white};
border-width: 0 2px 2px 0;
transform: rotate(45deg);
}
`;
const Label = styled.label`
cursor: pointer;
color: ${theme.colors.gray900};
font-size: ${theme.typography.primaryFontSize};
user-select: none;
`;
interface CheckboxProps {
id: string;
checked: boolean;
onChange: (event: ChangeEvent<HTMLInputElement>) => void;
label?: string;
value?: string;
disabled?: boolean;
className?: string;
}
const Checkbox: React.FC<CheckboxProps> = ({id, checked, onChange, label, value, disabled = false, className}) => {
return (
<CheckboxContainer className={className}>
<HiddenCheckbox id={id} checked={checked} onChange={onChange} value={value} disabled={disabled} />
<StyledCheckbox checked={checked} />
{label && <Label htmlFor={id}>{label}</Label>}
</CheckboxContainer>
);
};
export default Checkbox;

View File

@@ -0,0 +1,117 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import React, {ChangeEvent, forwardRef, ForwardedRef, InputHTMLAttributes} from 'react';
import * as styled from 'styled-components';
import Theme from 'theme';
import {Label} from './label';
export interface IInput extends InputHTMLAttributes<HTMLInputElement> {
onChange?: (event: ChangeEvent<HTMLInputElement>) => void;
error?: boolean;
icon?: React.JSX.Element;
imagePath?: string;
imageAltText?: string;
label?: string;
labelColor?: string;
labelIcon?: React.JSX.Element;
labelClassName?: string;
helperText?: string;
helperTextClassName?: string;
width?: number | string;
}
const {colors, typography, formFieldWidth, formFieldMaxWidth, primaryBorderColor, primaryBorderRadius, primaryInputHeight, inputIconWidth, spacing} = Theme;
export const InputElement = styled.default.input<IInput>`
background-color: ${colors.white};
border: 1px solid ${({error}) => (error ? colors.lightRed : primaryBorderColor)};
border-radius: ${primaryBorderRadius};
display: block;
font-size: ${typography.primaryFontSize};
height: ${primaryInputHeight};
line-height: ${typography.primaryLineHeight};
outline: none;
padding: ${spacing.small} ${({icon, imagePath}) => (icon || imagePath ? spacing.xlarge : spacing.small)};
transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out;
background-position: 1rem center;
background-repeat: no-repeat;
width: inherit;
opacity: ${({disabled}) => (disabled ? 0.8 : 1)};
cursor: ${({disabled}) => disabled && 'not-allowed'};
-webkit-text-fill-color: ${({disabled}) => disabled && colors.gray800};
`;
const HelperText = styled.default.p<IInput>`
color: ${({error}) => (error ? colors.lightRed : colors.gray600)};
font-weight: 400;
font-size: ${typography.fontSizeS};
margin-top: ${spacing.xxSmall};
`;
const ImageWrapper = styled.default.div`
width: ${inputIconWidth}px;
height: ${inputIconWidth}px;
z-index: 1;
top: calc(50% - ${inputIconWidth / 2}px);
left: 8px;
position: absolute;
display: flex;
align-items: center;
& img, svg {
width: ${inputIconWidth}px;
height: ${inputIconWidth}px;
}
`;
const InputWrapper = styled.default.div`
width: 100%;
position: relative;
`;
export const InputComponentWrapper = styled.default.div<IInput>`
position: relative;
width: ${({width}) => (width && isNaN(+width) ? width : (width || formFieldWidth) + 'px')};
max-width: ${formFieldMaxWidth}px;
display: flex;
flex-direction: column;
`;
export const InputComponent = forwardRef(
(
{
label,
labelColor,
labelIcon,
labelClassName,
icon,
imagePath,
imageAltText = '',
helperText,
helperTextClassName,
error,
width,
disabled,
name,
...props
}: IInput,
ref: ForwardedRef<HTMLInputElement>
): React.JSX.Element => {
const InputIcon = icon || (imagePath && <img src={imagePath} alt={imageAltText} />);
return (
<InputComponentWrapper width={width}>
{!!label && <Label text={label} color={labelColor} icon={labelIcon} className={labelClassName} />}
<InputWrapper>
<ImageWrapper>{InputIcon}</ImageWrapper>
<InputElement icon={icon} name={name} imagePath={imagePath} disabled={disabled} ref={ref} {...props} />
</InputWrapper>
{!!helperText && (
<HelperText className={helperTextClassName} error={error}>
{helperText}
</HelperText>
)}
</InputComponentWrapper>
);
}
);
export default InputComponent;
export const Input = InputComponent;

View File

@@ -0,0 +1,73 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import * as styled from 'styled-components';
import {JSX, useState, useEffect, ChangeEvent} from 'react';
import moment from 'moment';
import {IInput} from './Input';
import Input from './Input';
import Theme from 'theme';
import searchImage from 'assets/images/search-150x150.png';
const searchWaitTimeout = moment.duration(1, 'seconds').asMilliseconds();
interface ISearchInput extends IInput {
search: (str: string) => void;
defaultValue?: string;
minLengthForSearch?: number;
}
const SearchInput = styled.default(Input)`
min-width: 100%;
padding-left: ${Theme.spacing.xlarge};
`;
export const SearchInputWrapper = styled.default.div`
position: relative;
display: flex;
& div {
width: 100%;
position: relative;
align-self: center;
& img {
width: 1rem;
height: 1rem;
top: 50%;
transform: translateY(-50%);
left: 0.5rem;
position: absolute;
}
}
`;
export const Search = ({search, defaultValue = '', minLengthForSearch = 2}: ISearchInput): JSX.Element => {
const [currentSearchTerm, setCurrentSearchTerm] = useState<string>(defaultValue);
const onChange = (event: ChangeEvent<HTMLInputElement>): void => {
setCurrentSearchTerm(event.target.value);
};
useEffect(() => {
let timeout = null;
if (currentSearchTerm.length >= minLengthForSearch || currentSearchTerm.length === 0) {
timeout = setTimeout(() => search(currentSearchTerm), searchWaitTimeout);
}
return () => {
if (timeout) {
clearInterval(timeout);
}
};
}, [currentSearchTerm, minLengthForSearch, search]);
return (
<SearchInputWrapper>
<div className="search-bar">
<img src={searchImage} alt={'searchImage'} />
<SearchInput value={currentSearchTerm} onChange={onChange} name="testId-search" />
</div>
</SearchInputWrapper>
);
};
export default Search;

View File

@@ -0,0 +1 @@
export * from './label';

View File

@@ -0,0 +1,19 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import React from 'react';
import {Label as StyledLabel} from './style';
interface ILabel {
text: string;
htmlFor?: string;
color?: string;
icon?: React.JSX.Element;
className?: string;
}
export const Label = ({text, htmlFor, color, icon, className}: ILabel): React.JSX.Element => (
<StyledLabel className={className} htmlFor={htmlFor} color={color}>
{text} {icon}
</StyledLabel>
);

View File

@@ -0,0 +1,15 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import * as styled from 'styled-components';
import Theme from 'theme';
const {spacing, colors, typography} = Theme;
export const Label = styled.default.label<{color?: string}>`
font-size: ${typography.fontSizeS};
color: ${({color}) => color || colors.gray900};
font-weight: bold;
margin: ${spacing.xxSmall} 0;
display: block;
`;

View File

@@ -0,0 +1,198 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import React, {useEffect, useRef, useState, ReactNode} from 'react';
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
import {IconDefinition, IconProp} from '@fortawesome/fontawesome-svg-core';
import {useComponentVisible, useCurrentWidth} from 'utility/custom-hooks';
import {IconMenuWrapper, IconMenuDropDownWrapper, IconMenuContent, IconMenuPointer, DropdownIcon, IconMenuDropDownItem} from './style';
import {IconMenuPosition, defaultArrowWidth, defaultArrowEdgeGap} from './types';
interface IIconMenuItems {
title: string;
value: string;
className?: string;
onSelect?: () => void;
onClick?: () => void;
modal?: {
component: ReactNode;
action?: () => void;
};
}
interface IMenuPointerStyle {
left?: number | string;
right?: number | string;
top?: number | string;
bottom?: number | string;
width?: number | string;
height?: number | string;
}
interface IIconMenu {
items: IIconMenuItems[];
icon?: IconDefinition | IconProp;
iconClassName?: string;
iconColor?: string;
title?: string;
menuVisible?: boolean;
showTail?: boolean;
position?: IconMenuPosition;
hasPointer?: boolean;
dropdownMargin?: number;
margin?: number | string;
disabled?: boolean;
}
const IconMenu = ({
items = [],
icon,
iconClassName,
iconColor = 'white',
menuVisible = false,
title,
showTail = true,
position = IconMenuPosition.BottomLeft,
hasPointer = true,
dropdownMargin = 0,
margin,
disabled
}: IIconMenu): React.JSX.Element => {
const dropdownRef = useRef<HTMLDivElement>(null);
const [dropdownStyle, setDropdownStyle] = useState<any>(null);
const [menuPointerStyle, setMenuPointerStyle] = useState<IMenuPointerStyle>({
right: -defaultArrowWidth / 2,
top: '50%'
});
const {ref, isComponentVisible, setIsComponentVisible} = useComponentVisible(menuVisible);
const width = useCurrentWidth();
useEffect(() => {
if (!isComponentVisible) {
setDropdownStyle(null);
}
}, [isComponentVisible]);
useEffect(() => {
if (ref.current && dropdownRef.current && isComponentVisible && position) {
const refRect = (ref.current as HTMLElement).getBoundingClientRect();
const dropdownRefRect = (dropdownRef.current as HTMLElement).getBoundingClientRect();
const newArrowPosition: IMenuPointerStyle = {
width: `${defaultArrowWidth}px`,
height: `${defaultArrowWidth}px`
};
const pointerMargin = Math.sqrt((defaultArrowWidth * defaultArrowWidth) / 2);
let top = 0;
let left = 0;
switch (position) {
case IconMenuPosition.Right: {
newArrowPosition.top = `calc(50% - ${defaultArrowWidth / 2}px)`;
newArrowPosition.left = `-${defaultArrowWidth / 2}px`;
top = refRect.top + refRect.height / 2 - dropdownRefRect.height / 2;
left = refRect.left + refRect.width + pointerMargin + dropdownMargin;
break;
}
case IconMenuPosition.Top: {
newArrowPosition.left = '50%';
newArrowPosition.bottom = `-${defaultArrowWidth / 2}px`;
top = refRect.top - dropdownRefRect.height - pointerMargin - dropdownMargin;
left = refRect.left + refRect.width / 2 - dropdownRefRect.width / 2;
break;
}
case IconMenuPosition.TopLeft: {
newArrowPosition.right = `${defaultArrowEdgeGap}px`;
newArrowPosition.bottom = `-${defaultArrowWidth / 2}px`;
top = refRect.top - dropdownRefRect.height - pointerMargin - dropdownMargin;
left = refRect.left + refRect.width / 2 - dropdownRefRect.width + defaultArrowWidth / 2 + defaultArrowEdgeGap;
break;
}
case IconMenuPosition.TopRight: {
newArrowPosition.left = `${defaultArrowEdgeGap}px`;
newArrowPosition.bottom = `-${defaultArrowWidth / 2}px`;
top = refRect.top - dropdownRefRect.height - pointerMargin - dropdownMargin;
left = refRect.left + refRect.width / 2 - defaultArrowWidth / 2 - defaultArrowEdgeGap;
break;
}
case IconMenuPosition.Bottom: {
newArrowPosition.left = '50%';
newArrowPosition.top = `-${defaultArrowWidth / 2}px`;
top = refRect.top + refRect.height + pointerMargin + dropdownMargin;
left = refRect.left + refRect.width / 2 - dropdownRefRect.width / 2;
break;
}
case IconMenuPosition.BottomLeft: {
newArrowPosition.right = `${defaultArrowEdgeGap}px`;
newArrowPosition.top = `-${defaultArrowWidth / 2}px`;
top = refRect.top + refRect.height + pointerMargin + dropdownMargin;
left = refRect.left + refRect.width / 2 - dropdownRefRect.width + defaultArrowWidth / 2 + defaultArrowEdgeGap;
break;
}
case IconMenuPosition.BottomRight: {
newArrowPosition.left = `${defaultArrowEdgeGap}px`;
newArrowPosition.top = `-${defaultArrowWidth / 2}px`;
top = refRect.top + refRect.height + pointerMargin + dropdownMargin;
left = refRect.left + refRect.width / 2 - defaultArrowWidth / 2 - defaultArrowEdgeGap;
break;
}
case IconMenuPosition.Left:
default: {
newArrowPosition.top = `calc(50% - ${defaultArrowWidth / 2}px)`;
newArrowPosition.right = `-${defaultArrowWidth / 2}px`;
top = refRect.top + refRect.height / 2 - dropdownRefRect.height / 2;
left = refRect.left - dropdownRefRect.width - pointerMargin - dropdownMargin;
}
}
setDropdownStyle({
top,
left
});
setMenuPointerStyle(newArrowPosition);
}
}, [isComponentVisible, ref, position, dropdownMargin, width]);
const handleClickIcon = () => {
setIsComponentVisible(!isComponentVisible);
};
return (
<>
<IconMenuWrapper ref={ref} margin={margin}>
<DropdownIcon role="button" tabIndex={0} onClick={handleClickIcon} className={`testId-dropdownIcon ${iconClassName} ${disabled && 'disabled'}`}>
{title}
{icon && <FontAwesomeIcon icon={icon} color={iconColor} size="lg" />}
</DropdownIcon>
{isComponentVisible && (
<IconMenuDropDownWrapper ref={dropdownRef} visible={isComponentVisible && !!dropdownStyle} showTail={showTail} style={dropdownStyle || undefined}>
<IconMenuContent className="testId-dropdownItems">
{!!hasPointer && <IconMenuPointer style={menuPointerStyle} />}
{items.map((item, i) => (
<IconMenuDropDownItem key={`${item.value}-${i}`} className={item.className} onMouseUp={item.onClick} data-value={item.value}>
{item.title}
</IconMenuDropDownItem>
))}
</IconMenuContent>
</IconMenuDropDownWrapper>
)}
</IconMenuWrapper>
</>
);
};
export default IconMenu;

View File

@@ -0,0 +1,4 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
export {default as IconMenu} from './icon-menu';

View File

@@ -0,0 +1,79 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import * as styled from 'styled-components';
import Theme from 'theme';
import caretUp from 'assets/images/caret-up.svg';
const {colors, spacing} = Theme;
export const IconMenuWrapper = styled.default.div<{margin?: number | string}>`
margin: ${({margin}) => (margin !== undefined ? margin : '.5rem 0 .5rem 1rem')};
div {
outline: none;
}
& img{
width: 24px;
height: 24px;
cursor: pointer;
}
`;
export const IconMenuDropDownWrapper = styled.default.div<{showTail?: boolean; visible?: boolean}>`
position: fixed;
width: 200px;
min-height: 31px;
right: 2.5rem;
${({showTail}) =>
showTail &&
styled.css`
background-image: url(${caretUp});
`};
background-position: top 0 right .5rem;
background-repeat: no-repeat;
z-index: 9999;
visibility: hidden;
${({visible}) =>
visible &&
styled.css`
visibility: visible;
`}
`;
export const IconMenuContent = styled.default.div`
background-color: ${colors.gray100};
border: 1px solid ${colors.gray200};
width: 200px;
overflow: auto;
border-radius: ${spacing.xxSmall};
padding: ${spacing.small} 0;
z-index: 10;
`;
export const IconMenuDropDownItem = styled.default.div`
padding: ${spacing.small};
text-decoration: none;
display: flex;
align-items: center;
font-size: 16px;
cursor: pointer;
color: ${colors.black};
background-color: ${colors.white};
&:hover {
background-color: ${colors.gray400};
}
`;
export const DropdownIcon = styled.default.div<{disabled?: boolean}>`
display: flex;
justify-content: center;
cursor: pointer;
min-width: 1rem;
&.disabled {
pointer-events: none;
opacity: 0.5;
}
`;
export const IconMenuPointer = styled.default.div`
position: absolute;
background-color: ${colors.gray100};
transform: rotate(45deg);
`;

View File

@@ -0,0 +1,19 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
export enum IconMenuPosition {
Left = 'left',
Right = 'right',
Top = 'top',
TopLeft = 'top-left',
TopRight = 'top-right',
Bottom = 'bottom',
BottomLeft = 'bottom-left',
BottomRight = 'bottom-right'
}
const defaultArrowWidth = 12;
const defaultArrowEdgeGap = 8;
export {defaultArrowWidth, defaultArrowEdgeGap};

16
src/components/index.ts Normal file
View File

@@ -0,0 +1,16 @@
export * from './buttons';
export * from './channel-icon-menu';
export * from './error-renderer';
export * from './layout';
export * from './loaders';
export * from './modal';
export * from './new-tab-link';
export * from './pre-formatted-code';
export * from './tags';
export * from './table-screen-header';
export * from './table-with-pagination';
export * from './ui';
export * from './tooltip';
export * from './ProtectedRoute';
export * from './table';
export * from './typography';

View File

@@ -0,0 +1,4 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
export * from './indicators';

View File

@@ -0,0 +1,27 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import {JSX} from 'react';
import {LoadingWheel as Loader} from 'components/loaders';
import {SingleStreamSymbol, OfflineSymbol, MultipleStreamSymbol, Indicator} from './style';
export const OfflineIndicator = (): JSX.Element => (
<Indicator>
<OfflineSymbol />
</Indicator>
);
export const SingleStreamIndicator = (): JSX.Element => (
<Indicator className="single-stream-indicator">
<SingleStreamSymbol className="testId-singleStreamIndicator" />
</Indicator>
);
export const MultiStreamIndicator = (): JSX.Element => (
<Indicator className="multi-stream-indicator">
<MultipleStreamSymbol className="testId-multiStreamIndicator" />
</Indicator>
);
export const LoadingIndicator = (): JSX.Element => (
<Indicator>
<Loader size="medium" />
</Indicator>
);

View File

@@ -0,0 +1,43 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import * as styled from 'styled-components';
import {LoadingWheel as Loader} from 'components';
export const Indicator = styled.default.div`
display: flex;
align-items: center;
justify-content: center;
${Loader} {
flex: 0;
margin: 0;
& span {
margin: 0;
}
}
`;
export const IndicatorOutline = styled.default.div`
width: 20px;
height: 20px;
border-radius: 50%;
`;
export const OfflineSymbol = styled.default(IndicatorOutline)`
border: 3px solid #707070;
background-color: transparent;
`;
export const SingleStreamSymbol = styled.default(IndicatorOutline)`
background-color: #08BD0B;
`;
export const MultipleStreamSymbol = styled.default(SingleStreamSymbol)`
width: 1rem;
height: 1rem;
margin-left: -2px;
box-shadow: 9px 0 0 0 #08BD0B;
`;

View File

@@ -0,0 +1,37 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import {JSX} from 'react';
import {useSelector} from 'react-redux';
import {AppStore} from 'store';
import {DataRowType} from 'components/table';
import {SingleStreamIndicator, OfflineIndicator, MultiStreamIndicator, LoadingIndicator} from './indicators';
interface IPublishingStateIndicator {
row: DataRowType;
publishingStateKey: string;
idKey: string;
}
const PublishingStateIndicator = ({row, publishingStateKey, idKey}: IPublishingStateIndicator): JSX.Element => {
const id = row[idKey];
const publishingState = useSelector((state: AppStore) => publishingStateKey && state[publishingStateKey as keyof AppStore]?.publishingState);
const rowPublishingState = publishingState.find((record: Record<string, any>) => record[idKey] === id);
if (!rowPublishingState) {
return <LoadingIndicator />;
}
if (!rowPublishingState.isOnline) {
return <OfflineIndicator />;
}
if (rowPublishingState.multipleStreams) {
return <MultiStreamIndicator />;
}
return <SingleStreamIndicator />;
};
export default PublishingStateIndicator;

View File

@@ -0,0 +1 @@
export * from '../forms/label';

View File

@@ -0,0 +1,56 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import * as styled from 'styled-components';
import Theme from 'theme';
interface IColumn {
align?: string;
size?: number;
padding?: string;
}
const {footerHeight} = Theme;
export const AppContainer = styled.default.div`
flex: 1;
display: flex;
overflow-x: hidden;
min-height: 0;
`;
export const Body = styled.default.div`
flex: 1;
margin: 1rem;
padding: 1rem ${Theme.spacing.xlarge};
background: ${Theme.colors.gray900};
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
overflow: hidden;
display: flex;
flex-direction: column;
min-height: 0;
`;
export const Row = styled.default.div`
display: flex;
`;
export const Column = styled.default.div<IColumn>`
flex: ${({size}): number => size || 1};
text-align: ${({align}): string => align || 'right'};
${({padding}) =>
padding &&
styled.css`
padding: ${padding};
`}
`;
export const Main = styled.default.div`
height: 100%;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
padding: 2rem;
`;

View File

@@ -0,0 +1,42 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import * as styled from 'styled-components';
import Theme from 'theme';
interface LoadingWheelProps {
size?: 'small' | 'medium' | 'large';
color?: string;
className?: string;
}
const LoadingWheelContainer = styled.default.div<{
size: number;
color: string;
}>`
display: inline-block;
width: ${({size}) => size}px;
height: ${({size}) => size}px;
border: 3px solid ${({color}) => color}20;
border-radius: 50%;
border-top-color: ${({color}) => color};
animation: spin 1s ease-in-out infinite;
@keyframes spin {
to {
transform: rotate(360deg);
}
}
`;
export const LoadingWheel: React.FC<LoadingWheelProps> = ({size = 'medium', color = Theme.colors.white, className}) => {
const sizeMap = {
small: Theme.loaderSize.small,
medium: Theme.loaderSize.medium,
large: Theme.loaderSize.large
};
return <LoadingWheelContainer size={sizeMap[size]} color={color} className={className} role="status" aria-label="Loading" />;
};
export default LoadingWheel;

View File

@@ -0,0 +1,4 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
export * from './LoadingWheel';

View File

@@ -0,0 +1,5 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
export {default as Modal} from './modal';

View File

@@ -0,0 +1,40 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import {LoadingWheel as Loader} from 'components';
import PreFormattedCode from 'components/pre-formatted-code';
import okImage from 'assets/images/icon/ok.svg';
import errorImage from 'assets/images/icon/error.svg';
import React from 'react';
import {DialogResponse, StatusCode, FormLoaderContainer} from './style';
interface IFormResponseComponent {
response: {
error: string | boolean | Error;
status: number | string;
data?: any; //eslint-disable-line
};
}
const FormResponse = (props: IFormResponseComponent): React.JSX.Element => {
const {response} = props;
return !response ? (
<FormLoaderContainer>
<Loader color="dark" size="medium" />
</FormLoaderContainer>
) : (
<DialogResponse error={response.error || ''}>
<h3 className="testId-responseModal">{response.error ? 'Error' : 'Success'}</h3>
<div className="response-icon">
<img src={response.error ? errorImage : okImage} alt="status icon" />
</div>
<StatusCode error={response.error}>Status: {response.status}</StatusCode>
{response.data && typeof response.data === 'object' && <PreFormattedCode data={response.data} />}
{response.error && typeof response.error === 'string' && <PreFormattedCode data={{error: response.error}} />}
</DialogResponse>
);
};
export default FormResponse;

View File

@@ -0,0 +1,4 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
export {default as FormResponse} from './form-response';

View File

@@ -0,0 +1,175 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import * as styled from 'styled-components';
import Theme from 'theme';
import {InputComponentWrapper} from 'components/forms/Input';
// import {AdvancedSelectContainer, ComponentWrapper} from 'components/ui/advanced-select/advanced-select';
// import InputWithTagsWrapper from 'components/ui/input-with-tags/input-with-tags';
// import TagContainer from 'components/ui/input-with-tags/input-with-tags';
// import TagWrapper from 'components/ui/input-with-tags/input-with-tags';
const {spacing, blackWithOpacity, typography, colors, primaryBorderRadius, primaryBorderColor} = Theme;
export const DialogContent = styled.default.div`
display: flex;
width: 400px;
margin: ${spacing.small};
`;
export const DialogForm = styled.default.div`
display: flex;
flex-direction: column;
width: 100%;
/* stylelint-disable */
& ${InputComponentWrapper} {
width: 100%;
max-width: 100%;
}
/* TagWrapper {
& > div {
width: 100%;
max-width: 100%;
}
} */
/* stylelint-enable */
h3 {
color: ${colors.gray700};
font-size: ${typography.fontSizeXl};
line-height: 24px;
font-weight: 500;
letter-spacing: 0.36px;
display: flex;
align-items: flex-start;
a {
font-size: ${typography.fontSizeS};
margin: 0 0 0 0.5rem;
}
}
> p {
color: ${blackWithOpacity};
font-size: ${typography.primaryFontSize};
margin-top: ${spacing.small};
line-height: 24px;
i {
font-weight: bold;
padding: 0 ${spacing.xsmall};
}
a {
color: ${colors.lightBlue};
text-decoration: underline;
}
}
strong {
p {
margin-top: 0;
margin-bottom: ${spacing.xSmall};
}
svg {
margin: 0 ${spacing.xxSmall};
color: ${colors.lightBlue};
}
}
select {
background: ${colors.transparent};
border: 1px solid ${primaryBorderColor} !important;
}
input {
padding: ${spacing.small};
margin-bottom: ${spacing.xSmall};
}
.button-group {
display: flex;
margin-top: ${spacing.small};
justify-content: center;
}
.error-text {
font-size: ${typography.fontSizeXS};
color: ${colors.lightRed};
}
.loading {
width: 100%;
position: absolute;
top: 0;
right: 0;
background-color: rgba(0,0,0,0.5);
display: flex;
align-items: center;
justify-content: center;
}
`;
export const Options = styled.default.div`
display: flex;
align-items: flex-end;
&>div {
margin: 0 1rem 0 0;
}
`;
export const DialogResponse = styled.default(DialogContent)<{error?: string | boolean | Error}>`
width: 100%;
margin: 0;
flex-direction: column;
align-items: center;
justify-content: center;
h3 {
color: ${colors.green};
font-size: ${typography.fontSizeXl};
line-height: 24px;
font-weight: 500;
letter-spacing: 0.36px;
${({error}) =>
error &&
styled.css`
color: ${colors.lightRed};
`}
}
.response-icon{
img {
width: 100px;
height: 100px;
margin: ${spacing.small} 0;
}
}
.json-renderer {
margin-top: ${spacing.small};
width: 100%;
height: auto;
height: 300px;
padding: ${spacing.small};
overflow: auto;
background-color: ${colors.gray200};
font-size: ${typography.fontSizeS};
}
`;
export const StatusCode = styled.default.div<{error?: string | boolean | Error}>`
display: flex;
justify-content: center;
width: 100%;
margin: ${spacing.xxSmall} 0;
padding: ${spacing.xsmall} 0;
color: ${colors.green};
border-radius: ${primaryBorderRadius};
border: 1px solid ${colors.green};
${({error}) =>
error &&
styled.css`
border-color: ${colors.lightRed};
color: ${colors.lightRed};
`}
`;
export const Error = styled.default.div`
font-size: ${typography.fontSizeXS};
color: ${colors.lightRed};
`;
export const FormLoaderContainer = styled.default.div`
height: 430px;
display: flex;
justify-content: center;
align-items: center;
`;

View File

@@ -0,0 +1,91 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import React from 'react';
import {createPortal} from 'react-dom';
import {ConfirmButton} from 'components/buttons';
import {theme} from 'components/shared/theme';
import {ModalOverlay, ModalContainer, ModalButtonsContaier, CloseButton} from './style';
interface IModal {
children: React.JSX.Element;
close: () => void;
className?: string;
submitButton?: {
onClick: () => void;
label?: string;
className?: string;
disabled?: boolean;
textColor?: string;
backgroundColor?: string;
borderColor?: string;
};
cancelButton?: {
onClick?: () => void;
label?: string;
className?: string;
disabled?: boolean;
textColor?: string;
backgroundColor?: string;
borderColor?: string;
};
}
const Modal = (props: IModal): React.JSX.Element => {
const {children, className, close} = props;
const submitButton = {
onClick: props.submitButton?.onClick || null,
label: 'Submit',
disabled: false,
textColor: theme.colors.gray700,
backgroundColor: theme.colors.white,
borderColor: theme.colors.gray700,
...props.submitButton
};
const cancelButton = {
label: 'Cancel',
disabled: false,
textColor: theme.colors.white,
backgroundColor: theme.colors.gray700,
borderColor: theme.colors.gray700,
...props.cancelButton
};
const handleCancel = () => {
if (cancelButton?.onClick) {
cancelButton.onClick();
} else {
close();
}
};
const clickModalContainer = (e: React.MouseEvent) => {
e.stopPropagation();
};
return createPortal(
<ModalOverlay onClick={close}>
<ModalContainer className={className} onClick={clickModalContainer}>
<CloseButton onClick={close} />
{children}
<ModalButtonsContaier>
{submitButton.onClick && (
<ConfirmButton {...submitButton} onClick={submitButton.onClick}>
{submitButton.label}
</ConfirmButton>
)}
{!props.cancelButton ||
(!cancelButton.disabled && (
<ConfirmButton className="testId-cancel" {...cancelButton} onClick={handleCancel}>
{cancelButton.label}
</ConfirmButton>
))}
</ModalButtonsContaier>
</ModalContainer>
</ModalOverlay>,
document.body
);
};
export default Modal;

View File

@@ -0,0 +1,5 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
export {default as MultiStepModal} from './multi-step-modal';

View File

@@ -0,0 +1,66 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import React, {useState} from 'react';
import {Modal} from 'components/modal';
interface IMultiStepModal {
isOpen: boolean;
closeModal: () => void;
steps: {
title: string;
component: React.JSX.Element;
saveButton?: {
onClick?: () => void;
text?: string;
disabled?: boolean;
className?: string;
};
cancel?: () => void;
cancelDisabled?: boolean;
}[];
}
const MultiStepModal = ({isOpen, closeModal, steps}: IMultiStepModal): React.JSX.Element => {
const [currentStep, setCurrentStep] = useState(0);
const isLastStep = steps.length - 1 === currentStep;
const saveButtonText = isLastStep ? 'Done' : 'Next';
const handleCloseModal = () => {
closeModal();
setCurrentStep(0);
};
const handleSave = () => {
if (steps[currentStep]?.saveButton?.onClick) {
steps[currentStep].saveButton.onClick();
}
if (isLastStep) {
handleCloseModal();
} else {
setCurrentStep(currentStep + 1);
}
};
if (isOpen) {
return (
<Modal
close={handleCloseModal}
submitButton={{
className: steps[currentStep]?.saveButton?.className,
disabled: steps[currentStep]?.saveButton?.disabled,
onClick: handleSave,
label: steps[currentStep]?.saveButton?.text || saveButtonText
}}
cancelButton={{disabled: steps[currentStep]?.cancelDisabled}}>
{steps[currentStep]?.component || null}
</Modal>
);
}
return null;
};
export default MultiStepModal;

View File

@@ -0,0 +1,80 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import * as styled from 'styled-components';
import {theme, paddings} from 'components/shared/theme';
import {ConfirmButton} from 'components/buttons';
const {colors} = theme;
export const ModalOverlay = styled.default.div`
position: fixed;
width: 100%;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background-color: ${colors.halfTransparentBlack};
top: 0;
left: 0;
z-index: 9999;
`;
export const ModalContainer = styled.default.div`
width: 60%;
max-width: 800px;
border-radius: 4px;
padding: ${paddings.xlarge};
background-color: ${colors.white};
position: relative;
max-height: 90%;
overflow: auto;
&.full-width {
width: auto;
max-width: 100%;
overflow-x: hidden;
}
&.dark {
background-color: ${colors.gray1000}
}
`;
export const CloseButton = styled.default.span`
cursor: pointer;
height: 1rem;
width: 1rem;
color: ${colors.gray700};
position: absolute;
top: 0.5rem;
right: 0.5rem;
&:before,
&:after {
position: absolute;
left: 0.4rem;
content: ' ';
height: 1rem;
width: 0.2rem;
background-color: ${colors.gray700};
}
&:before {
transform: rotate(45deg);
}
&:after {
transform: rotate(-45deg);
}
`;
export const ModalButtonsContaier = styled.default.div`
display: flex;
justify-content: center;
align-items: center;
margin: 24px 0 0;
${ConfirmButton} {
margin: 0 0.5rem;
}
`;

View File

@@ -0,0 +1,26 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import React from 'react';
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
import {IconDefinition} from '@fortawesome/fontawesome-svg-core';
interface ILink {
icon?: IconDefinition;
text?: string;
iconColor?: string;
link: string;
}
export const NewTabLink = (props: ILink & Partial<HTMLLinkElement>): React.JSX.Element => {
const {icon, className, text, link, iconColor = 'white'} = props;
return (
<a rel="noopener noreferrer" target="_blank" href={link} className={className}>
{icon && <FontAwesomeIcon icon={icon} style={{color: iconColor}} />}
{text}
</a>
);
};
export default NewTabLink;

View File

@@ -0,0 +1,5 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
export * from './pagination';
export {default as Pagination} from './pagination';

View File

@@ -0,0 +1,80 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import {Fragment} from 'react';
import {PaginationWrapper, ItemRange, PaginationContainer, PageButton} from './style';
interface IPagination {
currentPageNumber: number;
numberOfItems: number;
itemsPerPage: number;
setCurrentPage: (page: number) => void;
itemText?: string;
}
export const Pagination = (props: IPagination): JSX.Element => {
const maxNumberOfButtonsToShow = 3;
const LowerBoundLimit = 2;
const higherBoundLimit = 1;
const {currentPageNumber, numberOfItems, itemsPerPage, setCurrentPage, itemText} = props;
const totalNumberOfPages = Math.ceil(numberOfItems / itemsPerPage);
const setPage = (page: number): void => {
setCurrentPage(page);
};
const minimumItemBoundPerPage = (currentPageNumber - 1) * itemsPerPage + 1;
const maximumItemBoundPerPage = currentPageNumber * itemsPerPage;
const generateButtons = (bounds = 1): JSX.Element[] => {
const buttonToShow = maxNumberOfButtonsToShow > totalNumberOfPages ? totalNumberOfPages : maxNumberOfButtonsToShow;
const buttons = [];
let count: number;
if (currentPageNumber <= bounds) {
count = 1;
} else if (currentPageNumber + bounds > totalNumberOfPages) {
count = currentPageNumber - (buttonToShow - (totalNumberOfPages - currentPageNumber + 1));
} else {
count = currentPageNumber - bounds;
}
for (let y = 0; y < buttonToShow; y++) {
buttons.push(
<PageButton key={`page-button-${y}`} onClick={() => setPage(count + y)} active={currentPageNumber === count + y}>
{count + y}
</PageButton>
);
}
return buttons;
};
return (
<PaginationContainer className="pagination-container">
{numberOfItems ? (
<PaginationWrapper>
{currentPageNumber >= LowerBoundLimit && (
<Fragment>
{currentPageNumber > 2 && totalNumberOfPages !== 3 && <PageButton onClick={() => setPage(1)}>1</PageButton>}
{currentPageNumber > LowerBoundLimit && currentPageNumber !== 3 && <p>...</p>}
</Fragment>
)}
{generateButtons()}
{currentPageNumber <= totalNumberOfPages - higherBoundLimit && (
<Fragment>
{currentPageNumber < totalNumberOfPages - higherBoundLimit && currentPageNumber + 2 !== totalNumberOfPages && <p>...</p>}
{currentPageNumber + 1 !== totalNumberOfPages && totalNumberOfPages !== 3 && (
<PageButton onClick={() => setPage(totalNumberOfPages)}>{totalNumberOfPages}</PageButton>
)}
</Fragment>
)}
</PaginationWrapper>
) : null}
<ItemRange>
{numberOfItems > 0 ? minimumItemBoundPerPage : 0} - {maximumItemBoundPerPage > numberOfItems ? numberOfItems : maximumItemBoundPerPage} of{' '}
{numberOfItems} {itemText ? itemText : `channels`}
</ItemRange>
</PaginationContainer>
);
};
export default Pagination;

View File

@@ -0,0 +1,40 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import * as styled from 'styled-components';
import {theme, paddings} from 'components/shared/theme';
const {colors, fontSizeS, spacing, primaryThemeColor} = theme;
export const PaginationContainer = styled.default.div`
display: flex;
width: 100%;
align-items: center;
flex-wrap: wrap;
margin: ${spacing.small} 0;
`;
export const PaginationWrapper = styled.default.div`
display: flex;
flex-wrap: wrap;
`;
export const ItemRange = styled.default.div`
display: flex;
justify-content: flex-end;
margin-left: auto;
font-size: ${fontSizeS};
color: ${colors.lightBlue};
`;
export const PageButton = styled.default.button<{active?: boolean}>`
margin: 0 ${paddings.xsmall} ${paddings.xsmall} 0;
font-size: ${fontSizeS};
border: 1px solid ${primaryThemeColor};
border-radius: 4px;
height: 28px;
width: 36px;
cursor: pointer;
background-color: ${({active}) => (active ? primaryThemeColor : 'transparent')};
color: ${({active}) => (active ? colors.white : primaryThemeColor)};
`;

View File

@@ -0,0 +1,5 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
export {default} from './pre-formatted-code';

View File

@@ -0,0 +1,58 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import React, {Fragment, useState} from 'react';
import {faCopy, faCheck} from '@fortawesome/free-solid-svg-icons';
import IconButton from 'components/buttons/icon-button';
import {CodeContainer} from './styles';
interface IPreFormattedCode {
data: Record<string, any> | Array<any>; // eslint-disable-line
prefixCharacter?: string;
color?: string;
showCopyIcon?: boolean;
}
const iconChangeTimeout = 2000;
const PreFormattedCode = ({data, prefixCharacter, color, showCopyIcon = true}: IPreFormattedCode): React.JSX.Element => {
const [copied, setCopied] = useState(false);
const json = JSON.stringify(data, null, 2);
const lines = json.split('\n');
const text = lines.map(line => line.replace(/^< /, '')).join('\n');
const copyJsonToClipboard = (text: string): void => {
navigator.clipboard.writeText(text);
setCopied(true);
setTimeout(() => setCopied(false), iconChangeTimeout);
};
const handleCopy = event => {
const originalString = event.target.textContent;
const modifiedString = originalString.replace(/[<>]/g, '');
event.clipboardData.setData('text/plain', modifiedString);
event.preventDefault();
};
const handleCopyIconClick = () => copyJsonToClipboard(text);
return (
<CodeContainer color={color}>
<pre>
<code onCopy={handleCopy}>
{lines.map((line, index) => (
<Fragment key={index}>
{prefixCharacter} {line} <br />
{index === lines.length - 1 && prefixCharacter}
</Fragment>
))}
</code>
</pre>
{showCopyIcon && <IconButton onClick={handleCopyIconClick} tooltipText="Copy" icon={copied ? faCheck : faCopy} />}
</CodeContainer>
);
};
export default PreFormattedCode;

View File

@@ -0,0 +1,34 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import * as styled from 'styled-components';
import Theme from 'theme';
const {colors} = Theme;
export const CodeContainer = styled.default.div<{color?: string}>`
background-color: ${colors.gray200};
padding: 1rem;
margin: 1rem 0 0;
display: flex;
color: ${({color}) => color || colors.black};
position: relative;
width: 100%;
&>span {
position: absolute;
right: 0.5rem;
top: 0.5rem;
}
pre {
width: 100%;
white-space: pre-wrap;
max-height: 40vh;
overflow: auto;
}
code {
word-wrap: break-word;
}
`;

View File

@@ -0,0 +1,6 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
export {default as RestrictedTextWithLabel} from './restricted-text-with-label';
export {default as RestrictedText} from './restricted-text';
export * from './restricted-text';

View File

@@ -0,0 +1,30 @@
/**
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
*/
import {JSX} from 'react';
import {RestrictedRowLabel, RestrictedRowText, RestrictedRowWrapper} from './style';
import {RestrictedText} from '.';
interface IRestrictedTextWithLabel {
label: string;
text: string;
isLink?: boolean;
linkClassName?: string;
labelIcon?: JSX.Element;
}
const RestrictedTextWithLabel = ({label, text, labelIcon, isLink = false, linkClassName = ''}: IRestrictedTextWithLabel): JSX.Element => {
return (
<RestrictedRowWrapper>
<RestrictedRowLabel>
{label} {labelIcon}
</RestrictedRowLabel>
<RestrictedRowText>
<RestrictedText text={text} isLink={isLink} linkClassName={linkClassName} />
</RestrictedRowText>
</RestrictedRowWrapper>
);
};
export default RestrictedTextWithLabel;

Some files were not shown because too many files have changed in this diff Show More