diff --git a/.eslintrc.js b/.eslintrc.js
new file mode 100644
index 0000000..0d4c003
--- /dev/null
+++ b/.eslintrc.js
@@ -0,0 +1,16 @@
+module.exports = {
+ env: { browser: true, es2020: true },
+ extends: [
+ 'eslint:recommended',
+ 'plugin:@typescript-eslint/recommended',
+ 'plugin:react-hooks/recommended',
+ ],
+ parser: '@typescript-eslint/parser',
+ parserOptions: { ecmaVersion: 'latest', sourceType: 'module' },
+ plugins: ['react-refresh'],
+ rules: {
+ 'react-refresh/only-export-components': 'warn',
+ '@typescript-eslint/no-explicit-any': "off"
+
+ },
+}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..e3118db
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,25 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
+*.zip
\ No newline at end of file
diff --git a/.prettierrc b/.prettierrc
new file mode 100644
index 0000000..0a4d4fc
--- /dev/null
+++ b/.prettierrc
@@ -0,0 +1,10 @@
+{
+ "printWidth": 80,
+ "singleQuote": false,
+ "trailingComma": "es5",
+ "bracketSpacing": true,
+ "jsxBracketSameLine": false,
+ "arrowParens": "avoid",
+ "tabWidth": 2,
+ "semi": true
+}
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..58f8c68
--- /dev/null
+++ b/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+ Q-Share
+
+
+
+
+
+
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..44991b7
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,7530 @@
+{
+ "name": "qsupport",
+ "version": "1.0.0",
+ "lockfileVersion": 2,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "qsupport",
+ "version": "1.0.0",
+ "dependencies": {
+ "@emotion/react": "^11.10.6",
+ "@emotion/styled": "^11.10.6",
+ "@mui/icons-material": "^5.11.11",
+ "@mui/material": "^5.11.13",
+ "@reduxjs/toolkit": "^1.9.3",
+ "compressorjs": "^1.2.1",
+ "dompurify": "^3.0.6",
+ "localforage": "^1.10.0",
+ "moment": "^2.29.4",
+ "prettier": "^3.2.4",
+ "quill-image-resize-module-react": "^3.0.0",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
+ "react-dropzone": "^14.2.3",
+ "react-intersection-observer": "^9.4.3",
+ "react-quill": "^2.0.0",
+ "react-redux": "^8.0.5",
+ "react-rnd": "^10.4.1",
+ "react-router-dom": "^6.9.0",
+ "react-toastify": "^9.1.2",
+ "short-unique-id": "^4.4.4",
+ "ts-key-enum": "^2.0.12"
+ },
+ "devDependencies": {
+ "@types/react": "^18.0.28",
+ "@types/react-dom": "^18.0.11",
+ "@typescript-eslint/eslint-plugin": "^5.57.1",
+ "@typescript-eslint/parser": "^5.57.1",
+ "@vitejs/plugin-react": "^4.0.0",
+ "eslint": "^8.38.0",
+ "eslint-plugin-react-hooks": "^4.6.0",
+ "eslint-plugin-react-refresh": "^0.3.4",
+ "typescript": "^5.0.2",
+ "vite": "6.0.0-alpha.1"
+ }
+ },
+ "node_modules/@ampproject/remapping": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz",
+ "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.0",
+ "@jridgewell/trace-mapping": "^0.3.9"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz",
+ "integrity": "sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==",
+ "dependencies": {
+ "@babel/highlight": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/compat-data": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.5.tgz",
+ "integrity": "sha512-4Jc/YuIaYqKnDDz892kPIledykKg12Aw1PYX5i/TY28anJtacvM1Rrr8wbieB9GfEJwlzqT0hUEao0CxEebiDA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/core": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.5.tgz",
+ "integrity": "sha512-SBuTAjg91A3eKOvD+bPEz3LlhHZRNu1nFOVts9lzDJTXshHTjII0BAtDS3Y2DAkdZdDKWVZGVwkDfc4Clxn1dg==",
+ "dev": true,
+ "dependencies": {
+ "@ampproject/remapping": "^2.2.0",
+ "@babel/code-frame": "^7.22.5",
+ "@babel/generator": "^7.22.5",
+ "@babel/helper-compilation-targets": "^7.22.5",
+ "@babel/helper-module-transforms": "^7.22.5",
+ "@babel/helpers": "^7.22.5",
+ "@babel/parser": "^7.22.5",
+ "@babel/template": "^7.22.5",
+ "@babel/traverse": "^7.22.5",
+ "@babel/types": "^7.22.5",
+ "convert-source-map": "^1.7.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.2",
+ "semver": "^6.3.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
+ }
+ },
+ "node_modules/@babel/core/node_modules/semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@babel/generator": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.5.tgz",
+ "integrity": "sha512-+lcUbnTRhd0jOewtFSedLyiPsD5tswKkbgcezOqqWFUVNEwoUTlpPOBmvhG7OXWLR4jMdv0czPGH5XbflnD1EA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.22.5",
+ "@jridgewell/gen-mapping": "^0.3.2",
+ "@jridgewell/trace-mapping": "^0.3.17",
+ "jsesc": "^2.5.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.5.tgz",
+ "integrity": "sha512-Ji+ywpHeuqxB8WDxraCiqR0xfhYjiDE/e6k7FuIaANnoOFxAHskHChz4vA1mJC9Lbm01s1PVAGhQY4FUKSkGZw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/compat-data": "^7.22.5",
+ "@babel/helper-validator-option": "^7.22.5",
+ "browserslist": "^4.21.3",
+ "lru-cache": "^5.1.1",
+ "semver": "^6.3.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets/node_modules/semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@babel/helper-environment-visitor": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz",
+ "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-function-name": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz",
+ "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/template": "^7.22.5",
+ "@babel/types": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-hoist-variables": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz",
+ "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-imports": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz",
+ "integrity": "sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==",
+ "dependencies": {
+ "@babel/types": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-transforms": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.5.tgz",
+ "integrity": "sha512-+hGKDt/Ze8GFExiVHno/2dvG5IdstpzCq0y4Qc9OJ25D4q3pKfiIP/4Vp3/JvhDkLKsDK2api3q3fpIgiIF5bw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-environment-visitor": "^7.22.5",
+ "@babel/helper-module-imports": "^7.22.5",
+ "@babel/helper-simple-access": "^7.22.5",
+ "@babel/helper-split-export-declaration": "^7.22.5",
+ "@babel/helper-validator-identifier": "^7.22.5",
+ "@babel/template": "^7.22.5",
+ "@babel/traverse": "^7.22.5",
+ "@babel/types": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-simple-access": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz",
+ "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-split-export-declaration": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.5.tgz",
+ "integrity": "sha512-thqK5QFghPKWLhAV321lxF95yCg2K3Ob5yw+M3VHWfdia0IkPXUtoLH8x/6Fh486QUvzhb8YOWHChTVen2/PoQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz",
+ "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz",
+ "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-option": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz",
+ "integrity": "sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helpers": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.5.tgz",
+ "integrity": "sha512-pSXRmfE1vzcUIDFQcSGA5Mr+GxBV9oiRKDuDxXvWQQBCh8HoIjs/2DlDB7H8smac1IVrB9/xdXj2N3Wol9Cr+Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/template": "^7.22.5",
+ "@babel/traverse": "^7.22.5",
+ "@babel/types": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/highlight": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.5.tgz",
+ "integrity": "sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==",
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.22.5",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.5.tgz",
+ "integrity": "sha512-DFZMC9LJUG9PLOclRC32G63UXwzqS2koQC8dkx+PLdmt1xSePYpbT/NbsrJy8Q/muXz7o/h/d4A7Fuyixm559Q==",
+ "dev": true,
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-jsx-self": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.22.5.tgz",
+ "integrity": "sha512-nTh2ogNUtxbiSbxaT4Ds6aXnXEipHweN9YRgOX/oNXdf0cCrGn/+2LozFa3lnPV5D90MkjhgckCPBrsoSc1a7g==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-jsx-source": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.22.5.tgz",
+ "integrity": "sha512-yIiRO6yobeEIaI0RTbIr8iAK9FcBHLtZq0S89ZPjDLQXBA4xvghaKqI0etp/tF3htTM0sazJKKLz9oEiGRtu7w==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/runtime": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.5.tgz",
+ "integrity": "sha512-ecjvYlnAaZ/KVneE/OdKYBYfgXV3Ptu6zQWmgEF7vwKhQnvVS6bjMD2XYgj+SNvQ1GfK/pjgokfPkC/2CO8CuA==",
+ "dependencies": {
+ "regenerator-runtime": "^0.13.11"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/template": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz",
+ "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.22.5",
+ "@babel/parser": "^7.22.5",
+ "@babel/types": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.5.tgz",
+ "integrity": "sha512-7DuIjPgERaNo6r+PZwItpjCZEa5vyw4eJGufeLxrPdBXBoLcCJCIasvK6pK/9DVNrLZTLFhUGqaC6X/PA007TQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.22.5",
+ "@babel/generator": "^7.22.5",
+ "@babel/helper-environment-visitor": "^7.22.5",
+ "@babel/helper-function-name": "^7.22.5",
+ "@babel/helper-hoist-variables": "^7.22.5",
+ "@babel/helper-split-export-declaration": "^7.22.5",
+ "@babel/parser": "^7.22.5",
+ "@babel/types": "^7.22.5",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz",
+ "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==",
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.22.5",
+ "@babel/helper-validator-identifier": "^7.22.5",
+ "to-fast-properties": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@emotion/babel-plugin": {
+ "version": "11.11.0",
+ "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz",
+ "integrity": "sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==",
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.16.7",
+ "@babel/runtime": "^7.18.3",
+ "@emotion/hash": "^0.9.1",
+ "@emotion/memoize": "^0.8.1",
+ "@emotion/serialize": "^1.1.2",
+ "babel-plugin-macros": "^3.1.0",
+ "convert-source-map": "^1.5.0",
+ "escape-string-regexp": "^4.0.0",
+ "find-root": "^1.1.0",
+ "source-map": "^0.5.7",
+ "stylis": "4.2.0"
+ }
+ },
+ "node_modules/@emotion/cache": {
+ "version": "11.11.0",
+ "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.11.0.tgz",
+ "integrity": "sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==",
+ "dependencies": {
+ "@emotion/memoize": "^0.8.1",
+ "@emotion/sheet": "^1.2.2",
+ "@emotion/utils": "^1.2.1",
+ "@emotion/weak-memoize": "^0.3.1",
+ "stylis": "4.2.0"
+ }
+ },
+ "node_modules/@emotion/hash": {
+ "version": "0.9.1",
+ "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz",
+ "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ=="
+ },
+ "node_modules/@emotion/is-prop-valid": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz",
+ "integrity": "sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw==",
+ "dependencies": {
+ "@emotion/memoize": "^0.8.1"
+ }
+ },
+ "node_modules/@emotion/memoize": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz",
+ "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA=="
+ },
+ "node_modules/@emotion/react": {
+ "version": "11.11.1",
+ "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.1.tgz",
+ "integrity": "sha512-5mlW1DquU5HaxjLkfkGN1GA/fvVGdyHURRiX/0FHl2cfIfRxSOfmxEH5YS43edp0OldZrZ+dkBKbngxcNCdZvA==",
+ "dependencies": {
+ "@babel/runtime": "^7.18.3",
+ "@emotion/babel-plugin": "^11.11.0",
+ "@emotion/cache": "^11.11.0",
+ "@emotion/serialize": "^1.1.2",
+ "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1",
+ "@emotion/utils": "^1.2.1",
+ "@emotion/weak-memoize": "^0.3.1",
+ "hoist-non-react-statics": "^3.3.1"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@emotion/serialize": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.2.tgz",
+ "integrity": "sha512-zR6a/fkFP4EAcCMQtLOhIgpprZOwNmCldtpaISpvz348+DP4Mz8ZoKaGGCQpbzepNIUWbq4w6hNZkwDyKoS+HA==",
+ "dependencies": {
+ "@emotion/hash": "^0.9.1",
+ "@emotion/memoize": "^0.8.1",
+ "@emotion/unitless": "^0.8.1",
+ "@emotion/utils": "^1.2.1",
+ "csstype": "^3.0.2"
+ }
+ },
+ "node_modules/@emotion/sheet": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.2.tgz",
+ "integrity": "sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA=="
+ },
+ "node_modules/@emotion/styled": {
+ "version": "11.11.0",
+ "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.11.0.tgz",
+ "integrity": "sha512-hM5Nnvu9P3midq5aaXj4I+lnSfNi7Pmd4EWk1fOZ3pxookaQTNew6bp4JaCBYM4HVFZF9g7UjJmsUmC2JlxOng==",
+ "dependencies": {
+ "@babel/runtime": "^7.18.3",
+ "@emotion/babel-plugin": "^11.11.0",
+ "@emotion/is-prop-valid": "^1.2.1",
+ "@emotion/serialize": "^1.1.2",
+ "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1",
+ "@emotion/utils": "^1.2.1"
+ },
+ "peerDependencies": {
+ "@emotion/react": "^11.0.0-rc.0",
+ "react": ">=16.8.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@emotion/unitless": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz",
+ "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ=="
+ },
+ "node_modules/@emotion/use-insertion-effect-with-fallbacks": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz",
+ "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==",
+ "peerDependencies": {
+ "react": ">=16.8.0"
+ }
+ },
+ "node_modules/@emotion/utils": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.1.tgz",
+ "integrity": "sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg=="
+ },
+ "node_modules/@emotion/weak-memoize": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz",
+ "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww=="
+ },
+ "node_modules/@esbuild/aix-ppc64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz",
+ "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz",
+ "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz",
+ "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz",
+ "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz",
+ "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz",
+ "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz",
+ "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz",
+ "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz",
+ "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz",
+ "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz",
+ "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz",
+ "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz",
+ "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz",
+ "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz",
+ "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz",
+ "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz",
+ "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz",
+ "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz",
+ "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz",
+ "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz",
+ "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz",
+ "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz",
+ "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@eslint-community/eslint-utils": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
+ "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==",
+ "dev": true,
+ "dependencies": {
+ "eslint-visitor-keys": "^3.3.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
+ }
+ },
+ "node_modules/@eslint-community/regexpp": {
+ "version": "4.5.1",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz",
+ "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==",
+ "dev": true,
+ "engines": {
+ "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@eslint/eslintrc": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz",
+ "integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==",
+ "dev": true,
+ "dependencies": {
+ "ajv": "^6.12.4",
+ "debug": "^4.3.2",
+ "espree": "^9.5.2",
+ "globals": "^13.19.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"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint/eslintrc/node_modules/globals": {
+ "version": "13.20.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz",
+ "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==",
+ "dev": true,
+ "dependencies": {
+ "type-fest": "^0.20.2"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@eslint/js": {
+ "version": "8.43.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.43.0.tgz",
+ "integrity": "sha512-s2UHCoiXfxMvmfzqoN+vrQ84ahUSYde9qNO1MdxmoEhyHWsfmwOpFlwYV+ePJEVc7gFnATGUi376WowX1N7tFg==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@humanwhocodes/config-array": {
+ "version": "0.11.10",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz",
+ "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==",
+ "dev": true,
+ "dependencies": {
+ "@humanwhocodes/object-schema": "^1.2.1",
+ "debug": "^4.1.1",
+ "minimatch": "^3.0.5"
+ },
+ "engines": {
+ "node": ">=10.10.0"
+ }
+ },
+ "node_modules/@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12.22"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/object-schema": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz",
+ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
+ "dev": true
+ },
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz",
+ "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/set-array": "^1.0.1",
+ "@jridgewell/sourcemap-codec": "^1.4.10",
+ "@jridgewell/trace-mapping": "^0.3.9"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
+ "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/set-array": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
+ "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.4.15",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
+ "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
+ "dev": true
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.18",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz",
+ "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/resolve-uri": "3.1.0",
+ "@jridgewell/sourcemap-codec": "1.4.14"
+ }
+ },
+ "node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.4.14",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
+ "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
+ "dev": true
+ },
+ "node_modules/@mui/base": {
+ "version": "5.0.0-beta.4",
+ "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.4.tgz",
+ "integrity": "sha512-ejhtqYJpjDgHGEljjMBQWZ22yEK0OzIXNa7toJmmXsP4TT3W7xVy8bTJ0TniPDf+JNjrsgfgiFTDGdlEhV1E+g==",
+ "dependencies": {
+ "@babel/runtime": "^7.21.0",
+ "@emotion/is-prop-valid": "^1.2.1",
+ "@mui/types": "^7.2.4",
+ "@mui/utils": "^5.13.1",
+ "@popperjs/core": "^2.11.8",
+ "clsx": "^1.2.1",
+ "prop-types": "^15.8.1",
+ "react-is": "^18.2.0"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/mui"
+ },
+ "peerDependencies": {
+ "@types/react": "^17.0.0 || ^18.0.0",
+ "react": "^17.0.0 || ^18.0.0",
+ "react-dom": "^17.0.0 || ^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@mui/core-downloads-tracker": {
+ "version": "5.13.4",
+ "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.13.4.tgz",
+ "integrity": "sha512-yFrMWcrlI0TqRN5jpb6Ma9iI7sGTHpytdzzL33oskFHNQ8UgrtPas33Y1K7sWAMwCrr1qbWDrOHLAQG4tAzuSw==",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/mui"
+ }
+ },
+ "node_modules/@mui/icons-material": {
+ "version": "5.11.16",
+ "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.11.16.tgz",
+ "integrity": "sha512-oKkx9z9Kwg40NtcIajF9uOXhxiyTZrrm9nmIJ4UjkU2IdHpd4QVLbCc/5hZN/y0C6qzi2Zlxyr9TGddQx2vx2A==",
+ "dependencies": {
+ "@babel/runtime": "^7.21.0"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/mui"
+ },
+ "peerDependencies": {
+ "@mui/material": "^5.0.0",
+ "@types/react": "^17.0.0 || ^18.0.0",
+ "react": "^17.0.0 || ^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@mui/material": {
+ "version": "5.13.5",
+ "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.13.5.tgz",
+ "integrity": "sha512-eMay+Ue1OYXOFMQA5Aau7qbAa/kWHLAyi0McsbPTWssCbGehqkF6CIdPsfVGw6tlO+xPee1hUitphHJNL3xpOQ==",
+ "dependencies": {
+ "@babel/runtime": "^7.21.0",
+ "@mui/base": "5.0.0-beta.4",
+ "@mui/core-downloads-tracker": "^5.13.4",
+ "@mui/system": "^5.13.5",
+ "@mui/types": "^7.2.4",
+ "@mui/utils": "^5.13.1",
+ "@types/react-transition-group": "^4.4.6",
+ "clsx": "^1.2.1",
+ "csstype": "^3.1.2",
+ "prop-types": "^15.8.1",
+ "react-is": "^18.2.0",
+ "react-transition-group": "^4.4.5"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/mui"
+ },
+ "peerDependencies": {
+ "@emotion/react": "^11.5.0",
+ "@emotion/styled": "^11.3.0",
+ "@types/react": "^17.0.0 || ^18.0.0",
+ "react": "^17.0.0 || ^18.0.0",
+ "react-dom": "^17.0.0 || ^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@emotion/react": {
+ "optional": true
+ },
+ "@emotion/styled": {
+ "optional": true
+ },
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@mui/private-theming": {
+ "version": "5.13.1",
+ "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.13.1.tgz",
+ "integrity": "sha512-HW4npLUD9BAkVppOUZHeO1FOKUJWAwbpy0VQoGe3McUYTlck1HezGHQCfBQ5S/Nszi7EViqiimECVl9xi+/WjQ==",
+ "dependencies": {
+ "@babel/runtime": "^7.21.0",
+ "@mui/utils": "^5.13.1",
+ "prop-types": "^15.8.1"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/mui"
+ },
+ "peerDependencies": {
+ "@types/react": "^17.0.0 || ^18.0.0",
+ "react": "^17.0.0 || ^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@mui/styled-engine": {
+ "version": "5.13.2",
+ "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.13.2.tgz",
+ "integrity": "sha512-VCYCU6xVtXOrIN8lcbuPmoG+u7FYuOERG++fpY74hPpEWkyFQG97F+/XfTQVYzlR2m7nPjnwVUgATcTCMEaMvw==",
+ "dependencies": {
+ "@babel/runtime": "^7.21.0",
+ "@emotion/cache": "^11.11.0",
+ "csstype": "^3.1.2",
+ "prop-types": "^15.8.1"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/mui"
+ },
+ "peerDependencies": {
+ "@emotion/react": "^11.4.1",
+ "@emotion/styled": "^11.3.0",
+ "react": "^17.0.0 || ^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@emotion/react": {
+ "optional": true
+ },
+ "@emotion/styled": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@mui/system": {
+ "version": "5.13.5",
+ "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.13.5.tgz",
+ "integrity": "sha512-n0gzUxoZ2ZHZgnExkh2Htvo9uW2oakofgPRQrDoa/GQOWyRD0NH9MDszBwOb6AAoXZb+OV5TE7I4LeZ/dzgHYA==",
+ "dependencies": {
+ "@babel/runtime": "^7.21.0",
+ "@mui/private-theming": "^5.13.1",
+ "@mui/styled-engine": "^5.13.2",
+ "@mui/types": "^7.2.4",
+ "@mui/utils": "^5.13.1",
+ "clsx": "^1.2.1",
+ "csstype": "^3.1.2",
+ "prop-types": "^15.8.1"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/mui"
+ },
+ "peerDependencies": {
+ "@emotion/react": "^11.5.0",
+ "@emotion/styled": "^11.3.0",
+ "@types/react": "^17.0.0 || ^18.0.0",
+ "react": "^17.0.0 || ^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@emotion/react": {
+ "optional": true
+ },
+ "@emotion/styled": {
+ "optional": true
+ },
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@mui/types": {
+ "version": "7.2.4",
+ "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.4.tgz",
+ "integrity": "sha512-LBcwa8rN84bKF+f5sDyku42w1NTxaPgPyYKODsh01U1fVstTClbUoSA96oyRBnSNyEiAVjKm6Gwx9vjR+xyqHA==",
+ "peerDependencies": {
+ "@types/react": "*"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@mui/utils": {
+ "version": "5.13.1",
+ "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.13.1.tgz",
+ "integrity": "sha512-6lXdWwmlUbEU2jUI8blw38Kt+3ly7xkmV9ljzY4Q20WhsJMWiNry9CX8M+TaP/HbtuyR8XKsdMgQW7h7MM3n3A==",
+ "dependencies": {
+ "@babel/runtime": "^7.21.0",
+ "@types/prop-types": "^15.7.5",
+ "@types/react-is": "^18.2.0",
+ "prop-types": "^15.8.1",
+ "react-is": "^18.2.0"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/mui"
+ },
+ "peerDependencies": {
+ "react": "^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@popperjs/core": {
+ "version": "2.11.8",
+ "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
+ "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/popperjs"
+ }
+ },
+ "node_modules/@reduxjs/toolkit": {
+ "version": "1.9.5",
+ "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.5.tgz",
+ "integrity": "sha512-Rt97jHmfTeaxL4swLRNPD/zV4OxTes4la07Xc4hetpUW/vc75t5m1ANyxG6ymnEQ2FsLQsoMlYB2vV1sO3m8tQ==",
+ "dependencies": {
+ "immer": "^9.0.21",
+ "redux": "^4.2.1",
+ "redux-thunk": "^2.4.2",
+ "reselect": "^4.1.8"
+ },
+ "peerDependencies": {
+ "react": "^16.9.0 || ^17.0.0 || ^18",
+ "react-redux": "^7.2.1 || ^8.0.2"
+ },
+ "peerDependenciesMeta": {
+ "react": {
+ "optional": true
+ },
+ "react-redux": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@remix-run/router": {
+ "version": "1.6.3",
+ "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.6.3.tgz",
+ "integrity": "sha512-EXJysQ7J3veRECd0kZFQwYYd5sJMcq2O/m60zu1W2l3oVQ9xtub8jTOtYRE0+M2iomyG/W3Ps7+vp2kna0C27Q==",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@rollup/rollup-android-arm-eabi": {
+ "version": "4.14.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.14.1.tgz",
+ "integrity": "sha512-fH8/o8nSUek8ceQnT7K4EQbSiV7jgkHq81m9lWZFIXjJ7lJzpWXbQFpT/Zh6OZYnpFykvzC3fbEvEAFZu03dPA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-android-arm64": {
+ "version": "4.14.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.14.1.tgz",
+ "integrity": "sha512-Y/9OHLjzkunF+KGEoJr3heiD5X9OLa8sbT1lm0NYeKyaM3oMhhQFvPB0bNZYJwlq93j8Z6wSxh9+cyKQaxS7PQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-arm64": {
+ "version": "4.14.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.14.1.tgz",
+ "integrity": "sha512-+kecg3FY84WadgcuSVm6llrABOdQAEbNdnpi5X3UwWiFVhZIZvKgGrF7kmLguvxHNQy+UuRV66cLVl3S+Rkt+Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-x64": {
+ "version": "4.14.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.14.1.tgz",
+ "integrity": "sha512-2pYRzEjVqq2TB/UNv47BV/8vQiXkFGVmPFwJb+1E0IFFZbIX8/jo1olxqqMbo6xCXf8kabANhp5bzCij2tFLUA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
+ "version": "4.14.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.14.1.tgz",
+ "integrity": "sha512-mS6wQ6Do6/wmrF9aTFVpIJ3/IDXhg1EZcQFYHZLHqw6AzMBjTHWnCG35HxSqUNphh0EHqSM6wRTT8HsL1C0x5g==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-gnu": {
+ "version": "4.14.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.14.1.tgz",
+ "integrity": "sha512-p9rGKYkHdFMzhckOTFubfxgyIO1vw//7IIjBBRVzyZebWlzRLeNhqxuSaZ7kCEKVkm/kuC9fVRW9HkC/zNRG2w==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-musl": {
+ "version": "4.14.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.14.1.tgz",
+ "integrity": "sha512-nDY6Yz5xS/Y4M2i9JLQd3Rofh5OR8Bn8qe3Mv/qCVpHFlwtZSBYSPaU4mrGazWkXrdQ98GB//H0BirGR/SKFSw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
+ "version": "4.14.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.14.1.tgz",
+ "integrity": "sha512-im7HE4VBL+aDswvcmfx88Mp1soqL9OBsdDBU8NqDEYtkri0qV0THhQsvZtZeNNlLeCUQ16PZyv7cqutjDF35qw==",
+ "cpu": [
+ "ppc64le"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-gnu": {
+ "version": "4.14.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.14.1.tgz",
+ "integrity": "sha512-RWdiHuAxWmzPJgaHJdpvUUlDz8sdQz4P2uv367T2JocdDa98iRw2UjIJ4QxSyt077mXZT2X6pKfT2iYtVEvOFw==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-s390x-gnu": {
+ "version": "4.14.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.14.1.tgz",
+ "integrity": "sha512-VMgaGQ5zRX6ZqV/fas65/sUGc9cPmsntq2FiGmayW9KMNfWVG/j0BAqImvU4KTeOOgYSf1F+k6at1UfNONuNjA==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-gnu": {
+ "version": "4.14.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.14.1.tgz",
+ "integrity": "sha512-9Q7DGjZN+hTdJomaQ3Iub4m6VPu1r94bmK2z3UeWP3dGUecRC54tmVu9vKHTm1bOt3ASoYtEz6JSRLFzrysKlA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-musl": {
+ "version": "4.14.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.14.1.tgz",
+ "integrity": "sha512-JNEG/Ti55413SsreTguSx0LOVKX902OfXIKVg+TCXO6Gjans/k9O6ww9q3oLGjNDaTLxM+IHFMeXy/0RXL5R/g==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-arm64-msvc": {
+ "version": "4.14.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.14.1.tgz",
+ "integrity": "sha512-ryS22I9y0mumlLNwDFYZRDFLwWh3aKaC72CWjFcFvxK0U6v/mOkM5Up1bTbCRAhv3kEIwW2ajROegCIQViUCeA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-ia32-msvc": {
+ "version": "4.14.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.14.1.tgz",
+ "integrity": "sha512-TdloItiGk+T0mTxKx7Hp279xy30LspMso+GzQvV2maYePMAWdmrzqSNZhUpPj3CGw12aGj57I026PgLCTu8CGg==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-x64-msvc": {
+ "version": "4.14.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.14.1.tgz",
+ "integrity": "sha512-wQGI+LY/Py20zdUPq+XCem7JcPOyzIJBm3dli+56DJsQOHbnXZFEwgmnC6el1TPAfC8lBT3m+z69RmLykNUbew==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
+ "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==",
+ "dev": true
+ },
+ "node_modules/@types/hoist-non-react-statics": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz",
+ "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==",
+ "dependencies": {
+ "@types/react": "*",
+ "hoist-non-react-statics": "^3.3.0"
+ }
+ },
+ "node_modules/@types/json-schema": {
+ "version": "7.0.12",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz",
+ "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==",
+ "dev": true
+ },
+ "node_modules/@types/parse-json": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz",
+ "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA=="
+ },
+ "node_modules/@types/prop-types": {
+ "version": "15.7.5",
+ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
+ "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w=="
+ },
+ "node_modules/@types/quill": {
+ "version": "1.3.10",
+ "resolved": "https://registry.npmjs.org/@types/quill/-/quill-1.3.10.tgz",
+ "integrity": "sha512-IhW3fPW+bkt9MLNlycw8u8fWb7oO7W5URC9MfZYHBlA24rex9rs23D5DETChu1zvgVdc5ka64ICjJOgQMr6Shw==",
+ "dependencies": {
+ "parchment": "^1.1.2"
+ }
+ },
+ "node_modules/@types/react": {
+ "version": "18.2.13",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.13.tgz",
+ "integrity": "sha512-vJ+zElvi/Zn9cVXB5slX2xL8PZodPCwPRDpittQdw43JR2AJ5k3vKdgJJyneV/cYgIbLQUwXa9JVDvUZXGba+Q==",
+ "dependencies": {
+ "@types/prop-types": "*",
+ "@types/scheduler": "*",
+ "csstype": "^3.0.2"
+ }
+ },
+ "node_modules/@types/react-dom": {
+ "version": "18.2.6",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.6.tgz",
+ "integrity": "sha512-2et4PDvg6PVCyS7fuTc4gPoksV58bW0RwSxWKcPRcHZf0PRUGq03TKcD/rUHe3azfV6/5/biUBJw+HhCQjaP0A==",
+ "devOptional": true,
+ "dependencies": {
+ "@types/react": "*"
+ }
+ },
+ "node_modules/@types/react-is": {
+ "version": "18.2.1",
+ "resolved": "https://registry.npmjs.org/@types/react-is/-/react-is-18.2.1.tgz",
+ "integrity": "sha512-wyUkmaaSZEzFZivD8F2ftSyAfk6L+DfFliVj/mYdOXbVjRcS87fQJLTnhk6dRZPuJjI+9g6RZJO4PNCngUrmyw==",
+ "dependencies": {
+ "@types/react": "*"
+ }
+ },
+ "node_modules/@types/react-transition-group": {
+ "version": "4.4.6",
+ "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.6.tgz",
+ "integrity": "sha512-VnCdSxfcm08KjsJVQcfBmhEQAPnLB8G08hAxn39azX1qYBQ/5RVQuoHuKIcfKOdncuaUvEpFKFzEvbtIMsfVew==",
+ "dependencies": {
+ "@types/react": "*"
+ }
+ },
+ "node_modules/@types/scheduler": {
+ "version": "0.16.3",
+ "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz",
+ "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ=="
+ },
+ "node_modules/@types/semver": {
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz",
+ "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==",
+ "dev": true
+ },
+ "node_modules/@types/use-sync-external-store": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz",
+ "integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA=="
+ },
+ "node_modules/@typescript-eslint/eslint-plugin": {
+ "version": "5.60.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.60.0.tgz",
+ "integrity": "sha512-78B+anHLF1TI8Jn/cD0Q00TBYdMgjdOn980JfAVa9yw5sop8nyTfVOQAv6LWywkOGLclDBtv5z3oxN4w7jxyNg==",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/regexpp": "^4.4.0",
+ "@typescript-eslint/scope-manager": "5.60.0",
+ "@typescript-eslint/type-utils": "5.60.0",
+ "@typescript-eslint/utils": "5.60.0",
+ "debug": "^4.3.4",
+ "grapheme-splitter": "^1.0.4",
+ "ignore": "^5.2.0",
+ "natural-compare-lite": "^1.4.0",
+ "semver": "^7.3.7",
+ "tsutils": "^3.21.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "@typescript-eslint/parser": "^5.0.0",
+ "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/parser": {
+ "version": "5.60.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.60.0.tgz",
+ "integrity": "sha512-jBONcBsDJ9UoTWrARkRRCgDz6wUggmH5RpQVlt7BimSwaTkTjwypGzKORXbR4/2Hqjk9hgwlon2rVQAjWNpkyQ==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/scope-manager": "5.60.0",
+ "@typescript-eslint/types": "5.60.0",
+ "@typescript-eslint/typescript-estree": "5.60.0",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/scope-manager": {
+ "version": "5.60.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.60.0.tgz",
+ "integrity": "sha512-hakuzcxPwXi2ihf9WQu1BbRj1e/Pd8ZZwVTG9kfbxAMZstKz8/9OoexIwnmLzShtsdap5U/CoQGRCWlSuPbYxQ==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "5.60.0",
+ "@typescript-eslint/visitor-keys": "5.60.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils": {
+ "version": "5.60.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.60.0.tgz",
+ "integrity": "sha512-X7NsRQddORMYRFH7FWo6sA9Y/zbJ8s1x1RIAtnlj6YprbToTiQnM6vxcMu7iYhdunmoC0rUWlca13D5DVHkK2g==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/typescript-estree": "5.60.0",
+ "@typescript-eslint/utils": "5.60.0",
+ "debug": "^4.3.4",
+ "tsutils": "^3.21.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "*"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/types": {
+ "version": "5.60.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.60.0.tgz",
+ "integrity": "sha512-ascOuoCpNZBccFVNJRSC6rPq4EmJ2NkuoKnd6LDNyAQmdDnziAtxbCGWCbefG1CNzmDvd05zO36AmB7H8RzKPA==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree": {
+ "version": "5.60.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.60.0.tgz",
+ "integrity": "sha512-R43thAuwarC99SnvrBmh26tc7F6sPa2B3evkXp/8q954kYL6Ro56AwASYWtEEi+4j09GbiNAHqYwNNZuNlARGQ==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "5.60.0",
+ "@typescript-eslint/visitor-keys": "5.60.0",
+ "debug": "^4.3.4",
+ "globby": "^11.1.0",
+ "is-glob": "^4.0.3",
+ "semver": "^7.3.7",
+ "tsutils": "^3.21.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/utils": {
+ "version": "5.60.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.60.0.tgz",
+ "integrity": "sha512-ba51uMqDtfLQ5+xHtwlO84vkdjrqNzOnqrnwbMHMRY8Tqeme8C2Q8Fc7LajfGR+e3/4LoYiWXUM6BpIIbHJ4hQ==",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.2.0",
+ "@types/json-schema": "^7.0.9",
+ "@types/semver": "^7.3.12",
+ "@typescript-eslint/scope-manager": "5.60.0",
+ "@typescript-eslint/types": "5.60.0",
+ "@typescript-eslint/typescript-estree": "5.60.0",
+ "eslint-scope": "^5.1.1",
+ "semver": "^7.3.7"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/visitor-keys": {
+ "version": "5.60.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.60.0.tgz",
+ "integrity": "sha512-wm9Uz71SbCyhUKgcaPRauBdTegUyY/ZWl8gLwD/i/ybJqscrrdVSFImpvUz16BLPChIeKBK5Fa9s6KDQjsjyWw==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "5.60.0",
+ "eslint-visitor-keys": "^3.3.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@vitejs/plugin-react": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.0.1.tgz",
+ "integrity": "sha512-g25lL98essfeSj43HJ0o4DMp0325XK0ITkxpgChzJU/CyemgyChtlxfnRbjfwxDGCTRxTiXtQAsdebQXKMRSOA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/core": "^7.22.5",
+ "@babel/plugin-transform-react-jsx-self": "^7.22.5",
+ "@babel/plugin-transform-react-jsx-source": "^7.22.5",
+ "react-refresh": "^0.14.0"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "peerDependencies": {
+ "vite": "^4.2.0"
+ }
+ },
+ "node_modules/acorn": {
+ "version": "8.9.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.9.0.tgz",
+ "integrity": "sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ==",
+ "dev": true,
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "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"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dependencies": {
+ "color-convert": "^1.9.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true
+ },
+ "node_modules/array-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/attr-accept": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/attr-accept/-/attr-accept-2.2.2.tgz",
+ "integrity": "sha512-7prDjvt9HmqiZ0cl5CRjtS84sEyhsHP2coDkaZKRKVfCDo9s7iw7ChVmar78Gu9pC4SoR/28wFu/G5JJhTnqEg==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/babel-plugin-macros": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz",
+ "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==",
+ "dependencies": {
+ "@babel/runtime": "^7.12.5",
+ "cosmiconfig": "^7.0.0",
+ "resolve": "^1.19.0"
+ },
+ "engines": {
+ "node": ">=10",
+ "npm": ">=6"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true
+ },
+ "node_modules/blueimp-canvas-to-blob": {
+ "version": "3.29.0",
+ "resolved": "https://registry.npmjs.org/blueimp-canvas-to-blob/-/blueimp-canvas-to-blob-3.29.0.tgz",
+ "integrity": "sha512-0pcSSGxC0QxT+yVkivxIqW0Y4VlO2XSDPofBAqoJ1qJxgH9eiUDLv50Rixij2cDuEfx4M6DpD9UGZpRhT5Q8qg=="
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dev": true,
+ "dependencies": {
+ "fill-range": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/browserslist": {
+ "version": "4.21.9",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.9.tgz",
+ "integrity": "sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "caniuse-lite": "^1.0.30001503",
+ "electron-to-chromium": "^1.4.431",
+ "node-releases": "^2.0.12",
+ "update-browserslist-db": "^1.0.11"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
+ "node_modules/call-bind": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz",
+ "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==",
+ "dependencies": {
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.2.1",
+ "set-function-length": "^1.1.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001505",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001505.tgz",
+ "integrity": "sha512-jaAOR5zVtxHfL0NjZyflVTtXm3D3J9P15zSJ7HmQF8dSKGA6tqzQq+0ZI3xkjyQj46I4/M0K2GbMpcAFOcbr3A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ]
+ },
+ "node_modules/chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dependencies": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/chalk/node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/clone": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
+ "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==",
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/clsx": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz",
+ "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dependencies": {
+ "color-name": "1.1.3"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
+ },
+ "node_modules/compressorjs": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/compressorjs/-/compressorjs-1.2.1.tgz",
+ "integrity": "sha512-+geIjeRnPhQ+LLvvA7wxBQE5ddeLU7pJ3FsKFWirDw6veY3s9iLxAQEw7lXGHnhCJvBujEQWuNnGzZcvCvdkLQ==",
+ "dependencies": {
+ "blueimp-canvas-to-blob": "^3.29.0",
+ "is-blob": "^2.1.0"
+ }
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true
+ },
+ "node_modules/convert-source-map": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
+ "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A=="
+ },
+ "node_modules/cosmiconfig": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz",
+ "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==",
+ "dependencies": {
+ "@types/parse-json": "^4.0.0",
+ "import-fresh": "^3.2.1",
+ "parse-json": "^5.0.0",
+ "path-type": "^4.0.0",
+ "yaml": "^1.10.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "dev": true,
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/csstype": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz",
+ "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ=="
+ },
+ "node_modules/debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "2.1.2"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/deep-equal": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.2.tgz",
+ "integrity": "sha512-5tdhKF6DbU7iIzrIOa1AOUt39ZRm13cmL1cGEh//aqR8x9+tNfbywRf0n5FD/18OKMdo7DNEtrX2t22ZAkI+eg==",
+ "dependencies": {
+ "is-arguments": "^1.1.1",
+ "is-date-object": "^1.0.5",
+ "is-regex": "^1.1.4",
+ "object-is": "^1.1.5",
+ "object-keys": "^1.1.1",
+ "regexp.prototype.flags": "^1.5.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true
+ },
+ "node_modules/define-data-property": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz",
+ "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==",
+ "dependencies": {
+ "get-intrinsic": "^1.2.1",
+ "gopd": "^1.0.1",
+ "has-property-descriptors": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/define-properties": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
+ "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
+ "dependencies": {
+ "define-data-property": "^1.0.1",
+ "has-property-descriptors": "^1.0.0",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/dir-glob": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+ "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+ "dev": true,
+ "dependencies": {
+ "path-type": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/doctrine": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+ "dev": true,
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/dom-helpers": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
+ "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
+ "dependencies": {
+ "@babel/runtime": "^7.8.7",
+ "csstype": "^3.0.2"
+ }
+ },
+ "node_modules/dompurify": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.6.tgz",
+ "integrity": "sha512-ilkD8YEnnGh1zJ240uJsW7AzE+2qpbOUYjacomn3AvJ6J4JhKGSZ2nh4wUIXPZrEPppaCLx5jFe8T89Rk8tQ7w=="
+ },
+ "node_modules/electron-to-chromium": {
+ "version": "1.4.434",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.434.tgz",
+ "integrity": "sha512-5Gvm09UZTQRaWrimRtWRO5rvaX6Kpk5WHAPKDa7A4Gj6NIPuJ8w8WNpnxCXdd+CJJt6RBU6tUw0KyULoW6XuHw==",
+ "dev": true
+ },
+ "node_modules/error-ex": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+ "dependencies": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "node_modules/esbuild": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz",
+ "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==",
+ "dev": true,
+ "hasInstallScript": true,
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.20.2",
+ "@esbuild/android-arm": "0.20.2",
+ "@esbuild/android-arm64": "0.20.2",
+ "@esbuild/android-x64": "0.20.2",
+ "@esbuild/darwin-arm64": "0.20.2",
+ "@esbuild/darwin-x64": "0.20.2",
+ "@esbuild/freebsd-arm64": "0.20.2",
+ "@esbuild/freebsd-x64": "0.20.2",
+ "@esbuild/linux-arm": "0.20.2",
+ "@esbuild/linux-arm64": "0.20.2",
+ "@esbuild/linux-ia32": "0.20.2",
+ "@esbuild/linux-loong64": "0.20.2",
+ "@esbuild/linux-mips64el": "0.20.2",
+ "@esbuild/linux-ppc64": "0.20.2",
+ "@esbuild/linux-riscv64": "0.20.2",
+ "@esbuild/linux-s390x": "0.20.2",
+ "@esbuild/linux-x64": "0.20.2",
+ "@esbuild/netbsd-x64": "0.20.2",
+ "@esbuild/openbsd-x64": "0.20.2",
+ "@esbuild/sunos-x64": "0.20.2",
+ "@esbuild/win32-arm64": "0.20.2",
+ "@esbuild/win32-ia32": "0.20.2",
+ "@esbuild/win32-x64": "0.20.2"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
+ "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint": {
+ "version": "8.43.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.43.0.tgz",
+ "integrity": "sha512-aaCpf2JqqKesMFGgmRPessmVKjcGXqdlAYLLC3THM8t5nBRZRQ+st5WM/hoJXkdioEXLLbXgclUpM0TXo5HX5Q==",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.2.0",
+ "@eslint-community/regexpp": "^4.4.0",
+ "@eslint/eslintrc": "^2.0.3",
+ "@eslint/js": "8.43.0",
+ "@humanwhocodes/config-array": "^0.11.10",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@nodelib/fs.walk": "^1.2.8",
+ "ajv": "^6.10.0",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.2",
+ "debug": "^4.3.2",
+ "doctrine": "^3.0.0",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^7.2.0",
+ "eslint-visitor-keys": "^3.4.1",
+ "espree": "^9.5.2",
+ "esquery": "^1.4.2",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^6.0.1",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "globals": "^13.19.0",
+ "graphemer": "^1.4.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.0.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "is-path-inside": "^3.0.3",
+ "js-yaml": "^4.1.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "levn": "^0.4.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.1",
+ "strip-ansi": "^6.0.1",
+ "strip-json-comments": "^3.1.0",
+ "text-table": "^0.2.0"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-plugin-react-hooks": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz",
+ "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0"
+ }
+ },
+ "node_modules/eslint-plugin-react-refresh": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.3.5.tgz",
+ "integrity": "sha512-61qNIsc7fo9Pp/mju0J83kzvLm0Bsayu7OQSLEoJxLDCBjIIyb87bkzufoOvdDxLkSlMfkF7UxomC4+eztUBSA==",
+ "dev": true,
+ "peerDependencies": {
+ "eslint": ">=7"
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
+ "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
+ "dev": true,
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^4.1.1"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/eslint-visitor-keys": {
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz",
+ "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/eslint/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/eslint/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/eslint/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/eslint/node_modules/eslint-scope": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz",
+ "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==",
+ "dev": true,
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint/node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/eslint/node_modules/globals": {
+ "version": "13.20.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz",
+ "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==",
+ "dev": true,
+ "dependencies": {
+ "type-fest": "^0.20.2"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint/node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/eslint/node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/espree": {
+ "version": "9.5.2",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz",
+ "integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==",
+ "dev": true,
+ "dependencies": {
+ "acorn": "^8.8.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^3.4.1"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/esquery": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
+ "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/esquery/node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esrecurse/node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/eventemitter3": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-2.0.3.tgz",
+ "integrity": "sha512-jLN68Dx5kyFHaePoXWPsCGW5qdyZQtLYHkxkg02/Mz6g0kYpDx4FyP6XfArhQdlOC4b8Mv+EMxPo/8La7Tzghg=="
+ },
+ "node_modules/extend": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true
+ },
+ "node_modules/fast-diff": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.1.2.tgz",
+ "integrity": "sha512-KaJUt+M9t1qaIteSvjc6P3RbMdXsNhK61GRftR6SNxqmhthcd9MGIi4T+o0jD8LUSpSnSKXE20nLtJ3fOHxQig=="
+ },
+ "node_modules/fast-glob": {
+ "version": "3.2.12",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz",
+ "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/fast-glob/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true
+ },
+ "node_modules/fast-memoize": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/fast-memoize/-/fast-memoize-2.5.2.tgz",
+ "integrity": "sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw=="
+ },
+ "node_modules/fastq": {
+ "version": "1.15.0",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
+ "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==",
+ "dev": true,
+ "dependencies": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "node_modules/file-entry-cache": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+ "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+ "dev": true,
+ "dependencies": {
+ "flat-cache": "^3.0.4"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/file-selector": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/file-selector/-/file-selector-0.6.0.tgz",
+ "integrity": "sha512-QlZ5yJC0VxHxQQsQhXvBaC7VRJ2uaxTf+Tfpu4Z/OcVQJVpZO+DGU0rkoVW5ce2SccxugvpBJoMvUs59iILYdw==",
+ "dependencies": {
+ "tslib": "^2.4.0"
+ },
+ "engines": {
+ "node": ">= 12"
+ }
+ },
+ "node_modules/fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "dev": true,
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/find-root": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz",
+ "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng=="
+ },
+ "node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/flat-cache": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
+ "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==",
+ "dev": true,
+ "dependencies": {
+ "flatted": "^3.1.0",
+ "rimraf": "^3.0.2"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/flatted": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz",
+ "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==",
+ "dev": true
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "dev": true
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/functions-have-names": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
+ "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/gensync": {
+ "version": "1.0.0-beta.2",
+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
+ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/get-intrinsic": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz",
+ "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==",
+ "dependencies": {
+ "function-bind": "^1.1.2",
+ "has-proto": "^1.0.1",
+ "has-symbols": "^1.0.3",
+ "hasown": "^2.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "dev": true,
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/globals": {
+ "version": "11.12.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/globby": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
+ "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
+ "dev": true,
+ "dependencies": {
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.2.9",
+ "ignore": "^5.2.0",
+ "merge2": "^1.4.1",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/gopd": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
+ "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
+ "dependencies": {
+ "get-intrinsic": "^1.1.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/grapheme-splitter": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz",
+ "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==",
+ "dev": true
+ },
+ "node_modules/graphemer": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
+ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
+ "dev": true
+ },
+ "node_modules/has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "dependencies": {
+ "function-bind": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "node_modules/has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/has-property-descriptors": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz",
+ "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==",
+ "dependencies": {
+ "get-intrinsic": "^1.2.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz",
+ "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-symbols": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
+ "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-tostringtag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
+ "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
+ "dependencies": {
+ "has-symbols": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/hasown": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz",
+ "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==",
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/hoist-non-react-statics": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
+ "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
+ "dependencies": {
+ "react-is": "^16.7.0"
+ }
+ },
+ "node_modules/hoist-non-react-statics/node_modules/react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+ },
+ "node_modules/ignore": {
+ "version": "5.2.4",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
+ "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/immediate": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
+ "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ=="
+ },
+ "node_modules/immer": {
+ "version": "9.0.21",
+ "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz",
+ "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/immer"
+ }
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+ "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "dev": true,
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true
+ },
+ "node_modules/is-arguments": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
+ "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==",
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="
+ },
+ "node_modules/is-blob": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-blob/-/is-blob-2.1.0.tgz",
+ "integrity": "sha512-SZ/fTft5eUhQM6oF/ZaASFDEdbFVe89Imltn9uZr03wdKMcWNVYSMjQPFtg05QuNkt5l5c135ElvXEQG0rk4tw==",
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-core-module": {
+ "version": "2.12.1",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz",
+ "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==",
+ "dependencies": {
+ "has": "^1.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-date-object": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
+ "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-path-inside": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
+ "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-regex": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
+ "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true
+ },
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
+ },
+ "node_modules/js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dev": true,
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/jsesc": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
+ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
+ "dev": true,
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/json-parse-even-better-errors": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
+ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "node_modules/json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true
+ },
+ "node_modules/json5": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+ "dev": true,
+ "bin": {
+ "json5": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/lie": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz",
+ "integrity": "sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==",
+ "dependencies": {
+ "immediate": "~3.0.5"
+ }
+ },
+ "node_modules/lines-and-columns": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
+ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="
+ },
+ "node_modules/localforage": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/localforage/-/localforage-1.10.0.tgz",
+ "integrity": "sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==",
+ "dependencies": {
+ "lie": "3.1.1"
+ }
+ },
+ "node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
+ },
+ "node_modules/lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true
+ },
+ "node_modules/loose-envify": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "dependencies": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ },
+ "bin": {
+ "loose-envify": "cli.js"
+ }
+ },
+ "node_modules/lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "node_modules/merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/micromatch": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
+ "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+ "dev": true,
+ "dependencies": {
+ "braces": "^3.0.2",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/moment": {
+ "version": "2.29.4",
+ "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
+ "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.7",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
+ "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true
+ },
+ "node_modules/natural-compare-lite": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz",
+ "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==",
+ "dev": true
+ },
+ "node_modules/node-releases": {
+ "version": "2.0.12",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.12.tgz",
+ "integrity": "sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ==",
+ "dev": true
+ },
+ "node_modules/object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-is": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz",
+ "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==",
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object-keys": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dev": true,
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/optionator": {
+ "version": "0.9.1",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
+ "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==",
+ "dev": true,
+ "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.3"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/parchment": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/parchment/-/parchment-1.1.4.tgz",
+ "integrity": "sha512-J5FBQt/pM2inLzg4hEWmzQx/8h8D0CiDxaG3vyp9rKrQRSDgBlhjdP5jQGgosEajXPSQouXGHOmVdgo7QmJuOg=="
+ },
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/parse-json": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
+ "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
+ "dependencies": {
+ "@babel/code-frame": "^7.0.0",
+ "error-ex": "^1.3.1",
+ "json-parse-even-better-errors": "^2.3.0",
+ "lines-and-columns": "^1.1.6"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
+ },
+ "node_modules/path-type": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/picocolors": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
+ "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
+ "dev": true
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/postcss": {
+ "version": "8.4.38",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz",
+ "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "nanoid": "^3.3.7",
+ "picocolors": "^1.0.0",
+ "source-map-js": "^1.2.0"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/prettier": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.4.tgz",
+ "integrity": "sha512-FWu1oLHKCrtpO1ypU6J0SbK2d9Ckwysq6bHj/uaCP26DxrPpppCLQRGVuqAxSTvhF00AcvDRyYrLNW7ocBhFFQ==",
+ "bin": {
+ "prettier": "bin/prettier.cjs"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ },
+ "node_modules/prop-types": {
+ "version": "15.8.1",
+ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
+ "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+ "dependencies": {
+ "loose-envify": "^1.4.0",
+ "object-assign": "^4.1.1",
+ "react-is": "^16.13.1"
+ }
+ },
+ "node_modules/prop-types/node_modules/react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+ },
+ "node_modules/punycode": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
+ "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/quill": {
+ "version": "1.3.7",
+ "resolved": "https://registry.npmjs.org/quill/-/quill-1.3.7.tgz",
+ "integrity": "sha512-hG/DVzh/TiknWtE6QmWAF/pxoZKYxfe3J/d/+ShUWkDvvkZQVTPeVmUJVu1uE6DDooC4fWTiCLh84ul89oNz5g==",
+ "dependencies": {
+ "clone": "^2.1.1",
+ "deep-equal": "^1.0.1",
+ "eventemitter3": "^2.0.3",
+ "extend": "^3.0.2",
+ "parchment": "^1.1.4",
+ "quill-delta": "^3.6.2"
+ }
+ },
+ "node_modules/quill-delta": {
+ "version": "3.6.3",
+ "resolved": "https://registry.npmjs.org/quill-delta/-/quill-delta-3.6.3.tgz",
+ "integrity": "sha512-wdIGBlcX13tCHOXGMVnnTVFtGRLoP0imqxM696fIPwIf5ODIYUHIvHbZcyvGlZFiFhK5XzDC2lpjbxRhnM05Tg==",
+ "dependencies": {
+ "deep-equal": "^1.0.1",
+ "extend": "^3.0.2",
+ "fast-diff": "1.1.2"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/quill-image-resize-module-react": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/quill-image-resize-module-react/-/quill-image-resize-module-react-3.0.0.tgz",
+ "integrity": "sha512-3jVChLoXh+fwEELx3OswOEEuF+1KU3r/B9RAqZ//s+d+UMduVZzUepU1g/XoxjKoBJvWD2lJwBIFBRUNb8ebCw==",
+ "dependencies": {
+ "lodash": "^4.17.4",
+ "quill": "^1.2.2",
+ "raw-loader": "^0.5.1"
+ }
+ },
+ "node_modules/raw-loader": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-0.5.1.tgz",
+ "integrity": "sha512-sf7oGoLuaYAScB4VGr0tzetsYlS8EJH6qnTCfQ/WVEa89hALQ4RQfCKt5xCyPQKPDUbVUAIP1QsxAwfAjlDp7Q=="
+ },
+ "node_modules/re-resizable": {
+ "version": "6.9.6",
+ "resolved": "https://registry.npmjs.org/re-resizable/-/re-resizable-6.9.6.tgz",
+ "integrity": "sha512-0xYKS5+Z0zk+vICQlcZW+g54CcJTTmHluA7JUUgvERDxnKAnytylcyPsA+BSFi759s5hPlHmBRegFrwXs2FuBQ==",
+ "dependencies": {
+ "fast-memoize": "^2.5.1"
+ },
+ "peerDependencies": {
+ "react": "^16.13.1 || ^17.0.0 || ^18.0.0",
+ "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/react": {
+ "version": "18.2.0",
+ "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
+ "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==",
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-dom": {
+ "version": "18.2.0",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
+ "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==",
+ "dependencies": {
+ "loose-envify": "^1.1.0",
+ "scheduler": "^0.23.0"
+ },
+ "peerDependencies": {
+ "react": "^18.2.0"
+ }
+ },
+ "node_modules/react-draggable": {
+ "version": "4.4.5",
+ "resolved": "https://registry.npmjs.org/react-draggable/-/react-draggable-4.4.5.tgz",
+ "integrity": "sha512-OMHzJdyJbYTZo4uQE393fHcqqPYsEtkjfMgvCHr6rejT+Ezn4OZbNyGH50vv+SunC1RMvwOTSWkEODQLzw1M9g==",
+ "dependencies": {
+ "clsx": "^1.1.1",
+ "prop-types": "^15.8.1"
+ },
+ "peerDependencies": {
+ "react": ">= 16.3.0",
+ "react-dom": ">= 16.3.0"
+ }
+ },
+ "node_modules/react-dropzone": {
+ "version": "14.2.3",
+ "resolved": "https://registry.npmjs.org/react-dropzone/-/react-dropzone-14.2.3.tgz",
+ "integrity": "sha512-O3om8I+PkFKbxCukfIR3QAGftYXDZfOE2N1mr/7qebQJHs7U+/RSL/9xomJNpRg9kM5h9soQSdf0Gc7OHF5Fug==",
+ "dependencies": {
+ "attr-accept": "^2.2.2",
+ "file-selector": "^0.6.0",
+ "prop-types": "^15.8.1"
+ },
+ "engines": {
+ "node": ">= 10.13"
+ },
+ "peerDependencies": {
+ "react": ">= 16.8 || 18.0.0"
+ }
+ },
+ "node_modules/react-intersection-observer": {
+ "version": "9.5.0",
+ "resolved": "https://registry.npmjs.org/react-intersection-observer/-/react-intersection-observer-9.5.0.tgz",
+ "integrity": "sha512-bQbfe6Jl8KSynbWfQWz8LoGCCmG6fhsilljgc6dc1NMYpNmP20wfFsrF7CE5N9+LbWx33DUgJdkNBVhU1JzIRA==",
+ "peerDependencies": {
+ "react": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/react-is": {
+ "version": "18.2.0",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
+ "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
+ },
+ "node_modules/react-quill": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/react-quill/-/react-quill-2.0.0.tgz",
+ "integrity": "sha512-4qQtv1FtCfLgoD3PXAur5RyxuUbPXQGOHgTlFie3jtxp43mXDtzCKaOgQ3mLyZfi1PUlyjycfivKelFhy13QUg==",
+ "dependencies": {
+ "@types/quill": "^1.3.10",
+ "lodash": "^4.17.4",
+ "quill": "^1.3.7"
+ },
+ "peerDependencies": {
+ "react": "^16 || ^17 || ^18",
+ "react-dom": "^16 || ^17 || ^18"
+ }
+ },
+ "node_modules/react-redux": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.1.0.tgz",
+ "integrity": "sha512-CtHZzAOxi7GQvTph4dVLWwZHAWUjV2kMEQtk50OrN8z3gKxpWg3Tz7JfDw32N3Rpd7fh02z73cF6yZkK467gbQ==",
+ "dependencies": {
+ "@babel/runtime": "^7.12.1",
+ "@types/hoist-non-react-statics": "^3.3.1",
+ "@types/use-sync-external-store": "^0.0.3",
+ "hoist-non-react-statics": "^3.3.2",
+ "react-is": "^18.0.0",
+ "use-sync-external-store": "^1.0.0"
+ },
+ "peerDependencies": {
+ "@reduxjs/toolkit": "^1 || ^2.0.0-beta.0",
+ "@types/react": "^16.8 || ^17.0 || ^18.0",
+ "@types/react-dom": "^16.8 || ^17.0 || ^18.0",
+ "react": "^16.8 || ^17.0 || ^18.0",
+ "react-dom": "^16.8 || ^17.0 || ^18.0",
+ "react-native": ">=0.59",
+ "redux": "^4 || ^5.0.0-beta.0"
+ },
+ "peerDependenciesMeta": {
+ "@reduxjs/toolkit": {
+ "optional": true
+ },
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ },
+ "react-dom": {
+ "optional": true
+ },
+ "react-native": {
+ "optional": true
+ },
+ "redux": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/react-refresh": {
+ "version": "0.14.0",
+ "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz",
+ "integrity": "sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-rnd": {
+ "version": "10.4.1",
+ "resolved": "https://registry.npmjs.org/react-rnd/-/react-rnd-10.4.1.tgz",
+ "integrity": "sha512-0m887AjQZr6p2ADLNnipquqsDq4XJu/uqVqI3zuoGD19tRm6uB83HmZWydtkilNp5EWsOHbLGF4IjWMdd5du8Q==",
+ "dependencies": {
+ "re-resizable": "6.9.6",
+ "react-draggable": "4.4.5",
+ "tslib": "2.3.1"
+ },
+ "peerDependencies": {
+ "react": ">=16.3.0",
+ "react-dom": ">=16.3.0"
+ }
+ },
+ "node_modules/react-rnd/node_modules/tslib": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
+ "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
+ },
+ "node_modules/react-router": {
+ "version": "6.13.0",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.13.0.tgz",
+ "integrity": "sha512-Si6KnfEnJw7gUQkNa70dlpI1bul46FuSxX5t5WwlUBxE25DAz2BjVkwaK8Y2s242bQrZPXCpmwLPtIO5pv4tXg==",
+ "dependencies": {
+ "@remix-run/router": "1.6.3"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "react": ">=16.8"
+ }
+ },
+ "node_modules/react-router-dom": {
+ "version": "6.13.0",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.13.0.tgz",
+ "integrity": "sha512-6Nqoqd7fgwxxVGdbiMHTpDHCYPq62d7Wk1Of7B82vH7ZPwwsRaIa22zRZKPPg413R5REVNiyuQPKDG1bubcOFA==",
+ "dependencies": {
+ "@remix-run/router": "1.6.3",
+ "react-router": "6.13.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "react": ">=16.8",
+ "react-dom": ">=16.8"
+ }
+ },
+ "node_modules/react-toastify": {
+ "version": "9.1.3",
+ "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-9.1.3.tgz",
+ "integrity": "sha512-fPfb8ghtn/XMxw3LkxQBk3IyagNpF/LIKjOBflbexr2AWxAH1MJgvnESwEwBn9liLFXgTKWgBSdZpw9m4OTHTg==",
+ "dependencies": {
+ "clsx": "^1.1.1"
+ },
+ "peerDependencies": {
+ "react": ">=16",
+ "react-dom": ">=16"
+ }
+ },
+ "node_modules/react-transition-group": {
+ "version": "4.4.5",
+ "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
+ "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==",
+ "dependencies": {
+ "@babel/runtime": "^7.5.5",
+ "dom-helpers": "^5.0.1",
+ "loose-envify": "^1.4.0",
+ "prop-types": "^15.6.2"
+ },
+ "peerDependencies": {
+ "react": ">=16.6.0",
+ "react-dom": ">=16.6.0"
+ }
+ },
+ "node_modules/redux": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz",
+ "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==",
+ "dependencies": {
+ "@babel/runtime": "^7.9.2"
+ }
+ },
+ "node_modules/redux-thunk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz",
+ "integrity": "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==",
+ "peerDependencies": {
+ "redux": "^4"
+ }
+ },
+ "node_modules/regenerator-runtime": {
+ "version": "0.13.11",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
+ "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="
+ },
+ "node_modules/regexp.prototype.flags": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz",
+ "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==",
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "set-function-name": "^2.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/reselect": {
+ "version": "4.1.8",
+ "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz",
+ "integrity": "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ=="
+ },
+ "node_modules/resolve": {
+ "version": "1.22.2",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz",
+ "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==",
+ "dependencies": {
+ "is-core-module": "^2.11.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "dev": true,
+ "engines": {
+ "iojs": ">=1.0.0",
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "dev": true,
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/rollup": {
+ "version": "4.14.1",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.14.1.tgz",
+ "integrity": "sha512-4LnHSdd3QK2pa1J6dFbfm1HN0D7vSK/ZuZTsdyUAlA6Rr1yTouUTL13HaDOGJVgby461AhrNGBS7sCGXXtT+SA==",
+ "dev": true,
+ "dependencies": {
+ "@types/estree": "1.0.5"
+ },
+ "bin": {
+ "rollup": "dist/bin/rollup"
+ },
+ "engines": {
+ "node": ">=18.0.0",
+ "npm": ">=8.0.0"
+ },
+ "optionalDependencies": {
+ "@rollup/rollup-android-arm-eabi": "4.14.1",
+ "@rollup/rollup-android-arm64": "4.14.1",
+ "@rollup/rollup-darwin-arm64": "4.14.1",
+ "@rollup/rollup-darwin-x64": "4.14.1",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.14.1",
+ "@rollup/rollup-linux-arm64-gnu": "4.14.1",
+ "@rollup/rollup-linux-arm64-musl": "4.14.1",
+ "@rollup/rollup-linux-powerpc64le-gnu": "4.14.1",
+ "@rollup/rollup-linux-riscv64-gnu": "4.14.1",
+ "@rollup/rollup-linux-s390x-gnu": "4.14.1",
+ "@rollup/rollup-linux-x64-gnu": "4.14.1",
+ "@rollup/rollup-linux-x64-musl": "4.14.1",
+ "@rollup/rollup-win32-arm64-msvc": "4.14.1",
+ "@rollup/rollup-win32-ia32-msvc": "4.14.1",
+ "@rollup/rollup-win32-x64-msvc": "4.14.1",
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "node_modules/scheduler": {
+ "version": "0.23.0",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz",
+ "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==",
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ }
+ },
+ "node_modules/semver": {
+ "version": "7.5.2",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.2.tgz",
+ "integrity": "sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/semver/node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/semver/node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ },
+ "node_modules/set-function-length": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz",
+ "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==",
+ "dependencies": {
+ "define-data-property": "^1.1.1",
+ "get-intrinsic": "^1.2.1",
+ "gopd": "^1.0.1",
+ "has-property-descriptors": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/set-function-name": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz",
+ "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==",
+ "dependencies": {
+ "define-data-property": "^1.0.1",
+ "functions-have-names": "^1.2.3",
+ "has-property-descriptors": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/short-unique-id": {
+ "version": "4.4.4",
+ "resolved": "https://registry.npmjs.org/short-unique-id/-/short-unique-id-4.4.4.tgz",
+ "integrity": "sha512-oLF1NCmtbiTWl2SqdXZQbo5KM1b7axdp0RgQLq8qCBBLoq+o3A5wmLrNM6bZIh54/a8BJ3l69kTXuxwZ+XCYuw==",
+ "bin": {
+ "short-unique-id": "bin/short-unique-id",
+ "suid": "bin/short-unique-id"
+ }
+ },
+ "node_modules/slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz",
+ "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/stylis": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz",
+ "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw=="
+ },
+ "node_modules/supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dependencies": {
+ "has-flag": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
+ "dev": true
+ },
+ "node_modules/to-fast-properties": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
+ "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/ts-key-enum": {
+ "version": "2.0.12",
+ "resolved": "https://registry.npmjs.org/ts-key-enum/-/ts-key-enum-2.0.12.tgz",
+ "integrity": "sha512-Ety4IvKMaeG34AyXMp5r11XiVZNDRL+XWxXbVVJjLvq2vxKRttEANBE7Za1bxCAZRdH2/sZT6jFyyTWxXz28hw=="
+ },
+ "node_modules/tslib": {
+ "version": "2.5.3",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz",
+ "integrity": "sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w=="
+ },
+ "node_modules/tsutils": {
+ "version": "3.21.0",
+ "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
+ "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
+ "dev": true,
+ "dependencies": {
+ "tslib": "^1.8.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ },
+ "peerDependencies": {
+ "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta"
+ }
+ },
+ "node_modules/tsutils/node_modules/tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+ "dev": true
+ },
+ "node_modules/type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/type-fest": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "5.1.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.3.tgz",
+ "integrity": "sha512-XH627E9vkeqhlZFQuL+UsyAXEnibT0kWR2FWONlr4sTjvxyJYnyefgrkyECLzM5NenmKzRAy2rR/OlYLA1HkZw==",
+ "dev": true,
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/update-browserslist-db": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz",
+ "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "escalade": "^3.1.1",
+ "picocolors": "^1.0.0"
+ },
+ "bin": {
+ "update-browserslist-db": "cli.js"
+ },
+ "peerDependencies": {
+ "browserslist": ">= 4.21.0"
+ }
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/use-sync-external-store": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
+ "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==",
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/vite": {
+ "version": "6.0.0-alpha.1",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-6.0.0-alpha.1.tgz",
+ "integrity": "sha512-LVvQVG3AftURxT11TgWXpfVIqBKC4D/NA5ikYQb9hDORF0hvO+gsyvNu8GR73/oag09A5JJAPAFU+r7ly4+9Lw==",
+ "dev": true,
+ "dependencies": {
+ "esbuild": "^0.20.1",
+ "postcss": "^8.4.38",
+ "rollup": "^4.13.0"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^18.0.0 || >=20.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/vitejs/vite?sponsor=1"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ },
+ "peerDependencies": {
+ "@types/node": "^18.0.0 || >=20.0.0",
+ "less": "*",
+ "lightningcss": "^1.21.0",
+ "sass": "*",
+ "stylus": "*",
+ "sugarss": "*",
+ "terser": "^5.4.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "lightningcss": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/word-wrap": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
+ "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "dev": true
+ },
+ "node_modules/yallist": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+ "dev": true
+ },
+ "node_modules/yaml": {
+ "version": "1.10.2",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
+ "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ }
+ },
+ "dependencies": {
+ "@ampproject/remapping": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz",
+ "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==",
+ "dev": true,
+ "requires": {
+ "@jridgewell/gen-mapping": "^0.3.0",
+ "@jridgewell/trace-mapping": "^0.3.9"
+ }
+ },
+ "@babel/code-frame": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz",
+ "integrity": "sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==",
+ "requires": {
+ "@babel/highlight": "^7.22.5"
+ }
+ },
+ "@babel/compat-data": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.5.tgz",
+ "integrity": "sha512-4Jc/YuIaYqKnDDz892kPIledykKg12Aw1PYX5i/TY28anJtacvM1Rrr8wbieB9GfEJwlzqT0hUEao0CxEebiDA==",
+ "dev": true
+ },
+ "@babel/core": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.5.tgz",
+ "integrity": "sha512-SBuTAjg91A3eKOvD+bPEz3LlhHZRNu1nFOVts9lzDJTXshHTjII0BAtDS3Y2DAkdZdDKWVZGVwkDfc4Clxn1dg==",
+ "dev": true,
+ "requires": {
+ "@ampproject/remapping": "^2.2.0",
+ "@babel/code-frame": "^7.22.5",
+ "@babel/generator": "^7.22.5",
+ "@babel/helper-compilation-targets": "^7.22.5",
+ "@babel/helper-module-transforms": "^7.22.5",
+ "@babel/helpers": "^7.22.5",
+ "@babel/parser": "^7.22.5",
+ "@babel/template": "^7.22.5",
+ "@babel/traverse": "^7.22.5",
+ "@babel/types": "^7.22.5",
+ "convert-source-map": "^1.7.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.2",
+ "semver": "^6.3.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ }
+ }
+ },
+ "@babel/generator": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.5.tgz",
+ "integrity": "sha512-+lcUbnTRhd0jOewtFSedLyiPsD5tswKkbgcezOqqWFUVNEwoUTlpPOBmvhG7OXWLR4jMdv0czPGH5XbflnD1EA==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.22.5",
+ "@jridgewell/gen-mapping": "^0.3.2",
+ "@jridgewell/trace-mapping": "^0.3.17",
+ "jsesc": "^2.5.1"
+ }
+ },
+ "@babel/helper-compilation-targets": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.5.tgz",
+ "integrity": "sha512-Ji+ywpHeuqxB8WDxraCiqR0xfhYjiDE/e6k7FuIaANnoOFxAHskHChz4vA1mJC9Lbm01s1PVAGhQY4FUKSkGZw==",
+ "dev": true,
+ "requires": {
+ "@babel/compat-data": "^7.22.5",
+ "@babel/helper-validator-option": "^7.22.5",
+ "browserslist": "^4.21.3",
+ "lru-cache": "^5.1.1",
+ "semver": "^6.3.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ }
+ }
+ },
+ "@babel/helper-environment-visitor": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz",
+ "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==",
+ "dev": true
+ },
+ "@babel/helper-function-name": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz",
+ "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==",
+ "dev": true,
+ "requires": {
+ "@babel/template": "^7.22.5",
+ "@babel/types": "^7.22.5"
+ }
+ },
+ "@babel/helper-hoist-variables": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz",
+ "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.22.5"
+ }
+ },
+ "@babel/helper-module-imports": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz",
+ "integrity": "sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==",
+ "requires": {
+ "@babel/types": "^7.22.5"
+ }
+ },
+ "@babel/helper-module-transforms": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.5.tgz",
+ "integrity": "sha512-+hGKDt/Ze8GFExiVHno/2dvG5IdstpzCq0y4Qc9OJ25D4q3pKfiIP/4Vp3/JvhDkLKsDK2api3q3fpIgiIF5bw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-environment-visitor": "^7.22.5",
+ "@babel/helper-module-imports": "^7.22.5",
+ "@babel/helper-simple-access": "^7.22.5",
+ "@babel/helper-split-export-declaration": "^7.22.5",
+ "@babel/helper-validator-identifier": "^7.22.5",
+ "@babel/template": "^7.22.5",
+ "@babel/traverse": "^7.22.5",
+ "@babel/types": "^7.22.5"
+ }
+ },
+ "@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==",
+ "dev": true
+ },
+ "@babel/helper-simple-access": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz",
+ "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.22.5"
+ }
+ },
+ "@babel/helper-split-export-declaration": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.5.tgz",
+ "integrity": "sha512-thqK5QFghPKWLhAV321lxF95yCg2K3Ob5yw+M3VHWfdia0IkPXUtoLH8x/6Fh486QUvzhb8YOWHChTVen2/PoQ==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.22.5"
+ }
+ },
+ "@babel/helper-string-parser": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz",
+ "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw=="
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz",
+ "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ=="
+ },
+ "@babel/helper-validator-option": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz",
+ "integrity": "sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==",
+ "dev": true
+ },
+ "@babel/helpers": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.5.tgz",
+ "integrity": "sha512-pSXRmfE1vzcUIDFQcSGA5Mr+GxBV9oiRKDuDxXvWQQBCh8HoIjs/2DlDB7H8smac1IVrB9/xdXj2N3Wol9Cr+Q==",
+ "dev": true,
+ "requires": {
+ "@babel/template": "^7.22.5",
+ "@babel/traverse": "^7.22.5",
+ "@babel/types": "^7.22.5"
+ }
+ },
+ "@babel/highlight": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.5.tgz",
+ "integrity": "sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==",
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.22.5",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ }
+ },
+ "@babel/parser": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.5.tgz",
+ "integrity": "sha512-DFZMC9LJUG9PLOclRC32G63UXwzqS2koQC8dkx+PLdmt1xSePYpbT/NbsrJy8Q/muXz7o/h/d4A7Fuyixm559Q==",
+ "dev": true
+ },
+ "@babel/plugin-transform-react-jsx-self": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.22.5.tgz",
+ "integrity": "sha512-nTh2ogNUtxbiSbxaT4Ds6aXnXEipHweN9YRgOX/oNXdf0cCrGn/+2LozFa3lnPV5D90MkjhgckCPBrsoSc1a7g==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.22.5"
+ }
+ },
+ "@babel/plugin-transform-react-jsx-source": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.22.5.tgz",
+ "integrity": "sha512-yIiRO6yobeEIaI0RTbIr8iAK9FcBHLtZq0S89ZPjDLQXBA4xvghaKqI0etp/tF3htTM0sazJKKLz9oEiGRtu7w==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.22.5"
+ }
+ },
+ "@babel/runtime": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.5.tgz",
+ "integrity": "sha512-ecjvYlnAaZ/KVneE/OdKYBYfgXV3Ptu6zQWmgEF7vwKhQnvVS6bjMD2XYgj+SNvQ1GfK/pjgokfPkC/2CO8CuA==",
+ "requires": {
+ "regenerator-runtime": "^0.13.11"
+ }
+ },
+ "@babel/template": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz",
+ "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.22.5",
+ "@babel/parser": "^7.22.5",
+ "@babel/types": "^7.22.5"
+ }
+ },
+ "@babel/traverse": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.5.tgz",
+ "integrity": "sha512-7DuIjPgERaNo6r+PZwItpjCZEa5vyw4eJGufeLxrPdBXBoLcCJCIasvK6pK/9DVNrLZTLFhUGqaC6X/PA007TQ==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.22.5",
+ "@babel/generator": "^7.22.5",
+ "@babel/helper-environment-visitor": "^7.22.5",
+ "@babel/helper-function-name": "^7.22.5",
+ "@babel/helper-hoist-variables": "^7.22.5",
+ "@babel/helper-split-export-declaration": "^7.22.5",
+ "@babel/parser": "^7.22.5",
+ "@babel/types": "^7.22.5",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0"
+ }
+ },
+ "@babel/types": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz",
+ "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==",
+ "requires": {
+ "@babel/helper-string-parser": "^7.22.5",
+ "@babel/helper-validator-identifier": "^7.22.5",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "@emotion/babel-plugin": {
+ "version": "11.11.0",
+ "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz",
+ "integrity": "sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==",
+ "requires": {
+ "@babel/helper-module-imports": "^7.16.7",
+ "@babel/runtime": "^7.18.3",
+ "@emotion/hash": "^0.9.1",
+ "@emotion/memoize": "^0.8.1",
+ "@emotion/serialize": "^1.1.2",
+ "babel-plugin-macros": "^3.1.0",
+ "convert-source-map": "^1.5.0",
+ "escape-string-regexp": "^4.0.0",
+ "find-root": "^1.1.0",
+ "source-map": "^0.5.7",
+ "stylis": "4.2.0"
+ }
+ },
+ "@emotion/cache": {
+ "version": "11.11.0",
+ "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.11.0.tgz",
+ "integrity": "sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==",
+ "requires": {
+ "@emotion/memoize": "^0.8.1",
+ "@emotion/sheet": "^1.2.2",
+ "@emotion/utils": "^1.2.1",
+ "@emotion/weak-memoize": "^0.3.1",
+ "stylis": "4.2.0"
+ }
+ },
+ "@emotion/hash": {
+ "version": "0.9.1",
+ "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz",
+ "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ=="
+ },
+ "@emotion/is-prop-valid": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz",
+ "integrity": "sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw==",
+ "requires": {
+ "@emotion/memoize": "^0.8.1"
+ }
+ },
+ "@emotion/memoize": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz",
+ "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA=="
+ },
+ "@emotion/react": {
+ "version": "11.11.1",
+ "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.1.tgz",
+ "integrity": "sha512-5mlW1DquU5HaxjLkfkGN1GA/fvVGdyHURRiX/0FHl2cfIfRxSOfmxEH5YS43edp0OldZrZ+dkBKbngxcNCdZvA==",
+ "requires": {
+ "@babel/runtime": "^7.18.3",
+ "@emotion/babel-plugin": "^11.11.0",
+ "@emotion/cache": "^11.11.0",
+ "@emotion/serialize": "^1.1.2",
+ "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1",
+ "@emotion/utils": "^1.2.1",
+ "@emotion/weak-memoize": "^0.3.1",
+ "hoist-non-react-statics": "^3.3.1"
+ }
+ },
+ "@emotion/serialize": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.2.tgz",
+ "integrity": "sha512-zR6a/fkFP4EAcCMQtLOhIgpprZOwNmCldtpaISpvz348+DP4Mz8ZoKaGGCQpbzepNIUWbq4w6hNZkwDyKoS+HA==",
+ "requires": {
+ "@emotion/hash": "^0.9.1",
+ "@emotion/memoize": "^0.8.1",
+ "@emotion/unitless": "^0.8.1",
+ "@emotion/utils": "^1.2.1",
+ "csstype": "^3.0.2"
+ }
+ },
+ "@emotion/sheet": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.2.tgz",
+ "integrity": "sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA=="
+ },
+ "@emotion/styled": {
+ "version": "11.11.0",
+ "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.11.0.tgz",
+ "integrity": "sha512-hM5Nnvu9P3midq5aaXj4I+lnSfNi7Pmd4EWk1fOZ3pxookaQTNew6bp4JaCBYM4HVFZF9g7UjJmsUmC2JlxOng==",
+ "requires": {
+ "@babel/runtime": "^7.18.3",
+ "@emotion/babel-plugin": "^11.11.0",
+ "@emotion/is-prop-valid": "^1.2.1",
+ "@emotion/serialize": "^1.1.2",
+ "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1",
+ "@emotion/utils": "^1.2.1"
+ }
+ },
+ "@emotion/unitless": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz",
+ "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ=="
+ },
+ "@emotion/use-insertion-effect-with-fallbacks": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz",
+ "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==",
+ "requires": {}
+ },
+ "@emotion/utils": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.1.tgz",
+ "integrity": "sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg=="
+ },
+ "@emotion/weak-memoize": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz",
+ "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww=="
+ },
+ "@esbuild/aix-ppc64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz",
+ "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/android-arm": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz",
+ "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/android-arm64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz",
+ "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/android-x64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz",
+ "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/darwin-arm64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz",
+ "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/darwin-x64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz",
+ "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/freebsd-arm64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz",
+ "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/freebsd-x64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz",
+ "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/linux-arm": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz",
+ "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/linux-arm64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz",
+ "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/linux-ia32": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz",
+ "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/linux-loong64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz",
+ "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/linux-mips64el": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz",
+ "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/linux-ppc64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz",
+ "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/linux-riscv64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz",
+ "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/linux-s390x": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz",
+ "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/linux-x64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz",
+ "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/netbsd-x64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz",
+ "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/openbsd-x64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz",
+ "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/sunos-x64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz",
+ "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/win32-arm64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz",
+ "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/win32-ia32": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz",
+ "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/win32-x64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz",
+ "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==",
+ "dev": true,
+ "optional": true
+ },
+ "@eslint-community/eslint-utils": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
+ "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==",
+ "dev": true,
+ "requires": {
+ "eslint-visitor-keys": "^3.3.0"
+ }
+ },
+ "@eslint-community/regexpp": {
+ "version": "4.5.1",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz",
+ "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==",
+ "dev": true
+ },
+ "@eslint/eslintrc": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz",
+ "integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==",
+ "dev": true,
+ "requires": {
+ "ajv": "^6.12.4",
+ "debug": "^4.3.2",
+ "espree": "^9.5.2",
+ "globals": "^13.19.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"
+ },
+ "dependencies": {
+ "globals": {
+ "version": "13.20.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz",
+ "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==",
+ "dev": true,
+ "requires": {
+ "type-fest": "^0.20.2"
+ }
+ }
+ }
+ },
+ "@eslint/js": {
+ "version": "8.43.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.43.0.tgz",
+ "integrity": "sha512-s2UHCoiXfxMvmfzqoN+vrQ84ahUSYde9qNO1MdxmoEhyHWsfmwOpFlwYV+ePJEVc7gFnATGUi376WowX1N7tFg==",
+ "dev": true
+ },
+ "@humanwhocodes/config-array": {
+ "version": "0.11.10",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz",
+ "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==",
+ "dev": true,
+ "requires": {
+ "@humanwhocodes/object-schema": "^1.2.1",
+ "debug": "^4.1.1",
+ "minimatch": "^3.0.5"
+ }
+ },
+ "@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+ "dev": true
+ },
+ "@humanwhocodes/object-schema": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz",
+ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
+ "dev": true
+ },
+ "@jridgewell/gen-mapping": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz",
+ "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==",
+ "dev": true,
+ "requires": {
+ "@jridgewell/set-array": "^1.0.1",
+ "@jridgewell/sourcemap-codec": "^1.4.10",
+ "@jridgewell/trace-mapping": "^0.3.9"
+ }
+ },
+ "@jridgewell/resolve-uri": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
+ "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
+ "dev": true
+ },
+ "@jridgewell/set-array": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
+ "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
+ "dev": true
+ },
+ "@jridgewell/sourcemap-codec": {
+ "version": "1.4.15",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
+ "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
+ "dev": true
+ },
+ "@jridgewell/trace-mapping": {
+ "version": "0.3.18",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz",
+ "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==",
+ "dev": true,
+ "requires": {
+ "@jridgewell/resolve-uri": "3.1.0",
+ "@jridgewell/sourcemap-codec": "1.4.14"
+ },
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": {
+ "version": "1.4.14",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
+ "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
+ "dev": true
+ }
+ }
+ },
+ "@mui/base": {
+ "version": "5.0.0-beta.4",
+ "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.4.tgz",
+ "integrity": "sha512-ejhtqYJpjDgHGEljjMBQWZ22yEK0OzIXNa7toJmmXsP4TT3W7xVy8bTJ0TniPDf+JNjrsgfgiFTDGdlEhV1E+g==",
+ "requires": {
+ "@babel/runtime": "^7.21.0",
+ "@emotion/is-prop-valid": "^1.2.1",
+ "@mui/types": "^7.2.4",
+ "@mui/utils": "^5.13.1",
+ "@popperjs/core": "^2.11.8",
+ "clsx": "^1.2.1",
+ "prop-types": "^15.8.1",
+ "react-is": "^18.2.0"
+ }
+ },
+ "@mui/core-downloads-tracker": {
+ "version": "5.13.4",
+ "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.13.4.tgz",
+ "integrity": "sha512-yFrMWcrlI0TqRN5jpb6Ma9iI7sGTHpytdzzL33oskFHNQ8UgrtPas33Y1K7sWAMwCrr1qbWDrOHLAQG4tAzuSw=="
+ },
+ "@mui/icons-material": {
+ "version": "5.11.16",
+ "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.11.16.tgz",
+ "integrity": "sha512-oKkx9z9Kwg40NtcIajF9uOXhxiyTZrrm9nmIJ4UjkU2IdHpd4QVLbCc/5hZN/y0C6qzi2Zlxyr9TGddQx2vx2A==",
+ "requires": {
+ "@babel/runtime": "^7.21.0"
+ }
+ },
+ "@mui/material": {
+ "version": "5.13.5",
+ "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.13.5.tgz",
+ "integrity": "sha512-eMay+Ue1OYXOFMQA5Aau7qbAa/kWHLAyi0McsbPTWssCbGehqkF6CIdPsfVGw6tlO+xPee1hUitphHJNL3xpOQ==",
+ "requires": {
+ "@babel/runtime": "^7.21.0",
+ "@mui/base": "5.0.0-beta.4",
+ "@mui/core-downloads-tracker": "^5.13.4",
+ "@mui/system": "^5.13.5",
+ "@mui/types": "^7.2.4",
+ "@mui/utils": "^5.13.1",
+ "@types/react-transition-group": "^4.4.6",
+ "clsx": "^1.2.1",
+ "csstype": "^3.1.2",
+ "prop-types": "^15.8.1",
+ "react-is": "^18.2.0",
+ "react-transition-group": "^4.4.5"
+ }
+ },
+ "@mui/private-theming": {
+ "version": "5.13.1",
+ "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.13.1.tgz",
+ "integrity": "sha512-HW4npLUD9BAkVppOUZHeO1FOKUJWAwbpy0VQoGe3McUYTlck1HezGHQCfBQ5S/Nszi7EViqiimECVl9xi+/WjQ==",
+ "requires": {
+ "@babel/runtime": "^7.21.0",
+ "@mui/utils": "^5.13.1",
+ "prop-types": "^15.8.1"
+ }
+ },
+ "@mui/styled-engine": {
+ "version": "5.13.2",
+ "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.13.2.tgz",
+ "integrity": "sha512-VCYCU6xVtXOrIN8lcbuPmoG+u7FYuOERG++fpY74hPpEWkyFQG97F+/XfTQVYzlR2m7nPjnwVUgATcTCMEaMvw==",
+ "requires": {
+ "@babel/runtime": "^7.21.0",
+ "@emotion/cache": "^11.11.0",
+ "csstype": "^3.1.2",
+ "prop-types": "^15.8.1"
+ }
+ },
+ "@mui/system": {
+ "version": "5.13.5",
+ "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.13.5.tgz",
+ "integrity": "sha512-n0gzUxoZ2ZHZgnExkh2Htvo9uW2oakofgPRQrDoa/GQOWyRD0NH9MDszBwOb6AAoXZb+OV5TE7I4LeZ/dzgHYA==",
+ "requires": {
+ "@babel/runtime": "^7.21.0",
+ "@mui/private-theming": "^5.13.1",
+ "@mui/styled-engine": "^5.13.2",
+ "@mui/types": "^7.2.4",
+ "@mui/utils": "^5.13.1",
+ "clsx": "^1.2.1",
+ "csstype": "^3.1.2",
+ "prop-types": "^15.8.1"
+ }
+ },
+ "@mui/types": {
+ "version": "7.2.4",
+ "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.4.tgz",
+ "integrity": "sha512-LBcwa8rN84bKF+f5sDyku42w1NTxaPgPyYKODsh01U1fVstTClbUoSA96oyRBnSNyEiAVjKm6Gwx9vjR+xyqHA==",
+ "requires": {}
+ },
+ "@mui/utils": {
+ "version": "5.13.1",
+ "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.13.1.tgz",
+ "integrity": "sha512-6lXdWwmlUbEU2jUI8blw38Kt+3ly7xkmV9ljzY4Q20WhsJMWiNry9CX8M+TaP/HbtuyR8XKsdMgQW7h7MM3n3A==",
+ "requires": {
+ "@babel/runtime": "^7.21.0",
+ "@types/prop-types": "^15.7.5",
+ "@types/react-is": "^18.2.0",
+ "prop-types": "^15.8.1",
+ "react-is": "^18.2.0"
+ }
+ },
+ "@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ }
+ },
+ "@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true
+ },
+ "@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ }
+ },
+ "@popperjs/core": {
+ "version": "2.11.8",
+ "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
+ "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A=="
+ },
+ "@reduxjs/toolkit": {
+ "version": "1.9.5",
+ "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.5.tgz",
+ "integrity": "sha512-Rt97jHmfTeaxL4swLRNPD/zV4OxTes4la07Xc4hetpUW/vc75t5m1ANyxG6ymnEQ2FsLQsoMlYB2vV1sO3m8tQ==",
+ "requires": {
+ "immer": "^9.0.21",
+ "redux": "^4.2.1",
+ "redux-thunk": "^2.4.2",
+ "reselect": "^4.1.8"
+ }
+ },
+ "@remix-run/router": {
+ "version": "1.6.3",
+ "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.6.3.tgz",
+ "integrity": "sha512-EXJysQ7J3veRECd0kZFQwYYd5sJMcq2O/m60zu1W2l3oVQ9xtub8jTOtYRE0+M2iomyG/W3Ps7+vp2kna0C27Q=="
+ },
+ "@rollup/rollup-android-arm-eabi": {
+ "version": "4.14.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.14.1.tgz",
+ "integrity": "sha512-fH8/o8nSUek8ceQnT7K4EQbSiV7jgkHq81m9lWZFIXjJ7lJzpWXbQFpT/Zh6OZYnpFykvzC3fbEvEAFZu03dPA==",
+ "dev": true,
+ "optional": true
+ },
+ "@rollup/rollup-android-arm64": {
+ "version": "4.14.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.14.1.tgz",
+ "integrity": "sha512-Y/9OHLjzkunF+KGEoJr3heiD5X9OLa8sbT1lm0NYeKyaM3oMhhQFvPB0bNZYJwlq93j8Z6wSxh9+cyKQaxS7PQ==",
+ "dev": true,
+ "optional": true
+ },
+ "@rollup/rollup-darwin-arm64": {
+ "version": "4.14.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.14.1.tgz",
+ "integrity": "sha512-+kecg3FY84WadgcuSVm6llrABOdQAEbNdnpi5X3UwWiFVhZIZvKgGrF7kmLguvxHNQy+UuRV66cLVl3S+Rkt+Q==",
+ "dev": true,
+ "optional": true
+ },
+ "@rollup/rollup-darwin-x64": {
+ "version": "4.14.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.14.1.tgz",
+ "integrity": "sha512-2pYRzEjVqq2TB/UNv47BV/8vQiXkFGVmPFwJb+1E0IFFZbIX8/jo1olxqqMbo6xCXf8kabANhp5bzCij2tFLUA==",
+ "dev": true,
+ "optional": true
+ },
+ "@rollup/rollup-linux-arm-gnueabihf": {
+ "version": "4.14.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.14.1.tgz",
+ "integrity": "sha512-mS6wQ6Do6/wmrF9aTFVpIJ3/IDXhg1EZcQFYHZLHqw6AzMBjTHWnCG35HxSqUNphh0EHqSM6wRTT8HsL1C0x5g==",
+ "dev": true,
+ "optional": true
+ },
+ "@rollup/rollup-linux-arm64-gnu": {
+ "version": "4.14.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.14.1.tgz",
+ "integrity": "sha512-p9rGKYkHdFMzhckOTFubfxgyIO1vw//7IIjBBRVzyZebWlzRLeNhqxuSaZ7kCEKVkm/kuC9fVRW9HkC/zNRG2w==",
+ "dev": true,
+ "optional": true
+ },
+ "@rollup/rollup-linux-arm64-musl": {
+ "version": "4.14.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.14.1.tgz",
+ "integrity": "sha512-nDY6Yz5xS/Y4M2i9JLQd3Rofh5OR8Bn8qe3Mv/qCVpHFlwtZSBYSPaU4mrGazWkXrdQ98GB//H0BirGR/SKFSw==",
+ "dev": true,
+ "optional": true
+ },
+ "@rollup/rollup-linux-powerpc64le-gnu": {
+ "version": "4.14.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.14.1.tgz",
+ "integrity": "sha512-im7HE4VBL+aDswvcmfx88Mp1soqL9OBsdDBU8NqDEYtkri0qV0THhQsvZtZeNNlLeCUQ16PZyv7cqutjDF35qw==",
+ "dev": true,
+ "optional": true
+ },
+ "@rollup/rollup-linux-riscv64-gnu": {
+ "version": "4.14.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.14.1.tgz",
+ "integrity": "sha512-RWdiHuAxWmzPJgaHJdpvUUlDz8sdQz4P2uv367T2JocdDa98iRw2UjIJ4QxSyt077mXZT2X6pKfT2iYtVEvOFw==",
+ "dev": true,
+ "optional": true
+ },
+ "@rollup/rollup-linux-s390x-gnu": {
+ "version": "4.14.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.14.1.tgz",
+ "integrity": "sha512-VMgaGQ5zRX6ZqV/fas65/sUGc9cPmsntq2FiGmayW9KMNfWVG/j0BAqImvU4KTeOOgYSf1F+k6at1UfNONuNjA==",
+ "dev": true,
+ "optional": true
+ },
+ "@rollup/rollup-linux-x64-gnu": {
+ "version": "4.14.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.14.1.tgz",
+ "integrity": "sha512-9Q7DGjZN+hTdJomaQ3Iub4m6VPu1r94bmK2z3UeWP3dGUecRC54tmVu9vKHTm1bOt3ASoYtEz6JSRLFzrysKlA==",
+ "dev": true,
+ "optional": true
+ },
+ "@rollup/rollup-linux-x64-musl": {
+ "version": "4.14.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.14.1.tgz",
+ "integrity": "sha512-JNEG/Ti55413SsreTguSx0LOVKX902OfXIKVg+TCXO6Gjans/k9O6ww9q3oLGjNDaTLxM+IHFMeXy/0RXL5R/g==",
+ "dev": true,
+ "optional": true
+ },
+ "@rollup/rollup-win32-arm64-msvc": {
+ "version": "4.14.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.14.1.tgz",
+ "integrity": "sha512-ryS22I9y0mumlLNwDFYZRDFLwWh3aKaC72CWjFcFvxK0U6v/mOkM5Up1bTbCRAhv3kEIwW2ajROegCIQViUCeA==",
+ "dev": true,
+ "optional": true
+ },
+ "@rollup/rollup-win32-ia32-msvc": {
+ "version": "4.14.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.14.1.tgz",
+ "integrity": "sha512-TdloItiGk+T0mTxKx7Hp279xy30LspMso+GzQvV2maYePMAWdmrzqSNZhUpPj3CGw12aGj57I026PgLCTu8CGg==",
+ "dev": true,
+ "optional": true
+ },
+ "@rollup/rollup-win32-x64-msvc": {
+ "version": "4.14.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.14.1.tgz",
+ "integrity": "sha512-wQGI+LY/Py20zdUPq+XCem7JcPOyzIJBm3dli+56DJsQOHbnXZFEwgmnC6el1TPAfC8lBT3m+z69RmLykNUbew==",
+ "dev": true,
+ "optional": true
+ },
+ "@types/estree": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
+ "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==",
+ "dev": true
+ },
+ "@types/hoist-non-react-statics": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz",
+ "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==",
+ "requires": {
+ "@types/react": "*",
+ "hoist-non-react-statics": "^3.3.0"
+ }
+ },
+ "@types/json-schema": {
+ "version": "7.0.12",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz",
+ "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==",
+ "dev": true
+ },
+ "@types/parse-json": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz",
+ "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA=="
+ },
+ "@types/prop-types": {
+ "version": "15.7.5",
+ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
+ "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w=="
+ },
+ "@types/quill": {
+ "version": "1.3.10",
+ "resolved": "https://registry.npmjs.org/@types/quill/-/quill-1.3.10.tgz",
+ "integrity": "sha512-IhW3fPW+bkt9MLNlycw8u8fWb7oO7W5URC9MfZYHBlA24rex9rs23D5DETChu1zvgVdc5ka64ICjJOgQMr6Shw==",
+ "requires": {
+ "parchment": "^1.1.2"
+ }
+ },
+ "@types/react": {
+ "version": "18.2.13",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.13.tgz",
+ "integrity": "sha512-vJ+zElvi/Zn9cVXB5slX2xL8PZodPCwPRDpittQdw43JR2AJ5k3vKdgJJyneV/cYgIbLQUwXa9JVDvUZXGba+Q==",
+ "requires": {
+ "@types/prop-types": "*",
+ "@types/scheduler": "*",
+ "csstype": "^3.0.2"
+ }
+ },
+ "@types/react-dom": {
+ "version": "18.2.6",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.6.tgz",
+ "integrity": "sha512-2et4PDvg6PVCyS7fuTc4gPoksV58bW0RwSxWKcPRcHZf0PRUGq03TKcD/rUHe3azfV6/5/biUBJw+HhCQjaP0A==",
+ "devOptional": true,
+ "requires": {
+ "@types/react": "*"
+ }
+ },
+ "@types/react-is": {
+ "version": "18.2.1",
+ "resolved": "https://registry.npmjs.org/@types/react-is/-/react-is-18.2.1.tgz",
+ "integrity": "sha512-wyUkmaaSZEzFZivD8F2ftSyAfk6L+DfFliVj/mYdOXbVjRcS87fQJLTnhk6dRZPuJjI+9g6RZJO4PNCngUrmyw==",
+ "requires": {
+ "@types/react": "*"
+ }
+ },
+ "@types/react-transition-group": {
+ "version": "4.4.6",
+ "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.6.tgz",
+ "integrity": "sha512-VnCdSxfcm08KjsJVQcfBmhEQAPnLB8G08hAxn39azX1qYBQ/5RVQuoHuKIcfKOdncuaUvEpFKFzEvbtIMsfVew==",
+ "requires": {
+ "@types/react": "*"
+ }
+ },
+ "@types/scheduler": {
+ "version": "0.16.3",
+ "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz",
+ "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ=="
+ },
+ "@types/semver": {
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz",
+ "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==",
+ "dev": true
+ },
+ "@types/use-sync-external-store": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz",
+ "integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA=="
+ },
+ "@typescript-eslint/eslint-plugin": {
+ "version": "5.60.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.60.0.tgz",
+ "integrity": "sha512-78B+anHLF1TI8Jn/cD0Q00TBYdMgjdOn980JfAVa9yw5sop8nyTfVOQAv6LWywkOGLclDBtv5z3oxN4w7jxyNg==",
+ "dev": true,
+ "requires": {
+ "@eslint-community/regexpp": "^4.4.0",
+ "@typescript-eslint/scope-manager": "5.60.0",
+ "@typescript-eslint/type-utils": "5.60.0",
+ "@typescript-eslint/utils": "5.60.0",
+ "debug": "^4.3.4",
+ "grapheme-splitter": "^1.0.4",
+ "ignore": "^5.2.0",
+ "natural-compare-lite": "^1.4.0",
+ "semver": "^7.3.7",
+ "tsutils": "^3.21.0"
+ }
+ },
+ "@typescript-eslint/parser": {
+ "version": "5.60.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.60.0.tgz",
+ "integrity": "sha512-jBONcBsDJ9UoTWrARkRRCgDz6wUggmH5RpQVlt7BimSwaTkTjwypGzKORXbR4/2Hqjk9hgwlon2rVQAjWNpkyQ==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/scope-manager": "5.60.0",
+ "@typescript-eslint/types": "5.60.0",
+ "@typescript-eslint/typescript-estree": "5.60.0",
+ "debug": "^4.3.4"
+ }
+ },
+ "@typescript-eslint/scope-manager": {
+ "version": "5.60.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.60.0.tgz",
+ "integrity": "sha512-hakuzcxPwXi2ihf9WQu1BbRj1e/Pd8ZZwVTG9kfbxAMZstKz8/9OoexIwnmLzShtsdap5U/CoQGRCWlSuPbYxQ==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/types": "5.60.0",
+ "@typescript-eslint/visitor-keys": "5.60.0"
+ }
+ },
+ "@typescript-eslint/type-utils": {
+ "version": "5.60.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.60.0.tgz",
+ "integrity": "sha512-X7NsRQddORMYRFH7FWo6sA9Y/zbJ8s1x1RIAtnlj6YprbToTiQnM6vxcMu7iYhdunmoC0rUWlca13D5DVHkK2g==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/typescript-estree": "5.60.0",
+ "@typescript-eslint/utils": "5.60.0",
+ "debug": "^4.3.4",
+ "tsutils": "^3.21.0"
+ }
+ },
+ "@typescript-eslint/types": {
+ "version": "5.60.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.60.0.tgz",
+ "integrity": "sha512-ascOuoCpNZBccFVNJRSC6rPq4EmJ2NkuoKnd6LDNyAQmdDnziAtxbCGWCbefG1CNzmDvd05zO36AmB7H8RzKPA==",
+ "dev": true
+ },
+ "@typescript-eslint/typescript-estree": {
+ "version": "5.60.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.60.0.tgz",
+ "integrity": "sha512-R43thAuwarC99SnvrBmh26tc7F6sPa2B3evkXp/8q954kYL6Ro56AwASYWtEEi+4j09GbiNAHqYwNNZuNlARGQ==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/types": "5.60.0",
+ "@typescript-eslint/visitor-keys": "5.60.0",
+ "debug": "^4.3.4",
+ "globby": "^11.1.0",
+ "is-glob": "^4.0.3",
+ "semver": "^7.3.7",
+ "tsutils": "^3.21.0"
+ }
+ },
+ "@typescript-eslint/utils": {
+ "version": "5.60.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.60.0.tgz",
+ "integrity": "sha512-ba51uMqDtfLQ5+xHtwlO84vkdjrqNzOnqrnwbMHMRY8Tqeme8C2Q8Fc7LajfGR+e3/4LoYiWXUM6BpIIbHJ4hQ==",
+ "dev": true,
+ "requires": {
+ "@eslint-community/eslint-utils": "^4.2.0",
+ "@types/json-schema": "^7.0.9",
+ "@types/semver": "^7.3.12",
+ "@typescript-eslint/scope-manager": "5.60.0",
+ "@typescript-eslint/types": "5.60.0",
+ "@typescript-eslint/typescript-estree": "5.60.0",
+ "eslint-scope": "^5.1.1",
+ "semver": "^7.3.7"
+ }
+ },
+ "@typescript-eslint/visitor-keys": {
+ "version": "5.60.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.60.0.tgz",
+ "integrity": "sha512-wm9Uz71SbCyhUKgcaPRauBdTegUyY/ZWl8gLwD/i/ybJqscrrdVSFImpvUz16BLPChIeKBK5Fa9s6KDQjsjyWw==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/types": "5.60.0",
+ "eslint-visitor-keys": "^3.3.0"
+ }
+ },
+ "@vitejs/plugin-react": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.0.1.tgz",
+ "integrity": "sha512-g25lL98essfeSj43HJ0o4DMp0325XK0ITkxpgChzJU/CyemgyChtlxfnRbjfwxDGCTRxTiXtQAsdebQXKMRSOA==",
+ "dev": true,
+ "requires": {
+ "@babel/core": "^7.22.5",
+ "@babel/plugin-transform-react-jsx-self": "^7.22.5",
+ "@babel/plugin-transform-react-jsx-source": "^7.22.5",
+ "react-refresh": "^0.14.0"
+ }
+ },
+ "acorn": {
+ "version": "8.9.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.9.0.tgz",
+ "integrity": "sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ==",
+ "dev": true
+ },
+ "acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "requires": {}
+ },
+ "ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "requires": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "requires": {
+ "color-convert": "^1.9.0"
+ }
+ },
+ "argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true
+ },
+ "array-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+ "dev": true
+ },
+ "attr-accept": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/attr-accept/-/attr-accept-2.2.2.tgz",
+ "integrity": "sha512-7prDjvt9HmqiZ0cl5CRjtS84sEyhsHP2coDkaZKRKVfCDo9s7iw7ChVmar78Gu9pC4SoR/28wFu/G5JJhTnqEg=="
+ },
+ "babel-plugin-macros": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz",
+ "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==",
+ "requires": {
+ "@babel/runtime": "^7.12.5",
+ "cosmiconfig": "^7.0.0",
+ "resolve": "^1.19.0"
+ }
+ },
+ "balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true
+ },
+ "blueimp-canvas-to-blob": {
+ "version": "3.29.0",
+ "resolved": "https://registry.npmjs.org/blueimp-canvas-to-blob/-/blueimp-canvas-to-blob-3.29.0.tgz",
+ "integrity": "sha512-0pcSSGxC0QxT+yVkivxIqW0Y4VlO2XSDPofBAqoJ1qJxgH9eiUDLv50Rixij2cDuEfx4M6DpD9UGZpRhT5Q8qg=="
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dev": true,
+ "requires": {
+ "fill-range": "^7.0.1"
+ }
+ },
+ "browserslist": {
+ "version": "4.21.9",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.9.tgz",
+ "integrity": "sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==",
+ "dev": true,
+ "requires": {
+ "caniuse-lite": "^1.0.30001503",
+ "electron-to-chromium": "^1.4.431",
+ "node-releases": "^2.0.12",
+ "update-browserslist-db": "^1.0.11"
+ }
+ },
+ "call-bind": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz",
+ "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==",
+ "requires": {
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.2.1",
+ "set-function-length": "^1.1.1"
+ }
+ },
+ "callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="
+ },
+ "caniuse-lite": {
+ "version": "1.0.30001505",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001505.tgz",
+ "integrity": "sha512-jaAOR5zVtxHfL0NjZyflVTtXm3D3J9P15zSJ7HmQF8dSKGA6tqzQq+0ZI3xkjyQj46I4/M0K2GbMpcAFOcbr3A==",
+ "dev": true
+ },
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "dependencies": {
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="
+ }
+ }
+ },
+ "clone": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
+ "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w=="
+ },
+ "clsx": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz",
+ "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg=="
+ },
+ "color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "requires": {
+ "color-name": "1.1.3"
+ }
+ },
+ "color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
+ },
+ "compressorjs": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/compressorjs/-/compressorjs-1.2.1.tgz",
+ "integrity": "sha512-+geIjeRnPhQ+LLvvA7wxBQE5ddeLU7pJ3FsKFWirDw6veY3s9iLxAQEw7lXGHnhCJvBujEQWuNnGzZcvCvdkLQ==",
+ "requires": {
+ "blueimp-canvas-to-blob": "^3.29.0",
+ "is-blob": "^2.1.0"
+ }
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true
+ },
+ "convert-source-map": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
+ "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A=="
+ },
+ "cosmiconfig": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz",
+ "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==",
+ "requires": {
+ "@types/parse-json": "^4.0.0",
+ "import-fresh": "^3.2.1",
+ "parse-json": "^5.0.0",
+ "path-type": "^4.0.0",
+ "yaml": "^1.10.0"
+ }
+ },
+ "cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "dev": true,
+ "requires": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ }
+ },
+ "csstype": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz",
+ "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ=="
+ },
+ "debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dev": true,
+ "requires": {
+ "ms": "2.1.2"
+ }
+ },
+ "deep-equal": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.2.tgz",
+ "integrity": "sha512-5tdhKF6DbU7iIzrIOa1AOUt39ZRm13cmL1cGEh//aqR8x9+tNfbywRf0n5FD/18OKMdo7DNEtrX2t22ZAkI+eg==",
+ "requires": {
+ "is-arguments": "^1.1.1",
+ "is-date-object": "^1.0.5",
+ "is-regex": "^1.1.4",
+ "object-is": "^1.1.5",
+ "object-keys": "^1.1.1",
+ "regexp.prototype.flags": "^1.5.1"
+ }
+ },
+ "deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true
+ },
+ "define-data-property": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz",
+ "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==",
+ "requires": {
+ "get-intrinsic": "^1.2.1",
+ "gopd": "^1.0.1",
+ "has-property-descriptors": "^1.0.0"
+ }
+ },
+ "define-properties": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
+ "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
+ "requires": {
+ "define-data-property": "^1.0.1",
+ "has-property-descriptors": "^1.0.0",
+ "object-keys": "^1.1.1"
+ }
+ },
+ "dir-glob": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+ "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+ "dev": true,
+ "requires": {
+ "path-type": "^4.0.0"
+ }
+ },
+ "doctrine": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+ "dev": true,
+ "requires": {
+ "esutils": "^2.0.2"
+ }
+ },
+ "dom-helpers": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
+ "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
+ "requires": {
+ "@babel/runtime": "^7.8.7",
+ "csstype": "^3.0.2"
+ }
+ },
+ "dompurify": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.6.tgz",
+ "integrity": "sha512-ilkD8YEnnGh1zJ240uJsW7AzE+2qpbOUYjacomn3AvJ6J4JhKGSZ2nh4wUIXPZrEPppaCLx5jFe8T89Rk8tQ7w=="
+ },
+ "electron-to-chromium": {
+ "version": "1.4.434",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.434.tgz",
+ "integrity": "sha512-5Gvm09UZTQRaWrimRtWRO5rvaX6Kpk5WHAPKDa7A4Gj6NIPuJ8w8WNpnxCXdd+CJJt6RBU6tUw0KyULoW6XuHw==",
+ "dev": true
+ },
+ "error-ex": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+ "requires": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "esbuild": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz",
+ "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==",
+ "dev": true,
+ "requires": {
+ "@esbuild/aix-ppc64": "0.20.2",
+ "@esbuild/android-arm": "0.20.2",
+ "@esbuild/android-arm64": "0.20.2",
+ "@esbuild/android-x64": "0.20.2",
+ "@esbuild/darwin-arm64": "0.20.2",
+ "@esbuild/darwin-x64": "0.20.2",
+ "@esbuild/freebsd-arm64": "0.20.2",
+ "@esbuild/freebsd-x64": "0.20.2",
+ "@esbuild/linux-arm": "0.20.2",
+ "@esbuild/linux-arm64": "0.20.2",
+ "@esbuild/linux-ia32": "0.20.2",
+ "@esbuild/linux-loong64": "0.20.2",
+ "@esbuild/linux-mips64el": "0.20.2",
+ "@esbuild/linux-ppc64": "0.20.2",
+ "@esbuild/linux-riscv64": "0.20.2",
+ "@esbuild/linux-s390x": "0.20.2",
+ "@esbuild/linux-x64": "0.20.2",
+ "@esbuild/netbsd-x64": "0.20.2",
+ "@esbuild/openbsd-x64": "0.20.2",
+ "@esbuild/sunos-x64": "0.20.2",
+ "@esbuild/win32-arm64": "0.20.2",
+ "@esbuild/win32-ia32": "0.20.2",
+ "@esbuild/win32-x64": "0.20.2"
+ }
+ },
+ "escalade": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
+ "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
+ "dev": true
+ },
+ "escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="
+ },
+ "eslint": {
+ "version": "8.43.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.43.0.tgz",
+ "integrity": "sha512-aaCpf2JqqKesMFGgmRPessmVKjcGXqdlAYLLC3THM8t5nBRZRQ+st5WM/hoJXkdioEXLLbXgclUpM0TXo5HX5Q==",
+ "dev": true,
+ "requires": {
+ "@eslint-community/eslint-utils": "^4.2.0",
+ "@eslint-community/regexpp": "^4.4.0",
+ "@eslint/eslintrc": "^2.0.3",
+ "@eslint/js": "8.43.0",
+ "@humanwhocodes/config-array": "^0.11.10",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@nodelib/fs.walk": "^1.2.8",
+ "ajv": "^6.10.0",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.2",
+ "debug": "^4.3.2",
+ "doctrine": "^3.0.0",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^7.2.0",
+ "eslint-visitor-keys": "^3.4.1",
+ "espree": "^9.5.2",
+ "esquery": "^1.4.2",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^6.0.1",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "globals": "^13.19.0",
+ "graphemer": "^1.4.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.0.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "is-path-inside": "^3.0.3",
+ "js-yaml": "^4.1.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "levn": "^0.4.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.1",
+ "strip-ansi": "^6.0.1",
+ "strip-json-comments": "^3.1.0",
+ "text-table": "^0.2.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
+ },
+ "chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "eslint-scope": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz",
+ "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==",
+ "dev": true,
+ "requires": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ }
+ },
+ "estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true
+ },
+ "globals": {
+ "version": "13.20.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz",
+ "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==",
+ "dev": true,
+ "requires": {
+ "type-fest": "^0.20.2"
+ }
+ },
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ }
+ }
+ },
+ "eslint-plugin-react-hooks": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz",
+ "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==",
+ "dev": true,
+ "requires": {}
+ },
+ "eslint-plugin-react-refresh": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.3.5.tgz",
+ "integrity": "sha512-61qNIsc7fo9Pp/mju0J83kzvLm0Bsayu7OQSLEoJxLDCBjIIyb87bkzufoOvdDxLkSlMfkF7UxomC4+eztUBSA==",
+ "dev": true,
+ "requires": {}
+ },
+ "eslint-scope": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
+ "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
+ "dev": true,
+ "requires": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^4.1.1"
+ }
+ },
+ "eslint-visitor-keys": {
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz",
+ "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==",
+ "dev": true
+ },
+ "espree": {
+ "version": "9.5.2",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz",
+ "integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==",
+ "dev": true,
+ "requires": {
+ "acorn": "^8.8.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^3.4.1"
+ }
+ },
+ "esquery": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
+ "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
+ "dev": true,
+ "requires": {
+ "estraverse": "^5.1.0"
+ },
+ "dependencies": {
+ "estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true
+ }
+ }
+ },
+ "esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "requires": {
+ "estraverse": "^5.2.0"
+ },
+ "dependencies": {
+ "estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true
+ }
+ }
+ },
+ "estraverse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+ "dev": true
+ },
+ "esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true
+ },
+ "eventemitter3": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-2.0.3.tgz",
+ "integrity": "sha512-jLN68Dx5kyFHaePoXWPsCGW5qdyZQtLYHkxkg02/Mz6g0kYpDx4FyP6XfArhQdlOC4b8Mv+EMxPo/8La7Tzghg=="
+ },
+ "extend": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
+ },
+ "fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true
+ },
+ "fast-diff": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.1.2.tgz",
+ "integrity": "sha512-KaJUt+M9t1qaIteSvjc6P3RbMdXsNhK61GRftR6SNxqmhthcd9MGIi4T+o0jD8LUSpSnSKXE20nLtJ3fOHxQig=="
+ },
+ "fast-glob": {
+ "version": "3.2.12",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz",
+ "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ },
+ "dependencies": {
+ "glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "requires": {
+ "is-glob": "^4.0.1"
+ }
+ }
+ }
+ },
+ "fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true
+ },
+ "fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true
+ },
+ "fast-memoize": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/fast-memoize/-/fast-memoize-2.5.2.tgz",
+ "integrity": "sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw=="
+ },
+ "fastq": {
+ "version": "1.15.0",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
+ "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==",
+ "dev": true,
+ "requires": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "file-entry-cache": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+ "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+ "dev": true,
+ "requires": {
+ "flat-cache": "^3.0.4"
+ }
+ },
+ "file-selector": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/file-selector/-/file-selector-0.6.0.tgz",
+ "integrity": "sha512-QlZ5yJC0VxHxQQsQhXvBaC7VRJ2uaxTf+Tfpu4Z/OcVQJVpZO+DGU0rkoVW5ce2SccxugvpBJoMvUs59iILYdw==",
+ "requires": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "dev": true,
+ "requires": {
+ "to-regex-range": "^5.0.1"
+ }
+ },
+ "find-root": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz",
+ "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng=="
+ },
+ "find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ }
+ },
+ "flat-cache": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
+ "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==",
+ "dev": true,
+ "requires": {
+ "flatted": "^3.1.0",
+ "rimraf": "^3.0.2"
+ }
+ },
+ "flatted": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz",
+ "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==",
+ "dev": true
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "dev": true
+ },
+ "fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "dev": true,
+ "optional": true
+ },
+ "function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="
+ },
+ "functions-have-names": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
+ "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ=="
+ },
+ "gensync": {
+ "version": "1.0.0-beta.2",
+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
+ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+ "dev": true
+ },
+ "get-intrinsic": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz",
+ "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==",
+ "requires": {
+ "function-bind": "^1.1.2",
+ "has-proto": "^1.0.1",
+ "has-symbols": "^1.0.3",
+ "hasown": "^2.0.0"
+ }
+ },
+ "glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "requires": {
+ "is-glob": "^4.0.3"
+ }
+ },
+ "globals": {
+ "version": "11.12.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+ "dev": true
+ },
+ "globby": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
+ "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
+ "dev": true,
+ "requires": {
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.2.9",
+ "ignore": "^5.2.0",
+ "merge2": "^1.4.1",
+ "slash": "^3.0.0"
+ }
+ },
+ "gopd": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
+ "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
+ "requires": {
+ "get-intrinsic": "^1.1.3"
+ }
+ },
+ "grapheme-splitter": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz",
+ "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==",
+ "dev": true
+ },
+ "graphemer": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
+ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
+ "dev": true
+ },
+ "has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "requires": {
+ "function-bind": "^1.1.1"
+ }
+ },
+ "has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="
+ },
+ "has-property-descriptors": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz",
+ "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==",
+ "requires": {
+ "get-intrinsic": "^1.2.2"
+ }
+ },
+ "has-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz",
+ "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg=="
+ },
+ "has-symbols": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
+ "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A=="
+ },
+ "has-tostringtag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
+ "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
+ "requires": {
+ "has-symbols": "^1.0.2"
+ }
+ },
+ "hasown": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz",
+ "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==",
+ "requires": {
+ "function-bind": "^1.1.2"
+ }
+ },
+ "hoist-non-react-statics": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
+ "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
+ "requires": {
+ "react-is": "^16.7.0"
+ },
+ "dependencies": {
+ "react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+ }
+ }
+ },
+ "ignore": {
+ "version": "5.2.4",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
+ "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
+ "dev": true
+ },
+ "immediate": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
+ "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ=="
+ },
+ "immer": {
+ "version": "9.0.21",
+ "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz",
+ "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA=="
+ },
+ "import-fresh": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+ "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+ "requires": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ }
+ },
+ "imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "dev": true,
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true
+ },
+ "is-arguments": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
+ "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==",
+ "requires": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ }
+ },
+ "is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="
+ },
+ "is-blob": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-blob/-/is-blob-2.1.0.tgz",
+ "integrity": "sha512-SZ/fTft5eUhQM6oF/ZaASFDEdbFVe89Imltn9uZr03wdKMcWNVYSMjQPFtg05QuNkt5l5c135ElvXEQG0rk4tw=="
+ },
+ "is-core-module": {
+ "version": "2.12.1",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz",
+ "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==",
+ "requires": {
+ "has": "^1.0.3"
+ }
+ },
+ "is-date-object": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
+ "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
+ "requires": {
+ "has-tostringtag": "^1.0.0"
+ }
+ },
+ "is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true
+ },
+ "is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^2.1.1"
+ }
+ },
+ "is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true
+ },
+ "is-path-inside": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
+ "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
+ "dev": true
+ },
+ "is-regex": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
+ "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
+ "requires": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ }
+ },
+ "isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true
+ },
+ "js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
+ },
+ "js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dev": true,
+ "requires": {
+ "argparse": "^2.0.1"
+ }
+ },
+ "jsesc": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
+ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
+ "dev": true
+ },
+ "json-parse-even-better-errors": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
+ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="
+ },
+ "json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true
+ },
+ "json5": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+ "dev": true
+ },
+ "levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "requires": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ }
+ },
+ "lie": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz",
+ "integrity": "sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==",
+ "requires": {
+ "immediate": "~3.0.5"
+ }
+ },
+ "lines-and-columns": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
+ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="
+ },
+ "localforage": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/localforage/-/localforage-1.10.0.tgz",
+ "integrity": "sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==",
+ "requires": {
+ "lie": "3.1.1"
+ }
+ },
+ "locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "requires": {
+ "p-locate": "^5.0.0"
+ }
+ },
+ "lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
+ },
+ "lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true
+ },
+ "loose-envify": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "requires": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ }
+ },
+ "lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "dev": true,
+ "requires": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true
+ },
+ "micromatch": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
+ "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+ "dev": true,
+ "requires": {
+ "braces": "^3.0.2",
+ "picomatch": "^2.3.1"
+ }
+ },
+ "minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "moment": {
+ "version": "2.29.4",
+ "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
+ "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w=="
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "nanoid": {
+ "version": "3.3.7",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
+ "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
+ "dev": true
+ },
+ "natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true
+ },
+ "natural-compare-lite": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz",
+ "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==",
+ "dev": true
+ },
+ "node-releases": {
+ "version": "2.0.12",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.12.tgz",
+ "integrity": "sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ==",
+ "dev": true
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="
+ },
+ "object-is": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz",
+ "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==",
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3"
+ }
+ },
+ "object-keys": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dev": true,
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "optionator": {
+ "version": "0.9.1",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
+ "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==",
+ "dev": true,
+ "requires": {
+ "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.3"
+ }
+ },
+ "p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "requires": {
+ "yocto-queue": "^0.1.0"
+ }
+ },
+ "p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "requires": {
+ "p-limit": "^3.0.2"
+ }
+ },
+ "parchment": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/parchment/-/parchment-1.1.4.tgz",
+ "integrity": "sha512-J5FBQt/pM2inLzg4hEWmzQx/8h8D0CiDxaG3vyp9rKrQRSDgBlhjdP5jQGgosEajXPSQouXGHOmVdgo7QmJuOg=="
+ },
+ "parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "requires": {
+ "callsites": "^3.0.0"
+ }
+ },
+ "parse-json": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
+ "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
+ "requires": {
+ "@babel/code-frame": "^7.0.0",
+ "error-ex": "^1.3.1",
+ "json-parse-even-better-errors": "^2.3.0",
+ "lines-and-columns": "^1.1.6"
+ }
+ },
+ "path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "dev": true
+ },
+ "path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true
+ },
+ "path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
+ },
+ "path-type": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw=="
+ },
+ "picocolors": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
+ "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
+ "dev": true
+ },
+ "picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true
+ },
+ "postcss": {
+ "version": "8.4.38",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz",
+ "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==",
+ "dev": true,
+ "requires": {
+ "nanoid": "^3.3.7",
+ "picocolors": "^1.0.0",
+ "source-map-js": "^1.2.0"
+ }
+ },
+ "prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true
+ },
+ "prettier": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.4.tgz",
+ "integrity": "sha512-FWu1oLHKCrtpO1ypU6J0SbK2d9Ckwysq6bHj/uaCP26DxrPpppCLQRGVuqAxSTvhF00AcvDRyYrLNW7ocBhFFQ=="
+ },
+ "prop-types": {
+ "version": "15.8.1",
+ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
+ "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+ "requires": {
+ "loose-envify": "^1.4.0",
+ "object-assign": "^4.1.1",
+ "react-is": "^16.13.1"
+ },
+ "dependencies": {
+ "react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+ }
+ }
+ },
+ "punycode": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
+ "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==",
+ "dev": true
+ },
+ "queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "dev": true
+ },
+ "quill": {
+ "version": "1.3.7",
+ "resolved": "https://registry.npmjs.org/quill/-/quill-1.3.7.tgz",
+ "integrity": "sha512-hG/DVzh/TiknWtE6QmWAF/pxoZKYxfe3J/d/+ShUWkDvvkZQVTPeVmUJVu1uE6DDooC4fWTiCLh84ul89oNz5g==",
+ "requires": {
+ "clone": "^2.1.1",
+ "deep-equal": "^1.0.1",
+ "eventemitter3": "^2.0.3",
+ "extend": "^3.0.2",
+ "parchment": "^1.1.4",
+ "quill-delta": "^3.6.2"
+ }
+ },
+ "quill-delta": {
+ "version": "3.6.3",
+ "resolved": "https://registry.npmjs.org/quill-delta/-/quill-delta-3.6.3.tgz",
+ "integrity": "sha512-wdIGBlcX13tCHOXGMVnnTVFtGRLoP0imqxM696fIPwIf5ODIYUHIvHbZcyvGlZFiFhK5XzDC2lpjbxRhnM05Tg==",
+ "requires": {
+ "deep-equal": "^1.0.1",
+ "extend": "^3.0.2",
+ "fast-diff": "1.1.2"
+ }
+ },
+ "quill-image-resize-module-react": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/quill-image-resize-module-react/-/quill-image-resize-module-react-3.0.0.tgz",
+ "integrity": "sha512-3jVChLoXh+fwEELx3OswOEEuF+1KU3r/B9RAqZ//s+d+UMduVZzUepU1g/XoxjKoBJvWD2lJwBIFBRUNb8ebCw==",
+ "requires": {
+ "lodash": "^4.17.4",
+ "quill": "^1.2.2",
+ "raw-loader": "^0.5.1"
+ }
+ },
+ "raw-loader": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-0.5.1.tgz",
+ "integrity": "sha512-sf7oGoLuaYAScB4VGr0tzetsYlS8EJH6qnTCfQ/WVEa89hALQ4RQfCKt5xCyPQKPDUbVUAIP1QsxAwfAjlDp7Q=="
+ },
+ "re-resizable": {
+ "version": "6.9.6",
+ "resolved": "https://registry.npmjs.org/re-resizable/-/re-resizable-6.9.6.tgz",
+ "integrity": "sha512-0xYKS5+Z0zk+vICQlcZW+g54CcJTTmHluA7JUUgvERDxnKAnytylcyPsA+BSFi759s5hPlHmBRegFrwXs2FuBQ==",
+ "requires": {
+ "fast-memoize": "^2.5.1"
+ }
+ },
+ "react": {
+ "version": "18.2.0",
+ "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
+ "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==",
+ "requires": {
+ "loose-envify": "^1.1.0"
+ }
+ },
+ "react-dom": {
+ "version": "18.2.0",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
+ "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==",
+ "requires": {
+ "loose-envify": "^1.1.0",
+ "scheduler": "^0.23.0"
+ }
+ },
+ "react-draggable": {
+ "version": "4.4.5",
+ "resolved": "https://registry.npmjs.org/react-draggable/-/react-draggable-4.4.5.tgz",
+ "integrity": "sha512-OMHzJdyJbYTZo4uQE393fHcqqPYsEtkjfMgvCHr6rejT+Ezn4OZbNyGH50vv+SunC1RMvwOTSWkEODQLzw1M9g==",
+ "requires": {
+ "clsx": "^1.1.1",
+ "prop-types": "^15.8.1"
+ }
+ },
+ "react-dropzone": {
+ "version": "14.2.3",
+ "resolved": "https://registry.npmjs.org/react-dropzone/-/react-dropzone-14.2.3.tgz",
+ "integrity": "sha512-O3om8I+PkFKbxCukfIR3QAGftYXDZfOE2N1mr/7qebQJHs7U+/RSL/9xomJNpRg9kM5h9soQSdf0Gc7OHF5Fug==",
+ "requires": {
+ "attr-accept": "^2.2.2",
+ "file-selector": "^0.6.0",
+ "prop-types": "^15.8.1"
+ }
+ },
+ "react-intersection-observer": {
+ "version": "9.5.0",
+ "resolved": "https://registry.npmjs.org/react-intersection-observer/-/react-intersection-observer-9.5.0.tgz",
+ "integrity": "sha512-bQbfe6Jl8KSynbWfQWz8LoGCCmG6fhsilljgc6dc1NMYpNmP20wfFsrF7CE5N9+LbWx33DUgJdkNBVhU1JzIRA==",
+ "requires": {}
+ },
+ "react-is": {
+ "version": "18.2.0",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
+ "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
+ },
+ "react-quill": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/react-quill/-/react-quill-2.0.0.tgz",
+ "integrity": "sha512-4qQtv1FtCfLgoD3PXAur5RyxuUbPXQGOHgTlFie3jtxp43mXDtzCKaOgQ3mLyZfi1PUlyjycfivKelFhy13QUg==",
+ "requires": {
+ "@types/quill": "^1.3.10",
+ "lodash": "^4.17.4",
+ "quill": "^1.3.7"
+ }
+ },
+ "react-redux": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.1.0.tgz",
+ "integrity": "sha512-CtHZzAOxi7GQvTph4dVLWwZHAWUjV2kMEQtk50OrN8z3gKxpWg3Tz7JfDw32N3Rpd7fh02z73cF6yZkK467gbQ==",
+ "requires": {
+ "@babel/runtime": "^7.12.1",
+ "@types/hoist-non-react-statics": "^3.3.1",
+ "@types/use-sync-external-store": "^0.0.3",
+ "hoist-non-react-statics": "^3.3.2",
+ "react-is": "^18.0.0",
+ "use-sync-external-store": "^1.0.0"
+ }
+ },
+ "react-refresh": {
+ "version": "0.14.0",
+ "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz",
+ "integrity": "sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==",
+ "dev": true
+ },
+ "react-rnd": {
+ "version": "10.4.1",
+ "resolved": "https://registry.npmjs.org/react-rnd/-/react-rnd-10.4.1.tgz",
+ "integrity": "sha512-0m887AjQZr6p2ADLNnipquqsDq4XJu/uqVqI3zuoGD19tRm6uB83HmZWydtkilNp5EWsOHbLGF4IjWMdd5du8Q==",
+ "requires": {
+ "re-resizable": "6.9.6",
+ "react-draggable": "4.4.5",
+ "tslib": "2.3.1"
+ },
+ "dependencies": {
+ "tslib": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
+ "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
+ }
+ }
+ },
+ "react-router": {
+ "version": "6.13.0",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.13.0.tgz",
+ "integrity": "sha512-Si6KnfEnJw7gUQkNa70dlpI1bul46FuSxX5t5WwlUBxE25DAz2BjVkwaK8Y2s242bQrZPXCpmwLPtIO5pv4tXg==",
+ "requires": {
+ "@remix-run/router": "1.6.3"
+ }
+ },
+ "react-router-dom": {
+ "version": "6.13.0",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.13.0.tgz",
+ "integrity": "sha512-6Nqoqd7fgwxxVGdbiMHTpDHCYPq62d7Wk1Of7B82vH7ZPwwsRaIa22zRZKPPg413R5REVNiyuQPKDG1bubcOFA==",
+ "requires": {
+ "@remix-run/router": "1.6.3",
+ "react-router": "6.13.0"
+ }
+ },
+ "react-toastify": {
+ "version": "9.1.3",
+ "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-9.1.3.tgz",
+ "integrity": "sha512-fPfb8ghtn/XMxw3LkxQBk3IyagNpF/LIKjOBflbexr2AWxAH1MJgvnESwEwBn9liLFXgTKWgBSdZpw9m4OTHTg==",
+ "requires": {
+ "clsx": "^1.1.1"
+ }
+ },
+ "react-transition-group": {
+ "version": "4.4.5",
+ "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
+ "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==",
+ "requires": {
+ "@babel/runtime": "^7.5.5",
+ "dom-helpers": "^5.0.1",
+ "loose-envify": "^1.4.0",
+ "prop-types": "^15.6.2"
+ }
+ },
+ "redux": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz",
+ "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==",
+ "requires": {
+ "@babel/runtime": "^7.9.2"
+ }
+ },
+ "redux-thunk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz",
+ "integrity": "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==",
+ "requires": {}
+ },
+ "regenerator-runtime": {
+ "version": "0.13.11",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
+ "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="
+ },
+ "regexp.prototype.flags": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz",
+ "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==",
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "set-function-name": "^2.0.0"
+ }
+ },
+ "reselect": {
+ "version": "4.1.8",
+ "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz",
+ "integrity": "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ=="
+ },
+ "resolve": {
+ "version": "1.22.2",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz",
+ "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==",
+ "requires": {
+ "is-core-module": "^2.11.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ }
+ },
+ "resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="
+ },
+ "reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "dev": true
+ },
+ "rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "dev": true,
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ },
+ "rollup": {
+ "version": "4.14.1",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.14.1.tgz",
+ "integrity": "sha512-4LnHSdd3QK2pa1J6dFbfm1HN0D7vSK/ZuZTsdyUAlA6Rr1yTouUTL13HaDOGJVgby461AhrNGBS7sCGXXtT+SA==",
+ "dev": true,
+ "requires": {
+ "@rollup/rollup-android-arm-eabi": "4.14.1",
+ "@rollup/rollup-android-arm64": "4.14.1",
+ "@rollup/rollup-darwin-arm64": "4.14.1",
+ "@rollup/rollup-darwin-x64": "4.14.1",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.14.1",
+ "@rollup/rollup-linux-arm64-gnu": "4.14.1",
+ "@rollup/rollup-linux-arm64-musl": "4.14.1",
+ "@rollup/rollup-linux-powerpc64le-gnu": "4.14.1",
+ "@rollup/rollup-linux-riscv64-gnu": "4.14.1",
+ "@rollup/rollup-linux-s390x-gnu": "4.14.1",
+ "@rollup/rollup-linux-x64-gnu": "4.14.1",
+ "@rollup/rollup-linux-x64-musl": "4.14.1",
+ "@rollup/rollup-win32-arm64-msvc": "4.14.1",
+ "@rollup/rollup-win32-ia32-msvc": "4.14.1",
+ "@rollup/rollup-win32-x64-msvc": "4.14.1",
+ "@types/estree": "1.0.5",
+ "fsevents": "~2.3.2"
+ }
+ },
+ "run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "dev": true,
+ "requires": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "scheduler": {
+ "version": "0.23.0",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz",
+ "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==",
+ "requires": {
+ "loose-envify": "^1.1.0"
+ }
+ },
+ "semver": {
+ "version": "7.5.2",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.2.tgz",
+ "integrity": "sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^6.0.0"
+ },
+ "dependencies": {
+ "lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "requires": {
+ "yallist": "^4.0.0"
+ }
+ },
+ "yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ }
+ }
+ },
+ "set-function-length": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz",
+ "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==",
+ "requires": {
+ "define-data-property": "^1.1.1",
+ "get-intrinsic": "^1.2.1",
+ "gopd": "^1.0.1",
+ "has-property-descriptors": "^1.0.0"
+ }
+ },
+ "set-function-name": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz",
+ "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==",
+ "requires": {
+ "define-data-property": "^1.0.1",
+ "functions-have-names": "^1.2.3",
+ "has-property-descriptors": "^1.0.0"
+ }
+ },
+ "shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "requires": {
+ "shebang-regex": "^3.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true
+ },
+ "short-unique-id": {
+ "version": "4.4.4",
+ "resolved": "https://registry.npmjs.org/short-unique-id/-/short-unique-id-4.4.4.tgz",
+ "integrity": "sha512-oLF1NCmtbiTWl2SqdXZQbo5KM1b7axdp0RgQLq8qCBBLoq+o3A5wmLrNM6bZIh54/a8BJ3l69kTXuxwZ+XCYuw=="
+ },
+ "slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ=="
+ },
+ "source-map-js": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz",
+ "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==",
+ "dev": true
+ },
+ "strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^5.0.1"
+ }
+ },
+ "strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true
+ },
+ "stylis": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz",
+ "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw=="
+ },
+ "supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ },
+ "supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="
+ },
+ "text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
+ "dev": true
+ },
+ "to-fast-properties": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
+ "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog=="
+ },
+ "to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "requires": {
+ "is-number": "^7.0.0"
+ }
+ },
+ "ts-key-enum": {
+ "version": "2.0.12",
+ "resolved": "https://registry.npmjs.org/ts-key-enum/-/ts-key-enum-2.0.12.tgz",
+ "integrity": "sha512-Ety4IvKMaeG34AyXMp5r11XiVZNDRL+XWxXbVVJjLvq2vxKRttEANBE7Za1bxCAZRdH2/sZT6jFyyTWxXz28hw=="
+ },
+ "tslib": {
+ "version": "2.5.3",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz",
+ "integrity": "sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w=="
+ },
+ "tsutils": {
+ "version": "3.21.0",
+ "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
+ "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.8.1"
+ },
+ "dependencies": {
+ "tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+ "dev": true
+ }
+ }
+ },
+ "type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "requires": {
+ "prelude-ls": "^1.2.1"
+ }
+ },
+ "type-fest": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+ "dev": true
+ },
+ "typescript": {
+ "version": "5.1.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.3.tgz",
+ "integrity": "sha512-XH627E9vkeqhlZFQuL+UsyAXEnibT0kWR2FWONlr4sTjvxyJYnyefgrkyECLzM5NenmKzRAy2rR/OlYLA1HkZw==",
+ "dev": true
+ },
+ "update-browserslist-db": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz",
+ "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==",
+ "dev": true,
+ "requires": {
+ "escalade": "^3.1.1",
+ "picocolors": "^1.0.0"
+ }
+ },
+ "uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "requires": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "use-sync-external-store": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
+ "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==",
+ "requires": {}
+ },
+ "vite": {
+ "version": "6.0.0-alpha.1",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-6.0.0-alpha.1.tgz",
+ "integrity": "sha512-LVvQVG3AftURxT11TgWXpfVIqBKC4D/NA5ikYQb9hDORF0hvO+gsyvNu8GR73/oag09A5JJAPAFU+r7ly4+9Lw==",
+ "dev": true,
+ "requires": {
+ "esbuild": "^0.20.1",
+ "fsevents": "~2.3.3",
+ "postcss": "^8.4.38",
+ "rollup": "^4.13.0"
+ }
+ },
+ "which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ },
+ "word-wrap": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
+ "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
+ "dev": true
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "dev": true
+ },
+ "yallist": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+ "dev": true
+ },
+ "yaml": {
+ "version": "1.10.2",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
+ "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg=="
+ },
+ "yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true
+ }
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..6f3aea4
--- /dev/null
+++ b/package.json
@@ -0,0 +1,48 @@
+{
+ "name": "qsupport",
+ "private": true,
+ "version": "1.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "tsc && vite build",
+ "lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "@emotion/react": "^11.10.6",
+ "@emotion/styled": "^11.10.6",
+ "@mui/icons-material": "^5.11.11",
+ "@mui/material": "^5.11.13",
+ "@reduxjs/toolkit": "^1.9.3",
+ "compressorjs": "^1.2.1",
+ "dompurify": "^3.0.6",
+ "localforage": "^1.10.0",
+ "moment": "^2.29.4",
+ "prettier": "^3.2.4",
+ "quill-image-resize-module-react": "^3.0.0",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
+ "react-dropzone": "^14.2.3",
+ "react-intersection-observer": "^9.4.3",
+ "react-quill": "^2.0.0",
+ "react-redux": "^8.0.5",
+ "react-rnd": "^10.4.1",
+ "react-router-dom": "^6.9.0",
+ "react-toastify": "^9.1.2",
+ "short-unique-id": "^4.4.4",
+ "ts-key-enum": "^2.0.12"
+ },
+ "devDependencies": {
+ "@types/react": "^18.0.28",
+ "@types/react-dom": "^18.0.11",
+ "@typescript-eslint/eslint-plugin": "^5.57.1",
+ "@typescript-eslint/parser": "^5.57.1",
+ "@vitejs/plugin-react": "^4.0.0",
+ "eslint": "^8.38.0",
+ "eslint-plugin-react-hooks": "^4.6.0",
+ "eslint-plugin-react-refresh": "^0.3.4",
+ "typescript": "^5.0.2",
+ "vite": "6.0.0-alpha.1"
+ }
+}
diff --git a/public/favicon.ico b/public/favicon.ico
new file mode 100644
index 0000000..86847ec
Binary files /dev/null and b/public/favicon.ico differ
diff --git a/src/App.css b/src/App.css
new file mode 100644
index 0000000..da78883
--- /dev/null
+++ b/src/App.css
@@ -0,0 +1,43 @@
+#root {
+ max-width: 1280px;
+ margin: 0 auto;
+ padding: 2rem;
+ text-align: center;
+}
+
+.logo {
+ height: 6em;
+ padding: 1.5em;
+ will-change: filter;
+ transition: filter 300ms;
+}
+.logo:hover {
+ filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+ filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+ from {
+ transform: rotate(0deg);
+ }
+ to {
+ transform: rotate(360deg);
+ }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+ a:nth-of-type(2) .logo {
+ animation: logo-spin infinite 20s linear;
+ }
+}
+
+.card {
+ padding: 2em;
+}
+
+.read-the-docs {
+ color: #888;
+}
+
diff --git a/src/App.tsx b/src/App.tsx
new file mode 100644
index 0000000..46a84ca
--- /dev/null
+++ b/src/App.tsx
@@ -0,0 +1,39 @@
+import { useState } from "react";
+import { Route, Routes } from "react-router-dom";
+import { ThemeProvider } from "@mui/material/styles";
+import { CssBaseline } from "@mui/material";
+import { darkTheme, lightTheme } from "./styles/theme";
+import { store } from "./state/store";
+import { Provider } from "react-redux";
+import GlobalWrapper from "./wrappers/GlobalWrapper";
+import Notification from "./components/common/Notification/Notification";
+import { Home } from "./pages/Home/Home";
+import { IssueContent } from "./pages/IssueContent/IssueContent.tsx";
+import DownloadWrapper from "./wrappers/DownloadWrapper";
+import { IndividualProfile } from "./pages/IndividualProfile/IndividualProfile";
+
+function App() {
+ // const themeColor = window._qdnTheme
+
+ const [theme, setTheme] = useState("dark");
+
+ return (
+
+
+
+
+ setTheme(val)}>
+
+
+ } />
+ } />
+ } />
+
+
+
+
+
+ );
+}
+
+export default App;
diff --git a/src/assets/icons/ClosedIcon.png b/src/assets/icons/ClosedIcon.png
new file mode 100644
index 0000000..4e2a8f7
Binary files /dev/null and b/src/assets/icons/ClosedIcon.png differ
diff --git a/src/assets/icons/CompleteIcon.png b/src/assets/icons/CompleteIcon.png
new file mode 100644
index 0000000..6913308
Binary files /dev/null and b/src/assets/icons/CompleteIcon.png differ
diff --git a/src/assets/icons/InProgressIcon.png b/src/assets/icons/InProgressIcon.png
new file mode 100644
index 0000000..b699642
Binary files /dev/null and b/src/assets/icons/InProgressIcon.png differ
diff --git a/src/assets/icons/OpenIcon.png b/src/assets/icons/OpenIcon.png
new file mode 100644
index 0000000..c516754
Binary files /dev/null and b/src/assets/icons/OpenIcon.png differ
diff --git a/src/assets/icons/audio.webp b/src/assets/icons/audio.webp
new file mode 100644
index 0000000..c5b4560
Binary files /dev/null and b/src/assets/icons/audio.webp differ
diff --git a/src/assets/icons/book.webp b/src/assets/icons/book.webp
new file mode 100644
index 0000000..27ea88f
Binary files /dev/null and b/src/assets/icons/book.webp differ
diff --git a/src/assets/icons/document.webp b/src/assets/icons/document.webp
new file mode 100644
index 0000000..bd863ab
Binary files /dev/null and b/src/assets/icons/document.webp differ
diff --git a/src/assets/icons/gaming.webp b/src/assets/icons/gaming.webp
new file mode 100644
index 0000000..578a122
Binary files /dev/null and b/src/assets/icons/gaming.webp differ
diff --git a/src/assets/icons/image.webp b/src/assets/icons/image.webp
new file mode 100644
index 0000000..052d3ff
Binary files /dev/null and b/src/assets/icons/image.webp differ
diff --git a/src/assets/icons/media.webp b/src/assets/icons/media.webp
new file mode 100644
index 0000000..1df0cbc
Binary files /dev/null and b/src/assets/icons/media.webp differ
diff --git a/src/assets/icons/software.webp b/src/assets/icons/software.webp
new file mode 100644
index 0000000..eba5ebc
Binary files /dev/null and b/src/assets/icons/software.webp differ
diff --git a/src/assets/icons/unknown.webp b/src/assets/icons/unknown.webp
new file mode 100644
index 0000000..e97a913
Binary files /dev/null and b/src/assets/icons/unknown.webp differ
diff --git a/src/assets/icons/video.webp b/src/assets/icons/video.webp
new file mode 100644
index 0000000..df78522
Binary files /dev/null and b/src/assets/icons/video.webp differ
diff --git a/src/assets/img/Q-SupportIcon.webp b/src/assets/img/Q-SupportIcon.webp
new file mode 100644
index 0000000..c1909d3
Binary files /dev/null and b/src/assets/img/Q-SupportIcon.webp differ
diff --git a/src/assets/react.svg b/src/assets/react.svg
new file mode 100644
index 0000000..6c87de9
--- /dev/null
+++ b/src/assets/react.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/svgs/AccountCircleSVG.tsx b/src/assets/svgs/AccountCircleSVG.tsx
new file mode 100644
index 0000000..deb88bd
--- /dev/null
+++ b/src/assets/svgs/AccountCircleSVG.tsx
@@ -0,0 +1,25 @@
+interface AccountCircleSVGProps {
+ color: string
+ height: string
+ width: string
+}
+
+export const AccountCircleSVG: React.FC = ({
+ color,
+ height,
+ width
+}) => {
+ return (
+
+ )
+}
diff --git a/src/assets/svgs/CircleSVG.tsx b/src/assets/svgs/CircleSVG.tsx
new file mode 100644
index 0000000..6954397
--- /dev/null
+++ b/src/assets/svgs/CircleSVG.tsx
@@ -0,0 +1,23 @@
+import { IconTypes } from "./IconTypes";
+
+export const CircleSVG: React.FC = ({
+ color,
+ height,
+ width,
+ className,
+ onClickFunc,
+}) => {
+ return (
+
+ );
+};
diff --git a/src/assets/svgs/DarkModeSVG.tsx b/src/assets/svgs/DarkModeSVG.tsx
new file mode 100644
index 0000000..fe9ccab
--- /dev/null
+++ b/src/assets/svgs/DarkModeSVG.tsx
@@ -0,0 +1,23 @@
+import { IconTypes } from './IconTypes'
+
+export const DarkModeSVG: React.FC = ({
+ color,
+ height,
+ width,
+ className,
+ onClickFunc
+}) => {
+ return (
+
+ )
+}
diff --git a/src/assets/svgs/DownloadedLight.tsx b/src/assets/svgs/DownloadedLight.tsx
new file mode 100644
index 0000000..c10311b
--- /dev/null
+++ b/src/assets/svgs/DownloadedLight.tsx
@@ -0,0 +1,13 @@
+import { IconTypes } from './IconTypes'
+
+export const DownloadedLight: React.FC = ({
+ color,
+ height,
+ width,
+ className,
+ onClickFunc
+}) => {
+ return (
+
+ )
+}
diff --git a/src/assets/svgs/DownloadingLight.tsx b/src/assets/svgs/DownloadingLight.tsx
new file mode 100644
index 0000000..9c57868
--- /dev/null
+++ b/src/assets/svgs/DownloadingLight.tsx
@@ -0,0 +1,13 @@
+import { IconTypes } from './IconTypes'
+
+export const DownloadingLight: React.FC = ({
+ color,
+ height,
+ width,
+ className,
+ onClickFunc
+}) => {
+ return (
+
+ )
+}
diff --git a/src/assets/svgs/EmptyCircleSVG.tsx b/src/assets/svgs/EmptyCircleSVG.tsx
new file mode 100644
index 0000000..c7177c6
--- /dev/null
+++ b/src/assets/svgs/EmptyCircleSVG.tsx
@@ -0,0 +1,23 @@
+import { IconTypes } from "./IconTypes";
+
+export const EmptyCircleSVG: React.FC = ({
+ color,
+ height,
+ width,
+ className,
+ onClickFunc,
+}) => {
+ return (
+
+
+ );
+};
+
+
+
diff --git a/src/assets/svgs/ExpandMoreSVG.tsx b/src/assets/svgs/ExpandMoreSVG.tsx
new file mode 100644
index 0000000..12f1935
--- /dev/null
+++ b/src/assets/svgs/ExpandMoreSVG.tsx
@@ -0,0 +1,22 @@
+import { IconTypes } from "./IconTypes";
+export const ExpandMoreSVG: React.FC = ({
+ color,
+ height,
+ width,
+ className,
+ onClickFunc
+}) => {
+ return (
+
+ );
+};
diff --git a/src/assets/svgs/IconTypes.ts b/src/assets/svgs/IconTypes.ts
new file mode 100644
index 0000000..e11b2aa
--- /dev/null
+++ b/src/assets/svgs/IconTypes.ts
@@ -0,0 +1,7 @@
+export interface IconTypes {
+ color?: string;
+ height: string;
+ width: string;
+ className?: string;
+ onClickFunc?: (e?: any) => void;
+}
diff --git a/src/assets/svgs/LightModeSVG.tsx b/src/assets/svgs/LightModeSVG.tsx
new file mode 100644
index 0000000..66b056f
--- /dev/null
+++ b/src/assets/svgs/LightModeSVG.tsx
@@ -0,0 +1,23 @@
+import { IconTypes } from './IconTypes'
+
+export const LightModeSVG: React.FC = ({
+ color,
+ height,
+ width,
+ className,
+ onClickFunc
+}) => {
+ return (
+
+ )
+}
diff --git a/src/assets/svgs/PlaylistSVG.tsx b/src/assets/svgs/PlaylistSVG.tsx
new file mode 100644
index 0000000..baf1778
--- /dev/null
+++ b/src/assets/svgs/PlaylistSVG.tsx
@@ -0,0 +1,18 @@
+import { IconTypes } from "./IconTypes";
+
+export const PlaylistSVG: React.FC = ({
+ color,
+ height,
+ width,
+ className,
+ onClickFunc
+}) => {
+ return (
+
+
+ );
+};
diff --git a/src/assets/svgs/TimesSVG.tsx b/src/assets/svgs/TimesSVG.tsx
new file mode 100644
index 0000000..48c31d9
--- /dev/null
+++ b/src/assets/svgs/TimesSVG.tsx
@@ -0,0 +1,23 @@
+import { IconTypes } from "./IconTypes";
+
+export const TimesSVG: React.FC = ({
+ color,
+ height,
+ width,
+ className,
+ onClickFunc
+}) => {
+ return (
+
+ );
+};
diff --git a/src/components/EditIssue/EditIssue.tsx b/src/components/EditIssue/EditIssue.tsx
new file mode 100644
index 0000000..f538e58
--- /dev/null
+++ b/src/components/EditIssue/EditIssue.tsx
@@ -0,0 +1,511 @@
+import React, { useEffect, useRef, useState } from "react";
+import {
+ CrowdfundActionButton,
+ CrowdfundActionButtonRow,
+ CustomInputField,
+ ModalBody,
+ NewCrowdfundTitle,
+} from "./Upload-styles";
+import { Box, Modal, Typography, useTheme } from "@mui/material";
+import RemoveIcon from "@mui/icons-material/Remove";
+
+import ShortUniqueId from "short-unique-id";
+import { useDispatch, useSelector } from "react-redux";
+import { useDropzone } from "react-dropzone";
+
+import { setNotification } from "../../state/features/notificationsSlice";
+import { objectToBase64 } from "../../utils/toBase64";
+import { RootState } from "../../state/store";
+import {
+ setEditFile,
+ updateFile,
+ updateInHashMap,
+} from "../../state/features/fileSlice.ts";
+import { QSUPPORT_FILE_BASE } from "../../constants/Identifiers.ts";
+import { MultiplePublish } from "../common/MultiplePublish/MultiplePublishAll";
+import { TextEditor } from "../common/TextEditor/TextEditor";
+import { extractTextFromHTML } from "../common/TextEditor/utils";
+import { allCategoryData } from "../../constants/Categories/1stCategories.ts";
+import { titleFormatter } from "../../constants/Misc.ts";
+import {
+ CategoryList,
+ CategoryListRef,
+ getCategoriesFromObject,
+} from "../common/CategoryList/CategoryList.tsx";
+import {
+ ImagePublisher,
+ ImagePublisherRef,
+} from "../common/ImagePublisher/ImagePublisher.tsx";
+
+const uid = new ShortUniqueId();
+const shortuid = new ShortUniqueId({ length: 5 });
+
+interface NewCrowdfundProps {
+ editId?: string;
+ editContent?: null | {
+ title: string;
+ user: string;
+ coverImage: string | null;
+ };
+}
+
+interface VideoFile {
+ file: File;
+ title: string;
+ description: string;
+ coverImage?: string;
+ identifier?: string;
+ filename?: string;
+}
+export const EditIssue = () => {
+ const theme = useTheme();
+ const dispatch = useDispatch();
+ const username = useSelector((state: RootState) => state.auth?.user?.name);
+ const userAddress = useSelector(
+ (state: RootState) => state.auth?.user?.address
+ );
+ const editFileProperties = useSelector(
+ (state: RootState) => state.file.editFileProperties
+ );
+ const [publishes, setPublishes] = useState(null);
+ const [isOpenMultiplePublish, setIsOpenMultiplePublish] = useState(false);
+ const [videoPropertiesToSetToRedux, setVideoPropertiesToSetToRedux] =
+ useState(null);
+
+ const [title, setTitle] = useState("");
+ const [description, setDescription] = useState("");
+ const [coverImage, setCoverImage] = useState("");
+ const [file, setFile] = useState(null);
+ const [files, setFiles] = useState([]);
+ const [editCategories, setEditCategories] = useState([]);
+ const categoryListRef = useRef(null);
+ const imagePublisherRef = useRef(null);
+
+ const { getRootProps, getInputProps } = useDropzone({
+ maxFiles: 10,
+ maxSize: 419430400, // 400 MB in bytes
+ onDrop: (acceptedFiles, rejectedFiles) => {
+ const formatArray = acceptedFiles.map(item => {
+ return {
+ file: item,
+ title: "",
+ description: "",
+ coverImage: "",
+ };
+ });
+
+ setFiles(prev => [...prev, ...formatArray]);
+
+ let errorString = null;
+ rejectedFiles.forEach(({ file, errors }) => {
+ errors.forEach(error => {
+ if (error.code === "file-too-large") {
+ errorString = "File must be under 400mb";
+ }
+ console.log(`Error with file ${file.name}: ${error.message}`);
+ });
+ });
+ if (errorString) {
+ const notificationObj = {
+ msg: errorString,
+ alertType: "error",
+ };
+
+ dispatch(setNotification(notificationObj));
+ }
+ },
+ });
+
+ useEffect(() => {
+ if (editFileProperties) {
+ setTitle(editFileProperties?.title || "");
+ setFiles(editFileProperties?.files || []);
+ if (editFileProperties?.htmlDescription) {
+ setDescription(editFileProperties?.htmlDescription);
+ } else if (editFileProperties?.fullDescription) {
+ const paragraph = `${editFileProperties?.fullDescription}
`;
+ setDescription(paragraph);
+ }
+
+ const categoriesFromEditFile =
+ getCategoriesFromObject(editFileProperties);
+ setEditCategories(categoriesFromEditFile);
+ }
+ }, [editFileProperties]);
+ const onClose = () => {
+ dispatch(setEditFile(null));
+ setVideoPropertiesToSetToRedux(null);
+ setFile(null);
+ setTitle("");
+ setDescription("");
+ setCoverImage("");
+ };
+
+ async function publishQDNResource() {
+ try {
+ const categoryList = categoryListRef.current?.getSelectedCategories();
+ if (!title) throw new Error("Please enter a title");
+ if (!description) throw new Error("Please enter a description");
+ if (!categoryList[0]) throw new Error("Please select a category");
+ if (!editFileProperties) return;
+ if (!userAddress) throw new Error("Unable to locate user address");
+
+ let errorMsg = "";
+ let name = "";
+ if (username) {
+ name = username;
+ }
+ if (!name) {
+ errorMsg =
+ "Cannot publish without access to your name. Please authenticate.";
+ }
+
+ if (editFileProperties?.user !== username) {
+ errorMsg = "Cannot publish another user's resource";
+ }
+
+ if (errorMsg) {
+ dispatch(
+ setNotification({
+ msg: errorMsg,
+ alertType: "error",
+ })
+ );
+ return;
+ }
+ let fileReferences = [];
+
+ let listOfPublishes = [];
+ const fullDescription = extractTextFromHTML(description);
+
+ const sanitizeTitle = title
+ .replace(/[^a-zA-Z0-9\s-]/g, "")
+ .replace(/\s+/g, "-")
+ .replace(/-+/g, "-")
+ .trim()
+ .toLowerCase();
+
+ for (const publish of files) {
+ if (publish?.identifier) {
+ fileReferences.push(publish);
+ continue;
+ }
+ const file = publish.file;
+ const id = uid();
+
+ const identifier = `${QSUPPORT_FILE_BASE}${sanitizeTitle.slice(0, 30)}_${id}`;
+
+ let fileExtension = "";
+ const fileExtensionSplit = file?.name?.split(".");
+ if (fileExtensionSplit?.length > 1) {
+ fileExtension = fileExtensionSplit?.pop() || "";
+ }
+ let firstPartName = fileExtensionSplit[0];
+
+ let filename = firstPartName.slice(0, 15);
+
+ // Step 1: Replace all white spaces with underscores
+
+ // Replace all forms of whitespace (including non-standard ones) with underscores
+ let stringWithUnderscores = filename.replace(/[\s\uFEFF\xA0]+/g, "_");
+
+ // Remove all non-alphanumeric characters (except underscores)
+ let alphanumericString = stringWithUnderscores.replace(
+ /[^a-zA-Z0-9_]/g,
+ ""
+ );
+
+ if (fileExtension) {
+ filename = `${alphanumericString.trim()}.${fileExtension}`;
+ } else {
+ filename = alphanumericString;
+ }
+
+ let metadescription =
+ `**${categoryListRef.current?.getCategoriesFetchString()}**` +
+ fullDescription.slice(0, 150);
+
+ const requestBodyVideo: any = {
+ action: "PUBLISH_QDN_RESOURCE",
+ name: name,
+ service: "FILE",
+ file,
+ title: title.slice(0, 50),
+ description: metadescription,
+ identifier,
+ filename,
+ tag1: QSUPPORT_FILE_BASE,
+ };
+ listOfPublishes.push(requestBodyVideo);
+ fileReferences.push({
+ filename: file.name,
+ identifier,
+ name,
+ service: "FILE",
+ mimetype: file.type,
+ size: file.size,
+ });
+ }
+
+ const fileObject: any = {
+ title,
+ version: editFileProperties.version,
+ fullDescription,
+ htmlDescription: description,
+ commentsId: editFileProperties.commentsId,
+ ...categoryListRef.current?.categoriesToObject(),
+ files: fileReferences,
+ images: imagePublisherRef?.current?.getImageArray(),
+ };
+
+ let metadescription =
+ `**${categoryListRef.current?.getCategoriesFetchString()}**` +
+ fullDescription.slice(0, 150);
+
+ const fileObjectToBase64 = await objectToBase64(fileObject);
+ // Description is obtained from raw data
+
+ const requestBodyJson: any = {
+ action: "PUBLISH_QDN_RESOURCE",
+ name: name,
+ service: "DOCUMENT",
+ data64: fileObjectToBase64,
+ title: title.slice(0, 50),
+ description: metadescription,
+ identifier: editFileProperties.id,
+ tag1: QSUPPORT_FILE_BASE,
+ filename: `video_metadata.json`,
+ };
+ listOfPublishes.push(requestBodyJson);
+
+ const multiplePublish = {
+ action: "PUBLISH_MULTIPLE_QDN_RESOURCES",
+ resources: [...listOfPublishes],
+ };
+ setPublishes(multiplePublish);
+ setIsOpenMultiplePublish(true);
+ setVideoPropertiesToSetToRedux({
+ ...editFileProperties,
+ ...fileObject,
+ });
+ } catch (error: any) {
+ let notificationObj: any = null;
+ if (typeof error === "string") {
+ notificationObj = {
+ msg: error || "Failed to publish update",
+ alertType: "error",
+ };
+ } else if (typeof error?.error === "string") {
+ notificationObj = {
+ msg: error?.error || "Failed to publish update",
+ alertType: "error",
+ };
+ } else {
+ notificationObj = {
+ msg: error?.message || "Failed to publish update",
+ alertType: "error",
+ };
+ }
+ if (!notificationObj) return;
+ dispatch(setNotification(notificationObj));
+
+ throw new Error("Failed to publish update");
+ }
+ }
+
+ const handleOnchange = (index: number, type: string, value: string) => {
+ // setFiles((prev) => {
+ // let formattedValue = value
+ // console.log({type})
+ // if(type === 'title'){
+ // formattedValue = value.replace(/[^a-zA-Z0-9\s]/g, "")
+ // }
+ // const copyFiles = [...prev];
+ // copyFiles[index] = {
+ // ...copyFiles[index],
+ // [type]: formattedValue,
+ // };
+ // return copyFiles;
+ // });
+ };
+
+ return (
+ <>
+
+
+
+ Update Issue
+
+ <>
+
+
+ Click to add more files
+
+ {files.map((file, index) => {
+ const isExistingFile = !!file?.identifier;
+ return (
+
+
+
+ {isExistingFile ? file.filename : file?.file?.name}
+
+ {
+ setFiles(prev => {
+ const copyPrev = [...prev];
+ copyPrev.splice(index, 1);
+ return copyPrev;
+ });
+ }}
+ sx={{
+ cursor: "pointer",
+ }}
+ />
+
+
+ );
+ })}
+
+
+
+
+
+
+
+ {
+ const value = e.target.value;
+ const formattedValue = value.replace(titleFormatter, "");
+ setTitle(formattedValue);
+ }}
+ inputProps={{ maxLength: 180 }}
+ required
+ />
+
+ Description of Issue
+
+ {
+ setDescription(value);
+ }}
+ />
+ >
+
+
+ {
+ onClose();
+ }}
+ variant="contained"
+ color="error"
+ >
+ Cancel
+
+
+ {
+ publishQDNResource();
+ }}
+ >
+ Publish
+
+
+
+
+
+ {isOpenMultiplePublish && (
+ {
+ setIsOpenMultiplePublish(false);
+ setPublishes(null);
+ if (messageNotification) {
+ dispatch(
+ setNotification({
+ msg: messageNotification,
+ alertType: "error",
+ })
+ );
+ }
+ }}
+ onSubmit={() => {
+ setIsOpenMultiplePublish(false);
+ const clonedCopy = structuredClone(videoPropertiesToSetToRedux);
+ dispatch(updateFile(clonedCopy));
+ dispatch(updateInHashMap(clonedCopy));
+ dispatch(
+ setNotification({
+ msg: "File updated",
+ alertType: "success",
+ })
+ );
+ onClose();
+ }}
+ publishes={publishes}
+ />
+ )}
+ >
+ );
+};
diff --git a/src/components/EditIssue/Upload-styles.tsx b/src/components/EditIssue/Upload-styles.tsx
new file mode 100644
index 0000000..b1b8813
--- /dev/null
+++ b/src/components/EditIssue/Upload-styles.tsx
@@ -0,0 +1,586 @@
+import { styled } from "@mui/system";
+import {
+ Accordion,
+ AccordionDetails,
+ AccordionSummary,
+ Box,
+ Button,
+ Grid,
+ Rating,
+ TextField,
+ Typography,
+ Select
+} from "@mui/material";
+import AddPhotoAlternateIcon from "@mui/icons-material/AddPhotoAlternate";
+import { TimesSVG } from "../../assets/svgs/TimesSVG";
+
+export const DoubleLine = styled(Typography)`
+ display: -webkit-box;
+ -webkit-box-orient: vertical;
+ -webkit-line-clamp: 3;
+ overflow: hidden;
+`;
+
+export const MainContainer = styled(Grid)({
+ width: "100%",
+ display: "flex",
+ alignItems: "flex-start",
+ justifyContent: "center",
+ margin: 0,
+});
+
+export const MainCol = styled(Grid)(({ theme }) => ({
+ display: "flex",
+ flexDirection: "column",
+ alignItems: "center",
+ width: "100%",
+ padding: "20px",
+}));
+
+export const CreateContainer = styled(Box)(({ theme }) => ({
+ position: "fixed",
+ bottom: "20px",
+ right: "20px",
+ cursor: "pointer",
+ background: theme.palette.background.default,
+ width: "50px",
+ height: "50px",
+ display: "flex",
+ justifyContent: "center",
+ alignItems: "center",
+ borderRadius: "50%",
+}));
+
+export const ModalBody = styled(Box)(({ theme }) => ({
+ position: "absolute",
+ backgroundColor: theme.palette.background.default,
+ borderRadius: "4px",
+ top: "50%",
+ left: "50%",
+ transform: "translate(-50%, -50%)",
+ width: "75%",
+ maxWidth: "900px",
+ padding: "15px 35px",
+ display: "flex",
+ flexDirection: "column",
+ gap: "17px",
+ overflowY: "auto",
+ maxHeight: "95vh",
+ boxShadow:
+ theme.palette.mode === "dark"
+ ? "0px 4px 5px 0px hsla(0,0%,0%,0.14), 0px 1px 10px 0px hsla(0,0%,0%,0.12), 0px 2px 4px -1px hsla(0,0%,0%,0.2)"
+ : "rgba(99, 99, 99, 0.2) 0px 2px 8px 0px",
+ "&::-webkit-scrollbar-track": {
+ backgroundColor: theme.palette.background.paper,
+ },
+ "&::-webkit-scrollbar-track:hover": {
+ backgroundColor: theme.palette.background.paper,
+ },
+ "&::-webkit-scrollbar": {
+ width: "16px",
+ height: "10px",
+ backgroundColor: theme.palette.mode === "light" ? "#f6f8fa" : "#292d3e",
+ },
+ "&::-webkit-scrollbar-thumb": {
+ backgroundColor: theme.palette.mode === "light" ? "#d3d9e1" : "#575757",
+ borderRadius: "8px",
+ backgroundClip: "content-box",
+ border: "4px solid transparent",
+ },
+ "&::-webkit-scrollbar-thumb:hover": {
+ backgroundColor: theme.palette.mode === "light" ? "#b7bcc4" : "#474646",
+ },
+}));
+
+export const NewCrowdfundTitle = styled(Typography)(({ theme }) => ({
+ fontWeight: 400,
+ fontFamily: "Raleway",
+ fontSize: "25px",
+ userSelect: "none",
+}));
+export const NewCrowdFundFont = styled(Typography)(({ theme }) => ({
+ fontWeight: 400,
+ fontFamily: "Raleway",
+ fontSize: "18px",
+ userSelect: "none",
+}));
+export const NewCrowdfundTimeDescription = styled(Typography)(({ theme }) => ({
+ fontWeight: 400,
+ fontFamily: "Raleway",
+ fontSize: "18px",
+ userSelect: "none",
+ fontStyle: "italic",
+ textDecoration: "underline",
+}));
+
+export const CustomInputField = styled(TextField)(({ theme }) => ({
+ fontFamily: "Mulish",
+ fontSize: "19px",
+ letterSpacing: "0px",
+ fontWeight: 400,
+ color: theme.palette.text.primary,
+ backgroundColor: theme.palette.background.default,
+ borderColor: theme.palette.background.paper,
+ "& label": {
+ color: theme.palette.mode === "light" ? "#808183" : "#edeef0",
+ fontFamily: "Mulish",
+ fontSize: "19px",
+ letterSpacing: "0px",
+ fontWeight: 400,
+ },
+ "& label.Mui-focused": {
+ color: theme.palette.mode === "light" ? "#A0AAB4" : "#d7d8da",
+ },
+ "& .MuiInput-underline:after": {
+ borderBottomColor: theme.palette.mode === "light" ? "#B2BAC2" : "#c9cccf",
+ },
+ "& .MuiOutlinedInput-root": {
+ "& fieldset": {
+ borderColor: "#E0E3E7",
+ },
+ "&:hover fieldset": {
+ borderColor: "#B2BAC2",
+ },
+ "&.Mui-focused fieldset": {
+ borderColor: "#6F7E8C",
+ },
+ },
+ "& .MuiInputBase-root": {
+ fontFamily: "Mulish",
+ fontSize: "19px",
+ letterSpacing: "0px",
+ fontWeight: 400,
+ },
+ "& [class$='-MuiFilledInput-root']": {
+ padding: "30px 12px 8px",
+ },
+ "& .MuiFilledInput-root:after": {
+ borderBottomColor: theme.palette.secondary.main,
+ },
+}));
+
+
+
+export const CrowdfundTitle = styled(Typography)(({ theme }) => ({
+ fontFamily: "Copse",
+ letterSpacing: "1px",
+ fontWeight: 400,
+ fontSize: "20px",
+ color: theme.palette.text.primary,
+ userSelect: "none",
+ wordBreak: "break-word",
+}));
+
+export const CrowdfundSubTitleRow = styled(Box)({
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "center",
+ width: "100%",
+ flexDirection: "row",
+});
+
+export const CrowdfundSubTitle = styled(Typography)(({ theme }) => ({
+ fontFamily: "Copse",
+ letterSpacing: "1px",
+ fontWeight: 400,
+ fontSize: "17px",
+ color: theme.palette.text.primary,
+ userSelect: "none",
+ wordBreak: "break-word",
+ borderBottom: `1px solid ${theme.palette.text.primary}`,
+ paddingBottom: "1.5px",
+ width: "fit-content",
+ textDecoration: "none",
+}));
+
+export const CrowdfundDescription = styled(Typography)(({ theme }) => ({
+ fontFamily: "Raleway",
+ fontSize: "16px",
+ color: theme.palette.text.primary,
+ userSelect: "none",
+ wordBreak: "break-word",
+}));
+
+export const Spacer = ({ height }: any) => {
+ return (
+
+ );
+};
+
+export const StyledCardHeaderComment = styled(Box)({
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "flex-start",
+ gap: "5px",
+ padding: "7px 0px",
+});
+export const StyledCardCol = styled(Box)({
+ display: "flex",
+ overflow: "hidden",
+ flexDirection: "column",
+ gap: "2px",
+ alignItems: "flex-start",
+ width: "100%",
+});
+
+export const StyledCardColComment = styled(Box)({
+ display: "flex",
+ overflow: "hidden",
+ flexDirection: "column",
+ gap: "2px",
+ alignItems: "flex-start",
+ width: "100%",
+});
+
+export const AuthorTextComment = styled(Typography)({
+ fontFamily: "Raleway, sans-serif",
+ fontSize: "16px",
+ lineHeight: "1.2",
+});
+
+export const AddLogoIcon = styled(AddPhotoAlternateIcon)(({ theme }) => ({
+ color: "#fff",
+ height: "25px",
+ width: "auto",
+}));
+
+export const CoverImagePreview = styled("img")(({ theme }) => ({
+ width: "100px",
+ height: "100px",
+ objectFit: "contain",
+ userSelect: "none",
+ borderRadius: "3px",
+ marginBottom: "10px",
+}));
+
+export const LogoPreviewRow = styled(Box)(({ theme }) => ({
+ display: "flex",
+ alignItems: "center",
+ gap: "10px",
+}));
+
+export const TimesIcon = styled(TimesSVG)(({ theme }) => ({
+ backgroundColor: theme.palette.background.paper,
+ borderRadius: "50%",
+ padding: "5px",
+ transition: "all 0.2s ease-in-out",
+ "&:hover": {
+ cursor: "pointer",
+ scale: "1.1",
+ },
+}));
+
+export const CrowdfundCardTitle = styled(DoubleLine)(({ theme }) => ({
+ fontFamily: "Montserrat",
+ fontSize: "24px",
+ letterSpacing: "-0.3px",
+ userSelect: "none",
+ marginBottom: "auto",
+ textAlign: "center",
+ "@media (max-width: 650px)": {
+ fontSize: "18px",
+ },
+}));
+
+export const CrowdfundUploadDate = styled(Typography)(({ theme }) => ({
+ fontFamily: "Montserrat",
+ fontSize: "12px",
+ letterSpacing: "0.2px",
+ color: theme.palette.text.primary,
+ userSelect: "none",
+}));
+
+export const CATContainer = styled(Box)(({ theme }) => ({
+ position: "relative",
+ display: "flex",
+ padding: "15px",
+ flexDirection: "column",
+ gap: "20px",
+ justifyContent: "center",
+ width: "100%",
+ alignItems: "center",
+}));
+
+export const AddCrowdFundButton = styled(Button)(({ theme }) => ({
+ display: "flex",
+ alignItems: "center",
+ textTransform: "none",
+ padding: "10px 25px",
+ fontSize: "15px",
+ gap: "8px",
+ color: "#ffffff",
+ backgroundColor:
+ theme.palette.mode === "dark" ? theme.palette.primary.main : "#2a9a86",
+ border: "none",
+ borderRadius: "5px",
+ transition: "all 0.3s ease-in-out",
+ "&:hover": {
+ cursor: "pointer",
+ backgroundColor:
+ theme.palette.mode === "dark" ? theme.palette.primary.dark : "#217e6d",
+ },
+}));
+
+export const EditCrowdFundButton = styled(Button)(({ theme }) => ({
+ display: "flex",
+ alignItems: "center",
+ textTransform: "none",
+ padding: "5px 12px",
+ gap: "8px",
+ color: "#ffffff",
+ backgroundColor:
+ theme.palette.mode === "dark" ? theme.palette.primary.main : "#2a9a86",
+ border: "none",
+ borderRadius: "5px",
+ transition: "all 0.3s ease-in-out",
+ "&:hover": {
+ cursor: "pointer",
+ backgroundColor:
+ theme.palette.mode === "dark" ? theme.palette.primary.dark : "#217e6d",
+ },
+}));
+
+export const CrowdfundListWrapper = styled(Box)(({ theme }) => ({
+ width: "100%",
+ display: "flex",
+ flexDirection: "column",
+ alignItems: "center",
+ marginTop: "0px",
+ background: theme.palette.background.default,
+}));
+
+export const CrowdfundTitleRow = styled(Box)(({ theme }) => ({
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "center",
+ width: "100%",
+ gap: "10px",
+}));
+
+export const CrowdfundPageTitle = styled(Typography)(({ theme }) => ({
+ fontFamily: "Copse",
+ fontSize: "35px",
+ fontWeight: 400,
+ letterSpacing: "1px",
+ userSelect: "none",
+ color: theme.palette.text.primary,
+}));
+
+export const CrowdfundStatusRow = styled(Box)(({ theme }) => ({
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "center",
+ fontFamily: "Mulish",
+ fontSize: "21px",
+ fontWeight: 400,
+ letterSpacing: 0,
+ border: `1px solid ${theme.palette.text.primary}`,
+ borderRadius: "8px",
+ padding: "15px 25px",
+ userSelect: "none",
+}));
+
+export const CrowdfundDescriptionRow = styled(Box)({
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "center",
+ width: "100%",
+ fontFamily: "Montserrat",
+ fontSize: "18px",
+ fontWeight: 400,
+ letterSpacing: 0,
+});
+
+export const AboutMyCrowdfund = styled(Typography)(({ theme }) => ({
+ fontFamily: "Copse",
+ fontSize: "23px",
+ fontWeight: 400,
+ letterSpacing: "1px",
+ userSelect: "none",
+ color: theme.palette.text.primary,
+}));
+
+export const CrowdfundInlineContentRow = styled(Box)({
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "center",
+ width: "100%",
+});
+
+export const CrowdfundInlineContent = styled(Box)(({ theme }) => ({
+ display: "flex",
+ fontFamily: "Mulish",
+ fontSize: "19px",
+ fontWeight: 400,
+ letterSpacing: 0,
+ userSelect: "none",
+ color: theme.palette.text.primary,
+}));
+
+export const CrowdfundAccordion = styled(Accordion)(({ theme }) => ({
+ backgroundColor: theme.palette.primary.light,
+ "& .Mui-expanded": {
+ minHeight: "auto !important",
+ },
+}));
+
+export const CrowdfundAccordionSummary = styled(AccordionSummary)({
+ height: "50px",
+ "& .Mui-expanded": {
+ margin: "0px !important",
+ },
+});
+
+export const CrowdfundAccordionFont = styled(Typography)(({ theme }) => ({
+ fontFamily: "Mulish",
+ fontSize: "20px",
+ fontWeight: 400,
+ letterSpacing: "0px",
+ color: theme.palette.text.primary,
+ userSelect: "none",
+}));
+
+export const CrowdfundAccordionDetails = styled(AccordionDetails)({
+ padding: "0px 16px 16px 16px",
+});
+
+export const AddCoverImageButton = styled(Button)(({ theme }) => ({
+ display: "flex",
+ alignItems: "center",
+ fontFamily: "Montserrat",
+ fontSize: "16px",
+ fontWeight: 400,
+ letterSpacing: "0.2px",
+ color: "white",
+ gap: "5px",
+}));
+
+export const CoverImage = styled("img")({
+ width: "100%",
+ height: "250px",
+ objectFit: "cover",
+ objectPosition: "center",
+});
+
+export const CrowdfundActionButtonRow = styled(Box)({
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "space-between",
+ width: "100%",
+});
+
+export const CrowdfundActionButton = styled(Button)(({ theme }) => ({
+ display: "flex",
+ alignItems: "center",
+ fontFamily: "Montserrat",
+ fontSize: "16px",
+ fontWeight: 400,
+ letterSpacing: "0.2px",
+ color: "white",
+ gap: "5px",
+}));
+
+export const BackToHomeButton = styled(Button)(({ theme }) => ({
+ position: "absolute",
+ top: "20px",
+ left: "20px",
+ display: "flex",
+ alignItems: "center",
+ fontFamily: "Montserrat",
+ fontSize: "13px",
+ fontWeight: 400,
+ letterSpacing: "0.2px",
+ color: "white",
+ gap: "5px",
+ padding: "5px 10px",
+ backgroundColor: theme.palette.secondary.main,
+ transition: "all 0.3s ease-in-out",
+ "&:hover": {
+ backgroundColor: theme.palette.secondary.dark,
+ cursor: "pointer",
+ },
+}));
+
+export const CrowdfundLoaderRow = styled(Box)({
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "center",
+ gap: "10px",
+ padding: "10px",
+});
+
+export const RatingContainer = styled(Box)({
+ display: "flex",
+ alignItems: "center",
+ padding: "1px 5px",
+ borderRadius: "5px",
+ backgroundColor: "transparent",
+ transition: "all 0.3s ease-in-out",
+ "&:hover": {
+ cursor: "pointer",
+ backgroundColor: "#e4ddddac",
+ },
+});
+
+export const StyledRating = styled(Rating)({
+ fontSize: "28px",
+});
+
+export const NoReviewsFont = styled(Typography)(({ theme }) => ({
+ fontFamily: "Mulish",
+ fontWeight: 400,
+ letterSpacing: 0,
+ color: theme.palette.text.primary,
+}));
+
+export const StyledButton = styled(Button)(({ theme }) => ({
+ fontWeight: 600,
+ color: theme.palette.text.primary
+}))
+
+export const CustomSelect = styled(Select)(({ theme }) => ({
+ fontFamily: "Mulish",
+ fontSize: "19px",
+ letterSpacing: "0px",
+ fontWeight: 400,
+ color: theme.palette.text.primary,
+ backgroundColor: theme.palette.background.default,
+ '& .MuiSelect-select': {
+ padding: '12px',
+ fontFamily: "Mulish",
+ fontSize: "19px",
+ letterSpacing: "0px",
+ fontWeight: 400,
+ borderRadius: theme.shape.borderRadius, // Match border radius
+ },
+ '&:before': {
+ // Underline style
+ borderBottomColor: theme.palette.mode === "light" ? "#B2BAC2" : "#c9cccf",
+ },
+ '&:after': {
+ // Underline style when focused
+ borderBottomColor: theme.palette.secondary.main,
+ },
+ '& .MuiOutlinedInput-root': {
+ '& fieldset': {
+ borderColor: "#E0E3E7",
+ },
+ '&:hover fieldset': {
+ borderColor: "#B2BAC2",
+ },
+ '&.Mui-focused fieldset': {
+ borderColor: "#6F7E8C",
+ },
+ },
+ '& .MuiInputBase-root': {
+ fontFamily: "Mulish",
+ fontSize: "19px",
+ letterSpacing: "0px",
+ fontWeight: 400,
+ color: theme.palette.text.primary,
+ },
+}));
diff --git a/src/components/EditPlaylist/EditPlaylist.tsx b/src/components/EditPlaylist/EditPlaylist.tsx
new file mode 100644
index 0000000..aab2f93
--- /dev/null
+++ b/src/components/EditPlaylist/EditPlaylist.tsx
@@ -0,0 +1,620 @@
+import React, { useEffect, useMemo, useState } from "react";
+import {
+ AddCoverImageButton,
+ AddLogoIcon,
+ CoverImagePreview,
+ CrowdfundActionButton,
+ CrowdfundActionButtonRow,
+ CustomInputField,
+ LogoPreviewRow,
+ ModalBody,
+ NewCrowdfundTitle,
+ TimesIcon,
+} from "./Upload-styles.tsx";
+import {
+ Box,
+ FormControl,
+ InputLabel,
+ MenuItem,
+ Modal,
+ OutlinedInput,
+ Select,
+ SelectChangeEvent,
+ Typography,
+ useTheme,
+} from "@mui/material";
+import ShortUniqueId from "short-unique-id";
+import { useDispatch, useSelector } from "react-redux";
+
+import { setNotification } from "../../state/features/notificationsSlice";
+import { objectToBase64 } from "../../utils/toBase64";
+import { RootState } from "../../state/store";
+import {
+ setEditPlaylist,
+ updateFile,
+ updateInHashMap,
+} from "../../state/features/fileSlice.ts";
+import ImageUploader from "../common/ImagePublisher/ImageUploader.tsx";
+import {
+ QSUPPORT_FILE_BASE,
+ QSUPPORT_PLAYLIST_BASE,
+} from "../../constants/Identifiers.ts";
+import { PlaylistListEdit } from "../PlaylistListEdit/PlaylistListEdit";
+import { TextEditor } from "../common/TextEditor/TextEditor";
+import { extractTextFromHTML } from "../common/TextEditor/utils";
+import {
+ firstCategories,
+ secondCategories,
+} from "../../constants/Categories/1stCategories.ts";
+
+const uid = new ShortUniqueId();
+const shortuid = new ShortUniqueId({ length: 5 });
+
+interface NewCrowdfundProps {
+ editId?: string;
+ editContent?: null | {
+ title: string;
+ user: string;
+ coverImage: string | null;
+ };
+}
+
+interface VideoFile {
+ file: File;
+ title: string;
+ description: string;
+ coverImage?: string;
+}
+export const EditPlaylist = () => {
+ const theme = useTheme();
+ const dispatch = useDispatch();
+ const username = useSelector((state: RootState) => state.auth?.user?.name);
+ const userAddress = useSelector(
+ (state: RootState) => state.auth?.user?.address
+ );
+ const editVideoProperties = useSelector(
+ (state: RootState) => state.file.editPlaylistProperties
+ );
+ const [playlistData, setPlaylistData] = useState(null);
+ const [title, setTitle] = useState("");
+ const [description, setDescription] = useState("");
+ const [coverImage, setCoverImage] = useState([]);
+ const [videos, setVideos] = useState([]);
+ const [selectedCategoryVideos, setSelectedCategoryVideos] =
+ useState(null);
+ const [selectedSubCategoryVideos, setSelectedSubCategoryVideos] =
+ useState(null);
+
+ const isNew = useMemo(() => {
+ return editVideoProperties?.mode === "new";
+ }, [editVideoProperties]);
+
+ useEffect(() => {
+ if (isNew) {
+ setPlaylistData({
+ videos: [],
+ });
+ }
+ }, [isNew]);
+
+ // useEffect(() => {
+ // if (editVideoProperties) {
+ // const descriptionString = editVideoProperties?.description || "";
+ // // Splitting the string at the asterisks
+ // const parts = descriptionString.split("**");
+
+ // // The part within the asterisks
+ // const extractedString = parts[1];
+
+ // // The part after the last asterisks
+ // const description = parts[2] || ""; // Using '|| '' to handle cases where there is no text after the last **
+ // setTitle(editVideoProperties?.title || "");
+ // setDescription(editVideoProperties?.fullDescription || "");
+ // setCoverImage(editVideoProperties?.videoImage || "");
+
+ // // Split the extracted string into key-value pairs
+ // const keyValuePairs = extractedString.split(";");
+
+ // // Initialize variables to hold the category and subcategory values
+ // let category, subcategory;
+
+ // // Loop through each key-value pair
+ // keyValuePairs.forEach((pair) => {
+ // const [key, value] = pair.split(":");
+
+ // // Check the key and assign the value to the appropriate variable
+ // if (key === "category") {
+ // category = value;
+ // } else if (key === "subcategory") {
+ // subcategory = value;
+ // }
+ // });
+
+ // if(category){
+ // const selectedOption = categories.find((option) => option.id === +category);
+ // setSelectedCategoryVideos(selectedOption || null);
+ // }
+
+ // if(subcategory){
+ // const selectedOption = categories.find((option) => option.id === +subcategory);
+ // setSelectedCategoryVideos(selectedOption || null);
+ // }
+
+ // }
+ // }, [editVideoProperties]);
+
+ const checkforPlaylist = React.useCallback(async videoList => {
+ try {
+ const combinedData: any = {};
+ const videos = [];
+ if (videoList) {
+ for (const vid of videoList) {
+ const url = `/arbitrary/resources/search?mode=ALL&service=DOCUMENT&identifier=${vid.identifier}&limit=1&includemetadata=true&reverse=true&name=${vid.name}&exactmatchnames=true&offset=0`;
+ const response = await fetch(url, {
+ method: "GET",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+ const responseDataSearchVid = await response.json();
+
+ if (responseDataSearchVid?.length > 0) {
+ let resourceData2 = responseDataSearchVid[0];
+ videos.push(resourceData2);
+ }
+ }
+ }
+ combinedData.videos = videos;
+ setPlaylistData(combinedData);
+ } catch (error) {}
+ }, []);
+
+ useEffect(() => {
+ if (editVideoProperties) {
+ setTitle(editVideoProperties?.title || "");
+
+ if (editVideoProperties?.htmlDescription) {
+ setDescription(editVideoProperties?.htmlDescription);
+ } else if (editVideoProperties?.description) {
+ const paragraph = `${editVideoProperties?.description}
`;
+ setDescription(paragraph);
+ }
+ setCoverImage(editVideoProperties?.image || "");
+ setVideos(editVideoProperties?.videos || []);
+
+ if (editVideoProperties?.category) {
+ const selectedOption = firstCategories.find(
+ option => option.id === +editVideoProperties.category
+ );
+ setSelectedCategoryVideos(selectedOption || null);
+ }
+
+ if (
+ editVideoProperties?.category &&
+ editVideoProperties?.subcategory &&
+ secondCategories[+editVideoProperties?.category]
+ ) {
+ const selectedOption = secondCategories[
+ +editVideoProperties?.category
+ ]?.find(option => option.id === +editVideoProperties.subcategory);
+ setSelectedSubCategoryVideos(selectedOption || null);
+ }
+
+ if (editVideoProperties?.videos) {
+ checkforPlaylist(editVideoProperties?.videos);
+ }
+ }
+ }, [editVideoProperties]);
+
+ const onClose = () => {
+ setTitle("");
+ setDescription("");
+ setVideos([]);
+ setPlaylistData(null);
+ setSelectedCategoryVideos(null);
+ setSelectedSubCategoryVideos(null);
+ setCoverImage([]);
+ dispatch(setEditPlaylist(null));
+ };
+
+ async function publishQDNResource() {
+ try {
+ if (!title) throw new Error("Please enter a title");
+ if (!description) throw new Error("Please enter a description");
+ if (!coverImage) throw new Error("Please select cover image");
+ if (!selectedCategoryVideos) throw new Error("Please select a category");
+
+ if (!editVideoProperties) return;
+ if (!userAddress) throw new Error("Unable to locate user address");
+ let errorMsg = "";
+ let name = "";
+ if (username) {
+ name = username;
+ }
+ if (!name) {
+ errorMsg =
+ "Cannot publish without access to your name. Please authenticate.";
+ }
+
+ if (!isNew && editVideoProperties?.user !== username) {
+ errorMsg = "Cannot publish another user's resource";
+ }
+
+ if (errorMsg) {
+ dispatch(
+ setNotification({
+ msg: errorMsg,
+ alertType: "error",
+ })
+ );
+ return;
+ }
+ const category = selectedCategoryVideos.id;
+ const subcategory = selectedSubCategoryVideos?.id || "";
+
+ const videoStructured = playlistData.videos.map(item => {
+ const descriptionVid = item?.metadata?.description;
+ if (!descriptionVid) throw new Error("cannot find video code");
+
+ // Split the string by ';'
+ let parts = descriptionVid.split(";");
+
+ // Initialize a variable to hold the code value
+ let codeValue = "";
+
+ // Loop through the parts to find the one that starts with 'code:'
+ for (let part of parts) {
+ if (part.startsWith("code:")) {
+ codeValue = part.split(":")[1];
+ break;
+ }
+ }
+ if (!codeValue) throw new Error("cannot find video code");
+
+ return {
+ identifier: item.identifier,
+ name: item.name,
+ service: item.service,
+ code: codeValue,
+ };
+ });
+ const id = uid();
+
+ let commentsId = editVideoProperties?.id;
+
+ if (isNew) {
+ commentsId = `${QSUPPORT_PLAYLIST_BASE}_cm_${id}`;
+ }
+ const stringDescription = extractTextFromHTML(description);
+
+ const playlistObject: any = {
+ title,
+ version: 1,
+ description: stringDescription,
+ htmlDescription: description,
+ image: coverImage,
+ videos: videoStructured,
+ commentsId: commentsId,
+ category,
+ subcategory,
+ };
+
+ const codes = videoStructured.map(item => `c:${item.code};`).join("");
+ let metadescription =
+ `**category:${category};subcategory:${subcategory};${codes}**` +
+ stringDescription.slice(0, 120);
+
+ const crowdfundObjectToBase64 = await objectToBase64(playlistObject);
+ // Description is obtained from raw data
+
+ let identifier = editVideoProperties?.id;
+ const sanitizeTitle = title
+ .replace(/[^a-zA-Z0-9\s-]/g, "")
+ .replace(/\s+/g, "-")
+ .replace(/-+/g, "-")
+ .trim()
+ .toLowerCase();
+ if (isNew) {
+ identifier = `${QSUPPORT_PLAYLIST_BASE}${sanitizeTitle.slice(0, 30)}_${id}`;
+ }
+ const requestBodyJson: any = {
+ action: "PUBLISH_QDN_RESOURCE",
+ name: username,
+ service: "PLAYLIST",
+ data64: crowdfundObjectToBase64,
+ title: title.slice(0, 50),
+ description: metadescription,
+ identifier: identifier,
+ tag1: QSUPPORT_FILE_BASE,
+ };
+
+ await qortalRequest(requestBodyJson);
+ if (isNew) {
+ const objectToStore = {
+ title: title.slice(0, 50),
+ description: metadescription,
+ id: identifier,
+ service: "PLAYLIST",
+ name: username,
+ ...playlistObject,
+ };
+ dispatch(updateFile(objectToStore));
+ dispatch(updateInHashMap(objectToStore));
+ } else {
+ dispatch(
+ updateFile({
+ ...editVideoProperties,
+ ...playlistObject,
+ })
+ );
+ dispatch(
+ updateInHashMap({
+ ...editVideoProperties,
+ ...playlistObject,
+ })
+ );
+ }
+
+ onClose();
+ } catch (error: any) {
+ let notificationObj: any = null;
+ if (typeof error === "string") {
+ notificationObj = {
+ msg: error || "Failed to publish update",
+ alertType: "error",
+ };
+ } else if (typeof error?.error === "string") {
+ notificationObj = {
+ msg: error?.error || "Failed to publish update",
+ alertType: "error",
+ };
+ } else {
+ notificationObj = {
+ msg: error?.message || "Failed to publish update",
+ alertType: "error",
+ };
+ }
+ if (!notificationObj) return;
+ dispatch(setNotification(notificationObj));
+
+ throw new Error("Failed to publish update");
+ }
+ }
+
+ const handleOnchange = (index: number, type: string, value: string) => {
+ // setFiles((prev) => {
+ // let formattedValue = value
+ // console.log({type})
+ // if(type === 'title'){
+ // formattedValue = value.replace(/[^a-zA-Z0-9\s]/g, "")
+ // }
+ // const copyFiles = [...prev];
+ // copyFiles[index] = {
+ // ...copyFiles[index],
+ // [type]: formattedValue,
+ // };
+ // return copyFiles;
+ // });
+ };
+
+ const handleOptionCategoryChangeVideos = (
+ event: SelectChangeEvent
+ ) => {
+ const optionId = event.target.value;
+ const selectedOption = firstCategories.find(
+ option => option.id === +optionId
+ );
+ setSelectedCategoryVideos(selectedOption || null);
+ };
+ const handleOptionSubCategoryChangeVideos = (
+ event: SelectChangeEvent,
+ subcategories: any[]
+ ) => {
+ const optionId = event.target.value;
+ const selectedOption = subcategories.find(
+ option => option.id === +optionId
+ );
+ setSelectedSubCategoryVideos(selectedOption || null);
+ };
+
+ const removeVideo = index => {
+ const copyData = structuredClone(playlistData);
+ copyData.videos.splice(index, 1);
+ setPlaylistData(copyData);
+ };
+
+ const addVideo = data => {
+ if (playlistData?.videos?.length > 9) {
+ dispatch(
+ setNotification({
+ msg: "Max 10 videos per playlist",
+ alertType: "error",
+ })
+ );
+ return;
+ }
+ const copyData = structuredClone(playlistData);
+ copyData.videos = [...copyData.videos, { ...data }];
+ setPlaylistData(copyData);
+ };
+
+ return (
+ <>
+
+
+
+ {isNew ? (
+ Create new playlist
+ ) : (
+ Update Playlist properties
+ )}
+
+ <>
+
+
+ Select a Category
+ }
+ value={selectedCategoryVideos?.id || ""}
+ onChange={handleOptionCategoryChangeVideos}
+ >
+ {firstCategories.map(option => (
+
+ ))}
+
+
+ {selectedCategoryVideos &&
+ secondCategories[selectedCategoryVideos?.id] && (
+
+ Select a Sub-Category
+ }
+ value={selectedSubCategoryVideos?.id || ""}
+ onChange={e =>
+ handleOptionSubCategoryChangeVideos(
+ e,
+ secondCategories[selectedCategoryVideos?.id]
+ )
+ }
+ >
+ {secondCategories[selectedCategoryVideos.id].map(
+ option => (
+
+ )
+ )}
+
+
+ )}
+
+
+ {!coverImage ? (
+ setCoverImage(img)}>
+
+ Add Cover Image
+
+
+
+ ) : (
+
+ {coverImage.map(
+ image =>
+ image && (
+
+ )
+ )}
+ setCoverImage([])}
+ height={"32"}
+ width={"32"}
+ >
+
+ )}
+ {
+ const value = e.target.value;
+ const formattedValue = value.replace(
+ /[^a-zA-Z0-9\s-_!?]/g,
+ ""
+ );
+ setTitle(formattedValue);
+ }}
+ inputProps={{ maxLength: 180 }}
+ required
+ />
+ {/* setDescription(e.target.value)}
+ inputProps={{ maxLength: 10000 }}
+ multiline
+ maxRows={3}
+ required
+ /> */}
+
+ Description of playlist
+
+ {
+ setDescription(value);
+ }}
+ />
+
+
+
+ >
+
+
+ {
+ onClose();
+ }}
+ variant="contained"
+ color="error"
+ >
+ Cancel
+
+
+ {
+ publishQDNResource();
+ }}
+ >
+ Publish
+
+
+
+
+
+ >
+ );
+};
diff --git a/src/components/EditPlaylist/Upload-styles.tsx b/src/components/EditPlaylist/Upload-styles.tsx
new file mode 100644
index 0000000..b1b8813
--- /dev/null
+++ b/src/components/EditPlaylist/Upload-styles.tsx
@@ -0,0 +1,586 @@
+import { styled } from "@mui/system";
+import {
+ Accordion,
+ AccordionDetails,
+ AccordionSummary,
+ Box,
+ Button,
+ Grid,
+ Rating,
+ TextField,
+ Typography,
+ Select
+} from "@mui/material";
+import AddPhotoAlternateIcon from "@mui/icons-material/AddPhotoAlternate";
+import { TimesSVG } from "../../assets/svgs/TimesSVG";
+
+export const DoubleLine = styled(Typography)`
+ display: -webkit-box;
+ -webkit-box-orient: vertical;
+ -webkit-line-clamp: 3;
+ overflow: hidden;
+`;
+
+export const MainContainer = styled(Grid)({
+ width: "100%",
+ display: "flex",
+ alignItems: "flex-start",
+ justifyContent: "center",
+ margin: 0,
+});
+
+export const MainCol = styled(Grid)(({ theme }) => ({
+ display: "flex",
+ flexDirection: "column",
+ alignItems: "center",
+ width: "100%",
+ padding: "20px",
+}));
+
+export const CreateContainer = styled(Box)(({ theme }) => ({
+ position: "fixed",
+ bottom: "20px",
+ right: "20px",
+ cursor: "pointer",
+ background: theme.palette.background.default,
+ width: "50px",
+ height: "50px",
+ display: "flex",
+ justifyContent: "center",
+ alignItems: "center",
+ borderRadius: "50%",
+}));
+
+export const ModalBody = styled(Box)(({ theme }) => ({
+ position: "absolute",
+ backgroundColor: theme.palette.background.default,
+ borderRadius: "4px",
+ top: "50%",
+ left: "50%",
+ transform: "translate(-50%, -50%)",
+ width: "75%",
+ maxWidth: "900px",
+ padding: "15px 35px",
+ display: "flex",
+ flexDirection: "column",
+ gap: "17px",
+ overflowY: "auto",
+ maxHeight: "95vh",
+ boxShadow:
+ theme.palette.mode === "dark"
+ ? "0px 4px 5px 0px hsla(0,0%,0%,0.14), 0px 1px 10px 0px hsla(0,0%,0%,0.12), 0px 2px 4px -1px hsla(0,0%,0%,0.2)"
+ : "rgba(99, 99, 99, 0.2) 0px 2px 8px 0px",
+ "&::-webkit-scrollbar-track": {
+ backgroundColor: theme.palette.background.paper,
+ },
+ "&::-webkit-scrollbar-track:hover": {
+ backgroundColor: theme.palette.background.paper,
+ },
+ "&::-webkit-scrollbar": {
+ width: "16px",
+ height: "10px",
+ backgroundColor: theme.palette.mode === "light" ? "#f6f8fa" : "#292d3e",
+ },
+ "&::-webkit-scrollbar-thumb": {
+ backgroundColor: theme.palette.mode === "light" ? "#d3d9e1" : "#575757",
+ borderRadius: "8px",
+ backgroundClip: "content-box",
+ border: "4px solid transparent",
+ },
+ "&::-webkit-scrollbar-thumb:hover": {
+ backgroundColor: theme.palette.mode === "light" ? "#b7bcc4" : "#474646",
+ },
+}));
+
+export const NewCrowdfundTitle = styled(Typography)(({ theme }) => ({
+ fontWeight: 400,
+ fontFamily: "Raleway",
+ fontSize: "25px",
+ userSelect: "none",
+}));
+export const NewCrowdFundFont = styled(Typography)(({ theme }) => ({
+ fontWeight: 400,
+ fontFamily: "Raleway",
+ fontSize: "18px",
+ userSelect: "none",
+}));
+export const NewCrowdfundTimeDescription = styled(Typography)(({ theme }) => ({
+ fontWeight: 400,
+ fontFamily: "Raleway",
+ fontSize: "18px",
+ userSelect: "none",
+ fontStyle: "italic",
+ textDecoration: "underline",
+}));
+
+export const CustomInputField = styled(TextField)(({ theme }) => ({
+ fontFamily: "Mulish",
+ fontSize: "19px",
+ letterSpacing: "0px",
+ fontWeight: 400,
+ color: theme.palette.text.primary,
+ backgroundColor: theme.palette.background.default,
+ borderColor: theme.palette.background.paper,
+ "& label": {
+ color: theme.palette.mode === "light" ? "#808183" : "#edeef0",
+ fontFamily: "Mulish",
+ fontSize: "19px",
+ letterSpacing: "0px",
+ fontWeight: 400,
+ },
+ "& label.Mui-focused": {
+ color: theme.palette.mode === "light" ? "#A0AAB4" : "#d7d8da",
+ },
+ "& .MuiInput-underline:after": {
+ borderBottomColor: theme.palette.mode === "light" ? "#B2BAC2" : "#c9cccf",
+ },
+ "& .MuiOutlinedInput-root": {
+ "& fieldset": {
+ borderColor: "#E0E3E7",
+ },
+ "&:hover fieldset": {
+ borderColor: "#B2BAC2",
+ },
+ "&.Mui-focused fieldset": {
+ borderColor: "#6F7E8C",
+ },
+ },
+ "& .MuiInputBase-root": {
+ fontFamily: "Mulish",
+ fontSize: "19px",
+ letterSpacing: "0px",
+ fontWeight: 400,
+ },
+ "& [class$='-MuiFilledInput-root']": {
+ padding: "30px 12px 8px",
+ },
+ "& .MuiFilledInput-root:after": {
+ borderBottomColor: theme.palette.secondary.main,
+ },
+}));
+
+
+
+export const CrowdfundTitle = styled(Typography)(({ theme }) => ({
+ fontFamily: "Copse",
+ letterSpacing: "1px",
+ fontWeight: 400,
+ fontSize: "20px",
+ color: theme.palette.text.primary,
+ userSelect: "none",
+ wordBreak: "break-word",
+}));
+
+export const CrowdfundSubTitleRow = styled(Box)({
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "center",
+ width: "100%",
+ flexDirection: "row",
+});
+
+export const CrowdfundSubTitle = styled(Typography)(({ theme }) => ({
+ fontFamily: "Copse",
+ letterSpacing: "1px",
+ fontWeight: 400,
+ fontSize: "17px",
+ color: theme.palette.text.primary,
+ userSelect: "none",
+ wordBreak: "break-word",
+ borderBottom: `1px solid ${theme.palette.text.primary}`,
+ paddingBottom: "1.5px",
+ width: "fit-content",
+ textDecoration: "none",
+}));
+
+export const CrowdfundDescription = styled(Typography)(({ theme }) => ({
+ fontFamily: "Raleway",
+ fontSize: "16px",
+ color: theme.palette.text.primary,
+ userSelect: "none",
+ wordBreak: "break-word",
+}));
+
+export const Spacer = ({ height }: any) => {
+ return (
+
+ );
+};
+
+export const StyledCardHeaderComment = styled(Box)({
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "flex-start",
+ gap: "5px",
+ padding: "7px 0px",
+});
+export const StyledCardCol = styled(Box)({
+ display: "flex",
+ overflow: "hidden",
+ flexDirection: "column",
+ gap: "2px",
+ alignItems: "flex-start",
+ width: "100%",
+});
+
+export const StyledCardColComment = styled(Box)({
+ display: "flex",
+ overflow: "hidden",
+ flexDirection: "column",
+ gap: "2px",
+ alignItems: "flex-start",
+ width: "100%",
+});
+
+export const AuthorTextComment = styled(Typography)({
+ fontFamily: "Raleway, sans-serif",
+ fontSize: "16px",
+ lineHeight: "1.2",
+});
+
+export const AddLogoIcon = styled(AddPhotoAlternateIcon)(({ theme }) => ({
+ color: "#fff",
+ height: "25px",
+ width: "auto",
+}));
+
+export const CoverImagePreview = styled("img")(({ theme }) => ({
+ width: "100px",
+ height: "100px",
+ objectFit: "contain",
+ userSelect: "none",
+ borderRadius: "3px",
+ marginBottom: "10px",
+}));
+
+export const LogoPreviewRow = styled(Box)(({ theme }) => ({
+ display: "flex",
+ alignItems: "center",
+ gap: "10px",
+}));
+
+export const TimesIcon = styled(TimesSVG)(({ theme }) => ({
+ backgroundColor: theme.palette.background.paper,
+ borderRadius: "50%",
+ padding: "5px",
+ transition: "all 0.2s ease-in-out",
+ "&:hover": {
+ cursor: "pointer",
+ scale: "1.1",
+ },
+}));
+
+export const CrowdfundCardTitle = styled(DoubleLine)(({ theme }) => ({
+ fontFamily: "Montserrat",
+ fontSize: "24px",
+ letterSpacing: "-0.3px",
+ userSelect: "none",
+ marginBottom: "auto",
+ textAlign: "center",
+ "@media (max-width: 650px)": {
+ fontSize: "18px",
+ },
+}));
+
+export const CrowdfundUploadDate = styled(Typography)(({ theme }) => ({
+ fontFamily: "Montserrat",
+ fontSize: "12px",
+ letterSpacing: "0.2px",
+ color: theme.palette.text.primary,
+ userSelect: "none",
+}));
+
+export const CATContainer = styled(Box)(({ theme }) => ({
+ position: "relative",
+ display: "flex",
+ padding: "15px",
+ flexDirection: "column",
+ gap: "20px",
+ justifyContent: "center",
+ width: "100%",
+ alignItems: "center",
+}));
+
+export const AddCrowdFundButton = styled(Button)(({ theme }) => ({
+ display: "flex",
+ alignItems: "center",
+ textTransform: "none",
+ padding: "10px 25px",
+ fontSize: "15px",
+ gap: "8px",
+ color: "#ffffff",
+ backgroundColor:
+ theme.palette.mode === "dark" ? theme.palette.primary.main : "#2a9a86",
+ border: "none",
+ borderRadius: "5px",
+ transition: "all 0.3s ease-in-out",
+ "&:hover": {
+ cursor: "pointer",
+ backgroundColor:
+ theme.palette.mode === "dark" ? theme.palette.primary.dark : "#217e6d",
+ },
+}));
+
+export const EditCrowdFundButton = styled(Button)(({ theme }) => ({
+ display: "flex",
+ alignItems: "center",
+ textTransform: "none",
+ padding: "5px 12px",
+ gap: "8px",
+ color: "#ffffff",
+ backgroundColor:
+ theme.palette.mode === "dark" ? theme.palette.primary.main : "#2a9a86",
+ border: "none",
+ borderRadius: "5px",
+ transition: "all 0.3s ease-in-out",
+ "&:hover": {
+ cursor: "pointer",
+ backgroundColor:
+ theme.palette.mode === "dark" ? theme.palette.primary.dark : "#217e6d",
+ },
+}));
+
+export const CrowdfundListWrapper = styled(Box)(({ theme }) => ({
+ width: "100%",
+ display: "flex",
+ flexDirection: "column",
+ alignItems: "center",
+ marginTop: "0px",
+ background: theme.palette.background.default,
+}));
+
+export const CrowdfundTitleRow = styled(Box)(({ theme }) => ({
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "center",
+ width: "100%",
+ gap: "10px",
+}));
+
+export const CrowdfundPageTitle = styled(Typography)(({ theme }) => ({
+ fontFamily: "Copse",
+ fontSize: "35px",
+ fontWeight: 400,
+ letterSpacing: "1px",
+ userSelect: "none",
+ color: theme.palette.text.primary,
+}));
+
+export const CrowdfundStatusRow = styled(Box)(({ theme }) => ({
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "center",
+ fontFamily: "Mulish",
+ fontSize: "21px",
+ fontWeight: 400,
+ letterSpacing: 0,
+ border: `1px solid ${theme.palette.text.primary}`,
+ borderRadius: "8px",
+ padding: "15px 25px",
+ userSelect: "none",
+}));
+
+export const CrowdfundDescriptionRow = styled(Box)({
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "center",
+ width: "100%",
+ fontFamily: "Montserrat",
+ fontSize: "18px",
+ fontWeight: 400,
+ letterSpacing: 0,
+});
+
+export const AboutMyCrowdfund = styled(Typography)(({ theme }) => ({
+ fontFamily: "Copse",
+ fontSize: "23px",
+ fontWeight: 400,
+ letterSpacing: "1px",
+ userSelect: "none",
+ color: theme.palette.text.primary,
+}));
+
+export const CrowdfundInlineContentRow = styled(Box)({
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "center",
+ width: "100%",
+});
+
+export const CrowdfundInlineContent = styled(Box)(({ theme }) => ({
+ display: "flex",
+ fontFamily: "Mulish",
+ fontSize: "19px",
+ fontWeight: 400,
+ letterSpacing: 0,
+ userSelect: "none",
+ color: theme.palette.text.primary,
+}));
+
+export const CrowdfundAccordion = styled(Accordion)(({ theme }) => ({
+ backgroundColor: theme.palette.primary.light,
+ "& .Mui-expanded": {
+ minHeight: "auto !important",
+ },
+}));
+
+export const CrowdfundAccordionSummary = styled(AccordionSummary)({
+ height: "50px",
+ "& .Mui-expanded": {
+ margin: "0px !important",
+ },
+});
+
+export const CrowdfundAccordionFont = styled(Typography)(({ theme }) => ({
+ fontFamily: "Mulish",
+ fontSize: "20px",
+ fontWeight: 400,
+ letterSpacing: "0px",
+ color: theme.palette.text.primary,
+ userSelect: "none",
+}));
+
+export const CrowdfundAccordionDetails = styled(AccordionDetails)({
+ padding: "0px 16px 16px 16px",
+});
+
+export const AddCoverImageButton = styled(Button)(({ theme }) => ({
+ display: "flex",
+ alignItems: "center",
+ fontFamily: "Montserrat",
+ fontSize: "16px",
+ fontWeight: 400,
+ letterSpacing: "0.2px",
+ color: "white",
+ gap: "5px",
+}));
+
+export const CoverImage = styled("img")({
+ width: "100%",
+ height: "250px",
+ objectFit: "cover",
+ objectPosition: "center",
+});
+
+export const CrowdfundActionButtonRow = styled(Box)({
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "space-between",
+ width: "100%",
+});
+
+export const CrowdfundActionButton = styled(Button)(({ theme }) => ({
+ display: "flex",
+ alignItems: "center",
+ fontFamily: "Montserrat",
+ fontSize: "16px",
+ fontWeight: 400,
+ letterSpacing: "0.2px",
+ color: "white",
+ gap: "5px",
+}));
+
+export const BackToHomeButton = styled(Button)(({ theme }) => ({
+ position: "absolute",
+ top: "20px",
+ left: "20px",
+ display: "flex",
+ alignItems: "center",
+ fontFamily: "Montserrat",
+ fontSize: "13px",
+ fontWeight: 400,
+ letterSpacing: "0.2px",
+ color: "white",
+ gap: "5px",
+ padding: "5px 10px",
+ backgroundColor: theme.palette.secondary.main,
+ transition: "all 0.3s ease-in-out",
+ "&:hover": {
+ backgroundColor: theme.palette.secondary.dark,
+ cursor: "pointer",
+ },
+}));
+
+export const CrowdfundLoaderRow = styled(Box)({
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "center",
+ gap: "10px",
+ padding: "10px",
+});
+
+export const RatingContainer = styled(Box)({
+ display: "flex",
+ alignItems: "center",
+ padding: "1px 5px",
+ borderRadius: "5px",
+ backgroundColor: "transparent",
+ transition: "all 0.3s ease-in-out",
+ "&:hover": {
+ cursor: "pointer",
+ backgroundColor: "#e4ddddac",
+ },
+});
+
+export const StyledRating = styled(Rating)({
+ fontSize: "28px",
+});
+
+export const NoReviewsFont = styled(Typography)(({ theme }) => ({
+ fontFamily: "Mulish",
+ fontWeight: 400,
+ letterSpacing: 0,
+ color: theme.palette.text.primary,
+}));
+
+export const StyledButton = styled(Button)(({ theme }) => ({
+ fontWeight: 600,
+ color: theme.palette.text.primary
+}))
+
+export const CustomSelect = styled(Select)(({ theme }) => ({
+ fontFamily: "Mulish",
+ fontSize: "19px",
+ letterSpacing: "0px",
+ fontWeight: 400,
+ color: theme.palette.text.primary,
+ backgroundColor: theme.palette.background.default,
+ '& .MuiSelect-select': {
+ padding: '12px',
+ fontFamily: "Mulish",
+ fontSize: "19px",
+ letterSpacing: "0px",
+ fontWeight: 400,
+ borderRadius: theme.shape.borderRadius, // Match border radius
+ },
+ '&:before': {
+ // Underline style
+ borderBottomColor: theme.palette.mode === "light" ? "#B2BAC2" : "#c9cccf",
+ },
+ '&:after': {
+ // Underline style when focused
+ borderBottomColor: theme.palette.secondary.main,
+ },
+ '& .MuiOutlinedInput-root': {
+ '& fieldset': {
+ borderColor: "#E0E3E7",
+ },
+ '&:hover fieldset': {
+ borderColor: "#B2BAC2",
+ },
+ '&.Mui-focused fieldset': {
+ borderColor: "#6F7E8C",
+ },
+ },
+ '& .MuiInputBase-root': {
+ fontFamily: "Mulish",
+ fontSize: "19px",
+ letterSpacing: "0px",
+ fontWeight: 400,
+ color: theme.palette.text.primary,
+ },
+}));
diff --git a/src/components/PlaylistListEdit/PlaylistListEdit.tsx b/src/components/PlaylistListEdit/PlaylistListEdit.tsx
new file mode 100644
index 0000000..7a9c208
--- /dev/null
+++ b/src/components/PlaylistListEdit/PlaylistListEdit.tsx
@@ -0,0 +1,210 @@
+import React, { useState } from "react";
+import { CardContentContainerComment } from "../common/Comments/Comments-styles";
+import {
+ CrowdfundSubTitle,
+ CrowdfundSubTitleRow,
+} from "../PublishIssue/Upload-styles.tsx";
+import { Box, Button, Input, Typography, useTheme } from "@mui/material";
+import { useNavigate } from "react-router-dom";
+import DeleteOutlineIcon from "@mui/icons-material/DeleteOutline";
+import AddIcon from "@mui/icons-material/Add";
+import { QSUPPORT_FILE_BASE } from "../../constants/Identifiers.ts";
+import { useSelector } from "react-redux";
+import { RootState } from "../../state/store";
+
+export const PlaylistListEdit = ({ playlistData, removeVideo, addVideo }) => {
+ const theme = useTheme();
+ const navigate = useNavigate();
+ const username = useSelector((state: RootState) => state.auth?.user?.name);
+
+ const [searchResults, setSearchResults] = useState([]);
+ const [filterSearch, setFilterSearch] = useState("");
+ const search = async () => {
+ const url = `/arbitrary/resources/search?mode=ALL&service=DOCUMENT&mode=ALL&identifier=${QSUPPORT_FILE_BASE}&title=${filterSearch}&limit=20&includemetadata=true&reverse=true&name=${username}&exactmatchnames=true&offset=0`;
+ const response = await fetch(url, {
+ method: "GET",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+ const responseDataSearchVid = await response.json();
+ setSearchResults(responseDataSearchVid);
+ };
+
+ return (
+
+
+
+ Playlist
+
+
+ {playlistData?.videos?.map((vid, index) => {
+ return (
+
+
+ {index + 1}
+
+
+ {vid?.metadata?.title}
+
+ {
+ removeVideo(index);
+ }}
+ sx={{
+ cursor: "pointer",
+ }}
+ />
+
+ );
+ })}
+
+
+
+
+ Add videos to playlist
+
+
+
+ {
+ setFilterSearch(e.target.value);
+ }}
+ value={filterSearch}
+ placeholder="Search by title"
+ sx={{
+ borderBottom: "1px solid white",
+ "&&:before": {
+ borderBottom: "none",
+ },
+ "&&:after": {
+ borderBottom: "none",
+ },
+ "&&:hover:before": {
+ borderBottom: "none",
+ },
+ "&&.Mui-focused:before": {
+ borderBottom: "none",
+ },
+ "&&.Mui-focused": {
+ outline: "none",
+ },
+ fontSize: "18px",
+ }}
+ />
+
+
+
+ {searchResults?.map((vid, index) => {
+ return (
+
+
+ {index + 1}
+
+
+ {vid?.metadata?.title}
+
+ {
+ addVideo(vid);
+ }}
+ sx={{
+ cursor: "pointer",
+ }}
+ />
+
+ );
+ })}
+
+
+
+ );
+};
diff --git a/src/components/Playlists/Playlists.tsx b/src/components/Playlists/Playlists.tsx
new file mode 100644
index 0000000..0ac3c6f
--- /dev/null
+++ b/src/components/Playlists/Playlists.tsx
@@ -0,0 +1,79 @@
+import React from "react";
+import { CardContentContainerComment } from "../common/Comments/Comments-styles";
+import {
+ CrowdfundSubTitle,
+ CrowdfundSubTitleRow,
+} from "../PublishIssue/Upload-styles.tsx";
+import { Box, Typography, useTheme } from "@mui/material";
+import { useNavigate } from "react-router-dom";
+
+export const Playlists = ({ playlistData, currentVideoIdentifier }) => {
+ const theme = useTheme();
+ const navigate = useNavigate();
+
+ return (
+
+
+ Playlist
+
+
+ {playlistData?.videos?.map((vid, index) => {
+ const isCurrentVidPlayling =
+ vid?.identifier === currentVideoIdentifier;
+
+ return (
+ {
+ if (isCurrentVidPlayling) return;
+
+ navigate(`/video/${vid.name}/${vid.identifier}`);
+ }}
+ >
+
+ {index + 1}
+
+
+ {vid?.metadata?.title}
+
+
+ );
+ })}
+
+
+ );
+};
diff --git a/src/components/PublishIssue/PublishIssue.tsx b/src/components/PublishIssue/PublishIssue.tsx
new file mode 100644
index 0000000..2fddf9c
--- /dev/null
+++ b/src/components/PublishIssue/PublishIssue.tsx
@@ -0,0 +1,493 @@
+import React, { useEffect, useRef, useState } from "react";
+import {
+ ActionButton,
+ ActionButtonRow,
+ CustomInputField,
+ ModalBody,
+ NewCrowdfundTitle,
+ StyledButton,
+} from "./Upload-styles";
+import { Box, Modal, Typography, useTheme } from "@mui/material";
+import RemoveIcon from "@mui/icons-material/Remove";
+import ShortUniqueId from "short-unique-id";
+import { useDispatch, useSelector } from "react-redux";
+import AddBoxIcon from "@mui/icons-material/AddBox";
+import { useDropzone } from "react-dropzone";
+
+import { setNotification } from "../../state/features/notificationsSlice";
+import { objectToBase64 } from "../../utils/toBase64";
+import { RootState } from "../../state/store";
+import { QSUPPORT_FILE_BASE } from "../../constants/Identifiers.ts";
+import { MultiplePublish } from "../common/MultiplePublish/MultiplePublishAll";
+import { TextEditor } from "../common/TextEditor/TextEditor";
+import { extractTextFromHTML } from "../common/TextEditor/utils";
+import { allCategoryData } from "../../constants/Categories/1stCategories.ts";
+import { titleFormatter } from "../../constants/Misc.ts";
+import {
+ appendCategoryToList,
+ CategoryList,
+ CategoryListRef,
+} from "../common/CategoryList/CategoryList.tsx";
+import { SupportState } from "../../constants/Categories/2ndCategories.ts";
+import {
+ ImagePublisher,
+ ImagePublisherRef,
+} from "../common/ImagePublisher/ImagePublisher.tsx";
+
+const uid = new ShortUniqueId();
+const shortuid = new ShortUniqueId({ length: 5 });
+
+interface NewCrowdfundProps {
+ editId?: string;
+ editContent?: null | {
+ title: string;
+ user: string;
+ coverImage: string | null;
+ };
+}
+
+interface VideoFile {
+ file: File;
+ title: string;
+ description: string;
+ coverImage?: string;
+}
+export const PublishIssue = ({ editId, editContent }: NewCrowdfundProps) => {
+ const theme = useTheme();
+ const dispatch = useDispatch();
+ const [isOpenMultiplePublish, setIsOpenMultiplePublish] = useState(false);
+ const username = useSelector((state: RootState) => state.auth?.user?.name);
+ const userAddress = useSelector(
+ (state: RootState) => state.auth?.user?.address
+ );
+ const [files, setFiles] = useState([]);
+
+ const [isOpen, setIsOpen] = useState(false);
+ const [title, setTitle] = useState("");
+ const [description, setDescription] = useState("");
+ const [step, setStep] = useState("videos");
+ const [playlistCoverImage, setPlaylistCoverImage] = useState(
+ null
+ );
+ const [selectExistingPlaylist, setSelectExistingPlaylist] =
+ useState(null);
+ const [playlistTitle, setPlaylistTitle] = useState("");
+ const [playlistDescription, setPlaylistDescription] = useState("");
+ const [selectedCategory, setSelectedCategory] = useState(null);
+ const [selectedSubCategory, setSelectedSubCategory] = useState(null);
+
+ const [playlistSetting, setPlaylistSetting] = useState(null);
+ const [publishes, setPublishes] = useState(null);
+ const categoryListRef = useRef(null);
+ const imagePublisherRef = useRef(null);
+ const { getRootProps, getInputProps } = useDropzone({
+ maxFiles: 10,
+ maxSize: 419430400, // 400 MB in bytes
+ onDrop: (acceptedFiles, rejectedFiles) => {
+ const formatArray = acceptedFiles.map(item => {
+ return {
+ file: item,
+ title: "",
+ description: "",
+ coverImage: "",
+ };
+ });
+
+ setFiles(prev => [...prev, ...formatArray]);
+
+ let errorString = null;
+ rejectedFiles.forEach(({ file, errors }) => {
+ errors.forEach(error => {
+ if (error.code === "file-too-large") {
+ errorString = "File must be under 400mb";
+ }
+ console.log(`Error with file ${file.name}: ${error.message}`);
+ });
+ });
+ if (errorString) {
+ const notificationObj = {
+ msg: errorString,
+ alertType: "error",
+ };
+
+ dispatch(setNotification(notificationObj));
+ }
+ },
+ });
+
+ useEffect(() => {
+ if (editContent) {
+ }
+ }, [editContent]);
+
+ const onClose = () => {
+ setIsOpen(false);
+ };
+
+ async function publishQDNResource() {
+ try {
+ if (!categoryListRef.current) throw new Error("No CategoryListRef found");
+ if (!userAddress) throw new Error("Unable to locate user address");
+
+ if (!title) throw new Error("Please enter a title");
+ if (!description) throw new Error("Please enter a description");
+ if (!categoryListRef.current?.getSelectedCategories()[0])
+ throw new Error("Please select a category");
+ let errorMsg = "";
+ let name = "";
+ if (username) {
+ name = username;
+ }
+ if (!name) {
+ errorMsg =
+ "Cannot publish without access to your name. Please authenticate.";
+ }
+
+ if (editId && editContent?.user !== name) {
+ errorMsg = "Cannot publish another user's resource";
+ }
+
+ if (errorMsg) {
+ dispatch(
+ setNotification({
+ msg: errorMsg,
+ alertType: "error",
+ })
+ );
+ return;
+ }
+
+ let fileReferences = [];
+
+ let listOfPublishes = [];
+
+ const fullDescription = extractTextFromHTML(description);
+
+ const sanitizeTitle = title
+ .replace(/[^a-zA-Z0-9\s-]/g, "")
+ .replace(/\s+/g, "-")
+ .replace(/-+/g, "-")
+ .trim()
+ .toLowerCase();
+
+ for (const publish of files) {
+ const file = publish.file;
+ const id = uid();
+
+ const identifier = `${QSUPPORT_FILE_BASE}${sanitizeTitle.slice(0, 30)}_${id}`;
+
+ let fileExtension = "";
+ const fileExtensionSplit = file?.name?.split(".");
+ if (fileExtensionSplit?.length > 1) {
+ fileExtension = fileExtensionSplit?.pop() || "";
+ }
+ let firstPartName = fileExtensionSplit[0];
+
+ let filename = firstPartName.slice(0, 15);
+
+ // Step 1: Replace all white spaces with underscores
+
+ // Replace all forms of whitespace (including non-standard ones) with underscores
+ let stringWithUnderscores = filename.replace(/[\s\uFEFF\xA0]+/g, "_");
+
+ // Remove all non-alphanumeric characters (except underscores)
+ let alphanumericString = stringWithUnderscores.replace(
+ /[^a-zA-Z0-9_]/g,
+ ""
+ );
+
+ if (fileExtension) {
+ filename = `${alphanumericString.trim()}.${fileExtension}`;
+ } else {
+ filename = alphanumericString;
+ }
+
+ const categoryList = appendCategoryToList(
+ categoryListRef.current?.getSelectedCategories(),
+ "101"
+ );
+ const categoryString = `**${categoryListRef.current?.getCategoriesFetchString(categoryList)}**`;
+ let metadescription = categoryString + fullDescription.slice(0, 150);
+
+ const requestBodyVideo: any = {
+ action: "PUBLISH_QDN_RESOURCE",
+ name: name,
+ service: "FILE",
+ file,
+ title: title.slice(0, 50),
+ description: metadescription,
+ identifier,
+ filename,
+ tag1: QSUPPORT_FILE_BASE,
+ };
+ listOfPublishes.push(requestBodyVideo);
+ fileReferences.push({
+ filename: file.name,
+ identifier,
+ name,
+ service: "FILE",
+ mimetype: file.type,
+ size: file.size,
+ });
+ }
+
+ const idMeta = uid();
+ const identifier = `${QSUPPORT_FILE_BASE}${sanitizeTitle.slice(0, 30)}_${idMeta}`;
+
+ const categoryList = appendCategoryToList(
+ categoryListRef.current?.getSelectedCategories(),
+ "101"
+ );
+
+ const fileObject: any = {
+ title,
+ version: 1,
+ fullDescription,
+ htmlDescription: description,
+ commentsId: `${QSUPPORT_FILE_BASE}_cm_${idMeta}`,
+ ...categoryListRef.current?.categoriesToObject(categoryList),
+ files: fileReferences,
+ images: imagePublisherRef?.current?.getImageArray(),
+ };
+
+ const categoryString = `**${categoryListRef.current?.getCategoriesFetchString(categoryList)}**`;
+ let metadescription = categoryString + fullDescription.slice(0, 150);
+
+ const fileObjectToBase64 = await objectToBase64(fileObject);
+ // Description is obtained from raw data
+ const requestBodyJson: any = {
+ action: "PUBLISH_QDN_RESOURCE",
+ name: name,
+ service: "DOCUMENT",
+ data64: fileObjectToBase64,
+ title: title.slice(0, 50),
+ description: metadescription,
+ identifier: identifier + "_metadata",
+ tag1: QSUPPORT_FILE_BASE,
+ filename: `video_metadata.json`,
+ };
+ listOfPublishes.push(requestBodyJson);
+
+ const multiplePublish = {
+ action: "PUBLISH_MULTIPLE_QDN_RESOURCES",
+ resources: [...listOfPublishes],
+ };
+ setPublishes(multiplePublish);
+ setIsOpenMultiplePublish(true);
+ } catch (error: any) {
+ let notificationObj: any = null;
+ if (typeof error === "string") {
+ notificationObj = {
+ msg: error || "Failed to publish issue",
+ alertType: "error",
+ };
+ } else if (typeof error?.error === "string") {
+ notificationObj = {
+ msg: error?.error || "Failed to publish issue",
+ alertType: "error",
+ };
+ } else {
+ notificationObj = {
+ msg: error?.message || "Failed to publish issue",
+ alertType: "error",
+ };
+ }
+ if (!notificationObj) return;
+ dispatch(setNotification(notificationObj));
+ }
+ }
+
+ return (
+ <>
+ {username && (
+ <>
+ {editId ? null : (
+ }
+ onClick={() => {
+ setIsOpen(true);
+ }}
+ >
+ Open an Issue
+
+ )}
+ >
+ )}
+
+
+
+
+ Issue
+
+
+ {step === "videos" && (
+ <>
+
+
+
+ Publish files related to issue (Optional)
+
+
+ {files.map((file, index) => {
+ return (
+
+
+ {file?.file?.name}
+ {
+ setFiles(prev => {
+ const copyPrev = [...prev];
+ copyPrev.splice(index, 1);
+ return copyPrev;
+ });
+ }}
+ sx={{
+ cursor: "pointer",
+ }}
+ />
+
+
+ );
+ })}
+
+ <>
+
+
+
+
+ {
+ const value = e.target.value;
+ const formattedValue = value.replace(titleFormatter, "");
+ setTitle(formattedValue);
+ }}
+ inputProps={{ maxLength: 180 }}
+ required
+ />
+
+ Description of Issue
+
+ {
+ setDescription(value);
+ }}
+ />
+ >
+ >
+ )}
+
+ {
+ onClose();
+ }}
+ variant="contained"
+ color="error"
+ >
+ Cancel
+
+
+ {
+ publishQDNResource();
+ }}
+ >
+ Publish
+
+
+
+
+
+
+ {isOpenMultiplePublish && (
+ {
+ setIsOpenMultiplePublish(false);
+ setPublishes(null);
+ if (messageNotification) {
+ dispatch(
+ setNotification({
+ msg: messageNotification,
+ alertType: "error",
+ })
+ );
+ }
+ }}
+ onSubmit={() => {
+ setIsOpenMultiplePublish(false);
+ setIsOpen(false);
+ setFiles([]);
+ setStep("videos");
+ setPlaylistCoverImage(null);
+ setPlaylistTitle("");
+ setPlaylistDescription("");
+ setSelectedCategory(null);
+ setSelectedSubCategory(null);
+ setPlaylistSetting(null);
+ categoryListRef.current?.clearCategories();
+ dispatch(
+ setNotification({
+ msg: "Issue published",
+ alertType: "success",
+ })
+ );
+ }}
+ publishes={publishes}
+ />
+ )}
+ >
+ );
+};
diff --git a/src/components/PublishIssue/Upload-styles.tsx b/src/components/PublishIssue/Upload-styles.tsx
new file mode 100644
index 0000000..b448902
--- /dev/null
+++ b/src/components/PublishIssue/Upload-styles.tsx
@@ -0,0 +1,585 @@
+import { styled } from "@mui/system";
+import {
+ Accordion,
+ AccordionDetails,
+ AccordionSummary,
+ Box,
+ Button,
+ Grid,
+ Rating,
+ Select,
+ TextField,
+ Typography,
+} from "@mui/material";
+import AddPhotoAlternateIcon from "@mui/icons-material/AddPhotoAlternate";
+import { TimesSVG } from "../../assets/svgs/TimesSVG";
+
+export const DoubleLine = styled(Typography)`
+ display: -webkit-box;
+ -webkit-box-orient: vertical;
+ -webkit-line-clamp: 3;
+ overflow: hidden;
+`;
+
+export const MainContainer = styled(Grid)({
+ width: "100%",
+ display: "flex",
+ alignItems: "flex-start",
+ justifyContent: "center",
+ margin: 0,
+});
+
+export const MainCol = styled(Grid)(({ theme }) => ({
+ display: "flex",
+ flexDirection: "column",
+ alignItems: "center",
+ width: "100%",
+ padding: "20px",
+}));
+
+export const CreateContainer = styled(Box)(({ theme }) => ({
+ position: "fixed",
+ bottom: "20px",
+ right: "20px",
+ cursor: "pointer",
+ background: theme.palette.background.default,
+ width: "50px",
+ height: "50px",
+ display: "flex",
+ justifyContent: "center",
+ alignItems: "center",
+ borderRadius: "50%",
+}));
+
+export const ModalBody = styled(Box)(({ theme }) => ({
+ position: "absolute",
+ backgroundColor: theme.palette.background.default,
+ borderRadius: "4px",
+ top: "50%",
+ left: "50%",
+ transform: "translate(-50%, -50%)",
+ width: "75%",
+ maxWidth: "900px",
+ padding: "15px 35px",
+ display: "flex",
+ flexDirection: "column",
+ gap: "17px",
+ overflowY: "auto",
+ maxHeight: "95vh",
+ boxShadow:
+ theme.palette.mode === "dark"
+ ? "0px 4px 5px 0px hsla(0,0%,0%,0.14), 0px 1px 10px 0px hsla(0,0%,0%,0.12), 0px 2px 4px -1px hsla(0,0%,0%,0.2)"
+ : "rgba(99, 99, 99, 0.2) 0px 2px 8px 0px",
+ "&::-webkit-scrollbar-track": {
+ backgroundColor: theme.palette.background.paper,
+ },
+ "&::-webkit-scrollbar-track:hover": {
+ backgroundColor: theme.palette.background.paper,
+ },
+ "&::-webkit-scrollbar": {
+ width: "16px",
+ height: "10px",
+ backgroundColor: theme.palette.mode === "light" ? "#f6f8fa" : "#292d3e",
+ },
+ "&::-webkit-scrollbar-thumb": {
+ backgroundColor: theme.palette.mode === "light" ? "#d3d9e1" : "#575757",
+ borderRadius: "8px",
+ backgroundClip: "content-box",
+ border: "4px solid transparent",
+ },
+ "&::-webkit-scrollbar-thumb:hover": {
+ backgroundColor: theme.palette.mode === "light" ? "#b7bcc4" : "#474646",
+ },
+}));
+
+export const NewCrowdfundTitle = styled(Typography)(({ theme }) => ({
+ fontWeight: 400,
+ fontFamily: "Raleway",
+ fontSize: "25px",
+ userSelect: "none",
+}));
+export const NewCrowdFundFont = styled(Typography)(({ theme }) => ({
+ fontWeight: 400,
+ fontFamily: "Raleway",
+ fontSize: "18px",
+ userSelect: "none",
+}));
+export const NewCrowdfundTimeDescription = styled(Typography)(({ theme }) => ({
+ fontWeight: 400,
+ fontFamily: "Raleway",
+ fontSize: "18px",
+ userSelect: "none",
+ fontStyle: "italic",
+ textDecoration: "underline",
+}));
+
+export const CustomInputField = styled(TextField)(({ theme }) => ({
+ fontFamily: "Mulish",
+ fontSize: "19px",
+ letterSpacing: "0px",
+ fontWeight: 400,
+ color: theme.palette.text.primary,
+ backgroundColor: theme.palette.background.default,
+ borderColor: theme.palette.background.paper,
+ "& label": {
+ color: theme.palette.mode === "light" ? "#808183" : "#edeef0",
+ fontFamily: "Mulish",
+ fontSize: "19px",
+ letterSpacing: "0px",
+ fontWeight: 400,
+ },
+ "& label.Mui-focused": {
+ color: theme.palette.mode === "light" ? "#A0AAB4" : "#d7d8da",
+ },
+ "& .MuiInput-underline:after": {
+ borderBottomColor: theme.palette.mode === "light" ? "#B2BAC2" : "#c9cccf",
+ },
+ "& .MuiOutlinedInput-root": {
+ "& fieldset": {
+ borderColor: "#E0E3E7",
+ },
+ "&:hover fieldset": {
+ borderColor: "#B2BAC2",
+ },
+ "&.Mui-focused fieldset": {
+ borderColor: "#6F7E8C",
+ },
+ },
+ "& .MuiInputBase-root": {
+ fontFamily: "Mulish",
+ fontSize: "19px",
+ letterSpacing: "0px",
+ fontWeight: 400,
+ },
+ "& [class$='-MuiFilledInput-root']": {
+ padding: "30px 12px 8px",
+ },
+ "& .MuiFilledInput-root:after": {
+ borderBottomColor: theme.palette.secondary.main,
+ },
+}));
+
+export const CrowdfundTitle = styled(Typography)(({ theme }) => ({
+ fontFamily: "Copse",
+ letterSpacing: "1px",
+ fontWeight: 400,
+ fontSize: "20px",
+ color: theme.palette.text.primary,
+ userSelect: "none",
+ wordBreak: "break-word",
+}));
+
+export const CrowdfundSubTitleRow = styled(Box)({
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "center",
+ width: "100%",
+ flexDirection: "row",
+});
+
+export const CrowdfundSubTitle = styled(Typography)(({ theme }) => ({
+ fontFamily: "Copse",
+ letterSpacing: "1px",
+ fontWeight: 400,
+ fontSize: "17px",
+ color: theme.palette.text.primary,
+ userSelect: "none",
+ wordBreak: "break-word",
+ borderBottom: `1px solid ${theme.palette.text.primary}`,
+ paddingBottom: "1.5px",
+ width: "fit-content",
+ textDecoration: "none",
+}));
+
+export const CrowdfundDescription = styled(Typography)(({ theme }) => ({
+ fontFamily: "Raleway",
+ fontSize: "16px",
+ color: theme.palette.text.primary,
+ userSelect: "none",
+ wordBreak: "break-word",
+}));
+
+export const Spacer = ({ height }: any) => {
+ return (
+
+ );
+};
+
+export const StyledCardHeaderComment = styled(Box)({
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "flex-start",
+ gap: "5px",
+ padding: "7px 0px",
+});
+export const StyledCardCol = styled(Box)({
+ display: "flex",
+ overflow: "hidden",
+ flexDirection: "column",
+ gap: "2px",
+ alignItems: "flex-start",
+ width: "100%",
+});
+
+export const StyledCardColComment = styled(Box)({
+ display: "flex",
+ overflow: "hidden",
+ flexDirection: "column",
+ gap: "2px",
+ alignItems: "flex-start",
+ width: "100%",
+});
+
+export const AuthorTextComment = styled(Typography)({
+ fontFamily: "Raleway, sans-serif",
+ fontSize: "16px",
+ lineHeight: "1.2",
+});
+
+export const AddLogoIcon = styled(AddPhotoAlternateIcon)(({ theme }) => ({
+ color: "#fff",
+ height: "25px",
+ width: "auto",
+}));
+
+export const CoverImagePreview = styled("img")(({ theme }) => ({
+ width: "100px",
+ height: "100px",
+ objectFit: "contain",
+ userSelect: "none",
+ borderRadius: "3px",
+ marginBottom: "10px",
+}));
+
+export const LogoPreviewRow = styled(Box)(({ theme }) => ({
+ display: "flex",
+ alignItems: "center",
+ gap: "10px",
+}));
+
+export const TimesIcon = styled(TimesSVG)(({ theme }) => ({
+ backgroundColor: theme.palette.background.paper,
+ borderRadius: "50%",
+ padding: "5px",
+ transition: "all 0.2s ease-in-out",
+ "&:hover": {
+ cursor: "pointer",
+ scale: "1.1",
+ },
+}));
+
+export const CrowdfundCardTitle = styled(DoubleLine)(({ theme }) => ({
+ fontFamily: "Montserrat",
+ fontSize: "24px",
+ letterSpacing: "-0.3px",
+ userSelect: "none",
+ marginBottom: "auto",
+ textAlign: "center",
+ "@media (max-width: 650px)": {
+ fontSize: "18px",
+ },
+}));
+
+export const CrowdfundUploadDate = styled(Typography)(({ theme }) => ({
+ fontFamily: "Montserrat",
+ fontSize: "12px",
+ letterSpacing: "0.2px",
+ color: theme.palette.text.primary,
+ userSelect: "none",
+}));
+
+export const CATContainer = styled(Box)(({ theme }) => ({
+ position: "relative",
+ display: "flex",
+ padding: "15px",
+ flexDirection: "column",
+ gap: "20px",
+ justifyContent: "center",
+ width: "100%",
+ alignItems: "center",
+}));
+
+export const AddCrowdFundButton = styled(Button)(({ theme }) => ({
+ display: "flex",
+ alignItems: "center",
+ textTransform: "none",
+ padding: "10px 25px",
+ fontSize: "15px",
+ gap: "8px",
+ color: "#ffffff",
+ backgroundColor:
+ theme.palette.mode === "dark" ? theme.palette.primary.main : "#2a9a86",
+ border: "none",
+ borderRadius: "5px",
+ transition: "all 0.3s ease-in-out",
+ "&:hover": {
+ cursor: "pointer",
+ backgroundColor:
+ theme.palette.mode === "dark" ? theme.palette.primary.dark : "#217e6d",
+ },
+}));
+
+export const EditCrowdFundButton = styled(Button)(({ theme }) => ({
+ display: "flex",
+ alignItems: "center",
+ textTransform: "none",
+ padding: "5px 12px",
+ gap: "8px",
+ color: "#ffffff",
+ backgroundColor:
+ theme.palette.mode === "dark" ? theme.palette.primary.main : "#2a9a86",
+ border: "none",
+ borderRadius: "5px",
+ transition: "all 0.3s ease-in-out",
+ "&:hover": {
+ cursor: "pointer",
+ backgroundColor:
+ theme.palette.mode === "dark" ? theme.palette.primary.dark : "#217e6d",
+ },
+}));
+
+export const CrowdfundListWrapper = styled(Box)(({ theme }) => ({
+ width: "100%",
+ display: "flex",
+ flexDirection: "column",
+ alignItems: "center",
+ marginTop: "0px",
+ background: theme.palette.background.default,
+}));
+
+export const CrowdfundTitleRow = styled(Box)(({ theme }) => ({
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "center",
+ width: "100%",
+ gap: "10px",
+}));
+
+export const CrowdfundPageTitle = styled(Typography)(({ theme }) => ({
+ fontFamily: "Copse",
+ fontSize: "35px",
+ fontWeight: 400,
+ letterSpacing: "1px",
+ userSelect: "none",
+ color: theme.palette.text.primary,
+}));
+
+export const CrowdfundStatusRow = styled(Box)(({ theme }) => ({
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "center",
+ fontFamily: "Mulish",
+ fontSize: "21px",
+ fontWeight: 400,
+ letterSpacing: 0,
+ border: `1px solid ${theme.palette.text.primary}`,
+ borderRadius: "8px",
+ padding: "15px 25px",
+ userSelect: "none",
+}));
+
+export const CrowdfundDescriptionRow = styled(Box)({
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "center",
+ width: "100%",
+ fontFamily: "Montserrat",
+ fontSize: "18px",
+ fontWeight: 400,
+ letterSpacing: 0,
+});
+
+export const AboutMyCrowdfund = styled(Typography)(({ theme }) => ({
+ fontFamily: "Copse",
+ fontSize: "23px",
+ fontWeight: 400,
+ letterSpacing: "1px",
+ userSelect: "none",
+ color: theme.palette.text.primary,
+}));
+
+export const CrowdfundInlineContentRow = styled(Box)({
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "center",
+ width: "100%",
+});
+
+export const CrowdfundInlineContent = styled(Box)(({ theme }) => ({
+ display: "flex",
+ fontFamily: "Mulish",
+ fontSize: "19px",
+ fontWeight: 400,
+ letterSpacing: 0,
+ userSelect: "none",
+ color: theme.palette.text.primary,
+}));
+
+export const CrowdfundAccordion = styled(Accordion)(({ theme }) => ({
+ backgroundColor: theme.palette.primary.light,
+ "& .Mui-expanded": {
+ minHeight: "auto !important",
+ },
+}));
+
+export const CrowdfundAccordionSummary = styled(AccordionSummary)({
+ height: "50px",
+ "& .Mui-expanded": {
+ margin: "0px !important",
+ },
+});
+
+export const CrowdfundAccordionFont = styled(Typography)(({ theme }) => ({
+ fontFamily: "Mulish",
+ fontSize: "20px",
+ fontWeight: 400,
+ letterSpacing: "0px",
+ color: theme.palette.text.primary,
+ userSelect: "none",
+}));
+
+export const CrowdfundAccordionDetails = styled(AccordionDetails)({
+ padding: "0px 16px 16px 16px",
+});
+
+export const AddCoverImageButton = styled(Button)(({ theme }) => ({
+ display: "flex",
+ alignItems: "center",
+ fontFamily: "Montserrat",
+ fontSize: "16px",
+ fontWeight: 400,
+ letterSpacing: "0.2px",
+ color: "white",
+ gap: "5px",
+}));
+
+export const CoverImage = styled("img")({
+ width: "100%",
+ height: "250px",
+ objectFit: "cover",
+ objectPosition: "center",
+});
+
+export const ActionButtonRow = styled(Box)({
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "space-between",
+ width: "100%",
+});
+
+export const ActionButton = styled(Button)(({ theme }) => ({
+ display: "flex",
+ alignItems: "center",
+ fontFamily: "Montserrat",
+ fontSize: "16px",
+ fontWeight: 400,
+ letterSpacing: "0.2px",
+ color: "white",
+ gap: "5px",
+}));
+
+export const BackToHomeButton = styled(Button)(({ theme }) => ({
+ position: "absolute",
+ top: "20px",
+ left: "20px",
+ display: "flex",
+ alignItems: "center",
+ fontFamily: "Montserrat",
+ fontSize: "13px",
+ fontWeight: 400,
+ letterSpacing: "0.2px",
+ color: "white",
+ gap: "5px",
+ padding: "5px 10px",
+ backgroundColor: theme.palette.secondary.main,
+ transition: "all 0.3s ease-in-out",
+ "&:hover": {
+ backgroundColor: theme.palette.secondary.dark,
+ cursor: "pointer",
+ },
+}));
+
+export const CrowdfundLoaderRow = styled(Box)({
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "center",
+ gap: "10px",
+ padding: "10px",
+});
+
+export const RatingContainer = styled(Box)({
+ display: "flex",
+ alignItems: "center",
+ padding: "1px 5px",
+ borderRadius: "5px",
+ backgroundColor: "transparent",
+ transition: "all 0.3s ease-in-out",
+ "&:hover": {
+ cursor: "pointer",
+ backgroundColor: "#e4ddddac",
+ },
+});
+
+export const StyledRating = styled(Rating)({
+ fontSize: "28px",
+});
+
+export const NoReviewsFont = styled(Typography)(({ theme }) => ({
+ fontFamily: "Mulish",
+ fontWeight: 400,
+ letterSpacing: 0,
+ color: theme.palette.text.primary,
+}));
+
+export const StyledButton = styled(Button)(({ theme }) => ({
+ fontWeight: 600,
+ color: theme.palette.text.primary,
+ fontFamily: "Cairo",
+}));
+
+export const CustomSelect = styled(Select)(({ theme }) => ({
+ fontFamily: "Mulish",
+ fontSize: "19px",
+ letterSpacing: "0px",
+ fontWeight: 400,
+ color: theme.palette.text.primary,
+ backgroundColor: theme.palette.background.default,
+ "& .MuiSelect-select": {
+ padding: "12px",
+ fontFamily: "Mulish",
+ fontSize: "19px",
+ letterSpacing: "0px",
+ fontWeight: 400,
+ borderRadius: theme.shape.borderRadius, // Match border radius
+ },
+ "&:before": {
+ // Underline style
+ borderBottomColor: theme.palette.mode === "light" ? "#B2BAC2" : "#c9cccf",
+ },
+ "&:after": {
+ // Underline style when focused
+ borderBottomColor: theme.palette.secondary.main,
+ },
+ "& .MuiOutlinedInput-root": {
+ "& fieldset": {
+ borderColor: "#E0E3E7",
+ },
+ "&:hover fieldset": {
+ borderColor: "#B2BAC2",
+ },
+ "&.Mui-focused fieldset": {
+ borderColor: "#6F7E8C",
+ },
+ },
+ "& .MuiInputBase-root": {
+ fontFamily: "Mulish",
+ fontSize: "19px",
+ letterSpacing: "0px",
+ fontWeight: 400,
+ color: theme.palette.text.primary,
+ },
+}));
diff --git a/src/components/ResponsiveImage.tsx b/src/components/ResponsiveImage.tsx
new file mode 100644
index 0000000..22d8b9d
--- /dev/null
+++ b/src/components/ResponsiveImage.tsx
@@ -0,0 +1,109 @@
+import React, { useState, useEffect, CSSProperties } from 'react'
+import Skeleton from '@mui/material/Skeleton'
+import { Box } from '@mui/material'
+
+interface ResponsiveImageProps {
+ src: string
+ width: number
+ height: number
+ alt?: string
+ className?: string
+ style?: CSSProperties
+}
+
+const ResponsiveImage: React.FC = ({
+ src,
+ width,
+ height,
+ alt,
+ className,
+ style
+}) => {
+ const [loading, setLoading] = useState(true)
+
+
+
+ const aspectRatio = (height / width) * 100
+
+
+
+ const imageStyle: CSSProperties = {
+ width: '100%',
+ height: '100%',
+ objectFit: 'cover'
+ }
+
+ const wrapperStyle: CSSProperties = {
+ position: 'relative',
+ paddingBottom: `${aspectRatio}%`,
+ overflow: 'hidden',
+ ...style
+ }
+
+ return (
+
+
+ {loading && (
+
+ )}
+
+
setLoading(false)}
+ src={src}
+ style={{
+ width: '100%',
+ height: '100%',
+ borderRadius: '8px',
+ visibility: loading ? 'hidden' : 'visible',
+ position: loading ? 'absolute' : 'unset',
+ objectFit: 'contain'
+ }}
+ />
+
+ )
+
+ return (
+
+ {loading ? (
+
+ ) : (
+
![{alt}]({src})
+ )}
+
+ )
+}
+
+export default ResponsiveImage
diff --git a/src/components/StatsData.tsx b/src/components/StatsData.tsx
new file mode 100644
index 0000000..cf25422
--- /dev/null
+++ b/src/components/StatsData.tsx
@@ -0,0 +1,67 @@
+import React, { useEffect } from "react";
+import { styled } from "@mui/system";
+import { Grid } from "@mui/material";
+import { useSelector } from "react-redux";
+import { RootState } from "../state/store.ts";
+import { useFetchFiles } from "../hooks/useFetchFiles.tsx";
+
+export const StatsData = () => {
+ const StatsCol = styled(Grid)(({ theme }) => ({
+ display: "flex",
+ flexDirection: "column",
+ width: "100%",
+ padding: "20px 0px",
+ backgroundColor: theme.palette.background.default,
+ }));
+
+ const {
+ getFiles,
+ checkAndUpdateFile,
+ getFile,
+ hashMapFiles,
+ getNewFiles,
+ checkNewFiles,
+ getFilesFiltered,
+ getFilesCount,
+ } = useFetchFiles();
+
+ const totalIssuesPublished = useSelector(
+ (state: RootState) => state.global.totalFilesPublished
+ );
+ const totalNamesPublished = useSelector(
+ (state: RootState) => state.global.totalNamesPublished
+ );
+ const issuesPerNamePublished = useSelector(
+ (state: RootState) => state.global.filesPerNamePublished
+ );
+
+ useEffect(() => {
+ getFilesCount();
+ }, [getFilesCount]);
+
+ return (
+ totalIssuesPublished > 0 && (
+
+
+ Issues Published:{" "}
+
+ {totalIssuesPublished || ""}
+
+
+
+ Publishers:{" "}
+
+ {totalNamesPublished || ""}
+
+
+
+ Average:{" "}
+
+ {issuesPerNamePublished > 0 &&
+ Number(issuesPerNamePublished).toFixed(0)}
+
+
+
+ )
+ );
+};
diff --git a/src/components/common/BlockedNamesModal/BlockedNamesModal-styles.ts b/src/components/common/BlockedNamesModal/BlockedNamesModal-styles.ts
new file mode 100644
index 0000000..05ebf6e
--- /dev/null
+++ b/src/components/common/BlockedNamesModal/BlockedNamesModal-styles.ts
@@ -0,0 +1,28 @@
+import { styled } from '@mui/system';
+import {
+ Box,
+ Modal,
+ Typography
+} from '@mui/material';
+
+export const StyledModal = styled(Modal)(({ theme }) => ({
+ display: 'flex',
+ alignItems: 'center',
+ justifyContent: 'center'
+}))
+
+export const ModalContent = styled(Box)(({ theme }) => ({
+ backgroundColor: theme.palette.primary.main,
+ padding: theme.spacing(4),
+ borderRadius: theme.spacing(1),
+ width: '40%',
+ '&:focus': {
+ outline: 'none'
+ }
+}))
+
+export const ModalText = styled(Typography)(({ theme }) => ({
+ fontFamily: "Raleway",
+ fontSize: "25px",
+ color: theme.palette.text.primary,
+}));
\ No newline at end of file
diff --git a/src/components/common/BlockedNamesModal/BlockedNamesModal.tsx b/src/components/common/BlockedNamesModal/BlockedNamesModal.tsx
new file mode 100644
index 0000000..89f60c6
--- /dev/null
+++ b/src/components/common/BlockedNamesModal/BlockedNamesModal.tsx
@@ -0,0 +1,100 @@
+import React, { useState } from "react";
+import {
+ Box,
+ Button,
+ Modal,
+ Typography,
+ SelectChangeEvent,
+ ListItem,
+ List,
+ useTheme
+} from "@mui/material";
+import {
+ StyledModal,
+ ModalContent,
+ ModalText
+} from "./BlockedNamesModal-styles";
+
+interface PostModalProps {
+ open: boolean;
+ onClose: () => void;
+}
+
+export const BlockedNamesModal: React.FC = ({
+ open,
+ onClose
+}) => {
+ const [blockedNames, setBlockedNames] = useState([]);
+ const theme = useTheme();
+ const getBlockedNames = React.useCallback(async () => {
+ try {
+ const listName = `blockedNames`;
+ const response = await qortalRequest({
+ action: "GET_LIST_ITEMS",
+ list_name: listName
+ });
+ setBlockedNames(response);
+ } catch (error) {
+ onClose();
+ }
+ }, []);
+
+ React.useEffect(() => {
+ getBlockedNames();
+ }, [getBlockedNames]);
+
+ const removeFromBlockList = async (name: string) => {
+ try {
+ const response = await qortalRequest({
+ action: "DELETE_LIST_ITEM",
+ list_name: "blockedNames",
+ item: name
+ });
+
+ if (response === true) {
+ setBlockedNames((prev) => prev.filter((n) => n !== name));
+ }
+ } catch (error) {}
+ };
+
+ return (
+
+
+ Manage blocked names
+
+ {blockedNames.map((name, index) => (
+
+ {name}
+
+
+ ))}
+
+
+
+
+ );
+};
diff --git a/src/components/common/CategoryList/CategoryList-styles.tsx b/src/components/common/CategoryList/CategoryList-styles.tsx
new file mode 100644
index 0000000..ab2ec67
--- /dev/null
+++ b/src/components/common/CategoryList/CategoryList-styles.tsx
@@ -0,0 +1,9 @@
+import { styled } from "@mui/system";
+import { Box } from "@mui/material";
+
+export const CategoryContainer = styled(Box)(({ theme }) => ({
+ display: "flex",
+ alignItems: "center",
+ flexDirection: "row",
+ gap: "5px",
+}));
diff --git a/src/components/common/CategoryList/CategoryList.tsx b/src/components/common/CategoryList/CategoryList.tsx
new file mode 100644
index 0000000..b4057fc
--- /dev/null
+++ b/src/components/common/CategoryList/CategoryList.tsx
@@ -0,0 +1,320 @@
+import {
+ Box,
+ FormControl,
+ InputLabel,
+ MenuItem,
+ OutlinedInput,
+ Select,
+ SelectChangeEvent,
+ SxProps,
+ Theme,
+} from "@mui/material";
+
+import React, { useEffect, useImperativeHandle, useState } from "react";
+import { CategoryContainer } from "./CategoryList-styles.tsx";
+import { allCategoryData } from "../../../constants/Categories/1stCategories.ts";
+import { log } from "../../../constants/Misc.ts";
+
+export interface Category {
+ id: number;
+ name: string;
+ icon?: string;
+}
+
+export interface Categories {
+ [key: number]: Category[];
+}
+export interface CategoryData {
+ category: Category[];
+ subCategories: Categories[];
+}
+
+type ListDirection = "column" | "row";
+
+interface CategoryListProps {
+ sx?: SxProps;
+ categoryData: CategoryData;
+ initialCategories?: string[];
+ columns?: number;
+ afterChange?: (categories: string[]) => void;
+ excludeCategories?: Category[];
+}
+
+export type CategoryListRef = {
+ getSelectedCategories: () => string[];
+ setSelectedCategories: (arr: string[]) => void;
+ clearCategories: () => void;
+ getCategoriesFetchString: (categories?: string[]) => string;
+ categoriesToObject: (categories?: string[]) => object;
+};
+
+export const CategoryList = React.forwardRef<
+ CategoryListRef,
+ CategoryListProps
+>(
+ (
+ {
+ sx,
+ categoryData,
+ initialCategories,
+ columns = 1,
+ afterChange,
+ excludeCategories,
+ }: CategoryListProps,
+ ref
+ ) => {
+ const categoriesLength = categoryData.subCategories.length + 1;
+
+ let emptyCategories: string[] = [];
+ for (let i = 0; i < categoriesLength; i++) emptyCategories.push("");
+
+ const [selectedCategories, setSelectedCategories] = useState(
+ initialCategories || emptyCategories
+ );
+ useEffect(() => {
+ if (initialCategories) setSelectedCategories(initialCategories);
+ }, [initialCategories]);
+
+ const updateCategories = (categories: string[]) => {
+ setSelectedCategories(categories);
+ if (afterChange) afterChange(categories);
+ };
+ const categoriesToObject = (categories: string[]) => {
+ let categoriesObject = {};
+ categories.map((category, index) => {
+ if (index === 0) categoriesObject["category"] = category;
+ else if (index === 1) categoriesObject["subcategory"] = category;
+ else categoriesObject[`subcategory${index}`] = category;
+ });
+ if (log) console.log("categoriesObject is: ", categoriesObject);
+ return categoriesObject;
+ };
+
+ const clearCategories = () => {
+ updateCategories(emptyCategories);
+ };
+
+ useImperativeHandle(ref, () => ({
+ getSelectedCategories: () => {
+ return selectedCategories;
+ },
+ setSelectedCategories: categories => {
+ if (log) console.log("setSelectedCategories: ", categories);
+ updateCategories(categories);
+ },
+ clearCategories,
+ getCategoriesFetchString: (categories?: string[]) =>
+ getCategoriesFetchString(categories || selectedCategories),
+ categoriesToObject: (categories?: string[]) =>
+ categoriesToObject(categories || selectedCategories),
+ }));
+
+ const selectCategory = (optionId: string, index: number) => {
+ const isMainCategory = index === 0;
+ const subCategoryIndex = index - 1;
+ let selectedOption: Category | undefined;
+ if (isMainCategory)
+ selectedOption = categoryData.category.find(
+ option => option.id === +optionId
+ );
+ else {
+ const subCategoryLevel = categoryData.subCategories[subCategoryIndex];
+ const parentCategory = selectedCategories[subCategoryIndex];
+ const subCategory = subCategoryLevel[parentCategory];
+
+ selectedOption = subCategory.find(option => option.id === +optionId);
+ }
+ const newSelectedCategories: string[] = selectedCategories.map(
+ (category, categoryIndex) => {
+ if (index > categoryIndex) return category;
+ else if (index === categoryIndex) return selectedOption.id.toString();
+ else return "";
+ }
+ );
+ updateCategories(newSelectedCategories);
+ };
+
+ const selectCategoryEvent = (event: SelectChangeEvent, index: number) => {
+ const optionId = event.target.value;
+ selectCategory(optionId, index);
+ };
+
+ const categorySelectSX = {
+ // Target the input field
+ ".MuiSelect-select": {
+ fontSize: "16px", // Change font size for the selected value
+ padding: "10px 5px 15px 15px;",
+ },
+ // Target the dropdown icon
+ ".MuiSelect-icon": {
+ fontSize: "20px", // Adjust if needed
+ },
+ // Target the dropdown menu
+ "& .MuiMenu-paper": {
+ ".MuiMenuItem-root": {
+ fontSize: "14px", // Change font size for the menu items
+ },
+ },
+ };
+
+ const fillMenu = (category: Categories, index: number) => {
+ const subCategoryIndex = selectedCategories[index];
+ if (log) console.log("selected categories: ", selectedCategories);
+ if (log) console.log("index is: ", index);
+ if (log) console.log("subCategoryIndex is: ", subCategoryIndex);
+ if (log) console.log("category is: ", category);
+ if (log)
+ console.log(
+ "subCategoryIndex within category: ",
+ selectedCategories[subCategoryIndex]
+ );
+ if (log) console.log("categoryData: ", categoryData);
+
+ const menuToFill = category[subCategoryIndex];
+ if (menuToFill)
+ return menuToFill.map(option => (
+
+ ));
+ };
+
+ const hasSubCategory = (category: Categories, index: number) => {
+ const subCategoryIndex = selectedCategories[index];
+ const subCategory = category[subCategoryIndex];
+ if (excludeCategories && subCategory === excludeCategories) return false;
+ return subCategory && subCategoryIndex;
+ };
+
+ return (
+
+
+
+
+
+ Category
+
+ }
+ value={selectedCategories[0] || ""}
+ onChange={e => {
+ selectCategoryEvent(e, 0);
+ }}
+ sx={categorySelectSX}
+ >
+ {categoryData.category.map(option => (
+
+ ))}
+
+
+
+ {categoryData.subCategories.map(
+ (category, index) =>
+ hasSubCategory(category, index) && (
+
+
+ {`Category-${index + 2}`}
+
+ }
+ value={selectedCategories[index + 1] || ""}
+ onChange={e => {
+ selectCategoryEvent(e, index + 1);
+ }}
+ sx={{
+ width: "100%",
+ // Target the input field
+ ".MuiSelect-select": {
+ fontSize: "16px", // Change font size for the selected value
+ padding: "10px 5px 15px 15px;",
+ },
+ // Target the dropdown icon
+ ".MuiSelect-icon": {
+ fontSize: "20px", // Adjust if needed
+ },
+ // Target the dropdown menu
+ "& .MuiMenu-paper": {
+ ".MuiMenuItem-root": {
+ fontSize: "14px", // Change font size for the menu items
+ },
+ },
+ }}
+ >
+ {fillMenu(category, index)}
+
+
+ )
+ )}
+
+
+
+ );
+ }
+);
+
+export const getCategoriesFetchString = (categories: string[]) => {
+ let fetchString = "";
+ categories.map((category, index) => {
+ if (category) {
+ if (index === 0) fetchString += `cat:${category}`;
+ else if (index === 1) fetchString += `;sub:${category}`;
+ else fetchString += `;sub${index}:${category}`;
+ }
+ });
+ if (log) console.log("categoriesAsDescription: ", fetchString);
+ return fetchString;
+};
+
+export const appendCategoryToList = (
+ categories: string[],
+ appendedCategoryID: string
+) => {
+ const filteredCategories = categories.filter(
+ categoryString => categoryString.length > 0
+ );
+ filteredCategories.push(appendedCategoryID);
+ return filteredCategories;
+};
+
+export const getCategoriesFromObject = (editFileProperties: any) => {
+ const categoryList: string[] = [];
+ const categoryCount = allCategoryData.subCategories.length + 1;
+
+ for (let i = 0; i < categoryCount; i++) {
+ if (i === 0 && editFileProperties.category)
+ categoryList.push(editFileProperties.category);
+ else if (i === 1 && editFileProperties.subcategory)
+ categoryList.push(editFileProperties.subcategory);
+ else categoryList.push(editFileProperties[`subcategory${i}`] || "");
+ }
+ return categoryList;
+};
diff --git a/src/components/common/CategoryList/CategorySelect.tsx b/src/components/common/CategoryList/CategorySelect.tsx
new file mode 100644
index 0000000..e69de29
diff --git a/src/components/common/Comments/Comment.tsx b/src/components/common/Comments/Comment.tsx
new file mode 100644
index 0000000..d7b9f76
--- /dev/null
+++ b/src/components/common/Comments/Comment.tsx
@@ -0,0 +1,295 @@
+import {
+ Avatar,
+ Box,
+ Button,
+ Dialog,
+ DialogActions,
+ DialogContent,
+ DialogTitle,
+ Typography,
+ useTheme,
+} from "@mui/material";
+import React, { useCallback, useState, useEffect } from "react";
+import { CommentEditor } from "./CommentEditor";
+import {
+ CardContentContainerComment,
+ CommentActionButtonRow,
+ CommentDateText,
+ EditReplyButton,
+ StyledCardComment,
+} from "./Comments-styles";
+import { StyledCardHeaderComment } from "./Comments-styles";
+import { StyledCardColComment } from "./Comments-styles";
+import { AuthorTextComment } from "./Comments-styles";
+import {
+ StyledCardContentComment,
+ LoadMoreCommentsButton as CommentActionButton,
+} from "./Comments-styles";
+import { useSelector } from "react-redux";
+import { RootState } from "../../../state/store";
+import Portal from "../Portal";
+import { formatDate } from "../../../utils/time";
+interface CommentProps {
+ comment: any;
+ postId: string;
+ postName: string;
+ onSubmit: (obj?: any, isEdit?: boolean) => void;
+}
+export const Comment = ({
+ comment,
+ postId,
+ postName,
+ onSubmit,
+}: CommentProps) => {
+ const [isReplying, setIsReplying] = useState(false);
+ const [isEditing, setIsEditing] = useState(false);
+ const { user } = useSelector((state: RootState) => state.auth);
+ const [currentEdit, setCurrentEdit] = useState(null);
+ const theme = useTheme();
+
+ const handleSubmit = useCallback((comment: any, isEdit?: boolean) => {
+ onSubmit(comment, isEdit);
+ setCurrentEdit(null);
+ setIsReplying(false);
+ }, []);
+
+ return (
+
+ );
+};
+
+const CommentCard = ({
+ message,
+ created,
+ name,
+ replies,
+ children,
+ setCurrentEdit,
+}: any) => {
+ const [avatarUrl, setAvatarUrl] = React.useState("");
+ const { user } = useSelector((state: RootState) => state.auth);
+
+ const theme = useTheme();
+
+ const getAvatar = React.useCallback(async (author: string) => {
+ try {
+ const url = await qortalRequest({
+ action: "GET_QDN_RESOURCE_URL",
+ name: author,
+ service: "THUMBNAIL",
+ identifier: "qortal_avatar",
+ });
+
+ setAvatarUrl(url);
+ } catch (error) {
+ console.error(error);
+ }
+ }, []);
+
+ useEffect(() => {
+ getAvatar(name);
+ }, [name]);
+
+ return (
+
+
+
+
+
+
+ {name}
+
+
+
+ {message}
+
+
+ {replies?.map((reply: any) => {
+ return (
+
+
+
+ {reply?.created && (
+
+ {formatDate(+reply?.created)}
+
+ )}
+ {user?.name === reply?.name ? (
+ setCurrentEdit(reply)}
+ sx={{}}
+ >
+ edit
+
+ ) : (
+
+ )}
+
+
+
+ );
+ })}
+
+ {children}
+
+ );
+};
diff --git a/src/components/common/Comments/CommentEditor.tsx b/src/components/common/Comments/CommentEditor.tsx
new file mode 100644
index 0000000..2a25759
--- /dev/null
+++ b/src/components/common/Comments/CommentEditor.tsx
@@ -0,0 +1,254 @@
+import { Box, Button, TextField } from "@mui/material";
+import React, { useEffect, useState } from "react";
+import { useDispatch, useSelector } from "react-redux";
+import { RootState } from "../../../state/store";
+import ShortUniqueId from "short-unique-id";
+import { setNotification } from "../../../state/features/notificationsSlice";
+import { toBase64 } from "../../../utils/toBase64";
+import localforage from "localforage";
+import {
+ CommentInput,
+ CommentInputContainer,
+ SubmitCommentButton,
+} from "./Comments-styles";
+import { QSUPPORT_COMMENT_BASE } from "../../../constants/Identifiers.ts";
+const uid = new ShortUniqueId();
+
+const notification = localforage.createInstance({
+ name: "notification",
+});
+
+const MAX_ITEMS = 10;
+
+export interface Item {
+ id: string;
+ lastSeen: number;
+ postId: string;
+ postName: string;
+}
+
+export async function addItem(item: Item): Promise {
+ // Get all items
+ let notificationComments: Item[] =
+ (await notification.getItem("comments")) || [];
+
+ // Find the item with the same id, if it exists
+ let existingItemIndex = notificationComments.findIndex(i => i.id === item.id);
+
+ if (existingItemIndex !== -1) {
+ // If the item exists, update its date
+ notificationComments[existingItemIndex].lastSeen = item.lastSeen;
+ } else {
+ // If the item doesn't exist, add it
+ notificationComments.push(item);
+
+ // If adding the item has caused us to exceed the max number of items, remove the oldest one
+ if (notificationComments.length > MAX_ITEMS) {
+ notificationComments.sort((a, b) => b.lastSeen - a.lastSeen); // sort items by date, newest first
+ notificationComments.pop(); // remove the oldest item
+ }
+ }
+
+ // Store the items back into localForage
+ await notification.setItem("comments", notificationComments);
+}
+export async function updateItemDate(item: any): Promise {
+ // Get all items
+ let notificationComments: Item[] =
+ (await notification.getItem("comments")) || [];
+
+ let notificationCreatorComment: any =
+ (await notification.getItem("post-comments")) || {};
+ const findPostId = notificationCreatorComment[item.postId];
+ if (findPostId) {
+ notificationCreatorComment[item.postId].lastSeen = item.lastSeen;
+ }
+
+ // Find the item with the same id, if it exists
+ notificationComments.forEach((nc, index) => {
+ if (nc.postId === item.postId) {
+ notificationComments[index].lastSeen = item.lastSeen;
+ }
+ });
+
+ // Store the items back into localForage
+ await notification.setItem("comments", notificationComments);
+ await notification.setItem("post-comments", notificationCreatorComment);
+}
+interface CommentEditorProps {
+ postId: string;
+ postName: string;
+ onSubmit: (obj: any) => void;
+ isReply?: boolean;
+ commentId?: string;
+ isEdit?: boolean;
+ commentMessage?: string;
+}
+
+function utf8ToBase64(inputString: string): string {
+ // Encode the string as UTF-8
+ const utf8String = encodeURIComponent(inputString).replace(
+ /%([0-9A-F]{2})/g,
+ (match, p1) => String.fromCharCode(Number("0x" + p1))
+ );
+
+ // Convert the UTF-8 encoded string to base64
+ const base64String = btoa(utf8String);
+ return base64String;
+}
+
+export const CommentEditor = ({
+ onSubmit,
+ postId,
+ postName,
+ isReply,
+ commentId,
+ isEdit,
+ commentMessage,
+}: CommentEditorProps) => {
+ const [value, setValue] = useState("");
+ const dispatch = useDispatch();
+ const { user } = useSelector((state: RootState) => state.auth);
+
+ useEffect(() => {
+ if (isEdit && commentMessage) {
+ setValue(commentMessage);
+ }
+ }, [isEdit, commentMessage]);
+
+ const publishComment = async (
+ identifier: string,
+ idForNotification?: string
+ ) => {
+ let address;
+ let name;
+ let errorMsg = "";
+
+ address = user?.address;
+ name = user?.name || "";
+
+ if (!address) {
+ errorMsg = "Cannot post: your address isn't available";
+ }
+ if (!name) {
+ errorMsg = "Cannot post without a name";
+ }
+
+ if (value.length > 200) {
+ errorMsg = "Comment needs to be under 200 characters";
+ }
+
+ if (errorMsg) {
+ dispatch(
+ setNotification({
+ msg: errorMsg,
+ alertType: "error",
+ })
+ );
+ throw new Error(errorMsg);
+ }
+
+ try {
+ const base64 = utf8ToBase64(value);
+ const resourceResponse = await qortalRequest({
+ action: "PUBLISH_QDN_RESOURCE",
+ name: name,
+ service: "BLOG_COMMENT",
+ data64: base64,
+ identifier: identifier,
+ });
+ dispatch(
+ setNotification({
+ msg: "Comment successfully published",
+ alertType: "success",
+ })
+ );
+ if (idForNotification) {
+ addItem({
+ id: idForNotification,
+ lastSeen: Date.now(),
+ postId,
+ postName: postName,
+ });
+ }
+
+ return resourceResponse;
+ } catch (error: any) {
+ let notificationObj: any = null;
+ if (typeof error === "string") {
+ notificationObj = {
+ msg: error || "Failed to publish comment",
+ alertType: "error",
+ };
+ } else if (typeof error?.error === "string") {
+ notificationObj = {
+ msg: error?.error || "Failed to publish comment",
+ alertType: "error",
+ };
+ } else {
+ notificationObj = {
+ msg: error?.message || "Failed to publish comment",
+ alertType: "error",
+ };
+ }
+ if (!notificationObj) throw new Error("Failed to publish comment");
+
+ dispatch(setNotification(notificationObj));
+ throw new Error("Failed to publish comment");
+ }
+ };
+ const handleSubmit = async () => {
+ try {
+ const id = uid();
+
+ let identifier = `${QSUPPORT_COMMENT_BASE}${postId.slice(-12)}_base_${id}`;
+ let idForNotification = identifier;
+
+ if (isReply && commentId) {
+ const removeBaseCommentId = commentId;
+ removeBaseCommentId.replace("_base_", "");
+ identifier = `${QSUPPORT_COMMENT_BASE}${postId.slice(
+ -12
+ )}_reply_${removeBaseCommentId.slice(-6)}_${id}`;
+ idForNotification = commentId;
+ }
+ if (isEdit && commentId) {
+ identifier = commentId;
+ }
+
+ await publishComment(identifier, idForNotification);
+ onSubmit({
+ created: Date.now(),
+ identifier,
+ message: value,
+ service: "BLOG_COMMENT",
+ name: user?.name,
+ });
+ setValue("");
+ } catch (error) {
+ console.error(error);
+ }
+ };
+
+ return (
+
+ setValue(e.target.value)}
+ />
+
+
+ {isReply ? "Submit reply" : isEdit ? "Edit" : "Submit comment"}
+
+
+ );
+};
diff --git a/src/components/common/Comments/CommentSection.tsx b/src/components/common/Comments/CommentSection.tsx
new file mode 100644
index 0000000..8f350bf
--- /dev/null
+++ b/src/components/common/Comments/CommentSection.tsx
@@ -0,0 +1,281 @@
+import { useCallback, useEffect, useMemo, useState } from "react";
+import { CommentEditor } from "./CommentEditor";
+import { Comment } from "./Comment";
+import { CircularProgress } from "@mui/material";
+import { styled } from "@mui/system";
+import { useSelector } from "react-redux";
+import { RootState } from "../../../state/store";
+import { useLocation, useNavigate } from "react-router-dom";
+import {
+ CommentContainer,
+ CommentEditorContainer,
+ CommentsContainer,
+ LoadMoreCommentsButton,
+ LoadMoreCommentsButtonRow,
+ NoCommentsRow,
+} from "./Comments-styles";
+import { QSUPPORT_COMMENT_BASE } from "../../../constants/Identifiers.ts";
+import {
+ CrowdfundSubTitle,
+ CrowdfundSubTitleRow,
+} from "../../PublishIssue/Upload-styles.tsx";
+
+interface CommentSectionProps {
+ postId: string;
+ postName: string;
+}
+
+const Panel = styled("div")`
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ width: 100%;
+ padding-bottom: 10px;
+ height: 100%;
+ overflow: hidden;
+
+ &::-webkit-scrollbar {
+ width: 8px;
+ height: 8px;
+ }
+
+ &::-webkit-scrollbar-thumb {
+ background-color: #888;
+ border-radius: 4px;
+ }
+
+ &::-webkit-scrollbar-thumb:hover {
+ background-color: #555;
+ }
+`;
+export const CommentSection = ({ postId, postName }: CommentSectionProps) => {
+ const navigate = useNavigate();
+ const location = useLocation();
+ const [listComments, setListComments] = useState([]);
+ const [isOpen, setIsOpen] = useState(false);
+ const { user } = useSelector((state: RootState) => state.auth);
+ const [newMessages, setNewMessages] = useState(0);
+ const [loadingComments, setLoadingComments] = useState(false);
+
+ const onSubmit = (obj?: any, isEdit?: boolean) => {
+ if (isEdit) {
+ setListComments((prev: any[]) => {
+ const findCommentIndex = prev.findIndex(
+ item => item?.identifier === obj?.identifier
+ );
+ if (findCommentIndex === -1) return prev;
+
+ const newArray = [...prev];
+ newArray[findCommentIndex] = obj;
+ return newArray;
+ });
+
+ return;
+ }
+ setListComments(prev => [
+ ...prev,
+ {
+ ...obj,
+ },
+ ]);
+ };
+
+ useEffect(() => {
+ const query = new URLSearchParams(location.search);
+ let commentVar = query?.get("comment");
+ if (commentVar) {
+ if (commentVar && commentVar.endsWith("/")) {
+ commentVar = commentVar.slice(0, -1);
+ }
+ setIsOpen(true);
+ if (listComments.length > 0) {
+ const el = document.getElementById(commentVar);
+ if (el) {
+ el.scrollIntoView();
+ el.classList.add("glow");
+ setTimeout(() => {
+ el.classList.remove("glow");
+ }, 2000);
+ }
+ navigate(location.pathname, { replace: true });
+ }
+ }
+ }, [navigate, location, listComments]);
+
+ const getReplies = useCallback(
+ async (commentId, postId) => {
+ const offset = 0;
+
+ const removeBaseCommentId = commentId.replace("_base_", "");
+ const url = `/arbitrary/resources/search?mode=ALL&service=BLOG_COMMENT&query=${QSUPPORT_COMMENT_BASE}${postId.slice(
+ -12
+ )}_reply_${removeBaseCommentId.slice(
+ -6
+ )}&limit=0&includemetadata=false&offset=${offset}&reverse=false&excludeblocked=true`;
+ const response = await fetch(url, {
+ method: "GET",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+ const responseData = await response.json();
+ const comments: any[] = [];
+ for (const comment of responseData) {
+ if (comment.identifier && comment.name) {
+ const url = `/arbitrary/BLOG_COMMENT/${comment.name}/${comment.identifier}`;
+ const response = await fetch(url, {
+ method: "GET",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+
+ const responseData2 = await response.text();
+ if (responseData) {
+ comments.push({
+ message: responseData2,
+ ...comment,
+ });
+ }
+ }
+ }
+ return comments;
+ },
+ [postId]
+ );
+
+ const getComments = useCallback(
+ async (isNewMessages?: boolean, numberOfComments?: number) => {
+ try {
+ setLoadingComments(true);
+ let offset = 0;
+ if (isNewMessages && numberOfComments) {
+ offset = numberOfComments;
+ }
+ const url = `/arbitrary/resources/search?mode=ALL&service=BLOG_COMMENT&query=${QSUPPORT_COMMENT_BASE}${postId.slice(
+ -12
+ )}_base_&limit=20&includemetadata=false&offset=${offset}&reverse=false&excludeblocked=true`;
+ const response = await fetch(url, {
+ method: "GET",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+ const responseData = await response.json();
+ let comments: any[] = [];
+ for (const comment of responseData) {
+ if (comment.identifier && comment.name) {
+ const url = `/arbitrary/BLOG_COMMENT/${comment.name}/${comment.identifier}`;
+ const response = await fetch(url, {
+ method: "GET",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+
+ const responseData2 = await response.text();
+ if (responseData) {
+ comments.push({
+ message: responseData2,
+ ...comment,
+ });
+ }
+ const res = await getReplies(comment.identifier, postId);
+ comments = [...comments, ...res];
+ }
+ }
+ if (isNewMessages) {
+ setListComments(prev => [...prev, ...comments]);
+ setNewMessages(0);
+ } else {
+ setListComments(comments);
+ }
+ } catch (error) {
+ console.error(error);
+ } finally {
+ setLoadingComments(false);
+ }
+ },
+ [postId]
+ );
+
+ useEffect(() => {
+ getComments();
+ }, [getComments, postId]);
+
+ const structuredCommentList = useMemo(() => {
+ return listComments.reduce((acc, curr, index, array) => {
+ if (curr?.identifier?.includes("_reply_")) {
+ return acc;
+ }
+ acc.push({
+ ...curr,
+ replies: array.filter(comment =>
+ comment.identifier.includes(`_reply_${curr.identifier.slice(-6)}`)
+ ),
+ });
+ return acc;
+ }, []);
+ }, [listComments]);
+
+ return (
+ <>
+
+
+ Comments
+
+
+ {loadingComments ? (
+
+
+
+ ) : listComments.length === 0 ? (
+
+ There are no comments yet. Be the first to comment!
+
+ ) : (
+
+ {structuredCommentList.map((comment: any) => {
+ return (
+
+ );
+ })}
+
+ )}
+ {listComments.length > 20 && (
+
+ {
+ getComments(
+ true,
+ listComments.filter(
+ item => !item.identifier.includes("_reply_")
+ ).length
+ );
+ }}
+ variant="contained"
+ size="small"
+ >
+ Load More Comments
+
+
+ )}
+
+
+
+
+
+ >
+ );
+};
diff --git a/src/components/common/Comments/Comments-styles.tsx b/src/components/common/Comments/Comments-styles.tsx
new file mode 100644
index 0000000..e215c9d
--- /dev/null
+++ b/src/components/common/Comments/Comments-styles.tsx
@@ -0,0 +1,281 @@
+import { styled } from "@mui/system";
+import { Card, Box, Typography, Button, TextField } from "@mui/material";
+
+export const StyledCard = styled(Card)(({ theme }) => ({
+ backgroundColor:
+ theme.palette.mode === "light"
+ ? theme.palette.primary.main
+ : theme.palette.primary.dark,
+ maxWidth: "600px",
+ width: "100%",
+ margin: "10px 0px",
+ cursor: "pointer",
+ "@media (max-width: 450px)": {
+ width: "100%;",
+ },
+}));
+
+export const CardContentContainer = styled(Box)(({ theme }) => ({
+ backgroundColor:
+ theme.palette.mode === "light"
+ ? theme.palette.primary.dark
+ : theme.palette.primary.light,
+ margin: "5px 10px",
+ borderRadius: "15px",
+}));
+
+export const CardContentContainerComment = styled(Box)(({ theme }) => ({
+ backgroundColor: theme.palette.mode === "light" ? "#a9d9d038" : "#c3abe414",
+ border: `1px solid ${theme.palette.primary.main}`,
+ margin: "0px",
+ padding: "8px 15px",
+ borderRadius: "8px",
+ width: "100%",
+ display: "flex",
+ flexDirection: "column",
+}));
+
+export const StyledCardHeader = styled(Box)({
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "flex-start",
+ gap: "5px",
+ padding: "7px",
+});
+
+export const StyledCardHeaderComment = styled(Box)({
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "flex-start",
+ gap: "7px",
+ padding: "9px 7px",
+});
+
+export const StyledCardCol = styled(Box)({
+ display: "flex",
+ overflow: "hidden",
+ flexDirection: "column",
+ gap: "2px",
+ alignItems: "flex-start",
+ width: "100%",
+});
+
+export const StyledCardColComment = styled(Box)({
+ display: "flex",
+ overflow: "hidden",
+ flexDirection: "column",
+ gap: "2px",
+ alignItems: "flex-start",
+ width: "100%",
+});
+
+export const StyledCardContent = styled(Box)({
+ display: "flex",
+ flexDirection: "column",
+ alignItems: "center",
+ justifyContent: "flex-start",
+ padding: "5px 10px",
+ gap: "10px",
+});
+
+export const StyledCardContentComment = styled(Box)({
+ display: "flex",
+ flexDirection: "column",
+ alignItems: "flex-start",
+ justifyContent: "flex-start",
+ padding: "5px 10px",
+ gap: "10px",
+});
+
+export const StyledCardComment = styled(Typography)(({ theme }) => ({
+ fontFamily: "Mulish",
+ letterSpacing: 0,
+ fontWeight: 400,
+ color: theme.palette.text.primary,
+ fontSize: "19px",
+ wordBreak: "break-word"
+}));
+
+export const TitleText = styled(Typography)({
+ whiteSpace: "nowrap",
+ overflow: "hidden",
+ textOverflow: "ellipsis",
+ width: "100%",
+ fontFamily: "Cairo, sans-serif",
+ fontSize: "22px",
+ lineHeight: "1.2",
+});
+
+export const AuthorText = styled(Typography)({
+ fontFamily: "Raleway, sans-serif",
+ fontSize: "16px",
+ lineHeight: "1.2",
+});
+
+export const AuthorTextComment = styled(Typography)(({ theme }) => ({
+ fontFamily: "Montserrat, sans-serif",
+ fontSize: "17px",
+ letterSpacing: "0.3px",
+ fontWeight: 400,
+ color: theme.palette.text.primary,
+ userSelect: "none",
+}));
+
+export const IconsBox = styled(Box)({
+ display: "flex",
+ gap: "3px",
+ position: "absolute",
+ top: "12px",
+ right: "5px",
+ transition: "all 0.3s ease-in-out",
+});
+
+export const BookmarkIconContainer = styled(Box)({
+ display: "flex",
+ boxShadow: "rgba(99, 99, 99, 0.2) 0px 2px 8px 0px;",
+ backgroundColor: "#fbfbfb",
+ color: "#50e3c2",
+ padding: "5px",
+ borderRadius: "3px",
+ transition: "all 0.3s ease-in-out",
+ "&:hover": {
+ cursor: "pointer",
+ transform: "scale(1.1)",
+ },
+});
+
+export const BlockIconContainer = styled(Box)({
+ display: "flex",
+ boxShadow: "rgba(99, 99, 99, 0.2) 0px 2px 8px 0px;",
+ backgroundColor: "#fbfbfb",
+ color: "#c25252",
+ padding: "5px",
+ borderRadius: "3px",
+ transition: "all 0.3s ease-in-out",
+ "&:hover": {
+ cursor: "pointer",
+ transform: "scale(1.1)",
+ },
+});
+
+export const CommentsContainer = styled(Box)({
+ width: "90%",
+ maxWidth: "1000px",
+ display: "flex",
+ flexDirection: "column",
+ flex: "1",
+ overflow: "auto",
+});
+
+export const CommentContainer = styled(Box)({
+ display: "flex",
+ flexDirection: "column",
+ margin: "25px 0px 50px 0px",
+ maxWidth: "100%",
+ width: "100%",
+ gap: "10px",
+ padding: "0px 5px",
+});
+
+export const NoCommentsRow = styled(Box)({
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "center",
+ flex: "1",
+ padding: "10px 0px",
+ fontFamily: "Mulish",
+ letterSpacing: 0,
+ fontWeight: 400,
+ fontSize: "18px",
+});
+
+export const LoadMoreCommentsButtonRow = styled(Box)({
+ display: "flex",
+});
+
+export const EditReplyButton = styled(Button)(({ theme }) => ({
+ width: "30px",
+ alignSelf: "flex-end",
+ background: theme.palette.primary.light,
+ color: "#ffffff",
+}));
+
+export const LoadMoreCommentsButton = styled(Button)(({ theme }) => ({
+ fontFamily: "Montserrat",
+ fontWeight: 400,
+ letterSpacing: "0.2px",
+ fontSize: "15px",
+ backgroundColor: theme.palette.primary.main,
+ color: "#ffffff",
+}));
+
+export const CommentActionButtonRow = styled(Box)({
+ display: "flex",
+ alignItems: "center",
+ gap: "5px",
+});
+
+export const CommentEditorContainer = styled(Box)({
+ width: "100%",
+ display: "flex",
+ justifyContent: "center",
+});
+
+export const CommentDateText = styled(Typography)(({ theme }) => ({
+ fontFamily: "Mulish",
+ letterSpacing: 0,
+ fontWeight: 400,
+ fontSize: "13px",
+ marginLeft: "5px",
+ color: theme.palette.text.primary,
+}));
+
+export const CommentInputContainer = styled(Box)({
+ display: "flex",
+ flexDirection: "column",
+ marginTop: "15px",
+ width: "90%",
+ maxWidth: "1000px",
+ borderRadius: "8px",
+ gap: "10px",
+ alignItems: "center",
+ marginBottom: "25px",
+});
+
+export const CommentInput = styled(TextField)(({ theme }) => ({
+ backgroundColor: theme.palette.mode === "light" ? "#a9d9d01d" : "#c3abe4a",
+ border: `1px solid ${theme.palette.primary.main}`,
+ width: "100%",
+ borderRadius: "8px",
+ '& [class$="-MuiFilledInput-root"]': {
+ fontFamily: "Mulish",
+ letterSpacing: 0,
+ fontWeight: 400,
+ color: theme.palette.text.primary,
+ fontSize: "19px",
+ minHeight: "100px",
+ backgroundColor: "transparent",
+ "&:before": {
+ borderBottom: "none",
+ "&:hover": {
+ borderBottom: "none",
+ },
+ },
+ "&:hover": {
+ backgroundColor: "transparent",
+ "&:before": {
+ borderBottom: "none",
+ },
+ },
+ },
+}));
+
+export const SubmitCommentButton = styled(Button)(({ theme }) => ({
+ fontFamily: "Montserrat",
+ fontWeight: 400,
+ letterSpacing: "0.2px",
+ fontSize: "15px",
+ backgroundColor: theme.palette.primary.main,
+ color: "#ffffff",
+ width: "75%",
+}));
diff --git a/src/components/common/ConsentModal.tsx b/src/components/common/ConsentModal.tsx
new file mode 100644
index 0000000..fb2f534
--- /dev/null
+++ b/src/components/common/ConsentModal.tsx
@@ -0,0 +1,72 @@
+import * as React from "react";
+import Button from "@mui/material/Button";
+import Dialog from "@mui/material/Dialog";
+import DialogActions from "@mui/material/DialogActions";
+import DialogContent from "@mui/material/DialogContent";
+import DialogContentText from "@mui/material/DialogContentText";
+import DialogTitle from "@mui/material/DialogTitle";
+import localForage from "localforage";
+import { useTheme } from "@mui/material";
+const generalLocal = localForage.createInstance({
+ name: "q-share-general",
+});
+
+export default function ConsentModal() {
+ const theme = useTheme();
+
+ const [open, setOpen] = React.useState(false);
+
+ const handleClose = () => {
+ setOpen(false);
+ };
+
+ const getIsConsented = React.useCallback(async () => {
+ try {
+ const hasConsented = await generalLocal.getItem("general-consent");
+ if (hasConsented) return;
+
+ setOpen(true);
+ generalLocal.setItem("general-consent", true);
+ } catch (error) {}
+ }, []);
+
+ React.useEffect(() => {
+ getIsConsented();
+ }, []);
+ return (
+
+
+
+ );
+}
diff --git a/src/components/common/DownloadTaskManager.tsx b/src/components/common/DownloadTaskManager.tsx
new file mode 100644
index 0000000..5089b21
--- /dev/null
+++ b/src/components/common/DownloadTaskManager.tsx
@@ -0,0 +1,204 @@
+import React, { useState, useEffect } from 'react'
+import {
+ Accordion,
+ AccordionDetails,
+ AccordionSummary,
+ Box,
+ Button,
+ LinearProgress,
+ List,
+ ListItem,
+ ListItemIcon,
+ Popover,
+ Typography,
+ useTheme
+} from '@mui/material'
+import { Movie } from '@mui/icons-material'
+import { useSelector } from 'react-redux'
+import { RootState } from '../../state/store'
+import ExpandMoreIcon from '@mui/icons-material/ExpandMore'
+import { useLocation, useNavigate } from 'react-router-dom'
+import { DownloadingLight } from '../../assets/svgs/DownloadingLight'
+import { DownloadedLight } from '../../assets/svgs/DownloadedLight'
+import AttachFileIcon from "@mui/icons-material/AttachFile";
+
+export const DownloadTaskManager: React.FC = () => {
+ const { downloads } = useSelector((state: RootState) => state.global)
+ const location = useLocation()
+ const theme = useTheme()
+ const [visible, setVisible] = useState(false)
+ const [hidden, setHidden] = useState(true)
+ const navigate = useNavigate()
+ const [anchorEl, setAnchorEl] = useState(null);
+
+
+ const [openDownload, setOpenDownload] = useState(false);
+
+
+ const handleClick = (event?: React.MouseEvent) => {
+ const target = event?.currentTarget as unknown as HTMLButtonElement | null;
+ setAnchorEl(target);
+ };
+
+ const handleCloseDownload = () => {
+ setAnchorEl(null);
+ setOpenDownload(false);
+ };
+
+ useEffect(() => {
+ // Simulate downloads for demo purposes
+
+ if (visible) {
+ setTimeout(() => {
+ setHidden(true)
+ setVisible(false)
+ }, 3000)
+ }
+ }, [visible])
+
+
+ useEffect(() => {
+ if (Object.keys(downloads).length === 0) return
+ setVisible(true)
+ setHidden(false)
+ }, [downloads])
+
+
+ if (
+ !downloads ||
+ Object.keys(downloads).length === 0
+ )
+ return null
+
+
+ let downloadInProgress = false
+ if(Object.keys(downloads).find((key)=> (downloads[key]?.status?.status !== 'READY' && downloads[key]?.status?.status !== 'DOWNLOADED'))){
+ downloadInProgress = true
+ }
+
+ return (
+
+
+
+
+
+ {Object.keys(downloads)
+ .map((download: any) => {
+ const downloadObj = downloads[download]
+ const progress = downloads[download]?.status?.percentLoaded || 0
+ const status = downloads[download]?.status?.status
+ const service = downloads[download]?.service
+ return (
+ {
+ const id = downloadObj?.properties?.jsonId
+ if (!id) return
+
+ navigate(
+ `/share/${downloadObj?.properties?.name}/${id}`
+ )
+ }}
+ >
+
+
+
+
+
+
+
+
+
+
+
+ {`${progress?.toFixed(0)}%`}{' '}
+ {status && status === 'REFETCHING' && '- refetching'}
+ {status && status === 'DOWNLOADED' && '- building'}
+
+
+
+ {downloadObj?.identifier}
+
+
+ )
+ })}
+
+
+
+
+
+ )
+}
diff --git a/src/components/common/FileElement.tsx b/src/components/common/FileElement.tsx
new file mode 100644
index 0000000..4027bf9
--- /dev/null
+++ b/src/components/common/FileElement.tsx
@@ -0,0 +1,446 @@
+import * as React from "react";
+import { styled, useTheme } from "@mui/material/styles";
+import Box from "@mui/material/Box";
+import Typography from "@mui/material/Typography";
+import { useDispatch, useSelector } from "react-redux";
+import { CircularProgress } from "@mui/material";
+import AttachFileIcon from "@mui/icons-material/AttachFile";
+import { MyContext } from "../../wrappers/DownloadWrapper";
+import { RootState } from "../../state/store";
+import { setNotification } from "../../state/features/notificationsSlice";
+
+const Widget = styled("div")(({ theme }) => ({
+ padding: 8,
+ borderRadius: 10,
+ maxWidth: 350,
+ position: "relative",
+ zIndex: 1,
+ backdropFilter: "blur(40px)",
+ background: "skyblue",
+ transition: "0.2s all",
+ "&:hover": {
+ opacity: 0.75,
+ },
+}));
+
+const CoverImage = styled("div")({
+ width: 40,
+ height: 40,
+ objectFit: "cover",
+ overflow: "hidden",
+ flexShrink: 0,
+ borderRadius: 8,
+ backgroundColor: "rgba(0,0,0,0.08)",
+ "& > img": {
+ width: "100%",
+ },
+});
+
+interface IAudioElement {
+ title: string;
+ description?: string;
+ author?: string;
+ fileInfo?: any;
+ postId?: string;
+ user?: string;
+ children?: React.ReactNode;
+ mimeType?: string;
+ disable?: boolean;
+ mode?: string;
+ otherUser?: string;
+ customStyles?: any;
+ jsonId:string;
+}
+
+interface CustomWindow extends Window {
+ showSaveFilePicker: any; // Replace 'any' with the appropriate type if you know it
+}
+
+const customWindow = window as unknown as CustomWindow;
+
+export default function FileElement({
+ title,
+ description,
+ author,
+ fileInfo,
+ children,
+ mimeType,
+ disable,
+ customStyles,
+ jsonId
+}: IAudioElement) {
+ const { downloadVideo } = React.useContext(MyContext);
+ const [startedDownload, setStartedDownload] = React.useState(false)
+ const [isLoading, setIsLoading] = React.useState(false);
+ const [fileProperties, setFileProperties] = React.useState(null);
+ const [downloadLoader, setDownloadLoader] = React.useState(false);
+ const downloads = useSelector((state: RootState) => state.global?.downloads);
+ const status = React.useRef(null)
+
+ const hasCommencedDownload = React.useRef(false);
+ const dispatch = useDispatch();
+ const reDownload = React.useRef(false)
+ const isFetchingProperties = React.useRef(false)
+ const download = React.useMemo(() => {
+ if (!downloads || !fileInfo?.identifier) return {};
+ const findDownload = downloads[fileInfo?.identifier];
+
+ if (!findDownload) return {};
+ return findDownload;
+ }, [downloads, fileInfo]);
+
+ const resourceStatus = React.useMemo(() => {
+ return download?.status || {};
+ }, [download]);
+
+ const retryDownload = React.useRef(0);
+
+ const handlePlay = async () => {
+ if (disable) return;
+ hasCommencedDownload.current = true;
+ setStartedDownload(true)
+ if (
+ resourceStatus?.status === "READY"
+ ) {
+ if (downloadLoader) return;
+
+ setDownloadLoader(true);
+ let filename = download?.properties?.filename
+ let mimeType = download?.properties?.type
+
+ try {
+ const { name, service, identifier } = fileInfo;
+
+ const res = await qortalRequest({
+ action: "GET_QDN_RESOURCE_PROPERTIES",
+ name: name,
+ service: service,
+ identifier: identifier,
+ });
+ filename = res?.filename || filename;
+ mimeType = res?.mimeType || mimeType;
+ } catch (error) {
+
+ }
+ try {
+ const { name, service, identifier } = fileInfo;
+
+ const url = `/arbitrary/${service}/${name}/${identifier}`;
+ fetch(url)
+ .then(response => response.blob())
+ .then(async blob => {
+ await qortalRequest({
+ action: "SAVE_FILE",
+ blob,
+ filename: filename,
+ mimeType,
+ });
+ })
+ .catch(error => {
+ console.error("Error fetching the video:", error);
+ });
+ } catch (error: any) {
+ let notificationObj: any = null;
+ if (typeof error === "string") {
+ notificationObj = {
+ msg: error || "Failed to send message",
+ alertType: "error",
+ };
+ } else if (typeof error?.error === "string") {
+ notificationObj = {
+ msg: error?.error || "Failed to send message",
+ alertType: "error",
+ };
+ } else {
+ notificationObj = {
+ msg: error?.message || "Failed to send message",
+ alertType: "error",
+ };
+ }
+ if (!notificationObj) return;
+ dispatch(setNotification(notificationObj));
+ } finally {
+ setDownloadLoader(false);
+ }
+ return;
+ }
+
+ const { name, service, identifier } = fileInfo;
+
+ setIsLoading(true);
+ downloadVideo({
+ name,
+ service,
+ identifier,
+ properties: {
+ ...fileInfo,
+ jsonId
+ },
+ });
+ };
+
+ const refetch = React.useCallback(async () => {
+ if (!fileInfo) return
+ try {
+ const { name, service, identifier } = fileInfo;
+ isFetchingProperties.current = true
+ await qortalRequest({
+ action: 'GET_QDN_RESOURCE_PROPERTIES',
+ name,
+ service,
+ identifier
+ })
+
+ } catch (error) {
+
+ } finally {
+ isFetchingProperties.current = false
+ }
+
+ }, [fileInfo])
+
+ const refetchInInterval = ()=> {
+ try {
+ const interval = setInterval(()=> {
+ if(status?.current === 'DOWNLOADED'){
+ refetch()
+ }
+ if(status?.current === 'READY'){
+ clearInterval(interval);
+ }
+
+ }, 7500)
+ } catch (error) {
+
+ }
+ }
+
+ React.useEffect(() => {
+ if(resourceStatus?.status){
+ status.current = resourceStatus?.status
+ }
+ if (
+ resourceStatus?.status === 'DOWNLOADED' &&
+ reDownload?.current === false
+ ) {
+ refetchInInterval()
+ reDownload.current = true
+ }
+ }, [resourceStatus])
+
+
+ React.useEffect(() => {
+ if (
+ resourceStatus?.status === "READY" &&
+ download?.url &&
+ download?.properties?.filename &&
+ hasCommencedDownload.current
+ ) {
+ setIsLoading(false);
+ dispatch(
+ setNotification({
+ msg: "Download completed. Click to save file",
+ alertType: "info",
+ })
+ );
+ }
+ }, [resourceStatus, download]);
+
+ return (
+
+ {children && (
+
+ {children}{" "}
+ {((resourceStatus.status && resourceStatus?.status !== "READY") ||
+ isLoading) && startedDownload ? (
+ <>
+
+ {`${Math.round(
+ resourceStatus?.percentLoaded || 0
+ ).toFixed(0)}% loaded`}
+ >
+ ) : resourceStatus?.status === "READY" ? (
+ <>
+
+ Ready to save: click here
+
+ {downloadLoader && (
+
+ )}
+ >
+ ) : null}
+
+ )}
+ {!children && (
+
+
+
+
+
+
+
+ {author}
+
+
+ {title}
+
+
+ {description}
+
+ {mimeType && (
+
+ {mimeType}
+
+ )}
+
+
+ {((resourceStatus.status && resourceStatus?.status !== "READY") ||
+ isLoading) && startedDownload && (
+
+
+ {resourceStatus && (
+
+ {resourceStatus?.status === "REFETCHING" ? (
+ <>
+ <>
+ {(
+ (resourceStatus?.localChunkCount /
+ resourceStatus?.totalChunkCount) *
+ 100
+ )?.toFixed(0)}
+ %
+ >
+
+ <> Refetching in 2 minutes>
+ >
+ ) : resourceStatus?.status === "DOWNLOADED" ? (
+ <>Download Completed: building file...>
+ ) : resourceStatus?.status !== "READY" ? (
+ <>
+ {(
+ (resourceStatus?.localChunkCount /
+ resourceStatus?.totalChunkCount) *
+ 100
+ )?.toFixed(0)}
+ %
+ >
+ ) : (
+ <>Download Completed: fetching file...>
+ )}
+
+ )}
+
+ )}
+ {resourceStatus?.status === "READY" &&
+ download?.url &&
+ download?.properties?.filename && (
+
+
+ Ready to save: click here
+
+ {downloadLoader && (
+
+ )}
+
+ )}
+
+ )}
+
+ );
+}
diff --git a/src/components/common/ImagePublisher/ImagePublisher-styles.tsx b/src/components/common/ImagePublisher/ImagePublisher-styles.tsx
new file mode 100644
index 0000000..00c4f3a
--- /dev/null
+++ b/src/components/common/ImagePublisher/ImagePublisher-styles.tsx
@@ -0,0 +1,47 @@
+import { Box, Button } from "@mui/material";
+import { styled } from "@mui/system";
+import AddPhotoAlternateIcon from "@mui/icons-material/AddPhotoAlternate";
+import { TimesSVG } from "./TimesSVG.tsx";
+
+export const AddCoverImageButton = styled(Button)(({ theme }) => ({
+ display: "flex",
+ alignItems: "center",
+ fontFamily: "Montserrat",
+ fontSize: "16px",
+ fontWeight: 400,
+ letterSpacing: "0.2px",
+ color: "white",
+ gap: "5px",
+}));
+
+export const AddLogoIcon = styled(AddPhotoAlternateIcon)(({ theme }) => ({
+ color: "#fff",
+ height: "25px",
+ width: "auto",
+}));
+
+export const LogoPreviewRow = styled(Box)(({ theme }) => ({
+ display: "flex",
+ alignItems: "center",
+ gap: "10px",
+}));
+
+export const CoverImagePreview = styled("img")(({ theme }) => ({
+ width: "100px",
+ height: "100px",
+ objectFit: "contain",
+ userSelect: "none",
+ borderRadius: "3px",
+ marginBottom: "10px",
+}));
+
+export const TimesIcon = styled(TimesSVG)(({ theme }) => ({
+ backgroundColor: theme.palette.background.paper,
+ borderRadius: "50%",
+ padding: "5px",
+ transition: "all 0.2s ease-in-out",
+ "&:hover": {
+ cursor: "pointer",
+ scale: "1.1",
+ },
+}));
diff --git a/src/components/common/ImagePublisher/ImagePublisher.tsx b/src/components/common/ImagePublisher/ImagePublisher.tsx
new file mode 100644
index 0000000..5358b71
--- /dev/null
+++ b/src/components/common/ImagePublisher/ImagePublisher.tsx
@@ -0,0 +1,62 @@
+import ImageUploader from "./ImageUploader.tsx";
+import React, { useImperativeHandle, useState } from "react";
+import {
+ AddCoverImageButton,
+ AddLogoIcon,
+ CoverImagePreview,
+ LogoPreviewRow,
+ TimesIcon,
+} from "./ImagePublisher-styles.tsx";
+import { useTheme } from "@mui/material";
+
+export type ImagePublisherRef = {
+ getImageArray: () => string[];
+};
+
+interface ImagePublisherProps {
+ initialImages?: string[];
+}
+export const ImagePublisher = React.forwardRef<
+ ImagePublisherRef,
+ ImagePublisherProps
+>(({ initialImages }: ImagePublisherProps, ref) => {
+ const theme = useTheme();
+ const [imageArray, setImageArray] = useState(initialImages || []);
+
+ useImperativeHandle(ref, () => ({
+ getImageArray: () => {
+ return imageArray;
+ },
+ }));
+
+ return (
+ <>
+ {imageArray.length === 0 ? (
+ setImageArray(img)}>
+
+ Add Images
+
+
+
+ ) : (
+
+ {imageArray.map(
+ image =>
+ image &&
+ )}
+ setImageArray([])}
+ height={"32"}
+ width={"32"}
+ >
+
+ )}
+ >
+ );
+});
diff --git a/src/components/common/ImagePublisher/ImageUploader.tsx b/src/components/common/ImagePublisher/ImageUploader.tsx
new file mode 100644
index 0000000..6919bff
--- /dev/null
+++ b/src/components/common/ImagePublisher/ImageUploader.tsx
@@ -0,0 +1,109 @@
+import React, { useCallback } from "react";
+import { Box } from "@mui/material";
+import {
+ DropzoneInputProps,
+ DropzoneRootProps,
+ useDropzone,
+} from "react-dropzone";
+import Compressor from "compressorjs";
+import { setNotification } from "../../../state/features/notificationsSlice.ts";
+import { useDispatch } from "react-redux";
+
+const toBase64 = (file: File): Promise =>
+ new Promise((resolve, reject) => {
+ const reader = new FileReader();
+ reader.readAsDataURL(file);
+ reader.onload = () => resolve(reader.result);
+ reader.onerror = error => {
+ reject(error);
+ };
+ });
+
+interface ImageUploaderProps {
+ children: React.ReactNode;
+ onPick: (base64Img: string[]) => void;
+}
+
+export const ImageUploader: React.FC = ({
+ children,
+ onPick,
+}) => {
+ const dispatch = useDispatch();
+ const imageLimit = 3;
+
+ const compressImages = async (images: File[]) => {
+ const promises = images.map(image => {
+ return new Promise(resolve => {
+ new Compressor(image, {
+ quality: 0.6,
+ maxWidth: 1200,
+ mimeType: "image/webp",
+ success(result) {
+ const file = new File([result], "name", {
+ type: "image/webp",
+ });
+ resolve(result);
+ },
+ error(err) {},
+ });
+ });
+ });
+ return await Promise.all(promises);
+ };
+
+ const onDrop = useCallback(
+ async (acceptedFiles: File[]) => {
+ if (acceptedFiles.length > imageLimit) {
+ const notificationObj = {
+ msg: `Only ${imageLimit} images can be published`,
+ alertType: "error",
+ };
+ dispatch(setNotification(notificationObj));
+ return;
+ }
+
+ try {
+ const compressedImages = await compressImages(acceptedFiles);
+ if (!compressedImages) return;
+
+ const base64Iamges = await Promise.all(
+ compressedImages.map(image => toBase64(image as File))
+ );
+
+ onPick(base64Iamges as string[]);
+ } catch (error) {
+ console.error(error);
+ }
+ },
+ [onPick]
+ );
+
+ const {
+ getRootProps,
+ getInputProps,
+ isDragActive,
+ }: {
+ getRootProps: () => DropzoneRootProps;
+ getInputProps: () => DropzoneInputProps;
+ isDragActive: boolean;
+ } = useDropzone({
+ onDrop,
+ accept: {
+ "image/*": [],
+ },
+ });
+
+ return (
+
+
+ {children}
+
+ );
+};
+
+export default ImageUploader;
diff --git a/src/components/common/ImagePublisher/TimesSVG.tsx b/src/components/common/ImagePublisher/TimesSVG.tsx
new file mode 100644
index 0000000..4f97ce4
--- /dev/null
+++ b/src/components/common/ImagePublisher/TimesSVG.tsx
@@ -0,0 +1,28 @@
+export interface IconTypes {
+ color?: string;
+ height: string;
+ width: string;
+ className?: string;
+ onClickFunc?: (e?: any) => void;
+}
+export const TimesSVG: React.FC = ({
+ color,
+ height,
+ width,
+ className,
+ onClickFunc,
+}) => {
+ return (
+
+ );
+};
diff --git a/src/components/common/LazyLoad.tsx b/src/components/common/LazyLoad.tsx
new file mode 100644
index 0000000..5ce7a30
--- /dev/null
+++ b/src/components/common/LazyLoad.tsx
@@ -0,0 +1,48 @@
+import React, { useState, useEffect, useRef } from 'react'
+import { useInView } from 'react-intersection-observer'
+import CircularProgress from '@mui/material/CircularProgress'
+
+interface Props {
+ onLoadMore: () => Promise
+ isLoading?: boolean
+}
+
+const LazyLoad: React.FC = ({ onLoadMore, isLoading }) => {
+ const [isFetching, setIsFetching] = useState(false)
+
+ const firstLoad = useRef(false)
+ const [ref, inView] = useInView({
+ threshold: 0.7
+ })
+
+ useEffect(() => {
+ if (inView) {
+ setIsFetching(true)
+ onLoadMore().finally(() => {
+ setIsFetching(false)
+ firstLoad.current = true
+ })
+ }
+ }, [inView])
+
+ return (
+
+ )
+}
+
+export default LazyLoad
diff --git a/src/components/common/MultiplePublish/MultiplePublishAll.tsx b/src/components/common/MultiplePublish/MultiplePublishAll.tsx
new file mode 100644
index 0000000..7b4fd50
--- /dev/null
+++ b/src/components/common/MultiplePublish/MultiplePublishAll.tsx
@@ -0,0 +1,225 @@
+/* eslint-disable @typescript-eslint/no-explicit-any */
+import {
+ Box,
+ Button,
+ CircularProgress,
+ Modal,
+ Typography,
+ useTheme,
+} from "@mui/material";
+import React, { useCallback, useEffect, useState, useRef } from "react";
+import { CircleSVG } from "../../../assets/svgs/CircleSVG";
+import { EmptyCircleSVG } from "../../../assets/svgs/EmptyCircleSVG";
+import { styled } from "@mui/system";
+
+interface Publish {
+ resources: any[];
+ action: string;
+}
+
+interface MultiplePublishProps {
+ publishes: Publish;
+ isOpen: boolean;
+ onSubmit: () => void;
+ onError: (message?: string) => void;
+}
+export const MultiplePublish = ({
+ publishes,
+ isOpen,
+ onSubmit,
+ onError,
+}: MultiplePublishProps) => {
+ const theme = useTheme();
+ const listOfSuccessfulPublishesRef = useRef([]);
+ const [listOfSuccessfulPublishes, setListOfSuccessfulPublishes] = useState<
+ any[]
+ >([]);
+ const [listOfUnsuccessfulPublishes, setListOfUnSuccessfulPublishes] =
+ useState([]);
+ const [currentlyInPublish, setCurrentlyInPublish] = useState(null);
+ const hasStarted = useRef(false);
+ const publish = useCallback(async (pub: any) => {
+ const lengthOfResources = pub?.resources?.length;
+ const lengthOfTimeout = lengthOfResources * 30000;
+ return await qortalRequestWithTimeout(pub, lengthOfTimeout);
+ }, []);
+ const [isPublishing, setIsPublishing] = useState(true);
+
+ const handlePublish = useCallback(
+ async (pub: any) => {
+ try {
+ setCurrentlyInPublish(pub?.identifier);
+ setIsPublishing(true);
+ const res = await publish(pub);
+
+ onSubmit();
+ setListOfUnSuccessfulPublishes([]);
+ } catch (error: any) {
+ const unsuccessfulPublishes = error?.error?.unsuccessfulPublishes || [];
+ if (error?.error === "User declined request") {
+ onError();
+ return;
+ }
+
+ if (error?.error === "The request timed out") {
+ onError("The request timed out");
+
+ return;
+ }
+
+ if (unsuccessfulPublishes?.length > 0) {
+ setListOfUnSuccessfulPublishes(unsuccessfulPublishes);
+ }
+ } finally {
+ setIsPublishing(false);
+ }
+ },
+ [publish]
+ );
+
+ const retry = () => {
+ let newlistOfMultiplePublishes: any[] = [];
+ listOfUnsuccessfulPublishes?.forEach(item => {
+ const findPub = publishes?.resources.find(
+ (res: any) => res?.identifier === item.identifier
+ );
+ if (findPub) {
+ newlistOfMultiplePublishes.push(findPub);
+ }
+ });
+ const multiplePublish = {
+ ...publishes,
+ resources: newlistOfMultiplePublishes,
+ };
+ handlePublish(multiplePublish);
+ };
+
+ const startPublish = useCallback(
+ async (pubs: any) => {
+ await handlePublish(pubs);
+ },
+ [handlePublish, onSubmit, listOfSuccessfulPublishes, publishes]
+ );
+
+ useEffect(() => {
+ if (publishes && !hasStarted.current) {
+ hasStarted.current = true;
+ startPublish(publishes);
+ }
+ }, [startPublish, publishes, listOfSuccessfulPublishes]);
+
+ return (
+
+
+ {publishes?.resources?.map((publish: any) => {
+ const unpublished = listOfUnsuccessfulPublishes.map(
+ item => item?.identifier
+ );
+ return (
+
+ {publish?.identifier}
+ {!isPublishing && hasStarted.current ? (
+ <>
+ {!unpublished.includes(publish.identifier) ? (
+
+ ) : (
+
+ )}
+ >
+ ) : (
+
+ )}
+
+ );
+ })}
+ {!isPublishing && listOfUnsuccessfulPublishes.length > 0 && (
+ <>
+
+ Some files were not published. Please try again. It's important
+ that all the files get published. Maybe wait a couple minutes if
+ the error keeps occurring
+
+
+ >
+ )}
+
+
+ );
+};
+
+export const ModalBody = styled(Box)(({ theme }) => ({
+ position: "absolute",
+ backgroundColor: theme.palette.background.default,
+ borderRadius: "4px",
+ top: "50%",
+ left: "50%",
+ transform: "translate(-50%, -50%)",
+ width: "75%",
+ maxWidth: "900px",
+ padding: "15px 35px",
+ display: "flex",
+ flexDirection: "column",
+ gap: "17px",
+ overflowY: "auto",
+ maxHeight: "95vh",
+ boxShadow:
+ theme.palette.mode === "dark"
+ ? "0px 4px 5px 0px hsla(0,0%,0%,0.14), 0px 1px 10px 0px hsla(0,0%,0%,0.12), 0px 2px 4px -1px hsla(0,0%,0%,0.2)"
+ : "rgba(99, 99, 99, 0.2) 0px 2px 8px 0px",
+ "&::-webkit-scrollbar-track": {
+ backgroundColor: theme.palette.background.paper,
+ },
+ "&::-webkit-scrollbar-track:hover": {
+ backgroundColor: theme.palette.background.paper,
+ },
+ "&::-webkit-scrollbar": {
+ width: "16px",
+ height: "10px",
+ backgroundColor: theme.palette.mode === "light" ? "#f6f8fa" : "#292d3e",
+ },
+ "&::-webkit-scrollbar-thumb": {
+ backgroundColor: theme.palette.mode === "light" ? "#d3d9e1" : "#575757",
+ borderRadius: "8px",
+ backgroundClip: "content-box",
+ border: "4px solid transparent",
+ },
+ "&::-webkit-scrollbar-thumb:hover": {
+ backgroundColor: theme.palette.mode === "light" ? "#b7bcc4" : "#474646",
+ },
+}));
diff --git a/src/components/common/Notification/Notification.tsx b/src/components/common/Notification/Notification.tsx
new file mode 100644
index 0000000..501f081
--- /dev/null
+++ b/src/components/common/Notification/Notification.tsx
@@ -0,0 +1,86 @@
+import { useDispatch, useSelector } from 'react-redux'
+import { toast, ToastContainer, Zoom, Slide } from 'react-toastify'
+import { removeNotification } from '../../../state/features/notificationsSlice'
+import 'react-toastify/dist/ReactToastify.css'
+import { RootState } from '../../../state/store'
+
+const Notification = () => {
+ const dispatch = useDispatch()
+
+ const { alertTypes } = useSelector((state: RootState) => state.notifications)
+
+ if (alertTypes.alertError) {
+ toast.error(`❌ ${alertTypes?.alertError}`, {
+ position: 'bottom-right',
+ autoClose: 4000,
+ hideProgressBar: false,
+ closeOnClick: true,
+ pauseOnHover: true,
+ draggable: true,
+ progress: undefined,
+ icon: false
+ })
+ dispatch(removeNotification())
+ }
+ if (alertTypes.alertSuccess) {
+ toast.success(`✔️ ${alertTypes?.alertSuccess}`, {
+ position: 'bottom-right',
+ autoClose: 4000,
+ hideProgressBar: false,
+ closeOnClick: true,
+ pauseOnHover: true,
+ draggable: true,
+ progress: undefined,
+ icon: false
+ })
+ dispatch(removeNotification())
+ }
+ if (alertTypes.alertInfo) {
+ toast.info(`${alertTypes?.alertInfo}`, {
+ position: 'top-right',
+ autoClose: 1300,
+ hideProgressBar: false,
+ closeOnClick: true,
+ pauseOnHover: true,
+ draggable: true,
+ progress: undefined,
+ theme: 'light'
+ })
+ dispatch(removeNotification())
+ }
+
+ if (alertTypes.alertInfo) {
+ return (
+
+ )
+ }
+
+ return (
+
+ )
+}
+
+export default Notification
diff --git a/src/components/common/PageLoader.tsx b/src/components/common/PageLoader.tsx
new file mode 100644
index 0000000..e8e5740
--- /dev/null
+++ b/src/components/common/PageLoader.tsx
@@ -0,0 +1,43 @@
+import React from 'react';
+import CircularProgress from '@mui/material/CircularProgress';
+import Box from '@mui/system/Box';
+import { useTheme } from '@mui/material'
+
+interface PageLoaderProps {
+ size?: number
+ thickness?: number
+}
+
+const PageLoader: React.FC = ({
+ size = 40,
+ thickness = 5
+}) => {
+ const theme = useTheme()
+
+ return (
+
+
+
+ )
+}
+
+export default PageLoader;
diff --git a/src/components/common/Portal.tsx b/src/components/common/Portal.tsx
new file mode 100644
index 0000000..1e0cb26
--- /dev/null
+++ b/src/components/common/Portal.tsx
@@ -0,0 +1,25 @@
+import React, { useEffect, useState } from 'react'
+import { createPortal } from 'react-dom'
+
+interface PortalProps {
+ children: React.ReactNode
+}
+
+const Portal: React.FC = ({ children }) => {
+ const [mounted, setMounted] = useState(false)
+
+ useEffect(() => {
+ setMounted(true)
+
+ return () => setMounted(false)
+ }, [])
+
+ return mounted
+ ? createPortal(
+ children,
+ document.querySelector('#modal-root') as HTMLElement
+ )
+ : null
+}
+
+export default Portal
diff --git a/src/components/common/TextEditor/DisplayHtml.tsx b/src/components/common/TextEditor/DisplayHtml.tsx
new file mode 100644
index 0000000..f6c1bd1
--- /dev/null
+++ b/src/components/common/TextEditor/DisplayHtml.tsx
@@ -0,0 +1,40 @@
+import { useMemo } from "react";
+import DOMPurify from "dompurify";
+import "react-quill/dist/quill.snow.css";
+import "react-quill/dist/quill.core.css";
+import "react-quill/dist/quill.bubble.css";
+import { convertQortalLinks } from "./utils";
+import { Box, styled } from "@mui/material";
+
+
+const CrowdfundInlineContent = styled(Box)(({ theme }) => ({
+ display: "flex",
+ fontFamily: "Mulish",
+ fontSize: "19px",
+ fontWeight: 400,
+ letterSpacing: 0,
+ color: theme.palette.text.primary,
+ width: '100%'
+ }));
+
+export const DisplayHtml = ({ html }) => {
+ const cleanContent = useMemo(() => {
+ if (!html) return null;
+
+ const sanitize: string = DOMPurify.sanitize(html, {
+ USE_PROFILES: { html: true },
+ });
+ const anchorQortal = convertQortalLinks(sanitize);
+ return anchorQortal;
+ }, [html]);
+
+ if (!cleanContent) return null;
+ return (
+
+
+
+ );
+};
diff --git a/src/components/common/TextEditor/TextEditor.tsx b/src/components/common/TextEditor/TextEditor.tsx
new file mode 100644
index 0000000..805ebbd
--- /dev/null
+++ b/src/components/common/TextEditor/TextEditor.tsx
@@ -0,0 +1,38 @@
+import React from "react";
+import ReactQuill, { Quill } from "react-quill";
+import "react-quill/dist/quill.snow.css";
+import ImageResize from "quill-image-resize-module-react";
+
+Quill.register("modules/imageResize", ImageResize);
+
+const modules = {
+ imageResize: {
+ parchment: Quill.import("parchment"),
+ modules: ["Resize", "DisplaySize"],
+ },
+ toolbar: [
+ ["bold", "italic", "underline", "strike"], // styled text
+ ["blockquote", "code-block"], // blocks
+ [{ header: 1 }, { header: 2 }], // custom button values
+ [{ list: "ordered" }, { list: "bullet" }], // lists
+ [{ script: "sub" }, { script: "super" }], // superscript/subscript
+ [{ indent: "-1" }, { indent: "+1" }], // outdent/indent
+ [{ direction: "rtl" }], // text direction
+ [{ size: ["small", false, "large", "huge"] }], // custom dropdown
+ [{ header: [1, 2, 3, 4, 5, 6, false] }], // custom button values
+ [{ color: [] }, { background: [] }], // dropdown with defaults
+ [{ font: [] }], // font family
+ [{ align: [] }], // text align
+ ["clean"], // remove formatting
+ ],
+};
+export const TextEditor = ({ inlineContent, setInlineContent }) => {
+ return (
+
+ );
+};
diff --git a/src/components/common/TextEditor/utils.ts b/src/components/common/TextEditor/utils.ts
new file mode 100644
index 0000000..76ca5fe
--- /dev/null
+++ b/src/components/common/TextEditor/utils.ts
@@ -0,0 +1,26 @@
+export function convertQortalLinks(inputHtml) {
+ // Regular expression to match 'qortal://...' URLs.
+ // This will stop at the first whitespace, comma, or HTML tag
+ var regex = /(qortal:\/\/[^\s,<]+)/g;
+
+ // Replace matches in inputHtml with formatted anchor tag
+ var outputHtml = inputHtml.replace(regex, function (match) {
+ return `${match}`;
+ });
+
+ return outputHtml;
+}
+
+export function extractTextFromHTML(htmlString: any, length = 150) {
+ // Create a temporary DOM element
+ const tempDiv = document.createElement("div");
+ // Replace br tags and block-level tags with a space before setting the HTML content
+ const htmlWithSpaces = htmlString.replace(/<\/?(br|p|div|h[1-6]|ul|ol|li|blockquote)[^>]*>/gi, ' ');
+ tempDiv.innerHTML = htmlWithSpaces;
+ // Extract the text content
+ let text = tempDiv.textContent || tempDiv.innerText || "";
+ // Replace multiple spaces with a single space and trim
+ text = text.replace(/\s+/g, ' ').trim();
+ // Slice the text to the desired length
+ return text.slice(0, length);
+ }
\ No newline at end of file
diff --git a/src/components/common/VideoPlayer.tsx b/src/components/common/VideoPlayer.tsx
new file mode 100644
index 0000000..93feddc
--- /dev/null
+++ b/src/components/common/VideoPlayer.tsx
@@ -0,0 +1,857 @@
+import React, { useContext, useEffect, useMemo, useRef, useState } from 'react'
+import ReactDOM from 'react-dom'
+import { Box, IconButton, Slider } from '@mui/material'
+import { CircularProgress, Typography } from '@mui/material'
+import { Key } from 'ts-key-enum'
+import {
+ PlayArrow,
+ Pause,
+ VolumeUp,
+ Fullscreen,
+ PictureInPicture, VolumeOff
+} from '@mui/icons-material'
+import { styled } from '@mui/system'
+import { MyContext } from '../../wrappers/DownloadWrapper'
+import { useDispatch, useSelector } from 'react-redux'
+import { RootState } from '../../state/store'
+import { Refresh } from '@mui/icons-material'
+
+import { Menu, MenuItem } from '@mui/material'
+import { MoreVert as MoreIcon } from '@mui/icons-material'
+import { setVideoPlaying } from '../../state/features/globalSlice'
+const VideoContainer = styled(Box)`
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ width: 100%;
+ height: 100%;
+ margin: 0px;
+ padding: 0px;
+`
+
+const VideoElement = styled('video')`
+ width: 100%;
+ height: auto;
+ max-height: calc(100vh - 150px);
+ background: rgb(33, 33, 33);
+`
+
+const ControlsContainer = styled(Box)`
+ position: absolute;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ padding: 8px;
+ background-color: rgba(0, 0, 0, 0.6);
+`
+
+interface VideoPlayerProps {
+ src?: string
+ poster?: string
+ name?: string
+ identifier?: string
+ service?: string
+ autoplay?: boolean
+ from?: string | null
+ customStyle?: any
+ user?: string
+ jsonId?: string
+}
+
+export const VideoPlayer: React.FC = ({
+ poster,
+ name,
+ identifier,
+ service,
+ autoplay = true,
+ from = null,
+ customStyle = {},
+ user = '',
+ jsonId = ''
+}) => {
+ const dispatch = useDispatch()
+ const videoRef = useRef(null)
+ const [playing, setPlaying] = useState(false)
+ const [volume, setVolume] = useState(1)
+ const [mutedVolume, setMutedVolume] = useState(1)
+ const [isMuted, setIsMuted] = useState(false)
+ const [progress, setProgress] = useState(0)
+ const [isLoading, setIsLoading] = useState(false)
+ const [canPlay, setCanPlay] = useState(false)
+ const [startPlay, setStartPlay] = useState(false)
+ const [isMobileView, setIsMobileView] = useState(false)
+ const [playbackRate, setPlaybackRate] = useState(1)
+ const [anchorEl, setAnchorEl] = useState(null)
+ const videoPlaying = useSelector((state: RootState) => state.global.videoPlaying);
+ const reDownload = useRef(false)
+ const isFetchingProperties = useRef(false)
+
+ const status = useRef(null)
+ const { downloads } = useSelector((state: RootState) => state.global)
+ const download = useMemo(() => {
+ if (!downloads || !identifier) return {}
+ const findDownload = downloads[identifier]
+
+ if (!findDownload) return {}
+ return findDownload
+ }, [downloads, identifier])
+
+ const src = useMemo(() => {
+ return download?.url || ''
+ }, [download?.url])
+ const resourceStatus = useMemo(() => {
+ return download?.status || {}
+ }, [download])
+
+ const minSpeed = 0.25;
+ const maxSpeed = 4.0;
+ const speedChange = 0.25;
+
+ const updatePlaybackRate = (newSpeed: number) => {
+ if (videoRef.current) {
+ if (newSpeed > maxSpeed || newSpeed < minSpeed)
+ newSpeed = minSpeed
+ videoRef.current.playbackRate = newSpeed
+ setPlaybackRate(newSpeed)
+ }
+ }
+
+ const increaseSpeed = (wrapOverflow = true) => {
+ const changedSpeed = playbackRate + speedChange
+ let newSpeed = wrapOverflow ? changedSpeed : Math.min(changedSpeed, maxSpeed)
+
+
+ if (videoRef.current) {
+ updatePlaybackRate(newSpeed);
+ }
+ }
+
+ const decreaseSpeed = () => {
+ if (videoRef.current) {
+ updatePlaybackRate(playbackRate - speedChange);
+ }
+ }
+
+
+
+ const refetch = React.useCallback(async () => {
+ if (!name || !identifier || !service || isFetchingProperties.current) return
+ try {
+ isFetchingProperties.current = true
+ await qortalRequest({
+ action: 'GET_QDN_RESOURCE_PROPERTIES',
+ name,
+ service,
+ identifier
+ })
+
+ } catch (error) {
+
+ } finally {
+ isFetchingProperties.current = false
+ }
+
+ }, [identifier, name, service])
+
+
+ const toggleRef = useRef(null)
+ const { downloadVideo } = useContext(MyContext)
+ const togglePlay = async () => {
+ if (!videoRef.current) return
+ setStartPlay(true)
+ if (!src || resourceStatus?.status !== 'READY') {
+ const el = document.getElementById('videoWrapper')
+ if (el) {
+ el?.parentElement?.removeChild(el)
+ }
+ ReactDOM.flushSync(() => {
+ setIsLoading(true)
+ })
+ getSrc()
+ }
+ if (playing) {
+ videoRef.current.pause()
+ } else {
+ videoRef.current.play()
+ }
+ setPlaying(!playing)
+ }
+
+ const onVolumeChange = (_: any, value: number | number[]) => {
+ if (!videoRef.current) return
+ videoRef.current.volume = value as number
+ setVolume(value as number)
+ setIsMuted(false)
+ }
+
+ const onProgressChange = (_: any, value: number | number[]) => {
+ if (!videoRef.current) return
+ videoRef.current.currentTime = value as number
+ setProgress(value as number)
+ if (!playing) {
+ videoRef.current.play()
+ setPlaying(true)
+ }
+ }
+
+ const handleEnded = () => {
+ setPlaying(false)
+ }
+
+ const updateProgress = () => {
+ if (!videoRef.current) return
+ setProgress(videoRef.current.currentTime)
+ }
+
+ const [isFullscreen, setIsFullscreen] = useState(false)
+
+ const enterFullscreen = () => {
+ if (!videoRef.current) return
+ if (videoRef.current.requestFullscreen) {
+ videoRef.current.requestFullscreen()
+ }
+ }
+
+ const exitFullscreen = () => {
+ if (document.exitFullscreen) {
+ document.exitFullscreen()
+ }
+ }
+
+ const toggleFullscreen = () => {
+ isFullscreen ? exitFullscreen() : enterFullscreen()
+ }
+ const togglePictureInPicture = async () => {
+ if (!videoRef.current) return
+ if (document.pictureInPictureElement === videoRef.current) {
+ await document.exitPictureInPicture()
+ } else {
+ await videoRef.current.requestPictureInPicture()
+ }
+ }
+
+ useEffect(() => {
+ const handleFullscreenChange = () => {
+ setIsFullscreen(!!document.fullscreenElement)
+ }
+
+ document.addEventListener('fullscreenchange', handleFullscreenChange)
+ return () => {
+ document.removeEventListener('fullscreenchange', handleFullscreenChange)
+ }
+ }, [])
+
+ useEffect(()=> {
+ if(videoPlaying && videoPlaying.id === identifier && src && videoRef?.current){
+ handleCanPlay()
+ videoRef.current.volume = videoPlaying.volume
+ videoRef.current.currentTime = videoPlaying.currentTime
+ videoRef.current.play()
+ setPlaying(true)
+ setStartPlay(true)
+ dispatch(setVideoPlaying(null))
+ }
+ }, [videoPlaying, identifier, src])
+
+ const handleCanPlay = () => {
+ setIsLoading(false)
+ setCanPlay(true)
+ }
+
+ const getSrc = React.useCallback(async () => {
+ if (!name || !identifier || !service || !jsonId || !user) return
+ try {
+ downloadVideo({
+ name,
+ service,
+ identifier,
+ properties: {
+ jsonId,
+ user
+ }
+ })
+ } catch (error) {
+ console.error(error)
+ }
+ }, [identifier, name, service, jsonId, user])
+
+ useEffect(() => {
+ const videoElement = videoRef.current
+
+ const handleLeavePictureInPicture = async (event: any) => {
+ const target = event?.target
+ if (target) {
+ target.pause()
+ if (setPlaying) {
+ setPlaying(false)
+ }
+ }
+ }
+
+ if (videoElement) {
+ videoElement.addEventListener(
+ 'leavepictureinpicture',
+ handleLeavePictureInPicture
+ )
+ }
+
+ return () => {
+ if (videoElement) {
+ videoElement.removeEventListener(
+ 'leavepictureinpicture',
+ handleLeavePictureInPicture
+ )
+ }
+ }
+ }, [])
+
+ useEffect(() => {
+ const videoElement = videoRef.current
+
+ const minimizeVideo = async () => {
+ if (!videoElement) return
+
+ dispatch(setVideoPlaying(videoElement))
+ // const handleClose = () => {
+ // if (videoElement && videoElement.parentElement) {
+ // const el = document.getElementById('videoWrapper')
+ // if (el) {
+ // el?.parentElement?.removeChild(el)
+ // }
+ // }
+ // }
+ // const createCloseButton = (): HTMLButtonElement => {
+ // const closeButton = document.createElement('button')
+ // closeButton.textContent = 'X'
+ // closeButton.style.position = 'absolute'
+ // closeButton.style.top = '0'
+ // closeButton.style.right = '0'
+ // closeButton.style.backgroundColor = 'rgba(255, 255, 255, 0.7)'
+ // closeButton.style.border = 'none'
+ // closeButton.style.fontWeight = 'bold'
+ // closeButton.style.fontSize = '1.2rem'
+ // closeButton.style.cursor = 'pointer'
+ // closeButton.style.padding = '2px 8px'
+ // closeButton.style.borderRadius = '0 0 0 4px'
+
+ // closeButton.addEventListener('click', handleClose)
+
+ // return closeButton
+ // }
+ // const buttonClose = createCloseButton()
+ // const videoWrapper = document.createElement('div')
+ // videoWrapper.id = 'videoWrapper'
+ // videoWrapper.style.position = 'fixed'
+ // videoWrapper.style.zIndex = '900000009'
+ // videoWrapper.style.bottom = '0px'
+ // videoWrapper.style.right = '0px'
+
+ // videoElement.parentElement?.insertBefore(videoWrapper, videoElement)
+ // videoWrapper.appendChild(videoElement)
+
+ // videoWrapper.appendChild(buttonClose)
+ // videoElement.controls = true
+ // videoElement.style.height = 'auto'
+ // videoElement.style.width = '300px'
+
+ // document.body.appendChild(videoWrapper)
+ }
+
+ return () => {
+ if (videoElement) {
+ if (videoElement && !videoElement.paused && !videoElement.ended) {
+ minimizeVideo()
+ }
+ }
+ }
+ }, [])
+
+ function formatTime(seconds: number): string {
+ seconds = Math.floor(seconds)
+ let minutes: number | string = Math.floor(seconds / 60)
+ let hours: number | string = Math.floor(minutes / 60)
+
+ let remainingSeconds: number | string = seconds % 60
+ let remainingMinutes: number | string = minutes % 60
+
+ if (remainingSeconds < 10) {
+ remainingSeconds = '0' + remainingSeconds
+ }
+
+ if (remainingMinutes < 10) {
+ remainingMinutes = '0' + remainingMinutes
+ }
+
+ if (hours === 0) {
+ hours = ''
+ }
+ else {
+ hours = hours + ':'
+ }
+
+ return hours + remainingMinutes + ':' + remainingSeconds
+ }
+
+ const reloadVideo = () => {
+ if (!videoRef.current) return
+ const currentTime = videoRef.current.currentTime
+ videoRef.current.src = src
+ videoRef.current.load()
+ videoRef.current.currentTime = currentTime
+ if (playing) {
+ videoRef.current.play()
+ }
+ }
+
+ const refetchInInterval = ()=> {
+ try {
+ const interval = setInterval(()=> {
+ if(status?.current === 'DOWNLOADED'){
+ refetch()
+ }
+ if(status?.current === 'READY'){
+ clearInterval(interval);
+ }
+
+ }, 7500)
+ } catch (error) {
+
+ }
+ }
+
+ useEffect(() => {
+ if(resourceStatus?.status){
+ status.current = resourceStatus?.status
+ }
+ if (
+ resourceStatus?.status === 'DOWNLOADED' &&
+ reDownload?.current === false
+ ) {
+ refetchInInterval()
+ reDownload.current = true
+ }
+ }, [getSrc, resourceStatus])
+
+ const handleMenuOpen = (event: any) => {
+ setAnchorEl(event.currentTarget)
+ }
+
+ const handleMenuClose = () => {
+ setAnchorEl(null)
+ }
+
+ useEffect(() => {
+ const videoWidth = videoRef?.current?.offsetWidth
+ if (videoWidth && videoWidth <= 600) {
+ setIsMobileView(true)
+ }
+ }, [canPlay])
+
+ const getDownloadProgress = (current: number, total: number) => {
+ const progress = current / total * 100;
+ return Number.isNaN(progress) ? '' : progress.toFixed(0) + '%'
+ }
+ const mute = () => {
+ setIsMuted(true)
+ setMutedVolume(volume)
+ setVolume(0)
+ if (videoRef.current) videoRef.current.volume = 0
+ }
+ const unMute = () => {
+ setIsMuted(false)
+ setVolume(mutedVolume)
+ if (videoRef.current) videoRef.current.volume = mutedVolume
+ }
+
+ const toggleMute = () => {
+ isMuted ? unMute() : mute();
+ }
+
+ const changeVolume = (volumeChange: number) => {
+ if (videoRef.current) {
+ const minVolume = 0;
+ const maxVolume = 1;
+
+
+ let newVolume = volumeChange + volume
+
+ newVolume = Math.max(newVolume, minVolume)
+ newVolume = Math.min(newVolume, maxVolume)
+
+ setIsMuted(false)
+ setMutedVolume(newVolume)
+ videoRef.current.volume = newVolume
+ setVolume(newVolume);
+ }
+
+ }
+ const setProgressRelative = (secondsChange: number) => {
+ if (videoRef.current) {
+ const currentTime = videoRef.current?.currentTime
+ const minTime = 0
+ const maxTime = videoRef.current?.duration || 100
+
+ let newTime = currentTime + secondsChange;
+ newTime = Math.max(newTime, minTime)
+ newTime = Math.min(newTime, maxTime)
+ videoRef.current.currentTime = newTime;
+ setProgress(newTime);
+ }
+ }
+
+ const setProgressAbsolute = (videoPercent: number) => {
+ if (videoRef.current) {
+ videoPercent = Math.min(videoPercent, 100)
+ videoPercent = Math.max(videoPercent, 0)
+ const finalTime = videoRef.current?.duration * videoPercent / 100
+ videoRef.current.currentTime = finalTime
+ setProgress(finalTime);
+ }
+ }
+
+
+ const keyboardShortcutsDown = (e: React.KeyboardEvent) => {
+ e.preventDefault()
+
+ switch (e.key) {
+ case Key.Add: increaseSpeed(false); break;
+ case '+': increaseSpeed(false); break;
+ case '>': increaseSpeed(false); break;
+
+ case Key.Subtract: decreaseSpeed(); break;
+ case '-': decreaseSpeed(); break;
+ case '<': decreaseSpeed(); break;
+
+ case Key.ArrowLeft: {
+ if (e.shiftKey) setProgressRelative(-300);
+ else if (e.ctrlKey) setProgressRelative(-60);
+ else if (e.altKey) setProgressRelative(-10);
+ else setProgressRelative(-5);
+ } break;
+
+ case Key.ArrowRight: {
+ if (e.shiftKey) setProgressRelative(300);
+ else if (e.ctrlKey) setProgressRelative(60);
+ else if (e.altKey) setProgressRelative(10);
+ else setProgressRelative(5);
+ } break;
+
+ case Key.ArrowDown: changeVolume(-0.05); break;
+ case Key.ArrowUp: changeVolume(0.05); break;
+ }
+ }
+
+ const keyboardShortcutsUp = (e: React.KeyboardEvent) => {
+ e.preventDefault()
+
+ switch (e.key) {
+ case ' ': togglePlay(); break;
+ case 'm': toggleMute(); break;
+
+ case 'f': enterFullscreen(); break;
+ case Key.Escape: exitFullscreen(); break;
+
+ case '0': setProgressAbsolute(0); break;
+ case '1': setProgressAbsolute(10); break;
+ case '2': setProgressAbsolute(20); break;
+ case '3': setProgressAbsolute(30); break;
+ case '4': setProgressAbsolute(40); break;
+ case '5': setProgressAbsolute(50); break;
+ case '6': setProgressAbsolute(60); break;
+ case '7': setProgressAbsolute(70); break;
+ case '8': setProgressAbsolute(80); break;
+ case '9': setProgressAbsolute(90); break;
+ }
+ }
+
+ return (
+
+
+ {isLoading && (
+
+
+ {resourceStatus && (
+
+ {resourceStatus?.status === 'NOT_PUBLISHED' && (
+ <>Video file was not published. Please inform the publisher!>
+ )}
+ {resourceStatus?.status === 'REFETCHING' ? (
+ <>
+ <>
+ {getDownloadProgress(resourceStatus?.localChunkCount, resourceStatus?.totalChunkCount)}
+ >
+
+ <> Refetching in 25 seconds>
+ >
+ ) : resourceStatus?.status === 'DOWNLOADED' ? (
+ <>Download Completed: building video...>
+ ) : resourceStatus?.status !== 'READY' ? (
+ <>
+ {getDownloadProgress(resourceStatus?.localChunkCount, resourceStatus?.totalChunkCount)}
+
+ >
+ ) : (
+ <>Fetching video...>
+ )}
+
+ )}
+
+ )}
+ {((!src && !isLoading) || !startPlay) && (
+ {
+ if (from === 'create') return
+ dispatch(setVideoPlaying(null))
+ togglePlay()
+ }}
+ sx={{
+ cursor: 'pointer'
+ }}
+ >
+
+
+ )}
+
+
+
+
+ {isMobileView && canPlay ? (
+ <>
+
+ {playing ? : }
+
+
+
+
+
+
+
+
+
+ >
+ ) : canPlay ? (
+ <>
+
+ {playing ? : }
+
+
+
+
+
+
+ {progress && videoRef.current?.duration && formatTime(progress)}/
+ {progress &&
+ videoRef.current?.duration &&
+ formatTime(videoRef.current?.duration)}
+
+
+ {isMuted ? : }
+
+
+ increaseSpeed()}
+ >
+ Speed: {playbackRate}x
+
+
+
+
+
+
+
+
+ >
+ ) : null}
+
+
+ )
+}
diff --git a/src/components/common/VideoPlayerGlobal.tsx b/src/components/common/VideoPlayerGlobal.tsx
new file mode 100644
index 0000000..da14639
--- /dev/null
+++ b/src/components/common/VideoPlayerGlobal.tsx
@@ -0,0 +1,648 @@
+import React, { useContext, useEffect, useMemo, useRef, useState } from 'react'
+import ReactDOM from 'react-dom'
+import { Box, IconButton, Slider, useTheme } from '@mui/material'
+import { CircularProgress, Typography } from '@mui/material'
+import { Key } from 'ts-key-enum'
+import {
+ PlayArrow,
+ Pause,
+ VolumeUp,
+ Fullscreen,
+ PictureInPicture, VolumeOff
+} from '@mui/icons-material'
+import { styled } from '@mui/system'
+import { MyContext } from '../../wrappers/DownloadWrapper'
+import { useDispatch, useSelector } from 'react-redux'
+import { RootState } from '../../state/store'
+import { Refresh } from '@mui/icons-material'
+import CloseIcon from '@mui/icons-material/Close';
+
+import { Menu, MenuItem } from '@mui/material'
+import { MoreVert as MoreIcon } from '@mui/icons-material'
+import { setVideoPlaying } from '../../state/features/globalSlice'
+const VideoContainer = styled(Box)`
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ width: 100%;
+ height: 100%;
+ margin: 0px;
+ padding: 0px;
+`
+
+const VideoElement = styled('video')`
+ width: 100%;
+ height: auto;
+ max-height: calc(100vh - 150px);
+ background: rgb(33, 33, 33);
+`
+
+const ControlsContainer = styled(Box)`
+ position: absolute;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ padding: 8px;
+ background-color: rgba(0, 0, 0, 0.6);
+`
+
+interface VideoPlayerProps {
+ src?: string
+ poster?: string
+ name?: string
+ identifier?: string
+ service?: string
+ autoplay?: boolean
+ from?: string | null
+ customStyle?: any
+ user?: string
+ jsonId?: string
+ element?: null | any
+ checkIfDrag?: ()=> boolean;
+}
+
+export const VideoPlayerGlobal: React.FC = ({
+ poster,
+ name,
+ identifier,
+ service,
+ autoplay = true,
+ from = null,
+ customStyle = {},
+ user = '',
+ jsonId = '',
+ element,
+ checkIfDrag
+}) => {
+ const theme = useTheme()
+
+ const videoRef = useRef(null)
+ const [playing, setPlaying] = useState(false)
+ const [volume, setVolume] = useState(1)
+ const [mutedVolume, setMutedVolume] = useState(1)
+ const [isMuted, setIsMuted] = useState(false)
+ const [progress, setProgress] = useState(0)
+ const [isLoading, setIsLoading] = useState(false)
+ const [canPlay, setCanPlay] = useState(false)
+ const [startPlay, setStartPlay] = useState(false)
+ const [isMobileView, setIsMobileView] = useState(false)
+ const [playbackRate, setPlaybackRate] = useState(1)
+ const [anchorEl, setAnchorEl] = useState(null)
+ const dispatch = useDispatch()
+ const reDownload = useRef(false)
+ const { downloads } = useSelector((state: RootState) => state.global)
+ const download = useMemo(() => {
+ if (!downloads || !identifier) return {}
+ const findDownload = downloads[identifier]
+
+ if (!findDownload) return {}
+ return findDownload
+ }, [downloads, identifier])
+
+
+ const resourceStatus = useMemo(() => {
+ return download?.status || {}
+ }, [download])
+
+ const minSpeed = 0.25;
+ const maxSpeed = 4.0;
+ const speedChange = 0.25;
+
+ const updatePlaybackRate = (newSpeed: number) => {
+ if (videoRef.current) {
+ if (newSpeed > maxSpeed || newSpeed < minSpeed)
+ newSpeed = minSpeed
+ videoRef.current.playbackRate = newSpeed
+ setPlaybackRate(newSpeed)
+ }
+ }
+
+ const increaseSpeed = (wrapOverflow = true) => {
+ const changedSpeed = playbackRate + speedChange
+ let newSpeed = wrapOverflow ? changedSpeed : Math.min(changedSpeed, maxSpeed)
+
+
+ if (videoRef.current) {
+ updatePlaybackRate(newSpeed);
+ }
+ }
+
+ const decreaseSpeed = () => {
+ if (videoRef.current) {
+ updatePlaybackRate(playbackRate - speedChange);
+ }
+ }
+
+
+ const toggleRef = useRef(null)
+ const { downloadVideo } = useContext(MyContext)
+ const togglePlay = async () => {
+
+ if(checkIfDrag && checkIfDrag()) return
+ if (!videoRef.current) return
+ if (playing) {
+ videoRef.current.pause()
+ } else {
+ videoRef.current.play()
+ }
+ setPlaying((prev)=> !prev)
+ }
+
+ const onVolumeChange = (_: any, value: number | number[]) => {
+ if (!videoRef.current) return
+ videoRef.current.volume = value as number
+ setVolume(value as number)
+ setIsMuted(false)
+ }
+
+ const onProgressChange = (_: any, value: number | number[]) => {
+ if (!videoRef.current) return
+ videoRef.current.currentTime = value as number
+ setProgress(value as number)
+ if (!playing) {
+ videoRef.current.play()
+ setPlaying(true)
+ }
+ }
+
+ const handleEnded = () => {
+ setPlaying(false)
+ }
+
+ const updateProgress = () => {
+ if (!videoRef.current) return
+ setProgress(videoRef.current.currentTime)
+ }
+
+ const [isFullscreen, setIsFullscreen] = useState(false)
+
+ const enterFullscreen = () => {
+ if (!videoRef.current) return
+ if (videoRef.current.requestFullscreen) {
+ videoRef.current.requestFullscreen()
+ }
+ }
+
+ const exitFullscreen = () => {
+ if (document.exitFullscreen) {
+ document.exitFullscreen()
+ }
+ }
+
+ const toggleFullscreen = () => {
+ isFullscreen ? exitFullscreen() : enterFullscreen()
+ }
+ const togglePictureInPicture = async () => {
+ if (!videoRef.current) return
+ if (document.pictureInPictureElement === videoRef.current) {
+ await document.exitPictureInPicture()
+ } else {
+ await videoRef.current.requestPictureInPicture()
+ }
+ }
+
+ useEffect(() => {
+ const handleFullscreenChange = () => {
+ setIsFullscreen(!!document.fullscreenElement)
+ }
+
+ document.addEventListener('fullscreenchange', handleFullscreenChange)
+ return () => {
+ document.removeEventListener('fullscreenchange', handleFullscreenChange)
+ }
+ }, [])
+
+
+ const handleCanPlay = () => {
+ setIsLoading(false)
+ setCanPlay(true)
+ }
+
+
+
+ useEffect(() => {
+ const videoElement = videoRef.current
+
+ const handleLeavePictureInPicture = async (event: any) => {
+ const target = event?.target
+ if (target) {
+ target.pause()
+ if (setPlaying) {
+ setPlaying(false)
+ }
+ }
+ }
+
+ if (videoElement) {
+ videoElement.addEventListener(
+ 'leavepictureinpicture',
+ handleLeavePictureInPicture
+ )
+ }
+
+ return () => {
+ if (videoElement) {
+ videoElement.removeEventListener(
+ 'leavepictureinpicture',
+ handleLeavePictureInPicture
+ )
+ }
+ }
+ }, [])
+
+
+
+ function formatTime(seconds: number): string {
+ seconds = Math.floor(seconds)
+ let minutes: number | string = Math.floor(seconds / 60)
+ let hours: number | string = Math.floor(minutes / 60)
+
+ let remainingSeconds: number | string = seconds % 60
+ let remainingMinutes: number | string = minutes % 60
+
+ if (remainingSeconds < 10) {
+ remainingSeconds = '0' + remainingSeconds
+ }
+
+ if (remainingMinutes < 10) {
+ remainingMinutes = '0' + remainingMinutes
+ }
+
+ if (hours === 0) {
+ hours = ''
+ }
+ else {
+ hours = hours + ':'
+ }
+
+ return hours + remainingMinutes + ':' + remainingSeconds
+ }
+
+ const reloadVideo = () => {
+ if (!videoRef.current) return
+ const src = videoRef.current.src
+ const currentTime = videoRef.current.currentTime
+ videoRef.current.src = src
+ videoRef.current.load()
+ videoRef.current.currentTime = currentTime
+ if (playing) {
+ videoRef.current.play()
+ }
+ }
+
+
+ const handleMenuOpen = (event: any) => {
+ setAnchorEl(event.currentTarget)
+ }
+
+
+ const handleMenuClose = () => {
+ setAnchorEl(null)
+ }
+
+ useEffect(() => {
+ const videoWidth = videoRef?.current?.offsetWidth
+ if (videoWidth && videoWidth <= 600) {
+ setIsMobileView(true)
+ }
+ }, [canPlay])
+
+ const getDownloadProgress = (current: number, total: number) => {
+ const progress = current / total * 100;
+ return Number.isNaN(progress) ? '' : progress.toFixed(0) + '%'
+ }
+ const mute = () => {
+ setIsMuted(true)
+ setMutedVolume(volume)
+ setVolume(0)
+ if (videoRef.current) videoRef.current.volume = 0
+ }
+ const unMute = () => {
+ setIsMuted(false)
+ setVolume(mutedVolume)
+ if (videoRef.current) videoRef.current.volume = mutedVolume
+ }
+
+ const toggleMute = () => {
+ isMuted ? unMute() : mute();
+ }
+
+ const changeVolume = (volumeChange: number) => {
+ if (videoRef.current) {
+ const minVolume = 0;
+ const maxVolume = 1;
+
+
+ let newVolume = volumeChange + volume
+
+ newVolume = Math.max(newVolume, minVolume)
+ newVolume = Math.min(newVolume, maxVolume)
+
+ setIsMuted(false)
+ setMutedVolume(newVolume)
+ videoRef.current.volume = newVolume
+ setVolume(newVolume);
+ }
+
+ }
+ const setProgressRelative = (secondsChange: number) => {
+ if (videoRef.current) {
+ const currentTime = videoRef.current?.currentTime
+ const minTime = 0
+ const maxTime = videoRef.current?.duration || 100
+
+ let newTime = currentTime + secondsChange;
+ newTime = Math.max(newTime, minTime)
+ newTime = Math.min(newTime, maxTime)
+ videoRef.current.currentTime = newTime;
+ setProgress(newTime);
+ }
+ }
+
+ const setProgressAbsolute = (videoPercent: number) => {
+ if (videoRef.current) {
+ videoPercent = Math.min(videoPercent, 100)
+ videoPercent = Math.max(videoPercent, 0)
+ const finalTime = videoRef.current?.duration * videoPercent / 100
+ videoRef.current.currentTime = finalTime
+ setProgress(finalTime);
+ }
+ }
+
+
+ const keyboardShortcutsDown = (e: React.KeyboardEvent) => {
+ e.preventDefault()
+
+ switch (e.key) {
+ case Key.Add: increaseSpeed(false); break;
+ case '+': increaseSpeed(false); break;
+ case '>': increaseSpeed(false); break;
+
+ case Key.Subtract: decreaseSpeed(); break;
+ case '-': decreaseSpeed(); break;
+ case '<': decreaseSpeed(); break;
+
+ case Key.ArrowLeft: {
+ if (e.shiftKey) setProgressRelative(-300);
+ else if (e.ctrlKey) setProgressRelative(-60);
+ else if (e.altKey) setProgressRelative(-10);
+ else setProgressRelative(-5);
+ } break;
+
+ case Key.ArrowRight: {
+ if (e.shiftKey) setProgressRelative(300);
+ else if (e.ctrlKey) setProgressRelative(60);
+ else if (e.altKey) setProgressRelative(10);
+ else setProgressRelative(5);
+ } break;
+
+ case Key.ArrowDown: changeVolume(-0.05); break;
+ case Key.ArrowUp: changeVolume(0.05); break;
+ }
+ }
+
+ const keyboardShortcutsUp = (e: React.KeyboardEvent) => {
+ e.preventDefault()
+
+ switch (e.key) {
+ case ' ': togglePlay(); break;
+ case 'm': toggleMute(); break;
+
+ case 'f': enterFullscreen(); break;
+ case Key.Escape: exitFullscreen(); break;
+
+ case '0': setProgressAbsolute(0); break;
+ case '1': setProgressAbsolute(10); break;
+ case '2': setProgressAbsolute(20); break;
+ case '3': setProgressAbsolute(30); break;
+ case '4': setProgressAbsolute(40); break;
+ case '5': setProgressAbsolute(50); break;
+ case '6': setProgressAbsolute(60); break;
+ case '7': setProgressAbsolute(70); break;
+ case '8': setProgressAbsolute(80); break;
+ case '9': setProgressAbsolute(90); break;
+ }
+ }
+
+ useEffect(()=> {
+ if(element){
+ let oldElement = document.getElementById('videoPlayer');
+ if(oldElement && oldElement?.parentNode){
+ oldElement?.parentNode.replaceChild(element, oldElement);
+ videoRef.current = element
+ setPlaying(true)
+ setCanPlay(true)
+ setStartPlay(true)
+ videoRef?.current?.addEventListener('click', ()=> {})
+ videoRef?.current?.addEventListener('timeupdate', updateProgress)
+ videoRef?.current?.addEventListener('ended', handleEnded)
+
+ }
+
+ }
+}, [element])
+
+ return (
+
+
+
+ {
+ dispatch(setVideoPlaying(null))
+ }} sx={{
+ cursor: 'pointer',
+ backgroundColor: 'rgba(0,0,0,.5)'
+ }}>
+
+
+
+
+
+ {isMobileView && canPlay ? (
+ <>
+
+ {playing ? : }
+
+
+
+
+
+
+
+
+
+ >
+ ) : canPlay ? (
+ <>
+
+ {playing ? : }
+
+
+
+
+
+
+ {progress && videoRef.current?.duration && formatTime(progress)}/
+ {progress &&
+ videoRef.current?.duration &&
+ formatTime(videoRef.current?.duration)}
+
+
+ {isMuted ? : }
+
+
+ increaseSpeed()}
+ >
+ Speed: {playbackRate}x
+
+
+
+
+
+
+
+
+ >
+ ) : null}
+
+
+ )
+}
diff --git a/src/components/layout/Navbar/Navbar-styles.tsx b/src/components/layout/Navbar/Navbar-styles.tsx
new file mode 100644
index 0000000..4c3fed0
--- /dev/null
+++ b/src/components/layout/Navbar/Navbar-styles.tsx
@@ -0,0 +1,121 @@
+import { AppBar, Button, Typography, Box } from "@mui/material";
+import { styled } from "@mui/system";
+import { LightModeSVG } from "../../../assets/svgs/LightModeSVG";
+import { DarkModeSVG } from "../../../assets/svgs/DarkModeSVG";
+
+export const CustomAppBar = styled(AppBar)(({ theme }) => ({
+ display: "flex",
+ flexDirection: "row",
+ justifyContent: "space-between",
+ alignItems: "center",
+ width: "100%",
+ padding: "5px 16px",
+ backgroundImage: "none",
+ borderBottom: `1px solid ${theme.palette.primary.light}`,
+ backgroundColor: theme.palette.background.default,
+ [theme.breakpoints.only("xs")]: {
+ gap: "15px",
+ },
+ height: "100px",
+}));
+export const LogoContainer = styled("div")({
+ cursor: "pointer",
+ height: "100%",
+ display: "flex",
+ alignItems: "center",
+});
+
+export const CustomTitle = styled(Typography)({
+ fontWeight: 600,
+ color: "#000000",
+});
+
+export const AuthenticateButton = styled(Button)(({ theme }) => ({
+ display: "flex",
+ flexDirection: "row",
+ alignItems: "center",
+ padding: "8px 15px",
+ borderRadius: "40px",
+ gap: "4px",
+ backgroundColor: theme.palette.secondary.main,
+ color: "#fff",
+ fontFamily: "Raleway",
+ transition: "all 0.3s ease-in-out",
+ boxShadow: "none",
+ "&:hover": {
+ cursor: "pointer",
+ boxShadow: "rgba(0, 0, 0, 0.15) 1.95px 1.95px 2.6px;",
+ backgroundColor: theme.palette.secondary.dark,
+ filter: "brightness(1.1)",
+ },
+}));
+
+export const AvatarContainer = styled(Box)({
+ display: "flex",
+ alignItems: "center",
+ "&:hover": {
+ cursor: "pointer",
+ "& #expand-icon": {
+ transition: "all 0.3s ease-in-out",
+ filter: "brightness(0.7)",
+ },
+ },
+});
+
+export const DropdownContainer = styled(Box)(({ theme }) => ({
+ display: "flex",
+ alignItems: "center",
+ gap: "5px",
+ backgroundColor: theme.palette.background.paper,
+ padding: "10px 15px",
+ transition: "all 0.4s ease-in-out",
+ "&:hover": {
+ cursor: "pointer",
+ filter:
+ theme.palette.mode === "light" ? "brightness(0.95)" : "brightness(1.1)",
+ },
+}));
+
+export const DropdownText = styled(Typography)(({ theme }) => ({
+ fontFamily: "Raleway",
+ fontSize: "16px",
+ color: theme.palette.text.primary,
+ userSelect: "none",
+}));
+
+export const NavbarName = styled(Typography)(({ theme }) => ({
+ fontFamily: "Raleway",
+ fontSize: "18px",
+ color: theme.palette.text.primary,
+ margin: "0 10px",
+}));
+
+export const ThemeSelectRow = styled(Box)({
+ display: "flex",
+ alignItems: "center",
+ gap: "5px",
+ flexBasis: 0,
+ height: "100%",
+});
+
+export const LightModeIcon = styled(LightModeSVG)(({ theme }) => ({
+ transition: "all 0.1s ease-in-out",
+ "&:hover": {
+ cursor: "pointer",
+ filter:
+ theme.palette.mode === "dark"
+ ? "drop-shadow(0px 4px 6px rgba(255, 255, 255, 0.6))"
+ : "drop-shadow(0px 4px 6px rgba(99, 88, 88, 0.1))",
+ },
+}));
+
+export const DarkModeIcon = styled(DarkModeSVG)(({ theme }) => ({
+ transition: "all 0.1s ease-in-out",
+ "&:hover": {
+ cursor: "pointer",
+ filter:
+ theme.palette.mode === "dark"
+ ? "drop-shadow(0px 4px 6px rgba(255, 255, 255, 0.6))"
+ : "drop-shadow(0px 4px 6px rgba(99, 88, 88, 0.1))",
+ },
+}));
diff --git a/src/components/layout/Navbar/Navbar.tsx b/src/components/layout/Navbar/Navbar.tsx
new file mode 100644
index 0000000..f184c92
--- /dev/null
+++ b/src/components/layout/Navbar/Navbar.tsx
@@ -0,0 +1,312 @@
+import React, { useRef, useState } from "react";
+import { Box, Input, Popover, Typography, useTheme } from "@mui/material";
+import { BlockedNamesModal } from "../../common/BlockedNamesModal/BlockedNamesModal";
+
+import {
+ AvatarContainer,
+ CustomAppBar,
+ DropdownContainer,
+ DropdownText,
+ LogoContainer,
+ NavbarName,
+ ThemeSelectRow,
+} from "./Navbar-styles";
+import { AccountCircleSVG } from "../../../assets/svgs/AccountCircleSVG";
+import BackspaceIcon from "@mui/icons-material/Backspace";
+
+import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
+import PersonOffIcon from "@mui/icons-material/PersonOff";
+import { useNavigate } from "react-router-dom";
+import SearchIcon from "@mui/icons-material/Search";
+
+import { DownloadTaskManager } from "../../common/DownloadTaskManager";
+import QSupportLogo from "../../../assets/img/Q-SupportIcon.webp";
+import { useDispatch, useSelector } from "react-redux";
+import {
+ addFilteredFiles,
+ setFilterValue,
+ setIsFiltering,
+} from "../../../state/features/fileSlice.ts";
+import { RootState } from "../../../state/store";
+import { useWindowSize } from "../../../hooks/useWindowSize";
+import { PublishIssue } from "../../PublishIssue/PublishIssue.tsx";
+
+interface Props {
+ isAuthenticated: boolean;
+ userName: string | null;
+ userAvatar: string;
+ authenticate: () => void;
+ setTheme: (val: string) => void;
+}
+
+const NavBar: React.FC = ({
+ isAuthenticated,
+ userName,
+ userAvatar,
+ authenticate,
+ setTheme,
+}) => {
+ const windowSize = useWindowSize();
+ const searchValRef = useRef("");
+ const inputRef = useRef(null);
+ const theme = useTheme();
+ const dispatch = useDispatch();
+ const navigate = useNavigate();
+ const [anchorEl, setAnchorEl] = React.useState(
+ null
+ );
+ const [openUserDropdown, setOpenUserDropdown] = useState(false);
+ const [isOpenBlockedNamesModal, setIsOpenBlockedNamesModal] =
+ useState(false);
+
+ const [anchorElNotification, setAnchorElNotification] =
+ React.useState(null);
+ const filterValue = useSelector((state: RootState) => state.file.filterValue);
+
+ const handleClick = (event: React.MouseEvent) => {
+ const target = event.currentTarget as unknown as HTMLButtonElement | null;
+ setAnchorEl(target);
+ };
+ const openNotificationPopover = (event: any) => {
+ const target = event.currentTarget as unknown as HTMLButtonElement | null;
+ setAnchorElNotification(target);
+ };
+ const closeNotificationPopover = () => {
+ setAnchorElNotification(null);
+ };
+
+ const openPopover = Boolean(anchorElNotification);
+ const idNotification = openPopover
+ ? "simple-popover-notification"
+ : undefined;
+
+ const handleCloseUserDropdown = () => {
+ setAnchorEl(null);
+ setOpenUserDropdown(false);
+ };
+
+ const onCloseBlockedNames = () => {
+ setIsOpenBlockedNamesModal(false);
+ };
+
+ return (
+
+
+
+ {
+ navigate("/");
+ dispatch(setIsFiltering(false));
+ dispatch(setFilterValue(""));
+ dispatch(addFilteredFiles([]));
+ searchValRef.current = "";
+ if (!inputRef.current) return;
+ inputRef.current.value = "";
+ }}
+ >
+
+
+
+ Welcome to Q-Support
+
+
+
+
+
+
+ {
+ searchValRef.current = e.target.value;
+ }}
+ onKeyDown={event => {
+ if (event.key === "Enter" || event.keyCode === 13) {
+ if (!searchValRef.current) {
+ dispatch(setIsFiltering(false));
+ dispatch(setFilterValue(""));
+ dispatch(addFilteredFiles([]));
+ searchValRef.current = "";
+ if (!inputRef.current) return;
+ inputRef.current.value = "";
+ return;
+ }
+ navigate("/");
+ dispatch(setIsFiltering(true));
+ dispatch(addFilteredFiles([]));
+ dispatch(setFilterValue(searchValRef.current));
+ }
+ }}
+ placeholder="Search"
+ sx={{
+ "&&:before": {
+ borderBottom: "none",
+ },
+ "&&:after": {
+ borderBottom: "none",
+ },
+ "&&:hover:before": {
+ borderBottom: "none",
+ },
+ "&&.Mui-focused:before": {
+ borderBottom: "none",
+ },
+ "&&.Mui-focused": {
+ outline: "none",
+ },
+ fontSize: "18px",
+ }}
+ />
+
+ {
+ if (!searchValRef.current) {
+ dispatch(setIsFiltering(false));
+ dispatch(setFilterValue(""));
+ dispatch(addFilteredFiles([]));
+ searchValRef.current = "";
+ if (!inputRef.current) return;
+ inputRef.current.value = "";
+ return;
+ }
+ navigate("/");
+ dispatch(setIsFiltering(true));
+ dispatch(addFilteredFiles([]));
+ dispatch(setFilterValue(searchValRef.current));
+ }}
+ />
+ {
+ dispatch(setIsFiltering(false));
+ dispatch(setFilterValue(""));
+ dispatch(addFilteredFiles([]));
+ searchValRef.current = "";
+ if (!inputRef.current) return;
+ inputRef.current.value = "";
+ }}
+ />
+
+
+
+
+ {isAuthenticated && userName && (
+ <>
+ {
+ handleClick(e);
+ setOpenUserDropdown(true);
+ }}
+ >
+ {userName}
+ {!userAvatar ? (
+
+ ) : (
+
+ )}
+
+
+ >
+ )}
+
+ {isAuthenticated && userName && (
+ <>
+
+ >
+ )}
+
+
+
+ {
+ setIsOpenBlockedNamesModal(true);
+ handleCloseUserDropdown();
+ }}
+ >
+
+ Blocked Names
+
+
+ {isOpenBlockedNamesModal && (
+
+ )}
+
+
+ );
+};
+
+export default NavBar;
diff --git a/src/constants/Categories/1stCategories.ts b/src/constants/Categories/1stCategories.ts
new file mode 100644
index 0000000..a074e55
--- /dev/null
+++ b/src/constants/Categories/1stCategories.ts
@@ -0,0 +1,48 @@
+import audioIcon from "../../assets/icons/audio.webp";
+import bookIcon from "../../assets/icons/book.webp";
+import documentIcon from "../../assets/icons/document.webp";
+import gamingIcon from "../../assets/icons/gaming.webp";
+import imageIcon from "../../assets/icons/image.webp";
+import softwareIcon from "../../assets/icons/software.webp";
+import unknownIcon from "../../assets/icons/unknown.webp";
+import videoIcon from "../../assets/icons/video.webp";
+
+import {
+ Categories,
+ Category,
+ CategoryData,
+} from "../../components/common/CategoryList/CategoryList.tsx";
+import {
+ getAllCategoriesWithIcons,
+ sortCategory,
+} from "./CategoryFunctions.ts";
+import { QappCategories, SupportState } from "./2ndCategories.ts";
+
+export const firstCategories: Category[] = [
+ { id: 1, name: "Core" },
+ { id: 2, name: "UI" },
+ { id: 3, name: "Q-Apps" },
+ { id: 4, name: "Website" },
+ { id: 5, name: "Marketing" },
+ { id: 99, name: "Other" },
+];
+export const secondCategories: Categories = {
+ 1: SupportState,
+ 2: SupportState,
+ 3: QappCategories,
+ 4: SupportState,
+ 5: SupportState,
+ 99: SupportState,
+};
+
+export let thirdCategories: Categories = {};
+QappCategories.map(
+ supportStateCategory =>
+ (thirdCategories[supportStateCategory.id] = SupportState)
+);
+export const allCategoryData: CategoryData = {
+ category: firstCategories,
+ subCategories: [secondCategories, thirdCategories],
+};
+
+export const iconCategories = getAllCategoriesWithIcons();
diff --git a/src/constants/Categories/2ndCategories.ts b/src/constants/Categories/2ndCategories.ts
new file mode 100644
index 0000000..ead50e9
--- /dev/null
+++ b/src/constants/Categories/2ndCategories.ts
@@ -0,0 +1,23 @@
+import OpenIcon from "../../assets/icons/OpenIcon.png";
+import ClosedIcon from "../../assets/icons/ClosedIcon.png";
+import InProgressIcon from "../../assets/icons/InProgressIcon.png";
+import CompleteIcon from "../../assets/icons/CompleteIcon.png";
+
+export const SupportState = [
+ { id: 101, name: "Open", icon: OpenIcon },
+ { id: 102, name: "Closed", icon: ClosedIcon },
+ { id: 103, name: "In Progress", icon: InProgressIcon },
+ { id: 104, name: "Complete", icon: CompleteIcon },
+];
+
+export const QappCategories = [
+ { id: 301, name: "Q-Blog" },
+ { id: 302, name: "Q-Mail" },
+ { id: 303, name: "Q-Shop" },
+ { id: 304, name: "Q-Fund" },
+ { id: 305, name: "Ear-Bump" },
+ { id: 306, name: "Q-Tube" },
+ { id: 307, name: "Q-Share" },
+ { id: 308, name: "Q-Support" },
+ { id: 399, name: "Other" },
+];
diff --git a/src/constants/Categories/3rdCategories.ts b/src/constants/Categories/3rdCategories.ts
new file mode 100644
index 0000000..e69de29
diff --git a/src/constants/Categories/CategoryFunctions.ts b/src/constants/Categories/CategoryFunctions.ts
new file mode 100644
index 0000000..3c228b7
--- /dev/null
+++ b/src/constants/Categories/CategoryFunctions.ts
@@ -0,0 +1,91 @@
+import {
+ Category,
+ getCategoriesFromObject,
+} from "../../components/common/CategoryList/CategoryList.tsx";
+import { allCategoryData, iconCategories } from "./1stCategories.ts";
+
+export const sortCategory = (a: Category, b: Category) => {
+ if (a.name === "Other") return 1;
+ else if (b.name === "Other") return -1;
+ else return a.name.localeCompare(b.name);
+};
+type Direction = "forward" | "backward";
+const findCategory = (categoryID: number) => {
+ return allCategoryData.category.find(category => {
+ return category.id === categoryID;
+ });
+};
+const findSubCategory = (
+ categoryID: number,
+ direction: Direction = "forward"
+) => {
+ const subCategoriesList = allCategoryData.subCategories;
+ if (direction === "backward") subCategoriesList.reverse();
+
+ for (const subCategories of subCategoriesList) {
+ for (const subCategoryID in subCategories) {
+ const returnValue = subCategories[subCategoryID].find(categoryObj => {
+ return categoryObj.id === categoryID;
+ });
+ if (returnValue) return returnValue;
+ }
+ }
+};
+export const findCategoryData = (
+ categoryID: number,
+ direction: Direction = "forward"
+) => {
+ return direction === "forward"
+ ? findCategory(categoryID) || findSubCategory(categoryID, "forward")
+ : findSubCategory(categoryID, "backward") || findCategory(categoryID);
+};
+export const findAllCategoryData = (
+ categories: string[],
+ direction: Direction = "forward"
+) => {
+ let foundIcons: Category[] = [];
+ if (direction === "backward") categories.reverse();
+
+ categories.map(category => {
+ if (category) {
+ const icon = findCategoryData(+category, "backward");
+ if (icon) foundIcons.push(icon);
+ }
+ });
+ return foundIcons;
+};
+
+export const getCategoriesWithIcons = (categories: Category[]) => {
+ return categories.filter(category => {
+ return category.icon;
+ });
+};
+
+export const getAllCategoriesWithIcons = () => {
+ const categoriesWithIcons: Category[] = [];
+
+ allCategoryData.category.map(category => {
+ if (category.icon) categoriesWithIcons.push(category);
+ });
+ const subCategoriesList = allCategoryData.subCategories;
+
+ for (const subCategories of subCategoriesList) {
+ for (const subCategoryID in subCategories) {
+ const categoryWithIcon = subCategories[subCategoryID].map(categoryObj => {
+ if (categoryObj.icon) categoriesWithIcons.push(categoryObj);
+ });
+ }
+ }
+ return categoriesWithIcons;
+};
+
+export const getIconsFromObject = (fileObj: any) => {
+ const categories = getCategoriesFromObject(fileObj);
+ const icons = categories
+ .map(categoryID => {
+ return iconCategories.find(category => category.id === +categoryID)?.icon;
+ })
+ .reverse();
+
+ return icons.find(icon => icon !== undefined);
+};
diff --git a/src/constants/Identifiers.ts b/src/constants/Identifiers.ts
new file mode 100644
index 0000000..446f2b3
--- /dev/null
+++ b/src/constants/Identifiers.ts
@@ -0,0 +1,13 @@
+const useTestIdentifiers = false;
+
+export const QSUPPORT_FILE_BASE = useTestIdentifiers
+ ? "MYTEST_support_issue_"
+ : "q_support_issue_";
+
+export const QSUPPORT_PLAYLIST_BASE = useTestIdentifiers
+ ? "MYTEST_support_playlist_"
+ : "q_support_playlist_";
+
+export const QSUPPORT_COMMENT_BASE = useTestIdentifiers
+ ? "qcomment_v1_MYTEST_support_"
+ : "qcomment_v1_q_support_";
diff --git a/src/constants/Misc.ts b/src/constants/Misc.ts
new file mode 100644
index 0000000..7de896c
--- /dev/null
+++ b/src/constants/Misc.ts
@@ -0,0 +1,5 @@
+export const minPriceSuperlike = 10;
+export const titleFormatter = /[^a-zA-Z0-9\s-_!?()&'",.;:|—~@#$%^*+=<>]/g;
+export const titleFormatterOnSave = /[^a-zA-Z0-9\s-_!()&',.;—~@#$%^+=]/g;
+
+export const log = false;
diff --git a/src/global.d.ts b/src/global.d.ts
new file mode 100644
index 0000000..27c12a2
--- /dev/null
+++ b/src/global.d.ts
@@ -0,0 +1,62 @@
+// src/global.d.ts
+interface QortalRequestOptions {
+ action: string
+ name?: string
+ service?: string
+ data64?: string
+ title?: string
+ description?: string
+ category?: string
+ tags?: string[]
+ identifier?: string
+ address?: string
+ metaData?: string
+ encoding?: string
+ includeMetadata?: boolean
+ limit?: numebr
+ offset?: number
+ reverse?: boolean
+ resources?: any[]
+ filename?: string
+ list_name?: string
+ item?: string
+ items?: strings[]
+ tag1?: string
+ tag2?: string
+ tag3?: string
+ tag4?: string
+ tag5?: string
+ coin?: string
+ destinationAddress?: string
+ amount?: number
+ blob?: Blob
+ mimeType?: string
+ file?: File
+ encryptedData?: string
+ name?: string
+ mode?: string
+ query?: string
+ excludeBlocked?: boolean
+ exactMatchNames?: boolean
+}
+
+declare function qortalRequest(options: QortalRequestOptions): Promise
+declare function qortalRequestWithTimeout(
+ options: QortalRequestOptions,
+ time: number
+): Promise
+
+declare global {
+ interface Window {
+ _qdnBase: any // Replace 'any' with the appropriate type if you know it
+ _qdnTheme: string
+ }
+}
+
+declare global {
+ interface Window {
+ showSaveFilePicker: (
+ options?: SaveFilePickerOptions
+ ) => Promise
+ }
+}
diff --git a/src/hooks/useFetchFiles.tsx b/src/hooks/useFetchFiles.tsx
new file mode 100644
index 0000000..d9d8dd9
--- /dev/null
+++ b/src/hooks/useFetchFiles.tsx
@@ -0,0 +1,421 @@
+import React from "react";
+import { useDispatch, useSelector } from "react-redux";
+import {
+ addFiles,
+ addToHashMap,
+ setCountNewFiles,
+ upsertFiles,
+ upsertFilesBeginning,
+ Video,
+ upsertFilteredFiles,
+} from "../state/features/fileSlice.ts";
+import {
+ setIsLoadingGlobal,
+ setUserAvatarHash,
+ setTotalFilesPublished,
+ setTotalNamesPublished,
+ setFilesPerNamePublished,
+} from "../state/features/globalSlice";
+import { RootState } from "../state/store";
+import { fetchAndEvaluateVideos } from "../utils/fetchVideos";
+import {
+ QSUPPORT_PLAYLIST_BASE,
+ QSUPPORT_FILE_BASE,
+} from "../constants/Identifiers.ts";
+import { RequestQueue } from "../utils/queue";
+import { queue } from "../wrappers/GlobalWrapper";
+import { getCategoriesFetchString } from "../components/common/CategoryList/CategoryList.tsx";
+
+export const useFetchFiles = () => {
+ const dispatch = useDispatch();
+ const hashMapFiles = useSelector(
+ (state: RootState) => state.file.hashMapFiles
+ );
+ const videos = useSelector((state: RootState) => state.file.files);
+ const userAvatarHash = useSelector(
+ (state: RootState) => state.global.userAvatarHash
+ );
+ const filteredVideos = useSelector(
+ (state: RootState) => state.file.filteredFiles
+ );
+
+ const totalFilesPublished = useSelector(
+ (state: RootState) => state.global.totalFilesPublished
+ );
+ const totalNamesPublished = useSelector(
+ (state: RootState) => state.global.totalNamesPublished
+ );
+ const filesPerNamePublished = useSelector(
+ (state: RootState) => state.global.filesPerNamePublished
+ );
+
+ const checkAndUpdateFile = React.useCallback(
+ (video: Video) => {
+ const existingVideo = hashMapFiles[video.id];
+ if (!existingVideo) {
+ return true;
+ } else if (
+ video?.updated &&
+ existingVideo?.updated &&
+ (!existingVideo?.updated || video?.updated) > existingVideo?.updated
+ ) {
+ return true;
+ } else {
+ return false;
+ }
+ },
+ [hashMapFiles]
+ );
+
+ const getAvatar = React.useCallback(async (author: string) => {
+ try {
+ let url = await qortalRequest({
+ action: "GET_QDN_RESOURCE_URL",
+ name: author,
+ service: "THUMBNAIL",
+ identifier: "qortal_avatar",
+ });
+
+ dispatch(
+ setUserAvatarHash({
+ name: author,
+ url,
+ })
+ );
+ } catch (error) {}
+ }, []);
+
+ const getFile = async (
+ user: string,
+ videoId: string,
+ content: any,
+ retries: number = 0
+ ) => {
+ try {
+ const res = await fetchAndEvaluateVideos({
+ user,
+ videoId,
+ content,
+ });
+
+ dispatch(addToHashMap(res));
+ } catch (error) {
+ retries = retries + 1;
+ if (retries < 2) {
+ // 3 is the maximum number of retries here, you can adjust it to your needs
+ queue.push(() => getFile(user, videoId, content, retries + 1));
+ } else {
+ console.error("Failed to get video after 3 attempts", error);
+ }
+ }
+ };
+
+ const getNewFiles = React.useCallback(async () => {
+ try {
+ dispatch(setIsLoadingGlobal(true));
+
+ const url = `/arbitrary/resources/search?mode=ALL&service=DOCUMENT&query=${QSUPPORT_FILE_BASE}&limit=20&includemetadata=false&reverse=true&excludeblocked=true&exactmatchnames=true`;
+ const response = await fetch(url, {
+ method: "GET",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+ const responseData = await response.json();
+
+ // const responseData = await qortalRequest({
+ // action: "SEARCH_QDN_RESOURCES",
+ // mode: "ALL",
+ // service: "DOCUMENT",
+ // query: "${QTUBE_VIDEO_BASE}",
+ // limit: 20,
+ // includeMetadata: true,
+ // reverse: true,
+ // excludeBlocked: true,
+ // exactMatchNames: true,
+ // name: names
+ // })
+ const latestVideo = videos[0];
+ if (!latestVideo) return;
+ const findVideo = responseData?.findIndex(
+ (item: any) => item?.identifier === latestVideo?.id
+ );
+ let fetchAll = responseData;
+ let willFetchAll = true;
+ if (findVideo !== -1) {
+ willFetchAll = false;
+ fetchAll = responseData.slice(0, findVideo);
+ }
+
+ const structureData = fetchAll.map((video: any): Video => {
+ return {
+ title: video?.metadata?.title,
+ category: video?.metadata?.category,
+ categoryName: video?.metadata?.categoryName,
+ tags: video?.metadata?.tags || [],
+ description: video?.metadata?.description,
+ created: video?.created,
+ updated: video?.updated,
+ user: video.name,
+ videoImage: "",
+ id: video.identifier,
+ };
+ });
+ if (!willFetchAll) {
+ dispatch(upsertFilesBeginning(structureData));
+ }
+ if (willFetchAll) {
+ dispatch(addFiles(structureData));
+ }
+ setTimeout(() => {
+ dispatch(setCountNewFiles(0));
+ }, 1000);
+ for (const content of structureData) {
+ if (content.user && content.id) {
+ const res = checkAndUpdateFile(content);
+ if (res) {
+ queue.push(() => getFile(content.user, content.id, content));
+ }
+ }
+ }
+ } catch (error) {
+ } finally {
+ dispatch(setIsLoadingGlobal(false));
+ }
+ }, [videos, hashMapFiles]);
+
+ const getFiles = React.useCallback(
+ async (
+ filters = {},
+ reset?: boolean,
+ resetFilers?: boolean,
+ limit?: number
+ ) => {
+ try {
+ const {
+ name = "",
+ categories = [],
+ keywords = "",
+ type = "",
+ }: any = resetFilers ? {} : filters;
+ let offset = videos.length;
+ if (reset) {
+ offset = 0;
+ }
+ const videoLimit = limit || 50;
+ let defaultUrl = `/arbitrary/resources/search?mode=ALL&includemetadata=false&reverse=true&excludeblocked=true&exactmatchnames=true&offset=${offset}&limit=${videoLimit}`;
+
+ if (name) {
+ defaultUrl += `&name=${name}`;
+ }
+
+ if (categories.length > 0) {
+ defaultUrl += "&description=" + getCategoriesFetchString(categories);
+ }
+
+ if (keywords) {
+ defaultUrl = defaultUrl + `&query=${keywords}`;
+ }
+ if (type === "playlists") {
+ defaultUrl = defaultUrl + `&service=PLAYLIST`;
+ defaultUrl = defaultUrl + `&identifier=${QSUPPORT_PLAYLIST_BASE}`;
+ } else {
+ defaultUrl = defaultUrl + `&service=DOCUMENT`;
+ defaultUrl = defaultUrl + `&identifier=${QSUPPORT_FILE_BASE}`;
+ }
+
+ // const url = `/arbitrary/resources/search?mode=ALL&service=DOCUMENT&query=${QTUBE_VIDEO_BASE}&limit=${videoLimit}&includemetadata=false&reverse=true&excludeblocked=true&exactmatchnames=true&offset=${offset}`
+ const url = defaultUrl;
+ const response = await fetch(url, {
+ method: "GET",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+ const responseData = await response.json();
+
+ // const responseData = await qortalRequest({
+ // action: "SEARCH_QDN_RESOURCES",
+ // mode: "ALL",
+ // service: "DOCUMENT",
+ // query: "${QTUBE_VIDEO_BASE}",
+ // limit: 20,
+ // includeMetadata: true,
+ // offset: offset,
+ // reverse: true,
+ // excludeBlocked: true,
+ // exactMatchNames: true,
+ // name: names
+ // })
+ const structureData = responseData.map((video: any): Video => {
+ return {
+ title: video?.metadata?.title,
+ service: video?.service,
+ category: video?.metadata?.category,
+ categoryName: video?.metadata?.categoryName,
+ tags: video?.metadata?.tags || [],
+ description: video?.metadata?.description,
+ created: video?.created,
+ updated: video?.updated,
+ user: video.name,
+ videoImage: "",
+ id: video.identifier,
+ };
+ });
+ if (reset) {
+ dispatch(addFiles(structureData));
+ } else {
+ dispatch(upsertFiles(structureData));
+ }
+ for (const content of structureData) {
+ if (content.user && content.id) {
+ const res = checkAndUpdateFile(content);
+ if (res) {
+ queue.push(() => getFile(content.user, content.id, content));
+ }
+ }
+ }
+ } catch (error) {
+ console.log({ error });
+ } finally {
+ }
+ },
+ [videos, hashMapFiles]
+ );
+
+ const getFilesFiltered = React.useCallback(
+ async (filterValue: string) => {
+ try {
+ const offset = filteredVideos.length;
+ const replaceSpacesWithUnderscore = filterValue.replace(/ /g, "_");
+
+ const url = `/arbitrary/resources/search?mode=ALL&service=DOCUMENT&query=${replaceSpacesWithUnderscore}&identifier=${QSUPPORT_FILE_BASE}&limit=10&includemetadata=false&reverse=true&excludeblocked=true&exactmatchnames=true&offset=${offset}`;
+ const response = await fetch(url, {
+ method: "GET",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+ const responseData = await response.json();
+
+ // const responseData = await qortalRequest({
+ // action: "SEARCH_QDN_RESOURCES",
+ // mode: "ALL",
+ // service: "DOCUMENT",
+ // query: replaceSpacesWithUnderscore,
+ // identifier: "${QTUBE_VIDEO_BASE}",
+ // limit: 20,
+ // includeMetadata: true,
+ // offset: offset,
+ // reverse: true,
+ // excludeBlocked: true,
+ // exactMatchNames: true,
+ // name: names
+ // })
+ const structureData = responseData.map((video: any): Video => {
+ return {
+ title: video?.metadata?.title,
+ category: video?.metadata?.category,
+ categoryName: video?.metadata?.categoryName,
+ tags: video?.metadata?.tags || [],
+ description: video?.metadata?.description,
+ created: video?.created,
+ updated: video?.updated,
+ user: video.name,
+ videoImage: "",
+ id: video.identifier,
+ };
+ });
+ dispatch(upsertFilteredFiles(structureData));
+
+ for (const content of structureData) {
+ if (content.user && content.id) {
+ const res = checkAndUpdateFile(content);
+ if (res) {
+ queue.push(() => getFile(content.user, content.id, content));
+ }
+ }
+ }
+ } catch (error) {
+ } finally {
+ }
+ },
+ [filteredVideos, hashMapFiles]
+ );
+
+ const checkNewFiles = React.useCallback(async () => {
+ try {
+ const url = `/arbitrary/resources/search?mode=ALL&service=DOCUMENT&query=${QSUPPORT_FILE_BASE}&limit=20&includemetadata=false&reverse=true&excludeblocked=true&exactmatchnames=true`;
+ const response = await fetch(url, {
+ method: "GET",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+ const responseData = await response.json();
+ // const responseData = await qortalRequest({
+ // action: "SEARCH_QDN_RESOURCES",
+ // mode: "ALL",
+ // service: "DOCUMENT",
+ // query: "${QTUBE_VIDEO_BASE}",
+ // limit: 20,
+ // includeMetadata: true,
+ // reverse: true,
+ // excludeBlocked: true,
+ // exactMatchNames: true,
+ // name: names
+ // })
+ const latestVideo = videos[0];
+ if (!latestVideo) return;
+ const findVideo = responseData?.findIndex(
+ (item: any) => item?.identifier === latestVideo?.id
+ );
+ if (findVideo === -1) {
+ dispatch(setCountNewFiles(responseData.length));
+ return;
+ }
+ const newArray = responseData.slice(0, findVideo);
+ dispatch(setCountNewFiles(newArray.length));
+ return;
+ } catch (error) {}
+ }, [videos]);
+
+ const getFilesCount = React.useCallback(async () => {
+ try {
+ let url = `/arbitrary/resources/search?mode=ALL&includemetadata=false&limit=0&service=DOCUMENT&identifier=${QSUPPORT_FILE_BASE}`;
+
+ const response = await fetch(url, {
+ method: "GET",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+ const responseData = await response.json();
+
+ const totalFilesPublished = responseData.length;
+ const uniqueNames = new Set(responseData.map(video => video.name));
+ const totalNamesPublished = uniqueNames.size;
+ const filesPerNamePublished = (
+ totalFilesPublished / totalNamesPublished
+ ).toFixed(2);
+
+ dispatch(setTotalFilesPublished(totalFilesPublished));
+ dispatch(setTotalNamesPublished(totalNamesPublished));
+ dispatch(setFilesPerNamePublished(filesPerNamePublished));
+ } catch (error) {
+ console.log({ error });
+ } finally {
+ }
+ }, []);
+
+ return {
+ getFiles,
+ checkAndUpdateFile,
+ getFile,
+ hashMapFiles,
+ getNewFiles,
+ checkNewFiles,
+ getFilesFiltered,
+ getFilesCount,
+ };
+};
diff --git a/src/hooks/useWindowSize.tsx b/src/hooks/useWindowSize.tsx
new file mode 100644
index 0000000..bf2b9cc
--- /dev/null
+++ b/src/hooks/useWindowSize.tsx
@@ -0,0 +1,25 @@
+import { useState, useEffect } from 'react';
+
+export function useWindowSize() {
+ const [windowSize, setWindowSize] = useState({
+ width: undefined,
+ });
+
+ useEffect(() => {
+ function handleResize() {
+ setWindowSize({
+ width: window.innerWidth,
+ });
+ }
+
+ window.addEventListener("resize", handleResize);
+
+ // Call handler right away so state gets updated with initial window size
+ handleResize();
+
+ // Remove event listener on cleanup
+ return () => window.removeEventListener("resize", handleResize);
+ }, []); // Empty array means that effect doesn't depend on any values from props or state, so it runs once when the component mounts, and never re-runs.
+
+ return windowSize;
+}
diff --git a/src/index.css b/src/index.css
new file mode 100644
index 0000000..2dd2e4a
--- /dev/null
+++ b/src/index.css
@@ -0,0 +1,229 @@
+@font-face {
+ font-family: 'Cambon Light';
+ src: url("./styles/fonts/Cambon-Light.ttf") format("truetype");
+}
+
+@font-face {
+ font-family: 'Merriweather Sans';
+ src: url("./styles/fonts/Merriweather Sans.ttf") format("truetype");
+}
+
+@font-face {
+ font-family: 'Karla';
+ src: url("./styles/fonts/Karla.ttf") format("truetype");
+}
+
+@font-face {
+ font-family: 'Proxima Nova';
+ src: url("./styles/fonts/ProximaNova.otf") format("opentype");
+}
+
+@font-face {
+ font-family: 'Raleway';
+ src: url("./styles/fonts/Raleway.ttf") format("truetype");
+}
+
+@font-face {
+ font-family: 'Catamaran';
+ src: url("./styles/fonts/Catamaran.ttf") format("truetype");
+}
+
+@font-face {
+ font-family: 'Oxygen';
+ src: url("./styles/fonts/Oxygen.ttf") format("truetype");
+}
+
+@font-face {
+ font-family: 'Cairo';
+ src: url("./styles/fonts/Cairo.ttf") format("truetype");
+}
+
+:root {
+ padding: 0px;
+ margin: 0px;
+ box-sizing: border-box;
+}
+
+
+.line-clamp {
+ height: 100px;
+ overflow: hidden;
+ display: -webkit-box;
+ -webkit-line-clamp: 5; /* number of lines to show */
+ -webkit-box-orient: vertical;
+ text-overflow: ellipsis;
+}
+
+.edit-btn:hover {
+ opacity: .75;
+ transition: .2s all;
+
+}
+
+.post-image {
+ max-width: 100%;
+ border-radius: 5px;
+ width: 100%;
+ height: 100%;
+}
+
+
+
+.test-grid {
+ display: grid;
+ grid-template-columns: repeat(4, 1fr);
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ min-height: 25px;
+}
+
+.test-grid-item {
+ border: 1px solid powderblue;
+}
+
+
+body::-webkit-scrollbar-track {
+ background-color: transparent;
+
+
+ }
+ body::-webkit-scrollbar-track:hover {
+ background-color: transparent;
+ }
+
+ body::-webkit-scrollbar {
+ width: 16px;
+ height: 10px;
+ background-color: white;
+ }
+
+ body::-webkit-scrollbar-thumb {
+ background-color: #838eee;
+ border-radius: 8px;
+ background-clip: content-box;
+ border: 4px solid transparent;
+
+ }
+
+ body::-webkit-scrollbar-thumb:hover {
+ background-color: #6270f0;
+ }
+
+
+ .MuiList-root::-webkit-scrollbar-track {
+ background-color: transparent;
+
+
+ }
+ .MuiList-root::-webkit-scrollbar-track:hover {
+ background-color: transparent;
+ }
+
+ .MuiList-root::-webkit-scrollbar {
+ width: 14px;
+ height: 10px;
+ background-color: white;
+ }
+
+ .MuiList-root::-webkit-scrollbar-thumb {
+ background-color: lightgray;
+ border-radius: 8px;
+ background-clip: content-box;
+ border: 4px solid transparent;
+
+ }
+
+ .MuiList-root::-webkit-scrollbar-thumb:hover {
+ background-color: lightslategray;
+ }
+
+ .my-masonry-grid {
+ display: -webkit-box; /* Not needed if autoprefixing */
+ display: -ms-flexbox; /* Not needed if autoprefixing */
+ display: flex;
+ margin-left: -20px; /* gutter size offset */
+ width: auto;
+ padding: 15px 20px;
+ }
+
+ .my-masonry-grid_column {
+ padding-left: 20px; /* gutter size */
+ background-clip: padding-box;
+ }
+
+ /* Style your items */
+ .my-masonry-grid_column > li { /* change div to reference your elements you put in */
+ margin-bottom: 30px;
+ }
+
+ .my-svg path {
+ fill: red
+ }
+
+ .qortal-link {
+ text-decoration: none; /* Removes the underline */
+ color: inherit; /* Inherits the color of the parent element */
+ }
+ .qortal-link:hover, a:focus {
+ text-decoration: underline; /* Adds underline on hover and focus for accessibility */
+ }
+
+ .download-icon {
+ transition: all 0.5s ease-in-out;
+ animation: downloadIconAnimation 2s infinite;
+ }
+
+ @keyframes downloadIconAnimation {
+ 0% { transform: scale(1); fill: #fff; }
+ 50% { transform: scale(1.2); fill: #3498db; }
+ 100% { transform: scale(1); fill: #fff; }
+ }
+
+ .closePlayer {
+ position: absolute;
+ top: 0px;
+ width: 100%;
+ transition: all 0.3s;
+ display: flex;
+ justify-content: flex-end;
+ z-index: 8000;
+ }
+
+
+/* When the screen is 600px or less, display .myClassUnder600 and hide .myClassOver600 */
+@media screen and (max-width: 600px) {
+ .myClassUnder600 {
+ display: none !important;
+ }
+
+
+}
+
+@media screen and (min-width: 601px) {
+ .myClassOver600 {
+ display: none !important;
+ }
+}
+
+.ql-editor {
+ min-height: 100px;
+ width: 100%
+}
+
+.ql-editor img {
+ cursor: default;
+}
+
+.ql-container {
+ font-size: 16px
+}
+
+.hover-click {
+ transition: opacity 0.2s;
+}
+.hover-click:hover {
+ opacity: 0.7;
+}
\ No newline at end of file
diff --git a/src/main.tsx b/src/main.tsx
new file mode 100644
index 0000000..b13bb52
--- /dev/null
+++ b/src/main.tsx
@@ -0,0 +1,17 @@
+import ReactDOM from 'react-dom/client'
+import App from './App'
+import './index.css'
+import { BrowserRouter } from 'react-router-dom'
+interface CustomWindow extends Window {
+ _qdnBase: string
+}
+
+const customWindow = window as unknown as CustomWindow
+
+const baseUrl = customWindow?._qdnBase || ''
+ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
+
+
+
+
+)
diff --git a/src/pages/Home/Channels.tsx b/src/pages/Home/Channels.tsx
new file mode 100644
index 0000000..90bffc6
--- /dev/null
+++ b/src/pages/Home/Channels.tsx
@@ -0,0 +1,79 @@
+import React, { useCallback, useEffect, useRef, useState } from "react";
+import { useNavigate } from "react-router-dom";
+import { useSelector } from "react-redux";
+import { RootState } from "../../state/store";
+import { Avatar, Box, Button, Typography, useTheme } from "@mui/material";
+import { useFetchFiles } from "../../hooks/useFetchFiles.tsx";
+import LazyLoad from "../../components/common/LazyLoad";
+import {
+ BottomParent,
+ NameContainer,
+ VideoCard,
+ VideoCardName,
+ VideoCardTitle,
+ FileContainer,
+ VideoUploadDate,
+} from "./FileList-styles.tsx";
+import ResponsiveImage from "../../components/ResponsiveImage";
+import { formatDate, formatTimestampSeconds } from "../../utils/time";
+import { ChannelCard, ChannelTitle } from "./Home-styles";
+
+interface VideoListProps {
+ mode?: string;
+}
+export const Channels = ({ mode }: VideoListProps) => {
+ const theme = useTheme();
+ const navigate = useNavigate();
+ const publishNames = useSelector(
+ (state: RootState) => state.global.publishNames
+ );
+ const userAvatarHash = useSelector(
+ (state: RootState) => state.global.userAvatarHash
+ );
+
+ return (
+
+
+ {publishNames &&
+ publishNames?.slice(0, 10).map(name => {
+ let avatarUrl = "";
+ if (userAvatarHash[name]) {
+ avatarUrl = userAvatarHash[name];
+ }
+ return (
+
+ {
+ navigate(`/channel/${name}`);
+ }}
+ >
+ {name}
+
+
+
+ );
+ })}
+
+
+ );
+};
diff --git a/src/pages/Home/FileList-styles.tsx b/src/pages/Home/FileList-styles.tsx
new file mode 100644
index 0000000..f026dc7
--- /dev/null
+++ b/src/pages/Home/FileList-styles.tsx
@@ -0,0 +1,290 @@
+import { styled } from "@mui/system";
+import {
+ Box,
+ Grid,
+ Typography,
+ Checkbox,
+ TextField,
+ InputLabel,
+ Autocomplete,
+} from "@mui/material";
+
+export const FileContainer = styled(Box)(({ theme }) => ({
+ position: "relative",
+ display: "flex",
+ padding: "15px",
+ flexDirection: "row",
+ gap: "20px",
+ flexWrap: "wrap",
+ justifyContent: "flex-start",
+ width: "100%",
+}));
+
+export const StoresRow = styled(Grid)(({ theme }) => ({
+ display: "flex",
+ flexDirection: "column",
+ alignItems: "center",
+ justifyContent: "flex-start",
+ gap: "15px",
+ width: "auto",
+ position: "relative",
+ "@media (max-width: 450px)": {
+ width: "100%",
+ },
+}));
+
+export const VideoCard = styled(Grid)(({ theme }) => ({
+ position: "relative",
+ display: "flex",
+ flexDirection: "column",
+ height: "320px",
+ width: "300px",
+ backgroundColor: theme.palette.background.paper,
+ borderRadius: "8px",
+ padding: "10px 15px",
+ gap: "20px",
+ cursor: "pointer",
+ border:
+ theme.palette.mode === "dark"
+ ? "none"
+ : `1px solid ${theme.palette.primary.light}`,
+ boxShadow:
+ theme.palette.mode === "dark"
+ ? "0px 4px 5px 0px hsla(0,0%,0%,0.14), 0px 1px 10px 0px hsla(0,0%,0%,0.12), 0px 2px 4px -1px hsla(0,0%,0%,0.2)"
+ : "rgba(99, 99, 99, 0.2) 0px 2px 8px 0px",
+ transition: "all 0.3s ease-in-out",
+ "&:hover": {
+ boxShadow:
+ theme.palette.mode === "dark"
+ ? "0px 8px 10px 1px hsla(0,0%,0%,0.14), 0px 3px 14px 2px hsla(0,0%,0%,0.12), 0px 5px 5px -3px hsla(0,0%,0%,0.2)"
+ : "rgba(0, 0, 0, 0.1) 0px 4px 6px -1px, rgba(0, 0, 0, 0.06) 0px 2px 4px -1px;",
+ },
+}));
+
+export const StoreCardInfo = styled(Grid)(({ theme }) => ({
+ display: "flex",
+ flexDirection: "column",
+ gap: "10px",
+ padding: "5px",
+ marginTop: "15px",
+}));
+
+export const VideoImageContainer = styled(Grid)(({ theme }) => ({}));
+
+export const VideoCardImage = styled("img")(({ theme }) => ({
+ maxWidth: "300px",
+ minWidth: "150px",
+ borderRadius: "5px",
+ height: "150px",
+ objectFit: "fill",
+ width: "266px",
+}));
+
+const DoubleLine = styled(Typography)`
+ display: -webkit-box;
+ -webkit-box-orient: vertical;
+ -webkit-line-clamp: 2;
+ overflow: hidden;
+`;
+
+export const VideoCardTitle = styled(DoubleLine)(({ theme }) => ({
+ fontFamily: "Cairo",
+ fontSize: "16px",
+ letterSpacing: "0.4px",
+ color: theme.palette.text.primary,
+ userSelect: "none",
+}));
+export const VideoCardName = styled(Typography)(({ theme }) => ({
+ fontFamily: "Cairo",
+ fontSize: "14px",
+ letterSpacing: "0.4px",
+ color: theme.palette.text.primary,
+ userSelect: "none",
+ overflow: "hidden",
+ whiteSpace: "nowrap",
+ textOverflow: "ellipsis",
+ width: "100%",
+}));
+export const VideoUploadDate = styled(Typography)(({ theme }) => ({
+ fontFamily: "Cairo",
+ fontSize: "12px",
+ letterSpacing: "0.4px",
+ color: theme.palette.text.primary,
+ userSelect: "none",
+}));
+export const BottomParent = styled(Box)(({ theme }) => ({
+ display: "flex",
+ alignItems: "flex-start",
+ flexDirection: "column",
+}));
+export const VideoCardDescription = styled(Typography)(({ theme }) => ({
+ fontFamily: "Karla",
+ fontSize: "20px",
+ letterSpacing: "0px",
+ color: theme.palette.text.primary,
+ userSelect: "none",
+}));
+
+export const StoreCardOwner = styled(Typography)(({ theme }) => ({
+ fontFamily: "Livvic",
+ color: theme.palette.text.primary,
+ fontSize: "17px",
+ position: "absolute",
+ bottom: "5px",
+ right: "10px",
+ userSelect: "none",
+}));
+
+export const StoreCardYouOwn = styled(Box)(({ theme }) => ({
+ position: "absolute",
+ top: "5px",
+ right: "10px",
+ display: "flex",
+ alignItems: "center",
+ gap: "5px",
+ fontFamily: "Livvic",
+ fontSize: "15px",
+ color: theme.palette.text.primary,
+}));
+
+export const MyStoresRow = styled(Grid)(({ theme }) => ({
+ display: "flex",
+ flexDirection: "row",
+ justifyContent: "flex-end",
+ padding: "5px",
+ width: "100%",
+}));
+
+export const NameContainer = styled(Box)(({ theme }) => ({
+ display: "flex",
+ flexDirection: "row",
+ justifyContent: "flex-start",
+ alignItems: "center",
+ gap: "10px",
+ marginBottom: "10px",
+}));
+
+export const MyStoresCard = styled(Box)(({ theme }) => ({
+ display: "flex",
+ flexDirection: "row",
+ alignItems: "center",
+ width: "auto",
+ borderRadius: "4px",
+ backgroundColor: theme.palette.background.paper,
+ padding: "5px 10px",
+ fontFamily: "Raleway",
+ fontSize: "18px",
+ color: theme.palette.text.primary,
+}));
+
+export const MyStoresCheckbox = styled(Checkbox)(({ theme }) => ({
+ color: "#c0d4ff",
+ "&.Mui-checked": {
+ color: "#6596ff",
+ },
+}));
+
+export const FiltersCol = styled(Grid)(({ theme }) => ({
+ display: "flex",
+ flexDirection: "column",
+ height: "100%",
+ padding: "20px 15px",
+ backgroundColor: theme.palette.background.default,
+ borderTop: `1px solid ${theme.palette.background.paper}`,
+ borderRight: `1px solid ${theme.palette.background.paper}`,
+}));
+
+export const FiltersContainer = styled(Box)(({ theme }) => ({
+ display: "flex",
+ flexDirection: "column",
+ justifyContent: "space-between",
+}));
+
+export const FiltersRow = styled(Box)(({ theme }) => ({
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "space-between",
+ width: "100%",
+ padding: "0 15px",
+ fontSize: "16px",
+ userSelect: "none",
+}));
+
+export const FiltersTitle = styled(Typography)(({ theme }) => ({
+ display: "flex",
+ alignItems: "center",
+ gap: "5px",
+ margin: "20px 0",
+ fontFamily: "Raleway",
+ fontSize: "17px",
+ color: theme.palette.text.primary,
+ userSelect: "none",
+}));
+
+export const FiltersCheckbox = styled(Checkbox)(({ theme }) => ({
+ color: "#c0d4ff",
+ "&.Mui-checked": {
+ color: "#6596ff",
+ },
+}));
+
+export const FilterSelect = styled(Autocomplete)(({ theme }) => ({
+ "& #categories-select": {
+ padding: "7px",
+ },
+ "& .MuiSelect-placeholder": {
+ fontFamily: "Raleway",
+ fontSize: "17px",
+ color: theme.palette.text.primary,
+ userSelect: "none",
+ },
+ "& MuiFormLabel-root": {
+ fontFamily: "Raleway",
+ fontSize: "17px",
+ color: theme.palette.text.primary,
+ userSelect: "none",
+ },
+}));
+
+export const FilterSelectMenuItems = styled(TextField)(({ theme }) => ({
+ fontFamily: "Raleway",
+ fontSize: "17px",
+ color: theme.palette.text.primary,
+ userSelect: "none",
+}));
+
+export const FiltersSubContainer = styled(Box)(({ theme }) => ({
+ display: "flex",
+ alignItems: "center",
+ flexDirection: "column",
+ gap: "5px",
+}));
+
+export const FilterDropdownLabel = styled(InputLabel)(({ theme }) => ({
+ fontFamily: "Raleway",
+ fontSize: "16px",
+ color: theme.palette.text.primary,
+}));
+
+export const IconsBox = styled(Box)({
+ display: "flex",
+ gap: "3px",
+ position: "absolute",
+ top: "-20px",
+ right: "-5px",
+ transition: "all 0.3s ease-in-out",
+});
+
+export const BlockIconContainer = styled(Box)({
+ display: "flex",
+ boxShadow: "rgba(99, 99, 99, 0.2) 0px 2px 8px 0px;",
+ backgroundColor: "#fbfbfb",
+ color: "#c25252",
+ padding: "2px",
+ borderRadius: "3px",
+ transition: "all 0.3s ease-in-out",
+ "&:hover": {
+ cursor: "pointer",
+ transform: "scale(1.1)",
+ },
+});
diff --git a/src/pages/Home/FileList.tsx b/src/pages/Home/FileList.tsx
new file mode 100644
index 0000000..85d7929
--- /dev/null
+++ b/src/pages/Home/FileList.tsx
@@ -0,0 +1,207 @@
+import { Avatar, Box, Skeleton, Tooltip } from "@mui/material";
+import {
+ BlockIconContainer,
+ BottomParent,
+ FileContainer,
+ IconsBox,
+ NameContainer,
+ VideoCard,
+ VideoCardName,
+ VideoCardTitle,
+ VideoUploadDate,
+} from "./FileList-styles.tsx";
+import EditIcon from "@mui/icons-material/Edit";
+import {
+ blockUser,
+ setEditFile,
+ Video,
+} from "../../state/features/fileSlice.ts";
+import BlockIcon from "@mui/icons-material/Block";
+import AttachFileIcon from "@mui/icons-material/AttachFile";
+import { formatBytes } from "../IssueContent/IssueContent.tsx";
+import { formatDate } from "../../utils/time.ts";
+import React, { useState } from "react";
+import { useDispatch, useSelector } from "react-redux";
+import { RootState } from "../../state/store.ts";
+import { useNavigate } from "react-router-dom";
+import { getIconsFromObject } from "../../constants/Categories/CategoryFunctions.ts";
+
+interface FileListProps {
+ files: Video[];
+}
+export const FileList = ({ files }: FileListProps) => {
+ const hashMapFiles = useSelector(
+ (state: RootState) => state.file.hashMapFiles
+ );
+
+ const [showIcons, setShowIcons] = useState(null);
+ const username = useSelector((state: RootState) => state.auth?.user?.name);
+ const dispatch = useDispatch();
+ const navigate = useNavigate();
+
+ const blockUserFunc = async (user: string) => {
+ if (user === "Q-Share") return;
+
+ try {
+ const response = await qortalRequest({
+ action: "ADD_LIST_ITEMS",
+ list_name: "blockedNames",
+ items: [user],
+ });
+
+ if (response === true) {
+ dispatch(blockUser(user));
+ }
+ } catch (error) {}
+ };
+
+ return (
+
+ {files.map((file: any, index: number) => {
+ const existingFile = hashMapFiles[file?.id];
+ let hasHash = false;
+ let fileObj = file;
+ if (existingFile) {
+ fileObj = existingFile;
+ hasHash = true;
+ }
+ const icon = getIconsFromObject(fileObj);
+ return (
+ setShowIcons(fileObj.id)}
+ onMouseLeave={() => setShowIcons(null)}
+ >
+ {hasHash ? (
+ <>
+
+ {fileObj?.user === username && (
+
+
+ {
+ dispatch(setEditFile(fileObj));
+ }}
+ />
+
+
+ )}
+
+
+
+ {
+ blockUserFunc(fileObj?.user);
+ }}
+ />
+
+
+
+ {
+ navigate(`/share/${fileObj?.user}/${fileObj?.id}`);
+ }}
+ sx={{
+ height: "100%",
+ width: "100%",
+ display: "flex",
+ gap: "25px",
+ flexDirection: "row",
+ justifyContent: "space-between",
+ }}
+ >
+
+ {icon ? (
+
+ ) : (
+
+ )}
+
+
+ {formatBytes(
+ fileObj?.files.reduce(
+ (acc, cur) => acc + (cur?.size || 0),
+ 0
+ )
+ )}
+
+ {fileObj.title}
+
+
+ {
+ e.stopPropagation();
+ navigate(`/channel/${fileObj?.user}`);
+ }}
+ >
+
+
+ {fileObj?.user}
+
+
+
+ {fileObj?.created && (
+
+ {formatDate(fileObj.created)}
+
+ )}
+
+
+ >
+ ) : (
+
+ )}
+
+ );
+ })}
+
+ );
+};
diff --git a/src/pages/Home/FileListComponentLevel.tsx b/src/pages/Home/FileListComponentLevel.tsx
new file mode 100644
index 0000000..43a5b54
--- /dev/null
+++ b/src/pages/Home/FileListComponentLevel.tsx
@@ -0,0 +1,246 @@
+import React, { useEffect, useRef, useState } from "react";
+import { useNavigate, useParams } from "react-router-dom";
+import { useSelector } from "react-redux";
+import { RootState } from "../../state/store";
+import AttachFileIcon from "@mui/icons-material/AttachFile";
+
+import { Avatar, Box, Skeleton, useTheme } from "@mui/material";
+import { useFetchFiles } from "../../hooks/useFetchFiles.tsx";
+import LazyLoad from "../../components/common/LazyLoad";
+import {
+ BottomParent,
+ FileContainer,
+ NameContainer,
+ VideoCard,
+ VideoCardName,
+ VideoCardTitle,
+ VideoUploadDate,
+} from "./FileList-styles.tsx";
+import { formatDate } from "../../utils/time";
+import { Video } from "../../state/features/fileSlice.ts";
+import { queue } from "../../wrappers/GlobalWrapper";
+import { QSUPPORT_FILE_BASE } from "../../constants/Identifiers.ts";
+import { formatBytes } from "../IssueContent/IssueContent.tsx";
+import { getIconsFromObject } from "../../constants/Categories/CategoryFunctions.ts";
+
+interface VideoListProps {
+ mode?: string;
+}
+export const FileListComponentLevel = ({ mode }: VideoListProps) => {
+ const { name: paramName } = useParams();
+ const theme = useTheme();
+ const [isLoading, setIsLoading] = useState(true);
+
+ const firstFetch = useRef(false);
+ const afterFetch = useRef(false);
+ const hashMapVideos = useSelector(
+ (state: RootState) => state.file.hashMapFiles
+ );
+
+ const [videos, setVideos] = React.useState