From ac7e48c5f6a5fdf5071d43294ed2def69e75865e Mon Sep 17 00:00:00 2001 From: Sheldon Guo Date: Sun, 30 Jun 2024 10:09:46 +0800 Subject: [PATCH] refactor: rewrite the UI of the code scanner. (#4677) * feat: workbench block * feat: mobilePage * fix: update WorkbenchAction * feat: support qrcode embed in markdown and scan in mobile * fix: fix markdown button be covered problem * fix: fix unit test error * fix: fix unit test errors * refactor: use react router in qrcode scanner * feat: markdown add loading * fix: fix blank content in print page * refactor: change plugin dependencies to devDependencies * feat: add some padding in markdown editor * chore: improve some code * feat: improve code * fix: add QRCodeScanner * fix: iconColor * fix: Improve code * feat: Improve code * fix: version * chore: improve some code * chore: improve some code * fix: i18n * refactor: refact the UI of code scanner * feat: add some locale * feat: add qrbox * feat: add image upload and fix qrbox * feat: fix full screen problem * fix: fix not full screen problem * fix: add some error handling * feat: add album locale --------- Co-authored-by: chenos --- lerna.json | 4 +- .../plugin-block-workbench/package.json | 2 + .../src/client/WorkbenchBlock.tsx | 2 +- ...rkbenchScanActionSchemaInitializerItem.tsx | 36 +--- .../components/qrcode-scanner/ScanBox.tsx | 29 +++ .../components/qrcode-scanner/index.tsx | 200 ++++++++++++++---- .../components/qrcode-scanner/useScanner.ts | 77 +++++++ .../src/locale/zh-CN.json | 8 +- yarn.lock | 111 ++++++++-- 9 files changed, 373 insertions(+), 96 deletions(-) create mode 100644 packages/plugins/@nocobase/plugin-block-workbench/src/client/components/qrcode-scanner/ScanBox.tsx create mode 100644 packages/plugins/@nocobase/plugin-block-workbench/src/client/components/qrcode-scanner/useScanner.ts diff --git a/lerna.json b/lerna.json index 8a5d92685..5c9714c5f 100644 --- a/lerna.json +++ b/lerna.json @@ -2,9 +2,7 @@ "version": "1.2.11-alpha", "npmClient": "yarn", "useWorkspaces": true, - "npmClientArgs": [ - "--ignore-engines" - ], + "npmClientArgs": ["--ignore-engines"], "command": { "version": { "forcePublish": true, diff --git a/packages/plugins/@nocobase/plugin-block-workbench/package.json b/packages/plugins/@nocobase/plugin-block-workbench/package.json index 47f5020e2..7b25f4f5b 100644 --- a/packages/plugins/@nocobase/plugin-block-workbench/package.json +++ b/packages/plugins/@nocobase/plugin-block-workbench/package.json @@ -12,6 +12,8 @@ "@nocobase/test": "1.x" }, "devDependencies": { + "@ant-design/icons": "^5.x", + "antd": "^5.x", "html5-qrcode": "^2.3.8", "react-router-dom": "^6.x" }, diff --git a/packages/plugins/@nocobase/plugin-block-workbench/src/client/WorkbenchBlock.tsx b/packages/plugins/@nocobase/plugin-block-workbench/src/client/WorkbenchBlock.tsx index 1291b2ce8..1be89fd6d 100644 --- a/packages/plugins/@nocobase/plugin-block-workbench/src/client/WorkbenchBlock.tsx +++ b/packages/plugins/@nocobase/plugin-block-workbench/src/client/WorkbenchBlock.tsx @@ -37,7 +37,7 @@ const InternalIcons = () => { {fieldSchema.mapProperties((s, key) => ( - + ))} diff --git a/packages/plugins/@nocobase/plugin-block-workbench/src/client/WorkbenchScanActionSchemaInitializerItem.tsx b/packages/plugins/@nocobase/plugin-block-workbench/src/client/WorkbenchScanActionSchemaInitializerItem.tsx index 6aad14f1c..c6ea7464a 100644 --- a/packages/plugins/@nocobase/plugin-block-workbench/src/client/WorkbenchScanActionSchemaInitializerItem.tsx +++ b/packages/plugins/@nocobase/plugin-block-workbench/src/client/WorkbenchScanActionSchemaInitializerItem.tsx @@ -11,7 +11,6 @@ import { ButtonEditor, ISchema, SchemaSettings, - useActionContext, useSchemaInitializer, useSchemaInitializerItem, } from '@nocobase/client'; @@ -45,14 +44,6 @@ export function WorkbenchScanActionSchemaInitializerItem(props) { // 调用插入功能 const { insert } = useSchemaInitializer(); const { t } = useTranslation(); - const useCancelAction = () => { - const { setVisible } = useActionContext(); - return { - run() { - setVisible(false); - }, - }; - }; return ( +
+
+
+
+
+
+
+
+ + ); +} diff --git a/packages/plugins/@nocobase/plugin-block-workbench/src/client/components/qrcode-scanner/index.tsx b/packages/plugins/@nocobase/plugin-block-workbench/src/client/components/qrcode-scanner/index.tsx index 00d8be470..fd471ff7c 100644 --- a/packages/plugins/@nocobase/plugin-block-workbench/src/client/components/qrcode-scanner/index.tsx +++ b/packages/plugins/@nocobase/plugin-block-workbench/src/client/components/qrcode-scanner/index.tsx @@ -6,51 +6,177 @@ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License. * For more information, please refer to: https://www.nocobase.com/agreement. */ +import { LeftOutlined, FileImageOutlined } from '@ant-design/icons'; +import { Html5Qrcode } from 'html5-qrcode'; +import React, { useState, useEffect, useRef } from 'react'; +import { useActionContext } from '@nocobase/client'; +import { useTranslation } from 'react-i18next'; +import { ScanBox } from './ScanBox'; +import { useScanner } from './useScanner'; -import { Html5QrcodeScanner } from 'html5-qrcode'; -import { useNavigate } from 'react-router-dom'; -import React, { useEffect } from 'react'; +const qrcodeEleId = 'qrcode'; +export const QRCodeScannerInner = (props) => { + const containerRef = useRef(); + const imgUploaderRef = useRef(); + const { t } = useTranslation('block-workbench'); + const [originVideoSize, setOriginVideoSize] = useState({ width: 0, height: 0 }); + const vw = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0); + const vh = Math.max(document.documentElement.clientHeight || 0, window.innerHeight || 0); -const qrcodeRegionId = 'html5qr-code-full-region'; + const { startScanFile } = useScanner({ + onScannerSizeChanged: setOriginVideoSize, + elementId: qrcodeEleId, + }); -// Creates the configuration object for Html5QrcodeScanner. -const createConfig = (props) => { - const config: any = {}; - if (props.fps) { - config.fps = props.fps; - } - if (props.qrbox) { - config.qrbox = props.qrbox; - } - if (props.aspectRatio) { - config.aspectRatio = props.aspectRatio; - } - if (props.disableFlip !== undefined) { - config.disableFlip = props.disableFlip; - } - return config; + const getBoxStyle = (): React.CSSProperties => { + const size = Math.floor(Math.min(vw, vh) * 0.6); + return { + left: `${(vw - size) / 2}px`, + top: `${(vh - size) / 2}px`, + position: 'fixed', + width: `${size}px`, + height: `${size}px`, + }; + }; + + const onImgBtnClick = () => { + if (imgUploaderRef.current) imgUploaderRef.current.click(); + }; + const onImgUploaded = (event: React.ChangeEvent) => { + const files = event.target.files; + if (files.length > 0) { + const file = files[0]; + if (file.size < 1000000) startScanFile(file); + else alert(t('The image size is too large. Please compress it to below 1MB before uploading')); + } + }; + + useEffect(() => { + document.documentElement.style.overscrollBehavior = 'none'; + return () => { + document.documentElement.style.overscrollBehavior = 'default'; + }; + }, []); + + useEffect(() => { + const { width, height } = originVideoSize; + const vw = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0); + const vh = Math.max(document.documentElement.clientHeight || 0, window.innerHeight || 0); + if (width > 0 && height > 0 && height < vh) { + const zoomRatio = vh / height; + const zoomedWidth = Math.floor(zoomRatio * width); + const video = document.getElementsByTagName('video')[0]; + video.style.height = `${vh}px`; + video.style.width = `${zoomedWidth}px`; + containerRef.current.style.left = `${(vw - zoomedWidth) / 2}px`; + containerRef.current.style.position = `absolute`; + } + }, [originVideoSize]); + + const ToolBar = () => { + return ( +
+
+ + {t('Album')} + +
+
+ ); + }; + const imageBtnStyle: React.CSSProperties = { + zIndex: '1003', + fontSize: '1.8em', + fontWeight: 'bold', + }; + + return ( + <> +
+ + + + ); }; export const QRCodeScanner = (props) => { - const navigate = useNavigate(); + const { visible, setVisible } = useActionContext(); + const [cameraAvaliable, setCameraAvaliable] = useState(false); + const { t } = useTranslation('block-workbench'); + useEffect(() => { - // when component mounts - const config = createConfig(props); - const verbose = props.verbose === true; - // Suceess callback is required. - const qrCodeSuccessCallback = (decodedText, decodedResult) => { - navigate(decodedText); + const getCameras = async () => { + try { + const res = await Html5Qrcode.getCameras(); + if (res.length === 0) alert(t('No camera device detected')); + else setCameraAvaliable(true); + } catch (error) { + const errMsgMap = { + NotFoundError: t('No camera device detected'), + NotAllowedError: t('You have not granted permission to use the camera'), + }; + console.log(error); + const msg = errMsgMap[error.name]; + alert(msg ?? error); + setCameraAvaliable(false); + setVisible(false); + } }; - const html5QrcodeScanner = new Html5QrcodeScanner(qrcodeRegionId, config, verbose); - html5QrcodeScanner.render(qrCodeSuccessCallback, props.qrCodeErrorCallback); + if (visible && !cameraAvaliable) getCameras(); + }, [visible, cameraAvaliable, setVisible, t]); - // cleanup function when component will unmount - return () => { - html5QrcodeScanner.clear().catch((error) => { - console.error('Failed to clear html5QrcodeScanner. ', error); - }); - }; - }, [navigate, props]); + const style: React.CSSProperties = { + position: 'fixed', + width: '100%', + height: '100%', + background: 'black', + zIndex: '1001', + top: 0, + left: 0, + overflow: 'hidden', + }; + const backIconStyle: React.CSSProperties = { + position: 'absolute', + top: '22px', + left: '20px', + zIndex: '1003', + color: 'white', + fontSize: '1.8em', + fontWeight: 'bold', + }; - return
; + const titleStyle: React.CSSProperties = { + position: 'absolute', + color: 'white', + fontSize: '1.5em', + left: 0, + right: 0, + top: '20px', + zIndex: '1002', + marginLeft: 'auto', + marginRight: 'auto', + textAlign: 'center', + }; + + return visible && cameraAvaliable ? ( +
+ + setVisible(false)} /> +
{t('Scan QR code')}
+
+ ) : null; }; diff --git a/packages/plugins/@nocobase/plugin-block-workbench/src/client/components/qrcode-scanner/useScanner.ts b/packages/plugins/@nocobase/plugin-block-workbench/src/client/components/qrcode-scanner/useScanner.ts new file mode 100644 index 000000000..fc6443896 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-block-workbench/src/client/components/qrcode-scanner/useScanner.ts @@ -0,0 +1,77 @@ +/** + * This file is part of the NocoBase (R) project. + * Copyright (c) 2020-2024 NocoBase Co., Ltd. + * Authors: NocoBase Team. + * + * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License. + * For more information, please refer to: https://www.nocobase.com/agreement. + */ + +import { Html5Qrcode, Html5QrcodeScannerState } from 'html5-qrcode'; +import { useState, useCallback, useMemo, useEffect } from 'react'; +import { useNavigate } from 'react-router-dom'; +import { useTranslation } from 'react-i18next'; + +export function useScanner({ onScannerSizeChanged, elementId }) { + const [scanner, setScanner] = useState(); + const navigate = useNavigate(); + const { t } = useTranslation('block-workbench'); + const viewPoint = useMemo(() => { + const vw = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0); + const vh = Math.max(document.documentElement.clientHeight || 0, window.innerHeight || 0); + return { width: vw, height: vh }; + }, []); + + const startScanCamera = useCallback( + async (scanner: Html5Qrcode) => { + return scanner.start( + { + facingMode: 'environment', + }, + { + fps: 10, + qrbox(width, height) { + const minEdge = Math.min(width, height); + onScannerSizeChanged({ width, height }); + return { width: viewPoint.width, height: viewPoint.height }; + }, + }, + (text) => { + navigate(text); + }, + undefined, + ); + }, + [navigate, onScannerSizeChanged, viewPoint], + ); + const stopScanner = useCallback(async (scanner: Html5Qrcode) => { + const state = scanner.getState(); + if ([Html5QrcodeScannerState.SCANNING, Html5QrcodeScannerState.PAUSED].includes(state)) { + return scanner.stop(); + } else return; + }, []); + + const startScanFile = useCallback( + async (file: File) => { + await stopScanner(scanner); + try { + const { decodedText } = await scanner.scanFileV2(file, false); + navigate(decodedText); + } catch (error) { + alert(t('QR code recognition failed, please scan again')); + startScanCamera(scanner); + } + }, + [scanner, stopScanner, startScanCamera, t, navigate], + ); + + useEffect(() => { + const scanner = new Html5Qrcode(elementId); + setScanner(scanner); + startScanCamera(scanner); + return () => { + stopScanner(scanner); + }; + }, [elementId, startScanCamera, stopScanner]); + return { startScanCamera, startScanFile }; +} diff --git a/packages/plugins/@nocobase/plugin-block-workbench/src/locale/zh-CN.json b/packages/plugins/@nocobase/plugin-block-workbench/src/locale/zh-CN.json index e8f3af2a1..747862c61 100644 --- a/packages/plugins/@nocobase/plugin-block-workbench/src/locale/zh-CN.json +++ b/packages/plugins/@nocobase/plugin-block-workbench/src/locale/zh-CN.json @@ -1,4 +1,10 @@ { "Workbench": "工作台", - "Scan QR code": "扫描二维码" + "Scan QR code": "扫描二维码", + "Album": "相册", + "No camera device detected": "未检测到摄像头设备", + "You have not granted permission to use the camera": "您未授权使用摄像头", + "Unknown error": "未知错误", + "The image size is too large. Please compress it to below 1MB before uploading": "图片尺寸过大,请压缩到1MB以下上传", + "QR code recognition failed, please scan again": "二维码识别失败,请重新扫描" } \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 137e6468d..e3132ac48 100644 --- a/yarn.lock +++ b/yarn.lock @@ -217,6 +217,11 @@ resolved "https://registry.npmmirror.com/@ant-design/icons-svg/-/icons-svg-4.3.1.tgz#4b2f65a17d4d32b526baa6414aca2117382bf8da" integrity sha512-4QBZg8ccyC6LPIRii7A0bZUk3+lEDCLnhB+FVsflGdcWPPmV+j3fire4AwwoqHV/BibgvBmR9ZIo4s867smv+g== +"@ant-design/icons-svg@^4.4.0": + version "4.4.2" + resolved "https://registry.npmmirror.com/@ant-design/icons-svg/-/icons-svg-4.4.2.tgz#ed2be7fb4d82ac7e1d45a54a5b06d6cecf8be6f6" + integrity sha512-vHbT+zJEVzllwP+CM+ul7reTEfBR0vgxFe7+lREAsAA7YGsYpboiq2sQNeQeRvh09GfQgs/GyFEvZpJ9cLXpXA== + "@ant-design/icons@5.x", "@ant-design/icons@^5.0.0", "@ant-design/icons@^5.1.3", "@ant-design/icons@^5.1.4", "@ant-design/icons@^5.2.5", "@ant-design/icons@^5.2.6": version "5.2.6" resolved "https://registry.npmmirror.com/@ant-design/icons/-/icons-5.2.6.tgz#2d4a9a37f531eb2a20cebec01d6fb69cf593900d" @@ -228,6 +233,17 @@ classnames "^2.2.6" rc-util "^5.31.1" +"@ant-design/icons@^5.3.7": + version "5.3.7" + resolved "https://registry.npmmirror.com/@ant-design/icons/-/icons-5.3.7.tgz#d9f3654bf7934ee5faba43f91b5a187f5309ec68" + integrity sha512-bCPXTAg66f5bdccM4TT21SQBDO1Ek2gho9h3nO9DAKXJP4sq+5VBjrQMSxMVXSB3HyEz+cUbHQ5+6ogxCOpaew== + dependencies: + "@ant-design/colors" "^7.0.0" + "@ant-design/icons-svg" "^4.4.0" + "@babel/runtime" "^7.11.2" + classnames "^2.2.6" + rc-util "^5.31.1" + "@ant-design/plots@^2.1.4": version "2.1.14" resolved "https://registry.npmmirror.com/@ant-design/plots/-/plots-2.1.14.tgz#967a6fbf3e86ad216026fdbb853af1391549c795" @@ -5172,11 +5188,6 @@ resolved "https://registry.npmmirror.com/@remix-run/router/-/router-1.14.0.tgz#9bc39a5a3a71b81bdb310eba6def5bc3966695b7" integrity sha512-WOHih+ClN7N8oHk9N4JUiMxQJmRVaOxcg8w7F/oHUXzJt920ekASLI/7cYX8XkntDWRhLZtsk6LbGrkgOAvi5A== -"@remix-run/router@1.16.1": - version "1.16.1" - resolved "https://registry.npmmirror.com/@remix-run/router/-/router-1.16.1.tgz#73db3c48b975eeb06d0006481bde4f5f2d17d1cd" - integrity sha512-es2g3dq6Nb07iFxGk5GuHN20RwBZOsuDQN7izWIisUcv9r+d2C5jQxqmgkdebXgReWfiyUabcki6Fg77mSNrig== - "@restart/hooks@^0.4.7": version "0.4.15" resolved "https://registry.npmmirror.com/@restart/hooks/-/hooks-0.4.15.tgz#70990085c9b79d1f3e140db824b29218bdc2b5bb" @@ -6788,13 +6799,20 @@ "@types/prop-types" "*" "@types/react" "*" -"@types/react-dom@17.x", "@types/react-dom@^17.0.0", "@types/react-dom@^18.0.0": +"@types/react-dom@17.x", "@types/react-dom@^17.0.0": version "17.0.25" resolved "https://registry.npmmirror.com/@types/react-dom/-/react-dom-17.0.25.tgz#e0e5b3571e1069625b3a3da2b279379aa33a0cb5" integrity sha512-urx7A7UxkZQmThYA4So0NelOVjx3V4rNFVJwp0WZlbIK5eM4rNJDiN3R/E9ix0MBh6kAEojk/9YL+Te6D9zHNA== dependencies: "@types/react" "^17" +"@types/react-dom@^18.0.0": + version "18.3.0" + resolved "https://registry.npmmirror.com/@types/react-dom/-/react-dom-18.3.0.tgz#0cbc818755d87066ab6ca74fbedb2547d74a82b0" + integrity sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg== + dependencies: + "@types/react" "*" + "@types/react-redux@^7.1.20": version "7.1.33" resolved "https://registry.npmmirror.com/@types/react-redux/-/react-redux-7.1.33.tgz#53c5564f03f1ded90904e3c90f77e4bd4dc20b15" @@ -6805,7 +6823,7 @@ hoist-non-react-statics "^3.3.0" redux "^4.0.0" -"@types/react@*", "@types/react@16 || 17 || 18", "@types/react@17.x", "@types/react@>=16.9.11", "@types/react@^17", "@types/react@^17.0.0", "@types/react@^18.0.0": +"@types/react@*", "@types/react@16 || 17 || 18", "@types/react@17.x", "@types/react@>=16.9.11", "@types/react@^17", "@types/react@^17.0.0": version "17.0.73" resolved "https://registry.npmmirror.com/@types/react/-/react-17.0.73.tgz#23a663c803b18d8b7f4f2bb9b467f2f3fd70787a" integrity sha512-6AcjgPIVsXTIsFDgsGW0iQhvg0xb2vt2qAWgXyncnVNRaW9ZXTTwAh7RQoh7PzK1AhjPoGDvUBkdAREih9n5oQ== @@ -6814,6 +6832,14 @@ "@types/scheduler" "*" csstype "^3.0.2" +"@types/react@^18.0.0": + version "18.3.3" + resolved "https://registry.npmmirror.com/@types/react/-/react-18.3.3.tgz#9679020895318b0915d7a3ab004d92d33375c45f" + integrity sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw== + dependencies: + "@types/prop-types" "*" + csstype "^3.0.2" + "@types/readdir-glob@*": version "1.1.5" resolved "https://registry.npmmirror.com/@types/readdir-glob/-/readdir-glob-1.1.5.tgz#21a4a98898fc606cb568ad815f2a0eedc24d412a" @@ -7046,7 +7072,17 @@ semver "^7.5.4" ts-api-utils "^1.0.1" -"@typescript-eslint/parser@^5.62.0", "@typescript-eslint/parser@^6.2.0": +"@typescript-eslint/parser@^5.62.0": + version "5.62.0" + resolved "https://registry.npmmirror.com/@typescript-eslint/parser/-/parser-5.62.0.tgz#1b63d082d849a2fcae8a569248fbe2ee1b8a56c7" + integrity sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA== + dependencies: + "@typescript-eslint/scope-manager" "5.62.0" + "@typescript-eslint/types" "5.62.0" + "@typescript-eslint/typescript-estree" "5.62.0" + debug "^4.3.4" + +"@typescript-eslint/parser@^6.2.0": version "6.21.0" resolved "https://registry.npmmirror.com/@typescript-eslint/parser/-/parser-6.21.0.tgz#af8fcf66feee2edc86bc5d1cf45e33b0630bf35b" integrity sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ== @@ -8125,7 +8161,7 @@ antd-token-previewer@^2.0.0-alpha.6: use-debouncy "~4.3.0" vanilla-jsoneditor "^0.16.1" -antd@5.12.8, antd@5.x, antd@^5.12.8, antd@^5.5.1: +antd@5.x, antd@^5.12.8, antd@^5.5.1, antd@^5.x: version "5.12.8" resolved "https://registry.npmmirror.com/antd/-/antd-5.12.8.tgz#94fea825e9bae535af7adf70417fa1f0dadc4c98" integrity sha512-R2CRcB+aaVZurb3J0IKpBRWq5kW4CLcSqDF58/QBsqYdzK7XjSvM8+eF3rWVRUDbSJfGmyW7I80ywNRYpW1+vA== @@ -14908,7 +14944,7 @@ highlight.js@^10.1.0, highlight.js@^10.2.0: resolved "https://registry.npmmirror.com/highlight.js/-/highlight.js-10.7.3.tgz#697272e3991356e40c3cac566a74eef681756531" integrity sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A== -history@5.3.0: +history@5.3.0, history@^5.2.0: version "5.3.0" resolved "https://registry.npmmirror.com/history/-/history-5.3.0.tgz#1548abaa245ba47992f063a0783db91ef201c73b" integrity sha512-ZqaKwjjrAYUYfLG+htGaIIZ4nioX2L70ZUMIFysS3xvBsSG4x/n1V6TXV3N8ZYNuFGlDirFg32T7B6WOUPDYcQ== @@ -19337,7 +19373,7 @@ number-is-nan@^1.0.0: resolved "https://registry.npmmirror.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" integrity sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ== -nwsapi@2.2.7, nwsapi@^2.2.0: +nwsapi@^2.2.0: version "2.2.7" resolved "https://registry.npmmirror.com/nwsapi/-/nwsapi-2.2.7.tgz#738e0707d3128cb750dddcfe90e4610482df0f30" integrity sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ== @@ -21871,7 +21907,15 @@ react-copy-to-clipboard@^5.1.0: copy-to-clipboard "^3.3.1" prop-types "^15.8.1" -react-dom@18.1.0, react-dom@18.x, react-dom@^18.0.0, react-dom@^18.2.0: +react-dom@18.1.0: + version "18.1.0" + resolved "https://registry.npmmirror.com/react-dom/-/react-dom-18.1.0.tgz#7f6dd84b706408adde05e1df575b3a024d7e8a2f" + integrity sha512-fU1Txz7Budmvamp7bshe4Zi32d0ll7ect+ccxNu9FlObT605GOEB8BfO4tmRJ39R5Zj831VCpvQ05QPBW5yb+w== + dependencies: + loose-envify "^1.1.0" + scheduler "^0.22.0" + +react-dom@18.x, react-dom@^18.0.0, react-dom@^18.2.0: version "18.2.0" resolved "https://registry.npmmirror.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d" integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g== @@ -22063,7 +22107,15 @@ react-refresh@0.14.0, react-refresh@^0.14.0: resolved "https://registry.npmmirror.com/react-refresh/-/react-refresh-0.14.0.tgz#4e02825378a5f227079554d4284889354e5f553e" integrity sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ== -react-router-dom@6.3.0, react-router-dom@6.x, react-router-dom@^6.11.2, react-router-dom@^6.x: +react-router-dom@6.3.0: + version "6.3.0" + resolved "https://registry.npmmirror.com/react-router-dom/-/react-router-dom-6.3.0.tgz#a0216da813454e521905b5fa55e0e5176123f43d" + integrity sha512-uaJj7LKytRxZNQV8+RbzJWnJ8K2nPsOOEuX7aQstlMZKQT0164C+X2w6bnkqU3sjtLvpd5ojrezAyfZ1+0sStw== + dependencies: + history "^5.2.0" + react-router "6.3.0" + +react-router-dom@6.x, react-router-dom@^6.11.2, react-router-dom@^6.x: version "6.21.0" resolved "https://registry.npmmirror.com/react-router-dom/-/react-router-dom-6.21.0.tgz#aa4c6bc046a8e8723095bc09b3c0ab2254532712" integrity sha512-1dUdVj3cwc1npzJaf23gulB562ESNvxf7E4x8upNJycqyUm5BRRZ6dd3LrlzhtLaMrwOCO8R0zoiYxdaJx4LlQ== @@ -22071,12 +22123,19 @@ react-router-dom@6.3.0, react-router-dom@6.x, react-router-dom@^6.11.2, react-ro "@remix-run/router" "1.14.0" react-router "6.21.0" -react-router@6.21.0, react-router@6.3.0, react-router@^6.11.2: - version "6.23.1" - resolved "https://registry.npmmirror.com/react-router/-/react-router-6.23.1.tgz#d08cbdbd9d6aedc13eea6e94bc6d9b29cb1c4be9" - integrity sha512-fzcOaRF69uvqbbM7OhvQyBTFDVrrGlsFdS3AL+1KfIBtGETibHzi3FkoTRyiDJnWNc2VxrfvR+657ROHjaNjqQ== +react-router@6.21.0: + version "6.21.0" + resolved "https://registry.npmmirror.com/react-router/-/react-router-6.21.0.tgz#6fe3e59877aca3dccceec1801d26991ddf42d12b" + integrity sha512-hGZ0HXbwz3zw52pLZV3j3+ec+m/PQ9cTpBvqjFQmy2XVUWGn5MD+31oXHb6dVTxYzmAeaiUBYjkoNz66n3RGCg== dependencies: - "@remix-run/router" "1.16.1" + "@remix-run/router" "1.14.0" + +react-router@6.3.0: + version "6.3.0" + resolved "https://registry.npmmirror.com/react-router/-/react-router-6.3.0.tgz#3970cc64b4cb4eae0c1ea5203a80334fdd175557" + integrity sha512-7Wh1DzVQ+tlFjkeo+ujvjSqSJmkt1+8JO+T5xklPlgrh70y7ogx75ODRW0ThWhY7S+6yEDks8TYrtQe/aoboBQ== + dependencies: + history "^5.2.0" react-side-effect@^2.1.0: version "2.1.2" @@ -22095,7 +22154,14 @@ react-to-print@^2.14.7: resolved "https://registry.npmmirror.com/react-to-print/-/react-to-print-2.14.15.tgz#edb4ce8a92205cf37fd8c3d57de829034aa5c911" integrity sha512-SKnwOzU2cJ8eaAkoJO7+gNhvfEDmm+Y34IdcHsjtHioUevUPhprqbVtvNJlZ2JkGJ8ExK2QNWM9pXECTDR5D8w== -react@18.1.0, react@18.x, react@^18.0.0, react@^18.2.0: +react@18.1.0: + version "18.1.0" + resolved "https://registry.npmmirror.com/react/-/react-18.1.0.tgz#6f8620382decb17fdc5cc223a115e2adbf104890" + integrity sha512-4oL8ivCz5ZEPyclFQXaNksK3adutVS8l2xzZU0cqEFrE9Sb7fC0EFK5uEk74wIreL1DERyjvsU915j1pcT2uEQ== + dependencies: + loose-envify "^1.1.0" + +react@18.x, react@^18.0.0, react@^18.2.0: version "18.2.0" resolved "https://registry.npmmirror.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5" integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ== @@ -23095,6 +23161,13 @@ saxes@^5.0.1: dependencies: xmlchars "^2.2.0" +scheduler@^0.22.0: + version "0.22.0" + resolved "https://registry.npmmirror.com/scheduler/-/scheduler-0.22.0.tgz#83a5d63594edf074add9a7198b1bae76c3db01b8" + integrity sha512-6QAm1BgQI88NPYymgGQLCZgvep4FyePDWFpXVK+zNSUgHwlqpJy8VEh8Et0KxTACS4VWwMousBElAZOH9nkkoQ== + dependencies: + loose-envify "^1.1.0" + scheduler@^0.23.0: version "0.23.0" resolved "https://registry.npmmirror.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe"