maintenance
This commit is contained in:
871
bun.lock
871
bun.lock
@@ -1,871 +0,0 @@
|
|||||||
{
|
|
||||||
"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",
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@eslint/js": "9.34.0",
|
|
||||||
"@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",
|
|
||||||
"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": {
|
|
||||||
"@ampproject/remapping": ["@ampproject/remapping@2.3.0", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw=="],
|
|
||||||
|
|
||||||
"@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.0", "", {}, "sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw=="],
|
|
||||||
|
|
||||||
"@babel/core": ["@babel/core@7.28.3", "", { "dependencies": { "@ampproject/remapping": "^2.2.0", "@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.3", "@babel/parser": "^7.28.3", "@babel/template": "^7.27.2", "@babel/traverse": "^7.28.3", "@babel/types": "^7.28.2", "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-yDBHV9kQNcr2/sUr9jghVyz9C3Y5G2zUM2H2lo+9mKv4sFgbA8s8Z9t8D1jiTkGoO/NoIfKMyKWr4s6CN23ZwQ=="],
|
|
||||||
|
|
||||||
"@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.3", "", { "dependencies": { "@babel/template": "^7.27.2", "@babel/types": "^7.28.2" } }, "sha512-PTNtvUQihsAsDHMOP5pfobP8C6CM4JWXmP8DrEIt46c3r2bf87Ua1zoqevsMo9g+tWDwgWrFP5EIxuBx5RudAw=="],
|
|
||||||
|
|
||||||
"@babel/parser": ["@babel/parser@7.28.3", "", { "dependencies": { "@babel/types": "^7.28.2" }, "bin": "./bin/babel-parser.js" }, "sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA=="],
|
|
||||||
|
|
||||||
"@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.3", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.3", "@babel/helper-globals": "^7.28.0", "@babel/parser": "^7.28.3", "@babel/template": "^7.27.2", "@babel/types": "^7.28.2", "debug": "^4.3.1" } }, "sha512-7w4kZYHneL3A6NP2nxzHvT3HCZ7puDZZjFMqDpBPECub79sTtSO5CGXDkKrTQq8ksAwfD/XI2MRFX23njdDaIQ=="],
|
|
||||||
|
|
||||||
"@babel/types": ["@babel/types@7.28.2", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ=="],
|
|
||||||
|
|
||||||
"@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.7.0", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw=="],
|
|
||||||
|
|
||||||
"@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=="],
|
|
||||||
|
|
||||||
"@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="],
|
|
||||||
|
|
||||||
"@humanfs/node": ["@humanfs/node@0.16.6", "", { "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.3.0" } }, "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw=="],
|
|
||||||
|
|
||||||
"@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/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.24", "", { "dependencies": { "@swc/counter": "^0.1.3" } }, "sha512-tjTMh3V4vAORHtdTprLlfoMptu1WfTZG9Rsca6yOKyNYsRr+MUXutKmliB17orgSZk5DpnDxs8GUdd/qwYxOng=="],
|
|
||||||
|
|
||||||
"@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.30001739", "", {}, "sha512-y+j60d6ulelrNSwpPyrHdl+9mJnQzHBr08xm48Qno0nSk4h3Qojh+ziv2qE6rXf4k3tadF4o1J/1tAbVm1NtnA=="],
|
|
||||||
|
|
||||||
"chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
|
|
||||||
|
|
||||||
"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=="],
|
|
||||||
|
|
||||||
"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.212", "", {}, "sha512-gE7ErIzSW+d8jALWMcOIgf+IB6lpfsg6NwOhPVwKzDtN2qcBix47vlin4yzSregYDxTCXOUqAZjVY/Z3naS7ww=="],
|
|
||||||
|
|
||||||
"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.19", "", {}, "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw=="],
|
|
||||||
|
|
||||||
"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-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=="],
|
|
||||||
|
|
||||||
"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=="],
|
|
||||||
|
|
||||||
"tinyglobby": ["tinyglobby@0.2.14", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ=="],
|
|
||||||
|
|
||||||
"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=="],
|
|
||||||
|
|
||||||
"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=="],
|
|
||||||
|
|
||||||
"@humanfs/node/@humanwhocodes/retry": ["@humanwhocodes/retry@0.3.1", "", {}, "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA=="],
|
|
||||||
|
|
||||||
"@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=="],
|
|
||||||
|
|
||||||
"fdir/picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
|
|
||||||
|
|
||||||
"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=="],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -23,10 +23,15 @@
|
|||||||
"react-dom": "19.1.1",
|
"react-dom": "19.1.1",
|
||||||
"react-redux": "9.2.0",
|
"react-redux": "9.2.0",
|
||||||
"react-router-dom": "7.8.2",
|
"react-router-dom": "7.8.2",
|
||||||
"styled-components": "6.1.19"
|
"styled-components": "6.1.19",
|
||||||
|
"uuid": "11.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "9.34.0",
|
"@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/node": "24.3.0",
|
||||||
"@types/react": "19.1.12",
|
"@types/react": "19.1.12",
|
||||||
"@types/react-dom": "19.1.9",
|
"@types/react-dom": "19.1.9",
|
||||||
@@ -39,6 +44,8 @@
|
|||||||
"eslint-plugin-react-refresh": "0.4.20",
|
"eslint-plugin-react-refresh": "0.4.20",
|
||||||
"globals": "16.3.0",
|
"globals": "16.3.0",
|
||||||
"prettier": "3.6.2",
|
"prettier": "3.6.2",
|
||||||
|
"react-datepicker": "8.7.0",
|
||||||
|
"react-toastify": "11.0.5",
|
||||||
"typescript": "5.9.2",
|
"typescript": "5.9.2",
|
||||||
"typescript-eslint": "8.42.0",
|
"typescript-eslint": "8.42.0",
|
||||||
"typescript-plugin-styled-components": "3.0.0",
|
"typescript-plugin-styled-components": "3.0.0",
|
||||||
|
|||||||
16
src/App.tsx
16
src/App.tsx
@@ -1,11 +1,19 @@
|
|||||||
import {JSX} from 'react';
|
import React from 'react';
|
||||||
|
import styled from 'styled-components';
|
||||||
import Router from './routers';
|
import Router from './routers';
|
||||||
|
import Theme from './theme';
|
||||||
|
|
||||||
const App = (): JSX.Element => {
|
const AppContainer = styled.div`
|
||||||
|
min-height: 100vh;
|
||||||
|
background: ${Theme.backgrounds.defaultBackground};
|
||||||
|
background-attachment: fixed;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const App = (): React.JSX.Element => {
|
||||||
return (
|
return (
|
||||||
<>
|
<AppContainer>
|
||||||
<Router />
|
<Router />
|
||||||
</>
|
</AppContainer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import {JSX} from 'react';
|
import React from 'react';
|
||||||
import {Navigate, useLocation} from 'react-router-dom';
|
import {Navigate, useLocation} from 'react-router-dom';
|
||||||
import {useAppSelector} from 'store';
|
import {useAppSelector} from 'store';
|
||||||
import {selectIsAuthenticated} from 'store/slices/Authentication.slice';
|
import {selectIsAuthenticated} from 'store/slices/Authentication.slice';
|
||||||
|
|
||||||
export function ProtectedRoute({component}: {component: JSX.Element}): JSX.Element {
|
export function ProtectedRoute({component}: {component: React.JSX.Element}): React.JSX.Element {
|
||||||
const isAuthenticated = useAppSelector(selectIsAuthenticated);
|
const isAuthenticated = useAppSelector(selectIsAuthenticated);
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||||
*/
|
*/
|
||||||
import {useState} from 'react';
|
import React, {useState} from 'react';
|
||||||
import {faCopy, faCheck} from '@fortawesome/free-solid-svg-icons';
|
import {faCopy, faCheck} from '@fortawesome/free-solid-svg-icons';
|
||||||
import IconButton from 'components/buttons/icon-button';
|
import IconButton from 'components/buttons/icon-button';
|
||||||
|
|
||||||
@@ -9,7 +9,7 @@ import {CopyButtonContainer} from './styles';
|
|||||||
|
|
||||||
const iconChangeTimeout = 2000;
|
const iconChangeTimeout = 2000;
|
||||||
|
|
||||||
export const CopyIconButton = (props: {text: string; quoted?: boolean; displayText?: boolean; className?: string}): JSX.Element => {
|
export const CopyIconButton = (props: {text: string; quoted?: boolean; displayText?: boolean; className?: string}): React.JSX.Element => {
|
||||||
const {text, quoted = false, displayText = true, className} = props;
|
const {text, quoted = false, displayText = true, className} = props;
|
||||||
const [copied, setCopied] = useState(false);
|
const [copied, setCopied] = useState(false);
|
||||||
const copyToClipboard = (): void => {
|
const copyToClipboard = (): void => {
|
||||||
@@ -22,11 +22,7 @@ export const CopyIconButton = (props: {text: string; quoted?: boolean; displayTe
|
|||||||
return (
|
return (
|
||||||
<CopyButtonContainer className={className}>
|
<CopyButtonContainer className={className}>
|
||||||
{displayText && (quoted ? `"${text}"` : text)}
|
{displayText && (quoted ? `"${text}"` : text)}
|
||||||
<IconButton
|
<IconButton onClick={copyToClipboard} tooltipText="Copy" icon={copied ? faCheck : faCopy} />
|
||||||
onClick={copyToClipboard}
|
|
||||||
tooltipText="Copy"
|
|
||||||
icon={copied ? faCheck : faCopy}
|
|
||||||
/>
|
|
||||||
</CopyButtonContainer>
|
</CopyButtonContainer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||||
*/
|
*/
|
||||||
|
import React from 'react';
|
||||||
import {theme} from 'components/shared/theme';
|
import {theme} from 'components/shared/theme';
|
||||||
import {Button} from 'components/buttons';
|
import {Button} from 'components/buttons';
|
||||||
|
|
||||||
@@ -12,7 +13,7 @@ interface IExportFileButton {
|
|||||||
fileName?: string;
|
fileName?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ExportFileButton = ({label = 'Export File', file, fileName = 'file'}: IExportFileButton): JSX.Element => {
|
export const ExportFileButton = ({label = 'Export File', file, fileName = 'file'}: IExportFileButton): React.JSX.Element => {
|
||||||
const handleExport = () => {
|
const handleExport = () => {
|
||||||
const downloadUrl = URL.createObjectURL(new Blob([file]));
|
const downloadUrl = URL.createObjectURL(new Blob([file]));
|
||||||
const linkTag = document.createElement('a');
|
const linkTag = document.createElement('a');
|
||||||
@@ -24,12 +25,7 @@ export const ExportFileButton = ({label = 'Export File', file, fileName = 'file'
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button onClick={handleExport} className="testId-exportFile" backgroundColor={colors.red} borderColor={colors.red}>
|
||||||
onClick={handleExport}
|
|
||||||
className="testId-exportFile"
|
|
||||||
backgroundColor={colors.red}
|
|
||||||
borderColor={colors.red}
|
|
||||||
>
|
|
||||||
{label}
|
{label}
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -16,14 +16,9 @@ interface IIconButton {
|
|||||||
className?: string;
|
className?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const IconButton = ({
|
const IconButton = ({onClick, tooltipText, icon, className}: IIconButton) => (
|
||||||
onClick,
|
|
||||||
tooltipText,
|
|
||||||
icon,
|
|
||||||
className
|
|
||||||
}: IIconButton) => (
|
|
||||||
<Tooltip position={Position.Bottom} message={tooltipText}>
|
<Tooltip position={Position.Bottom} message={tooltipText}>
|
||||||
<IconButtonContainer className={`icon-button ${className}`} role="link" tabIndex={-11} onKeyDown={null} onClick={onClick}>
|
<IconButtonContainer className={`icon-button ${className}`} role="link" tabIndex={-11} onKeyDown={undefined} onClick={onClick}>
|
||||||
<FontAwesomeIcon icon={icon} />
|
<FontAwesomeIcon icon={icon} />
|
||||||
</IconButtonContainer>
|
</IconButtonContainer>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||||
*/
|
*/
|
||||||
|
import React from 'react';
|
||||||
import {IconButton} from './style';
|
import {IconButton} from './style';
|
||||||
import addIcon from 'assets/images/icon/hash-plus.svg';
|
import addIcon from 'assets/images/icon/hash-plus.svg';
|
||||||
|
|
||||||
@@ -9,7 +10,7 @@ interface IAddButton {
|
|||||||
className: string;
|
className: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const AddButton = ({onClick, className}: IAddButton): JSX.Element => (
|
export const AddButton = ({onClick, className}: IAddButton): React.JSX.Element => (
|
||||||
<IconButton onClick={onClick} className={className}>
|
<IconButton onClick={onClick} className={className}>
|
||||||
<img src={addIcon} alt={'Add'} />
|
<img src={addIcon} alt={'Add'} />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||||
*/
|
*/
|
||||||
|
import React from 'react';
|
||||||
import {IconButton} from './style';
|
import {IconButton} from './style';
|
||||||
|
|
||||||
import refreshIcon from 'assets/images/icon/refresh.svg';
|
import refreshIcon from 'assets/images/icon/refresh.svg';
|
||||||
@@ -10,7 +11,7 @@ interface IRefreshButton {
|
|||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const RefreshButton = ({onClick, disabled = false}: IRefreshButton): JSX.Element => (
|
export const RefreshButton = ({onClick, disabled = false}: IRefreshButton): React.JSX.Element => (
|
||||||
<IconButton onClick={onClick} disabled={disabled}>
|
<IconButton onClick={onClick} disabled={disabled}>
|
||||||
<img src={refreshIcon} alt={'Refresh'} />
|
<img src={refreshIcon} alt={'Refresh'} />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
|
|||||||
@@ -4,14 +4,14 @@
|
|||||||
import * as styled from 'styled-components';
|
import * as styled from 'styled-components';
|
||||||
import {theme} from 'components/shared/theme';
|
import {theme} from 'components/shared/theme';
|
||||||
|
|
||||||
const {fontSizeL, colors} = theme;
|
const {typography: {fontSizeL}, colors} = theme;
|
||||||
|
|
||||||
export const IconButton = styled.default.button`
|
export const IconButton = styled.default.button`
|
||||||
border: none;
|
border: none;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
font-size: ${fontSizeL};
|
font-size: ${fontSizeL};
|
||||||
color: ${colors.white};
|
color: ${colors.white};
|
||||||
opacity: ${({disabled}) => disabled ? 0.3 : 1};
|
opacity: ${({disabled}) => (disabled ? 0.3 : 1)};
|
||||||
cursor: ${({disabled}) => disabled ? 'not-allowed' : 'pointer'};
|
cursor: ${({disabled}) => (disabled ? 'not-allowed' : 'pointer')};
|
||||||
display: flex;
|
display: flex;
|
||||||
`;
|
`;
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||||
*/
|
*/
|
||||||
import * as styled from 'styled-components';
|
import * as styled from 'styled-components';
|
||||||
import Theme from 'theme';
|
import Theme from 'theme';
|
||||||
|
|
||||||
export const Button = styled.default.button<{
|
export const Button = styled.default.button<{
|
||||||
backgroundColor?: string;
|
backgroundColor?: string;
|
||||||
|
|||||||
@@ -1,15 +1,10 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||||
*/
|
*/
|
||||||
import {Fragment} from 'react';
|
import React, {Fragment} from 'react';
|
||||||
import {Tooltip, Position} from 'components/tooltip';
|
import {Tooltip, Position} from 'components/tooltip';
|
||||||
import {Label} from 'components/label';
|
import {Label} from 'components/label';
|
||||||
import {
|
import {RadioGroup, RadioWrapper, RadioButtonContainer, VisibleCheckBox} from './style';
|
||||||
RadioGroup,
|
|
||||||
RadioWrapper,
|
|
||||||
RadioButtonContainer,
|
|
||||||
VisibleCheckBox
|
|
||||||
} from './style';
|
|
||||||
|
|
||||||
interface IRadioItems {
|
interface IRadioItems {
|
||||||
label: string;
|
label: string;
|
||||||
@@ -17,13 +12,13 @@ interface IRadioItems {
|
|||||||
tooltipMessage?: string;
|
tooltipMessage?: string;
|
||||||
tooltipPosition?: Position;
|
tooltipPosition?: Position;
|
||||||
className?: string;
|
className?: string;
|
||||||
children?: JSX.Element;
|
children?: React.JSX.Element;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IRadioButtonGroup {
|
interface IRadioButtonGroup {
|
||||||
items: IRadioItems[];
|
items: IRadioItems[];
|
||||||
handleOnChange: (value) => void;
|
handleOnChange: (value: string) => void;
|
||||||
currentValue: string;
|
currentValue: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,30 +27,22 @@ const RadioButton = (props: {currentValue: string; value: string}) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RadioButtonContainer>
|
<RadioButtonContainer>
|
||||||
<input type="radio" readOnly={true} value={value} checked={currentValue === value}/>
|
<input type="radio" readOnly={true} value={value} checked={currentValue === value} />
|
||||||
<VisibleCheckBox checked={currentValue === value}><div/></VisibleCheckBox>
|
<VisibleCheckBox checked={currentValue === value}>
|
||||||
|
<div />
|
||||||
|
</VisibleCheckBox>
|
||||||
</RadioButtonContainer>
|
</RadioButtonContainer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const RadioButtonGroup = (props: IRadioButtonGroup): JSX.Element => {
|
const RadioButtonGroup = (props: IRadioButtonGroup): React.JSX.Element => {
|
||||||
const {items, handleOnChange, currentValue} = props;
|
const {items, handleOnChange, currentValue} = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RadioGroup>
|
<RadioGroup>
|
||||||
{items.map((
|
{items.map(({label, value, disabled, tooltipPosition, tooltipMessage, children, className}: IRadioItems, index: number) => (
|
||||||
{
|
<RadioWrapper
|
||||||
label,
|
tabIndex={-1}
|
||||||
value,
|
|
||||||
disabled,
|
|
||||||
tooltipPosition,
|
|
||||||
tooltipMessage,
|
|
||||||
children,
|
|
||||||
className
|
|
||||||
}: IRadioItems,
|
|
||||||
index: number
|
|
||||||
) => (
|
|
||||||
<RadioWrapper tabIndex={-1}
|
|
||||||
onKeyPress={() => null}
|
onKeyPress={() => null}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
className="button-container"
|
className="button-container"
|
||||||
@@ -65,18 +52,12 @@ const RadioButtonGroup = (props: IRadioButtonGroup): JSX.Element => {
|
|||||||
<RadioButton value={value} currentValue={currentValue} />
|
<RadioButton value={value} currentValue={currentValue} />
|
||||||
<Fragment>
|
<Fragment>
|
||||||
{tooltipMessage ? (
|
{tooltipMessage ? (
|
||||||
<Tooltip position={tooltipPosition} message={tooltipMessage}>
|
<Tooltip position={tooltipPosition || Position.Top} message={tooltipMessage}>
|
||||||
<Label
|
<Label className={className} text={label} />
|
||||||
className={className}
|
|
||||||
text={label}
|
|
||||||
/>
|
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
) :
|
) : (
|
||||||
<Label
|
<Label className={className} text={label} />
|
||||||
className={className}
|
)}
|
||||||
text={label}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
{children}
|
{children}
|
||||||
</Fragment>
|
</Fragment>
|
||||||
</RadioWrapper>
|
</RadioWrapper>
|
||||||
|
|||||||
@@ -2,13 +2,10 @@
|
|||||||
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||||
*/
|
*/
|
||||||
import * as styled from 'styled-components';
|
import * as styled from 'styled-components';
|
||||||
import {theme, paddings} from 'components/shared/theme';
|
import {theme, Theme} from 'components/shared/theme';
|
||||||
|
|
||||||
const {
|
const {spacing, typography: {primaryFontSize}, colors} = theme;
|
||||||
spacing,
|
const paddings = Theme.paddings;
|
||||||
primaryFontSize,
|
|
||||||
colors
|
|
||||||
} = theme;
|
|
||||||
|
|
||||||
export const RadioGroup = styled.default.div`
|
export const RadioGroup = styled.default.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -18,10 +15,12 @@ export const RadioWrapper = styled.default.div<{disabled?: boolean}>`
|
|||||||
padding: ${paddings.small};
|
padding: ${paddings.small};
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
${({disabled}) => disabled && styled.css`
|
${({disabled}) =>
|
||||||
pointer-events: none;
|
disabled &&
|
||||||
opacity: .5;
|
styled.css`
|
||||||
`}
|
pointer-events: none;
|
||||||
|
opacity: 0.5;
|
||||||
|
`}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const RadioButtonContainer = styled.default.div`
|
export const RadioButtonContainer = styled.default.div`
|
||||||
@@ -43,15 +42,17 @@ export const VisibleCheckBox = styled.default.div<{checked?: boolean}>`
|
|||||||
height: ${primaryFontSize};
|
height: ${primaryFontSize};
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
|
|
||||||
${({checked}) => checked && styled.css`
|
${({checked}) =>
|
||||||
border: none;
|
checked &&
|
||||||
background-color: ${colors.red};
|
styled.css`
|
||||||
|
border: none;
|
||||||
|
background-color: ${colors.red};
|
||||||
|
|
||||||
div {
|
div {
|
||||||
background-color: ${colors.black};
|
background-color: ${colors.black};
|
||||||
width: 5px;
|
width: 5px;
|
||||||
height: 5px;
|
height: 5px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
}
|
}
|
||||||
`}
|
`}
|
||||||
`;
|
`;
|
||||||
@@ -1,15 +1,11 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||||
*/
|
*/
|
||||||
|
import React from 'react';
|
||||||
import * as styled from 'styled-components';
|
import * as styled from 'styled-components';
|
||||||
import {theme} from 'components/shared/theme';
|
import {theme} from 'components/shared/theme';
|
||||||
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
|
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
|
||||||
import {
|
import {faBackward, faFastBackward, faFastForward, faForward} from '@fortawesome/free-solid-svg-icons';
|
||||||
faBackward,
|
|
||||||
faFastBackward,
|
|
||||||
faFastForward,
|
|
||||||
faForward
|
|
||||||
} from '@fortawesome/free-solid-svg-icons';
|
|
||||||
|
|
||||||
const {colors, spacing} = theme;
|
const {colors, spacing} = theme;
|
||||||
const ScrollButton = styled.default.button`
|
const ScrollButton = styled.default.button`
|
||||||
@@ -30,8 +26,8 @@ const TwinButtons = styled.default.div`
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const ScrollButtons = ({current}: {current: HTMLDivElement}): JSX.Element => {
|
export const ScrollButtons = ({current}: {current: HTMLDivElement}): React.JSX.Element => {
|
||||||
const getScrollStep = current => {
|
const getScrollStep = (current: HTMLDivElement) => {
|
||||||
const tableViewHeight = current.offsetHeight;
|
const tableViewHeight = current.offsetHeight;
|
||||||
|
|
||||||
return tableViewHeight / 2;
|
return tableViewHeight / 2;
|
||||||
|
|||||||
@@ -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;
|
||||||
@@ -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;
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
export {default} from './delete-channel-modal';
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
/**
|
||||||
|
* 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;
|
||||||
@@ -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;
|
||||||
4
src/components/channel-icon-menu/fork-channel/index.tsx
Normal file
4
src/components/channel-icon-menu/fork-channel/index.tsx
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
export {default} from './fork-channel-modal';
|
||||||
65
src/components/channel-icon-menu/index.tsx
Normal file
65
src/components/channel-icon-menu/index.tsx
Normal 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} />}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
4
src/components/channel-icon-menu/kill-channel/index.tsx
Normal file
4
src/components/channel-icon-menu/kill-channel/index.tsx
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
export {default} from './kill-channel-modal';
|
||||||
@@ -0,0 +1,129 @@
|
|||||||
|
/**
|
||||||
|
* 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;
|
||||||
@@ -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;
|
||||||
62
src/components/create-token-components/capabilities.tsx
Normal file
62
src/components/create-token-components/capabilities.tsx
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
/**
|
||||||
|
* 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;
|
||||||
8
src/components/create-token-components/index.ts
Normal file
8
src/components/create-token-components/index.ts
Normal 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';
|
||||||
44
src/components/create-token-components/index.tsx
Normal file
44
src/components/create-token-components/index.tsx
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
/**
|
||||||
|
* 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>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -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 {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;
|
||||||
60
src/components/create-token-components/styles.ts
Normal file
60
src/components/create-token-components/styles.ts
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
`;
|
||||||
60
src/components/create-token-components/validity-time.tsx
Normal file
60
src/components/create-token-components/validity-time.tsx
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
/**
|
||||||
|
* 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;
|
||||||
51
src/components/date-render-component/index.tsx
Normal file
51
src/components/date-render-component/index.tsx
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
/**
|
||||||
|
* 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>
|
||||||
|
);
|
||||||
|
};
|
||||||
212
src/components/drop-down/index.tsx
Normal file
212
src/components/drop-down/index.tsx
Normal file
@@ -0,0 +1,212 @@
|
|||||||
|
/**
|
||||||
|
* 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>
|
||||||
|
);
|
||||||
|
};
|
||||||
59
src/components/drop-down/style.ts
Normal file
59
src/components/drop-down/style.ts
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
/**
|
||||||
|
* 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'};
|
||||||
|
}
|
||||||
|
`}
|
||||||
|
`;
|
||||||
12
src/components/error-renderer/index.tsx
Normal file
12
src/components/error-renderer/index.tsx
Normal 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
|
||||||
|
});
|
||||||
|
};
|
||||||
23
src/components/error-renderer/style.ts
Normal file
23
src/components/error-renderer/style.ts
Normal 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};
|
||||||
|
`;
|
||||||
83
src/components/forms/Checkbox.tsx
Normal file
83
src/components/forms/Checkbox.tsx
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
/**
|
||||||
|
* 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;
|
||||||
88
src/components/forms/Checkbox/index.tsx
Normal file
88
src/components/forms/Checkbox/index.tsx
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
/**
|
||||||
|
* 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;
|
||||||
@@ -1,58 +1,48 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||||
*/
|
*/
|
||||||
import {ChangeEvent, forwardRef, ForwardedRef, InputHTMLAttributes} from 'react';
|
import React, {ChangeEvent, forwardRef, ForwardedRef, InputHTMLAttributes} from 'react';
|
||||||
import * as styled from 'styled-components';
|
import * as styled from 'styled-components';
|
||||||
import Theme from 'theme';
|
import Theme from 'theme';
|
||||||
import {Label} from '../label';
|
import {Label} from './label';
|
||||||
|
|
||||||
export interface IInput extends InputHTMLAttributes<HTMLInputElement> {
|
export interface IInput extends InputHTMLAttributes<HTMLInputElement> {
|
||||||
onChange?: (event: ChangeEvent<HTMLInputElement>) => void;
|
onChange?: (event: ChangeEvent<HTMLInputElement>) => void;
|
||||||
error?: boolean;
|
error?: boolean;
|
||||||
icon?: JSX.Element;
|
icon?: React.JSX.Element;
|
||||||
imagePath?: string;
|
imagePath?: string;
|
||||||
imageAltText?: string;
|
imageAltText?: string;
|
||||||
label?: string;
|
label?: string;
|
||||||
labelColor?: string;
|
labelColor?: string;
|
||||||
labelIcon?: JSX.Element;
|
labelIcon?: React.JSX.Element;
|
||||||
labelClassName?: string;
|
labelClassName?: string;
|
||||||
helperText?: string;
|
helperText?: string;
|
||||||
helperTextClassName?: string;
|
helperTextClassName?: string;
|
||||||
width?: number | string;
|
width?: number | string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const {
|
const {colors, typography, formFieldWidth, formFieldMaxWidth, primaryBorderColor, primaryBorderRadius, primaryInputHeight, inputIconWidth, spacing} = Theme;
|
||||||
colors,
|
|
||||||
typography,
|
|
||||||
formFieldWidth,
|
|
||||||
formFieldMaxWidth,
|
|
||||||
primaryBorderColor,
|
|
||||||
primaryBorderRadius,
|
|
||||||
primaryInputHeight,
|
|
||||||
inputIconWidth,
|
|
||||||
spacing
|
|
||||||
} = Theme;
|
|
||||||
|
|
||||||
export const InputElement = styled.default.input<IInput>`
|
export const InputElement = styled.default.input<IInput>`
|
||||||
background-color: ${colors.white};
|
background-color: ${colors.white};
|
||||||
border: 1px solid ${({error}) => error ? colors.lightRed : primaryBorderColor};
|
border: 1px solid ${({error}) => (error ? colors.lightRed : primaryBorderColor)};
|
||||||
border-radius: ${primaryBorderRadius};
|
border-radius: ${primaryBorderRadius};
|
||||||
display: block;
|
display: block;
|
||||||
font-size: ${typography.primaryFontSize};
|
font-size: ${typography.primaryFontSize};
|
||||||
height: ${primaryInputHeight};
|
height: ${primaryInputHeight};
|
||||||
line-height: ${typography.primaryLineHeight};
|
line-height: ${typography.primaryLineHeight};
|
||||||
outline: none;
|
outline: none;
|
||||||
padding: ${spacing.small} ${({icon, imagePath}) => (icon || imagePath) ? spacing.xlarge : spacing.small};
|
padding: ${spacing.small} ${({icon, imagePath}) => (icon || imagePath ? spacing.xlarge : spacing.small)};
|
||||||
transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out;
|
transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out;
|
||||||
background-position: 1rem center;
|
background-position: 1rem center;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
width: inherit;
|
width: inherit;
|
||||||
opacity: ${({disabled}) => disabled ? 0.8 : 1};
|
opacity: ${({disabled}) => (disabled ? 0.8 : 1)};
|
||||||
cursor: ${({disabled}) => disabled && 'not-allowed'};
|
cursor: ${({disabled}) => disabled && 'not-allowed'};
|
||||||
-webkit-text-fill-color: ${({disabled}) => disabled && colors.gray800};
|
-webkit-text-fill-color: ${({disabled}) => disabled && colors.gray800};
|
||||||
`;
|
`;
|
||||||
const HelperText = styled.default.p<IInput>`
|
const HelperText = styled.default.p<IInput>`
|
||||||
color: ${({error}) => error ? colors.lightRed : colors.gray600};
|
color: ${({error}) => (error ? colors.lightRed : colors.gray600)};
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-size: ${typography.fontSizeS};
|
font-size: ${typography.fontSizeS};
|
||||||
margin-top: ${spacing.xxSmall};
|
margin-top: ${spacing.xxSmall};
|
||||||
@@ -79,56 +69,49 @@ const InputWrapper = styled.default.div`
|
|||||||
|
|
||||||
export const InputComponentWrapper = styled.default.div<IInput>`
|
export const InputComponentWrapper = styled.default.div<IInput>`
|
||||||
position: relative;
|
position: relative;
|
||||||
width: ${({width}) => width && isNaN(+width) ? width : ((width || formFieldWidth) + 'px')};
|
width: ${({width}) => (width && isNaN(+width) ? width : (width || formFieldWidth) + 'px')};
|
||||||
max-width: ${formFieldMaxWidth}px;
|
max-width: ${formFieldMaxWidth}px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
`;
|
`;
|
||||||
export const InputComponent = forwardRef((
|
export const InputComponent = forwardRef(
|
||||||
{
|
(
|
||||||
label,
|
{
|
||||||
labelColor,
|
label,
|
||||||
labelIcon,
|
labelColor,
|
||||||
labelClassName,
|
labelIcon,
|
||||||
icon,
|
labelClassName,
|
||||||
imagePath,
|
icon,
|
||||||
imageAltText = '',
|
imagePath,
|
||||||
helperText,
|
imageAltText = '',
|
||||||
helperTextClassName,
|
helperText,
|
||||||
error,
|
helperTextClassName,
|
||||||
width,
|
error,
|
||||||
disabled,
|
width,
|
||||||
name,
|
disabled,
|
||||||
...props
|
name,
|
||||||
}: IInput, ref: ForwardedRef<HTMLInputElement>): JSX.Element => {
|
...props
|
||||||
const InputIcon = icon || (imagePath && <img src={imagePath} alt={imageAltText} />);
|
}: IInput,
|
||||||
|
ref: ForwardedRef<HTMLInputElement>
|
||||||
|
): React.JSX.Element => {
|
||||||
|
const InputIcon = icon || (imagePath && <img src={imagePath} alt={imageAltText} />);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<InputComponentWrapper width={width}>
|
<InputComponentWrapper width={width}>
|
||||||
{!!label && (
|
{!!label && <Label text={label} color={labelColor} icon={labelIcon} className={labelClassName} />}
|
||||||
<Label
|
<InputWrapper>
|
||||||
text={label}
|
<ImageWrapper>{InputIcon}</ImageWrapper>
|
||||||
color={labelColor}
|
<InputElement icon={icon} name={name} imagePath={imagePath} disabled={disabled} ref={ref} {...props} />
|
||||||
icon={labelIcon}
|
</InputWrapper>
|
||||||
className={labelClassName}
|
{!!helperText && (
|
||||||
/>
|
<HelperText className={helperTextClassName} error={error}>
|
||||||
)}
|
{helperText}
|
||||||
<InputWrapper>
|
</HelperText>
|
||||||
<ImageWrapper>
|
)}
|
||||||
{InputIcon}
|
</InputComponentWrapper>
|
||||||
</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 default InputComponent;
|
||||||
|
export const Input = InputComponent;
|
||||||
|
|||||||
77
src/components/forms/SearchInput.tsx
Normal file
77
src/components/forms/SearchInput.tsx
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
/**
|
||||||
|
* 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;
|
||||||
1
src/components/forms/label/index.ts
Normal file
1
src/components/forms/label/index.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export * from './label';
|
||||||
@@ -1,23 +1,19 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||||
*/
|
*/
|
||||||
import {JSX} from 'react';
|
import React from 'react';
|
||||||
import {Label as StyledLabel} from './style';
|
import {Label as StyledLabel} from './style';
|
||||||
|
|
||||||
interface ILabel {
|
interface ILabel {
|
||||||
text: string;
|
text: string;
|
||||||
htmlFor?: string;
|
htmlFor?: string;
|
||||||
color?: string;
|
color?: string;
|
||||||
icon?: JSX.Element;
|
icon?: React.JSX.Element;
|
||||||
className?: string;
|
className?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Label = ({text, htmlFor, color, icon, className}: ILabel): JSX.Element => (
|
export const Label = ({text, htmlFor, color, icon, className}: ILabel): React.JSX.Element => (
|
||||||
<StyledLabel
|
<StyledLabel className={className} htmlFor={htmlFor} color={color}>
|
||||||
className={className}
|
|
||||||
htmlFor={htmlFor}
|
|
||||||
color={color}
|
|
||||||
>
|
|
||||||
{text} {icon}
|
{text} {icon}
|
||||||
</StyledLabel>
|
</StyledLabel>
|
||||||
);
|
);
|
||||||
@@ -8,7 +8,7 @@ const {spacing, colors, typography} = Theme;
|
|||||||
|
|
||||||
export const Label = styled.default.label<{color?: string}>`
|
export const Label = styled.default.label<{color?: string}>`
|
||||||
font-size: ${typography.fontSizeS};
|
font-size: ${typography.fontSizeS};
|
||||||
color: ${({color}) => (color || colors.gray900)};
|
color: ${({color}) => color || colors.gray900};
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
margin: ${spacing.xxSmall} 0;
|
margin: ${spacing.xxSmall} 0;
|
||||||
display: block;
|
display: block;
|
||||||
|
|||||||
198
src/components/icon-menu/icon-menu.tsx
Normal file
198
src/components/icon-menu/icon-menu.tsx
Normal 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;
|
||||||
4
src/components/icon-menu/index.tsx
Normal file
4
src/components/icon-menu/index.tsx
Normal 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';
|
||||||
79
src/components/icon-menu/style.ts
Normal file
79
src/components/icon-menu/style.ts
Normal 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);
|
||||||
|
`;
|
||||||
19
src/components/icon-menu/types.ts
Normal file
19
src/components/icon-menu/types.ts
Normal 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};
|
||||||
@@ -1,4 +1,16 @@
|
|||||||
export * from './buttons';
|
export * from './buttons';
|
||||||
|
export * from './channel-icon-menu';
|
||||||
|
export * from './error-renderer';
|
||||||
|
export * from './layout';
|
||||||
export * from './loaders';
|
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 './ProtectedRoute';
|
||||||
|
export * from './table';
|
||||||
export * from './typography';
|
export * from './typography';
|
||||||
4
src/components/indicator-component/indicators/index.ts
Normal file
4
src/components/indicator-component/indicators/index.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
export * from './indicators';
|
||||||
11
src/components/indicator-component/indicators/indicators.tsx
Normal file
11
src/components/indicator-component/indicators/indicators.tsx
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
/**
|
||||||
|
* 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>;
|
||||||
43
src/components/indicator-component/indicators/style.ts
Normal file
43
src/components/indicator-component/indicators/style.ts
Normal 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;
|
||||||
|
`;
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/**
|
||||||
|
* 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;
|
||||||
1
src/components/label/index.ts
Normal file
1
src/components/label/index.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export * from '../forms/label';
|
||||||
57
src/components/layout/index.tsx
Normal file
57
src/components/layout/index.tsx
Normal 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';
|
||||||
|
|
||||||
|
interface IColumn {
|
||||||
|
align?: string;
|
||||||
|
size?: number;
|
||||||
|
padding?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const {footerHeight} = Theme;
|
||||||
|
|
||||||
|
export const AppContainer = styled.default.div`
|
||||||
|
margin: 3.5rem 0 ${footerHeight};
|
||||||
|
height: calc(100vh - 3.5rem - ${footerHeight});
|
||||||
|
overflow: auto;
|
||||||
|
display: flex;
|
||||||
|
overflow-x: hidden;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const Body = styled.default.div`
|
||||||
|
width: 100%;
|
||||||
|
margin: 4rem 0;
|
||||||
|
padding: 0 ${Theme.spacing.xlarge};
|
||||||
|
background: ${Theme.colors.gray900};
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||||
|
min-height: calc(100vh - 2rem);
|
||||||
|
overflow: auto;
|
||||||
|
max-height: calc(100vh - 2rem);
|
||||||
|
max-width: calc(100vw - 2rem);
|
||||||
|
`;
|
||||||
|
|
||||||
|
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;
|
||||||
|
`;
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||||
*/
|
*/
|
||||||
import * as styled from 'styled-components';
|
import * as styled from 'styled-components';
|
||||||
import Theme from 'theme';
|
import Theme from 'theme';
|
||||||
|
|
||||||
interface LoadingWheelProps {
|
interface LoadingWheelProps {
|
||||||
size?: 'small' | 'medium' | 'large';
|
size?: 'small' | 'medium' | 'large';
|
||||||
@@ -15,11 +15,11 @@ const LoadingWheelContainer = styled.default.div<{
|
|||||||
color: string;
|
color: string;
|
||||||
}>`
|
}>`
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: ${({ size }) => size}px;
|
width: ${({size}) => size}px;
|
||||||
height: ${({ size }) => size}px;
|
height: ${({size}) => size}px;
|
||||||
border: 3px solid ${({ color }) => color}20;
|
border: 3px solid ${({color}) => color}20;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
border-top-color: ${({ color }) => color};
|
border-top-color: ${({color}) => color};
|
||||||
animation: spin 1s ease-in-out infinite;
|
animation: spin 1s ease-in-out infinite;
|
||||||
|
|
||||||
@keyframes spin {
|
@keyframes spin {
|
||||||
@@ -29,26 +29,14 @@ const LoadingWheelContainer = styled.default.div<{
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const LoadingWheel: React.FC<LoadingWheelProps> = ({
|
export const LoadingWheel: React.FC<LoadingWheelProps> = ({size = 'medium', color = Theme.colors.white, className}) => {
|
||||||
size = 'medium',
|
|
||||||
color = Theme.colors.white,
|
|
||||||
className
|
|
||||||
}) => {
|
|
||||||
const sizeMap = {
|
const sizeMap = {
|
||||||
small: Theme.loaderSize.small,
|
small: Theme.loaderSize.small,
|
||||||
medium: Theme.loaderSize.medium,
|
medium: Theme.loaderSize.medium,
|
||||||
large: Theme.loaderSize.large
|
large: Theme.loaderSize.large
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return <LoadingWheelContainer size={sizeMap[size]} color={color} className={className} role="status" aria-label="Loading" />;
|
||||||
<LoadingWheelContainer
|
|
||||||
size={sizeMap[size]}
|
|
||||||
color={color}
|
|
||||||
className={className}
|
|
||||||
role="status"
|
|
||||||
aria-label="Loading"
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default LoadingWheel;
|
export default LoadingWheel;
|
||||||
|
|||||||
5
src/components/modal/index.ts
Normal file
5
src/components/modal/index.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export {default as Modal} from './modal';
|
||||||
40
src/components/modal/modal-form-response/form-response.tsx
Normal file
40
src/components/modal/modal-form-response/form-response.tsx
Normal 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;
|
||||||
4
src/components/modal/modal-form-response/index.tsx
Normal file
4
src/components/modal/modal-form-response/index.tsx
Normal 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';
|
||||||
175
src/components/modal/modal-form-response/style.ts
Normal file
175
src/components/modal/modal-form-response/style.ts
Normal 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;
|
||||||
|
`;
|
||||||
87
src/components/modal/modal.tsx
Normal file
87
src/components/modal/modal.tsx
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
/**
|
||||||
|
* 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;
|
||||||
5
src/components/modal/multi-step-modal/index.ts
Normal file
5
src/components/modal/multi-step-modal/index.ts
Normal 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';
|
||||||
66
src/components/modal/multi-step-modal/multi-step-modal.tsx
Normal file
66
src/components/modal/multi-step-modal/multi-step-modal.tsx
Normal 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;
|
||||||
80
src/components/modal/style.ts
Normal file
80
src/components/modal/style.ts
Normal 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;
|
||||||
|
}
|
||||||
|
`;
|
||||||
26
src/components/new-tab-link/index.tsx
Normal file
26
src/components/new-tab-link/index.tsx
Normal 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;
|
||||||
5
src/components/pagination/index.ts
Normal file
5
src/components/pagination/index.ts
Normal 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';
|
||||||
87
src/components/pagination/pagination.tsx
Normal file
87
src/components/pagination/pagination.tsx
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
/**
|
||||||
|
* 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;
|
||||||
45
src/components/pagination/style.tsx
Normal file
45
src/components/pagination/style.tsx
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
/**
|
||||||
|
* 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};
|
||||||
|
`;
|
||||||
5
src/components/pre-formatted-code/index.tsx
Normal file
5
src/components/pre-formatted-code/index.tsx
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export {default} from './pre-formatted-code';
|
||||||
58
src/components/pre-formatted-code/pre-formatted-code.tsx
Normal file
58
src/components/pre-formatted-code/pre-formatted-code.tsx
Normal 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;
|
||||||
34
src/components/pre-formatted-code/styles.ts
Normal file
34
src/components/pre-formatted-code/styles.ts
Normal 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;
|
||||||
|
}
|
||||||
|
`;
|
||||||
6
src/components/restricted-text/index.ts
Normal file
6
src/components/restricted-text/index.ts
Normal 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';
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
/**
|
||||||
|
* 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;
|
||||||
115
src/components/restricted-text/restricted-text.tsx
Normal file
115
src/components/restricted-text/restricted-text.tsx
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
import {JSX, useEffect, useRef, useState} from 'react';
|
||||||
|
import {faEye, faEyeSlash} from '@fortawesome/free-regular-svg-icons';
|
||||||
|
|
||||||
|
import {Link} from 'components/ui';
|
||||||
|
import IconButton from 'components/buttons/icon-button';
|
||||||
|
import {CopyIconButton} from 'components/buttons/copy-icon-button';
|
||||||
|
import NewTabLink from 'components/new-tab-link';
|
||||||
|
|
||||||
|
import {RestrictedDiv, MeasuringBlock, TruncatedBlock} from './style';
|
||||||
|
|
||||||
|
export interface IRestrictedText {
|
||||||
|
text: string;
|
||||||
|
hasViewOption?: boolean;
|
||||||
|
hasCopyOption?: boolean;
|
||||||
|
isLink?: boolean;
|
||||||
|
linkValue?: string;
|
||||||
|
linkClassName?: string;
|
||||||
|
index?: number;
|
||||||
|
fullWidth?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const iconButtonsWidth = 48;
|
||||||
|
|
||||||
|
export const RestrictedText = ({
|
||||||
|
text,
|
||||||
|
hasViewOption = true,
|
||||||
|
hasCopyOption = true,
|
||||||
|
isLink = false,
|
||||||
|
linkValue,
|
||||||
|
linkClassName = '',
|
||||||
|
fullWidth = true
|
||||||
|
}: IRestrictedText): JSX.Element => {
|
||||||
|
const restrictedDivRef = useRef(null);
|
||||||
|
const measuringRef = useRef(null);
|
||||||
|
const [showValue, setShowValue] = useState(false);
|
||||||
|
const [showEyeIcon, setShowEyeIcon] = useState(hasViewOption);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const handleResize = () => {
|
||||||
|
handleShowEyeIcon();
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener('resize', handleResize);
|
||||||
|
|
||||||
|
handleShowEyeIcon();
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener('resize', handleResize);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleShowEyeIcon = () => {
|
||||||
|
if (!restrictedDivRef.current || !measuringRef.current) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const containerWidth = restrictedDivRef.current.clientWidth - iconButtonsWidth;
|
||||||
|
const fullTextWidth = measuringRef.current.getBoundingClientRect()?.width;
|
||||||
|
|
||||||
|
setShowEyeIcon(fullTextWidth > containerWidth);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleShowValueChange = () => setShowValue(!showValue);
|
||||||
|
const CurrentTextView = (): JSX.Element => {
|
||||||
|
if (isLink && !linkValue) {
|
||||||
|
return (
|
||||||
|
<NewTabLink
|
||||||
|
link={text}
|
||||||
|
className={linkClassName}
|
||||||
|
text={text}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isLink && linkValue) {
|
||||||
|
return (
|
||||||
|
<Link
|
||||||
|
to={linkValue}
|
||||||
|
className={linkClassName}
|
||||||
|
>
|
||||||
|
{text}
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return <>{text}</>;
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<RestrictedDiv ref={restrictedDivRef} className={`testId-truncatedDetails ${fullWidth && 'full-width'}`}>
|
||||||
|
<MeasuringBlock ref={measuringRef}>{text}</MeasuringBlock>
|
||||||
|
<TruncatedBlock className={showValue ? '' : 'truncated'}>
|
||||||
|
<CurrentTextView />
|
||||||
|
</TruncatedBlock>
|
||||||
|
<div>
|
||||||
|
{showEyeIcon && (
|
||||||
|
<IconButton
|
||||||
|
onClick={handleShowValueChange}
|
||||||
|
tooltipText={showValue ? 'Hide' : 'Show'}
|
||||||
|
icon={showValue ? faEyeSlash : faEye}
|
||||||
|
className={`${isLink ? 'testId-permalink' : ''} testId-viewDetails`}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{hasCopyOption && (
|
||||||
|
<CopyIconButton text={text} displayText={false} className="testId-copyDetails" />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</RestrictedDiv>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default RestrictedText;
|
||||||
96
src/components/restricted-text/style.ts
Normal file
96
src/components/restricted-text/style.ts
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
/**
|
||||||
|
* 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,
|
||||||
|
typography,
|
||||||
|
spacing,
|
||||||
|
} = Theme;
|
||||||
|
|
||||||
|
export const RestrictedDiv = styled.default.div`
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: start;
|
||||||
|
word-wrap: break-word;
|
||||||
|
&.full-width {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
& div {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
align-content: center;
|
||||||
|
& span {
|
||||||
|
color: ${Theme.primaryThemeColor};
|
||||||
|
display: none;
|
||||||
|
cursor: pointer;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
.icon-button {
|
||||||
|
width: 1.5rem;
|
||||||
|
height: 1.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
& span {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const TruncatedBlock = styled.default.p`
|
||||||
|
overflow: hidden;
|
||||||
|
padding: ${spacing.small} 0;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
|
||||||
|
&.truncated {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const MeasuringBlock = styled.default.p`
|
||||||
|
position: fixed;
|
||||||
|
visibility: hidden;
|
||||||
|
opacity: 0;
|
||||||
|
white-space: nowrap;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const RestrictedRowWrapper = styled.default.div`
|
||||||
|
display: flex;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const RestrictedRowLabel = styled.default.div`
|
||||||
|
width: 135px;
|
||||||
|
display: flex;
|
||||||
|
align-self: center;
|
||||||
|
color: ${colors.gray300};
|
||||||
|
font-size: ${typography.fontSizeS};
|
||||||
|
padding: ${spacing.small};
|
||||||
|
|
||||||
|
a {
|
||||||
|
margin: 0 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
margin: 0 2px;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const RestrictedRowText = styled.default.div`
|
||||||
|
color: ${colors.gray300};
|
||||||
|
font-size: ${typography.fontSizeS};
|
||||||
|
border-bottom: 1px solid ${colors.gray700};
|
||||||
|
padding: ${spacing.small};
|
||||||
|
width: calc(100% - 135px);
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: ${colors.lightBlue};
|
||||||
|
overflow-wrap: anywhere;
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: ${typography.fontSizeS};
|
||||||
|
}
|
||||||
|
`;
|
||||||
2
src/components/shared/theme.ts
Normal file
2
src/components/shared/theme.ts
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
export {default, theme, Theme} from '../../theme';
|
||||||
|
export * from '../../theme';
|
||||||
@@ -12,9 +12,9 @@ export const truncateWord = (word = '', length = 30): string => {
|
|||||||
return word;
|
return word;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const isEqual = (a: any, b: any): boolean => { // eslint-disable-line
|
export const isEqual = (a: unknown, b: unknown): boolean => {
|
||||||
if (typeof(a) === typeof(b)) {
|
if (typeof a === typeof b) {
|
||||||
if (typeof(a) === 'object') {
|
if (typeof a === 'object') {
|
||||||
return JSON.stringify(a) === JSON.stringify(b);
|
return JSON.stringify(a) === JSON.stringify(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,8 +39,8 @@ export const mergeSimilarCSVFiles = (formerCSV: string, latterCSV: string): stri
|
|||||||
return formerCSV;
|
return formerCSV;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const chunk = (array: any[], size: number = 1) => { // eslint-disable-line
|
export const chunk = <T>(array: T[], size: number = 1): T[][] => {
|
||||||
const arrayChunks = [];
|
const arrayChunks: T[][] = [];
|
||||||
|
|
||||||
for (let i = 0; i < array.length; i += size) {
|
for (let i = 0; i < array.length; i += size) {
|
||||||
const arrayChunk = array.slice(i, i + size);
|
const arrayChunk = array.slice(i, i + size);
|
||||||
@@ -66,10 +66,7 @@ export const getRangeByInterval = (start: Date, end: Date, intervalAmount: Durat
|
|||||||
|
|
||||||
export const getBrowserLimits = (): IBrowserLimits => browserLimits[PlatformDetectionService.browserName.toLowerCase()];
|
export const getBrowserLimits = (): IBrowserLimits => browserLimits[PlatformDetectionService.browserName.toLowerCase()];
|
||||||
|
|
||||||
export const getMaxByPropertyName = (
|
export const getMaxByPropertyName = (array: Record<string, number | string | boolean>[], propertyName: string): number => {
|
||||||
array: Record<string, number | string | boolean>[],
|
|
||||||
propertyName: string
|
|
||||||
): number => {
|
|
||||||
let length = array.length;
|
let length = array.length;
|
||||||
let max = -Infinity;
|
let max = -Infinity;
|
||||||
|
|
||||||
|
|||||||
4
src/components/table-screen-header/index.ts
Normal file
4
src/components/table-screen-header/index.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
export {default as TableScreenHeader} from './table-screen-header';
|
||||||
37
src/components/table-screen-header/style.tsx
Normal file
37
src/components/table-screen-header/style.tsx
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/**
|
||||||
|
* 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 ScreenHeader = styled.default.div`
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: baseline;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
width: 100%;
|
||||||
|
margin: 0 0 .5rem;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const ScreenHeaderControls = styled.default.div`
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const HeaderControlWrapper = styled.default.div`
|
||||||
|
margin-left: 12px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const HeaderTitle = styled.default.div`
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
h2 {
|
||||||
|
color: ${colors.white};
|
||||||
|
margin: 0 .5rem 0 0;
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
color: ${colors.gray200};
|
||||||
|
}
|
||||||
|
`;
|
||||||
48
src/components/table-screen-header/table-screen-header.tsx
Normal file
48
src/components/table-screen-header/table-screen-header.tsx
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
import {JSX} from 'react';
|
||||||
|
import {
|
||||||
|
ITableWithLoadMoreHeader,
|
||||||
|
ITableWithPaginationHeader,
|
||||||
|
TableHeaderKey
|
||||||
|
} from 'interfaces/tableProps';
|
||||||
|
import {ScreenHeader, ScreenHeaderControls, HeaderControlWrapper, HeaderTitle} from './style';
|
||||||
|
|
||||||
|
type ScreenHeaderProps = ITableWithLoadMoreHeader | ITableWithPaginationHeader;
|
||||||
|
|
||||||
|
export interface ITableScreenHeader {
|
||||||
|
title: string;
|
||||||
|
subtitle?: string;
|
||||||
|
screenHeader: ScreenHeaderProps;
|
||||||
|
renderControl: (screenHeader: ScreenHeaderProps, key: TableHeaderKey) => JSX.Element | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const TableScreenHeader = ({
|
||||||
|
title,
|
||||||
|
subtitle = '',
|
||||||
|
screenHeader,
|
||||||
|
renderControl
|
||||||
|
}: ITableScreenHeader): JSX.Element => {
|
||||||
|
return (
|
||||||
|
<ScreenHeader className="table-header">
|
||||||
|
<HeaderTitle>
|
||||||
|
<h2>{title}</h2>
|
||||||
|
{subtitle && <p>{subtitle}</p>}
|
||||||
|
</HeaderTitle>
|
||||||
|
<ScreenHeaderControls>
|
||||||
|
{Object.keys(screenHeader).map(key => {
|
||||||
|
const headerControl = screenHeader[key].render
|
||||||
|
? screenHeader[key].render(key)
|
||||||
|
: renderControl(screenHeader, key as TableHeaderKey);
|
||||||
|
|
||||||
|
return headerControl ? (
|
||||||
|
<HeaderControlWrapper key={key}>{headerControl}</HeaderControlWrapper>
|
||||||
|
) : null;
|
||||||
|
})}
|
||||||
|
</ScreenHeaderControls>
|
||||||
|
</ScreenHeader>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TableScreenHeader;
|
||||||
6
src/components/table-with-pagination/index.ts
Normal file
6
src/components/table-with-pagination/index.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
export * from 'components/table';
|
||||||
|
export {default as TableWithPagination} from './table-with-pagination';
|
||||||
|
export {default as Pagination} from '../pagination/pagination';
|
||||||
205
src/components/table-with-pagination/table-with-pagination.tsx
Normal file
205
src/components/table-with-pagination/table-with-pagination.tsx
Normal file
@@ -0,0 +1,205 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
import {useEffect, useState} from 'react';
|
||||||
|
|
||||||
|
import {
|
||||||
|
DataRowType,
|
||||||
|
Table,
|
||||||
|
TableHeaderKey,
|
||||||
|
ITable,
|
||||||
|
ITableWithPaginationHeader,
|
||||||
|
ITableSort
|
||||||
|
} from 'components/table';
|
||||||
|
import {isEqual} from 'utility/validators';
|
||||||
|
import SearchInput from 'components/forms/SearchInput';
|
||||||
|
import {compare} from 'utility/sort';
|
||||||
|
import {TableScreenHeader} from 'components/table-screen-header/table-screen-header';
|
||||||
|
import {AddButton} from 'components/buttons/icon-buttons';
|
||||||
|
import {Pagination} from 'components/pagination/pagination' ;
|
||||||
|
import {Select} from 'components/ui/select';
|
||||||
|
|
||||||
|
import {useSort, useSearch} from 'utility/custom-hooks';
|
||||||
|
|
||||||
|
interface ITableWithPagination extends ITable {
|
||||||
|
screenHeader: ITableWithPaginationHeader;
|
||||||
|
paginationItemText?: string;
|
||||||
|
getCurrentDisplayList?: (data: Record<string, string | number | null>[]) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const TableWithPagination = ({
|
||||||
|
title = '',
|
||||||
|
screenHeader,
|
||||||
|
columns,
|
||||||
|
data,
|
||||||
|
sortColumn,
|
||||||
|
sortDirection,
|
||||||
|
style,
|
||||||
|
paginationItemText,
|
||||||
|
errorMessage,
|
||||||
|
getCurrentDisplayList,
|
||||||
|
changeSortProps,
|
||||||
|
searchValue: propsSearchValue = '',
|
||||||
|
changeSearch
|
||||||
|
}: ITableWithPagination): JSX.Element => {
|
||||||
|
const [currentPageNumber, setCurrentPageNumber] = useState<number>(1);
|
||||||
|
const [currentData, setCurrentData] = useState<DataRowType[]>([]);
|
||||||
|
const [filteredData, setFilteredData] = useState<DataRowType[]>(data || []);
|
||||||
|
const [total, setTotal] = useState<number>(data ? data.length : 0);
|
||||||
|
const [rowsCount, setRowsCount] = useState(10);
|
||||||
|
const [sortData, setSortData] = useSort({
|
||||||
|
sortColumn,
|
||||||
|
sortDirection
|
||||||
|
});
|
||||||
|
const [searchValue, setSearchValue] = useSearch(propsSearchValue);
|
||||||
|
const amendMarginsInElementsHeight = (selector: string, action: 'add' | 'remove') => {
|
||||||
|
const element = document.querySelector(selector);
|
||||||
|
let elementHeight = element?.clientHeight || 0;
|
||||||
|
|
||||||
|
if (!element) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action === 'add') {
|
||||||
|
elementHeight += parseInt(window?.getComputedStyle(element).getPropertyValue('margin-top'));
|
||||||
|
elementHeight += parseInt(window?.getComputedStyle(element).getPropertyValue('margin-bottom'));
|
||||||
|
} else {
|
||||||
|
elementHeight -= parseInt(window?.getComputedStyle(element).getPropertyValue('margin-top'));
|
||||||
|
elementHeight -= parseInt(window?.getComputedStyle(element).getPropertyValue('margin-bottom'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return elementHeight;
|
||||||
|
};
|
||||||
|
|
||||||
|
const calculateRowsCount = () => {
|
||||||
|
const tableContainerHeight = amendMarginsInElementsHeight('.table-container', 'remove') || 0;
|
||||||
|
const paginationHeight = amendMarginsInElementsHeight('.pagination-container', 'add') || 0;
|
||||||
|
const tableHeaderHeight = amendMarginsInElementsHeight('.table-header', 'add') || 0;
|
||||||
|
const tableRow = document.querySelector('.table-row') || {clientHeight: 50};
|
||||||
|
const rowHeight = tableRow?.clientHeight || 50;
|
||||||
|
const newRowsCount = Math.round((tableContainerHeight - paginationHeight - tableHeaderHeight) / rowHeight);
|
||||||
|
|
||||||
|
setRowsCount(newRowsCount || rowsCount);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
let pxRatioBeforeZoom = window.devicePixelRatio;
|
||||||
|
let windowHeightBeforeResize = window.innerHeight;
|
||||||
|
const trackResize = e => {
|
||||||
|
const pxRatioAfterZoom = e.devicePixelRatio;
|
||||||
|
const windowHeightAfterResize = e.target.innerHeight;
|
||||||
|
|
||||||
|
if (pxRatioAfterZoom !== pxRatioBeforeZoom || windowHeightAfterResize !== windowHeightBeforeResize) {
|
||||||
|
pxRatioBeforeZoom = pxRatioAfterZoom;
|
||||||
|
windowHeightBeforeResize = windowHeightAfterResize;
|
||||||
|
|
||||||
|
calculateRowsCount();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
calculateRowsCount();
|
||||||
|
|
||||||
|
window.addEventListener('resize', trackResize);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener('resize', trackResize);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
let newData = Array.isArray(data) ? [...data] : [];
|
||||||
|
|
||||||
|
if (searchValue && Array.isArray(data)) {
|
||||||
|
newData = data.filter(prop => {
|
||||||
|
return Object.keys(columns).some(key => {
|
||||||
|
return String(prop[key]).toLowerCase().includes(searchValue.toLowerCase());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isEqual(newData, filteredData)) {
|
||||||
|
setFilteredData(newData);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isEqual(total, newData.length)) {
|
||||||
|
setTotal(newData.length);
|
||||||
|
}
|
||||||
|
}, [data, searchValue, rowsCount, columns]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const start = (currentPageNumber - 1) * rowsCount;
|
||||||
|
const sortedData = sortData
|
||||||
|
? filteredData.sort((a, b) => compare(a, b, sortData.sortDirection, sortData.sortColumn))
|
||||||
|
: filteredData;
|
||||||
|
const newCurrentData = sortedData.slice(start, start + rowsCount);
|
||||||
|
|
||||||
|
if (!isEqual(newCurrentData, currentData)) {
|
||||||
|
setCurrentData(newCurrentData);
|
||||||
|
|
||||||
|
if (getCurrentDisplayList) {
|
||||||
|
getCurrentDisplayList(newCurrentData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [filteredData, currentPageNumber, rowsCount, sortData]);
|
||||||
|
|
||||||
|
const search = (val: string) => {
|
||||||
|
if (val !== searchValue) {
|
||||||
|
if (changeSearch) {
|
||||||
|
changeSearch({searchValue: val});
|
||||||
|
} else {
|
||||||
|
setSearchValue(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
setCurrentPageNumber(1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const sort = (data: ITableSort) => {
|
||||||
|
if (changeSortProps) {
|
||||||
|
changeSortProps(data);
|
||||||
|
} else {
|
||||||
|
setSortData(data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderControl = (screenHeader: ITableWithPaginationHeader, key: TableHeaderKey) => {
|
||||||
|
switch (key) {
|
||||||
|
case TableHeaderKey.Search:
|
||||||
|
return <SearchInput search={search} defaultValue={searchValue} />;
|
||||||
|
case TableHeaderKey.AddRow:
|
||||||
|
return <AddButton onClick={screenHeader[key]?.openAddRowModal} className="testId-hashAddButton" />;
|
||||||
|
case TableHeaderKey.SelectType:
|
||||||
|
return <Select {...screenHeader[key]} />;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<TableScreenHeader
|
||||||
|
title={title}
|
||||||
|
screenHeader={screenHeader}
|
||||||
|
renderControl={renderControl}
|
||||||
|
/>
|
||||||
|
<Table
|
||||||
|
columns={columns}
|
||||||
|
data={currentData}
|
||||||
|
sortColumn={sortColumn}
|
||||||
|
sortDirection={sortDirection}
|
||||||
|
style={style}
|
||||||
|
sort={sort}
|
||||||
|
errorMessage={errorMessage}
|
||||||
|
/>
|
||||||
|
<Pagination
|
||||||
|
currentPageNumber={currentPageNumber}
|
||||||
|
setCurrentPage={setCurrentPageNumber}
|
||||||
|
numberOfItems={total}
|
||||||
|
itemsPerPage={rowsCount}
|
||||||
|
itemText={paginationItemText}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TableWithPagination;
|
||||||
8
src/components/table/index.ts
Normal file
8
src/components/table/index.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
export * from 'interfaces/tableProps';
|
||||||
|
export {default as Table} from './table';
|
||||||
|
export * from './table-cells';
|
||||||
|
export * from './props';
|
||||||
|
export * from './style';
|
||||||
74
src/components/table/props.ts
Normal file
74
src/components/table/props.ts
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
import React, {CSSProperties} from 'react';
|
||||||
|
|
||||||
|
import {DirectionType, ITableSearch, ITableSort} from 'interfaces/tableProps';
|
||||||
|
import {ITableCellDropdown} from '.';
|
||||||
|
|
||||||
|
export enum CellType {
|
||||||
|
Text = 'text',
|
||||||
|
Link = 'link',
|
||||||
|
Date = 'date',
|
||||||
|
DateTime = 'datetime',
|
||||||
|
DropDown = 'dropdown',
|
||||||
|
Component = 'component'
|
||||||
|
}
|
||||||
|
|
||||||
|
export type DataValueType = string | number | null | undefined;
|
||||||
|
export type DataRowType = Record<string, DataValueType>;
|
||||||
|
|
||||||
|
interface ITableCellText {
|
||||||
|
propName: string;
|
||||||
|
hasShow?: boolean;
|
||||||
|
hasCopy?: boolean;
|
||||||
|
isSortable?: boolean;
|
||||||
|
direction?: DirectionType;
|
||||||
|
sortable?: boolean;
|
||||||
|
mutate?: (value: DataValueType | boolean) => string | number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ITableColumn {
|
||||||
|
title: string;
|
||||||
|
type?: CellType;
|
||||||
|
textCell?: ITableCellText;
|
||||||
|
renderCell?: (row?: DataRowType) => React.JSX.Element;
|
||||||
|
dropdownCell?: Omit<ITableCellDropdown, 'row'>;
|
||||||
|
thStyle?: CSSProperties;
|
||||||
|
tdStyle?: CSSProperties;
|
||||||
|
hasBorder?: boolean;
|
||||||
|
sortAction?: (key: string) => void;
|
||||||
|
hideColumnAt?: number;
|
||||||
|
isHidden?: boolean;
|
||||||
|
width?: number;
|
||||||
|
path?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ColumnsType = Record<string, ITableColumn>;
|
||||||
|
|
||||||
|
export interface ITableRow {
|
||||||
|
columns: ColumnsType;
|
||||||
|
row: DataRowType;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ITable {
|
||||||
|
title?: string;
|
||||||
|
columns: ColumnsType;
|
||||||
|
className?: string;
|
||||||
|
data?: DataRowType[];
|
||||||
|
tableName?: string;
|
||||||
|
addRow?: (row?: DataRowType) => void;
|
||||||
|
searchProps?: string[];
|
||||||
|
sortColumn?: string;
|
||||||
|
sortDirection?: DirectionType;
|
||||||
|
style?: CSSProperties;
|
||||||
|
tableHeader?: Element;
|
||||||
|
tableBottom?: Element;
|
||||||
|
sort?: (data: ITableSort) => void;
|
||||||
|
errorMessage?: null | string;
|
||||||
|
isFetching?: boolean;
|
||||||
|
hasMore?: boolean;
|
||||||
|
searchValue?: string;
|
||||||
|
changeSearch?: (val: ITableSearch) => void;
|
||||||
|
changeSortProps?: (data: ITableSort) => void;
|
||||||
|
}
|
||||||
75
src/components/table/style.tsx
Normal file
75
src/components/table/style.tsx
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
/**
|
||||||
|
* 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, typography, primaryBackground} = Theme;
|
||||||
|
|
||||||
|
export const Table = styled.default.table`
|
||||||
|
width: 100%;
|
||||||
|
max-height: calc(100vh - 2rem);
|
||||||
|
max-width: calc(100vw - 2rem);
|
||||||
|
border-collapse: collapse;
|
||||||
|
margin: 0;
|
||||||
|
table-layout: fixed;
|
||||||
|
background-color: ${Theme.blackWithOpacity};
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const Thead = styled.default.thead`
|
||||||
|
color: ${colors.white};
|
||||||
|
& tr {
|
||||||
|
vertical-align: middle;
|
||||||
|
border: none;
|
||||||
|
& th {
|
||||||
|
top: -1px;
|
||||||
|
background-color: ${primaryBackground};
|
||||||
|
padding: ${Theme.spacing.small} 0;
|
||||||
|
z-index: 10;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const TH = styled.default.th<{active?: boolean; border?: boolean; width?: number}>`
|
||||||
|
color: ${({active}) => (active ? colors.white : colors.gray500)};
|
||||||
|
font-size: ${typography.fontSizeS};
|
||||||
|
cursor: pointer;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
border-right-color: ${colors.gray700};
|
||||||
|
& span {
|
||||||
|
margin-left: .4rem;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const Tbody = styled.default.tbody`
|
||||||
|
tr:nth-child(odd) {
|
||||||
|
background: ${colors.gray800};
|
||||||
|
}
|
||||||
|
& tr {
|
||||||
|
border-color: transparent transparent ${colors.black} transparent;
|
||||||
|
height: 3rem;
|
||||||
|
& td {
|
||||||
|
color: ${colors.white};
|
||||||
|
padding: ${Theme.spacing.small};
|
||||||
|
word-wrap: break-word;
|
||||||
|
font-size: ${typography.fontSizeS};
|
||||||
|
position: relative;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
& > div,
|
||||||
|
& > p {
|
||||||
|
text-align: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
& a {
|
||||||
|
color: ${colors.lightBlue};
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
18
src/components/table/table-body.tsx
Normal file
18
src/components/table/table-body.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
import React from 'react';
|
||||||
|
import TableRow from './table-row';
|
||||||
|
import {Tbody} from './style';
|
||||||
|
import {ColumnsType} from './props';
|
||||||
|
|
||||||
|
interface ITableBody {
|
||||||
|
columns: ColumnsType;
|
||||||
|
data: Record<string, string | number | null>[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const TableBody = ({columns, data}: ITableBody): React.JSX.Element => (
|
||||||
|
<Tbody>{data.length ? data.map((row, idx) => <TableRow key={`tableRow-${idx}-${Date.now()}`} columns={columns} row={row} />) : null}</Tbody>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default TableBody;
|
||||||
4
src/components/table/table-cells/index.ts
Normal file
4
src/components/table/table-cells/index.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
export * from './table-cell-dropdown';
|
||||||
29
src/components/table/table-cells/table-cell-dropdown.tsx
Normal file
29
src/components/table/table-cells/table-cell-dropdown.tsx
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
import React from 'react';
|
||||||
|
import {DataRowType} from '../props';
|
||||||
|
|
||||||
|
export interface ITableCellDropdown {
|
||||||
|
row: DataRowType;
|
||||||
|
title?: string;
|
||||||
|
icon?: React.JSX.Element;
|
||||||
|
Component: (props: any) => React.JSX.Element; //eslint-disable-line
|
||||||
|
keys: string[];
|
||||||
|
action?: (key: string) => void;
|
||||||
|
componentProps?: Record<string, unknown>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const TableCellDropdown = ({title = '', Component, keys, action, componentProps, row}: ITableCellDropdown): React.JSX.Element => {
|
||||||
|
const data = {} as Record<string, unknown>;
|
||||||
|
|
||||||
|
keys.forEach(value => {
|
||||||
|
data[value] = row[value];
|
||||||
|
});
|
||||||
|
|
||||||
|
if (data.showDropdown !== undefined) {
|
||||||
|
return data.showDropdown ? <Component title={title} data={data} action={action} {...componentProps} /> : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return <Component title={title} data={data} action={action} {...componentProps} />;
|
||||||
|
};
|
||||||
66
src/components/table/table-header-cell.tsx
Normal file
66
src/components/table/table-header-cell.tsx
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
import React from 'react';
|
||||||
|
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
|
||||||
|
import {faCaretDown, faCaretUp} from '@fortawesome/free-solid-svg-icons';
|
||||||
|
|
||||||
|
import {DirectionType} from 'interfaces/tableProps';
|
||||||
|
import {TH} from './style';
|
||||||
|
import {ITableColumn, CellType} from './props';
|
||||||
|
|
||||||
|
interface ITableHeaderCell {
|
||||||
|
column: Partial<ITableColumn>;
|
||||||
|
sortHeaderColumn: string | null;
|
||||||
|
sortAction?: (key: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const TableHeaderCell = ({
|
||||||
|
column: {type, title, hasBorder = true, textCell, isHidden, width, thStyle},
|
||||||
|
sortHeaderColumn,
|
||||||
|
sortAction
|
||||||
|
}: ITableHeaderCell): React.JSX.Element | null => {
|
||||||
|
switch (type) {
|
||||||
|
case CellType.DropDown:
|
||||||
|
case CellType.Component: {
|
||||||
|
return (
|
||||||
|
<TH
|
||||||
|
border={hasBorder.toString()}
|
||||||
|
style={{
|
||||||
|
width,
|
||||||
|
maxWidth: width,
|
||||||
|
minWidth: width,
|
||||||
|
...thStyle
|
||||||
|
}}>
|
||||||
|
{title}
|
||||||
|
</TH>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
case CellType.Date:
|
||||||
|
case CellType.DateTime:
|
||||||
|
case CellType.Link:
|
||||||
|
case CellType.Text:
|
||||||
|
default: {
|
||||||
|
const {propName, isSortable = true, direction} = textCell;
|
||||||
|
const handleOnClick = () => {
|
||||||
|
if (sortAction && isSortable) {
|
||||||
|
sortAction(propName);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const isActive = isSortable && sortAction && sortHeaderColumn && sortHeaderColumn === propName;
|
||||||
|
|
||||||
|
return isHidden ? null : (
|
||||||
|
<TH active={isActive} border={hasBorder.toString()} key={propName} onClick={handleOnClick} width={width} style={thStyle}>
|
||||||
|
{title}
|
||||||
|
{isActive && (
|
||||||
|
<span>
|
||||||
|
<FontAwesomeIcon icon={direction === DirectionType.Asc ? faCaretDown : faCaretUp} />
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</TH>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
30
src/components/table/table-header.tsx
Normal file
30
src/components/table/table-header.tsx
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
import React from 'react';
|
||||||
|
import {Thead} from './style';
|
||||||
|
import {TableHeaderCell} from './table-header-cell';
|
||||||
|
import {ColumnsType} from './props';
|
||||||
|
|
||||||
|
export interface ITableHeader {
|
||||||
|
columns: ColumnsType;
|
||||||
|
sortHeaderColumn: string | null;
|
||||||
|
sortAction: (key: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const TableHeader = ({columns, sortHeaderColumn, sortAction}: ITableHeader): React.JSX.Element => {
|
||||||
|
const renderHeader = (): React.JSX.Element[] =>
|
||||||
|
Object.keys(columns).map(
|
||||||
|
(key: string, index: number): React.JSX.Element => (
|
||||||
|
<TableHeaderCell key={`table-header-cell-${index}`} column={columns[key]} sortHeaderColumn={sortHeaderColumn} sortAction={sortAction} />
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Thead>
|
||||||
|
<tr>{renderHeader()}</tr>
|
||||||
|
</Thead>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TableHeader;
|
||||||
91
src/components/table/table-row.tsx
Normal file
91
src/components/table/table-row.tsx
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
import React from 'react';
|
||||||
|
import moment from 'moment';
|
||||||
|
import {getDateFromNow} from 'utility/date';
|
||||||
|
import {DateComponent} from 'components/date-render-component';
|
||||||
|
import {RestrictedText} from 'components/restricted-text';
|
||||||
|
|
||||||
|
import {TableCellDropdown} from './table-cells';
|
||||||
|
import {CellType, ITableRow} from './props';
|
||||||
|
|
||||||
|
export const TableRow = ({columns, row}: ITableRow): React.JSX.Element | null => {
|
||||||
|
if (!row) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<tr className="table-row">
|
||||||
|
{Object.keys(columns).map((key, idx) => {
|
||||||
|
const {isHidden, renderCell, dropdownCell, textCell, type, path = '', tdStyle, width} = columns[key];
|
||||||
|
|
||||||
|
if (isHidden) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (renderCell) {
|
||||||
|
return (
|
||||||
|
<td key={`tableData${idx}`} style={tdStyle}>
|
||||||
|
{renderCell(row)}
|
||||||
|
</td>
|
||||||
|
);
|
||||||
|
} else if (dropdownCell) {
|
||||||
|
return (
|
||||||
|
<td
|
||||||
|
key={`tableData${idx}`}
|
||||||
|
style={{
|
||||||
|
width,
|
||||||
|
maxWidth: width,
|
||||||
|
minWidth: width,
|
||||||
|
...tdStyle
|
||||||
|
}}>
|
||||||
|
<TableCellDropdown row={row} {...dropdownCell} />
|
||||||
|
</td>
|
||||||
|
);
|
||||||
|
} else if (textCell) {
|
||||||
|
const {propName} = textCell;
|
||||||
|
const value = row[propName] || '';
|
||||||
|
|
||||||
|
if (type === CellType.Date) {
|
||||||
|
return (
|
||||||
|
<td key={`tableData${idx}`} style={tdStyle}>
|
||||||
|
{getDateFromNow(value)}
|
||||||
|
</td>
|
||||||
|
);
|
||||||
|
} else if (type === CellType.DateTime) {
|
||||||
|
return (
|
||||||
|
<td key={`tableData${idx}`} style={tdStyle}>
|
||||||
|
<DateComponent date={moment.utc(value)} />
|
||||||
|
</td>
|
||||||
|
);
|
||||||
|
} else if (type === CellType.Link) {
|
||||||
|
let link = path || '';
|
||||||
|
|
||||||
|
if (row.extraPath) {
|
||||||
|
link += `${path ? '/' : ''}${row.extraPath}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<td key={`tableData${idx}`} style={tdStyle}>
|
||||||
|
<div>
|
||||||
|
<RestrictedText isLink linkValue={link} linkClassName="testId-tableLink" text={`${value}`} />
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<td key={`tableData${idx}`} style={tdStyle}>
|
||||||
|
<RestrictedText index={idx} text={`${value}`} />
|
||||||
|
</td>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return <td key={`tableData${idx}`} />;
|
||||||
|
})}
|
||||||
|
</tr>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TableRow;
|
||||||
107
src/components/table/table.tsx
Normal file
107
src/components/table/table.tsx
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
import React, {useEffect, useLayoutEffect, useState} from 'react';
|
||||||
|
|
||||||
|
import {DirectionType} from 'interfaces/tableProps';
|
||||||
|
import {compare} from 'utility/sort';
|
||||||
|
import {Error} from 'components/error-renderer/style';
|
||||||
|
import {Table as TableContainer} from './style';
|
||||||
|
import TableHeader from './table-header';
|
||||||
|
import TableBody from './table-body';
|
||||||
|
import {ITable, DataRowType, ColumnsType} from './props';
|
||||||
|
|
||||||
|
const defaultHideColumnWidth = 100;
|
||||||
|
const TableComponent = ({columns, data, sortColumn, sortDirection, sort, errorMessage}: ITable): React.JSX.Element => {
|
||||||
|
const getHeadersBasedOnWidth = (columns: ColumnsType) => {
|
||||||
|
const newHeaders: ColumnsType = {};
|
||||||
|
|
||||||
|
Object.keys(columns).forEach(key => {
|
||||||
|
const hideColumnAt = columns[key]?.hideColumnAt || defaultHideColumnWidth;
|
||||||
|
const isHidden: boolean = columns[key]?.isHidden || window.innerWidth <= hideColumnAt;
|
||||||
|
|
||||||
|
newHeaders[key] = {
|
||||||
|
...columns[key],
|
||||||
|
isHidden
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return newHeaders;
|
||||||
|
};
|
||||||
|
|
||||||
|
const [sortHeaderColumn, setSortHeaderColumn] = useState<string | null>(sortColumn || null);
|
||||||
|
const [headers, setHeaders] = useState<ColumnsType>(getHeadersBasedOnWidth(columns));
|
||||||
|
const [modifiedData, setModifiedData] = useState<DataRowType[]>(data);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (sortColumn && sortDirection) {
|
||||||
|
const newHeaders: ColumnsType = {...headers};
|
||||||
|
|
||||||
|
if (headers[sortColumn]?.textCell) {
|
||||||
|
newHeaders[sortColumn] = {
|
||||||
|
...newHeaders[sortColumn],
|
||||||
|
textCell: {
|
||||||
|
...newHeaders[sortColumn].textCell,
|
||||||
|
direction: sortDirection,
|
||||||
|
propName: newHeaders[sortColumn].textCell?.propName || sortColumn
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
setHeaders(newHeaders);
|
||||||
|
}
|
||||||
|
}, [sortColumn, sortDirection]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setModifiedData(data);
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setHeaders(columns);
|
||||||
|
}, [columns]);
|
||||||
|
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
const updateComponentBasedOnWidth = () => {
|
||||||
|
setHeaders(getHeadersBasedOnWidth(columns));
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener('resize', updateComponentBasedOnWidth);
|
||||||
|
|
||||||
|
return () => window.removeEventListener('resize', updateComponentBasedOnWidth);
|
||||||
|
});
|
||||||
|
|
||||||
|
const sortAction = (propName: string) => {
|
||||||
|
if (headers[propName]) {
|
||||||
|
const newHeaders = {...headers};
|
||||||
|
const currentDirection = newHeaders[propName].textCell.direction;
|
||||||
|
const newDirection = currentDirection === DirectionType.Asc ? DirectionType.Desc : DirectionType.Asc;
|
||||||
|
|
||||||
|
newHeaders[propName].textCell.direction = newDirection;
|
||||||
|
|
||||||
|
if (sort) {
|
||||||
|
sort({
|
||||||
|
sortColumn: propName,
|
||||||
|
sortDirection: newDirection
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const newData = modifiedData.sort((a, b) => compare(a, b, newDirection, propName));
|
||||||
|
|
||||||
|
setModifiedData(newData);
|
||||||
|
}
|
||||||
|
|
||||||
|
setHeaders(newHeaders);
|
||||||
|
setSortHeaderColumn(propName);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return !errorMessage ? (
|
||||||
|
<TableContainer className="testId-table">
|
||||||
|
<TableHeader columns={headers} sortHeaderColumn={sortHeaderColumn} sortAction={sortAction} />
|
||||||
|
<TableBody columns={headers} data={modifiedData} />
|
||||||
|
</TableContainer>
|
||||||
|
) : (
|
||||||
|
<Error>{errorMessage || 'Error'}</Error>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TableComponent;
|
||||||
30
src/components/tags/index.tsx
Normal file
30
src/components/tags/index.tsx
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
import {FC, MouseEvent} from 'react';
|
||||||
|
import {TagContainer} from './style';
|
||||||
|
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
|
||||||
|
import {faTimes} from '@fortawesome/free-solid-svg-icons';
|
||||||
|
|
||||||
|
export interface ITag {
|
||||||
|
label: string;
|
||||||
|
onClose?: (event: MouseEvent<HTMLSpanElement>) => void | null;
|
||||||
|
handleClick?: () => void;
|
||||||
|
disabled?: boolean;
|
||||||
|
className?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Tag: FC<ITag> = ({className, label, onClose = null, handleClick = () => null, disabled = false}: ITag) => {
|
||||||
|
const onKeyPress = (): void => null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TagContainer onClick={handleClick} disabled={disabled} className={className}>
|
||||||
|
<p>{label}</p>
|
||||||
|
{onClose && (
|
||||||
|
<span role="button" tabIndex={-1} onKeyPress={onKeyPress} onClick={onClose}>
|
||||||
|
<FontAwesomeIcon icon={faTimes} />
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</TagContainer>
|
||||||
|
);
|
||||||
|
};
|
||||||
37
src/components/tags/style.ts
Normal file
37
src/components/tags/style.ts
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/**
|
||||||
|
* 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, spacing, fontSizeXS} = theme;
|
||||||
|
|
||||||
|
export const TagContainer = styled.default.div<{size?: string; disabled?: boolean}>`
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
border-radius: 1rem;
|
||||||
|
font-weight: 500;
|
||||||
|
margin: ${spacing.xxSmall};
|
||||||
|
color: ${colors.white};
|
||||||
|
background-color: ${colors.gray700};
|
||||||
|
height: 24px;
|
||||||
|
padding: 0 ${paddings.small};
|
||||||
|
font-size: ${fontSizeXS};
|
||||||
|
${({disabled}) =>
|
||||||
|
disabled &&
|
||||||
|
styled.css`
|
||||||
|
opacity: 0.3;
|
||||||
|
pointer-events: none;
|
||||||
|
`}
|
||||||
|
p {
|
||||||
|
text-align: center;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
span{
|
||||||
|
margin-top: 2px;
|
||||||
|
margin-left: ${spacing.xSmall};
|
||||||
|
}
|
||||||
|
`;
|
||||||
43
src/components/tooltip/index.tsx
Normal file
43
src/components/tooltip/index.tsx
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
import React, {useState} from 'react';
|
||||||
|
|
||||||
|
import {TooltipContainer, TooltipBubble} from './style';
|
||||||
|
import {Position} from './types';
|
||||||
|
|
||||||
|
export {Position};
|
||||||
|
|
||||||
|
interface ITooltip {
|
||||||
|
message: string;
|
||||||
|
position: Position;
|
||||||
|
children: React.JSX.Element | React.JSX.Element[];
|
||||||
|
width?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Tooltip = (props: ITooltip): React.JSX.Element => {
|
||||||
|
const {message, position, children, width} = props;
|
||||||
|
const [displayTooltip, setDisplayTooltip] = useState(false);
|
||||||
|
const showTooltip = () => {
|
||||||
|
setDisplayTooltip(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const hideTooltip = () => {
|
||||||
|
setDisplayTooltip(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TooltipContainer onBlur={hideTooltip} onMouseOut={hideTooltip}>
|
||||||
|
{displayTooltip && (
|
||||||
|
<TooltipBubble className={`tooltip-${position}`} width={width}>
|
||||||
|
<div className="tooltip-message">{message}</div>
|
||||||
|
</TooltipBubble>
|
||||||
|
)}
|
||||||
|
<span onFocus={showTooltip} onMouseOver={showTooltip}>
|
||||||
|
{children}
|
||||||
|
</span>
|
||||||
|
</TooltipContainer>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
Tooltip.Position = Position;
|
||||||
89
src/components/tooltip/style.ts
Normal file
89
src/components/tooltip/style.ts
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
/**
|
||||||
|
* 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, spacing, typography} = Theme;
|
||||||
|
|
||||||
|
export const TooltipContainer = styled.default.span`
|
||||||
|
position: relative;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const TooltipBubble = styled.default.div<{width?: number}>`
|
||||||
|
min-width: 120px;
|
||||||
|
max-width: 600px;
|
||||||
|
width: ${({width}) => width}px;
|
||||||
|
word-wrap: break-word;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 999;
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
&.tooltip-top {
|
||||||
|
bottom: 100%;
|
||||||
|
left: 50%;
|
||||||
|
padding-bottom: ${spacing.small};
|
||||||
|
transform: translateX(-50%);
|
||||||
|
&::after {
|
||||||
|
border-left: 9px solid transparent;
|
||||||
|
border-right: 9px solid transparent;
|
||||||
|
border-top: 9px solid rgba(0,0,0, .7);
|
||||||
|
bottom: 0;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.tooltip-bottom {
|
||||||
|
top: 100%;
|
||||||
|
left: 50%;
|
||||||
|
padding-top: ${spacing.small};
|
||||||
|
transform: translateX(-50%);
|
||||||
|
&::after {
|
||||||
|
border-left: 9px solid transparent;
|
||||||
|
border-right: 9px solid transparent;
|
||||||
|
border-bottom: 9px solid rgba(0,0,0, .7);
|
||||||
|
top: 0;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.tooltip-left {
|
||||||
|
top: 50%;
|
||||||
|
right: 100%;
|
||||||
|
padding-right: ${spacing.small};
|
||||||
|
transform: translateY(-50%);
|
||||||
|
&::after {
|
||||||
|
border-left: 9px solid rgba(0,0,0, .7);
|
||||||
|
border-top: 9px solid transparent;
|
||||||
|
border-bottom: 9px solid transparent;
|
||||||
|
top: 50%;
|
||||||
|
right: 0;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.tooltip-right {
|
||||||
|
top: 50%;
|
||||||
|
left: 100%;
|
||||||
|
padding-left: ${spacing.small};
|
||||||
|
transform: translateY(-50%);
|
||||||
|
&::after {
|
||||||
|
border-right: 9px solid rgba(0,0,0, .7);
|
||||||
|
border-top: 9px solid transparent;
|
||||||
|
border-bottom: 9px solid transparent;
|
||||||
|
top: 50%;
|
||||||
|
left: 0;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.tooltip-message {
|
||||||
|
background: rgba(0,0,0, .7);
|
||||||
|
border-radius: 3px;
|
||||||
|
color: ${colors.white};
|
||||||
|
font-size: ${typography.fontSizeS};
|
||||||
|
line-height: 1.4;
|
||||||
|
padding: ${spacing.small};
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
`;
|
||||||
10
src/components/tooltip/types.ts
Normal file
10
src/components/tooltip/types.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export enum Position {
|
||||||
|
Top = 'top',
|
||||||
|
Bottom = 'bottom',
|
||||||
|
Left = 'left',
|
||||||
|
Right = 'right'
|
||||||
|
}
|
||||||
@@ -2,8 +2,7 @@
|
|||||||
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||||
*/
|
*/
|
||||||
import * as styled from 'styled-components';
|
import * as styled from 'styled-components';
|
||||||
import Theme from 'theme';
|
import Theme from 'theme';
|
||||||
|
|
||||||
|
|
||||||
export const H1 = styled.default.h1`
|
export const H1 = styled.default.h1`
|
||||||
font-family: ${Theme.typography.primaryFont};
|
font-family: ${Theme.typography.primaryFont};
|
||||||
|
|||||||
202
src/components/ui/advanced-select/advanced-select.tsx
Normal file
202
src/components/ui/advanced-select/advanced-select.tsx
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
import React, {useState, useEffect, useRef, KeyboardEvent, ChangeEvent, ReactElement} from 'react';
|
||||||
|
|
||||||
|
import {Tag, ITag} from 'components/tags';
|
||||||
|
import {isEqual} from 'components/shared/utils';
|
||||||
|
import {Label} from 'components/forms/label';
|
||||||
|
|
||||||
|
import {AdvancedSelectContainer, ComponentWrapper, InputContainer, SelectInput, TagOptions} from './style';
|
||||||
|
|
||||||
|
export interface IAdvancedSelectItem {
|
||||||
|
value: string;
|
||||||
|
type: string[];
|
||||||
|
dependency?: string[];
|
||||||
|
set?: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IKeyboardEventWithTarget extends KeyboardEvent<HTMLInputElement> {
|
||||||
|
target: HTMLInputElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
const advancedSelectHeight = 250;
|
||||||
|
|
||||||
|
interface IAdvancedSelect {
|
||||||
|
selectedItems: IAdvancedSelectItem[];
|
||||||
|
setSelectedItems: (items: IAdvancedSelectItem[]) => void;
|
||||||
|
data: IAdvancedSelectItem[];
|
||||||
|
label?: string;
|
||||||
|
labelColor?: string;
|
||||||
|
labelIcon?: React.JSX.Element;
|
||||||
|
labelClassName?: string;
|
||||||
|
labelHtmlFor?: string;
|
||||||
|
width?: number | string;
|
||||||
|
className?: string;
|
||||||
|
allowMultiple?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const AdvancedSelect = ({
|
||||||
|
allowMultiple = true,
|
||||||
|
selectedItems,
|
||||||
|
setSelectedItems,
|
||||||
|
data,
|
||||||
|
label,
|
||||||
|
labelColor,
|
||||||
|
labelIcon,
|
||||||
|
labelClassName,
|
||||||
|
labelHtmlFor,
|
||||||
|
width,
|
||||||
|
className
|
||||||
|
}: IAdvancedSelect): React.JSX.Element => {
|
||||||
|
const [inputValue, setInputValue] = useState<string>('');
|
||||||
|
const [selectedSets, setSelectedSets] = useState<string[]>([]);
|
||||||
|
const firstUpdate = useRef(true);
|
||||||
|
const ref = useRef(null);
|
||||||
|
const scrollToBottom = (): void => {
|
||||||
|
ref.current.scrollTop = ref.current.scrollHeight;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getSelectedItemsSets = () => {
|
||||||
|
const selectedSets = [];
|
||||||
|
|
||||||
|
selectedItems.forEach((item: IAdvancedSelectItem) => {
|
||||||
|
if (item.set) {
|
||||||
|
item.set.forEach(set => {
|
||||||
|
selectedSets.push(set);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
setSelectedSets(selectedSets);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getSelectedItemsSets();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (firstUpdate.current) {
|
||||||
|
firstUpdate.current = false;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const timeout = setTimeout(() => scrollToBottom(), 0);
|
||||||
|
|
||||||
|
getSelectedItemsSets();
|
||||||
|
|
||||||
|
return () => clearTimeout(timeout);
|
||||||
|
}, [selectedItems]);
|
||||||
|
|
||||||
|
const getTagsContainerHeight = () => {
|
||||||
|
return advancedSelectHeight - 32 - ref?.current?.clientHeight;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getItemDependencies = (item: IAdvancedSelectItem): IAdvancedSelectItem[] => {
|
||||||
|
const allDependencies = [];
|
||||||
|
const getNestedDependencies = (dependencyItem: IAdvancedSelectItem): void => {
|
||||||
|
const itemAlreadySelected = selectedItems.some(selectedItem => selectedItem.value === dependencyItem.value);
|
||||||
|
const selectedItemsSet = new Set(selectedItems.map(item => item.value));
|
||||||
|
const dependenciesSet = new Set(allDependencies.map(item => item.value));
|
||||||
|
const oneOfTheDependenciesAlreadySelected = item.dependency?.some(dependency => selectedItemsSet.has(dependency) || dependenciesSet.has(dependency));
|
||||||
|
const itemIsANestedDependency = item.dependency?.includes(dependencyItem.value);
|
||||||
|
|
||||||
|
if ((itemIsANestedDependency && oneOfTheDependenciesAlreadySelected) || itemAlreadySelected) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
allDependencies.push(dependencyItem);
|
||||||
|
|
||||||
|
if (!dependencyItem.dependency) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencyItem.dependency.forEach((dependencyName: string) => {
|
||||||
|
const originalDependencyItem = data.find((element: IAdvancedSelectItem) => isEqual(dependencyName, element.value));
|
||||||
|
|
||||||
|
getNestedDependencies(originalDependencyItem);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
getNestedDependencies(item);
|
||||||
|
|
||||||
|
return allDependencies;
|
||||||
|
};
|
||||||
|
|
||||||
|
const selectItem = (item: IAdvancedSelectItem): void => {
|
||||||
|
const itemsToSelect = getItemDependencies(item);
|
||||||
|
|
||||||
|
setSelectedItems([...selectedItems, ...itemsToSelect]);
|
||||||
|
setInputValue('');
|
||||||
|
};
|
||||||
|
|
||||||
|
const filterTags = (datum: IAdvancedSelectItem) => {
|
||||||
|
return datum.value.toLowerCase().includes(inputValue.toLowerCase());
|
||||||
|
};
|
||||||
|
|
||||||
|
const generateAllItems = (): ReactElement<ITag>[] => {
|
||||||
|
const itemsToSelectFrom = data.filter((datum: IAdvancedSelectItem) => !selectedItems.includes(datum)).filter(filterTags);
|
||||||
|
|
||||||
|
return itemsToSelectFrom.map((datum: IAdvancedSelectItem) => (
|
||||||
|
<Tag
|
||||||
|
disabled={(!allowMultiple && !!selectedItems.length) || (datum.set && selectedSets.some(set => datum.set.includes(set)))}
|
||||||
|
key={datum.value}
|
||||||
|
label={datum.value}
|
||||||
|
handleClick={() => selectItem(datum)}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
const deselectItem = (item: IAdvancedSelectItem): void => {
|
||||||
|
const filteredItems = selectedItems.filter((datum: IAdvancedSelectItem) => {
|
||||||
|
if (datum.dependency) {
|
||||||
|
return !isEqual(datum, item) && !datum.dependency.includes(item.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return !isEqual(datum, item);
|
||||||
|
});
|
||||||
|
|
||||||
|
setSelectedItems(filteredItems);
|
||||||
|
};
|
||||||
|
|
||||||
|
const generateSelectedItems = (): ReactElement<ITag>[] => {
|
||||||
|
return selectedItems.map((item: IAdvancedSelectItem) => (
|
||||||
|
<Tag key={item.value} label={item.value} onClose={() => deselectItem(item)} className="testId-selectedItem" />
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleInput = (event: ChangeEvent<HTMLInputElement>): void => {
|
||||||
|
setInputValue(event.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onKeyDown = (event: IKeyboardEventWithTarget): void => {
|
||||||
|
if (event.key === 'Enter') {
|
||||||
|
const {value} = event.target;
|
||||||
|
|
||||||
|
selectItem({
|
||||||
|
value,
|
||||||
|
type: []
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ComponentWrapper width={width}>
|
||||||
|
{!!label && <Label text={label} color={labelColor} icon={labelIcon} className={labelClassName} htmlFor={labelHtmlFor} />}
|
||||||
|
<AdvancedSelectContainer className={className}>
|
||||||
|
<InputContainer ref={ref}>
|
||||||
|
{generateSelectedItems()}
|
||||||
|
<SelectInput
|
||||||
|
disabled={!allowMultiple && !!selectedItems.length}
|
||||||
|
className="testId-advancedSelectInput"
|
||||||
|
onChange={handleInput}
|
||||||
|
onKeyDown={onKeyDown}
|
||||||
|
value={inputValue}
|
||||||
|
/>
|
||||||
|
</InputContainer>
|
||||||
|
<TagOptions height={getTagsContainerHeight() || 0}>{generateAllItems()}</TagOptions>
|
||||||
|
</AdvancedSelectContainer>
|
||||||
|
</ComponentWrapper>
|
||||||
|
);
|
||||||
|
};
|
||||||
4
src/components/ui/advanced-select/index.ts
Normal file
4
src/components/ui/advanced-select/index.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
export * from './advanced-select';
|
||||||
62
src/components/ui/advanced-select/style.ts
Normal file
62
src/components/ui/advanced-select/style.ts
Normal 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, paddings} from 'components/shared/theme';
|
||||||
|
import {IInput} from '../input';
|
||||||
|
|
||||||
|
const {colors, primaryBorderRadius, spacing, formFieldWidth, formFieldMaxWidth} = theme;
|
||||||
|
|
||||||
|
export const ComponentWrapper = 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 AdvancedSelectContainer = styled.default.div`
|
||||||
|
color: ${colors.white};
|
||||||
|
width: ${theme.formFieldWidth}px;
|
||||||
|
height: ${theme.formFieldMaxHeight}px;
|
||||||
|
background-color: ${colors.gray500};
|
||||||
|
border-radius: ${primaryBorderRadius};
|
||||||
|
padding: ${paddings.small};
|
||||||
|
margin-top: 0;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const SelectInput = styled.default.input`
|
||||||
|
background-color: ${colors.transparent};
|
||||||
|
border: none;
|
||||||
|
line-height: 24px;
|
||||||
|
width: 100%;
|
||||||
|
color: ${colors.black};
|
||||||
|
padding: 0 ${paddings.xsmall};
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const InputContainer = styled.default.div`
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
border: none;
|
||||||
|
border-radius: ${primaryBorderRadius};
|
||||||
|
background-color: ${colors.white};
|
||||||
|
padding: ${paddings.xsmall};
|
||||||
|
min-height: 40px;
|
||||||
|
overflow-y: auto;
|
||||||
|
|
||||||
|
input {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const TagOptions = styled.default.div<{height: number}>`
|
||||||
|
height: 200px;
|
||||||
|
flex: 1;
|
||||||
|
overflow-y: auto;
|
||||||
|
margin-top: ${spacing.xSmall};
|
||||||
|
padding: ${paddings.xsmall};
|
||||||
|
${({height}) =>
|
||||||
|
height &&
|
||||||
|
styled.css`
|
||||||
|
height: ${height}px;
|
||||||
|
`}
|
||||||
|
`;
|
||||||
54
src/components/ui/date-picker/date-picker.tsx
Normal file
54
src/components/ui/date-picker/date-picker.tsx
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
import React from 'react';
|
||||||
|
import {ReactDatePickerProps} from 'react-datepicker';
|
||||||
|
|
||||||
|
import {Label} from 'components/label';
|
||||||
|
|
||||||
|
import {DatePickerContainer, DatePickerElement, HelperText} from './style';
|
||||||
|
|
||||||
|
interface IDatePicker extends Omit<ReactDatePickerProps, 'onChange'> {
|
||||||
|
label?: string;
|
||||||
|
labelColor?: string;
|
||||||
|
labelIcon?: React.JSX.Element;
|
||||||
|
labelHtmlFor?: string;
|
||||||
|
labelClassName?: string;
|
||||||
|
name: string;
|
||||||
|
onDateChange: (name: string, date: Date) => void;
|
||||||
|
error?: boolean;
|
||||||
|
helperText?: string;
|
||||||
|
helperTextClassName?: string;
|
||||||
|
width?: number | string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const DatePicker = ({
|
||||||
|
label,
|
||||||
|
labelColor,
|
||||||
|
labelIcon,
|
||||||
|
labelHtmlFor,
|
||||||
|
labelClassName,
|
||||||
|
name,
|
||||||
|
onDateChange,
|
||||||
|
error,
|
||||||
|
helperText,
|
||||||
|
helperTextClassName,
|
||||||
|
width,
|
||||||
|
...rest
|
||||||
|
}: IDatePicker): React.JSX.Element => {
|
||||||
|
const handleOnChange = (date: Date) => onDateChange(name, date);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DatePickerContainer width={width}>
|
||||||
|
{!!label && <Label text={label} color={labelColor} icon={labelIcon} htmlFor={labelHtmlFor} className={labelClassName} />}
|
||||||
|
<DatePickerElement name={name} onChange={handleOnChange} {...rest} />
|
||||||
|
{!!helperText && (
|
||||||
|
<HelperText className={helperTextClassName} error={error}>
|
||||||
|
{helperText}
|
||||||
|
</HelperText>
|
||||||
|
)}
|
||||||
|
</DatePickerContainer>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DatePicker;
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user