From 7391940b13b00a4157d5d8e771a954ea02068b15 Mon Sep 17 00:00:00 2001 From: Justin Ferrari <‘justinwesleyferrari@gmail.com’> Date: Fri, 8 Dec 2023 13:56:56 -0500 Subject: [PATCH] Initial q-blog commit in its own repo --- .gitignore | 24 + .prettierrc.json | 10 + index.html | 14 + package-lock.json | 6695 +++++++++++++++++ package.json | 54 + public/favicon.ico | Bin 0 -> 15406 bytes src/App.tsx | 67 + src/assets/img/arrr.png | Bin 0 -> 1429 bytes src/assets/img/btc.png | Bin 0 -> 1982 bytes src/assets/img/dgb.png | Bin 0 -> 4917 bytes src/assets/img/doge.png | Bin 0 -> 1798 bytes src/assets/img/ltc.png | Bin 0 -> 1480 bytes src/assets/img/qBlogLogo.png | Bin 0 -> 2506 bytes src/assets/img/qort.png | Bin 0 -> 1907 bytes src/assets/img/rvn.png | Bin 0 -> 2405 bytes src/assets/react.svg | 1 + src/assets/svgs/AccountCircleSVG.tsx | 25 + src/assets/svgs/AlignCenterSVG.tsx | 21 + src/assets/svgs/AlignLeftSVG.tsx | 17 + src/assets/svgs/AlignRightSVG.tsx | 17 + src/assets/svgs/BoldSVG.tsx | 17 + src/assets/svgs/CodeBlockSVG.tsx | 17 + src/assets/svgs/H2SVG.tsx | 17 + src/assets/svgs/H3SVG.tsx | 17 + src/assets/svgs/ItalicSVG.tsx | 17 + src/assets/svgs/LinkSVG.tsx | 17 + src/assets/svgs/NewWindowSVG.tsx | 25 + src/assets/svgs/UnderlineSVG.tsx | 17 + src/assets/svgs/accountCircle.svg | 1 + src/assets/svgs/interfaces.ts | 5 + src/components/AudioElement.tsx | 230 + src/components/DynamicHeightItem.tsx | 96 + src/components/DynamicHeightItemMinimal.tsx | 39 + src/components/FileElement.tsx | 445 ++ src/components/common/AudioPanel.tsx | 253 + src/components/common/AudioPlayer.tsx | 192 + src/components/common/AudioPublishModal.tsx | 366 + .../BlockedNamesModal-styles.ts | 28 + .../BlockedNamesModal/BlockedNamesModal.tsx | 100 + src/components/common/Comments/Comment.tsx | 336 + .../common/Comments/CommentEditor.tsx | 258 + .../common/Comments/CommentSection.tsx | 386 + .../ContextMenu/ContextMenuResource.tsx | 82 + src/components/common/CustomIcon.tsx | 16 + src/components/common/DownloadTaskManager.tsx | 289 + .../common/DraggableResizableGrid.tsx | 55 + src/components/common/ErrorBoundary.tsx | 36 + src/components/common/FilePanel.tsx | 257 + src/components/common/GenericPublishModal.tsx | 317 + src/components/common/ImageUploader.tsx | 89 + src/components/common/LazyLoad.tsx | 47 + .../common/Notification/Notification.tsx | 86 + src/components/common/PageLoader.tsx | 43 + src/components/common/Portal.tsx | 25 + src/components/common/PostPublishModal.tsx | 281 + src/components/common/PublishAudio.tsx | 111 + src/components/common/PublishGeneric.tsx | 120 + src/components/common/PublishVideo.tsx | 112 + src/components/common/ResponsiveImage.tsx | 124 + src/components/common/Tipping/Tipping.tsx | 289 + .../common/UserNavbar/UserNavbar-styles.ts | 55 + .../common/UserNavbar/UserNavbar.tsx | 135 + src/components/common/VideoContent.tsx | 51 + src/components/common/VideoPanel.tsx | 284 + src/components/common/VideoPlayer.tsx | 832 ++ src/components/common/VideoPublishModal.tsx | 287 + src/components/editor/BlogEditor.css | 78 + src/components/editor/BlogEditor.tsx | 574 ++ src/components/editor/ReadOnlySlate.tsx | 25 + src/components/editor/customTypes.ts | 47 + src/components/layout/Navbar/Navbar-styles.ts | 112 + src/components/layout/Navbar/Navbar.tsx | 490 ++ src/components/modals/ConsentModal.tsx | 70 + src/components/modals/EditBlogModal.tsx | 247 + src/components/modals/PublishBlogModal.tsx | 281 + src/components/modals/ReusableModal.tsx | 47 + src/constants/mail.ts | 3 + src/global.d.ts | 61 + src/hooks/useFetchMail.tsx | 469 ++ src/hooks/useFetchPosts.tsx | 362 + src/index.css | 162 + src/index.d.ts | 9 + src/interfaces/interfaces.ts | 8 + src/main.tsx | 19 + .../BlogIndividualPost/BlogIndividualPost.tsx | 951 +++ .../BlogIndividualProfile.tsx | 301 + src/pages/BlogList/BlogList.tsx | 225 + src/pages/BlogList/PostPreview-styles.ts | 134 + src/pages/BlogList/PostPreview.tsx | 320 + .../CreateEditProfile/CreatEditProfile.tsx | 7 + src/pages/CreatePost/CreatePost-styles.ts | 14 + src/pages/CreatePost/CreatePost.tsx | 194 + src/pages/CreatePost/CreatePostBuilder.tsx | 1409 ++++ src/pages/CreatePost/CreatePostMinimal.tsx | 1390 ++++ .../components/Navbar/NavbarBuilder.tsx | 261 + .../components/Toolbar/EditorToolbar.tsx | 157 + src/pages/EditPost/EditPost.tsx | 562 ++ src/pages/Home/Home.tsx | 7 + src/pages/Mail/AliasMail.tsx | 279 + src/pages/Mail/Mail.tsx | 342 + src/pages/Mail/MailTable.tsx | 190 + src/pages/Mail/MailThread.tsx | 315 + src/pages/Mail/NewMessage.tsx | 425 ++ src/pages/Mail/ShowMessage.tsx | 256 + src/state/features/authSlice.ts | 27 + src/state/features/blogSlice.ts | 331 + src/state/features/globalSlice.ts | 137 + src/state/features/mailSlice.ts | 345 + src/state/features/notificationsSlice.ts | 73 + src/state/store.ts | 31 + src/styles/fonts/Cairo.ttf | Bin 0 -> 353464 bytes src/styles/fonts/Cambon-Light.ttf | Bin 0 -> 123472 bytes src/styles/fonts/Catamaran.ttf | Bin 0 -> 182788 bytes src/styles/fonts/Oxygen.ttf | Bin 0 -> 46440 bytes src/styles/fonts/Raleway.ttf | Bin 0 -> 309720 bytes src/styles/theme.ts | 179 + src/utils/blogIdformats.ts | 29 + src/utils/checkAndUpdatePost.tsx | 23 + src/utils/checkStructure.ts | 49 + src/utils/extractTextFromSlate.ts | 14 + src/utils/fetchMail.ts | 73 + src/utils/fetchPosts.ts | 53 + src/utils/time.ts | 24 + src/utils/toBase64.ts | 174 + src/vite-env.d.ts | 1 + src/webworkers/decodeBase64.js | 62 + src/webworkers/getBlogWorker.js | 74 + src/wrappers/DownloadWrapper.tsx | 240 + src/wrappers/GlobalWrapper.tsx | 667 ++ tsconfig.json | 19 + vite.config.ts | 8 + 131 files changed, 27283 insertions(+) create mode 100644 .gitignore create mode 100644 .prettierrc.json create mode 100644 index.html create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 public/favicon.ico create mode 100644 src/App.tsx create mode 100644 src/assets/img/arrr.png create mode 100644 src/assets/img/btc.png create mode 100644 src/assets/img/dgb.png create mode 100644 src/assets/img/doge.png create mode 100644 src/assets/img/ltc.png create mode 100644 src/assets/img/qBlogLogo.png create mode 100644 src/assets/img/qort.png create mode 100644 src/assets/img/rvn.png create mode 100644 src/assets/react.svg create mode 100644 src/assets/svgs/AccountCircleSVG.tsx create mode 100644 src/assets/svgs/AlignCenterSVG.tsx create mode 100644 src/assets/svgs/AlignLeftSVG.tsx create mode 100644 src/assets/svgs/AlignRightSVG.tsx create mode 100644 src/assets/svgs/BoldSVG.tsx create mode 100644 src/assets/svgs/CodeBlockSVG.tsx create mode 100644 src/assets/svgs/H2SVG.tsx create mode 100644 src/assets/svgs/H3SVG.tsx create mode 100644 src/assets/svgs/ItalicSVG.tsx create mode 100644 src/assets/svgs/LinkSVG.tsx create mode 100644 src/assets/svgs/NewWindowSVG.tsx create mode 100644 src/assets/svgs/UnderlineSVG.tsx create mode 100644 src/assets/svgs/accountCircle.svg create mode 100644 src/assets/svgs/interfaces.ts create mode 100644 src/components/AudioElement.tsx create mode 100644 src/components/DynamicHeightItem.tsx create mode 100644 src/components/DynamicHeightItemMinimal.tsx create mode 100644 src/components/FileElement.tsx create mode 100644 src/components/common/AudioPanel.tsx create mode 100644 src/components/common/AudioPlayer.tsx create mode 100644 src/components/common/AudioPublishModal.tsx create mode 100644 src/components/common/BlockedNamesModal/BlockedNamesModal-styles.ts create mode 100644 src/components/common/BlockedNamesModal/BlockedNamesModal.tsx create mode 100644 src/components/common/Comments/Comment.tsx create mode 100644 src/components/common/Comments/CommentEditor.tsx create mode 100644 src/components/common/Comments/CommentSection.tsx create mode 100644 src/components/common/ContextMenu/ContextMenuResource.tsx create mode 100644 src/components/common/CustomIcon.tsx create mode 100644 src/components/common/DownloadTaskManager.tsx create mode 100644 src/components/common/DraggableResizableGrid.tsx create mode 100644 src/components/common/ErrorBoundary.tsx create mode 100644 src/components/common/FilePanel.tsx create mode 100644 src/components/common/GenericPublishModal.tsx create mode 100644 src/components/common/ImageUploader.tsx create mode 100644 src/components/common/LazyLoad.tsx create mode 100644 src/components/common/Notification/Notification.tsx create mode 100644 src/components/common/PageLoader.tsx create mode 100644 src/components/common/Portal.tsx create mode 100644 src/components/common/PostPublishModal.tsx create mode 100644 src/components/common/PublishAudio.tsx create mode 100644 src/components/common/PublishGeneric.tsx create mode 100644 src/components/common/PublishVideo.tsx create mode 100644 src/components/common/ResponsiveImage.tsx create mode 100644 src/components/common/Tipping/Tipping.tsx create mode 100644 src/components/common/UserNavbar/UserNavbar-styles.ts create mode 100644 src/components/common/UserNavbar/UserNavbar.tsx create mode 100644 src/components/common/VideoContent.tsx create mode 100644 src/components/common/VideoPanel.tsx create mode 100644 src/components/common/VideoPlayer.tsx create mode 100644 src/components/common/VideoPublishModal.tsx create mode 100644 src/components/editor/BlogEditor.css create mode 100644 src/components/editor/BlogEditor.tsx create mode 100644 src/components/editor/ReadOnlySlate.tsx create mode 100644 src/components/editor/customTypes.ts create mode 100644 src/components/layout/Navbar/Navbar-styles.ts create mode 100644 src/components/layout/Navbar/Navbar.tsx create mode 100644 src/components/modals/ConsentModal.tsx create mode 100644 src/components/modals/EditBlogModal.tsx create mode 100644 src/components/modals/PublishBlogModal.tsx create mode 100644 src/components/modals/ReusableModal.tsx create mode 100644 src/constants/mail.ts create mode 100644 src/global.d.ts create mode 100644 src/hooks/useFetchMail.tsx create mode 100644 src/hooks/useFetchPosts.tsx create mode 100644 src/index.css create mode 100644 src/index.d.ts create mode 100644 src/interfaces/interfaces.ts create mode 100644 src/main.tsx create mode 100644 src/pages/BlogIndividualPost/BlogIndividualPost.tsx create mode 100644 src/pages/BlogIndividualProfile/BlogIndividualProfile.tsx create mode 100644 src/pages/BlogList/BlogList.tsx create mode 100644 src/pages/BlogList/PostPreview-styles.ts create mode 100644 src/pages/BlogList/PostPreview.tsx create mode 100644 src/pages/CreateEditProfile/CreatEditProfile.tsx create mode 100644 src/pages/CreatePost/CreatePost-styles.ts create mode 100644 src/pages/CreatePost/CreatePost.tsx create mode 100644 src/pages/CreatePost/CreatePostBuilder.tsx create mode 100644 src/pages/CreatePost/CreatePostMinimal.tsx create mode 100644 src/pages/CreatePost/components/Navbar/NavbarBuilder.tsx create mode 100644 src/pages/CreatePost/components/Toolbar/EditorToolbar.tsx create mode 100644 src/pages/EditPost/EditPost.tsx create mode 100644 src/pages/Home/Home.tsx create mode 100644 src/pages/Mail/AliasMail.tsx create mode 100644 src/pages/Mail/Mail.tsx create mode 100644 src/pages/Mail/MailTable.tsx create mode 100644 src/pages/Mail/MailThread.tsx create mode 100644 src/pages/Mail/NewMessage.tsx create mode 100644 src/pages/Mail/ShowMessage.tsx create mode 100644 src/state/features/authSlice.ts create mode 100644 src/state/features/blogSlice.ts create mode 100644 src/state/features/globalSlice.ts create mode 100644 src/state/features/mailSlice.ts create mode 100644 src/state/features/notificationsSlice.ts create mode 100644 src/state/store.ts create mode 100644 src/styles/fonts/Cairo.ttf create mode 100644 src/styles/fonts/Cambon-Light.ttf create mode 100644 src/styles/fonts/Catamaran.ttf create mode 100644 src/styles/fonts/Oxygen.ttf create mode 100644 src/styles/fonts/Raleway.ttf create mode 100644 src/styles/theme.ts create mode 100644 src/utils/blogIdformats.ts create mode 100644 src/utils/checkAndUpdatePost.tsx create mode 100644 src/utils/checkStructure.ts create mode 100644 src/utils/extractTextFromSlate.ts create mode 100644 src/utils/fetchMail.ts create mode 100644 src/utils/fetchPosts.ts create mode 100644 src/utils/time.ts create mode 100644 src/utils/toBase64.ts create mode 100644 src/vite-env.d.ts create mode 100644 src/webworkers/decodeBase64.js create mode 100644 src/webworkers/getBlogWorker.js create mode 100644 src/wrappers/DownloadWrapper.tsx create mode 100644 src/wrappers/GlobalWrapper.tsx create mode 100644 tsconfig.json create mode 100644 vite.config.ts diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bfe8e32 --- /dev/null +++ b/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* +*.zip +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..0a4d4fc --- /dev/null +++ b/.prettierrc.json @@ -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..55edf06 --- /dev/null +++ b/index.html @@ -0,0 +1,14 @@ + + + + + + + + Q-Blog + + +
+ + + diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..15ce57f --- /dev/null +++ b/package-lock.json @@ -0,0 +1,6695 @@ +{ + "name": "q-blog", + "version": "0.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "q-blog", + "version": "0.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", + "@types/react-grid-layout": "^1.3.2", + "axios": "^1.3.4", + "compressorjs": "^1.2.1", + "localforage": "^1.10.0", + "moment": "^2.29.4", + "philliplm-react-modern-audio-player": "^1.4.6", + "react": "^18.2.0", + "react-copy-to-clipboard": "^5.1.0", + "react-dnd": "^16.0.1", + "react-dnd-html5-backend": "^16.0.1", + "react-dom": "^18.2.0", + "react-dropzone": "^14.2.3", + "react-grid-layout": "^1.3.4", + "react-intersection-observer": "^9.4.3", + "react-masonry-css": "^1.0.16", + "react-redux": "^8.0.5", + "react-resize-detector": "^8.0.4", + "react-router-dom": "^6.9.0", + "react-toastify": "^9.1.2", + "react-virtuoso": "^4.3.3", + "short-unique-id": "^4.4.4", + "slate": "^0.91.4", + "slate-history": "^0.86.0", + "slate-react": "^0.91.11", + "ts-key-enum": "^2.0.12" + }, + "devDependencies": { + "@mui/types": "^7.2.3", + "@types/react": "^18.0.28", + "@types/react-copy-to-clipboard": "^5.0.4", + "@types/react-dom": "^18.0.11", + "@vitejs/plugin-react-swc": "^3.2.0", + "prettier": "^2.8.6", + "typescript": "^4.9.3", + "vite": "^4.2.0", + "worker-loader": "^3.0.8" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "dependencies": { + "@babel/highlight": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/generator": { + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.3.tgz", + "integrity": "sha512-QS3iR1GYC/YGUnW7IdggFeN5c1poPUurnGttOV/bZgPGV+izC/D8HnD6DLwod0fsatNyVn1G3EVWMYIF0nHbeA==", + "dependencies": { + "@babel/types": "^7.21.3", + "@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-annotate-as-pure": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", + "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", + "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz", + "integrity": "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==", + "dependencies": { + "@babel/template": "^7.20.7", + "@babel/types": "^7.21.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", + "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", + "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", + "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.19.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", + "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.19.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", + "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.3.tgz", + "integrity": "sha512-lobG0d7aOfQRXh8AyklEAgZGvA4FShxo6xQbUrrT/cNBPUdIDojlokwJsQyCC/eKia7ifqM0yP+2DRZ4WKw2RQ==", + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz", + "integrity": "sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==", + "dependencies": { + "regenerator-runtime": "^0.13.11" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", + "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", + "dependencies": { + "@babel/code-frame": "^7.18.6", + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.3.tgz", + "integrity": "sha512-XLyopNeaTancVitYZe2MlUEvgKb6YVVPXzofHgqHijCImG33b/uTurMS488ht/Hbsb2XK3U2BnSTxKVNGV3nGQ==", + "dependencies": { + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.21.3", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.21.0", + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/parser": "^7.21.3", + "@babel/types": "^7.21.3", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.3.tgz", + "integrity": "sha512-sBGdETxC+/M4o/zKC0sl6sjWv62WFR/uzxrJ6uYyMLZOUlPnwzw0tKgVHOXxaAd5l2g8pEDM5RZ495GPQI77kg==", + "dependencies": { + "@babel/helper-string-parser": "^7.19.4", + "@babel/helper-validator-identifier": "^7.19.1", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@emotion/babel-plugin": { + "version": "11.10.6", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.10.6.tgz", + "integrity": "sha512-p2dAqtVrkhSa7xz1u/m9eHYdLi+en8NowrmXeF/dKtJpU8lCWli8RUAati7NcSl0afsBott48pdnANuD0wh9QQ==", + "dependencies": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.0", + "@emotion/memoize": "^0.8.0", + "@emotion/serialize": "^1.1.1", + "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.1.3" + } + }, + "node_modules/@emotion/cache": { + "version": "11.10.5", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.10.5.tgz", + "integrity": "sha512-dGYHWyzTdmK+f2+EnIGBpkz1lKc4Zbj2KHd4cX3Wi8/OWr5pKslNjc3yABKH4adRGCvSX4VDC0i04mrrq0aiRA==", + "dependencies": { + "@emotion/memoize": "^0.8.0", + "@emotion/sheet": "^1.2.1", + "@emotion/utils": "^1.2.0", + "@emotion/weak-memoize": "^0.3.0", + "stylis": "4.1.3" + } + }, + "node_modules/@emotion/hash": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.0.tgz", + "integrity": "sha512-14FtKiHhy2QoPIzdTcvh//8OyBlknNs2nXRwIhG904opCby3l+9Xaf/wuPvICBF0rc1ZCNBd3nKe9cd2mecVkQ==" + }, + "node_modules/@emotion/is-prop-valid": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.0.tgz", + "integrity": "sha512-3aDpDprjM0AwaxGE09bOPkNxHpBd+kA6jty3RnaEXdweX1DF1U3VQpPYb0g1IStAuK7SVQ1cy+bNBBKp4W3Fjg==", + "dependencies": { + "@emotion/memoize": "^0.8.0" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.0.tgz", + "integrity": "sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA==" + }, + "node_modules/@emotion/react": { + "version": "11.10.6", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.10.6.tgz", + "integrity": "sha512-6HT8jBmcSkfzO7mc+N1L9uwvOnlcGoix8Zn7srt+9ga0MjREo6lRpuVX0kzo6Jp6oTqDhREOFsygN6Ew4fEQbw==", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.10.6", + "@emotion/cache": "^11.10.5", + "@emotion/serialize": "^1.1.1", + "@emotion/use-insertion-effect-with-fallbacks": "^1.0.0", + "@emotion/utils": "^1.2.0", + "@emotion/weak-memoize": "^0.3.0", + "hoist-non-react-statics": "^3.3.1" + }, + "peerDependencies": { + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/serialize": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.1.tgz", + "integrity": "sha512-Zl/0LFggN7+L1liljxXdsVSVlg6E/Z/olVWpfxUTxOAmi8NU7YoeWeLfi1RmnB2TATHoaWwIBRoL+FvAJiTUQA==", + "dependencies": { + "@emotion/hash": "^0.9.0", + "@emotion/memoize": "^0.8.0", + "@emotion/unitless": "^0.8.0", + "@emotion/utils": "^1.2.0", + "csstype": "^3.0.2" + } + }, + "node_modules/@emotion/sheet": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.1.tgz", + "integrity": "sha512-zxRBwl93sHMsOj4zs+OslQKg/uhF38MB+OMKoCrVuS0nyTkqnau+BM3WGEoOptg9Oz45T/aIGs1qbVAsEFo3nA==" + }, + "node_modules/@emotion/styled": { + "version": "11.10.6", + "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.10.6.tgz", + "integrity": "sha512-OXtBzOmDSJo5Q0AFemHCfl+bUueT8BIcPSxu0EGTpGk6DmI5dnhSzQANm1e1ze0YZL7TDyAyy6s/b/zmGOS3Og==", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.10.6", + "@emotion/is-prop-valid": "^1.2.0", + "@emotion/serialize": "^1.1.1", + "@emotion/use-insertion-effect-with-fallbacks": "^1.0.0", + "@emotion/utils": "^1.2.0" + }, + "peerDependencies": { + "@emotion/react": "^11.0.0-rc.0", + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/stylis": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.8.5.tgz", + "integrity": "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==" + }, + "node_modules/@emotion/unitless": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.0.tgz", + "integrity": "sha512-VINS5vEYAscRl2ZUDiT3uMPlrFQupiKgHz5AA4bCH1miKBg4qtwkim1qPmJj/4WG6TreYMY111rEFsjupcOKHw==" + }, + "node_modules/@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.0.tgz", + "integrity": "sha512-1eEgUGmkaljiBnRMTdksDV1W4kUnmwgp7X9G8B++9GYwl1lUdqSndSriIrTJ0N7LQaoauY9JJ2yhiOYK5+NI4A==", + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@emotion/utils": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.0.tgz", + "integrity": "sha512-sn3WH53Kzpw8oQ5mgMmIzzyAaH2ZqFEbozVVBSYp538E06OSE6ytOp7pRAjNQR+Q/orwqdQYJSe2m3hCOeznkw==" + }, + "node_modules/@emotion/weak-memoize": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.0.tgz", + "integrity": "sha512-AHPmaAx+RYfZz0eYu6Gviiagpmiyw98ySSlQvCUhVGDRtDFe4DBS0x1bSjdF3gqUDYOczB+yYvBTtEylYSdRhg==" + }, + "node_modules/@esbuild/android-arm": { + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.11.tgz", + "integrity": "sha512-CdyX6sRVh1NzFCsf5vw3kULwlAhfy9wVt8SZlrhQ7eL2qBjGbFhRBWkkAzuZm9IIEOCKJw4DXA6R85g+qc8RDw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.11.tgz", + "integrity": "sha512-QnK4d/zhVTuV4/pRM4HUjcsbl43POALU2zvBynmrrqZt9LPcLA3x1fTZPBg2RRguBQnJcnU059yKr+bydkntjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.11.tgz", + "integrity": "sha512-3PL3HKtsDIXGQcSCKtWD/dy+mgc4p2Tvo2qKgKHj9Yf+eniwFnuoQ0OUhlSfAEpKAFzF9N21Nwgnap6zy3L3MQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.11.tgz", + "integrity": "sha512-pJ950bNKgzhkGNO3Z9TeHzIFtEyC2GDQL3wxkMApDEghYx5Qers84UTNc1bAxWbRkuJOgmOha5V0WUeh8G+YGw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.11.tgz", + "integrity": "sha512-iB0dQkIHXyczK3BZtzw1tqegf0F0Ab5texX2TvMQjiJIWXAfM4FQl7D909YfXWnB92OQz4ivBYQ2RlxBJrMJOw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.11.tgz", + "integrity": "sha512-7EFzUADmI1jCHeDRGKgbnF5sDIceZsQGapoO6dmw7r/ZBEKX7CCDnIz8m9yEclzr7mFsd+DyasHzpjfJnmBB1Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.11.tgz", + "integrity": "sha512-iPgenptC8i8pdvkHQvXJFzc1eVMR7W2lBPrTE6GbhR54sLcF42mk3zBOjKPOodezzuAz/KSu8CPyFSjcBMkE9g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.11.tgz", + "integrity": "sha512-M9iK/d4lgZH0U5M1R2p2gqhPV/7JPJcRz+8O8GBKVgqndTzydQ7B2XGDbxtbvFkvIs53uXTobOhv+RyaqhUiMg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.11.tgz", + "integrity": "sha512-Qxth3gsWWGKz2/qG2d5DsW/57SeA2AmpSMhdg9TSB5Svn2KDob3qxfQSkdnWjSd42kqoxIPy3EJFs+6w1+6Qjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.11.tgz", + "integrity": "sha512-dB1nGaVWtUlb/rRDHmuDQhfqazWE0LMro/AIbT2lWM3CDMHJNpLckH+gCddQyhhcLac2OYw69ikUMO34JLt3wA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.11.tgz", + "integrity": "sha512-aCWlq70Q7Nc9WDnormntGS1ar6ZFvUpqr8gXtO+HRejRYPweAFQN615PcgaSJkZjhHp61+MNLhzyVALSF2/Q0g==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.11.tgz", + "integrity": "sha512-cGeGNdQxqY8qJwlYH1BP6rjIIiEcrM05H7k3tR7WxOLmD1ZxRMd6/QIOWMb8mD2s2YJFNRuNQ+wjMhgEL2oCEw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.11.tgz", + "integrity": "sha512-BdlziJQPW/bNe0E8eYsHB40mYOluS+jULPCjlWiHzDgr+ZBRXPtgMV1nkLEGdpjrwgmtkZHEGEPaKdS/8faLDA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.11.tgz", + "integrity": "sha512-MDLwQbtF+83oJCI1Cixn68Et/ME6gelmhssPebC40RdJaect+IM+l7o/CuG0ZlDs6tZTEIoxUe53H3GmMn8oMA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.11.tgz", + "integrity": "sha512-4N5EMESvws0Ozr2J94VoUD8HIRi7X0uvUv4c0wpTHZyZY9qpaaN7THjosdiW56irQ4qnJ6Lsc+i+5zGWnyqWqQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.11.tgz", + "integrity": "sha512-rM/v8UlluxpytFSmVdbCe1yyKQd/e+FmIJE2oPJvbBo+D0XVWi1y/NQ4iTNx+436WmDHQBjVLrbnAQLQ6U7wlw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.11.tgz", + "integrity": "sha512-4WaAhuz5f91h3/g43VBGdto1Q+X7VEZfpcWGtOFXnggEuLvjV+cP6DyLRU15IjiU9fKLLk41OoJfBFN5DhPvag==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.11.tgz", + "integrity": "sha512-UBj135Nx4FpnvtE+C8TWGp98oUgBcmNmdYgl5ToKc0mBHxVVqVE7FUS5/ELMImOp205qDAittL6Ezhasc2Ev/w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.11.tgz", + "integrity": "sha512-1/gxTifDC9aXbV2xOfCbOceh5AlIidUrPsMpivgzo8P8zUtczlq1ncFpeN1ZyQJ9lVs2hILy1PG5KPp+w8QPPg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.11.tgz", + "integrity": "sha512-vtSfyx5yRdpiOW9yp6Ax0zyNOv9HjOAw8WaZg3dF5djEHKKm3UnoohftVvIJtRh0Ec7Hso0RIdTqZvPXJ7FdvQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.11.tgz", + "integrity": "sha512-GFPSLEGQr4wHFTiIUJQrnJKZhZjjq4Sphf+mM76nQR6WkQn73vm7IsacmBRPkALfpOCHsopSvLgqdd4iUW2mYw==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.11.tgz", + "integrity": "sha512-N9vXqLP3eRL8BqSy8yn4Y98cZI2pZ8fyuHx6lKjiG2WABpT2l01TXdzq5Ma2ZUBzfB7tx5dXVhge8X9u0S70ZQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@formatjs/ecma402-abstract": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.14.3.tgz", + "integrity": "sha512-SlsbRC/RX+/zg4AApWIFNDdkLtFbkq3LNoZWXZCE/nHVKqoIJyaoQyge/I0Y38vLxowUn9KTtXgusLD91+orbg==", + "dependencies": { + "@formatjs/intl-localematcher": "0.2.32", + "tslib": "^2.4.0" + } + }, + "node_modules/@formatjs/fast-memoize": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-2.0.1.tgz", + "integrity": "sha512-M2GgV+qJn5WJQAYewz7q2Cdl6fobQa69S1AzSM2y0P68ZDbK5cWrJIcPCO395Of1ksftGZoOt4LYCO/j9BKBSA==", + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@formatjs/icu-messageformat-parser": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.3.0.tgz", + "integrity": "sha512-xqtlqYAbfJDF4b6e4O828LBNOWXrFcuYadqAbYORlDRwhyJ2bH+xpUBPldZbzRGUN2mxlZ4Ykhm7jvERtmI8NQ==", + "dependencies": { + "@formatjs/ecma402-abstract": "1.14.3", + "@formatjs/icu-skeleton-parser": "1.3.18", + "tslib": "^2.4.0" + } + }, + "node_modules/@formatjs/icu-skeleton-parser": { + "version": "1.3.18", + "resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.3.18.tgz", + "integrity": "sha512-ND1ZkZfmLPcHjAH1sVpkpQxA+QYfOX3py3SjKWMUVGDow18gZ0WPqz3F+pJLYQMpS2LnnQ5zYR2jPVYTbRwMpg==", + "dependencies": { + "@formatjs/ecma402-abstract": "1.14.3", + "tslib": "^2.4.0" + } + }, + "node_modules/@formatjs/intl-localematcher": { + "version": "0.2.32", + "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.2.32.tgz", + "integrity": "sha512-k/MEBstff4sttohyEpXxCmC3MqbUn9VvHGlZ8fauLzkbwXmVrEeyzS+4uhrvAk9DWU9/7otYWxyDox4nT/KVLQ==", + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@internationalized/date": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@internationalized/date/-/date-3.1.0.tgz", + "integrity": "sha512-wjeur7K4AecT+YwoBmBXQ/+n5lP69tuZc34hw09s44EozZK7FZHSyfPvRp5/xEb2D6abLboskDY4jG+Nt0TNUQ==", + "dependencies": { + "@swc/helpers": "^0.4.14" + } + }, + "node_modules/@internationalized/message": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@internationalized/message/-/message-3.1.0.tgz", + "integrity": "sha512-Oo5m70FcBdADf7G8NkUffVSfuCdeAYVfsvNjZDi9ELpjvkc4YNJVTHt/NyTI9K7FgAVoELxiP9YmN0sJ+HNHYQ==", + "dependencies": { + "@swc/helpers": "^0.4.14", + "intl-messageformat": "^10.1.0" + } + }, + "node_modules/@internationalized/number": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@internationalized/number/-/number-3.2.0.tgz", + "integrity": "sha512-GUXkhXSX1Ee2RURnzl+47uvbOxnlMnvP9Er+QePTjDjOPWuunmLKlEkYkEcLiiJp7y4l9QxGDLOlVr8m69LS5w==", + "dependencies": { + "@swc/helpers": "^0.4.14" + } + }, + "node_modules/@internationalized/string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@internationalized/string/-/string-3.1.0.tgz", + "integrity": "sha512-TJQKiyUb+wyAfKF59UNeZ/kELMnkxyecnyPCnBI1ma4NaXReJW+7Cc2mObXAqraIBJUVv7rgI46RLKrLgi35ng==", + "dependencies": { + "@swc/helpers": "^0.4.14" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "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==", + "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==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "dev": true, + "peer": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "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==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", + "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", + "dependencies": { + "@jridgewell/resolve-uri": "3.1.0", + "@jridgewell/sourcemap-codec": "1.4.14" + } + }, + "node_modules/@juggle/resize-observer": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@juggle/resize-observer/-/resize-observer-3.4.0.tgz", + "integrity": "sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==" + }, + "node_modules/@mui/base": { + "version": "5.0.0-alpha.121", + "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.121.tgz", + "integrity": "sha512-8nJRY76UqlJV+q/Yzo0tgGfPWEOa+4N9rjO81fMmcJqP0I6m54hLDXsjvMg4tvelY5eKHXUK6Tb7en+GHfTqZA==", + "dependencies": { + "@babel/runtime": "^7.21.0", + "@emotion/is-prop-valid": "^1.2.0", + "@mui/types": "^7.2.3", + "@mui/utils": "^5.11.13", + "@popperjs/core": "^2.11.6", + "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.11.13", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.11.13.tgz", + "integrity": "sha512-lx+GXBR9h/ApZsEP728tl0pyZyuajto+VnBgsoAzw1d5+CbmOo8ZWieKwVUGxZlPT1wMYNUYS5NtKzCli0xYjw==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui" + } + }, + "node_modules/@mui/icons-material": { + "version": "5.11.11", + "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.11.11.tgz", + "integrity": "sha512-Eell3ADmQVE8HOpt/LZ3zIma8JSvPh3XgnhwZLT0k5HRqZcd6F/QDHc7xsWtgz09t+UEFvOYJXjtrwKmLdwwpw==", + "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.11.13", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.11.13.tgz", + "integrity": "sha512-2CnSj43F+159LbGmTLLQs5xbGYMiYlpTByQhP7c7cMX6opbScctBFE1PuyElpAmwW8Ag9ysfZH1d1MFAmJQkjg==", + "dependencies": { + "@babel/runtime": "^7.21.0", + "@mui/base": "5.0.0-alpha.121", + "@mui/core-downloads-tracker": "^5.11.13", + "@mui/system": "^5.11.13", + "@mui/types": "^7.2.3", + "@mui/utils": "^5.11.13", + "@types/react-transition-group": "^4.4.5", + "clsx": "^1.2.1", + "csstype": "^3.1.1", + "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.11.13", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.11.13.tgz", + "integrity": "sha512-PJnYNKzW5LIx3R+Zsp6WZVPs6w5sEKJ7mgLNnUXuYB1zo5aX71FVLtV7geyPXRcaN2tsoRNK7h444ED0t7cIjA==", + "dependencies": { + "@babel/runtime": "^7.21.0", + "@mui/utils": "^5.11.13", + "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.11.11", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.11.11.tgz", + "integrity": "sha512-wV0UgW4lN5FkDBXefN8eTYeuE9sjyQdg5h94vtwZCUamGQEzmCOtir4AakgmbWMy0x8OLjdEUESn9wnf5J9MOg==", + "dependencies": { + "@babel/runtime": "^7.21.0", + "@emotion/cache": "^11.10.5", + "csstype": "^3.1.1", + "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.11.13", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.11.13.tgz", + "integrity": "sha512-OWP0Alp6C8ufnGm9+CZcl3d+OoRXL2PnrRT5ohaMLxvGL9OfNcL2t4JOjMmA0k1UAGd6E/Ygbu5lEPrZSDlvCg==", + "dependencies": { + "@babel/runtime": "^7.21.0", + "@mui/private-theming": "^5.11.13", + "@mui/styled-engine": "^5.11.11", + "@mui/types": "^7.2.3", + "@mui/utils": "^5.11.13", + "clsx": "^1.2.1", + "csstype": "^3.1.1", + "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.3", + "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.3.tgz", + "integrity": "sha512-tZ+CQggbe9Ol7e/Fs5RcKwg/woU+o8DCtOnccX6KmbBc7YrfqMYEYuaIcXHuhpT880QwNkZZ3wQwvtlDFA2yOw==", + "peerDependencies": { + "@types/react": "*" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/utils": { + "version": "5.11.13", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.11.13.tgz", + "integrity": "sha512-5ltA58MM9euOuUcnvwFJqpLdEugc9XFsRR8Gt4zZNb31XzMfSKJPR4eumulyhsOTK1rWf7K4D63NKFPfX0AxqA==", + "dependencies": { + "@babel/runtime": "^7.21.0", + "@types/prop-types": "^15.7.5", + "@types/react-is": "^16.7.1 || ^17.0.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/@popperjs/core": { + "version": "2.11.6", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz", + "integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/@react-aria/focus": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.11.0.tgz", + "integrity": "sha512-yPuWs9bAR9CMfIwyOPm2oXLPF19gNkUqW+ozSPhWbLMTEa8Ma09eHW1br4xbN+4ONOm/dCJsIkxTNPUkiLdQoA==", + "dependencies": { + "@react-aria/interactions": "^3.14.0", + "@react-aria/utils": "^3.15.0", + "@react-types/shared": "^3.17.0", + "@swc/helpers": "^0.4.14", + "clsx": "^1.1.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/i18n": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@react-aria/i18n/-/i18n-3.7.0.tgz", + "integrity": "sha512-PZCWmhO9mJvelwiYlsXLY6W4L2o+oza3xnDx0cZDVqp/Hf+OwMAPHWtZsFRTKdjk4TaOPB/ISc9HknWn6UpY4w==", + "dependencies": { + "@internationalized/date": "^3.1.0", + "@internationalized/message": "^3.1.0", + "@internationalized/number": "^3.2.0", + "@internationalized/string": "^3.1.0", + "@react-aria/ssr": "^3.5.0", + "@react-aria/utils": "^3.15.0", + "@react-types/shared": "^3.17.0", + "@swc/helpers": "^0.4.14" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/interactions": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.14.0.tgz", + "integrity": "sha512-e1Tkr0UTuYFpV21PJrXy7jEY542Vl+C2Fo70oukZ1fN+wtfQkzodsTIzyepXb7kVMGmC34wDisMJUrksVkfY2w==", + "dependencies": { + "@react-aria/utils": "^3.15.0", + "@react-types/shared": "^3.17.0", + "@swc/helpers": "^0.4.14" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/overlays": { + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/@react-aria/overlays/-/overlays-3.13.0.tgz", + "integrity": "sha512-hRZyhAYzrlCcEWQ2k2jP24b0wc5/355Xl5w5FZHRmPeU1U4XlFwKX/eFlBs/li9Sprm1bTDXrCY480Kl6UsKDA==", + "dependencies": { + "@react-aria/focus": "^3.11.0", + "@react-aria/i18n": "^3.7.0", + "@react-aria/interactions": "^3.14.0", + "@react-aria/ssr": "^3.5.0", + "@react-aria/utils": "^3.15.0", + "@react-aria/visually-hidden": "^3.7.0", + "@react-stately/overlays": "^3.5.0", + "@react-types/button": "^3.7.1", + "@react-types/overlays": "^3.7.0", + "@react-types/shared": "^3.17.0", + "@swc/helpers": "^0.4.14" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/ssr": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.5.0.tgz", + "integrity": "sha512-h0MJdSWOd1qObLnJ8mprU31wI8tmKFJMuwT22MpWq6psisOOZaga6Ml4u6Ee6M6duWWISjXvqO4Sb/J0PBA+nQ==", + "dependencies": { + "@swc/helpers": "^0.4.14" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/utils": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.15.0.tgz", + "integrity": "sha512-aJZBG++iz1UwTW5gXFaHicKju4p0MPhAyBTcf2awHYWeTUUslDjJcEnNg7kjBYZBOrOSlA2rAt7/7C5CCURQPg==", + "dependencies": { + "@react-aria/ssr": "^3.5.0", + "@react-stately/utils": "^3.6.0", + "@react-types/shared": "^3.17.0", + "@swc/helpers": "^0.4.14", + "clsx": "^1.1.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/visually-hidden": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@react-aria/visually-hidden/-/visually-hidden-3.7.0.tgz", + "integrity": "sha512-v/0ujJ67H6LjwY8J7mIGPVB1K8suBArLV+w8UGdX/wFXRL7H4r2fiqlrwAElWSmNbhDQl5BDm/Zh/ub9jB9yzA==", + "dependencies": { + "@react-aria/interactions": "^3.14.0", + "@react-aria/utils": "^3.15.0", + "@react-types/shared": "^3.17.0", + "@swc/helpers": "^0.4.14", + "clsx": "^1.1.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-dnd/asap": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@react-dnd/asap/-/asap-5.0.2.tgz", + "integrity": "sha512-WLyfoHvxhs0V9U+GTsGilGgf2QsPl6ZZ44fnv0/b8T3nQyvzxidxsg/ZltbWssbsRDlYW8UKSQMTGotuTotZ6A==" + }, + "node_modules/@react-dnd/invariant": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@react-dnd/invariant/-/invariant-4.0.2.tgz", + "integrity": "sha512-xKCTqAK/FFauOM9Ta2pswIyT3D8AQlfrYdOi/toTPEhqCuAs1v5tcJ3Y08Izh1cJ5Jchwy9SeAXmMg6zrKs2iw==" + }, + "node_modules/@react-dnd/shallowequal": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@react-dnd/shallowequal/-/shallowequal-4.0.2.tgz", + "integrity": "sha512-/RVXdLvJxLg4QKvMoM5WlwNR9ViO9z8B/qPcc+C0Sa/teJY7QG7kJ441DwzOjMYEY7GmU4dj5EcGHIkKZiQZCA==" + }, + "node_modules/@react-spectrum/layout": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/@react-spectrum/layout/-/layout-3.5.0.tgz", + "integrity": "sha512-Yjy0uvGUHjczl44PQlMqOEBoJIe4coYwDQCoVl20YrTzGiMdwLV24Hs9uqK3I6yKmAoNxTehe0CdOVgwuVRF9g==", + "dependencies": { + "@react-aria/ssr": "^3.5.0", + "@react-aria/utils": "^3.15.0", + "@react-spectrum/utils": "^3.9.0", + "@react-types/layout": "^3.3.6", + "@react-types/shared": "^3.17.0", + "@swc/helpers": "^0.4.14", + "clsx": "^1.1.1" + }, + "peerDependencies": { + "@react-spectrum/provider": "^3.0.0", + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-spectrum/provider": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@react-spectrum/provider/-/provider-3.7.0.tgz", + "integrity": "sha512-6Uch60R5PKJC+ZY3VweVadaCoaIj6Nd85TKfFH4jf8NEzXv5CqjwUzwV5aQ6u3k1K24Ves7RpLlK53HW1wUm6w==", + "dependencies": { + "@react-aria/i18n": "^3.7.0", + "@react-aria/overlays": "^3.13.0", + "@react-aria/utils": "^3.15.0", + "@react-spectrum/utils": "^3.9.0", + "@react-types/provider": "^3.6.0", + "@react-types/shared": "^3.17.0", + "@swc/helpers": "^0.4.14", + "clsx": "^1.1.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-spectrum/theme-default": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/@react-spectrum/theme-default/-/theme-default-3.5.0.tgz", + "integrity": "sha512-DagwngJ9T7yGgtdTwKj9LaHbg3AWLW2/ILJK92xbPj/yAAEVXJ8vhiP9Tg3W3mZMsxBCNwTVLyOLheu7d+D8og==", + "dependencies": { + "@react-types/provider": "^3.6.0", + "@swc/helpers": "^0.4.14" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-spectrum/utils": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/@react-spectrum/utils/-/utils-3.9.0.tgz", + "integrity": "sha512-I1JKwiyLE54mAT7Z2wadVKoai1Q60QFg4XNuYUwk8TwWAEz7DUUHucntHAND6dqFpVIMK1Rk9lcZBft43FF2BQ==", + "dependencies": { + "@react-aria/i18n": "^3.7.0", + "@react-aria/ssr": "^3.5.0", + "@react-aria/utils": "^3.15.0", + "@react-types/shared": "^3.17.0", + "@swc/helpers": "^0.4.14", + "clsx": "^1.1.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-spectrum/view": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/@react-spectrum/view/-/view-3.5.0.tgz", + "integrity": "sha512-Zzsy2S6gT14vtli52tjM5VP1EdMOP+bppNCmwX+saUJuxaEdj6oYjP89quE4HwALzYceOfmXIuGDyEVeDcuSsQ==", + "dependencies": { + "@react-aria/i18n": "^3.7.0", + "@react-aria/utils": "^3.15.0", + "@react-spectrum/utils": "^3.9.0", + "@react-types/shared": "^3.17.0", + "@react-types/view": "^3.4.0", + "@swc/helpers": "^0.4.14" + }, + "peerDependencies": { + "@react-spectrum/provider": "^3.0.0", + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/overlays": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/@react-stately/overlays/-/overlays-3.5.0.tgz", + "integrity": "sha512-r+U/G0Y4tCfI5wyBeIu+hmcZVRN8ChoK2zM1srPH9nDKsijQard2goX+9YmKng2LJ01Re/P6F8S8jYbpfEdLfQ==", + "dependencies": { + "@react-stately/utils": "^3.6.0", + "@react-types/overlays": "^3.7.0", + "@swc/helpers": "^0.4.14" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/utils": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@react-stately/utils/-/utils-3.6.0.tgz", + "integrity": "sha512-rptF7iUWDrquaYvBAS4QQhOBQyLBncDeHF03WnHXAxnuPJXNcr9cXJtjJPGCs036ZB8Q2hc9BGG5wNyMkF5v+Q==", + "dependencies": { + "@swc/helpers": "^0.4.14" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/button": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/@react-types/button/-/button-3.7.1.tgz", + "integrity": "sha512-c+8xjmqWSjI5/mEHVLbVSp0eh/z2UU8Ga+wqjbEUZUjm8uopYj1PaCAwZ7YgcAebyQrL/21GyjK6tFHKzuUdJQ==", + "dependencies": { + "@react-types/shared": "^3.17.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/layout": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/@react-types/layout/-/layout-3.3.6.tgz", + "integrity": "sha512-8YF7nb+0AtSDRj+rejMRS5djWpqAf5Q6sJzgdccn42JQxW7jvxoKqN0pCRPqpMzQqae5hOsYYpVNfuIHwUUkUA==", + "dependencies": { + "@react-types/shared": "^3.17.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/overlays": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@react-types/overlays/-/overlays-3.7.0.tgz", + "integrity": "sha512-LstucncZ8dM+xJYEijI1V6jGH20w5XO/T60r7JTrgQElMC86phPeoWkMTN4c2lsRikybolDbvXL6XsF76YO56A==", + "dependencies": { + "@react-types/shared": "^3.17.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/provider": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@react-types/provider/-/provider-3.6.0.tgz", + "integrity": "sha512-29+X5yMr1uHUc/BmFoyBqfWyMT3YGZJffaprtGGRQkCuwMbqoA8GI+rGJzNAMAD/1cPNo237PAGsi4NAup5tAQ==", + "dependencies": { + "@react-types/shared": "^3.17.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/shared": { + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.17.0.tgz", + "integrity": "sha512-1SNZ/RhVrrQ1e6yE0bPV7d5Sfp+Uv0dfUEhwF9MAu2v5msu7AMewnsiojKNA0QA6Ing1gpDLjHCxtayQfuxqcg==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/view": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@react-types/view/-/view-3.4.0.tgz", + "integrity": "sha512-lXDLbOYRFwo8hxrSDIYUmnxOGZlHBDVEFe1ZKAXJ+qPwntzxhzUeAuddTiMDhEETKgTclmlIsJnwz+HNv6dhSQ==", + "dependencies": { + "@react-types/shared": "^3.17.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@reduxjs/toolkit": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.3.tgz", + "integrity": "sha512-GU2TNBQVofL09VGmuSioNPQIu6Ml0YLf4EJhgj0AvBadRlCGzUWet8372LjvO4fqKZF2vH1xU0htAa7BrK9pZg==", + "dependencies": { + "immer": "^9.0.16", + "redux": "^4.2.0", + "redux-thunk": "^2.4.2", + "reselect": "^4.1.7" + }, + "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.4.0", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.4.0.tgz", + "integrity": "sha512-BJ9SxXux8zAg991UmT8slpwpsd31K1dHHbD3Ba4VzD+liLQ4WAMSxQp2d2ZPRPfN0jN2NPRowcSSoM7lCaF08Q==", + "engines": { + "node": ">=14" + } + }, + "node_modules/@swc/core": { + "version": "1.3.41", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.3.41.tgz", + "integrity": "sha512-v6P2dfqJDpZ/7RXPvWge9oI6YgolDM0jtNhQZ2qdXrLBzaWQdDoBGBTJ8KN/nTgGhX3IkNvSB1fafXQ+nVnqAQ==", + "dev": true, + "hasInstallScript": true, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/swc" + }, + "optionalDependencies": { + "@swc/core-darwin-arm64": "1.3.41", + "@swc/core-darwin-x64": "1.3.41", + "@swc/core-linux-arm-gnueabihf": "1.3.41", + "@swc/core-linux-arm64-gnu": "1.3.41", + "@swc/core-linux-arm64-musl": "1.3.41", + "@swc/core-linux-x64-gnu": "1.3.41", + "@swc/core-linux-x64-musl": "1.3.41", + "@swc/core-win32-arm64-msvc": "1.3.41", + "@swc/core-win32-ia32-msvc": "1.3.41", + "@swc/core-win32-x64-msvc": "1.3.41" + } + }, + "node_modules/@swc/core-darwin-arm64": { + "version": "1.3.41", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.41.tgz", + "integrity": "sha512-D4fybODToO/BvuP35bionDUrSuTVVr8eW+mApr1unOqb3mfiqOrVv0VP2fpWNRYiA+xMq+oBCB6KcGpL60HKWQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-darwin-x64": { + "version": "1.3.41", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.3.41.tgz", + "integrity": "sha512-0RoVyiPCnylf3TG77C3S86PRSmaq+SaYB4VDLJFz3qcEHz1pfP0LhyskhgX4wjQV1mveDzFEn1BVAuo0eOMwZA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm-gnueabihf": { + "version": "1.3.41", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.3.41.tgz", + "integrity": "sha512-mZW7GeY7Uw1nkKoWpx898ou20oCSt8MR+jAVuAhMjX+G4Zr0WWXYSigWNiRymhR6Q9KhyvoFpMckguSvYWmXsw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-gnu": { + "version": "1.3.41", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.41.tgz", + "integrity": "sha512-e91LGn+6KuLFw3sWk5swwGc/dP4tXs0mg3HrhjImRoofU02Bb9aHcj5zgrSO8ZByvDtm/Knn16h1ojxIMOFaxg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-musl": { + "version": "1.3.41", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.41.tgz", + "integrity": "sha512-Q7hmrniLWsQ7zjtImGcjx1tl5/Qxpel+fC+OXTnGvAyyoGssSftIBlXMnqVLteL78zhxIPAzi+gizWAe5RGqrA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-gnu": { + "version": "1.3.41", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.41.tgz", + "integrity": "sha512-h4sv1sCfZQgRIwmykz8WPqVpbvHb13Qm3SsrbOudhAp2MuzpWzsgMP5hAEpdCP/nWreiCz3aoM6L8JeakRDq0g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-musl": { + "version": "1.3.41", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.41.tgz", + "integrity": "sha512-Z7c26i38378d0NT/dcz8qPSAXm41lqhNzykdhKhI+95mA9m4pskP18T/0I45rmyx1ywifypu+Ip+SXmKeVSPgQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-arm64-msvc": { + "version": "1.3.41", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.41.tgz", + "integrity": "sha512-I0CYnPc+ZGc912YeN0TykIOf/Q7yJQHRwDuhewwD6RkbiSEaVfSux5pAmmdoKw2aGMSq+cwLmgPe9HYLRNz+4w==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-ia32-msvc": { + "version": "1.3.41", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.41.tgz", + "integrity": "sha512-EygN4CVDWF29/U2T5fXGfWyLvRbMd2hiUgkciAl7zHuyJ6nKl+kpodqV2A0Wd4sFtSNedU0gQEBEXEe7cqvmsA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-x64-msvc": { + "version": "1.3.41", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.41.tgz", + "integrity": "sha512-Mfp8qD1hNwWWRy0ISdwQJu1g0UYoVTtuQlO0z3aGbXqL51ew9e56+8j3M1U9i95lXFyWkARgjDCcKkQi+WezyA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/helpers": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.14.tgz", + "integrity": "sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw==", + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/eslint": { + "version": "8.21.3", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.21.3.tgz", + "integrity": "sha512-fa7GkppZVEByMWGbTtE5MbmXWJTVbrjjaS8K6uQj+XtuuUv1fsuPAxhygfqLmsb/Ufb3CV8deFCpiMfAgi00Sw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", + "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", + "dev": true, + "peer": true, + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "0.0.51", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", + "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", + "dev": true, + "peer": 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/is-hotkey": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/@types/is-hotkey/-/is-hotkey-0.1.7.tgz", + "integrity": "sha512-yB5C7zcOM7idwYZZ1wKQ3pTfjA9BbvFqRWvKB46GFddxnJtHwi/b9y84ykQtxQPg5qhdpg4Q/kWU3EGoCTmLzQ==" + }, + "node_modules/@types/json-schema": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", + "dev": true + }, + "node_modules/@types/lodash": { + "version": "4.14.191", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.191.tgz", + "integrity": "sha512-BdZ5BCCvho3EIXw6wUCXHe7rS53AIDPLE+JzwgT+OsJk53oBfbSmZZ7CX4VaRoN78N+TJpFi9QPlfIVNmJYWxQ==" + }, + "node_modules/@types/node": { + "version": "18.15.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.5.tgz", + "integrity": "sha512-Ark2WDjjZO7GmvsyFFf81MXuGTA/d6oP38anyxWOL6EREyBKAxKoFHwBhaZxCfLRLpO8JgVXwqOwSwa7jRcjew==", + "devOptional": true, + "peer": 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/react": { + "version": "18.0.28", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.28.tgz", + "integrity": "sha512-RD0ivG1kEztNBdoAK7lekI9M+azSnitIn85h4iOiaLjaTrMjzslhaqCGaI4IyCJ1RljWiLCEu4jyrLLgqxBTew==", + "dependencies": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-copy-to-clipboard": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/react-copy-to-clipboard/-/react-copy-to-clipboard-5.0.4.tgz", + "integrity": "sha512-otTJsJpofYAeaIeOwV5xBUGpo6exXG2HX7X4nseToCB2VgPEBxGBHCm/FecZ676doNR7HCSTVtmohxfG2b3/yQ==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/react-dom": { + "version": "18.0.11", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.11.tgz", + "integrity": "sha512-O38bPbI2CWtgw/OoQoY+BRelw7uysmXbWvw3nLWO21H1HSh+GOlqPuXshJfjmpNlKiiSDG9cc1JZAaMmVdcTlw==", + "devOptional": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/react-grid-layout": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/react-grid-layout/-/react-grid-layout-1.3.2.tgz", + "integrity": "sha512-ZzpBEOC1JTQ7MGe1h1cPKSLP4jSWuxc+yvT4TsAlEW9+EFPzAf8nxQfFd7ea9gL17Em7PbwJZAsiwfQQBUklZQ==", + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/react-is": { + "version": "17.0.3", + "resolved": "https://registry.npmjs.org/@types/react-is/-/react-is-17.0.3.tgz", + "integrity": "sha512-aBTIWg1emtu95bLTLx0cpkxwGW3ueZv71nE2YFBpL8k/z5czEW8yYpOo8Dp+UUAFAtKwNaOsh/ioSeQnWlZcfw==", + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-juKD/eiSM3/xZYzjuzH6ZwpP+/lejltmiS3QEzV/vmb/Q8+HfDmxu+Baga8UEMGBqV88Nbg4l2hY/K2DkyaLLA==", + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/scheduler": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", + "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==" + }, + "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/@vitejs/plugin-react-swc": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react-swc/-/plugin-react-swc-3.2.0.tgz", + "integrity": "sha512-IcBoXL/mcH7JdQr/nfDlDwTdIaH8Rg7LpfQDF4nAht+juHWIuv6WhpKPCSfY4+zztAaB07qdBoFz1XCZsgo3pQ==", + "dev": true, + "dependencies": { + "@swc/core": "^1.3.35" + }, + "peerDependencies": { + "vite": "^4" + } + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", + "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", + "dev": true, + "peer": true, + "dependencies": { + "@webassemblyjs/helper-numbers": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", + "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", + "dev": true, + "peer": true + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", + "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", + "dev": true, + "peer": true + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", + "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", + "dev": true, + "peer": true + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", + "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", + "dev": true, + "peer": true, + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", + "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", + "dev": true, + "peer": true + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", + "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", + "dev": true, + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", + "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", + "dev": true, + "peer": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", + "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", + "dev": true, + "peer": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", + "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", + "dev": true, + "peer": true + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", + "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", + "dev": true, + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/helper-wasm-section": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-opt": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "@webassemblyjs/wast-printer": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", + "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", + "dev": true, + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", + "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", + "dev": true, + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", + "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", + "dev": true, + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", + "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", + "dev": true, + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true, + "peer": true + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true, + "peer": true + }, + "node_modules/acorn": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "dev": true, + "peer": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-assertions": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", + "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", + "dev": true, + "peer": true, + "peerDependencies": { + "acorn": "^8" + } + }, + "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/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "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/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "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/axios": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.4.tgz", + "integrity": "sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==", + "dependencies": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "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/babel-plugin-styled-components": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-2.0.7.tgz", + "integrity": "sha512-i7YhvPgVqRKfoQ66toiZ06jPNA3p6ierpfUuEWxNF+fV27Uv5gxBkf8KZLHUCc1nFA9j6+80pYoIpqCeyW3/bA==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.16.0", + "@babel/helper-module-imports": "^7.16.0", + "babel-plugin-syntax-jsx": "^6.18.0", + "lodash": "^4.17.11", + "picomatch": "^2.3.0" + }, + "peerDependencies": { + "styled-components": ">= 2" + } + }, + "node_modules/babel-plugin-syntax-jsx": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", + "integrity": "sha512-qrPaCSo9c8RHNRHIotaufGbuOBN8rtdC4QrrFFc43vyWCCz7Kl7GL1PGaXtMGQZUXrkCjNEgxDfmAuAabr/rlw==" + }, + "node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "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/browserslist": { + "version": "4.21.5", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", + "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "peer": true, + "dependencies": { + "caniuse-lite": "^1.0.30001449", + "electron-to-chromium": "^1.4.284", + "node-releases": "^2.0.8", + "update-browserslist-db": "^1.0.10" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "peer": true + }, + "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/camelize": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz", + "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001469", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001469.tgz", + "integrity": "sha512-Rcp7221ScNqQPP3W+lVOYDyjdR6dC+neEQCttoNr5bAyz54AboB4iwpnWgyi8P4YUsPybVzT4LgWiBbI3drL4g==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + } + ], + "peer": true + }, + "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/chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/classnames": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", + "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==" + }, + "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/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true, + "peer": true + }, + "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/compute-scroll-into-view": { + "version": "1.0.20", + "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-1.0.20.tgz", + "integrity": "sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg==" + }, + "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/copy-to-clipboard": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz", + "integrity": "sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==", + "dependencies": { + "toggle-selection": "^1.0.6" + } + }, + "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/css-color-keywords": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", + "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==", + "engines": { + "node": ">=4" + } + }, + "node_modules/css-to-react-native": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz", + "integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==", + "dependencies": { + "camelize": "^1.0.0", + "css-color-keywords": "^1.0.0", + "postcss-value-parser": "^4.0.2" + } + }, + "node_modules/csstype": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz", + "integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==" + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/direction": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/direction/-/direction-1.0.4.tgz", + "integrity": "sha512-GYqKi1aH7PJXxdhTeZBFrg8vUBeKXi+cNprXsC1kpJcbcVnV9wBsrOu1cQEdG0WeQwlfHiy3XvnKfIrJ2R0NzQ==", + "bin": { + "direction": "cli.js" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/dnd-core": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/dnd-core/-/dnd-core-16.0.1.tgz", + "integrity": "sha512-HK294sl7tbw6F6IeuK16YSBUoorvHpY8RHO+9yFfaJyCDVb6n7PRcezrOEOa2SBCqiYpemh5Jx20ZcjKdFAVng==", + "dependencies": { + "@react-dnd/asap": "^5.0.1", + "@react-dnd/invariant": "^4.0.1", + "redux": "^4.2.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/electron-to-chromium": { + "version": "1.4.334", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.334.tgz", + "integrity": "sha512-laZ1odk+TRen6q0GeyQx/JEkpD3iSZT7ewopCpKqg9bTjP1l8XRfU3Bg20CFjNPZkp5+NDBl3iqd4o/kPO+Vew==", + "dev": true, + "peer": true + }, + "node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.12.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", + "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", + "dev": true, + "peer": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "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/es-module-lexer": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", + "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", + "dev": true, + "peer": true + }, + "node_modules/esbuild": { + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.11.tgz", + "integrity": "sha512-pAMImyokbWDtnA/ufPxjQg0fYo2DDuzAlqwnDvbXqHLphe+m80eF++perYKVm8LeTuj2zUuFXC+xgSVxyoHUdg==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.17.11", + "@esbuild/android-arm64": "0.17.11", + "@esbuild/android-x64": "0.17.11", + "@esbuild/darwin-arm64": "0.17.11", + "@esbuild/darwin-x64": "0.17.11", + "@esbuild/freebsd-arm64": "0.17.11", + "@esbuild/freebsd-x64": "0.17.11", + "@esbuild/linux-arm": "0.17.11", + "@esbuild/linux-arm64": "0.17.11", + "@esbuild/linux-ia32": "0.17.11", + "@esbuild/linux-loong64": "0.17.11", + "@esbuild/linux-mips64el": "0.17.11", + "@esbuild/linux-ppc64": "0.17.11", + "@esbuild/linux-riscv64": "0.17.11", + "@esbuild/linux-s390x": "0.17.11", + "@esbuild/linux-x64": "0.17.11", + "@esbuild/netbsd-x64": "0.17.11", + "@esbuild/openbsd-x64": "0.17.11", + "@esbuild/sunos-x64": "0.17.11", + "@esbuild/win32-arm64": "0.17.11", + "@esbuild/win32-ia32": "0.17.11", + "@esbuild/win32-x64": "0.17.11" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "peer": 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-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, + "peer": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.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, + "peer": 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, + "peer": 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, + "peer": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.8.x" + } + }, + "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==" + }, + "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/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/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/follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "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.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true, + "peer": true + }, + "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==", + "engines": { + "node": ">=4" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "peer": 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/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/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.19", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.19.tgz", + "integrity": "sha512-eY+Y0qcsB4TZKwgQzLaE/lqYMlKhv5J9dyd2RhhtGhNo2njPXDqU9XPfcNfa3MIDsdtZt5KlkIsirlo4dHsWdQ==", + "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/intl-messageformat": { + "version": "10.3.3", + "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-10.3.3.tgz", + "integrity": "sha512-un/f07/g2e/3Q8e1ghDKET+el22Bi49M7O/rHxd597R+oLpPOMykSv5s51cABVfu3FZW+fea4hrzf2MHu1W4hw==", + "dependencies": { + "@formatjs/ecma402-abstract": "1.14.3", + "@formatjs/fast-memoize": "2.0.1", + "@formatjs/icu-messageformat-parser": "2.3.0", + "tslib": "^2.4.0" + } + }, + "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.11.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", + "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-hotkey": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/is-hotkey/-/is-hotkey-0.1.8.tgz", + "integrity": "sha512-qs3NZ1INIS+H+yeo7cD9pDfwYV/jqRh1JG9S9zYrNudkoUQg7OL7ziXqRKu+InFjUIDoP2o6HIkLYMh1pcWgyQ==" + }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "peer": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/jest-worker/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, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "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/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "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/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/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/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "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/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==" + }, + "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/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "peer": true + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "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==" + }, + "node_modules/nanoid": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "dev": true, + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true, + "peer": true + }, + "node_modules/node-releases": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", + "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==", + "dev": true, + "peer": 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/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-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/philliplm-react-modern-audio-player": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/philliplm-react-modern-audio-player/-/philliplm-react-modern-audio-player-1.4.6.tgz", + "integrity": "sha512-2C/1lpQJmD0gWJMVt6k/QNZoakxHwxGhRFyw17OVAwbpXmptisr9aHDzT/VPFKoIr5qj+y1WajJ4lnghbfzx9Q==", + "dependencies": { + "@react-spectrum/layout": "^3.3.1", + "@react-spectrum/provider": "^3.4.1", + "@react-spectrum/theme-default": "^3.3.1", + "@react-spectrum/view": "^3.2.1", + "classnames": "^2.3.1", + "react-icons": "^4.4.0", + "styled-components": "^5.3.5", + "wavesurfer.js": "^6.2.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "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==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.4.21", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", + "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + } + ], + "dependencies": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + }, + "node_modules/prettier": { + "version": "2.8.6", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.6.tgz", + "integrity": "sha512-mtuzdiBbHwPEgl7NxWlqOkithPyp4VN93V7VeHVWBF+ad3I5avc0RVDT4oImXQy9H/AqxA2NSQH8pSxHW6FYbQ==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "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/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "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/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "peer": true, + "dependencies": { + "safe-buffer": "^5.1.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-copy-to-clipboard": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/react-copy-to-clipboard/-/react-copy-to-clipboard-5.1.0.tgz", + "integrity": "sha512-k61RsNgAayIJNoy9yDsYzDe/yAZAzEbEgcz3DZMhF686LEyukcE1hzurxe85JandPUG+yTfGVFzuEw3xt8WP/A==", + "dependencies": { + "copy-to-clipboard": "^3.3.1", + "prop-types": "^15.8.1" + }, + "peerDependencies": { + "react": "^15.3.0 || 16 || 17 || 18" + } + }, + "node_modules/react-dnd": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/react-dnd/-/react-dnd-16.0.1.tgz", + "integrity": "sha512-QeoM/i73HHu2XF9aKksIUuamHPDvRglEwdHL4jsp784BgUuWcg6mzfxT0QDdQz8Wj0qyRKx2eMg8iZtWvU4E2Q==", + "dependencies": { + "@react-dnd/invariant": "^4.0.1", + "@react-dnd/shallowequal": "^4.0.1", + "dnd-core": "^16.0.1", + "fast-deep-equal": "^3.1.3", + "hoist-non-react-statics": "^3.3.2" + }, + "peerDependencies": { + "@types/hoist-non-react-statics": ">= 3.3.1", + "@types/node": ">= 12", + "@types/react": ">= 16", + "react": ">= 16.14" + }, + "peerDependenciesMeta": { + "@types/hoist-non-react-statics": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-dnd-html5-backend": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/react-dnd-html5-backend/-/react-dnd-html5-backend-16.0.1.tgz", + "integrity": "sha512-Wu3dw5aDJmOGw8WjH1I1/yTH+vlXEL4vmjk5p+MHxP8HuHJS1lAGeIdG/hze1AvNeXWo/JgULV87LyQOr+r5jw==", + "dependencies": { + "dnd-core": "^16.0.1" + } + }, + "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-grid-layout": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/react-grid-layout/-/react-grid-layout-1.3.4.tgz", + "integrity": "sha512-sB3rNhorW77HUdOjB4JkelZTdJGQKuXLl3gNg+BI8gJkTScspL1myfZzW/EM0dLEn+1eH+xW+wNqk0oIM9o7cw==", + "dependencies": { + "clsx": "^1.1.1", + "lodash.isequal": "^4.0.0", + "prop-types": "^15.8.1", + "react-draggable": "^4.0.0", + "react-resizable": "^3.0.4" + }, + "peerDependencies": { + "react": ">= 16.3.0", + "react-dom": ">= 16.3.0" + } + }, + "node_modules/react-icons": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.8.0.tgz", + "integrity": "sha512-N6+kOLcihDiAnj5Czu637waJqSnwlMNROzVZMhfX68V/9bu9qHaMIJC4UdozWoOk57gahFCNHwVvWzm0MTzRjg==", + "peerDependencies": { + "react": "*" + } + }, + "node_modules/react-intersection-observer": { + "version": "9.4.3", + "resolved": "https://registry.npmjs.org/react-intersection-observer/-/react-intersection-observer-9.4.3.tgz", + "integrity": "sha512-WNRqMQvKpupr6MzecAQI0Pj0+JQong307knLP4g/nBex7kYfIaZsPpXaIhKHR+oV8z+goUbH9e10j6lGRnTzlQ==", + "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-masonry-css": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/react-masonry-css/-/react-masonry-css-1.0.16.tgz", + "integrity": "sha512-KSW0hR2VQmltt/qAa3eXOctQDyOu7+ZBevtKgpNDSzT7k5LA/0XntNa9z9HKCdz3QlxmJHglTZ18e4sX4V8zZQ==", + "peerDependencies": { + "react": ">=16.0.0" + } + }, + "node_modules/react-redux": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.0.5.tgz", + "integrity": "sha512-Q2f6fCKxPFpkXt1qNRZdEDLlScsDWyrgSj0mliK59qU6W5gvBiKkdMEG2lJzhd1rCctf0hb6EtePPLZ2e0m1uw==", + "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": { + "@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" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + }, + "redux": { + "optional": true + } + } + }, + "node_modules/react-resizable": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/react-resizable/-/react-resizable-3.0.5.tgz", + "integrity": "sha512-vKpeHhI5OZvYn82kXOs1bC8aOXktGU5AmKAgaZS4F5JPburCtbmDPqE7Pzp+1kN4+Wb81LlF33VpGwWwtXem+w==", + "dependencies": { + "prop-types": "15.x", + "react-draggable": "^4.0.3" + }, + "peerDependencies": { + "react": ">= 16.3" + } + }, + "node_modules/react-resize-detector": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/react-resize-detector/-/react-resize-detector-8.0.4.tgz", + "integrity": "sha512-ln9pMAob8y8mc9UI4aZuuWFiyMqBjnTs/sxe9Vs9dPXUjwCTeKK1FP8I75ufnb/2mEEZXG6wOo/fjMcBRRuAXw==", + "dependencies": { + "lodash": "^4.17.21" + }, + "peerDependencies": { + "react": "^16.0.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-router": { + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.9.0.tgz", + "integrity": "sha512-51lKevGNUHrt6kLuX3e/ihrXoXCa9ixY/nVWRLlob4r/l0f45x3SzBvYJe3ctleLUQQ5fVa4RGgJOTH7D9Umhw==", + "dependencies": { + "@remix-run/router": "1.4.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/react-router-dom": { + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.9.0.tgz", + "integrity": "sha512-/seUAPY01VAuwkGyVBPCn1OXfVbaWGGu4QN9uj0kCPcTyNYgL1ldZpxZUpRU7BLheKQI4Twtl/OW2nHRF1u26Q==", + "dependencies": { + "@remix-run/router": "1.4.0", + "react-router": "6.9.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, + "node_modules/react-toastify": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-9.1.2.tgz", + "integrity": "sha512-PBfzXO5jMGEtdYR5jxrORlNZZe/EuOkwvwKijMatsZZm8IZwLj01YvobeJYNjFcA6uy6CVrx2fzL9GWbhWPTDA==", + "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/react-virtuoso": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/react-virtuoso/-/react-virtuoso-4.3.3.tgz", + "integrity": "sha512-x0DeGmVAVOVaTXRMG7jzrHBwK7+dkt7n0G3tNmZXphQUBgkVBYuZoaJltQeZGFN42++3XvrgwStKCtmzgMJ0lA==", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": ">=16 || >=17 || >= 18", + "react-dom": ">=16 || >=17 || >= 18" + } + }, + "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/reselect": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.7.tgz", + "integrity": "sha512-Zu1xbUt3/OPwsXL46hvOOoQrap2azE7ZQbokq61BQfiXvhewsKDwhMeZjTX9sX0nvw1t/U5Audyn1I9P/m9z0A==" + }, + "node_modules/resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "dependencies": { + "is-core-module": "^2.9.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/rollup": { + "version": "3.19.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.19.1.tgz", + "integrity": "sha512-lAbrdN7neYCg/8WaoWn/ckzCtz+jr70GFfYdlf50OF7387HTg+wiuiqJRFYawwSPpqfqDNYqK7smY/ks2iAudg==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=14.18.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "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" + } + ], + "peer": true + }, + "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/schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/scroll-into-view-if-needed": { + "version": "2.2.31", + "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.31.tgz", + "integrity": "sha512-dGCXy99wZQivjmjIqihaBQNjryrz5rueJY7eHfTdyWEiR4ttYpsajb14rn9s5d4DY4EcY6+4+U/maARBXJedkA==", + "dependencies": { + "compute-scroll-into-view": "^1.0.20" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", + "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", + "dev": true, + "peer": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" + }, + "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/slate": { + "version": "0.91.4", + "resolved": "https://registry.npmjs.org/slate/-/slate-0.91.4.tgz", + "integrity": "sha512-aUJ3rpjrdi5SbJ5G1Qjr3arytfRkEStTmHjBfWq2A2Q8MybacIzkScSvGJjQkdTk3djCK9C9SEOt39sSeZFwTw==", + "dependencies": { + "immer": "^9.0.6", + "is-plain-object": "^5.0.0", + "tiny-warning": "^1.0.3" + } + }, + "node_modules/slate-history": { + "version": "0.86.0", + "resolved": "https://registry.npmjs.org/slate-history/-/slate-history-0.86.0.tgz", + "integrity": "sha512-OxObL9tbhgwvSlnKSCpGIh7wnuaqvOj5jRExGjEyCU2Ke8ctf22HjT+jw7GEi9ttLzNTUmTEU3YIzqKGeqN+og==", + "dependencies": { + "is-plain-object": "^5.0.0" + }, + "peerDependencies": { + "slate": ">=0.65.3" + } + }, + "node_modules/slate-react": { + "version": "0.91.11", + "resolved": "https://registry.npmjs.org/slate-react/-/slate-react-0.91.11.tgz", + "integrity": "sha512-2nS29rc2kuTTJrEUOXGyTkFATmTEw/R9KuUXadUYiz+UVwuFOUMnBKuwJWyuIBOsFipS+06SkIayEf5CKdARRQ==", + "dependencies": { + "@juggle/resize-observer": "^3.4.0", + "@types/is-hotkey": "^0.1.1", + "@types/lodash": "^4.14.149", + "direction": "^1.0.3", + "is-hotkey": "^0.1.6", + "is-plain-object": "^5.0.0", + "lodash": "^4.17.4", + "scroll-into-view-if-needed": "^2.2.20", + "tiny-invariant": "1.0.6" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0", + "slate": ">=0.65.3" + } + }, + "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.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "peer": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/styled-components": { + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-5.3.9.tgz", + "integrity": "sha512-Aj3kb13B75DQBo2oRwRa/APdB5rSmwUfN5exyarpX+x/tlM/rwZA2vVk2vQgVSP6WKaZJHWwiFrzgHt+CLtB4A==", + "dependencies": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/traverse": "^7.4.5", + "@emotion/is-prop-valid": "^1.1.0", + "@emotion/stylis": "^0.8.4", + "@emotion/unitless": "^0.7.4", + "babel-plugin-styled-components": ">= 1.12.0", + "css-to-react-native": "^3.0.0", + "hoist-non-react-statics": "^3.0.0", + "shallowequal": "^1.1.0", + "supports-color": "^5.5.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/styled-components" + }, + "peerDependencies": { + "react": ">= 16.8.0", + "react-dom": ">= 16.8.0", + "react-is": ">= 16.8.0" + } + }, + "node_modules/styled-components/node_modules/@emotion/unitless": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", + "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==" + }, + "node_modules/stylis": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.1.3.tgz", + "integrity": "sha512-GP6WDNWf+o403jrEp9c5jibKavrtLW+/qYGhFxFrG8maXhwTBI7gLLhiBb0o7uFccWN+EOS9aMO6cGHWAO07OA==" + }, + "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/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/terser": { + "version": "5.16.6", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.6.tgz", + "integrity": "sha512-IBZ+ZQIA9sMaXmRZCUMDjNH0D5AQQfdn4WUjHL0+1lF4TP1IHRJbrhb6fNaXWikrYQTSkb7SLxkeXAiy1p7mbg==", + "dev": true, + "peer": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.3.7", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.7.tgz", + "integrity": "sha512-AfKwIktyP7Cu50xNjXF/6Qb5lBNzYaWpU6YfoX3uZicTx0zTy0stDDCsvjDapKsSDvOeWo5MEq4TmdBy2cNoHw==", + "dev": true, + "peer": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.17", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.1", + "terser": "^5.16.5" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/tiny-invariant": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.0.6.tgz", + "integrity": "sha512-FOyLWWVjG+aC0UqG76V53yAWdXfH8bO6FNmyZOuUrzDzK8DI3/JRY25UD7+g49JWM1LXwymsKERB+DzI0dTEQA==" + }, + "node_modules/tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" + }, + "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/toggle-selection": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", + "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==" + }, + "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.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + }, + "node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", + "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "peer": true, + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "browserslist-lint": "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": "4.2.0", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.2.0.tgz", + "integrity": "sha512-AbDTyzzwuKoRtMIRLGNxhLRuv1FpRgdIw+1y6AQG73Q5+vtecmvzKo/yk8X/vrHDpETRTx01ABijqUHIzBXi0g==", + "dev": true, + "dependencies": { + "esbuild": "^0.17.5", + "postcss": "^8.4.21", + "resolve": "^1.22.1", + "rollup": "^3.18.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + }, + "peerDependencies": { + "@types/node": ">= 14", + "less": "*", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/watchpack": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", + "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "dev": true, + "peer": true, + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/wavesurfer.js": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/wavesurfer.js/-/wavesurfer.js-6.6.2.tgz", + "integrity": "sha512-aPAU4OADQsyH8mIw2nXmoni8KHo8s1f1bd5ZUrxhN4P/VMWd+oPDqEwA01XPSEfasAJW6mZ/EHQ2bZ9nOWRrNw==" + }, + "node_modules/webpack": { + "version": "5.76.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.2.tgz", + "integrity": "sha512-Th05ggRm23rVzEOlX8y67NkYCHa9nTNcwHPBhdg+lKG+mtiW7XgggjAeeLnADAe7mLjJ6LUNfgHAuRRh+Z6J7w==", + "dev": true, + "peer": true, + "dependencies": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^0.0.51", + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/wasm-edit": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "acorn": "^8.7.1", + "acorn-import-assertions": "^1.7.6", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.10.0", + "es-module-lexer": "^0.9.0", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.1.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.1.3", + "watchpack": "^2.4.0", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/worker-loader": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/worker-loader/-/worker-loader-3.0.8.tgz", + "integrity": "sha512-XQyQkIFeRVC7f7uRhFdNMe/iJOdO6zxAaR3EWbDp45v3mDhrTi+++oswKNxShUNjPC/1xUp5DB29YKLhFo129g==", + "dev": true, + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "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" + } + } + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "requires": { + "@babel/highlight": "^7.18.6" + } + }, + "@babel/generator": { + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.3.tgz", + "integrity": "sha512-QS3iR1GYC/YGUnW7IdggFeN5c1poPUurnGttOV/bZgPGV+izC/D8HnD6DLwod0fsatNyVn1G3EVWMYIF0nHbeA==", + "requires": { + "@babel/types": "^7.21.3", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", + "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-environment-visitor": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", + "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==" + }, + "@babel/helper-function-name": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz", + "integrity": "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==", + "requires": { + "@babel/template": "^7.20.7", + "@babel/types": "^7.21.0" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", + "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-module-imports": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", + "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", + "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-string-parser": { + "version": "7.19.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", + "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==" + }, + "@babel/helper-validator-identifier": { + "version": "7.19.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", + "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==" + }, + "@babel/highlight": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "requires": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.3.tgz", + "integrity": "sha512-lobG0d7aOfQRXh8AyklEAgZGvA4FShxo6xQbUrrT/cNBPUdIDojlokwJsQyCC/eKia7ifqM0yP+2DRZ4WKw2RQ==" + }, + "@babel/runtime": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz", + "integrity": "sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==", + "requires": { + "regenerator-runtime": "^0.13.11" + } + }, + "@babel/template": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", + "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", + "requires": { + "@babel/code-frame": "^7.18.6", + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7" + } + }, + "@babel/traverse": { + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.3.tgz", + "integrity": "sha512-XLyopNeaTancVitYZe2MlUEvgKb6YVVPXzofHgqHijCImG33b/uTurMS488ht/Hbsb2XK3U2BnSTxKVNGV3nGQ==", + "requires": { + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.21.3", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.21.0", + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/parser": "^7.21.3", + "@babel/types": "^7.21.3", + "debug": "^4.1.0", + "globals": "^11.1.0" + } + }, + "@babel/types": { + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.3.tgz", + "integrity": "sha512-sBGdETxC+/M4o/zKC0sl6sjWv62WFR/uzxrJ6uYyMLZOUlPnwzw0tKgVHOXxaAd5l2g8pEDM5RZ495GPQI77kg==", + "requires": { + "@babel/helper-string-parser": "^7.19.4", + "@babel/helper-validator-identifier": "^7.19.1", + "to-fast-properties": "^2.0.0" + } + }, + "@emotion/babel-plugin": { + "version": "11.10.6", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.10.6.tgz", + "integrity": "sha512-p2dAqtVrkhSa7xz1u/m9eHYdLi+en8NowrmXeF/dKtJpU8lCWli8RUAati7NcSl0afsBott48pdnANuD0wh9QQ==", + "requires": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.0", + "@emotion/memoize": "^0.8.0", + "@emotion/serialize": "^1.1.1", + "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.1.3" + } + }, + "@emotion/cache": { + "version": "11.10.5", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.10.5.tgz", + "integrity": "sha512-dGYHWyzTdmK+f2+EnIGBpkz1lKc4Zbj2KHd4cX3Wi8/OWr5pKslNjc3yABKH4adRGCvSX4VDC0i04mrrq0aiRA==", + "requires": { + "@emotion/memoize": "^0.8.0", + "@emotion/sheet": "^1.2.1", + "@emotion/utils": "^1.2.0", + "@emotion/weak-memoize": "^0.3.0", + "stylis": "4.1.3" + } + }, + "@emotion/hash": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.0.tgz", + "integrity": "sha512-14FtKiHhy2QoPIzdTcvh//8OyBlknNs2nXRwIhG904opCby3l+9Xaf/wuPvICBF0rc1ZCNBd3nKe9cd2mecVkQ==" + }, + "@emotion/is-prop-valid": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.0.tgz", + "integrity": "sha512-3aDpDprjM0AwaxGE09bOPkNxHpBd+kA6jty3RnaEXdweX1DF1U3VQpPYb0g1IStAuK7SVQ1cy+bNBBKp4W3Fjg==", + "requires": { + "@emotion/memoize": "^0.8.0" + } + }, + "@emotion/memoize": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.0.tgz", + "integrity": "sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA==" + }, + "@emotion/react": { + "version": "11.10.6", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.10.6.tgz", + "integrity": "sha512-6HT8jBmcSkfzO7mc+N1L9uwvOnlcGoix8Zn7srt+9ga0MjREo6lRpuVX0kzo6Jp6oTqDhREOFsygN6Ew4fEQbw==", + "requires": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.10.6", + "@emotion/cache": "^11.10.5", + "@emotion/serialize": "^1.1.1", + "@emotion/use-insertion-effect-with-fallbacks": "^1.0.0", + "@emotion/utils": "^1.2.0", + "@emotion/weak-memoize": "^0.3.0", + "hoist-non-react-statics": "^3.3.1" + } + }, + "@emotion/serialize": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.1.tgz", + "integrity": "sha512-Zl/0LFggN7+L1liljxXdsVSVlg6E/Z/olVWpfxUTxOAmi8NU7YoeWeLfi1RmnB2TATHoaWwIBRoL+FvAJiTUQA==", + "requires": { + "@emotion/hash": "^0.9.0", + "@emotion/memoize": "^0.8.0", + "@emotion/unitless": "^0.8.0", + "@emotion/utils": "^1.2.0", + "csstype": "^3.0.2" + } + }, + "@emotion/sheet": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.1.tgz", + "integrity": "sha512-zxRBwl93sHMsOj4zs+OslQKg/uhF38MB+OMKoCrVuS0nyTkqnau+BM3WGEoOptg9Oz45T/aIGs1qbVAsEFo3nA==" + }, + "@emotion/styled": { + "version": "11.10.6", + "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.10.6.tgz", + "integrity": "sha512-OXtBzOmDSJo5Q0AFemHCfl+bUueT8BIcPSxu0EGTpGk6DmI5dnhSzQANm1e1ze0YZL7TDyAyy6s/b/zmGOS3Og==", + "requires": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.10.6", + "@emotion/is-prop-valid": "^1.2.0", + "@emotion/serialize": "^1.1.1", + "@emotion/use-insertion-effect-with-fallbacks": "^1.0.0", + "@emotion/utils": "^1.2.0" + } + }, + "@emotion/stylis": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.8.5.tgz", + "integrity": "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==" + }, + "@emotion/unitless": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.0.tgz", + "integrity": "sha512-VINS5vEYAscRl2ZUDiT3uMPlrFQupiKgHz5AA4bCH1miKBg4qtwkim1qPmJj/4WG6TreYMY111rEFsjupcOKHw==" + }, + "@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.0.tgz", + "integrity": "sha512-1eEgUGmkaljiBnRMTdksDV1W4kUnmwgp7X9G8B++9GYwl1lUdqSndSriIrTJ0N7LQaoauY9JJ2yhiOYK5+NI4A==", + "requires": {} + }, + "@emotion/utils": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.0.tgz", + "integrity": "sha512-sn3WH53Kzpw8oQ5mgMmIzzyAaH2ZqFEbozVVBSYp538E06OSE6ytOp7pRAjNQR+Q/orwqdQYJSe2m3hCOeznkw==" + }, + "@emotion/weak-memoize": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.0.tgz", + "integrity": "sha512-AHPmaAx+RYfZz0eYu6Gviiagpmiyw98ySSlQvCUhVGDRtDFe4DBS0x1bSjdF3gqUDYOczB+yYvBTtEylYSdRhg==" + }, + "@esbuild/android-arm": { + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.11.tgz", + "integrity": "sha512-CdyX6sRVh1NzFCsf5vw3kULwlAhfy9wVt8SZlrhQ7eL2qBjGbFhRBWkkAzuZm9IIEOCKJw4DXA6R85g+qc8RDw==", + "dev": true, + "optional": true + }, + "@esbuild/android-arm64": { + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.11.tgz", + "integrity": "sha512-QnK4d/zhVTuV4/pRM4HUjcsbl43POALU2zvBynmrrqZt9LPcLA3x1fTZPBg2RRguBQnJcnU059yKr+bydkntjg==", + "dev": true, + "optional": true + }, + "@esbuild/android-x64": { + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.11.tgz", + "integrity": "sha512-3PL3HKtsDIXGQcSCKtWD/dy+mgc4p2Tvo2qKgKHj9Yf+eniwFnuoQ0OUhlSfAEpKAFzF9N21Nwgnap6zy3L3MQ==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-arm64": { + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.11.tgz", + "integrity": "sha512-pJ950bNKgzhkGNO3Z9TeHzIFtEyC2GDQL3wxkMApDEghYx5Qers84UTNc1bAxWbRkuJOgmOha5V0WUeh8G+YGw==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-x64": { + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.11.tgz", + "integrity": "sha512-iB0dQkIHXyczK3BZtzw1tqegf0F0Ab5texX2TvMQjiJIWXAfM4FQl7D909YfXWnB92OQz4ivBYQ2RlxBJrMJOw==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-arm64": { + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.11.tgz", + "integrity": "sha512-7EFzUADmI1jCHeDRGKgbnF5sDIceZsQGapoO6dmw7r/ZBEKX7CCDnIz8m9yEclzr7mFsd+DyasHzpjfJnmBB1Q==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-x64": { + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.11.tgz", + "integrity": "sha512-iPgenptC8i8pdvkHQvXJFzc1eVMR7W2lBPrTE6GbhR54sLcF42mk3zBOjKPOodezzuAz/KSu8CPyFSjcBMkE9g==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm": { + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.11.tgz", + "integrity": "sha512-M9iK/d4lgZH0U5M1R2p2gqhPV/7JPJcRz+8O8GBKVgqndTzydQ7B2XGDbxtbvFkvIs53uXTobOhv+RyaqhUiMg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm64": { + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.11.tgz", + "integrity": "sha512-Qxth3gsWWGKz2/qG2d5DsW/57SeA2AmpSMhdg9TSB5Svn2KDob3qxfQSkdnWjSd42kqoxIPy3EJFs+6w1+6Qjg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ia32": { + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.11.tgz", + "integrity": "sha512-dB1nGaVWtUlb/rRDHmuDQhfqazWE0LMro/AIbT2lWM3CDMHJNpLckH+gCddQyhhcLac2OYw69ikUMO34JLt3wA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-loong64": { + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.11.tgz", + "integrity": "sha512-aCWlq70Q7Nc9WDnormntGS1ar6ZFvUpqr8gXtO+HRejRYPweAFQN615PcgaSJkZjhHp61+MNLhzyVALSF2/Q0g==", + "dev": true, + "optional": true + }, + "@esbuild/linux-mips64el": { + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.11.tgz", + "integrity": "sha512-cGeGNdQxqY8qJwlYH1BP6rjIIiEcrM05H7k3tR7WxOLmD1ZxRMd6/QIOWMb8mD2s2YJFNRuNQ+wjMhgEL2oCEw==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ppc64": { + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.11.tgz", + "integrity": "sha512-BdlziJQPW/bNe0E8eYsHB40mYOluS+jULPCjlWiHzDgr+ZBRXPtgMV1nkLEGdpjrwgmtkZHEGEPaKdS/8faLDA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-riscv64": { + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.11.tgz", + "integrity": "sha512-MDLwQbtF+83oJCI1Cixn68Et/ME6gelmhssPebC40RdJaect+IM+l7o/CuG0ZlDs6tZTEIoxUe53H3GmMn8oMA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-s390x": { + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.11.tgz", + "integrity": "sha512-4N5EMESvws0Ozr2J94VoUD8HIRi7X0uvUv4c0wpTHZyZY9qpaaN7THjosdiW56irQ4qnJ6Lsc+i+5zGWnyqWqQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-x64": { + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.11.tgz", + "integrity": "sha512-rM/v8UlluxpytFSmVdbCe1yyKQd/e+FmIJE2oPJvbBo+D0XVWi1y/NQ4iTNx+436WmDHQBjVLrbnAQLQ6U7wlw==", + "dev": true, + "optional": true + }, + "@esbuild/netbsd-x64": { + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.11.tgz", + "integrity": "sha512-4WaAhuz5f91h3/g43VBGdto1Q+X7VEZfpcWGtOFXnggEuLvjV+cP6DyLRU15IjiU9fKLLk41OoJfBFN5DhPvag==", + "dev": true, + "optional": true + }, + "@esbuild/openbsd-x64": { + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.11.tgz", + "integrity": "sha512-UBj135Nx4FpnvtE+C8TWGp98oUgBcmNmdYgl5ToKc0mBHxVVqVE7FUS5/ELMImOp205qDAittL6Ezhasc2Ev/w==", + "dev": true, + "optional": true + }, + "@esbuild/sunos-x64": { + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.11.tgz", + "integrity": "sha512-1/gxTifDC9aXbV2xOfCbOceh5AlIidUrPsMpivgzo8P8zUtczlq1ncFpeN1ZyQJ9lVs2hILy1PG5KPp+w8QPPg==", + "dev": true, + "optional": true + }, + "@esbuild/win32-arm64": { + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.11.tgz", + "integrity": "sha512-vtSfyx5yRdpiOW9yp6Ax0zyNOv9HjOAw8WaZg3dF5djEHKKm3UnoohftVvIJtRh0Ec7Hso0RIdTqZvPXJ7FdvQ==", + "dev": true, + "optional": true + }, + "@esbuild/win32-ia32": { + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.11.tgz", + "integrity": "sha512-GFPSLEGQr4wHFTiIUJQrnJKZhZjjq4Sphf+mM76nQR6WkQn73vm7IsacmBRPkALfpOCHsopSvLgqdd4iUW2mYw==", + "dev": true, + "optional": true + }, + "@esbuild/win32-x64": { + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.11.tgz", + "integrity": "sha512-N9vXqLP3eRL8BqSy8yn4Y98cZI2pZ8fyuHx6lKjiG2WABpT2l01TXdzq5Ma2ZUBzfB7tx5dXVhge8X9u0S70ZQ==", + "dev": true, + "optional": true + }, + "@formatjs/ecma402-abstract": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.14.3.tgz", + "integrity": "sha512-SlsbRC/RX+/zg4AApWIFNDdkLtFbkq3LNoZWXZCE/nHVKqoIJyaoQyge/I0Y38vLxowUn9KTtXgusLD91+orbg==", + "requires": { + "@formatjs/intl-localematcher": "0.2.32", + "tslib": "^2.4.0" + } + }, + "@formatjs/fast-memoize": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-2.0.1.tgz", + "integrity": "sha512-M2GgV+qJn5WJQAYewz7q2Cdl6fobQa69S1AzSM2y0P68ZDbK5cWrJIcPCO395Of1ksftGZoOt4LYCO/j9BKBSA==", + "requires": { + "tslib": "^2.4.0" + } + }, + "@formatjs/icu-messageformat-parser": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.3.0.tgz", + "integrity": "sha512-xqtlqYAbfJDF4b6e4O828LBNOWXrFcuYadqAbYORlDRwhyJ2bH+xpUBPldZbzRGUN2mxlZ4Ykhm7jvERtmI8NQ==", + "requires": { + "@formatjs/ecma402-abstract": "1.14.3", + "@formatjs/icu-skeleton-parser": "1.3.18", + "tslib": "^2.4.0" + } + }, + "@formatjs/icu-skeleton-parser": { + "version": "1.3.18", + "resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.3.18.tgz", + "integrity": "sha512-ND1ZkZfmLPcHjAH1sVpkpQxA+QYfOX3py3SjKWMUVGDow18gZ0WPqz3F+pJLYQMpS2LnnQ5zYR2jPVYTbRwMpg==", + "requires": { + "@formatjs/ecma402-abstract": "1.14.3", + "tslib": "^2.4.0" + } + }, + "@formatjs/intl-localematcher": { + "version": "0.2.32", + "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.2.32.tgz", + "integrity": "sha512-k/MEBstff4sttohyEpXxCmC3MqbUn9VvHGlZ8fauLzkbwXmVrEeyzS+4uhrvAk9DWU9/7otYWxyDox4nT/KVLQ==", + "requires": { + "tslib": "^2.4.0" + } + }, + "@internationalized/date": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@internationalized/date/-/date-3.1.0.tgz", + "integrity": "sha512-wjeur7K4AecT+YwoBmBXQ/+n5lP69tuZc34hw09s44EozZK7FZHSyfPvRp5/xEb2D6abLboskDY4jG+Nt0TNUQ==", + "requires": { + "@swc/helpers": "^0.4.14" + } + }, + "@internationalized/message": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@internationalized/message/-/message-3.1.0.tgz", + "integrity": "sha512-Oo5m70FcBdADf7G8NkUffVSfuCdeAYVfsvNjZDi9ELpjvkc4YNJVTHt/NyTI9K7FgAVoELxiP9YmN0sJ+HNHYQ==", + "requires": { + "@swc/helpers": "^0.4.14", + "intl-messageformat": "^10.1.0" + } + }, + "@internationalized/number": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@internationalized/number/-/number-3.2.0.tgz", + "integrity": "sha512-GUXkhXSX1Ee2RURnzl+47uvbOxnlMnvP9Er+QePTjDjOPWuunmLKlEkYkEcLiiJp7y4l9QxGDLOlVr8m69LS5w==", + "requires": { + "@swc/helpers": "^0.4.14" + } + }, + "@internationalized/string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@internationalized/string/-/string-3.1.0.tgz", + "integrity": "sha512-TJQKiyUb+wyAfKF59UNeZ/kELMnkxyecnyPCnBI1ma4NaXReJW+7Cc2mObXAqraIBJUVv7rgI46RLKrLgi35ng==", + "requires": { + "@swc/helpers": "^0.4.14" + } + }, + "@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "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==" + }, + "@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==" + }, + "@jridgewell/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "dev": true, + "peer": true, + "requires": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@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==" + }, + "@jridgewell/trace-mapping": { + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", + "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", + "requires": { + "@jridgewell/resolve-uri": "3.1.0", + "@jridgewell/sourcemap-codec": "1.4.14" + } + }, + "@juggle/resize-observer": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@juggle/resize-observer/-/resize-observer-3.4.0.tgz", + "integrity": "sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==" + }, + "@mui/base": { + "version": "5.0.0-alpha.121", + "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.121.tgz", + "integrity": "sha512-8nJRY76UqlJV+q/Yzo0tgGfPWEOa+4N9rjO81fMmcJqP0I6m54hLDXsjvMg4tvelY5eKHXUK6Tb7en+GHfTqZA==", + "requires": { + "@babel/runtime": "^7.21.0", + "@emotion/is-prop-valid": "^1.2.0", + "@mui/types": "^7.2.3", + "@mui/utils": "^5.11.13", + "@popperjs/core": "^2.11.6", + "clsx": "^1.2.1", + "prop-types": "^15.8.1", + "react-is": "^18.2.0" + } + }, + "@mui/core-downloads-tracker": { + "version": "5.11.13", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.11.13.tgz", + "integrity": "sha512-lx+GXBR9h/ApZsEP728tl0pyZyuajto+VnBgsoAzw1d5+CbmOo8ZWieKwVUGxZlPT1wMYNUYS5NtKzCli0xYjw==" + }, + "@mui/icons-material": { + "version": "5.11.11", + "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.11.11.tgz", + "integrity": "sha512-Eell3ADmQVE8HOpt/LZ3zIma8JSvPh3XgnhwZLT0k5HRqZcd6F/QDHc7xsWtgz09t+UEFvOYJXjtrwKmLdwwpw==", + "requires": { + "@babel/runtime": "^7.21.0" + } + }, + "@mui/material": { + "version": "5.11.13", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.11.13.tgz", + "integrity": "sha512-2CnSj43F+159LbGmTLLQs5xbGYMiYlpTByQhP7c7cMX6opbScctBFE1PuyElpAmwW8Ag9ysfZH1d1MFAmJQkjg==", + "requires": { + "@babel/runtime": "^7.21.0", + "@mui/base": "5.0.0-alpha.121", + "@mui/core-downloads-tracker": "^5.11.13", + "@mui/system": "^5.11.13", + "@mui/types": "^7.2.3", + "@mui/utils": "^5.11.13", + "@types/react-transition-group": "^4.4.5", + "clsx": "^1.2.1", + "csstype": "^3.1.1", + "prop-types": "^15.8.1", + "react-is": "^18.2.0", + "react-transition-group": "^4.4.5" + } + }, + "@mui/private-theming": { + "version": "5.11.13", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.11.13.tgz", + "integrity": "sha512-PJnYNKzW5LIx3R+Zsp6WZVPs6w5sEKJ7mgLNnUXuYB1zo5aX71FVLtV7geyPXRcaN2tsoRNK7h444ED0t7cIjA==", + "requires": { + "@babel/runtime": "^7.21.0", + "@mui/utils": "^5.11.13", + "prop-types": "^15.8.1" + } + }, + "@mui/styled-engine": { + "version": "5.11.11", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.11.11.tgz", + "integrity": "sha512-wV0UgW4lN5FkDBXefN8eTYeuE9sjyQdg5h94vtwZCUamGQEzmCOtir4AakgmbWMy0x8OLjdEUESn9wnf5J9MOg==", + "requires": { + "@babel/runtime": "^7.21.0", + "@emotion/cache": "^11.10.5", + "csstype": "^3.1.1", + "prop-types": "^15.8.1" + } + }, + "@mui/system": { + "version": "5.11.13", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.11.13.tgz", + "integrity": "sha512-OWP0Alp6C8ufnGm9+CZcl3d+OoRXL2PnrRT5ohaMLxvGL9OfNcL2t4JOjMmA0k1UAGd6E/Ygbu5lEPrZSDlvCg==", + "requires": { + "@babel/runtime": "^7.21.0", + "@mui/private-theming": "^5.11.13", + "@mui/styled-engine": "^5.11.11", + "@mui/types": "^7.2.3", + "@mui/utils": "^5.11.13", + "clsx": "^1.2.1", + "csstype": "^3.1.1", + "prop-types": "^15.8.1" + } + }, + "@mui/types": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.3.tgz", + "integrity": "sha512-tZ+CQggbe9Ol7e/Fs5RcKwg/woU+o8DCtOnccX6KmbBc7YrfqMYEYuaIcXHuhpT880QwNkZZ3wQwvtlDFA2yOw==", + "requires": {} + }, + "@mui/utils": { + "version": "5.11.13", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.11.13.tgz", + "integrity": "sha512-5ltA58MM9euOuUcnvwFJqpLdEugc9XFsRR8Gt4zZNb31XzMfSKJPR4eumulyhsOTK1rWf7K4D63NKFPfX0AxqA==", + "requires": { + "@babel/runtime": "^7.21.0", + "@types/prop-types": "^15.7.5", + "@types/react-is": "^16.7.1 || ^17.0.0", + "prop-types": "^15.8.1", + "react-is": "^18.2.0" + } + }, + "@popperjs/core": { + "version": "2.11.6", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz", + "integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==" + }, + "@react-aria/focus": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.11.0.tgz", + "integrity": "sha512-yPuWs9bAR9CMfIwyOPm2oXLPF19gNkUqW+ozSPhWbLMTEa8Ma09eHW1br4xbN+4ONOm/dCJsIkxTNPUkiLdQoA==", + "requires": { + "@react-aria/interactions": "^3.14.0", + "@react-aria/utils": "^3.15.0", + "@react-types/shared": "^3.17.0", + "@swc/helpers": "^0.4.14", + "clsx": "^1.1.1" + } + }, + "@react-aria/i18n": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@react-aria/i18n/-/i18n-3.7.0.tgz", + "integrity": "sha512-PZCWmhO9mJvelwiYlsXLY6W4L2o+oza3xnDx0cZDVqp/Hf+OwMAPHWtZsFRTKdjk4TaOPB/ISc9HknWn6UpY4w==", + "requires": { + "@internationalized/date": "^3.1.0", + "@internationalized/message": "^3.1.0", + "@internationalized/number": "^3.2.0", + "@internationalized/string": "^3.1.0", + "@react-aria/ssr": "^3.5.0", + "@react-aria/utils": "^3.15.0", + "@react-types/shared": "^3.17.0", + "@swc/helpers": "^0.4.14" + } + }, + "@react-aria/interactions": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.14.0.tgz", + "integrity": "sha512-e1Tkr0UTuYFpV21PJrXy7jEY542Vl+C2Fo70oukZ1fN+wtfQkzodsTIzyepXb7kVMGmC34wDisMJUrksVkfY2w==", + "requires": { + "@react-aria/utils": "^3.15.0", + "@react-types/shared": "^3.17.0", + "@swc/helpers": "^0.4.14" + } + }, + "@react-aria/overlays": { + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/@react-aria/overlays/-/overlays-3.13.0.tgz", + "integrity": "sha512-hRZyhAYzrlCcEWQ2k2jP24b0wc5/355Xl5w5FZHRmPeU1U4XlFwKX/eFlBs/li9Sprm1bTDXrCY480Kl6UsKDA==", + "requires": { + "@react-aria/focus": "^3.11.0", + "@react-aria/i18n": "^3.7.0", + "@react-aria/interactions": "^3.14.0", + "@react-aria/ssr": "^3.5.0", + "@react-aria/utils": "^3.15.0", + "@react-aria/visually-hidden": "^3.7.0", + "@react-stately/overlays": "^3.5.0", + "@react-types/button": "^3.7.1", + "@react-types/overlays": "^3.7.0", + "@react-types/shared": "^3.17.0", + "@swc/helpers": "^0.4.14" + } + }, + "@react-aria/ssr": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.5.0.tgz", + "integrity": "sha512-h0MJdSWOd1qObLnJ8mprU31wI8tmKFJMuwT22MpWq6psisOOZaga6Ml4u6Ee6M6duWWISjXvqO4Sb/J0PBA+nQ==", + "requires": { + "@swc/helpers": "^0.4.14" + } + }, + "@react-aria/utils": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.15.0.tgz", + "integrity": "sha512-aJZBG++iz1UwTW5gXFaHicKju4p0MPhAyBTcf2awHYWeTUUslDjJcEnNg7kjBYZBOrOSlA2rAt7/7C5CCURQPg==", + "requires": { + "@react-aria/ssr": "^3.5.0", + "@react-stately/utils": "^3.6.0", + "@react-types/shared": "^3.17.0", + "@swc/helpers": "^0.4.14", + "clsx": "^1.1.1" + } + }, + "@react-aria/visually-hidden": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@react-aria/visually-hidden/-/visually-hidden-3.7.0.tgz", + "integrity": "sha512-v/0ujJ67H6LjwY8J7mIGPVB1K8suBArLV+w8UGdX/wFXRL7H4r2fiqlrwAElWSmNbhDQl5BDm/Zh/ub9jB9yzA==", + "requires": { + "@react-aria/interactions": "^3.14.0", + "@react-aria/utils": "^3.15.0", + "@react-types/shared": "^3.17.0", + "@swc/helpers": "^0.4.14", + "clsx": "^1.1.1" + } + }, + "@react-dnd/asap": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@react-dnd/asap/-/asap-5.0.2.tgz", + "integrity": "sha512-WLyfoHvxhs0V9U+GTsGilGgf2QsPl6ZZ44fnv0/b8T3nQyvzxidxsg/ZltbWssbsRDlYW8UKSQMTGotuTotZ6A==" + }, + "@react-dnd/invariant": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@react-dnd/invariant/-/invariant-4.0.2.tgz", + "integrity": "sha512-xKCTqAK/FFauOM9Ta2pswIyT3D8AQlfrYdOi/toTPEhqCuAs1v5tcJ3Y08Izh1cJ5Jchwy9SeAXmMg6zrKs2iw==" + }, + "@react-dnd/shallowequal": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@react-dnd/shallowequal/-/shallowequal-4.0.2.tgz", + "integrity": "sha512-/RVXdLvJxLg4QKvMoM5WlwNR9ViO9z8B/qPcc+C0Sa/teJY7QG7kJ441DwzOjMYEY7GmU4dj5EcGHIkKZiQZCA==" + }, + "@react-spectrum/layout": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/@react-spectrum/layout/-/layout-3.5.0.tgz", + "integrity": "sha512-Yjy0uvGUHjczl44PQlMqOEBoJIe4coYwDQCoVl20YrTzGiMdwLV24Hs9uqK3I6yKmAoNxTehe0CdOVgwuVRF9g==", + "requires": { + "@react-aria/ssr": "^3.5.0", + "@react-aria/utils": "^3.15.0", + "@react-spectrum/utils": "^3.9.0", + "@react-types/layout": "^3.3.6", + "@react-types/shared": "^3.17.0", + "@swc/helpers": "^0.4.14", + "clsx": "^1.1.1" + } + }, + "@react-spectrum/provider": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@react-spectrum/provider/-/provider-3.7.0.tgz", + "integrity": "sha512-6Uch60R5PKJC+ZY3VweVadaCoaIj6Nd85TKfFH4jf8NEzXv5CqjwUzwV5aQ6u3k1K24Ves7RpLlK53HW1wUm6w==", + "requires": { + "@react-aria/i18n": "^3.7.0", + "@react-aria/overlays": "^3.13.0", + "@react-aria/utils": "^3.15.0", + "@react-spectrum/utils": "^3.9.0", + "@react-types/provider": "^3.6.0", + "@react-types/shared": "^3.17.0", + "@swc/helpers": "^0.4.14", + "clsx": "^1.1.1" + } + }, + "@react-spectrum/theme-default": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/@react-spectrum/theme-default/-/theme-default-3.5.0.tgz", + "integrity": "sha512-DagwngJ9T7yGgtdTwKj9LaHbg3AWLW2/ILJK92xbPj/yAAEVXJ8vhiP9Tg3W3mZMsxBCNwTVLyOLheu7d+D8og==", + "requires": { + "@react-types/provider": "^3.6.0", + "@swc/helpers": "^0.4.14" + } + }, + "@react-spectrum/utils": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/@react-spectrum/utils/-/utils-3.9.0.tgz", + "integrity": "sha512-I1JKwiyLE54mAT7Z2wadVKoai1Q60QFg4XNuYUwk8TwWAEz7DUUHucntHAND6dqFpVIMK1Rk9lcZBft43FF2BQ==", + "requires": { + "@react-aria/i18n": "^3.7.0", + "@react-aria/ssr": "^3.5.0", + "@react-aria/utils": "^3.15.0", + "@react-types/shared": "^3.17.0", + "@swc/helpers": "^0.4.14", + "clsx": "^1.1.1" + } + }, + "@react-spectrum/view": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/@react-spectrum/view/-/view-3.5.0.tgz", + "integrity": "sha512-Zzsy2S6gT14vtli52tjM5VP1EdMOP+bppNCmwX+saUJuxaEdj6oYjP89quE4HwALzYceOfmXIuGDyEVeDcuSsQ==", + "requires": { + "@react-aria/i18n": "^3.7.0", + "@react-aria/utils": "^3.15.0", + "@react-spectrum/utils": "^3.9.0", + "@react-types/shared": "^3.17.0", + "@react-types/view": "^3.4.0", + "@swc/helpers": "^0.4.14" + } + }, + "@react-stately/overlays": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/@react-stately/overlays/-/overlays-3.5.0.tgz", + "integrity": "sha512-r+U/G0Y4tCfI5wyBeIu+hmcZVRN8ChoK2zM1srPH9nDKsijQard2goX+9YmKng2LJ01Re/P6F8S8jYbpfEdLfQ==", + "requires": { + "@react-stately/utils": "^3.6.0", + "@react-types/overlays": "^3.7.0", + "@swc/helpers": "^0.4.14" + } + }, + "@react-stately/utils": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@react-stately/utils/-/utils-3.6.0.tgz", + "integrity": "sha512-rptF7iUWDrquaYvBAS4QQhOBQyLBncDeHF03WnHXAxnuPJXNcr9cXJtjJPGCs036ZB8Q2hc9BGG5wNyMkF5v+Q==", + "requires": { + "@swc/helpers": "^0.4.14" + } + }, + "@react-types/button": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/@react-types/button/-/button-3.7.1.tgz", + "integrity": "sha512-c+8xjmqWSjI5/mEHVLbVSp0eh/z2UU8Ga+wqjbEUZUjm8uopYj1PaCAwZ7YgcAebyQrL/21GyjK6tFHKzuUdJQ==", + "requires": { + "@react-types/shared": "^3.17.0" + } + }, + "@react-types/layout": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/@react-types/layout/-/layout-3.3.6.tgz", + "integrity": "sha512-8YF7nb+0AtSDRj+rejMRS5djWpqAf5Q6sJzgdccn42JQxW7jvxoKqN0pCRPqpMzQqae5hOsYYpVNfuIHwUUkUA==", + "requires": { + "@react-types/shared": "^3.17.0" + } + }, + "@react-types/overlays": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@react-types/overlays/-/overlays-3.7.0.tgz", + "integrity": "sha512-LstucncZ8dM+xJYEijI1V6jGH20w5XO/T60r7JTrgQElMC86phPeoWkMTN4c2lsRikybolDbvXL6XsF76YO56A==", + "requires": { + "@react-types/shared": "^3.17.0" + } + }, + "@react-types/provider": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@react-types/provider/-/provider-3.6.0.tgz", + "integrity": "sha512-29+X5yMr1uHUc/BmFoyBqfWyMT3YGZJffaprtGGRQkCuwMbqoA8GI+rGJzNAMAD/1cPNo237PAGsi4NAup5tAQ==", + "requires": { + "@react-types/shared": "^3.17.0" + } + }, + "@react-types/shared": { + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.17.0.tgz", + "integrity": "sha512-1SNZ/RhVrrQ1e6yE0bPV7d5Sfp+Uv0dfUEhwF9MAu2v5msu7AMewnsiojKNA0QA6Ing1gpDLjHCxtayQfuxqcg==", + "requires": {} + }, + "@react-types/view": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@react-types/view/-/view-3.4.0.tgz", + "integrity": "sha512-lXDLbOYRFwo8hxrSDIYUmnxOGZlHBDVEFe1ZKAXJ+qPwntzxhzUeAuddTiMDhEETKgTclmlIsJnwz+HNv6dhSQ==", + "requires": { + "@react-types/shared": "^3.17.0" + } + }, + "@reduxjs/toolkit": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.3.tgz", + "integrity": "sha512-GU2TNBQVofL09VGmuSioNPQIu6Ml0YLf4EJhgj0AvBadRlCGzUWet8372LjvO4fqKZF2vH1xU0htAa7BrK9pZg==", + "requires": { + "immer": "^9.0.16", + "redux": "^4.2.0", + "redux-thunk": "^2.4.2", + "reselect": "^4.1.7" + } + }, + "@remix-run/router": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.4.0.tgz", + "integrity": "sha512-BJ9SxXux8zAg991UmT8slpwpsd31K1dHHbD3Ba4VzD+liLQ4WAMSxQp2d2ZPRPfN0jN2NPRowcSSoM7lCaF08Q==" + }, + "@swc/core": { + "version": "1.3.41", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.3.41.tgz", + "integrity": "sha512-v6P2dfqJDpZ/7RXPvWge9oI6YgolDM0jtNhQZ2qdXrLBzaWQdDoBGBTJ8KN/nTgGhX3IkNvSB1fafXQ+nVnqAQ==", + "dev": true, + "requires": { + "@swc/core-darwin-arm64": "1.3.41", + "@swc/core-darwin-x64": "1.3.41", + "@swc/core-linux-arm-gnueabihf": "1.3.41", + "@swc/core-linux-arm64-gnu": "1.3.41", + "@swc/core-linux-arm64-musl": "1.3.41", + "@swc/core-linux-x64-gnu": "1.3.41", + "@swc/core-linux-x64-musl": "1.3.41", + "@swc/core-win32-arm64-msvc": "1.3.41", + "@swc/core-win32-ia32-msvc": "1.3.41", + "@swc/core-win32-x64-msvc": "1.3.41" + } + }, + "@swc/core-darwin-arm64": { + "version": "1.3.41", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.41.tgz", + "integrity": "sha512-D4fybODToO/BvuP35bionDUrSuTVVr8eW+mApr1unOqb3mfiqOrVv0VP2fpWNRYiA+xMq+oBCB6KcGpL60HKWQ==", + "dev": true, + "optional": true + }, + "@swc/core-darwin-x64": { + "version": "1.3.41", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.3.41.tgz", + "integrity": "sha512-0RoVyiPCnylf3TG77C3S86PRSmaq+SaYB4VDLJFz3qcEHz1pfP0LhyskhgX4wjQV1mveDzFEn1BVAuo0eOMwZA==", + "dev": true, + "optional": true + }, + "@swc/core-linux-arm-gnueabihf": { + "version": "1.3.41", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.3.41.tgz", + "integrity": "sha512-mZW7GeY7Uw1nkKoWpx898ou20oCSt8MR+jAVuAhMjX+G4Zr0WWXYSigWNiRymhR6Q9KhyvoFpMckguSvYWmXsw==", + "dev": true, + "optional": true + }, + "@swc/core-linux-arm64-gnu": { + "version": "1.3.41", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.41.tgz", + "integrity": "sha512-e91LGn+6KuLFw3sWk5swwGc/dP4tXs0mg3HrhjImRoofU02Bb9aHcj5zgrSO8ZByvDtm/Knn16h1ojxIMOFaxg==", + "dev": true, + "optional": true + }, + "@swc/core-linux-arm64-musl": { + "version": "1.3.41", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.41.tgz", + "integrity": "sha512-Q7hmrniLWsQ7zjtImGcjx1tl5/Qxpel+fC+OXTnGvAyyoGssSftIBlXMnqVLteL78zhxIPAzi+gizWAe5RGqrA==", + "dev": true, + "optional": true + }, + "@swc/core-linux-x64-gnu": { + "version": "1.3.41", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.41.tgz", + "integrity": "sha512-h4sv1sCfZQgRIwmykz8WPqVpbvHb13Qm3SsrbOudhAp2MuzpWzsgMP5hAEpdCP/nWreiCz3aoM6L8JeakRDq0g==", + "dev": true, + "optional": true + }, + "@swc/core-linux-x64-musl": { + "version": "1.3.41", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.41.tgz", + "integrity": "sha512-Z7c26i38378d0NT/dcz8qPSAXm41lqhNzykdhKhI+95mA9m4pskP18T/0I45rmyx1ywifypu+Ip+SXmKeVSPgQ==", + "dev": true, + "optional": true + }, + "@swc/core-win32-arm64-msvc": { + "version": "1.3.41", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.41.tgz", + "integrity": "sha512-I0CYnPc+ZGc912YeN0TykIOf/Q7yJQHRwDuhewwD6RkbiSEaVfSux5pAmmdoKw2aGMSq+cwLmgPe9HYLRNz+4w==", + "dev": true, + "optional": true + }, + "@swc/core-win32-ia32-msvc": { + "version": "1.3.41", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.41.tgz", + "integrity": "sha512-EygN4CVDWF29/U2T5fXGfWyLvRbMd2hiUgkciAl7zHuyJ6nKl+kpodqV2A0Wd4sFtSNedU0gQEBEXEe7cqvmsA==", + "dev": true, + "optional": true + }, + "@swc/core-win32-x64-msvc": { + "version": "1.3.41", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.41.tgz", + "integrity": "sha512-Mfp8qD1hNwWWRy0ISdwQJu1g0UYoVTtuQlO0z3aGbXqL51ew9e56+8j3M1U9i95lXFyWkARgjDCcKkQi+WezyA==", + "dev": true, + "optional": true + }, + "@swc/helpers": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.14.tgz", + "integrity": "sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw==", + "requires": { + "tslib": "^2.4.0" + } + }, + "@types/eslint": { + "version": "8.21.3", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.21.3.tgz", + "integrity": "sha512-fa7GkppZVEByMWGbTtE5MbmXWJTVbrjjaS8K6uQj+XtuuUv1fsuPAxhygfqLmsb/Ufb3CV8deFCpiMfAgi00Sw==", + "dev": true, + "peer": true, + "requires": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "@types/eslint-scope": { + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", + "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", + "dev": true, + "peer": true, + "requires": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "@types/estree": { + "version": "0.0.51", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", + "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", + "dev": true, + "peer": 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/is-hotkey": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/@types/is-hotkey/-/is-hotkey-0.1.7.tgz", + "integrity": "sha512-yB5C7zcOM7idwYZZ1wKQ3pTfjA9BbvFqRWvKB46GFddxnJtHwi/b9y84ykQtxQPg5qhdpg4Q/kWU3EGoCTmLzQ==" + }, + "@types/json-schema": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", + "dev": true + }, + "@types/lodash": { + "version": "4.14.191", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.191.tgz", + "integrity": "sha512-BdZ5BCCvho3EIXw6wUCXHe7rS53AIDPLE+JzwgT+OsJk53oBfbSmZZ7CX4VaRoN78N+TJpFi9QPlfIVNmJYWxQ==" + }, + "@types/node": { + "version": "18.15.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.5.tgz", + "integrity": "sha512-Ark2WDjjZO7GmvsyFFf81MXuGTA/d6oP38anyxWOL6EREyBKAxKoFHwBhaZxCfLRLpO8JgVXwqOwSwa7jRcjew==", + "devOptional": true, + "peer": 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/react": { + "version": "18.0.28", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.28.tgz", + "integrity": "sha512-RD0ivG1kEztNBdoAK7lekI9M+azSnitIn85h4iOiaLjaTrMjzslhaqCGaI4IyCJ1RljWiLCEu4jyrLLgqxBTew==", + "requires": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "@types/react-copy-to-clipboard": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/react-copy-to-clipboard/-/react-copy-to-clipboard-5.0.4.tgz", + "integrity": "sha512-otTJsJpofYAeaIeOwV5xBUGpo6exXG2HX7X4nseToCB2VgPEBxGBHCm/FecZ676doNR7HCSTVtmohxfG2b3/yQ==", + "dev": true, + "requires": { + "@types/react": "*" + } + }, + "@types/react-dom": { + "version": "18.0.11", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.11.tgz", + "integrity": "sha512-O38bPbI2CWtgw/OoQoY+BRelw7uysmXbWvw3nLWO21H1HSh+GOlqPuXshJfjmpNlKiiSDG9cc1JZAaMmVdcTlw==", + "devOptional": true, + "requires": { + "@types/react": "*" + } + }, + "@types/react-grid-layout": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/react-grid-layout/-/react-grid-layout-1.3.2.tgz", + "integrity": "sha512-ZzpBEOC1JTQ7MGe1h1cPKSLP4jSWuxc+yvT4TsAlEW9+EFPzAf8nxQfFd7ea9gL17Em7PbwJZAsiwfQQBUklZQ==", + "requires": { + "@types/react": "*" + } + }, + "@types/react-is": { + "version": "17.0.3", + "resolved": "https://registry.npmjs.org/@types/react-is/-/react-is-17.0.3.tgz", + "integrity": "sha512-aBTIWg1emtu95bLTLx0cpkxwGW3ueZv71nE2YFBpL8k/z5czEW8yYpOo8Dp+UUAFAtKwNaOsh/ioSeQnWlZcfw==", + "requires": { + "@types/react": "*" + } + }, + "@types/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-juKD/eiSM3/xZYzjuzH6ZwpP+/lejltmiS3QEzV/vmb/Q8+HfDmxu+Baga8UEMGBqV88Nbg4l2hY/K2DkyaLLA==", + "requires": { + "@types/react": "*" + } + }, + "@types/scheduler": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", + "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==" + }, + "@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==" + }, + "@vitejs/plugin-react-swc": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react-swc/-/plugin-react-swc-3.2.0.tgz", + "integrity": "sha512-IcBoXL/mcH7JdQr/nfDlDwTdIaH8Rg7LpfQDF4nAht+juHWIuv6WhpKPCSfY4+zztAaB07qdBoFz1XCZsgo3pQ==", + "dev": true, + "requires": { + "@swc/core": "^1.3.35" + } + }, + "@webassemblyjs/ast": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", + "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", + "dev": true, + "peer": true, + "requires": { + "@webassemblyjs/helper-numbers": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", + "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", + "dev": true, + "peer": true + }, + "@webassemblyjs/helper-api-error": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", + "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", + "dev": true, + "peer": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", + "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", + "dev": true, + "peer": true + }, + "@webassemblyjs/helper-numbers": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", + "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", + "dev": true, + "peer": true, + "requires": { + "@webassemblyjs/floating-point-hex-parser": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", + "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", + "dev": true, + "peer": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", + "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", + "dev": true, + "peer": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", + "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", + "dev": true, + "peer": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", + "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", + "dev": true, + "peer": true, + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", + "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", + "dev": true, + "peer": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", + "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", + "dev": true, + "peer": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/helper-wasm-section": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-opt": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "@webassemblyjs/wast-printer": "1.11.1" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", + "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", + "dev": true, + "peer": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", + "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", + "dev": true, + "peer": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", + "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", + "dev": true, + "peer": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", + "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", + "dev": true, + "peer": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true, + "peer": true + }, + "@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true, + "peer": true + }, + "acorn": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "dev": true, + "peer": true + }, + "acorn-import-assertions": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", + "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", + "dev": true, + "peer": 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" + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "requires": {} + }, + "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" + } + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "attr-accept": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/attr-accept/-/attr-accept-2.2.2.tgz", + "integrity": "sha512-7prDjvt9HmqiZ0cl5CRjtS84sEyhsHP2coDkaZKRKVfCDo9s7iw7ChVmar78Gu9pC4SoR/28wFu/G5JJhTnqEg==" + }, + "axios": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.4.tgz", + "integrity": "sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==", + "requires": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "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" + } + }, + "babel-plugin-styled-components": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-2.0.7.tgz", + "integrity": "sha512-i7YhvPgVqRKfoQ66toiZ06jPNA3p6ierpfUuEWxNF+fV27Uv5gxBkf8KZLHUCc1nFA9j6+80pYoIpqCeyW3/bA==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.16.0", + "@babel/helper-module-imports": "^7.16.0", + "babel-plugin-syntax-jsx": "^6.18.0", + "lodash": "^4.17.11", + "picomatch": "^2.3.0" + } + }, + "babel-plugin-syntax-jsx": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", + "integrity": "sha512-qrPaCSo9c8RHNRHIotaufGbuOBN8rtdC4QrrFFc43vyWCCz7Kl7GL1PGaXtMGQZUXrkCjNEgxDfmAuAabr/rlw==" + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "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==" + }, + "browserslist": { + "version": "4.21.5", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", + "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", + "dev": true, + "peer": true, + "requires": { + "caniuse-lite": "^1.0.30001449", + "electron-to-chromium": "^1.4.284", + "node-releases": "^2.0.8", + "update-browserslist-db": "^1.0.10" + } + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "peer": true + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" + }, + "camelize": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz", + "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==" + }, + "caniuse-lite": { + "version": "1.0.30001469", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001469.tgz", + "integrity": "sha512-Rcp7221ScNqQPP3W+lVOYDyjdR6dC+neEQCttoNr5bAyz54AboB4iwpnWgyi8P4YUsPybVzT4LgWiBbI3drL4g==", + "dev": true, + "peer": 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==" + } + } + }, + "chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "dev": true, + "peer": true + }, + "classnames": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", + "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==" + }, + "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==" + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true, + "peer": true + }, + "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" + } + }, + "compute-scroll-into-view": { + "version": "1.0.20", + "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-1.0.20.tgz", + "integrity": "sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg==" + }, + "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==" + }, + "copy-to-clipboard": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz", + "integrity": "sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==", + "requires": { + "toggle-selection": "^1.0.6" + } + }, + "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" + } + }, + "css-color-keywords": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", + "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==" + }, + "css-to-react-native": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz", + "integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==", + "requires": { + "camelize": "^1.0.0", + "css-color-keywords": "^1.0.0", + "postcss-value-parser": "^4.0.2" + } + }, + "csstype": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz", + "integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" + }, + "direction": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/direction/-/direction-1.0.4.tgz", + "integrity": "sha512-GYqKi1aH7PJXxdhTeZBFrg8vUBeKXi+cNprXsC1kpJcbcVnV9wBsrOu1cQEdG0WeQwlfHiy3XvnKfIrJ2R0NzQ==" + }, + "dnd-core": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/dnd-core/-/dnd-core-16.0.1.tgz", + "integrity": "sha512-HK294sl7tbw6F6IeuK16YSBUoorvHpY8RHO+9yFfaJyCDVb6n7PRcezrOEOa2SBCqiYpemh5Jx20ZcjKdFAVng==", + "requires": { + "@react-dnd/asap": "^5.0.1", + "@react-dnd/invariant": "^4.0.1", + "redux": "^4.2.0" + } + }, + "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" + } + }, + "electron-to-chromium": { + "version": "1.4.334", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.334.tgz", + "integrity": "sha512-laZ1odk+TRen6q0GeyQx/JEkpD3iSZT7ewopCpKqg9bTjP1l8XRfU3Bg20CFjNPZkp5+NDBl3iqd4o/kPO+Vew==", + "dev": true, + "peer": true + }, + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true + }, + "enhanced-resolve": { + "version": "5.12.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", + "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", + "dev": true, + "peer": true, + "requires": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + } + }, + "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" + } + }, + "es-module-lexer": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", + "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", + "dev": true, + "peer": true + }, + "esbuild": { + "version": "0.17.11", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.11.tgz", + "integrity": "sha512-pAMImyokbWDtnA/ufPxjQg0fYo2DDuzAlqwnDvbXqHLphe+m80eF++perYKVm8LeTuj2zUuFXC+xgSVxyoHUdg==", + "dev": true, + "requires": { + "@esbuild/android-arm": "0.17.11", + "@esbuild/android-arm64": "0.17.11", + "@esbuild/android-x64": "0.17.11", + "@esbuild/darwin-arm64": "0.17.11", + "@esbuild/darwin-x64": "0.17.11", + "@esbuild/freebsd-arm64": "0.17.11", + "@esbuild/freebsd-x64": "0.17.11", + "@esbuild/linux-arm": "0.17.11", + "@esbuild/linux-arm64": "0.17.11", + "@esbuild/linux-ia32": "0.17.11", + "@esbuild/linux-loong64": "0.17.11", + "@esbuild/linux-mips64el": "0.17.11", + "@esbuild/linux-ppc64": "0.17.11", + "@esbuild/linux-riscv64": "0.17.11", + "@esbuild/linux-s390x": "0.17.11", + "@esbuild/linux-x64": "0.17.11", + "@esbuild/netbsd-x64": "0.17.11", + "@esbuild/openbsd-x64": "0.17.11", + "@esbuild/sunos-x64": "0.17.11", + "@esbuild/win32-arm64": "0.17.11", + "@esbuild/win32-ia32": "0.17.11", + "@esbuild/win32-x64": "0.17.11" + } + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "peer": 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-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, + "peer": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "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, + "peer": 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, + "peer": true + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "peer": true + }, + "events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "peer": true + }, + "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==" + }, + "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 + }, + "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" + } + }, + "find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==" + }, + "follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==" + }, + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true, + "peer": true + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" + }, + "graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "peer": 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==" + }, + "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==" + } + } + }, + "immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==" + }, + "immer": { + "version": "9.0.19", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.19.tgz", + "integrity": "sha512-eY+Y0qcsB4TZKwgQzLaE/lqYMlKhv5J9dyd2RhhtGhNo2njPXDqU9XPfcNfa3MIDsdtZt5KlkIsirlo4dHsWdQ==" + }, + "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" + } + }, + "intl-messageformat": { + "version": "10.3.3", + "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-10.3.3.tgz", + "integrity": "sha512-un/f07/g2e/3Q8e1ghDKET+el22Bi49M7O/rHxd597R+oLpPOMykSv5s51cABVfu3FZW+fea4hrzf2MHu1W4hw==", + "requires": { + "@formatjs/ecma402-abstract": "1.14.3", + "@formatjs/fast-memoize": "2.0.1", + "@formatjs/icu-messageformat-parser": "2.3.0", + "tslib": "^2.4.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.11.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", + "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", + "requires": { + "has": "^1.0.3" + } + }, + "is-hotkey": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/is-hotkey/-/is-hotkey-0.1.8.tgz", + "integrity": "sha512-qs3NZ1INIS+H+yeo7cD9pDfwYV/jqRh1JG9S9zYrNudkoUQg7OL7ziXqRKu+InFjUIDoP2o6HIkLYMh1pcWgyQ==" + }, + "is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==" + }, + "jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "peer": true, + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "dependencies": { + "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, + "peer": true + }, + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "peer": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" + }, + "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 + }, + "json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true + }, + "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==" + }, + "loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "dev": true, + "peer": true + }, + "loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "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" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==" + }, + "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" + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "peer": true + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + }, + "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==" + }, + "nanoid": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "dev": true + }, + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true, + "peer": true + }, + "node-releases": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", + "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==", + "dev": true, + "peer": 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==" + }, + "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-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==" + }, + "philliplm-react-modern-audio-player": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/philliplm-react-modern-audio-player/-/philliplm-react-modern-audio-player-1.4.6.tgz", + "integrity": "sha512-2C/1lpQJmD0gWJMVt6k/QNZoakxHwxGhRFyw17OVAwbpXmptisr9aHDzT/VPFKoIr5qj+y1WajJ4lnghbfzx9Q==", + "requires": { + "@react-spectrum/layout": "^3.3.1", + "@react-spectrum/provider": "^3.4.1", + "@react-spectrum/theme-default": "^3.3.1", + "@react-spectrum/view": "^3.2.1", + "classnames": "^2.3.1", + "react-icons": "^4.4.0", + "styled-components": "^5.3.5", + "wavesurfer.js": "^6.2.0" + } + }, + "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==" + }, + "postcss": { + "version": "8.4.21", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", + "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", + "dev": true, + "requires": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + } + }, + "postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + }, + "prettier": { + "version": "2.8.6", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.6.tgz", + "integrity": "sha512-mtuzdiBbHwPEgl7NxWlqOkithPyp4VN93V7VeHVWBF+ad3I5avc0RVDT4oImXQy9H/AqxA2NSQH8pSxHW6FYbQ==", + "dev": true + }, + "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==" + } + } + }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "dev": true + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "peer": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "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-copy-to-clipboard": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/react-copy-to-clipboard/-/react-copy-to-clipboard-5.1.0.tgz", + "integrity": "sha512-k61RsNgAayIJNoy9yDsYzDe/yAZAzEbEgcz3DZMhF686LEyukcE1hzurxe85JandPUG+yTfGVFzuEw3xt8WP/A==", + "requires": { + "copy-to-clipboard": "^3.3.1", + "prop-types": "^15.8.1" + } + }, + "react-dnd": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/react-dnd/-/react-dnd-16.0.1.tgz", + "integrity": "sha512-QeoM/i73HHu2XF9aKksIUuamHPDvRglEwdHL4jsp784BgUuWcg6mzfxT0QDdQz8Wj0qyRKx2eMg8iZtWvU4E2Q==", + "requires": { + "@react-dnd/invariant": "^4.0.1", + "@react-dnd/shallowequal": "^4.0.1", + "dnd-core": "^16.0.1", + "fast-deep-equal": "^3.1.3", + "hoist-non-react-statics": "^3.3.2" + } + }, + "react-dnd-html5-backend": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/react-dnd-html5-backend/-/react-dnd-html5-backend-16.0.1.tgz", + "integrity": "sha512-Wu3dw5aDJmOGw8WjH1I1/yTH+vlXEL4vmjk5p+MHxP8HuHJS1lAGeIdG/hze1AvNeXWo/JgULV87LyQOr+r5jw==", + "requires": { + "dnd-core": "^16.0.1" + } + }, + "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-grid-layout": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/react-grid-layout/-/react-grid-layout-1.3.4.tgz", + "integrity": "sha512-sB3rNhorW77HUdOjB4JkelZTdJGQKuXLl3gNg+BI8gJkTScspL1myfZzW/EM0dLEn+1eH+xW+wNqk0oIM9o7cw==", + "requires": { + "clsx": "^1.1.1", + "lodash.isequal": "^4.0.0", + "prop-types": "^15.8.1", + "react-draggable": "^4.0.0", + "react-resizable": "^3.0.4" + } + }, + "react-icons": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.8.0.tgz", + "integrity": "sha512-N6+kOLcihDiAnj5Czu637waJqSnwlMNROzVZMhfX68V/9bu9qHaMIJC4UdozWoOk57gahFCNHwVvWzm0MTzRjg==", + "requires": {} + }, + "react-intersection-observer": { + "version": "9.4.3", + "resolved": "https://registry.npmjs.org/react-intersection-observer/-/react-intersection-observer-9.4.3.tgz", + "integrity": "sha512-WNRqMQvKpupr6MzecAQI0Pj0+JQong307knLP4g/nBex7kYfIaZsPpXaIhKHR+oV8z+goUbH9e10j6lGRnTzlQ==", + "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-masonry-css": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/react-masonry-css/-/react-masonry-css-1.0.16.tgz", + "integrity": "sha512-KSW0hR2VQmltt/qAa3eXOctQDyOu7+ZBevtKgpNDSzT7k5LA/0XntNa9z9HKCdz3QlxmJHglTZ18e4sX4V8zZQ==", + "requires": {} + }, + "react-redux": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.0.5.tgz", + "integrity": "sha512-Q2f6fCKxPFpkXt1qNRZdEDLlScsDWyrgSj0mliK59qU6W5gvBiKkdMEG2lJzhd1rCctf0hb6EtePPLZ2e0m1uw==", + "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-resizable": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/react-resizable/-/react-resizable-3.0.5.tgz", + "integrity": "sha512-vKpeHhI5OZvYn82kXOs1bC8aOXktGU5AmKAgaZS4F5JPburCtbmDPqE7Pzp+1kN4+Wb81LlF33VpGwWwtXem+w==", + "requires": { + "prop-types": "15.x", + "react-draggable": "^4.0.3" + } + }, + "react-resize-detector": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/react-resize-detector/-/react-resize-detector-8.0.4.tgz", + "integrity": "sha512-ln9pMAob8y8mc9UI4aZuuWFiyMqBjnTs/sxe9Vs9dPXUjwCTeKK1FP8I75ufnb/2mEEZXG6wOo/fjMcBRRuAXw==", + "requires": { + "lodash": "^4.17.21" + } + }, + "react-router": { + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.9.0.tgz", + "integrity": "sha512-51lKevGNUHrt6kLuX3e/ihrXoXCa9ixY/nVWRLlob4r/l0f45x3SzBvYJe3ctleLUQQ5fVa4RGgJOTH7D9Umhw==", + "requires": { + "@remix-run/router": "1.4.0" + } + }, + "react-router-dom": { + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.9.0.tgz", + "integrity": "sha512-/seUAPY01VAuwkGyVBPCn1OXfVbaWGGu4QN9uj0kCPcTyNYgL1ldZpxZUpRU7BLheKQI4Twtl/OW2nHRF1u26Q==", + "requires": { + "@remix-run/router": "1.4.0", + "react-router": "6.9.0" + } + }, + "react-toastify": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-9.1.2.tgz", + "integrity": "sha512-PBfzXO5jMGEtdYR5jxrORlNZZe/EuOkwvwKijMatsZZm8IZwLj01YvobeJYNjFcA6uy6CVrx2fzL9GWbhWPTDA==", + "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" + } + }, + "react-virtuoso": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/react-virtuoso/-/react-virtuoso-4.3.3.tgz", + "integrity": "sha512-x0DeGmVAVOVaTXRMG7jzrHBwK7+dkt7n0G3tNmZXphQUBgkVBYuZoaJltQeZGFN42++3XvrgwStKCtmzgMJ0lA==", + "requires": {} + }, + "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==" + }, + "reselect": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.7.tgz", + "integrity": "sha512-Zu1xbUt3/OPwsXL46hvOOoQrap2azE7ZQbokq61BQfiXvhewsKDwhMeZjTX9sX0nvw1t/U5Audyn1I9P/m9z0A==" + }, + "resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "requires": { + "is-core-module": "^2.9.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==" + }, + "rollup": { + "version": "3.19.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.19.1.tgz", + "integrity": "sha512-lAbrdN7neYCg/8WaoWn/ckzCtz+jr70GFfYdlf50OF7387HTg+wiuiqJRFYawwSPpqfqDNYqK7smY/ks2iAudg==", + "dev": true, + "requires": { + "fsevents": "~2.3.2" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "peer": true + }, + "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" + } + }, + "schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + }, + "scroll-into-view-if-needed": { + "version": "2.2.31", + "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.31.tgz", + "integrity": "sha512-dGCXy99wZQivjmjIqihaBQNjryrz5rueJY7eHfTdyWEiR4ttYpsajb14rn9s5d4DY4EcY6+4+U/maARBXJedkA==", + "requires": { + "compute-scroll-into-view": "^1.0.20" + } + }, + "serialize-javascript": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", + "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", + "dev": true, + "peer": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" + }, + "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==" + }, + "slate": { + "version": "0.91.4", + "resolved": "https://registry.npmjs.org/slate/-/slate-0.91.4.tgz", + "integrity": "sha512-aUJ3rpjrdi5SbJ5G1Qjr3arytfRkEStTmHjBfWq2A2Q8MybacIzkScSvGJjQkdTk3djCK9C9SEOt39sSeZFwTw==", + "requires": { + "immer": "^9.0.6", + "is-plain-object": "^5.0.0", + "tiny-warning": "^1.0.3" + } + }, + "slate-history": { + "version": "0.86.0", + "resolved": "https://registry.npmjs.org/slate-history/-/slate-history-0.86.0.tgz", + "integrity": "sha512-OxObL9tbhgwvSlnKSCpGIh7wnuaqvOj5jRExGjEyCU2Ke8ctf22HjT+jw7GEi9ttLzNTUmTEU3YIzqKGeqN+og==", + "requires": { + "is-plain-object": "^5.0.0" + } + }, + "slate-react": { + "version": "0.91.11", + "resolved": "https://registry.npmjs.org/slate-react/-/slate-react-0.91.11.tgz", + "integrity": "sha512-2nS29rc2kuTTJrEUOXGyTkFATmTEw/R9KuUXadUYiz+UVwuFOUMnBKuwJWyuIBOsFipS+06SkIayEf5CKdARRQ==", + "requires": { + "@juggle/resize-observer": "^3.4.0", + "@types/is-hotkey": "^0.1.1", + "@types/lodash": "^4.14.149", + "direction": "^1.0.3", + "is-hotkey": "^0.1.6", + "is-plain-object": "^5.0.0", + "lodash": "^4.17.4", + "scroll-into-view-if-needed": "^2.2.20", + "tiny-invariant": "1.0.6" + } + }, + "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.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true + }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "peer": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "peer": true + } + } + }, + "styled-components": { + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-5.3.9.tgz", + "integrity": "sha512-Aj3kb13B75DQBo2oRwRa/APdB5rSmwUfN5exyarpX+x/tlM/rwZA2vVk2vQgVSP6WKaZJHWwiFrzgHt+CLtB4A==", + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/traverse": "^7.4.5", + "@emotion/is-prop-valid": "^1.1.0", + "@emotion/stylis": "^0.8.4", + "@emotion/unitless": "^0.7.4", + "babel-plugin-styled-components": ">= 1.12.0", + "css-to-react-native": "^3.0.0", + "hoist-non-react-statics": "^3.0.0", + "shallowequal": "^1.1.0", + "supports-color": "^5.5.0" + }, + "dependencies": { + "@emotion/unitless": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", + "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==" + } + } + }, + "stylis": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.1.3.tgz", + "integrity": "sha512-GP6WDNWf+o403jrEp9c5jibKavrtLW+/qYGhFxFrG8maXhwTBI7gLLhiBb0o7uFccWN+EOS9aMO6cGHWAO07OA==" + }, + "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==" + }, + "tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "peer": true + }, + "terser": { + "version": "5.16.6", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.6.tgz", + "integrity": "sha512-IBZ+ZQIA9sMaXmRZCUMDjNH0D5AQQfdn4WUjHL0+1lF4TP1IHRJbrhb6fNaXWikrYQTSkb7SLxkeXAiy1p7mbg==", + "dev": true, + "peer": true, + "requires": { + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + } + }, + "terser-webpack-plugin": { + "version": "5.3.7", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.7.tgz", + "integrity": "sha512-AfKwIktyP7Cu50xNjXF/6Qb5lBNzYaWpU6YfoX3uZicTx0zTy0stDDCsvjDapKsSDvOeWo5MEq4TmdBy2cNoHw==", + "dev": true, + "peer": true, + "requires": { + "@jridgewell/trace-mapping": "^0.3.17", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.1", + "terser": "^5.16.5" + } + }, + "tiny-invariant": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.0.6.tgz", + "integrity": "sha512-FOyLWWVjG+aC0UqG76V53yAWdXfH8bO6FNmyZOuUrzDzK8DI3/JRY25UD7+g49JWM1LXwymsKERB+DzI0dTEQA==" + }, + "tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" + }, + "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==" + }, + "toggle-selection": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", + "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==" + }, + "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.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + }, + "typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true + }, + "update-browserslist-db": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", + "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", + "dev": true, + "peer": 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": "4.2.0", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.2.0.tgz", + "integrity": "sha512-AbDTyzzwuKoRtMIRLGNxhLRuv1FpRgdIw+1y6AQG73Q5+vtecmvzKo/yk8X/vrHDpETRTx01ABijqUHIzBXi0g==", + "dev": true, + "requires": { + "esbuild": "^0.17.5", + "fsevents": "~2.3.2", + "postcss": "^8.4.21", + "resolve": "^1.22.1", + "rollup": "^3.18.0" + } + }, + "watchpack": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", + "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "dev": true, + "peer": true, + "requires": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + } + }, + "wavesurfer.js": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/wavesurfer.js/-/wavesurfer.js-6.6.2.tgz", + "integrity": "sha512-aPAU4OADQsyH8mIw2nXmoni8KHo8s1f1bd5ZUrxhN4P/VMWd+oPDqEwA01XPSEfasAJW6mZ/EHQ2bZ9nOWRrNw==" + }, + "webpack": { + "version": "5.76.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.2.tgz", + "integrity": "sha512-Th05ggRm23rVzEOlX8y67NkYCHa9nTNcwHPBhdg+lKG+mtiW7XgggjAeeLnADAe7mLjJ6LUNfgHAuRRh+Z6J7w==", + "dev": true, + "peer": true, + "requires": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^0.0.51", + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/wasm-edit": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "acorn": "^8.7.1", + "acorn-import-assertions": "^1.7.6", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.10.0", + "es-module-lexer": "^0.9.0", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.1.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.1.3", + "watchpack": "^2.4.0", + "webpack-sources": "^3.2.3" + } + }, + "webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "dev": true, + "peer": true + }, + "worker-loader": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/worker-loader/-/worker-loader-3.0.8.tgz", + "integrity": "sha512-XQyQkIFeRVC7f7uRhFdNMe/iJOdO6zxAaR3EWbDp45v3mDhrTi+++oswKNxShUNjPC/1xUp5DB29YKLhFo129g==", + "dev": true, + "requires": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + } + }, + "yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..2be0b27 --- /dev/null +++ b/package.json @@ -0,0 +1,54 @@ +{ + "name": "q-blog", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc && vite build", + "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", + "@types/react-grid-layout": "^1.3.2", + "axios": "^1.3.4", + "compressorjs": "^1.2.1", + "localforage": "^1.10.0", + "moment": "^2.29.4", + "philliplm-react-modern-audio-player": "^1.4.6", + "react": "^18.2.0", + "react-copy-to-clipboard": "^5.1.0", + "react-dnd": "^16.0.1", + "react-dnd-html5-backend": "^16.0.1", + "react-dom": "^18.2.0", + "react-dropzone": "^14.2.3", + "react-grid-layout": "^1.3.4", + "react-intersection-observer": "^9.4.3", + "react-masonry-css": "^1.0.16", + "react-redux": "^8.0.5", + "react-resize-detector": "^8.0.4", + "react-router-dom": "^6.9.0", + "react-toastify": "^9.1.2", + "react-virtuoso": "^4.3.3", + "short-unique-id": "^4.4.4", + "slate": "^0.91.4", + "slate-history": "^0.86.0", + "slate-react": "^0.91.11", + "ts-key-enum": "^2.0.12" + }, + "devDependencies": { + "@mui/types": "^7.2.3", + "@types/react": "^18.0.28", + "@types/react-copy-to-clipboard": "^5.0.4", + "@types/react-dom": "^18.0.11", + "@vitejs/plugin-react-swc": "^3.2.0", + "prettier": "^2.8.6", + "typescript": "^4.9.3", + "vite": "^4.2.0", + "worker-loader": "^3.0.8" + } +} diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..d8d15a741981eff5c5e1aaff2441264073ca3fad GIT binary patch literal 15406 zcmeHO32;>99e;vVxf4is_Z=JYwwK`4(W-4x>sf2-QSlyVr;2z~ysA|hvGtm^+NpzB ztS02xeMdm+cwd0W2qRELQ9#r{5<*C_`;J`#h`Rm#-sUAQkC$UHcyyAP|9o%X`;Pzj z|Ni&?iy-VJ3>Aus1hnIYEB6+JqXj`2KR*Ba@M1wI$GeFWJH8((2yc}N!r|zHAsCT= zk7kejrE12G_CxNel2NUXcR_Bh@SWZkwv2eD8|X?)n=1XmQl$$VUAo^=ArL_azsy%AFFJ!4f$!uh#RIBuiQ{wB67T=mrb#CWs|MT zm4JsmaCGHyJg>F&_%=&ZHkgUhi8+!v@Q3-P+NwM=_mHq};FDm@iyVYGKHwhtEjLRT zV(GETrYhgDX7;FYeCLkW#OpZTe6py>rH3X?TQp0+i3@_QOLtnTcsZZ5$w(A*Z1C^j zKfbkEIt<^p+D5$1s)`=qj#s6Nt)w`O&#h{Sgl|nfjdu*`Fns6u)E3~*G2R*R8Tjvw z{mis9Y+(C~xS4tkS@#`$3Ojz7@(a=T;yd_@|0 z-)v*_Se)4#z-I^gy$!m}G?VfS4=i1}#nF^ib|OzdD>0_n*5n!Bhnrox8Okz@{XDBn zC-(%7F5hD&V^c`~uKjoCHxHk%Hlr)&Wpw!tOOKq4H7~La@>!YXhp=(pJJ4xpu0q%^ z_nfeA9owg+;muXi5q|LceqAl~%y_^F0P3f~zi%c5QVV3IFK9OuxmArzLE!sLRWy>z z?W*JYyIV^yYwin7JzfVL@rseoQt4n6#WSwSnfdw+f#(bIEVQrT2r5xp=y zw|I;PIqI2Or5fumY3$I;yMsYbYx>_~{f5TM=r8^AQwQYjjk08O`N&f0z}*4=Iz2sy zt-mO**H!4+4;@XsBCUy+*svP~LzkWY0y_V5=)w%z6m)Q#2W_hIUVVAwv~K%fM7vV< z65vxyS5g>LN1K5$?}q{S1@D!QEkohFrlrR%Lf4+-w#!R~bQk(vlhNYSJ!q?ur_@yx zjo)Q`qwE#T(GJ`8675H}R=EUveR3GUrd^nsFI{bFQjKFM4Zd~1zf(nI?4 zi#!~1+&|U_53F;lBgeHE!bqIIYyZ7I!IpM31768!@^sLk4nUf3gZ-;$eq>}M*uS^m z-uf87!kIg&q`68M5nMma_u-uM3qh~H;@mRW`$o{@*TJ=Nn9tEl4mFL^iK&{{_trix zjPm#K)`u-#PWkh%-!xYkZmOk6TFK~1mRfR@QOTF)=7MTE?mk!kWpz&HW5j)YFpKWeA_OC0oSpS_& z)wu8azcoBIdMy0me|G4n9q6~drCL1Q->0|pPba0bz*|kgf4e(}F3;Pl4wwAndFG(; zbAS!D-u-MSw`QVffAHpHe80{%q>D4gNJNiaf4!{_`Bpd%9Lfk*73+(FB zgE99q;I|dB@*rilYxevT&uBe->@b~}UtfX#+g1L!7RR!WKW^~m=X*;RFNaOooY#TM zI!lfHCM+KF#su3&=oCkfzZtfEu&@6&_hRa?6LF?*VgH}GJO;Z5K6sCMBCVGGG+kL- zhFDn&gSN_XGIb*C$zAY;njyn0g8Gm9$X1lb{NvkkCbl*faxL8o-d+a1{VCUG?B~XR z(8bUbO~C72@aq!5TRnmSov$m6*#8c!znuK)*T1G3I|1{&26(3v7;_oQhxl!F?i=en zYW&{a0$sVEa)ms=t1S-;BfG61&_A9WhqZ1j#dxYvK?-t0mkmLyX*UTqmXCv zFxFpyb9f?$*pK!Fcnov-3;7MuxKsaz?b~}-$eRAXq*ta^c@*m}%oy_R@OfrJ7H$I% z-3r-%1naMXY}fY%{y7VMrZ3)<995Dw;FtS=F@45}l`=Nz3kqFxu>T+h29g5IlORPa zOa%<)NkD|bzd;K8A5y@aFCAGhs2G!wCvK^hC!`JKhoLZEIU;Mw6OrdXA_u#-r$`4o zzOHaU++!%Kkh^;ge!+j>`#l+ijG?@McPnj8S?1`Gv*EYzw;_c!90Z@9Q?-nTYx`eWo3(#l&6HnF$1xmg7EIlsl|7;B;++4=SBZy!$)Ua&<&91 zKpkTe&SoKC(>D?S<{J5f`gyUNSlbArqhrX&A_w`3hkx_mgwTFrV+(n=yY%l9f8;t4 zk1a+F+-&RO^{9CrmQu&Y+W~9`3ic5Gdy#*@`>2^I$fZh}rHQwr#`Z_b1#+4td-||H0N!K2^?*-smJNuBP#ad7x>Q2 z4DkvlIqq=gnTdyoQz2~t|15GcbC_?Y4Pbt)(0OyHaWhw)O^Byq5B~z5p8#j%X_%*1 zK6mMkdKc(@Df=-7F9hFU-vItrMisBL<_N{iXY3CCoS$hlJ6E(k6(zx0c8M;C<6UO`dYz8~#{#$SgqEeExSic#bL6`aen$kZe9GzJ7M^*o+a$VIstMU z2X5CQ2c;lW%=s{n?#IFZ+=BZj;2GRWL2b*3+omr6#jYNGu)mM@OkCQGVX~#g&PN_{ z7WzI&*jz2$Quk=dB(CrE_1ga8kNpgF>oKqerY2WG*Qn63b9slutd30JcW+LA%Nhx7 z33vzhBb3dy7Q4zx3f*cY>`y$H2eRjjms*AlJu27Xyqe&5Zi4UjdR=*JdYE6(cFzk@!I@!815 zX1ux&&TMCI{zJd!@DGY+Vgo4a_FoLK!#TXH#bLK z7vi6jH*hv*(1rm2_C0|={E3@@Lp{#53xBuvi~3zsx{7ia#D5m#5&Uy9^v(*L+gf*@ z9e0fUeJO9`d&DY>F#onL`V1WXfyYhs4Iqoqh429Yj#1{?JjlciVg4=8w-t3Gj9W_l z&4hR^>mh#J`OJ4#Ql5-{i*dd<)BOAc$v6JQ z`j?^pBE1gUUDg1b8^nwEa;)0u&mrT8t(6w&+ZintBVxPsqnyC5peA-3{80LmI{>af ziTHO_bCq~~PxR@szdhS8;s#rCBY0pV&X;rVbX)k^(4Vun&M!GC%#OjH?hSwLOyJJ= z+Ci=9?qIFn+Y9U2tev55IvaZEWtVh-_x{ut@u;crPZ=%$OX-;Y7pcIeTnU>)AypSl$`eSA7u`V-bonQNdwnR{kT zF>&?x<#QMQaoD?_=}$i3Jx==3=^E*H*4LSfVtp`-F5Ws>V?>Pc8)#4ai!)PJI;uRi zw=r022>l(_!`zw}WIGJ^Lhxr_)^Vw)Nh7XLn}d0K^y9!gLu@sA3~)}myaWFk=a6D; z%1V^{sJA_M`|qozeZiTY0e!onH~RNAPw+eW9`&p;#6zgPE9=0=`53^B$q;91@&jot z`h(?H^z8cu=M4MJdl$GX@;l7WSk`$qHa_ef=}ui@CdC<;lX|}$Eoe`h#5e}_ z4{-qQ|NK3pi|6r2u1V(TeVS#;*Rop(0?_E-)-1OyEpvFJB&Nh z(BHu|aNnmWmmCqzB*%V#s}VaBI^@rJ+#$1Wtlnu)8AEap&|yjw&YXFhhv}n27feql zZ0Ijw@63t;0I1&$+pH!}7;r#s0CdM)c-(u`l=p4iv0@HkPv9RW>tFUA?Go+|oP;x9fjIlW z&EaK&vXXf)>Tc+h{c_N)*vC-rk-jnSheE!(`Tt#hdf)u>WoaEY zo_3k|BmcJoGO!kQWd{D2 { + // setIsDarkMode("dark"); + // } + + return ( + + + + + + + + + } + /> + } + /> + } /> + } /> + } /> + } + /> + } + /> + } /> + } /> + + + + + + ) +} + +export default App diff --git a/src/assets/img/arrr.png b/src/assets/img/arrr.png new file mode 100644 index 0000000000000000000000000000000000000000..d27456576e737c1353e256810d9b84dce7b42784 GIT binary patch literal 1429 zcmV;G1#0?k}ogVt_iv;g(_nl!MG8$U!DoWdu9kkw6h-ftOt@TB<<3sK5#b z%0a@oI37WePGIvKtR6|AI9mhAv#hf;g!DQH`61I`vLh+0A4)5ZAgMw_(fIw3) zJ;zl&sHJKOrdX)Hx;#!mMwh{?4+1iNCMv%cs&_F=hEbm`q|2jkHpr9){rIV#T^^%{ zqGI`FG|T-NsX|E0@RAuy6F+A}zL1-lD6p(ZBB$8#sMK3e0-2 zyN`|tb@-8)tA&n=Zp7vthfK?qt?H*&?8Ec>6y1K*Zl$YZC?)`2i2k;rbN5(Ja(f&> z+I84U^Cc*)6S}%Am?43*v&+{5%?Ss(|8(3zHn20hJXOrjyFuJRHpKXrg=S^dV)^SF z2l1dSSLXN6@BBXR1AV4vV;|eVi@+ZM7|I3uWBCi4oxV;L$+&{tePqNO-{FT843s4> zt0X1g`RVPW&|um@5()C9DX`ECi?KogX;&s8bNr+h1Qa2GTYhodULx1%dy;)-VmsA8APs0umM;p4i-Xy#(i%@Nrq=){EG``n z8)S$XAXhDYofCb_5&*4s8%WbSm%jwg^81isSt#ifaMl(afEg7*a+^RVP@R{Xlpw?2 z%hXKPIu?O+%R)&sbZ#P2AVGhAeK+?v5vio%PTVq$g+>dewJ1n1c7n>l((*&0+sF37 z1hC4FuZp}(QZ5SWcE=w6xh%tCDC7HY^JVk?3&ug07?jk#AM% zp8|1O^(-h(zSY1=b8vN(m9}V|ZWap4hn1x0U^z0D!f$4jecbWOsfvh5d+Q34B;Czhy%(n6vZ9lYt6&UXDakYjKP`=$833&u30U=V6#}s8^*@Ag)eEW!;kNq< jH3JJkl>Q2}zXA*Z%L07o@pf>Q00000NkvXXu0mjfhXs}` literal 0 HcmV?d00001 diff --git a/src/assets/img/btc.png b/src/assets/img/btc.png new file mode 100644 index 0000000000000000000000000000000000000000..fe3fd1a030bd2736ed76748d27e6584b3fa05c3a GIT binary patch literal 1982 zcmV;v2SNCWP)htPv-zHc{0_qe;RVIF+Z!7aDH+~!cJ9zWE z0z3R;&-88FK?e2QLmp!@E8cvh&hc=%{kbT8{6vWNHYd)RK99@$W6Yf$C}t1aw#Jzg z0V;Sa!^E?jk>}QSm5SwX6l)KBQTk+0IO|oeTiQv=s9ZvBZmmTrZ`ziI&lxG$;Z&v6ZUQj_sWG~M))W^e7D$CuHznMHr>Q@{nSfDQWq}b2MbIgTT zz^IxC6f5m)AyTYIo(7ztPO6RN45fh8bmc!vp{zk(9*5z6*bt5knS!?+5r9(7+s`Og z?bu8S)%ld|@)Abn>wnn39_;7E^Qti19)(pp?UZ&|FD+GddH97GzI-gMPL6m?%H8Hf z;BTPqMk*8w0Dl_&ZDq&7%d6~1XOj+Y*lnpJ?8F$`y-}IZHKxuO#X?@LytmFKZ7cjp zm4`i*Ihj;x7-&P-YUihk;4^t|1PduCvl(bi0LA>&TAed0Bbo?>P7amrmG>zweyU3w zysJEYn(tq0utMD!<@h6odbVIvDn(&+f_WHr_a)eS%A;Q$({d2!R!ywkXPrCd6#^(F zE{%&VAxye_@kptbl5T=h8B2ZFK(TUCE2=^P6o8w1j#TaCuT9$ZYHYq2>ZO~Y(7LeL zlI$ln^MPu<3X>9tK5KXD?jqUG#B*OK+el}f^+}HBMpaA}!G0FB)vW^6VL#I<9!vvc zvui_j+0SthPjEQFzdcrkmTd*}6g5Giqr6@n7oAlwe?FK!4{E5NwMc{tc%(KO0l2AS2uN1C~N>&=eDPwE0M1Q&!51npP5^&=$w5ojIT|E z`sCapF9DqY_0 z+J|C!i9BebTjc0EMs#dhkT|H*HdVFr3qr0yEoCT-l&?ra>O#pQXH}u1CnGm{ZR#upDJd zAPX%9211iOc{)tQg^rKrimI7*G0K8b0H%eSJuz4R{c!3Df9z-(?jPmPNWh7eUc%AtWtvpeHm= z)d4#RUVIebD|nSnlKm`D8_XNQu|T16f-CC|w8w@32%HSnX%!3T+1sU?sB+R+~g}N)wvhE_5HY3Wvi3>K5JK!&P>kH!4c@j{x84Y3h8GeDB zP=mU;AbI8p7680=3~K8A?@~?0dB>pgZzebeb(w8yKMPESo@ zz}%N0bFE#}vP(EFZElOj-3oJn8Bp#5s+Reocq3Jgf{KYk2i&`^_lB%q3{cb;14Mv@ zoOe&GUR}WgcJ*=<2C%Ew|1iQ`y`YK_Zuk{yRXozXLhTek0iyL+sQoX%0DJn9yuv^) QjsO4v07*qoM6N<$g5oNn-~a#s literal 0 HcmV?d00001 diff --git a/src/assets/img/dgb.png b/src/assets/img/dgb.png new file mode 100644 index 0000000000000000000000000000000000000000..6950158b56d73dcce67b8fece5cc1d1817b6b51c GIT binary patch literal 4917 zcmV-56Uyv~P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D63R(LK~#8N-JJ<^ z6ji#%|F=2|Nk||G2qLS1vM5X-K?u$OA|Q+BJ>{_}+h`KdVcv*}^3HP@^|+wpGR)}s zNa7Zb7(o#oKtUFX$d*JvS!Kt7VGXin?Yi&#s&61ocU4z+x)Yq=IhDTmcBi`PU*G-i zcW>RgEl|&BlkR-t0UPo1Vol$3k ziu8Q4HZfKTc^|#@frO^s3KcqS8|Vz@LppPjbsJlC$O*ZiB7Ji=3GoPo7z-(*>fkHA zAWP|cbIC2tL1wRQsxTyk?(EVEl4p)?5uzW4xM(2D)JNZvQ_24g%c1LPXL#w{U|>VS$>JmmCBt? z*O6)(goE601Z|OxfT+fh4X*=elVJ^9y9x-APf@`{nVqs*6$DJ}1A0o+VUhG1Lq0d^hyi7OKPw znNLSQ&~Ej&b*2=ohf@__LMcn1$vYE8`Ox>RrsKFatkMj&R;~R2=&i^;RG9@U$cRQD zyQj~F%2sS4h2wQ!VnRBh?OF!8_bUpCu5B?HNyqElN5{I0?1a)j7)&Qc8u-Syg=XYW zB1PX*Ij;z31;qA6(9cjj`71Xf!Hu1y<|v?)Y0xg5 zl@Q-AfPVIfD*1JyHEsjhZImxjFH(mj*{VlnTIEIB`Y>o=IaXqFRT0}iAu)qGzECgl zIq*^mPg~&lVX=8%94;7J*lCw6AHQBVaJE|4YS~S#Q=`@#dso&;gxR!lEW*RCTzl&7qWJVVqjipnibPzD8W^Dhj_A&w zzlgH(zy^<~hXm1KkkR^E!2SL%)IIg^bKV6_FZhuDj&)@`5$BHqh4bj>bvq$Pt!NY* zg`#y?Xc!%-N?eRce-X>R-h$lM|AbM)Qz;ChQ{jW5*Y`eIjo;7wr|W|OU~~X_+z-9c z4X%B9Lm(HK$>UV+GM-gFy&#$Xj&^0dz>UyO3fk*HOlI`3R1%XdkgvUKD=n+QhVOPG zv2jD(J%}vH7+IqCSXAQ6wOfqWK;e)IJC{&{YhmS*G)m8Bt=#Ysln#k+TbTG(>YE?R zBZH?NP#y96kporg3ZJgngpzZYFlIzwL`6m#GFMZ4vIL7)ZC1I!(M!)jP}kW4(nzpY zZqz&$?h$n-$@ucRl~BjJx{vKzO)m!>FoijaNlnOcY*t zd^|K|c`hX0{&+PCw;#l`@k7w1Ln~G8B6rC;%$S{nW5>_b+P@oBKV>rXnCn!D2jsHl zZ>U@Py~Dh-pns($kQq_Ntsco|!%l5n&d7vmOZ3H2n9Z5%?@~ zCZZzji>ja5Z)jivY3ITv=#)Yp80=%Dy&#TlGklX>l5f2c_YUc;a@QV%Z%@K2|1*hF zHqVM3C~06p9||{(!Bv-_QXh6XeHAm&*ta+sW~;#sQRb- z(O}B*3lL|y%{D_C8VWJ#Yat^VQeP5Yrxc00P#NqaoE|@lP zC{mL;sdw!0{hmYUKH@P-**jjXb#LhH2dJC}#iFddg+Rupc94z(s?Y<$f&7KzDtGPT zAaS32Y%FF@8L3KqbFs7>aowoTuJXRnVw*!IPv!<(mAE6M^F|F)OHz3cgtH8|a8l*2 zZMgbB^=dA@r9Qr0A|t}!aM*9{J#KpHXFQXlH+d{@n*Gy($SF zJ#T4;7atpsN~aT*RaMX{>6OwIP90Sgh&!t!em+%#*>e|>CGkvfd$3>3qz;80E|rxd z_E!5A$}UDE@hFsgcee(!sLJQ(khBw2fg4&;A@sc~R4%x@JNscw8hM8g?@^yUpw`>&Si?5jx8HFBYhu3pHXJ{hKQK@p*nomBCQ+9(D$0Gp z*c(6mcmx}_au3b^Nw;s+%(ndN^8Jgi4LF1}Kb+5D_mBVs+3m}SWtcr$P09xo#riCpbYHY6*sl>Jq4z$ zyb>QQwjAK~Al#v0=m1my=EkP2KjL6f04}YHA|G>NSMfFWp}O>ItutLs@uv}_iSy9f4CIcwftXuoBz z=8uzy)5Y?Axqd!bg51y7QOd5jt%sahL>^rZ7c9|JST~Ls5KI!ho)lfhtHvT6MN4f&3G{fU*y@lP?k{RXFR!Q zirAr1^lmy4h#&V8v9((pV9c;o#5XqSjMYGwI^O;GYnAg(v&1;edwCji|2`eDF?`3{ z_r-qhjRko9y(M%RYFpXq+t|Rkl{bS|mC(vA9ipUp!xV2i_GgPJ_YE?4;Wb#j{s$cR z$@`rF7V_CYjlrH3|G@Zr29S&_q_vpbSAXiY4=`)aN2;WDHH{JRZRxU@?x&cS=+N|> z0d(njSqbmRCicP+Z=`f>hve=zshl-$FK`Wn@Zs_;srId|!viDlz~Z-N;BektJT+|; z;^ORuaiwMDnE2QnyztgyD*^mQHtDERUdiM2PF&xXUXVtAvyAlB(3RFUyaB!3zkW57 z_54(%*$n1at|QMw4Of%+MrcQ3#x;x%NQylNj$+&+uVTwCo(o%jiE59CjD_s;FeS|D zn@C4i&urt{MB3&SQfNO>((9+S18blk-l%f+NQjNbk#(7fG3IuL9;Z{sKXR5(HUAKo z%BzejA565?w?S`zhst@tqb#kEm3+()P-gey+sGR@?Un1hlj{Cm>GAjULv$U9nYVcd zdf)p5roWJbi)EET7t=WR>$|CpS2nPioTzD$^VO>ddQ^hz;ZvLN&8#WoxMvjP6LUji zZchEAJ?32r6^wkNI$Pn^gK^&r18>))k#Qw4_vU z{8vrNDk|{Nl6B}e_RmNi^}krUc1uVvn?XA|cXO*Rr3%m58C(%GD}}ldhNxcQ=gsX} z=|kfN2T@9i@`@^~{B|22qON1B)C`QB{x^J6xI6Sh5?W#hI(Ie>Ge|QvH0+7pW?D39jDvaqhX`X1X5g~wWD&1qF2dUUUHGP87tUYg+cDMq zs|zXV+o(ksy&i-f-9(jmz$<$EMrJ2po)Yffs%Q41H+Wqm@5q=Y#`ES@GTqfb2_@%T z&k5<&hvu5Xuin`4;}K(Y>G-L$s^kjm@^@h7D<5Ln+O0}VhJ~yfF&WV+g?y)}n9S0e zVltlExE>YRL~pr^tq^)8S?N2FymE~N4%%}#Pj%58n0#+Pyzz8~ddJ0C61`<=8X_XX zDZHAChSBbmrzbu>2lGDrM&;@rK@G7?dBAF+0=AM~)VdeCvMxMD%Sz#gWqFY(uShK% zqRZX%5$jtSPBJ96Ql5~-gCjNj(wttn^jlo2sKogH>}QBs)9y;nUBD;H{fm2p3P1hP zb%gb*4+0CW7L)N_d(#VeHVKbHnLe86DB29?UcQlLo;61^hMh zbNqPtXFQqlAL!V&#g+HyW#zhU$R)w+3rEL+&|CGgXxRDDMA?Om&*r0vOnUwk^!7_C z=K=qt*tHCLaY)zZt8)Z(Vq_;{GO`8oNfPsAm2tzXpEQu-HQIf?%6Y&SPwzy*d%}&b zf`0=vK9`$)&T7ers3dK?V=icRauqLMMk#*s);sJ+Z@C9r7J3Cao&GF$rM<%kBs&j- z=y)f!=)Ml_8i0<`(cw-w>6mTIkXa5<#Txj;wke6U{8%Zlic;1~w9y{5bH{+4|AOu# z_^&TSRJ;*O>v22_(5D3Xnv?_e>>w_Lb(yrnL3|>qyY$&pmLbsS;HLmI}7E;pIRAlZXiE~GRL+hcRCSij;qHYFRq?Sl6c$+?u zjavG1J$W|SC~Aa4zue_z(!Qfkz0S**1+*Y5KRX%7jXyi^oGj6-vvKQ2k4f}LNajt5 z^6ALzTZap>)+Bv11^*f^L1VsPmKXRzRO8vnQ@mvGA@KUkyf9247`~AwA;h=Tp+3W6tSHR%QX5IT=i@!C%|I}UY@PG`P=e9TO0 zc&^PK2Jj#~zbEbfX-W;JEp*@GA7uBxvY)Q-AS1sUqqA@+DE~$UtHYraavO!zwGbd5C>`I2KenQO<*~d?)@$&(4ADzZ_ nGRQ5CveHA&dG+}dYQX;k6d8Qv8i;)j00000NkvXXu0mjfe}R$- literal 0 HcmV?d00001 diff --git a/src/assets/img/doge.png b/src/assets/img/doge.png new file mode 100644 index 0000000000000000000000000000000000000000..d99fa2ff2a6b1c969c23a22d9d265fa2c872a9ac GIT binary patch literal 1798 zcmV+h2l@DkP)m>denkSs zAba6f4~k2CXk5I&G6xDlBEQ&Qgdo#_?Sf#Xq6CVgH3E4OC`*PgSSHzlhGEq9Di9{X zWA@@}C_GR&5TuoZd5qjV1dV+VUrS+39-FvS1ksyEHsH$D1!!`F>BQBEXfOf3CJ(+w z{u+u;Bq`j)X^R3^wgrJkg(>S-rEE1-qrzkhmCEFC0P-jxS?5^^y*5u)N{`w^RzVB5G)_FlEmER%=`PrI@wu?G;X^=#>R3f_A0^2~DZ)x!2C> z8yp`;@}Z^48rmaju2cJbrxAh;aro+%F zZ`@d4{vYhkAG^WE+7i_<4bD&27!SiG4A8Bv#ljeb`XLomZP{KUV=a9G6nB+`iSE(x z6qp$Klxp9q#*;zD(cXkK)CmL=q^WY5LSl)kEvsaCYNtjNb5EAJ$*-wQpK%k#C8UPN z1C@VrfViK@cErckTf+&% zQ>A(f$v^HidMElvn)+W6Kxb~8O9@Km>Q{X_0#KS@Lo0hIfYP@7XiYvMvI!c@P5C@s z1OfGk477p(G`4h?Wi9VPK)u4kG&K=@=*DW8WnlIS4b;}yPTc2#f7rkps3c_iQffdM z1#!R7{56)fyd0=v5Y%p zVa)#N7rQ~@VY-`izT4+*EX_T!^i(`h)ZjqRgw`MGrrJLmnGP^EcWJ9qLbDo12HH@9 zuc&4-3Oq(zYfg{jOpl&rshyGd%#g&=6aAvISj;vf#4-b{ewrc7N@CKUN&cB03Pu*L zvwXJca=Kc+uULT6nr$w!x)KP^dit!4zqT*2mIv7EJ)%YXbZOF`KcBX;Y=+?I?nwcf zOj<;kH?DT-7zd&hX4`<`wTyhC!CZ~bheofw#{;G>dHpA$XMw~6(AW>}@8dKXEQM93 znRKXO!eurHubFfyO^uMWFZ-L?gE^qCi0ZE*!{r5?DysKcP<$r zNE_$Vb*1~I+-zi&TQOhQiq+&1|2yZCj9+5J-Mgy_cW;hN+Bi?AdDfwAD>0I zCWX7$us|t9(7Gu)5)9fWNNJJB(GWl>$RvUsB5EazVAH+?iXc;TbQ8TK57#9N ztZ<+dB>2U&h9I55CMj4`OQ0C70pvLGmnAbZlDzAG(9{b zjUjUsYElVMG;vdd=q)1~i1WGtE})oGF8Uzw)Dy50Jh`iDpa|3SvA=ZVSL1G>x&j&? znA}jAfd&vJ7gQ#o7=Sh!*k`i%)F?}!G8jM53@}WBzn!U~G8nWo-GHePj|^eX&2REp z0WE|qOXPO7imD<|^qaW=1|gOp)leni0gA!GC5VIpJs~k*lG7XMFP!i zJKN&=yv)}fWvLXhs;QwV6<0UhAK^N0T^&$IR)!ARS=3Osvitso9m3nC-1Cr1#P}znc4L^@I#hH8ig3O2%S6eoU8~B(4Qep6Cwc=GM1e zJ%M6ZNm;*hn4{dxY-*>S#c1CN8X8q~1(EaZx-__L(sPmzHm%F&y zb(PN1BriSjp-K{ZUjJFi4eb2d*CN3;l$kqc|I@h){h>{mZwR0|m7&clz7!&Ky#n2) zl}w(z`|w4ps>w5;kS~JYoVYQ_mCP4qbv;ksuWgZ)^}LpueX|#)eLoSa+r%L)dh+U{ z>PH^xedq+OVnp~$&`8~3dIFRudG}fUUIw%v)7*KIcc%cPVY|*r3IJ5vqS9eOsS!kT zpU4IP-IJ-IR^gq8@c0>pWmD<&S#lQ#?NzE9k10fn^5q~n?BPi|{H zb281)s$FBTE3Q8WZipszI*XXivNRMR*g^Pgb{(G&#hJKS+26$5uJe((XMtt0QUbG= z`k;w4 z+z5*;2#MVYE5K0YZPgY)sPZ=xv_TEGyA%Z!p@ti>iUeu_o2G|*4FYq9f~;%bfN)c5 zOF5~zj2~H$H?da0000K~#7F?OJ_o z6vq{RGrRX;`_6YZHV(0Ukn&MJB?u-;swO2;(=-qo2>1*nX+%hqG%8iqf2#D4QvONR zHmxc_Tct{YAPV-G64X?65=cou6qFK*ihwqy7;|Ss0e{_xeIL6!uW!%xdCy+kw}%hh zh@Wn6cV^zqynQq8&6_vNpum`YI67Tb#Ti7Xgh>Q4yx5o0>bjqv7J>g$$Z$)*ID&{X z&X1cGBR)X?)4&oK8+uw8Kzl#-t{O_KB6hWXQ|(7E#c_*-uY+|2>r2;|mG}bTb6{Ec z!-znb&ZQ$S#j!;&q*t00yuR8$LSBsKj$F4k6`pI~0RvbZhi56LdDtibx&SA(( z%qfvxgIz$T01ABE8U zGw?HQWSe&fBA=C&=ss%VKA_Qp^bf~of(RMIC!FATke;8;o^2eS5BW=f2YISpM}zw~ z_5E*{Y|x7bH+gALwY4OhBv=I^sa50%z4}^8*+-XyLc&%}YEEZ}Kd!~_*G3k6CV(E9 z!C`9qKClSdp*-r{+v_n1pPg}Gs1a@wD6}3Z5Q6@)4{2Wh8Z2T~bJ$O}FJ)ySHVf2N zyCCTfHhAozdXG($ODj+lTWEk=4U~-V>g>Zf-B6d*Ap8TmFU(|-^`&bU3bB@kvQ7iB zOuuM%e=h>xNNvW3tAn?s)ZsFi9o&81zc^*e{GJ{!mcYHVQJtZuHK*-^_BF*FX0(h; zHn51=L%nsfhQ<1`kkuHARGe?y!V;q!XQ&+v@8c4@3>H8_c_}+Bc7+M2ODDg|of)_RC4;LK7`~8OAy3`cBHeQ|Uo2#x-?C4urJOZxQXT1I_NzS?SJZ-oP zE=9Sv55~plH6ty2l6*`B5j3mflpRk{#X4gi#$!$>95{IeONEGj!>mxNt%{&Qg(rg2 ze>a&1H1Lb3uRi4sPE@bz=!Ii6pEKG=gR!`#xxFm?45HddON;Eu9)EclEMjQpCyElx z)K=4|E*+h#LBS!!e6#Gfm5@T+E6cf=RIM>h-c6@&z9y=7>Q{9N3Z=`CRn9bLdJxI3 zXGLf!YIqUyKw9`r2sNy9#LWnBOux0jKv86xPx{XQClp?$8O}?MX_4rQ=UNxyQDwMW z=CDJFlzx`7*ELN^TAuYf24+5&kh#mvUx-EqZUe}}Fz+|eOcO2lm=sysEH#yiUAfnF zd50YmvNZ{NJS`)kDp_rkk6~$Flc_h*u#l3Gq}_}Fk+;Kb0Quymi|VYt6*k&M+95}v zre>K_6zI;es%~;!nR*N&YM(Ob4f1Rg&7lnP03Ynd>Git3<`mj{x~f9~L4qE&!I3zB z&x}?rk&9`^R17(ST;B^>X&S$UfwL11-kdOMi8nm{|mWln@RfbQ1Zj{rQttdGJ$Fn{a+?qbCnWjXnKCXZG(HSIdSP6viLdA z-cW<5Rd+8l8RSXDz&GKpG>Pgf0LCzhIC=HO>VEx6lkB>;lrf96e1EPc&{+)@F=YS9 z;g`QK7E!3)-5BzF9t*;|59wF?bF*H7Nkpij{8ic&F4H7fqB#2=2sV`M7|SCeMpuIs zq}#!_jZKg(-8R8=;-;&)0U3N$vON?PHRuaEw5L% zl8!G1iwJITpYt7xY$G54m-PP9KrVCAJ3l)RfW<*0VxnveuA>Gowr#m5E8IZ~@S7BL zdyXc8fgiSnT3cf331dt>qto zY^!dJ%&Tn-liK48kSBuc-EU~9ts^1m>sAhtQS2fSwg`&*hcsokft@6tdG zI5iC7y|OJa*2$1Qzu3rtr%k@N1}gbSEU4b08Wcg^io=Gvo7KW%$G2U7T8$HTf? z`_bTa^PtV(Wq`lKz-5Yi_V>)xY+G|@e9*ru4YWKQtv_8U2J-a;34s+6mrI4ptQy%|WmHssSran*qABz0E UFWAIlcK`qY07*qoM6N<$f{LrPWB>pF literal 0 HcmV?d00001 diff --git a/src/assets/img/qort.png b/src/assets/img/qort.png new file mode 100644 index 0000000000000000000000000000000000000000..39d090f724b9c2708a771b0208dd41266d433cdf GIT binary patch literal 1907 zcmV-(2aNcMP)|H@`8$}eJETAGPXj)W25R?Ukkb0?o>#feEH&j>ZjYC{+oG`zj+g}jp#Eota zy;VvgZoPDK>n+ZKNC>sqA|RlG+EhhU2*P~ZnP9uS_Uz1?nT@qiS~*_N&c6Nf=Dj!H zyxmOGX0pw+NykuJdOOhP~gi*V948deV=bpF*|A2Bu zI{ahPVdS|i#QPO|PN@24C7cI;P^qL!*`p{~IUUweslF22PsfAH#fj&uJpYw!Hb zdVl;~N=sD&R0N=|i)4NA#0#ulKf|tHI6Jl7je8GSXZLqDc>0g4NkB~{P^k|2#08kG zbBpQFo&_cZZF--6m>%OmmIVgp7AkVHRoi|t;s9M-dPVE_or6DF#4R>Ccw!sab#A3? zZ9v8BVbi9c1dyvlR<^M}NP)HNU$0E#S#tpuezRvQ2m#1;{dIQgL_pf_@aezYxBiv_ zYcWWLdH!_T)xI(cT(yZ>ozo@%j$)f&(Db`7r2E~`&X1hFky9N`2bK>040lE-MtYo2rX}?KvM&y&x zg*U7WZC(Ew-TO7oUy0<}B=esIXwNj~L>dH(Smsf@jMC>>K|)}u7X02Om~Zw&l8 zPh$Y2PCC;O$F9?*LRtncS52jbHhgG-DEl4<1HQ|I*Tk{t1AU=SPtx!PDE#CV?gtyU zdrBz_BCtvnMqlU?efQll`eT4Du(fZ%Dm~Keg-185Oc1h&ND$6Au1FNtVYK+rH39WB z05u{)iU4~0%Wsv3b{^?mluU+YKlqK~pz=)9NI zI8E?_3IkfH0IdM60IdM6qyn@8be;hnRxpss5P)`lYXM5nguleG=%WPE1)u}pT5R2a ze6&nlWPJ#2kn*;M&Ul*!a@J;+=i!an?l zHjcSY6-k_0Xc7Jr<%d`wy2gQnkHm(*vCl$jBAE|OD@PVO``UNK6iwJAbb2gHJOJdF8__-FE>AamnB!jv=CRt4U}+rKR4V*6Z^!62C^8|uvjZS zwgim*|A30S8oVX=pV!Z%{uKqfMWuaotXIZh&?#zHxYVN)?F>Q%MQJPU=isLm>jVe`li7eZ0gtBO&O6BUv5Z#4b_PsMTa6fs#(uR5iKFD_blZy;kcA}tFYOoj)L5TK2SiV3_hsM%L4(yxH$dR32Ts%rh8_dFh`U2Hs zdSv%uf+F&FUHMdx($@h~%R)yiwR#{cC7>g~f*@F(6EJ5!ip@Hp0#w}E93Nx9IutV? z<8?I>)>bGIQWGkU1UiRQ?+vM53{ch=17rXTVkKhLt1GMkTfJPx0 txTCL73&mFC6>0)ZFgHh+XWI*A(+)*H2Pr02S_y9H;q2nn5YxCa+3PzDjTu9%eSn>fgNpp|wG zHjtJ;Imi~axgfP9g2!bQSkr+rkmwf!DF{*yY!d?;Oi7?TS|iA(A-$xHgEb{PaF`gi z!)XW;_%Vn1cc2H#4y2Xc9I!ERTOoMt2iSKBkeNI;@n8x>Z!59^f1)nHkswSTuTmBo zOyJ)s#J{8U8p{7sFwIR|Z&BbkS`auEVXFGopixcLt)Zy^^Qp&u@YtgdLT08Dsw+z& zcX<|!j!nX=uLq!`vo9qyRToemfI<|>dT#DA*tN3(c0Jo507NU%?ShL)x!Y_fBEf~FGpdbTz*5HlV4}MOBi?=4oGirTShmP9Zc0m(I4V4PQT~l5Nz<&RAwX4Bf zT?UcJAY8vb0w+#(!lrt+?7r}G=n9@>0Zr*W1|`7R$cj_#gH#b615jD%y?>3S?Q}Z8 zwYC_tvYfD<0YzEv$`X9&z`!l$4kD13mmT9CEHe87&Zbef$@3Q65vug)aN8cie0#6l z01wl|Jvg$gFZz{ovzdy<*^%_vBG+}Sk%cc-SI#+ywvomv{Nq0N-qdFSpF z+!>pKr7WUXtSN%hmH7$n3sWi!%TSPE7MQ1@y!k=a->hO4&cx(hxHU2X;qE~={#PfQ zJ=Y`nNuy%3+1E=uQqEM+PBc;f_VwWPl*vZ&GiM{PWQhYV_uha!mhewc&p;t7GfRr| zWAat0w%hHk*wz#ew2{o*nQxq7`S8V#KBissUHC?xKGkignD-i%mQyn`(Dm;?w4LXw zD7O16G{z+Mlr=lbyKgo^rMrar%|g}0-H2daBXlT;e8I@x*fgW*FS7_`%cyD5vZFIsI*L!M)+hPOioV4bffInP&Xw^sYzm_ zj|LT1yJJ%%p#s}=FAv2AvyDRQL$T(L7mW0xV4|OhWJr7{g@zWSg1Jj0y(s17_ZhC` z@%`f99#&DKqZ4+1r2+>Kid@Ydjr2^g+k_>h5s7r))9~NzHFrTsfl7yo<0HK&`T5z# zG*qIIXY4h1TA)fDq4-+fy|y?eQP&cj_eA7BX@M&BETxfNE>YK#+v9US7iW)92pLeh z2rn1u#S|+3IVCA7$|KWGQlM(%KGH}ZeQso2Um}>FGY2&EKLU!)3b{_ZT%;ETCxPME zyP9B`iTlM{8^@I90Ub^y?Ual3Vw0oy>P^+pjqnIhW$wrlfrjk09C4@k2Kfl~lt*)W6kzPllpOc+Mt)XEO4HXC7R4X2ZsIHdiM!VWPt`# z$$zRvdNI*IezH^cH5^VM)J~M3?Hant=hpQ;xkxWc_OeXb=W+O$7--1B&unNd?F|bX1p|rJVs~54M|2X<)p@29!>N!GJveyl(LfoZB3O3FUshM`tSuN`r@?lirf(X1x%x}II^=dHQ%#g-D>#k^Ft)#M{>;O zou{;Q$6oa8rq8p-nQ-sCp?{4RY{7l>$wBHwU9&=F+8N`=EJ74sv;%rRMb$e zr9)~TG*oiRbm%eg?0l{@-CzoerndHoYUa%A(|u+}cp>nxyzwojnKn=4GDE)6S~XYi zsyGR+B8Ef8KYjOFx(1&3ib!+nr&H(7{E*->L!x$K;Av$kQJP8wbWWYOd?74c?g9tR zhEVGi4pzgw0!n&Z&6N3}{6O4hHdO3vbl|a@b={D~3j?I; zg#l#1Vq>KR7B5|43E0Jpt5^Vb@$x?w!d<*Tm4$Gnmr!%_&B!IxhWIT)B)^2(e*z2u Xq@DHT-WO?J00000NkvXXu0mjfNJg50 literal 0 HcmV?d00001 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/AlignCenterSVG.tsx b/src/assets/svgs/AlignCenterSVG.tsx new file mode 100644 index 0000000..b78991b --- /dev/null +++ b/src/assets/svgs/AlignCenterSVG.tsx @@ -0,0 +1,21 @@ +import { SVGProps } from './interfaces' + +export const AlignCenterSVG: React.FC = ({ + color, + height, + width +}) => { + return ( + + + + ) +} diff --git a/src/assets/svgs/AlignLeftSVG.tsx b/src/assets/svgs/AlignLeftSVG.tsx new file mode 100644 index 0000000..4ac2eb4 --- /dev/null +++ b/src/assets/svgs/AlignLeftSVG.tsx @@ -0,0 +1,17 @@ +import { SVGProps } from './interfaces' + +export const AlignLeftSVG: React.FC = ({ color, height, width }) => { + return ( + + + + ) +} diff --git a/src/assets/svgs/AlignRightSVG.tsx b/src/assets/svgs/AlignRightSVG.tsx new file mode 100644 index 0000000..2a2eea8 --- /dev/null +++ b/src/assets/svgs/AlignRightSVG.tsx @@ -0,0 +1,17 @@ +import { SVGProps } from './interfaces' + +export const AlignRightSVG: React.FC = ({ color, height, width }) => { + return ( + + + + ) +} diff --git a/src/assets/svgs/BoldSVG.tsx b/src/assets/svgs/BoldSVG.tsx new file mode 100644 index 0000000..8d06816 --- /dev/null +++ b/src/assets/svgs/BoldSVG.tsx @@ -0,0 +1,17 @@ +import { SVGProps } from './interfaces' + +export const BoldSVG: React.FC = ({ color, height, width }) => { + return ( + + + + ) +} diff --git a/src/assets/svgs/CodeBlockSVG.tsx b/src/assets/svgs/CodeBlockSVG.tsx new file mode 100644 index 0000000..1fad02f --- /dev/null +++ b/src/assets/svgs/CodeBlockSVG.tsx @@ -0,0 +1,17 @@ +import { SVGProps } from './interfaces' + +export const CodeBlockSVG: React.FC = ({ color, height, width }) => { + return ( + + + + ) +} diff --git a/src/assets/svgs/H2SVG.tsx b/src/assets/svgs/H2SVG.tsx new file mode 100644 index 0000000..0328fc3 --- /dev/null +++ b/src/assets/svgs/H2SVG.tsx @@ -0,0 +1,17 @@ +import { SVGProps } from './interfaces' + +export const H2SVG: React.FC = ({ color, height, width }) => { + return ( + + + + ) +} diff --git a/src/assets/svgs/H3SVG.tsx b/src/assets/svgs/H3SVG.tsx new file mode 100644 index 0000000..7268032 --- /dev/null +++ b/src/assets/svgs/H3SVG.tsx @@ -0,0 +1,17 @@ +import { SVGProps } from './interfaces' + +export const H3SVG: React.FC = ({ color, height, width }) => { + return ( + + + + ) +} diff --git a/src/assets/svgs/ItalicSVG.tsx b/src/assets/svgs/ItalicSVG.tsx new file mode 100644 index 0000000..50a5493 --- /dev/null +++ b/src/assets/svgs/ItalicSVG.tsx @@ -0,0 +1,17 @@ +import { SVGProps } from './interfaces' + +export const ItalicSVG: React.FC = ({ color, height, width }) => { + return ( + + + + ) +} diff --git a/src/assets/svgs/LinkSVG.tsx b/src/assets/svgs/LinkSVG.tsx new file mode 100644 index 0000000..9994f43 --- /dev/null +++ b/src/assets/svgs/LinkSVG.tsx @@ -0,0 +1,17 @@ +import { SVGProps } from './interfaces' + +export const LinkSVG: React.FC = ({ color, height, width }) => { + return ( + + + + ) +} diff --git a/src/assets/svgs/NewWindowSVG.tsx b/src/assets/svgs/NewWindowSVG.tsx new file mode 100644 index 0000000..c97d483 --- /dev/null +++ b/src/assets/svgs/NewWindowSVG.tsx @@ -0,0 +1,25 @@ +interface NewWindowSVGProps { + color: string + height: string + width: string +} + +export const NewWindowSVG: React.FC = ({ + color, + height, + width +}) => { + return ( + + + + ) +} diff --git a/src/assets/svgs/UnderlineSVG.tsx b/src/assets/svgs/UnderlineSVG.tsx new file mode 100644 index 0000000..a65f597 --- /dev/null +++ b/src/assets/svgs/UnderlineSVG.tsx @@ -0,0 +1,17 @@ +import { SVGProps } from './interfaces' + +export const UnderlineSVG: React.FC = ({ color, height, width }) => { + return ( + + + + ) +} diff --git a/src/assets/svgs/accountCircle.svg b/src/assets/svgs/accountCircle.svg new file mode 100644 index 0000000..2edae3e --- /dev/null +++ b/src/assets/svgs/accountCircle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/interfaces.ts b/src/assets/svgs/interfaces.ts new file mode 100644 index 0000000..6a0d5e1 --- /dev/null +++ b/src/assets/svgs/interfaces.ts @@ -0,0 +1,5 @@ +export interface SVGProps { + color: string + height: string + width: string +} diff --git a/src/components/AudioElement.tsx b/src/components/AudioElement.tsx new file mode 100644 index 0000000..5b807ee --- /dev/null +++ b/src/components/AudioElement.tsx @@ -0,0 +1,230 @@ +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 AudiotrackIcon from '@mui/icons-material/Audiotrack' +import { MyContext } from '../wrappers/DownloadWrapper' +import { useDispatch, useSelector } from 'react-redux' +import { RootState } from '../state/store' +import { CircularProgress } from '@mui/material' +import { + setCurrAudio, + setShowingAudioPlayer +} from '../state/features/globalSlice' + +const Widget = styled('div')(({ theme }) => ({ + padding: 16, + borderRadius: 16, + maxWidth: '100%', + position: 'relative', + zIndex: 1, + // backgroundColor: + // theme.palette.mode === 'dark' ? 'rgba(0,0,0,0.6)' : 'rgba(255,255,255,0.4)', + backdropFilter: 'blur(40px)', + background: 'skyblue', + transition: '0.2s all', + '&:hover': { + opacity: 0.75 + } +})) + +const CoverImage = styled('div')({ + width: 100, + height: 100, + objectFit: 'cover', + overflow: 'hidden', + flexShrink: 0, + borderRadius: 8, + backgroundColor: 'rgba(0,0,0,0.08)', + '& > img': { + width: '100%' + } +}) + +const TinyText = styled(Typography)({ + fontSize: '0.75rem', + opacity: 0.38, + fontWeight: 500, + letterSpacing: 0.2 +}) + +interface IAudioElement { + onClick: () => void + title: string + description: string + author: string + audioInfo?: any + postId?: string + user?: string +} + +export default function AudioElement({ + onClick, + title, + description, + author, + audioInfo, + postId, + user +}: IAudioElement) { + const { downloadVideo } = React.useContext(MyContext) + const [isLoading, setIsLoading] = React.useState(false) + const { downloads } = useSelector((state: RootState) => state.global) + const reDownload = React.useRef(false) + + const dispatch = useDispatch() + const download = React.useMemo(() => { + if (!downloads || !audioInfo?.identifier) return {} + const findDownload = downloads[audioInfo?.identifier] + + if (!findDownload) return {} + return findDownload + }, [downloads, audioInfo]) + + const resourceStatus = React.useMemo(() => { + return download?.status || {} + }, [download]) + const handlePlay = () => { + if (!postId) return + const { name, service, identifier } = audioInfo + + if (download && resourceStatus?.status === 'READY') { + dispatch(setShowingAudioPlayer(true)) + dispatch(setCurrAudio(identifier)) + return + } + setIsLoading(true) + downloadVideo({ + name, + service, + identifier, + blogPost: { + postId, + user, + audioTitle: title, + audioDescription: description, + audioAuthor: author + } + }) + dispatch(setCurrAudio(identifier)) + dispatch(setShowingAudioPlayer(true)) + } + + React.useEffect(() => { + if (resourceStatus?.status === 'READY') { + setIsLoading(false) + } + }, [resourceStatus]) + + React.useEffect(() => { + if ( + resourceStatus?.status === 'DOWNLOADED' && + reDownload?.current === false + ) { + handlePlay() + reDownload.current = true + } + }, [handlePlay, resourceStatus]) + return ( + + + + + + + + + {author} + + + {title} + + + {description} + + + + {((resourceStatus.status && resourceStatus?.status !== 'READY') || + isLoading) && ( + + + {resourceStatus && ( + + {resourceStatus?.status === 'REFETCHING' ? ( + <> + <> + {( + (resourceStatus?.localChunkCount / + resourceStatus?.totalChunkCount) * + 100 + )?.toFixed(0)} + % + + + <> Refetching in 25 seconds + + ) : resourceStatus?.status === 'DOWNLOADED' ? ( + <>Download Completed: building audio... + ) : resourceStatus?.status !== 'READY' ? ( + <> + {( + (resourceStatus?.localChunkCount / + resourceStatus?.totalChunkCount) * + 100 + )?.toFixed(0)} + % + + ) : ( + <>Download Completed: fetching audio... + )} + + )} + + )} + + + ) +} diff --git a/src/components/DynamicHeightItem.tsx b/src/components/DynamicHeightItem.tsx new file mode 100644 index 0000000..a6ea00d --- /dev/null +++ b/src/components/DynamicHeightItem.tsx @@ -0,0 +1,96 @@ +import React, { useRef, useState, useEffect } from 'react' +import ReactResizeDetector from 'react-resize-detector' +import { Layouts, Layout } from 'react-grid-layout' + +interface DynamicHeightItemProps { + children: React.ReactNode + layouts: Layouts + setLayouts: (layouts: any) => void + i: string + breakpoint: keyof Layouts + rows?: number + count?: number + type?: string + padding?: number +} + +const DynamicHeightItem: React.FC = ({ + children, + layouts, + setLayouts, + i, + breakpoint, + rows = 1, + count, + type, + padding +}) => { + const [height, setHeight] = useState(rows * 150) + const ref = useRef(null) + + useEffect(() => { + if (ref.current) { + setHeight(ref.current.clientHeight) + } + }, [ref.current]) + + const onResize = () => { + if (ref.current) { + setHeight(ref.current.clientHeight) + } + } + + const getBreakpoint = (screenWidth: number) => { + if (screenWidth >= 996) { + return 'md' + } else if (screenWidth >= 768) { + return 'sm' + } else { + return 'xs' + } + } + + useEffect(() => { + const widthWin = window.innerWidth + let newBreakpoint = breakpoint + // if (!newBreakpoint) { + // newBreakpoint = getBreakpoint(widthWin) + // } + + setLayouts((prev: any) => { + const newLayouts: any = { ...prev } + newLayouts[newBreakpoint] = newLayouts[newBreakpoint]?.map( + (item: Layout) => { + if (item.i === i) { + let constantNum = 25 + + return { + ...item, + h: Math.ceil(height / (rows * constantNum)) // Adjust this value based on your rowHeight and the number of rows the element spans + } + } + return item + } + ) + return newLayouts + }) + }, [height, breakpoint, count, setLayouts]) + + + + return ( +
+ +
+ {children} +
+
+
+ ) +} + +export default DynamicHeightItem diff --git a/src/components/DynamicHeightItemMinimal.tsx b/src/components/DynamicHeightItemMinimal.tsx new file mode 100644 index 0000000..b80d53f --- /dev/null +++ b/src/components/DynamicHeightItemMinimal.tsx @@ -0,0 +1,39 @@ +import React, { useRef, useState, useEffect } from 'react' +import ReactResizeDetector from 'react-resize-detector' +import { Layouts, Layout } from 'react-grid-layout' + +interface DynamicHeightItemProps { + children: React.ReactNode + layouts: Layouts + setLayouts: (layouts: any) => void + i: string + breakpoint: keyof Layouts + rows?: number + count?: number + type?: string + padding?: number +} + +export const DynamicHeightItemMinimal: React.FC = ({ + children, + layouts, + setLayouts, + i, + breakpoint, + rows = 1, + count, + type, + padding +}) => { + return ( +
+
+ {children} +
+
+ ) +} diff --git a/src/components/FileElement.tsx b/src/components/FileElement.tsx new file mode 100644 index 0000000..fee23cb --- /dev/null +++ b/src/components/FileElement.tsx @@ -0,0 +1,445 @@ +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 AudiotrackIcon from '@mui/icons-material/Audiotrack' +import { MyContext } from '../wrappers/DownloadWrapper' +import { useDispatch, useSelector } from 'react-redux' +import { RootState } from '../state/store' +import { CircularProgress } from '@mui/material' +import AttachFileIcon from '@mui/icons-material/AttachFile' +import { + setCurrAudio, + setShowingAudioPlayer +} from '../state/features/globalSlice' +import { + base64ToUint8Array, + objectToUint8ArrayFromResponse +} from '../utils/toBase64' +import { setNotification } from '../state/features/notificationsSlice' + +const Widget = styled('div')(({ theme }) => ({ + padding: 8, + borderRadius: 10, + maxWidth: 350, + position: 'relative', + zIndex: 1, + // backgroundColor: + // theme.palette.mode === 'dark' ? 'rgba(0,0,0,0.6)' : 'rgba(255,255,255,0.4)', + 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%' + } +}) + +const TinyText = styled(Typography)({ + fontSize: '0.75rem', + opacity: 0.38, + fontWeight: 500, + letterSpacing: 0.2 +}) + +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 +} + +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, + postId = '', + user, + children, + mimeType, + disable, + mode, + otherUser +}: IAudioElement) { + const { downloadVideo } = React.useContext(MyContext) + const [isLoading, setIsLoading] = React.useState(false) + const [fileProperties, setFileProperties] = React.useState(null) + const [downloadLoader, setDownloadLoader] = React.useState(false) + + const [pdfSrc, setPdfSrc] = React.useState('') + const { downloads } = useSelector((state: RootState) => state.global) + const { user: username } = useSelector((state: RootState) => state.auth) + + const dispatch = useDispatch() + 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 saveFileToDisk = async (blob: any, fileName: any) => { + try { + const fileHandle = await customWindow.showSaveFilePicker({ + suggestedName: fileName, + types: [ + { + description: 'File' + } + ] + }) + const writeFile = async (fileHandle: any, contents: any) => { + const writable = await fileHandle.createWritable() + await writable.write(contents) + await writable.close() + } + writeFile(fileHandle, blob).then(() => console.log('FILE SAVED')) + } catch (error) { + console.log(error) + } + } + const handlePlay = async () => { + if (disable) return + if ( + resourceStatus?.status === 'READY' && + download?.url && + download?.blogPost?.filename + ) { + if (downloadLoader) return + dispatch( + setNotification({ + msg: 'Saving file... please wait', + alertType: 'info' + }) + ) + try { + const { name, service, identifier } = fileInfo + + setDownloadLoader(true) + const url = `/arbitrary/${service}/${name}/${identifier}` + fetch(url) + .then((response) => response.blob()) + .then(async (blob) => { + await qortalRequest({ + action: 'SAVE_FILE', + blob, + filename: download?.blogPost?.filename, + mimeType: download?.blogPost?.mimeType || '' + }) + // saveAs(blob, download?.blogPost?.filename) + }) + .catch((error) => { + console.error('Error fetching the video:', error) + // clearInterval(intervalId) + }) + .finally(() => { + setDownloadLoader(false) + }) + } catch (error: any) { + let notificationObj = 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 { + if (mode === 'mail') { + setDownloadLoader(false) + } + } + return + } + if (!postId) return + const { name, service, identifier } = fileInfo + let filename = fileProperties?.filename + let mimeType = fileProperties?.mimeType + if (!fileProperties) { + try { + dispatch( + setNotification({ + msg: 'Downloading file... please wait', + alertType: 'info' + }) + ) + let res = await qortalRequest({ + action: 'GET_QDN_RESOURCE_PROPERTIES', + name: name, + service: service, + identifier: identifier + }) + setFileProperties(res) + filename = res?.filename + mimeType = res?.mimeType + } catch (error: any) { + dispatch( + setNotification({ + msg: error?.message || 'Error with download. Please try again', + alertType: 'error' + }) + ) + } + } + if (!filename) return + + setIsLoading(true) + downloadVideo({ + name, + service, + identifier, + blogPost: { + postId, + user, + audioTitle: title, + audioDescription: description, + audioAuthor: author, + filename, + mimeType + } + }) + } + + React.useEffect(() => { + if ( + resourceStatus?.status === 'READY' && + download?.url && + download?.blogPost?.filename + ) { + setIsLoading(false) + } + }, [resourceStatus, download]) + + return ( + + {children && ( + + {children}{' '} + {(resourceStatus.status && resourceStatus?.status !== 'READY') || + isLoading ? ( + + ) : resourceStatus?.status === 'READY' ? ( + <> + + Ready to save: click here + + {downloadLoader && ( + + )} + + ) : null} + + )} + {!children && ( + + + + + + + + {author} + + + {title} + + + {description} + + {mimeType && ( + + {mimeType} + + )} + + + {((resourceStatus.status && resourceStatus?.status !== 'READY') || + isLoading) && ( + + + {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?.blogPost?.filename && ( + + + Ready to save: click here + + {downloadLoader && ( + + )} + + )} + + )} + + ) +} diff --git a/src/components/common/AudioPanel.tsx b/src/components/common/AudioPanel.tsx new file mode 100644 index 0000000..1d3d50b --- /dev/null +++ b/src/components/common/AudioPanel.tsx @@ -0,0 +1,253 @@ +import React, { useState, useEffect } from 'react' +import { styled, Box } from '@mui/system' +import { + Drawer, + List, + ListItem, + ListItemText, + Typography, + ButtonBase, + Button, + Tooltip +} from '@mui/material' +import VideoCallIcon from '@mui/icons-material/VideoCall' +import VideoModal from './VideoPublishModal' +import { useSelector } from 'react-redux' +import { RootState } from '../../state/store' +import { AudioModal } from './AudioPublishModal' +import AudioFileIcon from '@mui/icons-material/AudioFile' +interface VideoPanelProps { + onSelect: (video: Video) => void + height?: string + width?: string +} + +interface VideoApiResponse { + videos: Video[] +} + +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; + } +` + +const PublishButton = styled(Button)` + /* position: absolute; + bottom: 20px; + left: 0; + right: 0; + margin: auto; */ + max-width: 80%; +` + +export const AudioPanel: React.FC = ({ + onSelect, + height, + width +}) => { + const [isOpen, setIsOpen] = useState(false) + const [videos, setVideos] = useState([]) + const [isOpenVideoModal, setIsOpenVideoModal] = useState(false) + const { user } = useSelector((state: RootState) => state.auth) + const [editVideoIdentifier, setEditVideoIdentifier] = useState< + string | null | undefined + >() + + const fetchVideos = React.useCallback(async (): Promise => { + if (!user?.name) return [] + + let res = [] + try { + // res = await qortalRequest({ + // action: 'LIST_QDN_RESOURCES', + // service: 'AUDIO', + // name: user.name, + // includeMetadata: true, + // limit: 100, + // offset: 0, + // reverse: true + // }) + const res2 = await fetch( + `/arbitrary/resources?&service=AUDIO&name=${user.name}&includemetadata=true&limit=100&offset=0&reverse=true` + ) + const resData = await res2.json() + if (Array.isArray(resData)) { + res = resData + } + } catch (error) {} + + // Replace this URL with the actual API endpoint + + return res + }, [user]) + useEffect(() => { + fetchVideos().then((fetchedVideos) => setVideos(fetchedVideos)) + }, []) + + const handleToggle = () => { + setIsOpen(!isOpen) + } + + const handleClick = (video: Video) => { + onSelect(video) + } + + return ( + + + + + + + + + Select Audio + + + List of audios in QDN under your name + + + + + {videos.map((video) => ( + + handleClick(video)} + sx={{ width: '100%' }} + > + + + + + ))} + + + { + setEditVideoIdentifier(null) + setIsOpenVideoModal(true) + }} + > + Publish new audio file + + + + + { + setIsOpenVideoModal(false) + setEditVideoIdentifier(null) + }} + open={isOpenVideoModal} + onPublish={(value) => { + fetchVideos().then((fetchedVideos) => setVideos(fetchedVideos)) + setIsOpenVideoModal(false) + }} + editVideoIdentifier={editVideoIdentifier} + /> + + ) +} + +// Add this to your 'types.ts' file +export interface Video { + name: string + service: string + identifier: string + metadata: { + title: string + description: string + tags: string[] + category: string + categoryName: string + } + size: number + created: number + updated: number +} diff --git a/src/components/common/AudioPlayer.tsx b/src/components/common/AudioPlayer.tsx new file mode 100644 index 0000000..7cac33e --- /dev/null +++ b/src/components/common/AudioPlayer.tsx @@ -0,0 +1,192 @@ +import React, { useEffect, useMemo, useRef, useState } from 'react' +import { Box, IconButton, Slider } from '@mui/material' +import { CircularProgress, Typography } from '@mui/material' +import AudioPlyr from 'philliplm-react-modern-audio-player' +import LinearProgress from '@mui/material/LinearProgress' + +import { + PlayArrow, + Pause, + VolumeUp, + Fullscreen, + PictureInPicture +} from '@mui/icons-material' +import { styled } from '@mui/system' +import { + removeAudio, + setShowingAudioPlayer +} from '../../state/features/globalSlice' +import { useDispatch, useSelector } from 'react-redux' +import { RootState } from '../../state/store' + +const VideoContainer = styled(Box)` + position: relative; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + width: 100%; + height: 100%; + margin: 20px 0px; + z-index: 501; +` + +const VideoElement = styled('video')` + width: 100%; + height: auto; + 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 + title?: string + description?: string + playlist?: IPlaylist[] + currAudio: number | null +} + +export interface IPlaylist { + name: string + identifier: string + service: string + title: string + description: string +} +interface CustomWindow extends Window { + _qdnTheme: any // Replace 'any' with the appropriate type if you know it +} +const customWindow = window as unknown as CustomWindow +const themeColor = customWindow?._qdnTheme + +export const AudioPlayer: React.FC = ({ currAudio }) => { + const [isLoading, setIsLoading] = useState(false) + const { downloads, showingAudioPlayer } = useSelector( + (state: RootState) => state.global + ) + const dispatch = useDispatch() + const downloadsLength: number = useMemo( + () => + Object.keys(downloads) + .map((item) => { + return downloads[item] + }) + .filter( + (download: any) => + download?.service === 'AUDIO' && + download?.status?.status === 'READY' && + !!download.url + ).length, + [downloads] + ) + + const audioPlayList = useMemo(() => { + const filterAudios = Object.keys(downloads) + .map((item) => { + return downloads[item] + }) + .filter( + (download: any) => + download?.service === 'AUDIO' && + download?.url && + download?.status?.status === 'READY' + ) + return filterAudios.map((audio: any, index: number) => { + return { + name: audio?.blogPost?.audioTitle, + src: audio?.url, + id: index + 1, + identifier: audio?.identifier, + description: audio?.blogPost?.audioDescription || '' + } + }) + }, [downloadsLength]) + + const currAudioMemo: number | null = useMemo(() => { + const findIndex = audioPlayList.findIndex( + (item) => item?.identifier === currAudio + ) + if (findIndex !== -1) { + return findIndex + } + return null + }, [audioPlayList, currAudio]) + + if (isLoading) + return ( + + + Loading playlist... + + + + ) + + if (audioPlayList.length === 0 || !showingAudioPlayer) return null + return ( + + { + dispatch(setShowingAudioPlayer(false)) + }} + // rootContainerProps={{ + // colorScheme: theme, + // width + // }} + /> + + ) +} diff --git a/src/components/common/AudioPublishModal.tsx b/src/components/common/AudioPublishModal.tsx new file mode 100644 index 0000000..f733868 --- /dev/null +++ b/src/components/common/AudioPublishModal.tsx @@ -0,0 +1,366 @@ +import React, { useState } from 'react' +import { + Box, + Button, + Modal, + TextField, + Typography, + Select, + MenuItem, + FormControl, + InputLabel, + SelectChangeEvent, + OutlinedInput, + Chip, + IconButton +} from '@mui/material' +import { styled } from '@mui/system' +import { useDropzone } from 'react-dropzone' +import { toBase64 } from '../../utils/toBase64' +import AddIcon from '@mui/icons-material/Add' +import CloseIcon from '@mui/icons-material/Close' +import { usePublishAudio } from './PublishAudio' + +const StyledModal = styled(Modal)(({ theme }) => ({ + display: 'flex', + alignItems: 'center', + justifyContent: 'center' +})) + +const ChipContainer = styled(Box)({ + display: 'flex', + flexWrap: 'wrap', + '& > *': { + margin: '4px' + } +}) + +const ModalContent = styled(Box)(({ theme }) => ({ + backgroundColor: theme.palette.background.paper, + padding: theme.spacing(4), + borderRadius: theme.spacing(1), + width: '40%', + '&:focus': { + outline: 'none' + } +})) + +interface VideoModalProps { + open: boolean + onClose: () => void + onPublish: (value: any) => void + editVideoIdentifier?: string | null | undefined +} + +interface SelectOption { + id: string + name: string +} + +async function addAudioCoverImage( + base64Audio: string, + coverImageBase64: string +): Promise { + // Decode the base64 audio data + const audioData: Uint8Array = new Uint8Array( + atob(base64Audio) + .split('') + .map((char) => char.charCodeAt(0)) + ) + + const decoder: TextDecoder = new TextDecoder('utf-8') + const decodedAudioData: string = decoder.decode(audioData) + + // Create a Blob object from the decoded audio data + const blob: Blob = new Blob([decodedAudioData], { type: 'audio/mpeg' }) + + // Create a new file name for the audio with cover image + const fileName: string = 'audio-with-cover.mp3' + + // Create a new FormData object to hold the file and metadata + const formData: FormData = new FormData() + formData.append('file', blob, fileName) + + // Create a new image object from the base64 data + const image: HTMLImageElement = new Image() + image.src = `data:image/png;base64,${coverImageBase64}` + + // Wait for the image to load before getting its dimensions + await new Promise((resolve) => { + image.onload = () => resolve(null) + }) + + // Get the image dimensions + const width: number = image.width + const height: number = image.height + + // Create a new metadata object with the image dimensions + const metadata: any = { + title: 'Audio with Cover', + artist: 'Artist Name', + album: 'Album Name', + trackNumber: 1, + image: { + mime: 'image/png', + type: 3, + description: 'Cover Image', + data: coverImageBase64, + width: width, + height: height + } + } + + // Set the metadata on the file + formData.set('metadata', JSON.stringify(metadata)) + + // Create a new URL object for the file + const url: string = URL.createObjectURL(blob) + + // Create a download link for the file + const link: HTMLAnchorElement = document.createElement('a') + link.href = url + link.download = fileName + link.click() + + // Read the downloaded file and return its contents as a base64 string + const fileReader: FileReader = new FileReader() + fileReader.readAsDataURL(blob) + return await new Promise((resolve, reject) => { + fileReader.onload = () => { + const base64: string | undefined = fileReader.result?.toString() + if (base64 !== undefined) { + resolve(base64) + } else { + reject(new Error('Failed to read downloaded file.')) + } + } + fileReader.onerror = () => reject(fileReader.error) + }) +} + +export const AudioModal: React.FC = ({ + open, + onClose, + onPublish, + editVideoIdentifier +}) => { + const [file, setFile] = useState(null) + const [title, setTitle] = useState('') + const [description, setDescription] = useState('') + const [selectedOption, setSelectedOption] = useState( + null + ) + const [inputValue, setInputValue] = useState('') + const [chips, setChips] = useState([]) + + const [options, setOptions] = useState([]) + const [tags, setTags] = useState([]) + const { publishAudio } = usePublishAudio() + const { getRootProps, getInputProps } = useDropzone({ + accept: { + 'audio/*': [] + }, + maxFiles: 1, + onDrop: (acceptedFiles) => { + setFile(acceptedFiles[0]) + } + }) + + const handleTitleChange = (event: React.ChangeEvent) => { + setTitle(event.target.value) + } + + const handleDescriptionChange = ( + event: React.ChangeEvent + ) => { + setDescription(event.target.value) + } + + const handleOptionChange = (event: SelectChangeEvent) => { + const optionId = event.target.value + const selectedOption = options.find((option) => option.id === optionId) + setSelectedOption(selectedOption || null) + } + + const handleChipDelete = (index: number) => { + const newChips = [...chips] + newChips.splice(index, 1) + setChips(newChips) + } + + const handleSubmit = async () => { + const missingFields = [] + + if (!title) missingFields.push('title') + if (!file) missingFields.push('file') + if (missingFields.length > 0) { + const missingFieldsString = missingFields.join(', ') + const errMsg = `Missing: ${missingFieldsString}` + + return + } + if (!file) return + + const formattedTags: { [key: string]: string } = {} + chips.forEach((tag, i) => { + formattedTags[`tag${i + 1}`] = tag + }) + + try { + const base64 = await toBase64(file) + if (typeof base64 !== 'string') return + const base64String = base64.split(',')[1] + + const res = await publishAudio({ + editVideoIdentifier, + title, + description, + base64: base64String, + category: selectedOption?.id || '', + ...formattedTags + }) + onPublish(res) + setFile(null) + setTitle('') + setDescription('') + onClose() + } catch (error) {} + } + + const handleInputChange = (event: any) => { + setInputValue(event.target.value) + } + + const handleInputKeyDown = (event: any) => { + if (event.key === 'Enter' && inputValue !== '') { + if (chips.length < 5) { + setChips([...chips, inputValue]) + setInputValue('') + } else { + event.preventDefault() + } + } + } + + const addChip = () => { + if (chips.length < 5) { + setChips([...chips, inputValue]) + setInputValue('') + } + } + + const getListCategories = React.useCallback(async () => { + try { + const url = `/arbitrary/categories` + const response = await fetch(url, { + method: 'GET', + headers: { + 'Content-Type': 'application/json' + } + }) + const responseData = await response.json() + setOptions(responseData) + } catch (error) {} + }, []) + + React.useEffect(() => { + getListCategories() + }, [getListCategories]) + + return ( + + + {editVideoIdentifier && ( + + You are editing: {editVideoIdentifier} + + )} + + Upload Audio + + + + + {file + ? file.name + : 'Drag and drop an audio file here or click to select a file'} + + + + + {options.length > 0 && ( + + Select a Category + + + )} + + + + + + + + + + + {chips.map((chip, index) => ( + handleChipDelete(index)} + deleteIcon={} + /> + ))} + + + + + + ) +} 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..58c552d --- /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_q-blog` + 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_q-blog', + 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/Comments/Comment.tsx b/src/components/common/Comments/Comment.tsx new file mode 100644 index 0000000..fa2ffe5 --- /dev/null +++ b/src/components/common/Comments/Comment.tsx @@ -0,0 +1,336 @@ +import { + Avatar, + Box, + Button, + Dialog, + DialogActions, + DialogContent, + DialogTitle, + Typography, + useTheme +} from '@mui/material' +import React, { useCallback, useState } from 'react' +import { CommentEditor } from './CommentEditor' +import { CardContentContainerComment } from '../../../pages/BlogList/PostPreview-styles' +import { StyledCardHeaderComment } from '../../../pages/BlogList/PostPreview-styles' +import { StyledCardColComment } from '../../../pages/BlogList/PostPreview-styles' +import { AuthorTextComment } from '../../../pages/BlogList/PostPreview-styles' +import { StyledCardContentComment } from '../../../pages/BlogList/PostPreview-styles' +import { useSelector } from 'react-redux' +import { RootState } from '../../../state/store' +import Portal from '../Portal' +import { Tipping } from '../Tipping/Tipping' +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 ( + + {currentEdit && ( + + setCurrentEdit(null)} + aria-labelledby="alert-dialog-title" + aria-describedby="alert-dialog-description" + > + + + + handleSubmit(obj, true)} + postId={postId} + postName={postName} + isEdit + commentId={currentEdit?.identifier} + commentMessage={currentEdit?.message} + /> + + + + + + + + )} + + + + {comment?.created && ( + + {formatDate(+comment?.created)} + + )} + + + {user?.name === comment?.name && ( + + )} + {isReplying && ( + + )} + + + + {/* {comment?.message} */} + + + + {isReplying && ( + + )} + + + ) +} + +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 { + let url = await qortalRequest({ + action: 'GET_QDN_RESOURCE_URL', + name: author, + service: 'THUMBNAIL', + identifier: 'qortal_avatar' + }) + + setAvatarUrl(url) + } catch (error) {} + }, []) + + React.useEffect(() => { + getAvatar(name) + }, [name]) + return ( + + + + + + + + {name} + + + {name && ( + { + // setNameTip('') + }} + onClose={() => { + // setNameTip('') + }} + onlyIcon={true} + /> + )} + + + + {message} + + + + {replies?.map((reply: any) => { + return ( + + + + {reply?.created && ( + + {formatDate(+reply?.created)} + + )} + {user?.name === reply?.name ? ( + + ) : ( + + )} + + + {/* {reply?.message} */} + + ) + })} + + {children} + + ) +} diff --git a/src/components/common/Comments/CommentEditor.tsx b/src/components/common/Comments/CommentEditor.tsx new file mode 100644 index 0000000..b3602a2 --- /dev/null +++ b/src/components/common/Comments/CommentEditor.tsx @@ -0,0 +1,258 @@ +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' +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) + const notifications = useSelector( + (state: RootState) => state.global.notifications + ) + + 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 = 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 = `qcomment_v1_qblog_${postId.slice(-12)}_${id}` + let idForNotification = identifier + if (isReply && commentId) { + identifier = `qcomment_v1_qblog_${postId.slice( + -12 + )}_reply_${commentId.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) {} + } + + return ( + + setValue(e.target.value)} + /> + + + + ) +} diff --git a/src/components/common/Comments/CommentSection.tsx b/src/components/common/Comments/CommentSection.tsx new file mode 100644 index 0000000..96bb93b --- /dev/null +++ b/src/components/common/Comments/CommentSection.tsx @@ -0,0 +1,386 @@ +import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react' +import { CommentEditor, addItem, updateItemDate } from './CommentEditor' +import { Comment } from './Comment' +import { Box, Button, Drawer, Typography, useTheme } from '@mui/material' +import { styled } from '@mui/system' +import CloseIcon from '@mui/icons-material/Close' +import { useSelector } from 'react-redux' +import { RootState } from '../../../state/store' +import CommentIcon from '@mui/icons-material/Comment' +import { useNavigate, useLocation } from 'react-router-dom' + +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 notifications = useSelector( + (state: RootState) => state.global.notifications + ) + const notificationCreatorComment = useSelector( + (state: RootState) => state.global.notificationCreatorComment + ) + + const fullNotifications = useMemo(() => { + return [...notificationCreatorComment, ...notifications].sort( + (a, b) => b.created - a.created + ) + }, [notificationCreatorComment, notifications]) + const theme = useTheme() + 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 getComments = useCallback( + async (isNewMessages?: boolean, numberOfComments?: number) => { + let offset: number = 0 + if (isNewMessages && numberOfComments) { + offset = numberOfComments + } + const url = `/arbitrary/resources/search?mode=ALL&service=BLOG_COMMENT&query=qcomment_v1_qblog_${postId.slice( + -12 + )}&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 + }) + } + } + } + if (isNewMessages) { + setListComments((prev) => [...prev, ...comments]) + setNewMessages(0) + } else { + setListComments(comments) + } + + try { + } catch (error) {} + }, + [postId] + ) + + const checkAndUpdateNotification = async () => { + const filteredNotifications = fullNotifications.filter( + (notification) => + postId.includes(notification?.partialPostId) || + notification?.postId === postId + ) + filteredNotifications.forEach((notification) => { + if (postId) { + updateItemDate({ + id: notification?.identifier, + lastSeen: Date.now(), + postId + }) + } + }) + } + useEffect(() => { + if (fullNotifications && isOpen) { + checkAndUpdateNotification() + } + }, [fullNotifications, isOpen]) + + 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]) + + const interval = useRef(null) + + const checkNewComments = useCallback(async () => { + try { + const offset = listComments.length + const url = `/arbitrary/resources/search?mode=ALL&service=BLOG_COMMENT&query=qcomment_v1_qblog_${postId.slice( + -12 + )}&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() + setNewMessages(responseData.length) + } catch (error) {} + }, [listComments, postId]) + + const checkNewMessagesFunc = useCallback(() => { + let isCalling = false + interval.current = setInterval(async () => { + if (isCalling) return + isCalling = true + const res = await checkNewComments() + isCalling = false + }, 15000) + }, [checkNewComments]) + + useEffect(() => { + checkNewMessagesFunc() + + return () => { + if (interval?.current) { + clearInterval(interval.current) + } + } + }, [checkNewMessagesFunc]) + + return ( + <> + + setIsOpen((prev) => !prev)} + > + Comments + + {listComments?.length > 0 && ( + + {listComments.length < 10 ? listComments.length : '9+'} + + )} + + + {}} + ModalProps={{ + keepMounted: true // Better performance on mobile + }} + sx={{ + '& .MuiPaper-root': { + width: '400px' + } + }} + > + + + + {newMessages > 0 && ( + + )} + + setIsOpen(false)} + /> + + + + + {structuredCommentList.map((comment: any) => { + return ( + + ) + })} + + + + + + + + + ) +} diff --git a/src/components/common/ContextMenu/ContextMenuResource.tsx b/src/components/common/ContextMenu/ContextMenuResource.tsx new file mode 100644 index 0000000..af935f8 --- /dev/null +++ b/src/components/common/ContextMenu/ContextMenuResource.tsx @@ -0,0 +1,82 @@ +import * as React from 'react' +import Menu from '@mui/material/Menu' +import MenuItem from '@mui/material/MenuItem' +import Typography from '@mui/material/Typography' +import { CopyToClipboard } from 'react-copy-to-clipboard' +import { useDispatch } from 'react-redux' +import { setNotification } from '../../../state/features/notificationsSlice' +import { Box } from '@mui/material' + +export default function ContextMenuResource({ + children, + name, + service, + identifier, + link +}: any) { + const [contextMenu, setContextMenu] = React.useState<{ + mouseX: number + mouseY: number + } | null>(null) + const dispatch = useDispatch() + const handleContextMenu = (event: React.MouseEvent) => { + event.preventDefault() + setContextMenu( + contextMenu === null + ? { + mouseX: event.clientX + 2, + mouseY: event.clientY - 6 + } + : // repeated contextmenu when it is already open closes it with Chrome 84 on Ubuntu + // Other native context menus might behave different. + // With this behavior we prevent contextmenu from the backdrop to re-locale existing context menus. + null + ) + } + + const handleClose = () => { + setContextMenu(null) + } + + return ( +
+ {children} + + + { + handleClose() + dispatch( + setNotification({ + msg: 'Copied to clipboard!', + alertType: 'success' + }) + ) + }} + > + + Copy Link + + + + +
+ ) +} diff --git a/src/components/common/CustomIcon.tsx b/src/components/common/CustomIcon.tsx new file mode 100644 index 0000000..ae9ddd5 --- /dev/null +++ b/src/components/common/CustomIcon.tsx @@ -0,0 +1,16 @@ +import React from 'react' +import SvgIcon, { SvgIconProps } from '@mui/material/SvgIcon' +import { styled } from '@mui/system' + +const CustomSvgIcon: React.FC = styled(SvgIcon)(({ theme }) => ({ + cursor: 'pointer', + color: '#5f6368', + transition: 'all 0.2s', + '&:hover': { + transform: 'scale(1.1)' + } +})) as unknown as React.FC + +export const CustomIcon: React.FC = (props) => { + return +} diff --git a/src/components/common/DownloadTaskManager.tsx b/src/components/common/DownloadTaskManager.tsx new file mode 100644 index 0000000..afc00a8 --- /dev/null +++ b/src/components/common/DownloadTaskManager.tsx @@ -0,0 +1,289 @@ +import React, { useState, useEffect } from 'react' +import { + Accordion, + AccordionDetails, + AccordionSummary, + Box, + LinearProgress, + List, + ListItem, + ListItemIcon, + Typography, + useTheme +} from '@mui/material' +import { Movie, ArrowDropDown } from '@mui/icons-material' +import { SxProps } from '@mui/system' +import { Theme } from '@mui/material/styles' +import { useDispatch, useSelector } from 'react-redux' +import { RootState } from '../../state/store' +import ExpandMoreIcon from '@mui/icons-material/ExpandMore' +import { removePrefix } from '../../utils/blogIdformats' +import { useLocation, useNavigate } from 'react-router-dom' +import AudiotrackIcon from '@mui/icons-material/Audiotrack' +import { + setCurrAudio, + setShowingAudioPlayer +} from '../../state/features/globalSlice' +import { MAIL_ATTACHMENT_SERVICE_TYPE } from '../../constants/mail' + +type DownloadItem = { + id: string + name: string + progress: number +} + +export const DownloadTaskManager: React.FC = () => { + const { downloads } = useSelector((state: RootState) => state.global) + const dispatch = useDispatch() + const location = useLocation() + const isMailRoute = location.pathname === '/mail' + const theme = useTheme() + const [visible, setVisible] = useState(false) + const [hidden, setHidden] = useState(true) + const navigate = useNavigate() + const containerStyles: SxProps = { + position: 'fixed', + top: '50px', + right: 0, + zIndex: 1000, + maxHeight: '80%', + overflowY: 'auto', + backgroundColor: 'background.paper', + boxShadow: 2, + display: 'block' + } + + useEffect(() => { + // Simulate downloads for demo purposes + + if (visible) { + setTimeout(() => { + setHidden(true) + setVisible(false) + }, 3000) + } + }, [visible]) + + const toggleVisibility = () => { + setVisible(true) + setHidden(false) + } + + useEffect(() => { + if (Object.keys(downloads).length === 0) return + setVisible(true) + setHidden(false) + }, [downloads]) + + if (isMailRoute) return null + if ( + !downloads || + Object.keys(downloads).filter( + (item) => downloads[item].service !== MAIL_ATTACHMENT_SERVICE_TYPE + ).length === 0 + ) + return null + + return ( + + + } + aria-controls="panel1a-content" + id="panel1a-header" + sx={{ + minHeight: 'unset', + height: '36px', + backgroundColor: theme.palette.primary.light, + '&.MuiAccordionSummary-content': { + padding: 0, + margin: 0 + }, + '&.Mui-expanded': { + minHeight: 'unset', + height: '36px' + } + }} + > + + Downloads + + + + + {Object.keys(downloads) + .filter( + (item) => + downloads[item].service !== MAIL_ATTACHMENT_SERVICE_TYPE + ) + .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 ( + { + if (service === 'AUDIO' && downloadObj?.identifier) { + dispatch(setCurrAudio(downloadObj?.identifier)) + dispatch(setShowingAudioPlayer(true)) + return + } + + const str = downloadObj?.blogPost?.postId + if (!str) return + const arr = str.split('-post-') + const str1 = arr[0] + const str2 = arr[1] + const blogId = removePrefix(str1) + navigate( + `/${downloadObj?.blogPost.user}/${blogId}/${str2}` + ) + }} + > + + + {service === 'AUDIO' && ( + + )} + {service === 'VIDEO' && ( + + )} + + + + + + + {`${progress?.toFixed(0)}%`}{' '} + {status && status === 'REFETCHING' && '- refetching'} + {status && status === 'DOWNLOADED' && '- building'} + + + + {downloadObj?.identifier} + + + ) + })} + + + + + {/* {}} aria-label="toggle download manager"> + + */} + {/* + + {Object.keys(downloads).map((download: any) => { + const downloadObj = downloads[download] + const progress = downloads[download]?.status?.percentLoaded || 0 + return ( + + + + + + + + + + {`${progress}%`} + + + + + ) + })} + + */} + + ) +} diff --git a/src/components/common/DraggableResizableGrid.tsx b/src/components/common/DraggableResizableGrid.tsx new file mode 100644 index 0000000..871fec7 --- /dev/null +++ b/src/components/common/DraggableResizableGrid.tsx @@ -0,0 +1,55 @@ +// DraggableResizableGrid.tsx +import React from 'react' +import { DndProvider } from 'react-dnd' +import { HTML5Backend } from 'react-dnd-html5-backend' +import GridLayout, { Layout } from 'react-grid-layout' + +import './DraggableResizableGrid.css' // Add your custom CSS for the grid layout + +interface GridItem { + id: string + content: React.ReactNode +} + +interface DraggableResizableGridProps { + items: GridItem[] + cols?: number + rowHeight?: number + onLayoutChange?: (layout: Layout[]) => void +} + +const DraggableResizableGrid: React.FC = ({ + items, + cols = 12, + rowHeight = 30, + onLayoutChange +}) => { + const layout = items.map((item, index) => ({ + i: item.id, + x: index % cols, + y: Math.floor(index / cols), + w: 4, + h: 4 + })) + + return ( + + + {items.map((item) => ( +
+ {item.content} +
+ ))} +
+
+ ) +} + +export default DraggableResizableGrid diff --git a/src/components/common/ErrorBoundary.tsx b/src/components/common/ErrorBoundary.tsx new file mode 100644 index 0000000..58b3185 --- /dev/null +++ b/src/components/common/ErrorBoundary.tsx @@ -0,0 +1,36 @@ +import React, { ReactNode } from 'react' + +interface ErrorBoundaryProps { + children: ReactNode + fallback: ReactNode +} + +interface ErrorBoundaryState { + hasError: boolean +} + +class ErrorBoundary extends React.Component< + ErrorBoundaryProps, + ErrorBoundaryState +> { + state: ErrorBoundaryState = { + hasError: false + } + + static getDerivedStateFromError(_: Error): ErrorBoundaryState { + return { hasError: true } + } + + componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void { + // You can log the error and errorInfo here, for example, to an error reporting service. + console.error('Error caught in ErrorBoundary:', error, errorInfo) + } + + render(): React.ReactNode { + if (this.state.hasError) return this.props.fallback + + return this.props.children + } +} + +export default ErrorBoundary diff --git a/src/components/common/FilePanel.tsx b/src/components/common/FilePanel.tsx new file mode 100644 index 0000000..f08b313 --- /dev/null +++ b/src/components/common/FilePanel.tsx @@ -0,0 +1,257 @@ +import React, { useState, useEffect } from 'react' +import { styled, Box } from '@mui/system' +import { + Drawer, + List, + ListItem, + ListItemText, + Typography, + ButtonBase, + Button, + Tooltip +} from '@mui/material' +import VideoCallIcon from '@mui/icons-material/VideoCall' +import VideoModal from './VideoPublishModal' +import { useSelector } from 'react-redux' +import { RootState } from '../../state/store' +import AttachFileIcon from '@mui/icons-material/AttachFile' +import { AudioModal } from './AudioPublishModal' +import AudioFileIcon from '@mui/icons-material/AudioFile' +import { GenericModal } from './GenericPublishModal' +interface VideoPanelProps { + onSelect: (video: Video) => void + height?: string + width?: string +} + +interface VideoApiResponse { + videos: Video[] +} + +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; + } +` + +const PublishButton = styled(Button)` + /* position: absolute; + bottom: 20px; + left: 0; + right: 0; + margin: auto; */ + max-width: 80%; +` + +export const FilePanel: React.FC = ({ + onSelect, + height, + width +}) => { + const [isOpen, setIsOpen] = useState(false) + const [videos, setVideos] = useState([]) + const [isOpenVideoModal, setIsOpenVideoModal] = useState(false) + const { user } = useSelector((state: RootState) => state.auth) + const [editVideoIdentifier, setEditVideoIdentifier] = useState< + string | null | undefined + >() + const fetchVideos = React.useCallback(async (): Promise => { + if (!user?.name) return [] + + let res = [] + try { + // res = await qortalRequest({ + // action: 'LIST_QDN_RESOURCES', + // service: 'FILE', + // name: user.name, + // includeMetadata: true, + // limit: 100, + // offset: 0, + // reverse: true + // }) + + const res2 = await fetch( + `/arbitrary/resources?&service=FILE&name=${user.name}&includemetadata=true&limit=100&offset=0&reverse=true` + ) + const resData = await res2.json() + if (Array.isArray(resData)) { + res = resData + } + } catch (error) {} + + // Replace this URL with the actual API endpoint + + return res + }, [user]) + useEffect(() => { + fetchVideos().then((fetchedVideos) => setVideos(fetchedVideos)) + }, []) + + const handleToggle = () => { + setIsOpen(!isOpen) + } + + const handleClick = (video: Video) => { + onSelect(video) + } + + return ( + + + + + + + + + Select File + + + List of Files in QDN under your name (FILE service) + + + + + {videos.map((video) => ( + + handleClick(video)} + sx={{ width: '100%' }} + > + + + + + ))} + + + { + setEditVideoIdentifier(null) + setIsOpenVideoModal(true) + }} + > + Publish new file + + + + + { + setIsOpenVideoModal(false) + setEditVideoIdentifier(null) + }} + open={isOpenVideoModal} + onPublish={(value) => { + fetchVideos().then((fetchedVideos) => setVideos(fetchedVideos)) + setIsOpenVideoModal(false) + }} + editVideoIdentifier={editVideoIdentifier} + /> + + ) +} + +// Add this to your 'types.ts' file +export interface Video { + name: string + service: string + identifier: string + metadata: { + title: string + description: string + tags: string[] + category: string + categoryName: string + } + size: number + created: number + updated: number +} diff --git a/src/components/common/GenericPublishModal.tsx b/src/components/common/GenericPublishModal.tsx new file mode 100644 index 0000000..91df14e --- /dev/null +++ b/src/components/common/GenericPublishModal.tsx @@ -0,0 +1,317 @@ +import React, { useState } from 'react' +import { + Box, + Button, + Modal, + TextField, + Typography, + Select, + MenuItem, + FormControl, + InputLabel, + SelectChangeEvent, + OutlinedInput, + Chip, + IconButton +} from '@mui/material' +import { styled } from '@mui/system' +import { useDropzone } from 'react-dropzone' +import { toBase64 } from '../../utils/toBase64' +import AddIcon from '@mui/icons-material/Add' +import CloseIcon from '@mui/icons-material/Close' +import { usePublishGeneric } from './PublishGeneric' +import { useDispatch } from 'react-redux' +import { setNotification } from '../../state/features/notificationsSlice' + +const StyledModal = styled(Modal)(({ theme }) => ({ + display: 'flex', + alignItems: 'center', + justifyContent: 'center' +})) + +const ChipContainer = styled(Box)({ + display: 'flex', + flexWrap: 'wrap', + '& > *': { + margin: '4px' + } +}) + +const ModalContent = styled(Box)(({ theme }) => ({ + backgroundColor: theme.palette.background.paper, + padding: theme.spacing(4), + borderRadius: theme.spacing(1), + width: '40%', + '&:focus': { + outline: 'none' + } +})) + +interface GenericModalProps { + open: boolean + onClose: () => void + onPublish: (value: any) => void + acceptedFileType?: string + acceptedFileTypes?: string[] + service: string + identifierPrefix: string + editVideoIdentifier?: string | null | undefined +} + +interface SelectOption { + id: string + name: string +} +const maxSize = 500 * 1024 * 1024 + +export const GenericModal: React.FC = ({ + open, + onClose, + onPublish, + acceptedFileType, + acceptedFileTypes, + service, + identifierPrefix, + editVideoIdentifier +}) => { + const [file, setFile] = useState(null) + const [title, setTitle] = useState('') + const [description, setDescription] = useState('') + const [selectedOption, setSelectedOption] = useState( + null + ) + const [inputValue, setInputValue] = useState('') + const [chips, setChips] = useState([]) + + const [options, setOptions] = useState([]) + const [tags, setTags] = useState([]) + const { publishGeneric } = usePublishGeneric() + const dispatch = useDispatch() + + let acceptedFile = {} + if (acceptedFileType) { + acceptedFile = { + [acceptedFileType]: [] + } + } + const { getRootProps, getInputProps } = useDropzone({ + ...acceptedFile, + maxFiles: 1, + maxSize, + onDrop: (acceptedFiles) => { + setFile(acceptedFiles[0]) + }, + onDropRejected: (rejectedFiles) => { + dispatch( + setNotification({ + msg: 'Your file is over the 500mb limit.', + alertType: 'error' + }) + ) + } + }) + + const handleTitleChange = (event: React.ChangeEvent) => { + setTitle(event.target.value) + } + + const handleDescriptionChange = ( + event: React.ChangeEvent + ) => { + setDescription(event.target.value) + } + + const handleOptionChange = (event: SelectChangeEvent) => { + const optionId = event.target.value + const selectedOption = options.find((option) => option.id === optionId) + setSelectedOption(selectedOption || null) + } + + const handleChipDelete = (index: number) => { + const newChips = [...chips] + newChips.splice(index, 1) + setChips(newChips) + } + + const handleSubmit = async () => { + const missingFields = [] + + if (!title) missingFields.push('title') + if (!file) missingFields.push('file') + if (missingFields.length > 0) { + const missingFieldsString = missingFields.join(', ') + const errMsg = `Missing: ${missingFieldsString}` + + return + } + if (!file) return + + const formattedTags: { [key: string]: string } = {} + chips.forEach((tag, i) => { + formattedTags[`tag${i + 1}`] = tag + }) + + try { + const base64 = await toBase64(file) + if (typeof base64 !== 'string') return + const base64String = base64.split(',')[1] + const fileExtension = file?.name?.split('.')?.pop() + const fileTitle = title?.replace(/ /g, '_')?.slice(0, 20) + const filename = `${fileTitle}.${fileExtension}` + const res = await publishGeneric({ + editVideoIdentifier, + service, + identifierPrefix, + title, + description, + // base64: base64String, + file, + filename: filename, + category: selectedOption?.id || '', + ...formattedTags + }) + onPublish(res) + setFile(null) + setTitle('') + setDescription('') + onClose() + } catch (error) {} + } + + const handleInputChange = (event: any) => { + setInputValue(event.target.value) + } + + const handleInputKeyDown = (event: any) => { + if (event.key === 'Enter' && inputValue !== '') { + if (chips.length < 5) { + setChips([...chips, inputValue]) + setInputValue('') + } else { + event.preventDefault() + } + } + } + + const addChip = () => { + if (chips.length < 5) { + setChips([...chips, inputValue]) + setInputValue('') + } + } + + const getListCategories = React.useCallback(async () => { + try { + const url = `/arbitrary/categories` + const response = await fetch(url, { + method: 'GET', + headers: { + 'Content-Type': 'application/json' + } + }) + const responseData = await response.json() + setOptions(responseData) + } catch (error) {} + }, []) + + React.useEffect(() => { + getListCategories() + }, [getListCategories]) + + return ( + + + {editVideoIdentifier && ( + + You are editing: {editVideoIdentifier} + + )} + + Upload {service} + + + + + {file + ? file.name + : 'Drag and drop a file here or click to select a file'} + + + + + {options.length > 0 && ( + + Select a Category + + + )} + + + + + + + + + + + {chips.map((chip, index) => ( + handleChipDelete(index)} + deleteIcon={} + /> + ))} + + + + + + ) +} diff --git a/src/components/common/ImageUploader.tsx b/src/components/common/ImageUploader.tsx new file mode 100644 index 0000000..0cac393 --- /dev/null +++ b/src/components/common/ImageUploader.tsx @@ -0,0 +1,89 @@ +import React, { useCallback } from 'react' +import { Box, Button, TextField, Typography, Modal } from '@mui/material' +import { + useDropzone, + DropzoneRootProps, + DropzoneInputProps +} from 'react-dropzone' +import Compressor from 'compressorjs' + +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 +} + +const ImageUploader: React.FC = ({ children, onPick }) => { + const onDrop = useCallback( + async (acceptedFiles: File[]) => { + if (acceptedFiles.length > 1) { + return + } + let compressedFile: File | undefined + + try { + const image = acceptedFiles[0] + await 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' + }) + compressedFile = file + resolve() + }, + error(err) {} + }) + }) + if (!compressedFile) return + const base64Img = await toBase64(compressedFile) + + onPick(base64Img 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/LazyLoad.tsx b/src/components/common/LazyLoad.tsx new file mode 100644 index 0000000..6369d0d --- /dev/null +++ b/src/components/common/LazyLoad.tsx @@ -0,0 +1,47 @@ +import React, { useState, useEffect, useRef } from 'react' +import { useInView } from 'react-intersection-observer' +import CircularProgress from '@mui/material/CircularProgress' + +interface Props { + onLoadMore: () => Promise +} + +const LazyLoad: React.FC = ({ onLoadMore }) => { + 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/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/PostPublishModal.tsx b/src/components/common/PostPublishModal.tsx new file mode 100644 index 0000000..6f65741 --- /dev/null +++ b/src/components/common/PostPublishModal.tsx @@ -0,0 +1,281 @@ +import React, { useState } from 'react' +import { + Box, + Button, + Modal, + TextField, + Typography, + Select, + MenuItem, + FormControl, + InputLabel, + SelectChangeEvent, + OutlinedInput, + Chip, + IconButton +} from '@mui/material' +import { styled } from '@mui/system' +import { useDropzone } from 'react-dropzone' +import { usePublishVideo } from './PublishVideo' +import { toBase64 } from '../../utils/toBase64' +import AddIcon from '@mui/icons-material/Add' +import CloseIcon from '@mui/icons-material/Close' +const StyledModal = styled(Modal)(({ theme }) => ({ + display: 'flex', + alignItems: 'center', + justifyContent: 'center' +})) + +const ChipContainer = styled(Box)({ + display: 'flex', + flexWrap: 'wrap', + '& > *': { + margin: '4px' + } +}) + +const ModalContent = styled(Box)(({ theme }) => ({ + backgroundColor: theme.palette.background.paper, + padding: theme.spacing(4), + borderRadius: theme.spacing(1), + width: '40%', + '&:focus': { + outline: 'none' + } +})) + +interface PostModalProps { + open: boolean + onClose: () => void + onPublish: (value: any) => Promise + post: any + mode?: string + metadata?: any +} + +interface SelectOption { + id: string + name: string +} + +const PostPublishModal: React.FC = ({ + open, + onClose, + onPublish, + post, + mode, + metadata +}) => { + const [file, setFile] = useState(null) + const [title, setTitle] = useState('') + const [description, setDescription] = useState('') + const [selectedOption, setSelectedOption] = useState( + null + ) + const [inputValue, setInputValue] = useState('') + const [chips, setChips] = useState([]) + + const [options, setOptions] = useState([]) + const [tags, setTags] = useState([]) + const { publishVideo } = usePublishVideo() + const { getRootProps, getInputProps } = useDropzone({ + accept: { + 'video/*': [] + }, + maxFiles: 1, + onDrop: (acceptedFiles) => { + setFile(acceptedFiles[0]) + } + }) + + React.useEffect(() => { + if (post.title) { + setTitle(post.title) + } + // if (post.description) { + // setDescription(post.description) + // } + }, [post]) + + React.useEffect(() => { + if (mode === 'edit' && metadata) { + if (metadata.description) { + setDescription(metadata.description) + } + + const findCategory = options.find( + (option) => option.id === metadata?.category + ) + if (findCategory) { + setSelectedOption(findCategory) + } + + if (!metadata?.tags || !Array.isArray(metadata?.tags)) return + + setChips(metadata.tags.slice(0, -2)) + } + }, [mode, metadata, options]) + + const handleTitleChange = (event: React.ChangeEvent) => { + setTitle(event.target.value) + } + + const handleDescriptionChange = ( + event: React.ChangeEvent + ) => { + setDescription(event.target.value) + } + + const handleOptionChange = (event: SelectChangeEvent) => { + const optionId = event.target.value + const selectedOption = options.find((option) => option.id === optionId) + setSelectedOption(selectedOption || null) + } + + const handleChipDelete = (index: number) => { + const newChips = [...chips] + newChips.splice(index, 1) + setChips(newChips) + } + + const handleSubmit = async () => { + const formattedTags: { [key: string]: string } = {} + chips.forEach((tag, i) => { + formattedTags[`tag${i + 1}`] = tag + }) + + try { + await onPublish({ + title, + description, + tags: chips, + category: selectedOption?.id || '' + }) + setFile(null) + setTitle('') + setDescription('') + onClose() + } catch (error) {} + } + + const handleInputChange = (event: any) => { + setInputValue(event.target.value) + } + + + const handleInputKeyDown = (event: any) => { + if (event.key === 'Enter' && inputValue !== '') { + if (chips.length < 5) { + setChips([...chips, inputValue]) + setInputValue('') + } else { + event.preventDefault() + } + } + } + + const addChip = () => { + if (chips.length < 3) { + setChips([...chips, inputValue]) + setInputValue('') + } + } + + const getListCategories = React.useCallback(async () => { + try { + const url = `/arbitrary/categories` + const response = await fetch(url, { + method: 'GET', + headers: { + 'Content-Type': 'application/json' + } + }) + const responseData = await response.json() + setOptions(responseData) + } catch (error) {} + }, []) + + React.useEffect(() => { + getListCategories() + }, [getListCategories]) + + return ( + + + + Upload Blog Post + + + + + {options.length > 0 && ( + + Select a Category + + + )} + + + + + + + + + + + {chips.map((chip, index) => ( + handleChipDelete(index)} + deleteIcon={} + /> + ))} + + + + + + ) +} + +export default PostPublishModal diff --git a/src/components/common/PublishAudio.tsx b/src/components/common/PublishAudio.tsx new file mode 100644 index 0000000..d9e6952 --- /dev/null +++ b/src/components/common/PublishAudio.tsx @@ -0,0 +1,111 @@ +import React from 'react' +import { useDispatch, useSelector } from 'react-redux' +import { setNotification } from '../../state/features/notificationsSlice' +import { RootState } from '../../state/store' +import ShortUniqueId from 'short-unique-id' + +const uid = new ShortUniqueId() + +interface IPublishVideo { + title: string + description: string + base64: string + category: string + editVideoIdentifier?: string | null | undefined + +} + +export const usePublishAudio = () => { + const { user } = useSelector((state: RootState) => state.auth) + const dispatch = useDispatch() + const publishAudio = async ({ + editVideoIdentifier, + title, + description, + base64, + category, + ...rest + }: IPublishVideo) => { + let address + let name + let errorMsg = '' + + address = user?.address + name = user?.name || '' + + const missingFields = [] + if (!address) { + errorMsg = "Cannot post: your address isn't available" + } + if (!name) { + errorMsg = 'Cannot post without a name' + } + if (!title) missingFields.push('title') + if (missingFields.length > 0) { + const missingFieldsString = missingFields.join(', ') + const errMsg = `Missing: ${missingFieldsString}` + errorMsg = errMsg + } + + if (errorMsg) { + dispatch( + setNotification({ + msg: errorMsg, + alertType: 'error' + }) + ) + throw new Error(errorMsg) + } + + try { + const id = uid() + + let identifier = `qaudio_qblog_${id}` + if(editVideoIdentifier){ + identifier = editVideoIdentifier + } + const resourceResponse = await qortalRequest({ + action: 'PUBLISH_QDN_RESOURCE', + name: name, + service: 'AUDIO', + data64: base64, + title: title, + description: description, + category: category, + ...rest, + identifier: identifier + }) + dispatch( + setNotification({ + msg: 'Audio successfully published', + alertType: 'success' + }) + ) + return resourceResponse + } catch (error: any) { + let notificationObj = null + if (typeof error === 'string') { + notificationObj = { + msg: error || 'Failed to publish audio', + alertType: 'error' + } + } else if (typeof error?.error === 'string') { + notificationObj = { + msg: error?.error || 'Failed to publish audio', + alertType: 'error' + } + } else { + notificationObj = { + msg: error?.message || error?.message || 'Failed to publish audio', + alertType: 'error' + } + } + if (!notificationObj) return + dispatch(setNotification(notificationObj)) + + } + } + return { + publishAudio + } +} diff --git a/src/components/common/PublishGeneric.tsx b/src/components/common/PublishGeneric.tsx new file mode 100644 index 0000000..c744a8d --- /dev/null +++ b/src/components/common/PublishGeneric.tsx @@ -0,0 +1,120 @@ +import React from 'react' +import { useDispatch, useSelector } from 'react-redux' +import { setNotification } from '../../state/features/notificationsSlice' +import { RootState } from '../../state/store' +import ShortUniqueId from 'short-unique-id' + +const uid = new ShortUniqueId() + +interface IPublishGeneric { + title: string + description: string + base64?: string + file?: File + category: string + service: string + identifierPrefix: string + filename: string + editVideoIdentifier?: string | null | undefined +} + +export const usePublishGeneric = () => { + const { user } = useSelector((state: RootState) => state.auth) + const dispatch = useDispatch() + const publishGeneric = async ({ + editVideoIdentifier, + service, + identifierPrefix, + filename, + title, + description, + base64, + file, + category, + ...rest + }: IPublishGeneric) => { + let address + let name + let errorMsg = '' + + address = user?.address + name = user?.name || '' + + const missingFields = [] + if (!address) { + errorMsg = "Cannot post: your address isn't available" + } + if (!name) { + errorMsg = 'Cannot post without a name' + } + if (!title) missingFields.push('title') + if (missingFields.length > 0) { + const missingFieldsString = missingFields.join(', ') + const errMsg = `Missing: ${missingFieldsString}` + errorMsg = errMsg + } + + if (errorMsg) { + dispatch( + setNotification({ + msg: errorMsg, + alertType: 'error' + }) + ) + throw new Error(errorMsg) + } + + try { + const id = uid() + + let identifier = `${identifierPrefix}_${id}` + if (editVideoIdentifier) { + identifier = editVideoIdentifier + } + + const resourceResponse = await qortalRequest({ + action: 'PUBLISH_QDN_RESOURCE', + name: name, + service: service, + file, + title: title, + description: description, + category: category, + filename, + ...rest, + identifier: identifier + }) + dispatch( + setNotification({ + msg: `${service} successfully published`, + alertType: 'success' + }) + ) + return resourceResponse + } catch (error: any) { + let notificationObj = null + if (typeof error === 'string') { + notificationObj = { + msg: error || `Failed to publish ${service}`, + alertType: 'error' + } + } else if (typeof error?.error === 'string') { + notificationObj = { + msg: error?.error || `Failed to publish ${service}`, + alertType: 'error' + } + } else { + notificationObj = { + msg: + error?.message || error?.message || `Failed to publish ${service}`, + alertType: 'error' + } + } + if (!notificationObj) return + dispatch(setNotification(notificationObj)) + } + } + return { + publishGeneric + } +} diff --git a/src/components/common/PublishVideo.tsx b/src/components/common/PublishVideo.tsx new file mode 100644 index 0000000..4042994 --- /dev/null +++ b/src/components/common/PublishVideo.tsx @@ -0,0 +1,112 @@ +import React from 'react' +import { useDispatch, useSelector } from 'react-redux' +import { setNotification } from '../../state/features/notificationsSlice' +import { RootState } from '../../state/store' +import ShortUniqueId from 'short-unique-id' + +const uid = new ShortUniqueId() + +interface IPublishVideo { + title: string + description: string + base64?: string + category: string + editVideoIdentifier?: string | null | undefined + file?: File +} + +export const usePublishVideo = () => { + const { user } = useSelector((state: RootState) => state.auth) + const dispatch = useDispatch() + const publishVideo = async ({ + file, + editVideoIdentifier, + title, + description, + base64, + category, + ...rest + }: IPublishVideo) => { + let address + let name + let errorMsg = '' + + address = user?.address + name = user?.name || '' + + const missingFields = [] + if (!address) { + errorMsg = "Cannot post: your address isn't available" + } + if (!name) { + errorMsg = 'Cannot post without a name' + } + if (!title) missingFields.push('title') + if (missingFields.length > 0) { + const missingFieldsString = missingFields.join(', ') + const errMsg = `Missing: ${missingFieldsString}` + errorMsg = errMsg + } + + if (errorMsg) { + dispatch( + setNotification({ + msg: errorMsg, + alertType: 'error' + }) + ) + throw new Error(errorMsg) + } + + try { + const id = uid() + + let identifier = `qvideo_qblog_${id}` + if (editVideoIdentifier) { + identifier = editVideoIdentifier + } + const resourceResponse = await qortalRequest({ + action: 'PUBLISH_QDN_RESOURCE', + name: name, + service: 'VIDEO', + // data64: base64, + file: file, + title: title, + description: description, + category: category, + ...rest, + identifier: identifier + }) + dispatch( + setNotification({ + msg: 'Video successfully published', + alertType: 'success' + }) + ) + return resourceResponse + } catch (error: any) { + let notificationObj = null + if (typeof error === 'string') { + notificationObj = { + msg: error || 'Failed to publish video', + alertType: 'error' + } + } else if (typeof error?.error === 'string') { + notificationObj = { + msg: error?.error || 'Failed to publish video', + alertType: 'error' + } + } else { + notificationObj = { + msg: error?.message || 'Failed to publish video', + alertType: 'error' + } + } + if (!notificationObj) return + dispatch(setNotification(notificationObj)) + } + } + return { + publishVideo + } +} diff --git a/src/components/common/ResponsiveImage.tsx b/src/components/common/ResponsiveImage.tsx new file mode 100644 index 0000000..d903dce --- /dev/null +++ b/src/components/common/ResponsiveImage.tsx @@ -0,0 +1,124 @@ +import React, { useState, useEffect, CSSProperties } from 'react' +import Skeleton from '@mui/material/Skeleton' +import { Box } from '@mui/material' + +interface ResponsiveImageProps { + src: string + dimensions: string + alt?: string + className?: string + style?: CSSProperties +} + +const ResponsiveImage: React.FC = ({ + src, + dimensions, + alt, + className, + style +}) => { + const [loading, setLoading] = useState(true) + const matchResult = dimensions?.match(/v1\.(\d+(\.\d+)?)x(\d+)/) + + const width = matchResult ? parseFloat(matchResult[1]) : 1 // Default width value + const height = matchResult ? parseInt(matchResult[3], 10) : 1 // Default height value + + const aspectRatio = (height / width) * 100 + + useEffect(() => { + if (dimensions === 'v1.0x0') { + setLoading(false) + return + } + }, [dimensions]) + + if (dimensions === 'v1.0x0' || !dimensions) { + return null + } + + const imageStyle: CSSProperties = { + width: '100%', + height: '100%', + objectFit: 'cover' + } + + const wrapperStyle: CSSProperties = { + position: 'relative', + paddingBottom: `${aspectRatio}%`, + overflow: 'hidden', + ...style + } + + return ( + + {/* setLoading(false)} + src={src} + style={{ + width: '100%', + height: 'auto', + borderRadius: '8px' + }} + /> */} + {loading && ( + + )} + + setLoading(false)} + src={src} + style={{ + width: '100%', + height: 'auto', + borderRadius: '8px', + visibility: loading ? 'hidden' : 'visible', + position: loading ? 'absolute' : 'unset' + }} + /> + + ) + + return ( +
+ {loading ? ( + + ) : ( + {alt} + )} +
+ ) +} + +export default ResponsiveImage diff --git a/src/components/common/Tipping/Tipping.tsx b/src/components/common/Tipping/Tipping.tsx new file mode 100644 index 0000000..ca01dab --- /dev/null +++ b/src/components/common/Tipping/Tipping.tsx @@ -0,0 +1,289 @@ +import { + Avatar, + Box, + Button, + Dialog, + DialogActions, + DialogContent, + DialogTitle, + Input, + InputAdornment, + InputLabel, + Tooltip, + Typography, + useTheme +} from '@mui/material' +import React, { useCallback, useState } from 'react' +import { CardContentContainerComment } from '../../../pages/BlogList/PostPreview-styles' +import { StyledCardHeaderComment } from '../../../pages/BlogList/PostPreview-styles' +import { StyledCardColComment } from '../../../pages/BlogList/PostPreview-styles' +import { AuthorTextComment } from '../../../pages/BlogList/PostPreview-styles' +import { StyledCardContentComment } from '../../../pages/BlogList/PostPreview-styles' +import MenuItem from '@mui/material/MenuItem' +import Select, { SelectChangeEvent } from '@mui/material/Select' +import { useDispatch, useSelector } from 'react-redux' +import { RootState } from '../../../state/store' +import Portal from '../Portal' +import MonetizationOnIcon from '@mui/icons-material/MonetizationOn' +interface TippingProps { + name: string + onSubmit: () => void + onClose: () => void + onlyIcon?: boolean +} +import QORT from '../../../assets/img/qort.png' +import ARRR from '../../../assets/img/arrr.png' +import LTC from '../../../assets/img/ltc.png' +import BTC from '../../../assets/img/btc.png' +import DOGE from '../../../assets/img/doge.png' +import DGB from '../../../assets/img/dgb.png' +import RVN from '../../../assets/img/rvn.png' +import { setNotification } from '../../../state/features/notificationsSlice' +const coins = [ + { value: 'QORT', label: 'QORT' }, + { value: 'ARRR', label: 'ARRR' }, + { value: 'LTC', label: 'LTC' }, + { value: 'BTC', label: 'BTC' }, + { value: 'DOGE', label: 'DOGE' }, + { value: 'DGB', label: 'DGB' }, + { value: 'RVN', label: 'RVN' } +] +export const Tipping = ({ + onSubmit, + onClose, + name, + onlyIcon +}: TippingProps) => { + const { user } = useSelector((state: RootState) => state.auth) + const [isOpen, setIsOpen] = useState(false) + const [selectedCoin, setSelectedCoint] = useState(coins[0]) + const [amount, setAmount] = useState(0) + + const dispatch = useDispatch() + + const resetValues = () => { + setSelectedCoint(coins[0]) + setAmount(0) + setIsOpen(false) + } + + const sendCoin = async () => { + try { + if (!name) return + let res = await qortalRequest({ + action: 'GET_NAME_DATA', + name: name + }) + const address = res.owner + if (!address || !amount || !selectedCoin?.value) return + + if (isNaN(amount)) return + await qortalRequest({ + action: 'SEND_COIN', + coin: selectedCoin.value, + destinationAddress: address, + amount: amount + }) + dispatch( + setNotification({ + msg: 'Coin successfully sent', + alertType: 'success' + }) + ) + resetValues() + onSubmit() + } catch (error: any) { + let notificationObj = null + if (typeof error === 'string') { + notificationObj = { + msg: error || 'Failed to send coin', + alertType: 'error' + } + } else if (typeof error?.error === 'string') { + notificationObj = { + msg: error?.error || 'Failed to send coin', + alertType: 'error' + } + } else { + notificationObj = { + msg: error?.message || 'Failed to send coin', + alertType: 'error' + } + } + if (!notificationObj) return + dispatch(setNotification(notificationObj)) + } + } + + const handleOptionChange = (event: SelectChangeEvent) => { + const optionId = event.target.value + const selectedOption = coins.find( + (option: any) => option.value === optionId + ) + setSelectedCoint(selectedOption || null) + } + + const getLogo = (coin: string) => { + switch (coin) { + case 'QORT': + return QORT + case 'ARRR': + return ARRR + case 'LTC': + return LTC + case 'BTC': + return BTC + case 'DOGE': + return DOGE + case 'DGB': + return DGB + case 'RVN': + return RVN + default: + '' + // code block + } + } + + return ( + + + setIsOpen((prev) => !prev)} + > + + {!onlyIcon && ( + + Support + + )} + + + {isOpen && ( + + setIsOpen(false)} + aria-labelledby="alert-dialog-title" + aria-describedby="alert-dialog-description" + > + + + + + To + + + Coin + + + + Amount + + setAmount(+e.target.value)} + startAdornment={ + + + + } + /> + + + + + + + + + + )} + + ) +} diff --git a/src/components/common/UserNavbar/UserNavbar-styles.ts b/src/components/common/UserNavbar/UserNavbar-styles.ts new file mode 100644 index 0000000..a05b4c4 --- /dev/null +++ b/src/components/common/UserNavbar/UserNavbar-styles.ts @@ -0,0 +1,55 @@ +import { styled } from '@mui/system' +import { + AppBar, + Toolbar, + Typography, + Menu, + MenuItem +} from '@mui/material' + +export const CustomAppBar = styled(AppBar)(({ theme }) => ({ + backgroundColor: theme.palette.mode === "light" ? theme.palette.background.default : "#19191b", + color: theme.palette.text.primary +})) + +export const CustomToolbar = styled(Toolbar)({ + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center' +}) + +export const CustomTitle = styled(Typography)(({ theme }) => ({ + color: theme.palette.text.primary, + fontFamily: 'Raleway, Arial', + fontSize: '18px' +})) + +export const StyledAppBar = styled(AppBar)(({ theme }) => ({ + backgroundColor: theme.palette.primary.main +})) + +export const StyledToolbar = styled(Toolbar)(({ theme }) => ({ + justifyContent: 'space-between' +})) + +export const StyledMenu = styled(Menu)(({ theme }) => ({ + marginTop: theme.spacing(2), + overflow: 'hidden', + padding: 0, +})) + +export const StyledMenuItem = styled(MenuItem)(({ theme }) => ({ + width: '100%', + whiteSpace: 'nowrap', + maxWidth: '300px', + overflow: 'hidden', + textOverflow: 'ellipsis', + fontSize: "16px", + fontFamily: "Arial", + padding: "12px 10px", + transition: "all 0.3s ease-in-out", + "&:hover": { + cursor: "pointer", + filter: "brightness(1.1)" + } +})) \ No newline at end of file diff --git a/src/components/common/UserNavbar/UserNavbar.tsx b/src/components/common/UserNavbar/UserNavbar.tsx new file mode 100644 index 0000000..91b8022 --- /dev/null +++ b/src/components/common/UserNavbar/UserNavbar.tsx @@ -0,0 +1,135 @@ +import React from 'react' +import { styled } from '@mui/system' +import { + AppBar, + Toolbar, + Typography, + IconButton, + Menu, + MenuItem, + Box, + Button +} from '@mui/material' + +import { + CustomAppBar, + CustomToolbar, + CustomTitle, + StyledAppBar, + StyledToolbar, + StyledMenu, + StyledMenuItem +} from './UserNavbar-styles' + +import { useNavigate } from 'react-router-dom' +import { Menu as MenuIcon } from '@mui/icons-material' +import { removePrefix } from '../../../utils/blogIdformats' +import { QblogLogoContainer } from '../../layout/Navbar/Navbar-styles' +import QblogLogo from '../../../assets/img/qBlogLogo.png' + +interface Props { + title: string + menuItems: any[] + name: string + blogId: string +} + +export const UserNavbar: React.FC = ({ + title, + menuItems, + name, + blogId +}) => { + const navigate = useNavigate() + const [anchorEl, setAnchorEl] = React.useState(null) + + const handleClick = (event: React.MouseEvent) => { + setAnchorEl(event.currentTarget) + } + + const handleClose = () => { + setAnchorEl(null) + } + + const goToPost = (item: any) => { + if (!name) return + const { postId } = item + + const str = postId + const arr = str.split('-post-') + const str1 = arr[0] + const str2 = arr[1] + const blogId = removePrefix(str1) + navigate(`/${name}/${blogId}/${str2}`) + } + + const handleAction = (action: () => void) => { + handleClose() + setTimeout(() => { + action() + }, 100) + } + + return ( + + + + + + + { + navigate(`/${name}/${blogId}`) + }} + > + {title} + + + + {menuItems.map((item, index) => ( + handleAction(() => goToPost(item))} + > + {item.name} + + ))} + + + { + navigate(`/`) + }} + /> + + + + ) +} diff --git a/src/components/common/VideoContent.tsx b/src/components/common/VideoContent.tsx new file mode 100644 index 0000000..f8f2bc1 --- /dev/null +++ b/src/components/common/VideoContent.tsx @@ -0,0 +1,51 @@ +import React from 'react' +import { Box, Typography } from '@mui/material' +import { styled } from '@mui/system' +import { Description, Movie } from '@mui/icons-material' + +interface VideoProps { + title: string + description: string +} + +const StyledBox = styled(Box)` + margin: 20px 0px; + display: flex; + align-items: center; +` + +const Title = styled(Typography)`` + +const DescriptionIcon = styled(Description)` + color: #666; + margin-right: 0.5rem; +` + +const MovieIcon = styled(Movie)` + color: #666; + margin-right: 0.5rem; +` + +export const VideoContent: React.FC = ({ title, description }) => { + return ( + + + + + {title} + + + + + {description} + + + + ) +} diff --git a/src/components/common/VideoPanel.tsx b/src/components/common/VideoPanel.tsx new file mode 100644 index 0000000..3cfe65f --- /dev/null +++ b/src/components/common/VideoPanel.tsx @@ -0,0 +1,284 @@ +import React, { useState, useEffect } from 'react' +import { styled, Box } from '@mui/system' +import { + Drawer, + List, + ListItem, + ListItemText, + Typography, + ButtonBase, + Button, + Tooltip +} from '@mui/material' +import VideoCallIcon from '@mui/icons-material/VideoCall' +import VideoModal from './VideoPublishModal' +import { useDispatch, useSelector } from 'react-redux' +import { CopyToClipboard } from 'react-copy-to-clipboard' + +import { RootState } from '../../state/store' +import LinkIcon from '@mui/icons-material/Link' +import { setNotification } from '../../state/features/notificationsSlice' +interface VideoPanelProps { + onSelect: (video: Video) => void + height?: string + width?: string +} + +interface VideoApiResponse { + videos: Video[] +} + +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; + } +` + +const PublishButton = styled(Button)` + /* position: absolute; + bottom: 20px; + left: 0; + right: 0; + margin: auto; */ + max-width: 80%; +` + +export const VideoPanel: React.FC = ({ + onSelect, + height, + width +}) => { + const [isOpen, setIsOpen] = useState(false) + const [videos, setVideos] = useState([]) + const [isOpenVideoModal, setIsOpenVideoModal] = useState(false) + const { user } = useSelector((state: RootState) => state.auth) + const [editVideoIdentifier, setEditVideoIdentifier] = useState< + string | null | undefined + >() + const dispatch = useDispatch() + const fetchVideos = React.useCallback(async (): Promise => { + if (!user?.name) return [] + // Replace this URL with the actual API endpoint + let res = [] + try { + // res = await qortalRequest({ + // action: 'LIST_QDN_RESOURCES', + // service: 'VIDEO', + // name: user.name, + // includeMetadata: true, + // limit: 100, + // offset: 0, + // reverse: true + // }) + + const res2 = await fetch( + `/arbitrary/resources?&service=VIDEO&name=${user.name}&includemetadata=true&limit=100&offset=0&reverse=true` + ) + const resData = await res2.json() + if (Array.isArray(resData)) { + res = resData + } + } catch (error) { + // const res2 = await fetch( + // '/arbitrary/resources?&service=VIDEO&name=Phil&includemetadata=true&limit=100&offset=0&reverse=true' + // ) + // res = await res2.json() + } + + return res + }, [user]) + useEffect(() => { + fetchVideos().then((fetchedVideos) => setVideos(fetchedVideos)) + }, []) + + const handleToggle = () => { + setIsOpen(!isOpen) + } + + const handleClick = (video: Video) => { + onSelect(video) + } + + return ( + + + + + + + + + Select Video + + + List of videos in QDN under your name + + + + + {videos.map((video) => ( + + handleClick(video)} + sx={{ width: '100%' }} + > + + + + + { + dispatch( + setNotification({ + msg: 'Copied to clipboard!', + alertType: 'success' + }) + ) + }} + > + + + + + ))} + + + { + setEditVideoIdentifier(null) + setIsOpenVideoModal(true) + }} + > + Publish new video + + + + + { + setIsOpenVideoModal(false) + setEditVideoIdentifier(null) + }} + open={isOpenVideoModal} + onPublish={(value) => { + fetchVideos().then((fetchedVideos) => setVideos(fetchedVideos)) + setIsOpenVideoModal(false) + }} + editVideoIdentifier={editVideoIdentifier} + /> + + ) +} + +// Add this to your 'types.ts' file +export interface Video { + name: string + service: string + identifier: string + metadata: { + title: string + description: string + tags: string[] + category: string + categoryName: string + } + size: number + created: number + updated: number +} diff --git a/src/components/common/VideoPlayer.tsx b/src/components/common/VideoPlayer.tsx new file mode 100644 index 0000000..64bf633 --- /dev/null +++ b/src/components/common/VideoPlayer.tsx @@ -0,0 +1,832 @@ +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' +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; + 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 + setCount?: () => void + customStyle?: any + user?: string + postId?: string +} + +export const VideoPlayer: React.FC = ({ + poster, + name, + identifier, + service, + autoplay = true, + from = null, + setCount, + customStyle = {}, + user = '', + postId = '' + }) => { + 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 [consoleLog, setConsoleLog] = useState('Console Log Here') + const [debug, setDebug] = useState(false) + + 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 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 toggleRef = useRef(null) + const { downloadVideo } = useContext(MyContext) + const togglePlay = async () => { + if (!videoRef.current) return + setStartPlay(true) + if (!src) { + 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) + } + }, []) + + const handleLoadedMetadata = () => { + setIsLoading(false) + } + + const handleCanPlay = () => { + if (setCount) { + setCount() + } + setIsLoading(false) + setCanPlay(true) + } + + const getSrc = React.useCallback(async () => { + if (!name || !identifier || !service || !postId || !user) return + try { + downloadVideo({ + name, + service, + identifier, + blogPost: { + postId, + user + } + }) + } catch (error) {} + }, [identifier, name, service]) + + 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 + 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() + } + } + + useEffect(() => { + if ( + resourceStatus?.status === 'DOWNLOADED' && + reDownload?.current === false + ) { + getSrc() + 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() + //setConsoleLog(`Alt: ${e.altKey} Shift: ${e.shiftKey} Control: ${e.ctrlKey} Key: ${e.key}`) + + 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() + //setConsoleLog(`Alt: ${e.altKey} Shift: ${e.shiftKey} Control: ${e.ctrlKey} Key: ${e.key}`) + + 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 ( + + {/* + { + dispatch( + setNotification({ + msg: 'Copied to clipboard!', + alertType: 'success' + }) + ) + }} + > + + + */} + {isLoading && ( + + + {resourceStatus && ( + + {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)} + + + ) : ( + <>Download Completed: fetching video... + )} + + )} + + )} + {((!src && !isLoading) || !startPlay) && ( + { + if (from === 'create') return + + togglePlay() + }} + sx={{ + cursor: 'pointer' + }} + > + + + )} + + + + + {isMobileView && canPlay ? ( + <> + + {playing ? : } + + + + + + + + + + + + + + increaseSpeed()}> + + Speed: {playbackRate}x + + + + + + + + + + + ) : canPlay ? ( + <> + + {playing ? : } + + + + + + + {progress && videoRef.current?.duration && formatTime(progress)}/ + {progress && + videoRef.current?.duration && + formatTime(videoRef.current?.duration)} + + + {isMuted ? :} + + + increaseSpeed()} + > + Speed: {playbackRate}x + + + + + + + + + + ) : null} + + {debug ? {consoleLog}: <>} + + ) +} diff --git a/src/components/common/VideoPublishModal.tsx b/src/components/common/VideoPublishModal.tsx new file mode 100644 index 0000000..b7b10f6 --- /dev/null +++ b/src/components/common/VideoPublishModal.tsx @@ -0,0 +1,287 @@ +import React, { useState } from 'react' +import { + Box, + Button, + Modal, + TextField, + Typography, + Select, + MenuItem, + FormControl, + InputLabel, + SelectChangeEvent, + OutlinedInput, + Chip, + IconButton +} from '@mui/material' +import { styled } from '@mui/system' +import { useDropzone } from 'react-dropzone' +import { usePublishVideo } from './PublishVideo' +import { toBase64 } from '../../utils/toBase64' +import AddIcon from '@mui/icons-material/Add' +import CloseIcon from '@mui/icons-material/Close' +const StyledModal = styled(Modal)(({ theme }) => ({ + display: 'flex', + alignItems: 'center', + justifyContent: 'center' +})) + +const ChipContainer = styled(Box)({ + display: 'flex', + flexWrap: 'wrap', + '& > *': { + margin: '4px' + } +}) + +const ModalContent = styled(Box)(({ theme }) => ({ + backgroundColor: theme.palette.background.paper, + padding: theme.spacing(4), + borderRadius: theme.spacing(1), + width: '40%', + '&:focus': { + outline: 'none' + } +})) + +interface VideoModalProps { + open: boolean + onClose: () => void + onPublish: (value: any) => void + editVideoIdentifier?: string | null | undefined +} + +interface SelectOption { + id: string + name: string +} + +const VideoModal: React.FC = ({ + open, + onClose, + onPublish, + editVideoIdentifier +}) => { + const [file, setFile] = useState(null) + const [title, setTitle] = useState('') + const [description, setDescription] = useState('') + const [selectedOption, setSelectedOption] = useState( + null + ) + const [inputValue, setInputValue] = useState('') + const [chips, setChips] = useState([]) + + const [options, setOptions] = useState([]) + const [tags, setTags] = useState([]) + const { publishVideo } = usePublishVideo() + const { getRootProps, getInputProps } = useDropzone({ + accept: { + 'video/*': [] + }, + maxFiles: 1, + onDrop: (acceptedFiles) => { + setFile(acceptedFiles[0]) + } + }) + + const handleTitleChange = (event: React.ChangeEvent) => { + setTitle(event.target.value) + } + + const handleDescriptionChange = ( + event: React.ChangeEvent + ) => { + setDescription(event.target.value) + } + + const handleOptionChange = (event: SelectChangeEvent) => { + const optionId = event.target.value + const selectedOption = options.find((option) => option.id === optionId) + setSelectedOption(selectedOption || null) + } + + const handleChipDelete = (index: number) => { + const newChips = [...chips] + newChips.splice(index, 1) + setChips(newChips) + } + + const handleSubmit = async () => { + const missingFields = [] + + if (!title) missingFields.push('title') + if (!file) missingFields.push('file') + if (missingFields.length > 0) { + const missingFieldsString = missingFields.join(', ') + const errMsg = `Missing: ${missingFieldsString}` + + return + } + if (!file) return + + const formattedTags: { [key: string]: string } = {} + chips.forEach((tag, i) => { + formattedTags[`tag${i + 1}`] = tag + }) + + try { + // const base64 = await toBase64(file) + // if (typeof base64 !== 'string') return + // const base64String = base64.split(',')[1] + // if (!file) return + + const res = await publishVideo({ + file: file, + editVideoIdentifier, + title, + description, + category: selectedOption?.id || '', + ...formattedTags + }) + onPublish(res) + setFile(null) + setTitle('') + setDescription('') + onClose() + } catch (error) {} + } + + const handleInputChange = (event: any) => { + setInputValue(event.target.value) + } + + const handleInputKeyDown = (event: any) => { + if (event.key === 'Enter' && inputValue !== '') { + if (chips.length < 5) { + setChips([...chips, inputValue]) + setInputValue('') + } else { + event.preventDefault() + } + } + } + + const addChip = () => { + if (chips.length < 5) { + setChips([...chips, inputValue]) + setInputValue('') + } + } + + const getListCategories = React.useCallback(async () => { + try { + const url = `/arbitrary/categories` + const response = await fetch(url, { + method: 'GET', + headers: { + 'Content-Type': 'application/json' + } + }) + const responseData = await response.json() + setOptions(responseData) + } catch (error) {} + }, []) + + React.useEffect(() => { + getListCategories() + }, [getListCategories]) + + return ( + + + {editVideoIdentifier && ( + + You are editing: {editVideoIdentifier} + + )} + + Upload Video + + + + + {file + ? file.name + : 'Drag and drop a video file here or click to select a file'} + + + + + {options.length > 0 && ( + + Select a Category + + + )} + + + + + + + + + + + {chips.map((chip, index) => ( + handleChipDelete(index)} + deleteIcon={} + /> + ))} + + + + + + ) +} + +export default VideoModal diff --git a/src/components/editor/BlogEditor.css b/src/components/editor/BlogEditor.css new file mode 100644 index 0000000..0a3e0e8 --- /dev/null +++ b/src/components/editor/BlogEditor.css @@ -0,0 +1,78 @@ +/* src/components/BlogEditor.css */ +.blog-editor { + max-width: 800px; + margin: 0 auto; + padding: 1rem; + line-height: 1.5; + font-size: 18px; + max-height: 50vh; + overflow-y: auto; + min-height: 200px; + z-index: 500; + } + + .toolbar { + display: flex; + justify-content: center; + margin-bottom: 1rem; + } + + + + .toolbar-button:focus { + outline: none; + } + + .code-block { + background-color: #2c2b31; + color: rgb(238, 234, 234); + border-radius: 3px; + padding: 10px; + margin: 10px 0; + font-family: 'Courier New', Courier, monospace; + white-space: pre-wrap; + overflow-x: auto; + max-width: 100%; + font-size: 14px; + } + + .paragraph { + font-size: 20px; + margin: 0px; + } + + .paragraph-mail { + font-size: 16px; + margin: 0px; + } + + .toolbar-button { + background-color: white; + border: 1px solid gray; + border-radius: 5px; + margin-right: 5px; + cursor: pointer; + outline: none; + height: 32px; + width: 32px; + display: flex; + align-items: center; + justify-content: center; + } + + .toolbar-button.active { + background-color: lightgray; + } + + .h2 { + font-size: 25px + } + + .h2 { + font-size: 22px + } + + .align-center { + text-align: center; + } + diff --git a/src/components/editor/BlogEditor.tsx b/src/components/editor/BlogEditor.tsx new file mode 100644 index 0000000..0da146c --- /dev/null +++ b/src/components/editor/BlogEditor.tsx @@ -0,0 +1,574 @@ +// src/components/BlogEditor.tsx +// @ts-nocheck + +import React, { useMemo, useState, useCallback } from 'react'; +import { createEditor, Descendant, Editor, Transforms, Range } from 'slate' +import SvgIcon from '@material-ui/core/SvgIcon' +import { + Slate, + Editable, + withReact, + RenderElementProps, + RenderLeafProps, + useSlate +} from 'slate-react' +import { styled } from '@mui/system' +import { CustomElement, CustomText, FormatMark } from './customTypes' +import './BlogEditor.css' +import { Modal, Box, TextField, Button } from '@mui/material' + +import { AlignCenterSVG } from '../../assets/svgs/AlignCenterSVG' +import { BoldSVG } from '../../assets/svgs/BoldSVG' +import { ItalicSVG } from '../../assets/svgs/ItalicSVG' +import { UnderlineSVG } from '../../assets/svgs/UnderlineSVG' +import { H2SVG } from '../../assets/svgs/H2SVG' +import { H3SVG } from '../../assets/svgs/H3SVG' +import { AlignLeftSVG } from '../../assets/svgs/AlignLeftSVG' +import { AlignRightSVG } from '../../assets/svgs/AlignRightSVG' +import { CodeBlockSVG } from '../../assets/svgs/CodeBlockSVG' +import { LinkSVG } from '../../assets/svgs/LinkSVG' + +const initialValue: Descendant[] = [ + { + type: 'paragraph', + children: [{ text: 'Start writing your blog post...' }] + } +] + +interface MyComponentProps { + addPostSection?: (value: any) => void + editPostSection?: (value: any, section: any) => void + defaultValue?: any + section?: any + value: any + setValue: (value: any) => void + editorKey?: number + mode?: string +} + +const ModalBox = styled(Box)(({ theme }) => ({ + position: 'absolute', + top: '50%', + left: '50%', + transform: 'translate(-50%, -50%)', + backgroundColor: theme.palette.background.paper, + boxShadow: theme.shadows[5], + padding: theme.spacing(2, 4, 3), + gap: '15px', + borderRadius: '5px', + alignItems: 'center', + display: 'flex', + flex: 0 +})) + +const BlogEditor: React.FC = ({ + addPostSection, + editPostSection, + defaultValue, + section, + value, + setValue, + editorKey, + mode +}) => { + const editor = useMemo(() => withReact(createEditor()), []) + + // const [value, setValue] = useState(defaultValue || initialValue); + const isTextAlignmentActive = (editor: Editor, alignment: string) => { + const [match] = Editor.nodes(editor, { + match: (n) => { + return n?.textAlign === alignment?.replace(/^align-/, '') + } + }) + return !!match + } + + const toggleTextAlignment = (editor: Editor, alignment: string) => { + const isActive = isTextAlignmentActive(editor, alignment) + Transforms.setNodes( + editor, + { style: { textAlign: isActive ? 'inherit' : alignment } }, + { match: (n) => Editor.isBlock(editor, n) } + ) + } + + const toggleMark = (editor: Editor, format: FormatMark) => { + if ( + format === 'align-left' || + format === 'align-center' || + format === 'align-right' + ) { + toggleTextAlignment(editor, format) + } else { + const isActive = Editor?.marks(editor)?.[format] === true + if (isActive) { + Editor?.removeMark(editor, format) + } else { + Editor?.addMark(editor, format, true) + } + } + } + + const newValue = useMemo(() => [...(value || initialValue)], [value]) + + const types = ['paragraph', 'heading-2', 'heading-3'] + + const setTextAlignment = (editor, alignment) => { + const isActive = isTextAlignmentActive(editor, alignment) + const alignmentType = '' + Transforms?.setNodes( + editor, + { + textAlign: isActive ? null : alignment + }, + { + match: (n) => + n.type === 'heading-2' || + n.type === 'heading-3' || + n.type === 'paragraph' + } + ) + } + + const ToolbarButton: React.FC<{ + format: FormatMark | string + label: string + editor: Editor + children: React.ReactNode + }> = ({ format, label, editor, children }) => { + useSlate() + + let onClick = () => { + if (format === 'heading-2' || format === 'heading-3') { + toggleBlock(editor, format) + } else if ( + format === 'bold' || + format === 'italic' || + format === 'underline' || + format === '' + ) { + toggleMark(editor, format) + } else if ( + format === 'align-left' || + format === 'align-center' || + format === 'align-right' + ) { + setTextAlignment(editor, format?.replace(/^align-/, '')) + } + } + + let isActive = false + + try { + if ( + format === 'align-left' || + format === 'align-center' || + format === 'align-right' + ) { + isActive = isTextAlignmentActive(editor, format) + } else if (format === 'heading-2' || format === 'heading-3') { + isActive = isBlockActive(editor, format) + } else if ( + format === 'bold' || + format === 'italic' || + format === 'underline' || + format === '' + ) { + isActive = Editor?.marks(editor)?.[format] === true + } + } catch (error) {} + + return ( + + ) + } + + const ToolbarButtonCodeBlock: React.FC<{ + format: FormatMark | string + label: string + editor: Editor + children: React.ReactNode + }> = ({ format, label, editor, children }) => { + const editor2 = useSlate() + + let onClick = () => { + if (format === 'code-block') { + toggleBlock(editor, 'code-block') + } + } + let isActive = false + try { + if (format === 'code-block') { + isActive = isBlockActive(editor, format) + } + } catch (error) {} + + return ( + + ) + } + + const ToolbarButtonAlign: React.FC<{ + format: string + label: string + editor: Editor + }> = ({ format, label, editor }) => { + const isActive = + Editor?.nodes(editor, { + match: (n) => n?.align === format + })?.length > 0 + + return ( + + ) + } + + const ToolbarButtonCodeLink: React.FC<{ + format: FormatMark | string + label: string + editor: Editor + children: React.ReactNode + }> = ({ format, label, editor, children }) => { + useSlate() + + let isActive = false + try { + if (format === 'link') { + isActive = !!Editor?.marks(editor)?.link + } + } catch (error) {} + + return ( + + ) + } + + // Create a toggleBlock function and an isBlockActive function to handle block elements + const toggleBlock = (editor: Editor, format: string) => { + const isActive = isBlockActive(editor, format) + Transforms?.unwrapNodes(editor, { + match: (n) => Editor?.isBlock(editor, n), + split: true + }) + + if (isActive) { + Transforms?.setNodes(editor, { type: 'paragraph' }) + } else { + Transforms?.setNodes(editor, { type: format }) + } + } + + const isBlockActive = (editor: Editor, format: string) => { + const [match] = Editor?.nodes(editor, { + match: (n) => n?.type === format + }) + return !!match + } + + const handleKeyDown = (event: React.KeyboardEvent) => { + if (event.key === 'Enter' && isBlockActive(editor, 'code-block')) { + event.preventDefault() + editor?.insertText('\n') + } + + if (event.key === 'ArrowDown' && isBlockActive(editor, 'code-block')) { + event.preventDefault() + Transforms?.insertNodes(editor, { + type: 'paragraph', + children: [{ text: '' }] + }) + } + } + + const handleChange = (newValue: Descendant[]) => { + setValue(newValue) + } + + const toggleLink = (editor: Editor, url: string) => { + const { selection } = editor + + if (selection && !Range.isCollapsed(selection)) { + const isLink = Editor?.marks(editor)?.link === true + const isInsideLink = isLinkActive(editor) + + if (isLink) { + Editor?.removeMark(editor, 'link') + } else if (url) { + Editor?.addMark(editor, 'link', url) + } + } + } + + const [open, setOpen] = useState(false) + + const initialValue = 'qortal://' + const [inputValue, setInputValue] = useState(initialValue) + + const handleChangeLink = (event) => { + const newValue = event?.target?.value + if (newValue?.startsWith(initialValue)) { + setInputValue(newValue) + } + } + const isLinkActive = (editor: Editor) => { + const [link] = Editor?.nodes(editor, { + match: (n) => n?.type === 'link' + }) + return !!link + } + const handleSaveClick = () => { + const marks = Editor?.marks(editor) + const isLink = marks?.link === true + + if (isLink) { + Editor?.removeMark(editor, 'link') + return // Return early to skip the rest of the function + } + toggleLink(editor, inputValue) + setOpen(false) + } + + const onClose = () => { + setOpen(false) + } + + const handlePaste = (event: React.ClipboardEvent) => { + event.preventDefault() + const text = event?.clipboardData?.getData('text/plain') + const isCodeBlock = isBlockActive(editor, 'code-block') + + if (isCodeBlock) { + const lines = text?.split('\n') + const fragment: Descendant[] = [ + { + type: 'code-block', + children: lines?.map((line) => ({ + type: 'code-line', + children: [{ text: line }] + })) + } + ] + + Transforms?.insertFragment(editor, fragment) + } else if (text) { + const fragment = text?.split('\n').map((line) => ({ + type: 'paragraph', + children: [{ text: line }] + })) + + Transforms?.insertFragment(editor, fragment) + } + } + + return ( + + handleChange(newValue)} + key={editorKey || 1} + > +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ renderElement({ ...props, mode })} + renderLeaf={renderLeaf} + onKeyDown={handleKeyDown} + onPaste={handlePaste} + mode={mode} + /> +
+ + + + + + + {editPostSection && ( + + )} +
+ ) +} + +export default BlogEditor + +type ExtendedRenderElementProps = RenderElementProps & { mode?: string } + +export const renderElement = ({ + attributes, + children, + element, + mode +}: ExtendedRenderElementProps) => { + switch (element.type) { + case 'block-quote': + return
{children}
+ case 'heading-2': + return ( +

+ {children} +

+ ) + case 'heading-3': + return ( +

+ {children} +

+ ) + case 'code-block': + return ( +
+          {children}
+        
+ ) + case 'code-line': + return
{children}
+ case 'link': + return ( + + {children} + + ) + default: + return ( +

+ {children} +

+ ) + } +} + + +export const renderLeaf = ({ attributes, children, leaf }: RenderLeafProps) => { + let el = children + + if (leaf.bold) { + el = {el} + } + + if (leaf.italic) { + el = {el} + } + + if (leaf.underline) { + el = {el} + } + + if (leaf.link) { + el = ( + + {el} + + ) + } + + return {el} +} \ No newline at end of file diff --git a/src/components/editor/ReadOnlySlate.tsx b/src/components/editor/ReadOnlySlate.tsx new file mode 100644 index 0000000..cd2616c --- /dev/null +++ b/src/components/editor/ReadOnlySlate.tsx @@ -0,0 +1,25 @@ +import React, { useMemo } from 'react'; +import { createEditor, Descendant, Editor } from 'slate'; +import { withReact, Slate, Editable, RenderElementProps, RenderLeafProps } from 'slate-react'; +import { renderElement, renderLeaf } from './BlogEditor'; + +interface ReadOnlySlateProps { + content: any + mode?: string +} +const ReadOnlySlate: React.FC = ({ content, mode }) => { + const editor = useMemo(() => withReact(createEditor()), []) + const value = useMemo(() => content, [content]) + + return ( + {}}> + renderElement({ ...props, mode })} + renderLeaf={renderLeaf} + /> + + ) +} + +export default ReadOnlySlate; \ No newline at end of file diff --git a/src/components/editor/customTypes.ts b/src/components/editor/customTypes.ts new file mode 100644 index 0000000..46142fb --- /dev/null +++ b/src/components/editor/customTypes.ts @@ -0,0 +1,47 @@ +// src/customTypes.ts +import { BaseEditor } from 'slate'; +import { ReactEditor } from 'slate-react'; + +export type CustomText = { + text: string + bold?: boolean + italic?: boolean + underline?: boolean + code?: boolean +} + +export type HeadingElement = { + type: 'heading' + children: CustomText[] +} + +export type BlockQuoteElement = { + type: 'block-quote' + children: CustomText[] +} + +export type ParagraphElement = { + type: 'paragraph' + children: CustomText[] +} + +export type CodeBlockElement = { + type: 'code-block' + children: CustomText[] +} + +export type CustomElement = + | HeadingElement + | BlockQuoteElement + | ParagraphElement + | CodeBlockElement + +export type FormatMark = 'bold' | 'italic' | 'underline' | 'code' + +declare module 'slate' { + interface CustomTypes { + Editor: BaseEditor & ReactEditor; + Element: CustomElement; + Text: CustomText; + } +} diff --git a/src/components/layout/Navbar/Navbar-styles.ts b/src/components/layout/Navbar/Navbar-styles.ts new file mode 100644 index 0000000..7bff108 --- /dev/null +++ b/src/components/layout/Navbar/Navbar-styles.ts @@ -0,0 +1,112 @@ +import { AppBar, Button, Toolbar, Typography, Box } from '@mui/material' +import { styled } from '@mui/system' + +export const QblogLogoContainer = styled('img')({ + width: 'auto', + height: 'auto', + userSelect: 'none', + objectFit: 'contain', + cursor: 'pointer' +}) + +export const CustomAppBar = styled(AppBar)(({ theme }) => ({ + backgroundColor: theme.palette.mode === "light" ? theme.palette.background.default : "#19191b", + [theme.breakpoints.only('xs')]: { + gap: '15px', + }, +})) + +export const CustomToolbar = styled(Toolbar)({ + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center' +}) + +export const CustomTitle = styled(Typography)({ + fontWeight: 600, + color: '#000000' +}) + +export const StyledButton = styled(Button)(({ theme }) => ({ + fontWeight: 600, + color: theme.palette.text.primary +})) + +export const CreateBlogButton = styled(Button)(({ theme }) => ({ + display: 'flex', + flexDirection: 'row', + alignItems: 'center', + padding: '8px 15px', + borderRadius: "40px", + gap: '4px', + backgroundColor: theme.palette.secondary.main, + color: '#fff', + fontFamily: "Arial", + 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.main, + filter: "brightness(1.1)", + } +})) + +export const AuthenticateButton = styled(Button)({ + display: 'flex', + flexDirection: 'row', + alignItems: 'center', + padding: '8px 15px', + borderRadius: "40px", + gap: '4px', + backgroundColor: "#4ACE91", + color: '#fff', + fontFamily: "Arial", + 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: "#4ACE91", + 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.primary.main, + padding: "10px 15px", + transition: "all 0.4s ease-in-out", + "&:hover": { + cursor: "pointer", + filter: "brightness(0.95)" + } +})); + +export const DropdownText = styled(Typography)(({ theme }) => ({ + fontFamily: "Arial", + fontSize: "16px", + color: theme.palette.text.primary, + userSelect: "none" +})); + +export const NavbarName = styled(Typography)(({ theme }) => ({ + fontFamily: "Arial", + fontSize: "18px", + color: theme.palette.text.primary, + margin: "0 10px", +})); \ No newline at end of file diff --git a/src/components/layout/Navbar/Navbar.tsx b/src/components/layout/Navbar/Navbar.tsx new file mode 100644 index 0000000..e595aa8 --- /dev/null +++ b/src/components/layout/Navbar/Navbar.tsx @@ -0,0 +1,490 @@ +import React, { useMemo, useRef, useState } from 'react' +import { + Typography, + Box, + Popover, + useTheme, + Button, + Input, + List, + ListItem, + ListItemText +} from '@mui/material' +import AccountCircle from '@mui/icons-material/AccountCircle' +import AddBoxIcon from '@mui/icons-material/AddBox' +import Badge from '@mui/material/Badge' +import NotificationsIcon from '@mui/icons-material/Notifications' +import ExitToAppIcon from '@mui/icons-material/ExitToApp' +import { useNavigate } from 'react-router-dom' +import { togglePublishBlogModal } from '../../../state/features/globalSlice' +import { useDispatch, useSelector } from 'react-redux' +import AutoStoriesIcon from '@mui/icons-material/AutoStories' +import { RootState } from '../../../state/store' +import { UserNavbar } from '../../common/UserNavbar/UserNavbar' +import { removePrefix } from '../../../utils/blogIdformats' +import { useLocation } from 'react-router-dom' +import BookmarkIcon from '@mui/icons-material/Bookmark' +import SubscriptionsIcon from '@mui/icons-material/Subscriptions' +import { BlockedNamesModal } from '../../common/BlockedNamesModal/BlockedNamesModal' +import SearchIcon from '@mui/icons-material/Search' +import EmailIcon from '@mui/icons-material/Email' +import localforage from 'localforage' +const notification = localforage.createInstance({ + name: 'notification' +}) + +import BackspaceIcon from '@mui/icons-material/Backspace' +import { + AvatarContainer, + CreateBlogButton, + CustomAppBar, + CustomToolbar, + DropdownContainer, + DropdownText, + QblogLogoContainer, + StyledButton, + AuthenticateButton, + NavbarName +} from './Navbar-styles' +import { AccountCircleSVG } from '../../../assets/svgs/AccountCircleSVG' +import QblogLogo from '../../../assets/img/qBlogLogo.png' +import ExpandMoreIcon from '@mui/icons-material/ExpandMore' +import PersonOffIcon from '@mui/icons-material/PersonOff' +import { NewWindowSVG } from '../../../assets/svgs/NewWindowSVG' +import { + addFilteredPosts, + setFilterValue, + setIsFiltering +} from '../../../state/features/blogSlice' +import { Item } from '../../common/Comments/CommentEditor' +import { formatDate } from '../../../utils/time' +interface Props { + isAuthenticated: boolean + hasBlog: boolean + userName: string | null + userAvatar: string + blog: any + authenticate: () => void + hasAttemptedToFetchBlogInitial: boolean +} + +function useQuery() { + return new URLSearchParams(useLocation().search) +} + +const NavBar: React.FC = ({ + isAuthenticated, + hasBlog, + userName, + userAvatar, + blog, + authenticate, + hasAttemptedToFetchBlogInitial +}) => { + const navigate = useNavigate() + const dispatch = useDispatch() + const theme = useTheme() + const query = useQuery() + const { visitingBlog } = useSelector((state: RootState) => state.global) + const notifications = useSelector( + (state: RootState) => state.global.notifications + ) + const notificationCreatorComment = useSelector( + (state: RootState) => state.global.notificationCreatorComment + ) + + const fullNotifications = useMemo(() => { + return [...notificationCreatorComment, ...notifications].sort( + (a, b) => b.created - a.created + ) + }, [notificationCreatorComment, notifications]) + const location = useLocation() + const [anchorEl, setAnchorEl] = React.useState(null) + const [anchorElNotification, setAnchorElNotification] = + React.useState(null) + const [isOpenModal, setIsOpenModal] = React.useState(false) + const [searchVal, setSearchVal] = useState('') + const searchValRef = useRef('') + const inputRef = useRef(null) + const stripBlogId = removePrefix(visitingBlog?.blogId || '') + if (visitingBlog?.navbarConfig && location?.pathname?.includes(stripBlogId)) { + return ( + + ) + } + + 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 handleClose = () => { + setAnchorEl(null) + } + const onClose = () => { + setIsOpenModal(false) + } + const open = Boolean(anchorEl) + const id = open ? 'simple-popover' : undefined + const openPopover = Boolean(anchorElNotification) + const idNotification = openPopover ? 'simple-popover-notification' : undefined + + return ( + + + { + navigate(`/`) + dispatch(setIsFiltering(false)) + dispatch(setFilterValue('')) + dispatch(addFilteredPosts([])) + searchValRef.current = '' + if (!inputRef.current) return + inputRef.current.value = '' + }} + /> + + { + searchValRef.current = e.target.value + }} + onKeyDown={(event) => { + if (event.key === 'Enter' || event.keyCode === 13) { + if (!searchValRef.current) { + dispatch(setIsFiltering(false)) + dispatch(setFilterValue('')) + dispatch(addFilteredPosts([])) + searchValRef.current = '' + if (!inputRef.current) return + inputRef.current.value = '' + return + } + navigate('/') + dispatch(setIsFiltering(true)) + dispatch(addFilteredPosts([])) + dispatch(setFilterValue(searchValRef.current)) + } + }} + placeholder="Filter by name" + 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(addFilteredPosts([])) + searchValRef.current = '' + if (!inputRef.current) return + inputRef.current.value = '' + return + } + navigate('/') + dispatch(setIsFiltering(true)) + dispatch(addFilteredPosts([])) + dispatch(setFilterValue(searchValRef.current)) + }} + /> + { + dispatch(setIsFiltering(false)) + dispatch(setFilterValue('')) + dispatch(addFilteredPosts([])) + searchValRef.current = '' + if (!inputRef.current) return + inputRef.current.value = '' + }} + /> + + + {/* Add isAuthenticated && before username and wrap StyledButton in this condition*/} + {!isAuthenticated && ( + + + Authenticate + + )} + + + + + + + {fullNotifications.map((notification: any, index: number) => ( + { + const str = notification.postId + const arr = str.split('-post-') + const str1 = arr[0] + const str2 = arr[1] + const blogId = removePrefix(str1) + navigate( + `/${notification.postName}/${blogId}/${str2}?comment=${notification.identifier}` + ) + }} + > + + + From {notification.name} + + + } + secondary={ + + + {formatDate(notification.created)} + + + {' -comment'} + + + } + /> + + ))} + + + + {/* */} + {isAuthenticated && + userName && + hasAttemptedToFetchBlogInitial && + !hasBlog && ( + { + dispatch(togglePublishBlogModal(true)) + }} + > + + Create Blog + + )} + {isAuthenticated && userName && hasBlog && ( + <> + } + onClick={() => { + navigate(`/post/new`) + }} + > + Create Post + + + } + onClick={() => { + navigate(`/${userName}/${blog.blogId}`) + }} + > + My Blog + + + )} + + {isAuthenticated && userName && ( + + {userName} + {!userAvatar ? ( + + ) : ( + User Avatar + )} + + + )} + + navigate('/favorites')}> + + Favorites + + navigate('/subscriptions')}> + + Subscriptions + + { + setIsOpenModal(true) + handleClose() + }} + > + + Blocked Names + + + + + + Q-Mail + + + + {isOpenModal && ( + + )} + + + + ) +} + +export default NavBar diff --git a/src/components/modals/ConsentModal.tsx b/src/components/modals/ConsentModal.tsx new file mode 100644 index 0000000..2a176f2 --- /dev/null +++ b/src/components/modals/ConsentModal.tsx @@ -0,0 +1,70 @@ +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-blog-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 ( +
+ + Welcome + + + The Qortal community, along with its development team and the + creators of this application, cannot be held accountable for any + content published or displayed. Furthermore, they bear no + responsibility for any data loss that may occur as a result of using + this application. + + + + + + +
+ ) +} diff --git a/src/components/modals/EditBlogModal.tsx b/src/components/modals/EditBlogModal.tsx new file mode 100644 index 0000000..631ac25 --- /dev/null +++ b/src/components/modals/EditBlogModal.tsx @@ -0,0 +1,247 @@ +import React, { useState } from 'react' +import { + Box, + Button, + TextField, + Typography, + Modal, + Select, + MenuItem, + FormControl, + InputLabel, + SelectChangeEvent, + OutlinedInput, + Chip, + IconButton +} from '@mui/material' +import { useDispatch } from 'react-redux' +import { togglePublishBlogModal } from '../../state/features/globalSlice' +import AddIcon from '@mui/icons-material/Add' +import CloseIcon from '@mui/icons-material/Close' +import { styled } from '@mui/system' +interface SelectOption { + id: string + name: string +} +interface MyModalProps { + open: boolean + onClose: () => void + onPublish: ( + title: string, + description: string, + category: string, + tags: string[] + ) => Promise + currentBlog: any +} + +const ChipContainer = styled(Box)({ + display: 'flex', + flexWrap: 'wrap', + '& > *': { + margin: '4px' + } +}) + +const MyModal: React.FC = ({ + open, + onClose, + onPublish, + currentBlog +}) => { + const dispatch = useDispatch() + + const [title, setTitle] = useState('') + const [description, setDescription] = useState('') + const [errorMessage, setErrorMessage] = useState('') + const [selectedOption, setSelectedOption] = useState( + null + ) + const [inputValue, setInputValue] = useState('') + const [chips, setChips] = useState([]) + + const [options, setOptions] = useState([]) + React.useEffect(() => { + if (currentBlog) { + setTitle(currentBlog?.title || '') + setDescription(currentBlog?.description || '') + const findCategory = options.find( + (option) => option.id === currentBlog?.category + ) + if (!findCategory) return + setSelectedOption(findCategory) + if (!currentBlog?.tags || !Array.isArray(currentBlog.tags)) return + setChips(currentBlog.tags) + } + }, [currentBlog, options]) + + const handlePublish = async (): Promise => { + try { + await onPublish(title, description, selectedOption?.id || '', chips) + handleClose() + } catch (error: any) { + setErrorMessage(error.message) + } + } + + const handleClose = (): void => { + setErrorMessage('') + dispatch(togglePublishBlogModal(false)) + onClose() + } + + const handleOptionChange = (event: SelectChangeEvent) => { + const optionId = event.target.value + const selectedOption = options.find((option) => option.id === optionId) + setSelectedOption(selectedOption || null) + } + + const handleChipDelete = (index: number) => { + const newChips = [...chips] + newChips.splice(index, 1) + setChips(newChips) + } + + const handleInputChange = (event: any) => { + setInputValue(event.target.value) + } + + const handleInputKeyDown = (event: any) => { + if (event.key === 'Enter' && inputValue !== '') { + if (chips.length < 5) { + setChips([...chips, inputValue]) + setInputValue('') + } else { + event.preventDefault() + } + } + } + + const addChip = () => { + if (chips.length < 5) { + setChips([...chips, inputValue]) + setInputValue('') + } + } + + const getListCategories = React.useCallback(async () => { + try { + const url = `/arbitrary/categories` + const response = await fetch(url, { + method: 'GET', + headers: { + 'Content-Type': 'application/json' + } + }) + const responseData = await response.json() + setOptions(responseData) + } catch (error) {} + }, []) + + React.useEffect(() => { + getListCategories() + }, [getListCategories]) + + return ( + + + + Edit Blog + + setTitle(e.target.value)} + fullWidth + /> + setDescription(e.target.value)} + multiline + rows={4} + fullWidth + /> + {options.length > 0 && ( + + Select a Category + + + )} + + + + + + + + + + + {chips.map((chip, index) => ( + handleChipDelete(index)} + deleteIcon={} + /> + ))} + + + {errorMessage && ( + + {errorMessage} + + )} + + + + + + + ) +} + +export default MyModal diff --git a/src/components/modals/PublishBlogModal.tsx b/src/components/modals/PublishBlogModal.tsx new file mode 100644 index 0000000..5ce6045 --- /dev/null +++ b/src/components/modals/PublishBlogModal.tsx @@ -0,0 +1,281 @@ +import React, { ChangeEvent, useState } from 'react' +import { + Box, + Button, + TextField, + Typography, + Modal, + Select, + MenuItem, + FormControl, + InputLabel, + SelectChangeEvent, + OutlinedInput, + Chip, + IconButton +} from '@mui/material' +import { useDispatch } from 'react-redux' +import { togglePublishBlogModal } from '../../state/features/globalSlice' +import AddIcon from '@mui/icons-material/Add' +import CloseIcon from '@mui/icons-material/Close' +import { styled } from '@mui/system' +interface SelectOption { + id: string + name: string +} +interface MyModalProps { + open: boolean + onClose: () => void + onPublish: ( + title: string, + description: string, + category: string, + tags: string[], + blogIdentifier: string + ) => Promise + username: string +} + +const ChipContainer = styled(Box)({ + display: 'flex', + flexWrap: 'wrap', + '& > *': { + margin: '4px' + } +}) + +const MyModal: React.FC = ({ + open, + onClose, + onPublish, + username +}) => { + const dispatch = useDispatch() + + const [title, setTitle] = useState('') + const [description, setDescription] = useState('') + const [errorMessage, setErrorMessage] = useState('') + const [selectedOption, setSelectedOption] = useState( + null + ) + const [inputValue, setInputValue] = useState('') + const [chips, setChips] = useState([]) + const [blogIdentifier, setBlogIdentifier] = useState(username || '') + const [options, setOptions] = useState([]) + const handlePublish = async (): Promise => { + try { + await onPublish( + title, + description, + selectedOption?.id || '', + chips, + blogIdentifier + ) + handleClose() + } catch (error: any) { + setErrorMessage(error.message) + } + } + + const handleClose = (): void => { + setTitle('') + setDescription('') + setErrorMessage('') + dispatch(togglePublishBlogModal(false)) + onClose() + } + + const handleOptionChange = (event: SelectChangeEvent) => { + const optionId = event.target.value + const selectedOption = options.find((option) => option.id === optionId) + setSelectedOption(selectedOption || null) + } + + const handleChipDelete = (index: number) => { + const newChips = [...chips] + newChips.splice(index, 1) + setChips(newChips) + } + + const handleInputChange = (event: any) => { + setInputValue(event.target.value) + } + + const handleInputKeyDown = (event: any) => { + if (event.key === 'Enter' && inputValue !== '') { + if (chips.length < 5) { + setChips([...chips, inputValue]) + setInputValue('') + } else { + event.preventDefault() + } + } + } + + const addChip = () => { + if (chips.length < 5) { + setChips([...chips, inputValue]) + setInputValue('') + } + } + + const getListCategories = React.useCallback(async () => { + try { + const url = `/arbitrary/categories` + const response = await fetch(url, { + method: 'GET', + headers: { + 'Content-Type': 'application/json' + } + }) + const responseData = await response.json() + setOptions(responseData) + } catch (error) {} + }, []) + + React.useEffect(() => { + getListCategories() + }, [getListCategories]) + + const handleInputChangeId = (event: ChangeEvent) => { + // Replace any non-alphanumeric and non-space characters with an empty string + // Replace multiple spaces with a single dash and remove any dashes that come one after another + let newValue = event.target.value + .replace(/[^a-zA-Z0-9\s-]/g, '') + .replace(/\s+/g, '-') + .replace(/-+/g, '-') + .trim() + + if (newValue.toLowerCase().includes('post')) { + // Replace the 'post' string with an empty string + newValue = newValue.replace(/post/gi, '') + } + if (newValue.toLowerCase().includes('q-blog')) { + // Replace the 'q-blog' string with an empty string + newValue = newValue.replace(/q-blog/gi, '') + } + setBlogIdentifier(newValue) + } + + return ( + + + + Create blog + + setTitle(e.target.value)} + fullWidth + disabled={true} + /> + + + + setTitle(e.target.value)} + fullWidth + /> + setDescription(e.target.value)} + multiline + rows={4} + fullWidth + /> + {options.length > 0 && ( + + Select a Category + + + )} + + + + + + + + + + {chips.map((chip, index) => ( + handleChipDelete(index)} + deleteIcon={} + /> + ))} + + + {errorMessage && ( + + {errorMessage} + + )} + + + + + + + ) +} + +export default MyModal diff --git a/src/components/modals/ReusableModal.tsx b/src/components/modals/ReusableModal.tsx new file mode 100644 index 0000000..210aa0d --- /dev/null +++ b/src/components/modals/ReusableModal.tsx @@ -0,0 +1,47 @@ +import React from 'react' +import { Box, Modal, useTheme } from '@mui/material' + +interface MyModalProps { + open: boolean + onClose?: () => void + onSubmit?: (obj: any) => Promise + children: any + customStyles?: any +} + +export const ReusableModal: React.FC = ({ + open, + onClose, + onSubmit, + children, + customStyles = {} +}) => { + const theme = useTheme() + return ( + + + {children} + + + ) +} diff --git a/src/constants/mail.ts b/src/constants/mail.ts new file mode 100644 index 0000000..bbb6e7b --- /dev/null +++ b/src/constants/mail.ts @@ -0,0 +1,3 @@ +export const MAIL_SERVICE_TYPE: 'MAIL_PRIVATE' = 'MAIL_PRIVATE' +export const MAIL_ATTACHMENT_SERVICE_TYPE: 'ATTACHMENT_PRIVATE' = + 'ATTACHMENT_PRIVATE' diff --git a/src/global.d.ts b/src/global.d.ts new file mode 100644 index 0000000..213f36d --- /dev/null +++ b/src/global.d.ts @@ -0,0 +1,61 @@ +// 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 + count?: number + query?: string + exactMatchNames?: boolean + excludeBlocked?: boolean + mode?: string +} + +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/useFetchMail.tsx b/src/hooks/useFetchMail.tsx new file mode 100644 index 0000000..b156ee0 --- /dev/null +++ b/src/hooks/useFetchMail.tsx @@ -0,0 +1,469 @@ +import React from 'react' +import { useDispatch, useSelector } from 'react-redux' +import { + addPosts, + addToHashMap, + BlogPost, + populateFavorites, + setCountNewPosts, + upsertFilteredPosts, + upsertPosts, + upsertPostsBeginning, + upsertSubscriptionPosts +} from '../state/features/blogSlice' +import { + setCurrentBlog, + setIsLoadingGlobal, + setUserAvatarHash +} from '../state/features/globalSlice' +import { RootState } from '../state/store' +import { fetchAndEvaluatePosts } from '../utils/fetchPosts' +import { fetchAndEvaluateMail } from '../utils/fetchMail' +import { + addToHashMapMail, + upsertMessages, + upsertMessagesBeginning +} from '../state/features/mailSlice' +import { MAIL_SERVICE_TYPE } from '../constants/mail' + +export const useFetchMail = () => { + const dispatch = useDispatch() + const hashMapPosts = useSelector( + (state: RootState) => state.blog.hashMapPosts + ) + const hashMapMailMessages = useSelector( + (state: RootState) => state.mail.hashMapMailMessages + ) + const posts = useSelector((state: RootState) => state.blog.posts) + const mailMessages = useSelector( + (state: RootState) => state.mail.mailMessages + ) + + const filteredPosts = useSelector( + (state: RootState) => state.blog.filteredPosts + ) + const favoritesLocal = useSelector( + (state: RootState) => state.blog.favoritesLocal + ) + const favorites = useSelector((state: RootState) => state.blog.favorites) + const subscriptionPosts = useSelector( + (state: RootState) => state.blog.subscriptionPosts + ) + const subscriptions = useSelector( + (state: RootState) => state.blog.subscriptions + ) + + const checkAndUpdatePost = React.useCallback( + (post: BlogPost) => { + // Check if the post exists in hashMapPosts + const existingPost = hashMapPosts[post.id] + if (!existingPost) { + // If the post doesn't exist, add it to hashMapPosts + return true + } else if ( + post?.updated && + existingPost?.updated && + (!existingPost?.updated || post?.updated) > existingPost?.updated + ) { + // If the post exists and its updated is more recent than the existing post's updated, update it in hashMapPosts + return true + } else { + return false + } + }, + [hashMapPosts] + ) + + const getBlogPost = async (user: string, postId: string, content: any) => { + const res = await fetchAndEvaluatePosts({ + user, + postId, + content + }) + + dispatch(addToHashMap(res)) + } + + const getMailMessage = async (user: string, postId: string, content: any) => { + const res = await fetchAndEvaluateMail({ + user, + postId, + content + }) + + dispatch(addToHashMapMail(res)) + } + + const checkNewMessages = React.useCallback( + async (recipientName: string, recipientAddress: string) => { + try { + const query = `qortal_qmail_${recipientName.slice( + 0, + 20 + )}_${recipientAddress.slice(-6)}_mail_` + const url = `/arbitrary/resources/search?mode=ALL&service=${MAIL_SERVICE_TYPE}&query=${query}&limit=20&includemetadata=true&reverse=true&excludeblocked=true` + const response = await fetch(url, { + method: 'GET', + headers: { + 'Content-Type': 'application/json' + } + }) + const responseData = await response.json() + const latestPost = mailMessages[0] + if (!latestPost) return + const findPost = responseData?.findIndex( + (item: any) => item?.identifier === latestPost?.id + ) + if (findPost === -1) { + return + } + const newArray = responseData.slice(0, findPost) + const structureData = newArray.map((post: any): BlogPost => { + return { + title: post?.metadata?.title, + category: post?.metadata?.category, + categoryName: post?.metadata?.categoryName, + tags: post?.metadata?.tags || [], + description: post?.metadata?.description, + createdAt: post?.created, + updated: post?.updated, + user: post.name, + id: post.identifier + } + }) + dispatch(upsertMessagesBeginning(structureData)) + return + } catch (error) {} + }, + [mailMessages] + ) + + const getNewPosts = React.useCallback(async () => { + try { + dispatch(setIsLoadingGlobal(true)) + dispatch(setCountNewPosts(0)) + const url = `/arbitrary/resources/search?mode=ALL&service=BLOG_POST&query=q-blog-&limit=20&includemetadata=true&reverse=true&excludeblocked=true` + const response = await fetch(url, { + method: 'GET', + headers: { + 'Content-Type': 'application/json' + } + }) + const responseData = await response.json() + const latestPost = posts[0] + if (!latestPost) return + const findPost = responseData?.findIndex( + (item: any) => item?.identifier === latestPost?.id + ) + let fetchAll = responseData + let willFetchAll = true + if (findPost !== -1) { + willFetchAll = false + fetchAll = responseData.slice(0, findPost) + } + + const structureData = fetchAll.map((post: any): BlogPost => { + return { + title: post?.metadata?.title, + category: post?.metadata?.category, + categoryName: post?.metadata?.categoryName, + tags: post?.metadata?.tags || [], + description: post?.metadata?.description, + createdAt: post?.created, + updated: post?.updated, + user: post.name, + postImage: '', + id: post.identifier + } + }) + if (!willFetchAll) { + dispatch(upsertPostsBeginning(structureData)) + } + if (willFetchAll) { + dispatch(addPosts(structureData)) + } + + for (const content of structureData) { + if (content.user && content.id) { + const res = checkAndUpdatePost(content) + if (res) { + getBlogPost(content.user, content.id, content) + } + } + } + } catch (error) { + } finally { + dispatch(setIsLoadingGlobal(false)) + } + }, [posts, hashMapPosts]) + + const getBlogPosts = React.useCallback(async () => { + try { + const offset = posts.length + + dispatch(setIsLoadingGlobal(true)) + const url = `/arbitrary/resources/search?mode=ALL&service=BLOG_POST&query=q-blog-&limit=20&includemetadata=true&offset=${offset}&reverse=true&excludeblocked=true` + const response = await fetch(url, { + method: 'GET', + headers: { + 'Content-Type': 'application/json' + } + }) + const responseData = await response.json() + const structureData = responseData.map((post: any): BlogPost => { + return { + title: post?.metadata?.title, + category: post?.metadata?.category, + categoryName: post?.metadata?.categoryName, + tags: post?.metadata?.tags || [], + description: post?.metadata?.description, + createdAt: post?.created, + updated: post?.updated, + user: post.name, + postImage: '', + id: post.identifier + } + }) + dispatch(upsertPosts(structureData)) + + for (const content of structureData) { + if (content.user && content.id) { + const res = checkAndUpdatePost(content) + if (res) { + getBlogPost(content.user, content.id, content) + } + } + } + } catch (error) { + } finally { + dispatch(setIsLoadingGlobal(false)) + } + }, [posts, hashMapPosts]) + + const getAvatar = async (user: string) => { + try { + let url = await qortalRequest({ + action: 'GET_QDN_RESOURCE_URL', + name: user, + service: 'THUMBNAIL', + identifier: 'qortal_avatar' + }) + dispatch( + setUserAvatarHash({ + name: user, + url + }) + ) + } catch (error) {} + } + const getMailMessages = React.useCallback( + async (recipientName: string, recipientAddress: string) => { + try { + const offset = mailMessages.length + + dispatch(setIsLoadingGlobal(true)) + const query = `qortal_qmail_${recipientName.slice( + 0, + 20 + )}_${recipientAddress.slice(-6)}_mail_` + const url = `/arbitrary/resources/search?mode=ALL&service=${MAIL_SERVICE_TYPE}&query=${query}&limit=20&includemetadata=true&offset=${offset}&reverse=true&excludeblocked=true` + const response = await fetch(url, { + method: 'GET', + headers: { + 'Content-Type': 'application/json' + } + }) + const responseData = await response.json() + const structureData = responseData.map((post: any): BlogPost => { + return { + title: post?.metadata?.title, + category: post?.metadata?.category, + categoryName: post?.metadata?.categoryName, + tags: post?.metadata?.tags || [], + description: post?.metadata?.description, + createdAt: post?.created, + updated: post?.updated, + user: post.name, + id: post.identifier + } + }) + dispatch(upsertMessages(structureData)) + + for (const content of structureData) { + if (content.user && content.id) { + getAvatar(content.user) + } + } + } catch (error) { + } finally { + dispatch(setIsLoadingGlobal(false)) + } + }, + [mailMessages, hashMapMailMessages] + ) + const getBlogFilteredPosts = React.useCallback( + async (filterValue: string) => { + try { + const offset = filteredPosts.length + + dispatch(setIsLoadingGlobal(true)) + const url = `/arbitrary/resources/search?mode=ALL&service=BLOG_POST&query=q-blog-&limit=20&includemetadata=true&offset=${offset}&reverse=true&excludeblocked=true&name=${filterValue}` + const response = await fetch(url, { + method: 'GET', + headers: { + 'Content-Type': 'application/json' + } + }) + const responseData = await response.json() + const structureData = responseData.map((post: any): BlogPost => { + return { + title: post?.metadata?.title, + category: post?.metadata?.category, + categoryName: post?.metadata?.categoryName, + tags: post?.metadata?.tags || [], + description: post?.metadata?.description, + createdAt: post?.created, + updated: post?.updated, + user: post.name, + postImage: '', + id: post.identifier + } + }) + dispatch(upsertFilteredPosts(structureData)) + + for (const content of structureData) { + if (content.user && content.id) { + const res = checkAndUpdatePost(content) + if (res) { + getBlogPost(content.user, content.id, content) + } + } + } + } catch (error) { + } finally { + dispatch(setIsLoadingGlobal(false)) + } + }, + [filteredPosts, hashMapPosts] + ) + + const getBlogPostsSubscriptions = React.useCallback( + async (username: string) => { + try { + const offset = subscriptionPosts.length + dispatch(setIsLoadingGlobal(true)) + const url = `/arbitrary/resources/search?mode=ALL&service=BLOG_POST&query=q-blog-&limit=20&includemetadata=true&offset=${offset}&reverse=true&namefilter=q-blog-subscriptions-${username}&excludeblocked=true` + const response = await fetch(url, { + method: 'GET', + headers: { + 'Content-Type': 'application/json' + } + }) + const responseData = await response.json() + const structureData = responseData.map((post: any): BlogPost => { + return { + title: post?.metadata?.title, + category: post?.metadata?.category, + categoryName: post?.metadata?.categoryName, + tags: post?.metadata?.tags || [], + description: post?.metadata?.description, + createdAt: '', + user: post.name, + postImage: '', + id: post.identifier + } + }) + dispatch(upsertSubscriptionPosts(structureData)) + + for (const content of structureData) { + if (content.user && content.id) { + const res = checkAndUpdatePost(content) + if (res) { + getBlogPost(content.user, content.id, content) + } + } + } + } catch (error) { + } finally { + dispatch(setIsLoadingGlobal(false)) + } + }, + [subscriptionPosts, hashMapPosts, subscriptions] + ) + + const getBlogPostsFavorites = React.useCallback(async () => { + try { + const offset = favorites.length + const favSlice = (favoritesLocal || []).slice(offset, 20) + let favs = [] + for (const item of favSlice) { + try { + // await qortalRequest({ + // action: "SEARCH_QDN_RESOURCES", + // service: "THUMBNAIL", + // query: "search query goes here", // Optional - searches both "identifier" and "name" fields + // identifier: "search query goes here", // Optional - searches only the "identifier" field + // name: "search query goes here", // Optional - searches only the "name" field + // prefix: false, // Optional - if true, only the beginning of fields are matched in all of the above filters + // default: false, // Optional - if true, only resources without identifiers are returned + // includeStatus: false, // Optional - will take time to respond, so only request if necessary + // includeMetadata: false, // Optional - will take time to respond, so only request if necessary + // limit: 100, + // offset: 0, + // reverse: true + // }); + //TODO - NAME SHOULD BE EXACT + const url = `/arbitrary/resources/search?mode=ALL&service=BLOG_POST&identifier=${item.id}&exactmatchnames=true&name=${item.user}&limit=20&includemetadata=true&reverse=true&excludeblocked=true` + const response = await fetch(url, { + method: 'GET', + headers: { + 'Content-Type': 'application/json' + } + }) + const data = await response.json() + // + if (data.length > 0) { + favs.push(data[0]) + } + } catch (error) {} + } + const structureData = favs.map((post: any): BlogPost => { + return { + title: post?.metadata?.title, + category: post?.metadata?.category, + categoryName: post?.metadata?.categoryName, + tags: post?.metadata?.tags || [], + description: post?.metadata?.description, + createdAt: '', + user: post.name, + postImage: '', + id: post.identifier + } + }) + dispatch(populateFavorites(structureData)) + + for (const content of structureData) { + if (content.user && content.id) { + const res = checkAndUpdatePost(content) + if (res) { + getBlogPost(content.user, content.id, content) + } + } + } + } catch (error) { + } finally { + } + }, [hashMapPosts, favoritesLocal]) + return { + getBlogPosts, + getBlogPostsFavorites, + getBlogPostsSubscriptions, + checkAndUpdatePost, + getBlogPost, + hashMapPosts, + checkNewMessages, + getNewPosts, + getBlogFilteredPosts, + getMailMessages + } +} diff --git a/src/hooks/useFetchPosts.tsx b/src/hooks/useFetchPosts.tsx new file mode 100644 index 0000000..f9ca156 --- /dev/null +++ b/src/hooks/useFetchPosts.tsx @@ -0,0 +1,362 @@ +import React from 'react' +import { useDispatch, useSelector } from 'react-redux' +import { + addPosts, + addToHashMap, + BlogPost, + populateFavorites, + setCountNewPosts, + upsertFilteredPosts, + upsertPosts, + upsertPostsBeginning, + upsertSubscriptionPosts +} from '../state/features/blogSlice' +import { + setCurrentBlog, + setIsLoadingGlobal +} from '../state/features/globalSlice' +import { RootState } from '../state/store' +import { fetchAndEvaluatePosts } from '../utils/fetchPosts' + +export const useFetchPosts = () => { + const dispatch = useDispatch() + const hashMapPosts = useSelector( + (state: RootState) => state.blog.hashMapPosts + ) + const posts = useSelector((state: RootState) => state.blog.posts) + const filteredPosts = useSelector( + (state: RootState) => state.blog.filteredPosts + ) + const favoritesLocal = useSelector( + (state: RootState) => state.blog.favoritesLocal + ) + const favorites = useSelector((state: RootState) => state.blog.favorites) + const subscriptionPosts = useSelector( + (state: RootState) => state.blog.subscriptionPosts + ) + const subscriptions = useSelector( + (state: RootState) => state.blog.subscriptions + ) + + const checkAndUpdatePost = React.useCallback( + (post: BlogPost) => { + // Check if the post exists in hashMapPosts + const existingPost = hashMapPosts[post.id] + if (!existingPost) { + // If the post doesn't exist, add it to hashMapPosts + return true + } else if ( + post?.updated && + existingPost?.updated && + (!existingPost?.updated || post?.updated) > existingPost?.updated + ) { + // If the post exists and its updated is more recent than the existing post's updated, update it in hashMapPosts + return true + } else { + return false + } + }, + [hashMapPosts] + ) + + const getBlogPost = async (user: string, postId: string, content: any) => { + const res = await fetchAndEvaluatePosts({ + user, + postId, + content + }) + + dispatch(addToHashMap(res)) + } + + const checkNewMessages = React.useCallback(async () => { + try { + const url = `/arbitrary/resources/search?mode=ALL&service=BLOG_POST&query=q-blog-&limit=20&includemetadata=true&reverse=true&excludeblocked=true` + const response = await fetch(url, { + method: 'GET', + headers: { + 'Content-Type': 'application/json' + } + }) + const responseData = await response.json() + const latestPost = posts[0] + if (!latestPost) return + const findPost = responseData?.findIndex( + (item: any) => item?.identifier === latestPost?.id + ) + if (findPost === -1) { + dispatch(setCountNewPosts(responseData.length)) + return + } + const newArray = responseData.slice(0, findPost) + dispatch(setCountNewPosts(newArray.length)) + return + } catch (error) {} + }, [posts]) + + const getNewPosts = React.useCallback(async () => { + try { + dispatch(setIsLoadingGlobal(true)) + dispatch(setCountNewPosts(0)) + const url = `/arbitrary/resources/search?mode=ALL&service=BLOG_POST&query=q-blog-&limit=20&includemetadata=true&reverse=true&excludeblocked=true` + const response = await fetch(url, { + method: 'GET', + headers: { + 'Content-Type': 'application/json' + } + }) + const responseData = await response.json() + const latestPost = posts[0] + if (!latestPost) return + const findPost = responseData?.findIndex( + (item: any) => item?.identifier === latestPost?.id + ) + let fetchAll = responseData + let willFetchAll = true + if (findPost !== -1) { + willFetchAll = false + fetchAll = responseData.slice(0, findPost) + } + + const structureData = fetchAll.map((post: any): BlogPost => { + return { + title: post?.metadata?.title, + category: post?.metadata?.category, + categoryName: post?.metadata?.categoryName, + tags: post?.metadata?.tags || [], + description: post?.metadata?.description, + createdAt: post?.created, + updated: post?.updated, + user: post.name, + postImage: '', + id: post.identifier + } + }) + if (!willFetchAll) { + dispatch(upsertPostsBeginning(structureData)) + } + if (willFetchAll) { + dispatch(addPosts(structureData)) + } + + for (const content of structureData) { + if (content.user && content.id) { + const res = checkAndUpdatePost(content) + if (res) { + getBlogPost(content.user, content.id, content) + } + } + } + } catch (error) { + } finally { + dispatch(setIsLoadingGlobal(false)) + } + }, [posts, hashMapPosts]) + + const getBlogPosts = React.useCallback(async () => { + try { + const offset = posts.length + + dispatch(setIsLoadingGlobal(true)) + const url = `/arbitrary/resources/search?mode=ALL&service=BLOG_POST&query=q-blog-&limit=20&includemetadata=true&offset=${offset}&reverse=true&excludeblocked=true` + const response = await fetch(url, { + method: 'GET', + headers: { + 'Content-Type': 'application/json' + } + }) + const responseData = await response.json() + const structureData = responseData.map((post: any): BlogPost => { + return { + title: post?.metadata?.title, + category: post?.metadata?.category, + categoryName: post?.metadata?.categoryName, + tags: post?.metadata?.tags || [], + description: post?.metadata?.description, + createdAt: post?.created, + updated: post?.updated, + user: post.name, + postImage: '', + id: post.identifier + } + }) + dispatch(upsertPosts(structureData)) + + for (const content of structureData) { + if (content.user && content.id) { + const res = checkAndUpdatePost(content) + if (res) { + getBlogPost(content.user, content.id, content) + } + } + } + } catch (error) { + } finally { + dispatch(setIsLoadingGlobal(false)) + } + }, [posts, hashMapPosts]) + const getBlogFilteredPosts = React.useCallback( + async (filterValue: string) => { + try { + const offset = filteredPosts.length + + dispatch(setIsLoadingGlobal(true)) + const url = `/arbitrary/resources/search?mode=ALL&service=BLOG_POST&query=q-blog-&limit=20&includemetadata=true&offset=${offset}&reverse=true&excludeblocked=true&name=${filterValue}` + const response = await fetch(url, { + method: 'GET', + headers: { + 'Content-Type': 'application/json' + } + }) + const responseData = await response.json() + const structureData = responseData.map((post: any): BlogPost => { + return { + title: post?.metadata?.title, + category: post?.metadata?.category, + categoryName: post?.metadata?.categoryName, + tags: post?.metadata?.tags || [], + description: post?.metadata?.description, + createdAt: post?.created, + updated: post?.updated, + user: post.name, + postImage: '', + id: post.identifier + } + }) + dispatch(upsertFilteredPosts(structureData)) + + for (const content of structureData) { + if (content.user && content.id) { + const res = checkAndUpdatePost(content) + if (res) { + getBlogPost(content.user, content.id, content) + } + } + } + } catch (error) { + } finally { + dispatch(setIsLoadingGlobal(false)) + } + }, + [filteredPosts, hashMapPosts] + ) + + const getBlogPostsSubscriptions = React.useCallback( + async (username: string) => { + try { + const offset = subscriptionPosts.length + dispatch(setIsLoadingGlobal(true)) + const url = `/arbitrary/resources/search?mode=ALL&service=BLOG_POST&query=q-blog-&limit=20&includemetadata=true&offset=${offset}&reverse=true&namefilter=q-blog-subscriptions-${username}&excludeblocked=true` + const response = await fetch(url, { + method: 'GET', + headers: { + 'Content-Type': 'application/json' + } + }) + const responseData = await response.json() + const structureData = responseData.map((post: any): BlogPost => { + return { + title: post?.metadata?.title, + category: post?.metadata?.category, + categoryName: post?.metadata?.categoryName, + tags: post?.metadata?.tags || [], + description: post?.metadata?.description, + createdAt: '', + user: post.name, + postImage: '', + id: post.identifier + } + }) + dispatch(upsertSubscriptionPosts(structureData)) + + for (const content of structureData) { + if (content.user && content.id) { + const res = checkAndUpdatePost(content) + if (res) { + getBlogPost(content.user, content.id, content) + } + } + } + } catch (error) { + } finally { + dispatch(setIsLoadingGlobal(false)) + } + }, + [subscriptionPosts, hashMapPosts, subscriptions] + ) + + const getBlogPostsFavorites = React.useCallback(async () => { + try { + const offset = favorites.length + const favSlice = (favoritesLocal || []).slice(offset, 20) + let favs = [] + for (const item of favSlice) { + try { + // await qortalRequest({ + // action: "SEARCH_QDN_RESOURCES", + // service: "THUMBNAIL", + // query: "search query goes here", // Optional - searches both "identifier" and "name" fields + // identifier: "search query goes here", // Optional - searches only the "identifier" field + // name: "search query goes here", // Optional - searches only the "name" field + // prefix: false, // Optional - if true, only the beginning of fields are matched in all of the above filters + // default: false, // Optional - if true, only resources without identifiers are returned + // includeStatus: false, // Optional - will take time to respond, so only request if necessary + // includeMetadata: false, // Optional - will take time to respond, so only request if necessary + // limit: 100, + // offset: 0, + // reverse: true + // }); + //TODO - NAME SHOULD BE EXACT + const url = `/arbitrary/resources/search?mode=ALL&service=BLOG_POST&identifier=${item.id}&exactmatchnames=true&name=${item.user}&limit=20&includemetadata=true&reverse=true&excludeblocked=true` + const response = await fetch(url, { + method: 'GET', + headers: { + 'Content-Type': 'application/json' + } + }) + const data = await response.json() + // + if (data.length > 0) { + favs.push(data[0]) + } + } catch (error) {} + } + const structureData = favs.map((post: any): BlogPost => { + return { + title: post?.metadata?.title, + category: post?.metadata?.category, + categoryName: post?.metadata?.categoryName, + tags: post?.metadata?.tags || [], + description: post?.metadata?.description, + createdAt: '', + user: post.name, + postImage: '', + id: post.identifier + } + }) + dispatch(populateFavorites(structureData)) + + for (const content of structureData) { + if (content.user && content.id) { + const res = checkAndUpdatePost(content) + if (res) { + getBlogPost(content.user, content.id, content) + } + } + } + } catch (error) { + } finally { + } + }, [hashMapPosts, favoritesLocal]) + return { + getBlogPosts, + getBlogPostsFavorites, + getBlogPostsSubscriptions, + checkAndUpdatePost, + getBlogPost, + hashMapPosts, + checkNewMessages, + getNewPosts, + getBlogFilteredPosts + } +} diff --git a/src/index.css b/src/index.css new file mode 100644 index 0000000..1044a93 --- /dev/null +++ b/src/index.css @@ -0,0 +1,162 @@ +@font-face { + font-family: 'CambonLight'; + src: url('./styles/fonts/Cambon-Light.ttf') format('truetype'); +} + +@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: 0.75; + transition: 0.2s all; +} + +.post-image { + max-width: 100%; + border-radius: 5px; + width: 100%; + height: 100%; +} + +.grid-item { + /* Other styles */ + /* overflow: auto; */ +} + +.grid-item-view { + /* Other styles */ + /* overflow: auto; */ +} + +.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 */ +} + +.glow { + box-shadow: 0 0 10px #9ecaed, 0 0 20px #9ecaed, 0 0 30px #9ecaed, + 0 0 40px #9ecaed; +} diff --git a/src/index.d.ts b/src/index.d.ts new file mode 100644 index 0000000..996a468 --- /dev/null +++ b/src/index.d.ts @@ -0,0 +1,9 @@ +declare module 'webworker:getBlogWorker' { + const value: new () => Worker; + export default value; +} + +declare module 'webworker:decodeBase64' { + const value: new () => Worker + export default value +} \ No newline at end of file diff --git a/src/interfaces/interfaces.ts b/src/interfaces/interfaces.ts new file mode 100644 index 0000000..48b7666 --- /dev/null +++ b/src/interfaces/interfaces.ts @@ -0,0 +1,8 @@ +export interface BlogContent { + postContent: any[] + title: string + createdAt: number + user?: any + postId?: string + layouts?: any +} \ No newline at end of file diff --git a/src/main.tsx b/src/main.tsx new file mode 100644 index 0000000..b456834 --- /dev/null +++ b/src/main.tsx @@ -0,0 +1,19 @@ +import React from 'react' +import ReactDOM from 'react-dom/client' +import App from './App' +import './index.css' +import { HashRouter, BrowserRouter } from 'react-router-dom' +interface CustomWindow extends Window { + _qdnBase: any // Replace 'any' with the appropriate type if you know it +} + +const customWindow = window as unknown as CustomWindow + +// Now you can access the _qdnTheme property without TypeScript errors +const baseUrl = customWindow?._qdnBase || '' +ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( + + +