diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..03d9549 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 0ab4521..1850686 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,13 +8,19 @@ "name": "pdfwiz-app", "version": "0.1.0", "dependencies": { + "@ant-design/icons": "^5.2.6", "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", "@types/jest": "^27.5.2", - "@types/node": "^16.18.54", - "@types/react": "^18.2.22", + "@types/node": "^16.18.48", + "@types/react": "^18.2.21", "@types/react-dom": "^18.2.7", + "antd": "^5.8.6", + "html2canvas": "^1.4.1", + "jspdf": "^2.5.1", + "pdf-lib": "^1.17.1", + "pdfjs-dist": "^3.10.174", "react": "^18.2.0", "react-dom": "^18.2.0", "react-scripts": "5.0.1", @@ -58,6 +64,71 @@ "node": ">=6.0.0" } }, + "node_modules/@ant-design/colors": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-7.0.0.tgz", + "integrity": "sha512-iVm/9PfGCbC0dSMBrz7oiEXZaaGH7ceU40OJEfKmyuzR9R5CRimJYPlRiFtMQGQcbNMea/ePcoIebi4ASGYXtg==", + "dependencies": { + "@ctrl/tinycolor": "^3.4.0" + } + }, + "node_modules/@ant-design/cssinjs": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/@ant-design/cssinjs/-/cssinjs-1.17.0.tgz", + "integrity": "sha512-MgGCZ6sfD3yQB0XW0hN4jgixMxApTlDYyct+pc7fRZNO4CaqWWm/9iXkkljNR27lyWLZmm+XiDfcIOo1bnrnMA==", + "dependencies": { + "@babel/runtime": "^7.11.1", + "@emotion/hash": "^0.8.0", + "@emotion/unitless": "^0.7.5", + "classnames": "^2.3.1", + "csstype": "^3.0.10", + "rc-util": "^5.35.0", + "stylis": "^4.0.13" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/@ant-design/icons": { + "version": "5.2.6", + "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-5.2.6.tgz", + "integrity": "sha512-4wn0WShF43TrggskBJPRqCD0fcHbzTYjnaoskdiJrVHg86yxoZ8ZUqsXvyn4WUqehRiFKnaclOhqk9w4Ui2KVw==", + "dependencies": { + "@ant-design/colors": "^7.0.0", + "@ant-design/icons-svg": "^4.3.0", + "@babel/runtime": "^7.11.2", + "classnames": "^2.2.6", + "rc-util": "^5.31.1" + }, + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/@ant-design/icons-svg": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@ant-design/icons-svg/-/icons-svg-4.3.1.tgz", + "integrity": "sha512-4QBZg8ccyC6LPIRii7A0bZUk3+lEDCLnhB+FVsflGdcWPPmV+j3fire4AwwoqHV/BibgvBmR9ZIo4s867smv+g==" + }, + "node_modules/@ant-design/react-slick": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@ant-design/react-slick/-/react-slick-1.0.2.tgz", + "integrity": "sha512-Wj8onxL/T8KQLFFiCA4t8eIRGpRR+UPgOdac2sYzonv+i0n3kXHmvHLLiOYL655DQx2Umii9Y9nNgL7ssu5haQ==", + "dependencies": { + "@babel/runtime": "^7.10.4", + "classnames": "^2.2.5", + "json2mq": "^0.2.0", + "resize-observer-polyfill": "^1.5.1", + "throttle-debounce": "^5.0.0" + }, + "peerDependencies": { + "react": ">=16.9.0" + } + }, "node_modules/@babel/code-frame": { "version": "7.22.13", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", @@ -2275,6 +2346,24 @@ "postcss-selector-parser": "^6.0.10" } }, + "node_modules/@ctrl/tinycolor": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz", + "integrity": "sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/@emotion/hash": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", + "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==" + }, + "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/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -3118,6 +3207,26 @@ "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==" }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "optional": true, + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { "version": "5.1.1-v1", "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", @@ -3178,6 +3287,22 @@ "node": ">= 8" } }, + "node_modules/@pdf-lib/standard-fonts": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@pdf-lib/standard-fonts/-/standard-fonts-1.0.0.tgz", + "integrity": "sha512-hU30BK9IUN/su0Mn9VdlVKsWBS6GyhVfqjwl1FjZN4TxP6cCw0jP2w7V3Hf5uX7M0AZJ16vey9yE0ny7Sa59ZA==", + "dependencies": { + "pako": "^1.0.6" + } + }, + "node_modules/@pdf-lib/upng": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@pdf-lib/upng/-/upng-1.0.1.tgz", + "integrity": "sha512-dQK2FUMQtowVP00mtIksrlZhdFXQZPC+taih1q4CvPZ5vqdxR/LKBaFg0oAfzd1GlHZXXSPdQfzQnt+ViGvEIQ==", + "dependencies": { + "pako": "^1.0.10" + } + }, "node_modules/@pmmmwh/react-refresh-webpack-plugin": { "version": "0.5.11", "resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.11.tgz", @@ -3227,6 +3352,119 @@ } } }, + "node_modules/@rc-component/color-picker": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@rc-component/color-picker/-/color-picker-1.4.1.tgz", + "integrity": "sha512-vh5EWqnsayZa/JwUznqDaPJz39jznx/YDbyBuVJntv735tKXKwEUZZb2jYEldOg+NKWZwtALjGMrNeGBmqFoEw==", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@ctrl/tinycolor": "^3.6.0", + "classnames": "^2.2.6", + "rc-util": "^5.30.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/context": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@rc-component/context/-/context-1.4.0.tgz", + "integrity": "sha512-kFcNxg9oLRMoL3qki0OMxK+7g5mypjgaaJp/pkOis/6rVxma9nJBF/8kCIuTYHUQNr0ii7MxqE33wirPZLJQ2w==", + "dependencies": { + "@babel/runtime": "^7.10.1", + "rc-util": "^5.27.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/mini-decimal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rc-component/mini-decimal/-/mini-decimal-1.1.0.tgz", + "integrity": "sha512-jS4E7T9Li2GuYwI6PyiVXmxTiM6b07rlD9Ge8uGZSCz3WlzcG5ZK7g5bbuKNeZ9pgUuPK/5guV781ujdVpm4HQ==", + "dependencies": { + "@babel/runtime": "^7.18.0" + }, + "engines": { + "node": ">=8.x" + } + }, + "node_modules/@rc-component/mutate-observer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rc-component/mutate-observer/-/mutate-observer-1.1.0.tgz", + "integrity": "sha512-QjrOsDXQusNwGZPf4/qRQasg7UFEj06XiCJ8iuiq/Io7CrHrgVi6Uuetw60WAMG1799v+aM8kyc+1L/GBbHSlw==", + "dependencies": { + "@babel/runtime": "^7.18.0", + "classnames": "^2.3.2", + "rc-util": "^5.24.4" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/portal": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@rc-component/portal/-/portal-1.1.2.tgz", + "integrity": "sha512-6f813C0IsasTZms08kfA8kPAGxbbkYToa8ALaiDIGGECU4i9hj8Plgbx0sNJDrey3EtHO30hmdaxtT0138xZcg==", + "dependencies": { + "@babel/runtime": "^7.18.0", + "classnames": "^2.3.2", + "rc-util": "^5.24.4" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/tour": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@rc-component/tour/-/tour-1.10.0.tgz", + "integrity": "sha512-voV0BKaTJbewB9LLgAHQ7tAGG7rgDkKQkZo82xw2gIk542hY+o7zwoqdN16oHhIKk7eG/xi+mdXrONT62Dt57A==", + "dependencies": { + "@babel/runtime": "^7.18.0", + "@rc-component/portal": "^1.0.0-9", + "@rc-component/trigger": "^1.3.6", + "classnames": "^2.3.2", + "rc-util": "^5.24.4" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/trigger": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/@rc-component/trigger/-/trigger-1.17.0.tgz", + "integrity": "sha512-KN+lKHCi7L4kjuA9DU2PnwZxtIyes6R1wsexp0/Rnjr/ITELsPuC9kpzDK1+7AZMarDXUAHUdDGS2zUNEx2P0g==", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@rc-component/portal": "^1.1.0", + "classnames": "^2.3.2", + "rc-align": "^4.0.0", + "rc-motion": "^2.0.0", + "rc-resize-observer": "^1.3.1", + "rc-util": "^5.33.0" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, "node_modules/@rollup/plugin-babel": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", @@ -4085,6 +4323,12 @@ "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.8.tgz", "integrity": "sha512-u95svzDlTysU5xecFNTgfFG5RUWu1A9P0VzgpcIiGZA9iraHOdSzcxMxQ55DyeRaGCSxQi7LxXDI4rzq/MYfdg==" }, + "node_modules/@types/raf": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@types/raf/-/raf-3.4.0.tgz", + "integrity": "sha512-taW5/WYqo36N7V39oYyHP9Ipfd5pNFvGTIQsNGj86xV88YQ7GnI30/yMfKDF7Zgin0m3e+ikX88FvImnK4RjGw==", + "optional": true + }, "node_modules/@types/range-parser": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", @@ -4569,6 +4813,12 @@ "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==" }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "optional": true + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -4770,6 +5020,69 @@ "node": ">=4" } }, + "node_modules/antd": { + "version": "5.9.2", + "resolved": "https://registry.npmjs.org/antd/-/antd-5.9.2.tgz", + "integrity": "sha512-+ecGt8nDCjvNvKkalJQc4eBGtfdQuZ/WLXrk7X4FbhAhMplctrey4/SOvHeXjEjBnyNC/KSdF4EzKYKq01egbA==", + "dependencies": { + "@ant-design/colors": "^7.0.0", + "@ant-design/cssinjs": "^1.16.0", + "@ant-design/icons": "^5.2.2", + "@ant-design/react-slick": "~1.0.0", + "@babel/runtime": "^7.18.3", + "@ctrl/tinycolor": "^3.6.0", + "@rc-component/color-picker": "~1.4.1", + "@rc-component/mutate-observer": "^1.1.0", + "@rc-component/tour": "~1.10.0", + "@rc-component/trigger": "^1.15.6", + "classnames": "^2.2.6", + "copy-to-clipboard": "^3.2.0", + "dayjs": "^1.11.1", + "qrcode.react": "^3.1.0", + "rc-cascader": "~3.16.0", + "rc-checkbox": "~3.1.0", + "rc-collapse": "~3.7.1", + "rc-dialog": "~9.2.0", + "rc-drawer": "~6.4.1", + "rc-dropdown": "~4.1.0", + "rc-field-form": "~1.38.0", + "rc-image": "~7.2.0", + "rc-input": "~1.1.1", + "rc-input-number": "~8.0.4", + "rc-mentions": "~2.7.0", + "rc-menu": "~9.12.0", + "rc-motion": "^2.9.0", + "rc-notification": "~5.1.1", + "rc-pagination": "~3.6.1", + "rc-picker": "~3.14.1", + "rc-progress": "~3.5.1", + "rc-rate": "~2.12.0", + "rc-resize-observer": "^1.3.1", + "rc-segmented": "~2.2.2", + "rc-select": "~14.8.1", + "rc-slider": "~10.2.1", + "rc-steps": "~6.0.1", + "rc-switch": "~4.1.0", + "rc-table": "~7.34.0", + "rc-tabs": "~12.12.1", + "rc-textarea": "~1.3.4", + "rc-tooltip": "~6.0.1", + "rc-tree": "~5.7.10", + "rc-tree-select": "~5.12.1", + "rc-upload": "~4.3.4", + "rc-util": "^5.37.0", + "scroll-into-view-if-needed": "^3.0.3", + "throttle-debounce": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ant-design" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, "node_modules/any-promise": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", @@ -4787,6 +5100,25 @@ "node": ">= 8" } }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "optional": true + }, + "node_modules/are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "optional": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/arg": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", @@ -4843,6 +5175,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/array-tree-filter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-tree-filter/-/array-tree-filter-2.1.0.tgz", + "integrity": "sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw==" + }, "node_modules/array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", @@ -4968,6 +5305,11 @@ "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" }, + "node_modules/async-validator": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-4.2.5.tgz", + "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==" + }, "node_modules/asynciterator.prototype": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz", @@ -4989,6 +5331,17 @@ "node": ">= 4.0.0" } }, + "node_modules/atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "bin": { + "atob": "bin/atob.js" + }, + "engines": { + "node": ">= 4.5.0" + } + }, "node_modules/autoprefixer": { "version": "10.4.16", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.16.tgz", @@ -5337,6 +5690,14 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, + "node_modules/base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/batch": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", @@ -5513,6 +5874,17 @@ "node-int64": "^0.4.0" } }, + "node_modules/btoa": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/btoa/-/btoa-1.2.1.tgz", + "integrity": "sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==", + "bin": { + "btoa": "bin/btoa.js" + }, + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -5615,6 +5987,46 @@ } ] }, + "node_modules/canvas": { + "version": "2.11.2", + "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.11.2.tgz", + "integrity": "sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw==", + "hasInstallScript": true, + "optional": true, + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.0", + "nan": "^2.17.0", + "simple-get": "^3.0.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/canvg": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/canvg/-/canvg-3.0.10.tgz", + "integrity": "sha512-qwR2FRNO9NlzTeKIPIKpnTY6fqwuYSequ8Ru8c0YkYU7U0oW+hLUvWadLvAu1Rl72OMNiFhoLu4f8eUjQ7l/+Q==", + "optional": true, + "dependencies": { + "@babel/runtime": "^7.12.5", + "@types/raf": "^3.4.0", + "core-js": "^3.8.3", + "raf": "^3.4.1", + "regenerator-runtime": "^0.13.7", + "rgbcolor": "^1.0.1", + "stackblur-canvas": "^2.0.0", + "svg-pathdata": "^6.0.3" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/canvg/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==", + "optional": true + }, "node_modules/case-sensitive-paths-webpack-plugin": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz", @@ -5686,6 +6098,15 @@ "node": ">= 6" } }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "optional": true, + "engines": { + "node": ">=10" + } + }, "node_modules/chrome-trace-event": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", @@ -5713,6 +6134,11 @@ "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==" }, + "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/clean-css": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.2.tgz", @@ -5782,6 +6208,15 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "optional": true, + "bin": { + "color-support": "bin.js" + } + }, "node_modules/colord": { "version": "2.9.3", "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", @@ -5875,6 +6310,11 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, + "node_modules/compute-scroll-into-view": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-3.0.3.tgz", + "integrity": "sha512-nadqwNxghAGTamwIqQSG433W6OADZx2vCo3UXHNrzTRHK/htu+7+L0zhjEoaeaQVNAi3YgqWDv8+tzf0hRfR+A==" + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -5893,6 +6333,12 @@ "node": ">=0.8" } }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "optional": true + }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -5930,6 +6376,14 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, + "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/core-js": { "version": "3.32.2", "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.32.2.tgz", @@ -6048,6 +6502,14 @@ "postcss": "^8.4" } }, + "node_modules/css-line-break": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz", + "integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==", + "dependencies": { + "utrie": "^1.0.2" + } + }, "node_modules/css-loader": { "version": "6.8.1", "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.8.1.tgz", @@ -6416,6 +6878,11 @@ "node": ">=10" } }, + "node_modules/dayjs": { + "version": "1.11.10", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", + "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==" + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -6437,6 +6904,18 @@ "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==" }, + "node_modules/decompress-response": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", + "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", + "optional": true, + "dependencies": { + "mimic-response": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/dedent": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", @@ -6539,6 +7018,12 @@ "node": ">=0.4.0" } }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "optional": true + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -6564,6 +7049,15 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/detect-libc": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", + "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==", + "optional": true, + "engines": { + "node": ">=8" + } + }, "node_modules/detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", @@ -6667,6 +7161,11 @@ "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==" }, + "node_modules/dom-align": { + "version": "1.12.4", + "resolved": "https://registry.npmjs.org/dom-align/-/dom-align-1.12.4.tgz", + "integrity": "sha512-R8LUSEay/68zE5c8/3BDxiTEvgb4xZTF0RKmAHfiEVN3klfIpXfi2/QCoiWPccVQ0J/ZGdz9OjzL4uJEP/MRAw==" + }, "node_modules/dom-converter": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", @@ -6732,6 +7231,12 @@ "url": "https://github.com/fb55/domhandler?sponsor=1" } }, + "node_modules/dompurify": { + "version": "2.4.7", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.4.7.tgz", + "integrity": "sha512-kxxKlPEDa6Nc5WJi+qRgPbOAbgTpSULL+vI3NUXsZMlkJxTqYI9wg5ZTay2sFrdZRWHPWNi+EdAhcJf81WtoMQ==", + "optional": true + }, "node_modules/domutils": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", @@ -7911,6 +8416,11 @@ "bser": "2.1.1" } }, + "node_modules/fflate": { + "version": "0.4.8", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.4.8.tgz", + "integrity": "sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==" + }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -8303,6 +8813,36 @@ "node": ">=12" } }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs-minipass/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "optional": true + }, "node_modules/fs-monkey": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.4.tgz", @@ -8356,6 +8896,26 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "optional": true, + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -8655,6 +9215,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "optional": true + }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -8787,6 +9353,18 @@ "webpack": "^5.20.0" } }, + "node_modules/html2canvas": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz", + "integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==", + "dependencies": { + "css-line-break": "^2.1.0", + "text-segmentation": "^1.0.3" + }, + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/htmlparser2": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", @@ -11669,6 +12247,14 @@ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" }, + "node_modules/json2mq": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/json2mq/-/json2mq-0.2.0.tgz", + "integrity": "sha512-SzoRg7ux5DWTII9J2qkrZrqV1gt+rTaoufMxEzXbS26Uid0NwaJd123HcoB80TgubEppxxIGdNxCx50fEoEWQA==", + "dependencies": { + "string-convert": "^0.2.0" + } + }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -11721,6 +12307,23 @@ "node": ">=0.10.0" } }, + "node_modules/jspdf": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/jspdf/-/jspdf-2.5.1.tgz", + "integrity": "sha512-hXObxz7ZqoyhxET78+XR34Xu2qFGrJJ2I2bE5w4SM8eFaFEkW2xcGRVUss360fYelwRSid/jT078kbNvmoW0QA==", + "dependencies": { + "@babel/runtime": "^7.14.0", + "atob": "^2.1.2", + "btoa": "^1.2.1", + "fflate": "^0.4.8" + }, + "optionalDependencies": { + "canvg": "^3.0.6", + "core-js": "^3.6.0", + "dompurify": "^2.2.0", + "html2canvas": "^1.0.0-rc.5" + } + }, "node_modules/jsx-ast-utils": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", @@ -12060,8 +12663,20 @@ "node": ">=6" } }, - "node_modules/min-indent": { - "version": "1.0.1", + "node_modules/mimic-response": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", + "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", + "optional": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", "engines": { @@ -12159,6 +12774,46 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "optional": true, + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "optional": true + }, "node_modules/mkdirp": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", @@ -12197,6 +12852,12 @@ "thenify-all": "^1.0.0" } }, + "node_modules/nan": { + "version": "2.18.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.18.0.tgz", + "integrity": "sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==", + "optional": true + }, "node_modules/nanoid": { "version": "3.3.6", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", @@ -12246,6 +12907,48 @@ "tslib": "^2.0.3" } }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "optional": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "optional": true + }, + "node_modules/node-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "optional": true + }, + "node_modules/node-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "optional": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/node-forge": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", @@ -12264,6 +12967,21 @@ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==" }, + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "optional": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -12302,6 +13020,18 @@ "node": ">=8" } }, + "node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "optional": true, + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, "node_modules/nth-check": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", @@ -12594,6 +13324,11 @@ "node": ">=6" } }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" + }, "node_modules/param-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", @@ -12695,6 +13430,43 @@ "node": ">=8" } }, + "node_modules/path2d-polyfill": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path2d-polyfill/-/path2d-polyfill-2.0.1.tgz", + "integrity": "sha512-ad/3bsalbbWhmBo0D6FZ4RNMwsLsPpL6gnvhuSaU5Vm7b06Kr5ubSltQQ0T7YKsiJQO+g22zJ4dJKNTXIyOXtA==", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/pdf-lib": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/pdf-lib/-/pdf-lib-1.17.1.tgz", + "integrity": "sha512-V/mpyJAoTsN4cnP31vc0wfNA1+p20evqqnap0KLoRUN0Yk/p3wN52DOEsL4oBFcLdb76hlpKPtzJIgo67j/XLw==", + "dependencies": { + "@pdf-lib/standard-fonts": "^1.0.0", + "@pdf-lib/upng": "^1.0.1", + "pako": "^1.0.11", + "tslib": "^1.11.1" + } + }, + "node_modules/pdf-lib/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/pdfjs-dist": { + "version": "3.11.174", + "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-3.11.174.tgz", + "integrity": "sha512-TdTZPf1trZ8/UFu5Cx/GXB7GZM30LT+wWUNfsi6Bq8ePLnb+woNKtDymI2mxZYBpMbonNFqKmiz684DIfnd8dA==", + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "canvas": "^2.11.2", + "path2d-polyfill": "^2.0.1" + } + }, "node_modules/performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", @@ -14171,6 +14943,14 @@ "teleport": ">=0.2.0" } }, + "node_modules/qrcode.react": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/qrcode.react/-/qrcode.react-3.1.0.tgz", + "integrity": "sha512-oyF+Urr3oAMUG/OiOuONL3HXM+53wvuH3mtIWQrYmsXoAq0DkvZp2RYUWFSMFtbdOpuS++9v+WAkzNVkMlNW6Q==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/qs": { "version": "6.11.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", @@ -14266,6 +15046,597 @@ "node": ">=0.10.0" } }, + "node_modules/rc-align": { + "version": "4.0.15", + "resolved": "https://registry.npmjs.org/rc-align/-/rc-align-4.0.15.tgz", + "integrity": "sha512-wqJtVH60pka/nOX7/IspElA8gjPNQKIx/ZqJ6heATCkXpe1Zg4cPVrMD2vC96wjsFFL8WsmhPbx9tdMo1qqlIA==", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "dom-align": "^1.7.0", + "rc-util": "^5.26.0", + "resize-observer-polyfill": "^1.5.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-cascader": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/rc-cascader/-/rc-cascader-3.16.0.tgz", + "integrity": "sha512-c62glOhm66T0/Y8vOfIgZwHHTbqCyC7FvBTcNDuwbXZc8Dfbz6fB1yIuCB55z5rPA7nsUfMyNNuS8shReZWM+A==", + "dependencies": { + "@babel/runtime": "^7.12.5", + "array-tree-filter": "^2.1.0", + "classnames": "^2.3.1", + "rc-select": "~14.8.0", + "rc-tree": "~5.7.0", + "rc-util": "^5.35.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-checkbox": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/rc-checkbox/-/rc-checkbox-3.1.0.tgz", + "integrity": "sha512-PAwpJFnBa3Ei+5pyqMMXdcKYKNBMS+TvSDiLdDnARnMJHC8ESxwPfm4Ao1gJiKtWLdmGfigascnCpwrHFgoOBQ==", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.3.2", + "rc-util": "^5.25.2" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-collapse": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/rc-collapse/-/rc-collapse-3.7.1.tgz", + "integrity": "sha512-N/7ejyiTf3XElNJBBpxqnZBUuMsQWEOPjB2QkfNvZ/Ca54eAvJXuOD1EGbCWCk2m7v/MSxku7mRpdeaLOCd4Gg==", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-motion": "^2.3.4", + "rc-util": "^5.27.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-dialog": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/rc-dialog/-/rc-dialog-9.2.0.tgz", + "integrity": "sha512-dL2tklMou/QfK77+0CTH3FTnKCvIiYv9Df7PfFfg8YVXhYAGmuIkV4ooQYHAIR4juL3Ywcm5oQflF2vDDuGlUg==", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/portal": "^1.0.0-8", + "classnames": "^2.2.6", + "rc-motion": "^2.3.0", + "rc-util": "^5.21.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-drawer": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/rc-drawer/-/rc-drawer-6.4.1.tgz", + "integrity": "sha512-QIbNMjiZy322o9uEpJHsSZ5rS/zuxqam3lYVPDzjztoqsoDzTNNxWN77QVpOfQ0UC9/87+qu25zocJ+O9bK2Tg==", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/portal": "^1.1.1", + "classnames": "^2.2.6", + "rc-motion": "^2.6.1", + "rc-util": "^5.36.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-dropdown": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/rc-dropdown/-/rc-dropdown-4.1.0.tgz", + "integrity": "sha512-VZjMunpBdlVzYpEdJSaV7WM7O0jf8uyDjirxXLZRNZ+tAC+NzD3PXPEtliFwGzVwBBdCmGuSqiS9DWcOLxQ9tw==", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@rc-component/trigger": "^1.7.0", + "classnames": "^2.2.6", + "rc-util": "^5.17.0" + }, + "peerDependencies": { + "react": ">=16.11.0", + "react-dom": ">=16.11.0" + } + }, + "node_modules/rc-field-form": { + "version": "1.38.2", + "resolved": "https://registry.npmjs.org/rc-field-form/-/rc-field-form-1.38.2.tgz", + "integrity": "sha512-O83Oi1qPyEv31Sg+Jwvsj6pXc8uQI2BtIAkURr5lvEYHVggXJhdU/nynK8wY1gbw0qR48k731sN5ON4egRCROA==", + "dependencies": { + "@babel/runtime": "^7.18.0", + "async-validator": "^4.1.0", + "rc-util": "^5.32.2" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-image": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/rc-image/-/rc-image-7.2.0.tgz", + "integrity": "sha512-5Ug2hCVl6VcT0osR5XaZQ4zclTMEWPnbn3b4/TS/MR1QjRpEACLNFUzBGwr5mbAVhzvLWX5YZf4vO10xUA5IUA==", + "dependencies": { + "@babel/runtime": "^7.11.2", + "@rc-component/portal": "^1.0.2", + "classnames": "^2.2.6", + "rc-dialog": "~9.2.0", + "rc-motion": "^2.6.2", + "rc-util": "^5.34.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-input": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/rc-input/-/rc-input-1.1.1.tgz", + "integrity": "sha512-NTR1Z4em681L8/ewb2KR80RykSmN8I2mzqzJDCoUmTrV1BB9Hk5d7ha4TnfgdEPPL148N+603sW2LExSXk1IbA==", + "dependencies": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-util": "^5.18.1" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/rc-input-number": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/rc-input-number/-/rc-input-number-8.0.4.tgz", + "integrity": "sha512-TP+G5b7mZtbwXJ/YEZXF/OgbEZ6iqD4+RSuxZJ8VGKGXDcdt0FKIvpFoNQr/knspdFC4OxA0OfsWfFWfN4XSyA==", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/mini-decimal": "^1.0.1", + "classnames": "^2.2.5", + "rc-input": "~1.1.0", + "rc-util": "^5.28.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-mentions": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/rc-mentions/-/rc-mentions-2.7.0.tgz", + "integrity": "sha512-tn0x79cpnVYP+MA+jyBqalmEni9Ct7xHuA9QHIf5vwd25FU+hngGZ8n6Dfua7XCr4LhkZYjfD/rZTGrvY2C1Xg==", + "dependencies": { + "@babel/runtime": "^7.22.5", + "@rc-component/trigger": "^1.5.0", + "classnames": "^2.2.6", + "rc-input": "~1.1.0", + "rc-menu": "~9.12.0", + "rc-textarea": "~1.3.0", + "rc-util": "^5.34.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-menu": { + "version": "9.12.0", + "resolved": "https://registry.npmjs.org/rc-menu/-/rc-menu-9.12.0.tgz", + "integrity": "sha512-Apr/fRf5EcqWJ4nphHV6dTGZcLPaPzwY44q9hAtLJysY4rkC9Eg+ekj3uFx6opPWVruV2sJNWq/Po+HHtO48CA==", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/trigger": "^1.6.2", + "classnames": "2.x", + "rc-motion": "^2.4.3", + "rc-overflow": "^1.3.1", + "rc-util": "^5.27.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-motion": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/rc-motion/-/rc-motion-2.9.0.tgz", + "integrity": "sha512-XIU2+xLkdIr1/h6ohPZXyPBMvOmuyFZQ/T0xnawz+Rh+gh4FINcnZmMT5UTIj6hgI0VLDjTaPeRd+smJeSPqiQ==", + "dependencies": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-util": "^5.21.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-notification": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/rc-notification/-/rc-notification-5.1.1.tgz", + "integrity": "sha512-BPnded/WmWFE57ubqhVCgRSuedfQQNeSOYqdwppyr2B/Wt909gYFKyWAkFJVXuppAjsOGop05a93UaxjmUFdkg==", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-motion": "^2.6.0", + "rc-util": "^5.20.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-overflow": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/rc-overflow/-/rc-overflow-1.3.2.tgz", + "integrity": "sha512-nsUm78jkYAoPygDAcGZeC2VwIg/IBGSodtOY3pMof4W3M9qRJgqaDYm03ZayHlde3I6ipliAxbN0RUcGf5KOzw==", + "dependencies": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.37.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-pagination": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/rc-pagination/-/rc-pagination-3.6.1.tgz", + "integrity": "sha512-R/sUnKKXx1Nm4kZfUKS3YKa7yEPF1ZkVB/AynQaHt+nMER7h9wPTfliDJFdYo+RM/nk2JD4Yc5QpUq8fIQHeug==", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.1", + "rc-util": "^5.32.2" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-picker": { + "version": "3.14.3", + "resolved": "https://registry.npmjs.org/rc-picker/-/rc-picker-3.14.3.tgz", + "integrity": "sha512-41tVGgYnO1eXiVFTmhOkAyXqJSNTbNgmEGYxzsGzrhnH905yug9Z+6P0DYRaBC829xLxPA8GYpeWtGmm3OMQfw==", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/trigger": "^1.5.0", + "classnames": "^2.2.1", + "rc-util": "^5.30.0" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "date-fns": ">= 2.x", + "dayjs": ">= 1.x", + "luxon": ">= 3.x", + "moment": ">= 2.x", + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + }, + "peerDependenciesMeta": { + "date-fns": { + "optional": true + }, + "dayjs": { + "optional": true + }, + "luxon": { + "optional": true + }, + "moment": { + "optional": true + } + } + }, + "node_modules/rc-progress": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/rc-progress/-/rc-progress-3.5.1.tgz", + "integrity": "sha512-V6Amx6SbLRwPin/oD+k1vbPrO8+9Qf8zW1T8A7o83HdNafEVvAxPV5YsgtKFP+Ud5HghLj33zKOcEHrcrUGkfw==", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.6", + "rc-util": "^5.16.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-rate": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/rc-rate/-/rc-rate-2.12.0.tgz", + "integrity": "sha512-g092v5iZCdVzbjdn28FzvWebK2IutoVoiTeqoLTj9WM7SjA/gOJIw5/JFZMRyJYYVe1jLAU2UhAfstIpCNRozg==", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.5", + "rc-util": "^5.0.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-resize-observer": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/rc-resize-observer/-/rc-resize-observer-1.3.1.tgz", + "integrity": "sha512-iFUdt3NNhflbY3mwySv5CA1TC06zdJ+pfo0oc27xpf4PIOvfZwZGtD9Kz41wGYqC4SLio93RVAirSSpYlV/uYg==", + "dependencies": { + "@babel/runtime": "^7.20.7", + "classnames": "^2.2.1", + "rc-util": "^5.27.0", + "resize-observer-polyfill": "^1.5.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-segmented": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/rc-segmented/-/rc-segmented-2.2.2.tgz", + "integrity": "sha512-Mq52M96QdHMsNdE/042ibT5vkcGcD5jxKp7HgPC2SRofpia99P5fkfHy1pEaajLMF/kj0+2Lkq1UZRvqzo9mSA==", + "dependencies": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-motion": "^2.4.4", + "rc-util": "^5.17.0" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/rc-select": { + "version": "14.8.1", + "resolved": "https://registry.npmjs.org/rc-select/-/rc-select-14.8.1.tgz", + "integrity": "sha512-+MDaHteiKRL4iID9Osm8zAZTe+g7/t5CjIfJJ4QhPAvwGUaNCa2kvkMqiXfOfGevscVa+agha1Ov938MeAotfQ==", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/trigger": "^1.5.0", + "classnames": "2.x", + "rc-motion": "^2.0.1", + "rc-overflow": "^1.3.1", + "rc-util": "^5.16.1", + "rc-virtual-list": "^3.5.2" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, + "node_modules/rc-slider": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/rc-slider/-/rc-slider-10.2.1.tgz", + "integrity": "sha512-l355C/65iV4UFp7mXq5xBTNX2/tF2g74VWiTVlTpNp+6vjE/xaHHNiQq5Af+Uu28uUiqCuH/QXs5HfADL9KJ/A==", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.5", + "rc-util": "^5.27.0" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-steps": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/rc-steps/-/rc-steps-6.0.1.tgz", + "integrity": "sha512-lKHL+Sny0SeHkQKKDJlAjV5oZ8DwCdS2hFhAkIjuQt1/pB81M0cA0ErVFdHq9+jmPmFw1vJB2F5NBzFXLJxV+g==", + "dependencies": { + "@babel/runtime": "^7.16.7", + "classnames": "^2.2.3", + "rc-util": "^5.16.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-switch": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/rc-switch/-/rc-switch-4.1.0.tgz", + "integrity": "sha512-TI8ufP2Az9oEbvyCeVE4+90PDSljGyuwix3fV58p7HV2o4wBnVToEyomJRVyTaZeqNPAp+vqeo4Wnj5u0ZZQBg==", + "dependencies": { + "@babel/runtime": "^7.21.0", + "classnames": "^2.2.1", + "rc-util": "^5.30.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-table": { + "version": "7.34.4", + "resolved": "https://registry.npmjs.org/rc-table/-/rc-table-7.34.4.tgz", + "integrity": "sha512-os+i88Y2AO/6dNkOgJkKSHgXYaZZGnuOEEe+nyaq5IRgvAQNhLysUjXt2objtBeFDEZR8TqXrajwBNRUwunmdw==", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/context": "^1.4.0", + "classnames": "^2.2.5", + "rc-resize-observer": "^1.1.0", + "rc-util": "^5.36.0", + "rc-virtual-list": "^3.11.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-tabs": { + "version": "12.12.1", + "resolved": "https://registry.npmjs.org/rc-tabs/-/rc-tabs-12.12.1.tgz", + "integrity": "sha512-e10VBjEkECdPl4XZSs9to81SE+mgclBTM7J8/LMsFqmJoi05Tci91bRnmeeDtrcOCx2PuZdJv57XUlC4d8PEIw==", + "dependencies": { + "@babel/runtime": "^7.11.2", + "classnames": "2.x", + "rc-dropdown": "~4.1.0", + "rc-menu": "~9.12.0", + "rc-motion": "^2.6.2", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.34.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-textarea": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/rc-textarea/-/rc-textarea-1.3.4.tgz", + "integrity": "sha512-wn0YjTpvcVolcfXa0HtzL+jgV2QcwtfB29RwNAKj8hMgZOju1V24M3TfEDjABeQEAQbUGbjMbISREOX/YSVKhg==", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.1", + "rc-input": "~1.1.0", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.27.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-tooltip": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/rc-tooltip/-/rc-tooltip-6.0.1.tgz", + "integrity": "sha512-MdvPlsD1fDSxKp9+HjXrc/CxLmA/s11QYIh1R7aExxfodKP7CZA++DG1AjrW80F8IUdHYcR43HAm0Y2BYPelHA==", + "dependencies": { + "@babel/runtime": "^7.11.2", + "@rc-component/trigger": "^1.0.4", + "classnames": "^2.3.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-tree": { + "version": "5.7.12", + "resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-5.7.12.tgz", + "integrity": "sha512-LXA5nY2hG5koIAlHW5sgXgLpOMz+bFRbnZZ+cCg0tQs4Wv1AmY7EDi1SK7iFXhslYockbqUerQan82jljoaItg==", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-motion": "^2.0.1", + "rc-util": "^5.16.1", + "rc-virtual-list": "^3.5.1" + }, + "engines": { + "node": ">=10.x" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, + "node_modules/rc-tree-select": { + "version": "5.12.1", + "resolved": "https://registry.npmjs.org/rc-tree-select/-/rc-tree-select-5.12.1.tgz", + "integrity": "sha512-/IC6gRgRoUBCOwZASOiF3onp1484fb+Gke5zuxgsi3ViP+O2UTUByS1jTZzjNooidRgdwiQJksq1zVaVYw2TPg==", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-select": "~14.8.0", + "rc-tree": "~5.7.0", + "rc-util": "^5.16.1" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, + "node_modules/rc-upload": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/rc-upload/-/rc-upload-4.3.5.tgz", + "integrity": "sha512-EHlKJbhkgFSQHliTj9v/2K5aEuFwfUQgZARzD7AmAPOneZEPiCNF3n6PEWIuqz9h7oq6FuXgdR67sC5BWFxJbA==", + "dependencies": { + "@babel/runtime": "^7.18.3", + "classnames": "^2.2.5", + "rc-util": "^5.2.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-util": { + "version": "5.37.0", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.37.0.tgz", + "integrity": "sha512-cPMV8DzaHI1KDaS7XPRXAf4J7mtBqjvjikLpQieaeOO7+cEbqY2j7Kso/T0R0OiEZTNcLS/8Zl9YrlXiO9UbjQ==", + "dependencies": { + "@babel/runtime": "^7.18.3", + "react-is": "^16.12.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-util/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/rc-virtual-list": { + "version": "3.11.1", + "resolved": "https://registry.npmjs.org/rc-virtual-list/-/rc-virtual-list-3.11.1.tgz", + "integrity": "sha512-QKhksqvzKw63D8oVxAtnc82sWeyWZd135k67jVbf3cy42gz+r1Znt8ZCziveFWTqEYUVWnvjHTlEbc6lO0mkKg==", + "dependencies": { + "@babel/runtime": "^7.20.0", + "classnames": "^2.2.6", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.36.0" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, "node_modules/react": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", @@ -14717,6 +16088,11 @@ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" }, + "node_modules/resize-observer-polyfill": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", + "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==" + }, "node_modules/resolve": { "version": "1.22.6", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.6.tgz", @@ -14833,6 +16209,15 @@ "node": ">=0.10.0" } }, + "node_modules/rgbcolor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rgbcolor/-/rgbcolor-1.0.1.tgz", + "integrity": "sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw==", + "optional": true, + "engines": { + "node": ">= 0.8.15" + } + }, "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -15075,6 +16460,14 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/scroll-into-view-if-needed": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-3.1.0.tgz", + "integrity": "sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ==", + "dependencies": { + "compute-scroll-into-view": "^3.0.2" + } + }, "node_modules/select-hose": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", @@ -15254,6 +16647,12 @@ "node": ">= 0.8.0" } }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "optional": true + }, "node_modules/set-function-name": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", @@ -15317,6 +16716,37 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "optional": true + }, + "node_modules/simple-get": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz", + "integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==", + "optional": true, + "dependencies": { + "decompress-response": "^4.2.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, "node_modules/sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", @@ -15462,6 +16892,15 @@ "node": ">=8" } }, + "node_modules/stackblur-canvas": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/stackblur-canvas/-/stackblur-canvas-2.6.0.tgz", + "integrity": "sha512-8S1aIA+UoF6erJYnglGPug6MaHYGo1Ot7h5fuXx4fUPvcvQfcdw2o/ppCse63+eZf8PPidSu4v1JnmEVtEDnpg==", + "optional": true, + "engines": { + "node": ">=0.1.14" + } + }, "node_modules/stackframe": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", @@ -15587,6 +17026,11 @@ "safe-buffer": "~5.2.0" } }, + "node_modules/string-convert": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/string-convert/-/string-convert-0.2.1.tgz", + "integrity": "sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A==" + }, "node_modules/string-length": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", @@ -15783,6 +17227,11 @@ "postcss": "^8.2.15" } }, + "node_modules/stylis": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.0.tgz", + "integrity": "sha512-E87pIogpwUsUwXw7dNyU4QDjdgVMy52m+XEOPEKUn161cCzWjjhPSQhByfd1CcNvrOLnXQ6OnnZDwnJrz/Z4YQ==" + }, "node_modules/sucrase": { "version": "3.34.0", "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.34.0.tgz", @@ -15889,6 +17338,15 @@ "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==" }, + "node_modules/svg-pathdata": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/svg-pathdata/-/svg-pathdata-6.0.3.tgz", + "integrity": "sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==", + "optional": true, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/svgo": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz", @@ -16018,6 +17476,41 @@ "node": ">=6" } }, + "node_modules/tar": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", + "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", + "optional": true, + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "optional": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "optional": true + }, "node_modules/temp-dir": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", @@ -16137,6 +17630,14 @@ "node": ">=8" } }, + "node_modules/text-segmentation": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz", + "integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==", + "dependencies": { + "utrie": "^1.0.2" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -16166,6 +17667,14 @@ "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.2.tgz", "integrity": "sha512-WKexMoJj3vEuK0yFEapj8y64V0A6xcuPuK9Gt1d0R+dzCSJc0lHqQytAbSB4cDAK0dWh4T0E2ETkoLE2WZ41OQ==" }, + "node_modules/throttle-debounce": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-5.0.0.tgz", + "integrity": "sha512-2iQTSgkkc1Zyk0MeVrt/3BvuOXYPl/R8Z0U2xxo9rjwNciaHDG3R+Lm6dh4EeUci49DanvBnuqI6jshoQQRGEg==", + "engines": { + "node": ">=12.22" + } + }, "node_modules/thunky": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", @@ -16195,6 +17704,11 @@ "node": ">=8.0" } }, + "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/toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", @@ -16597,6 +18111,14 @@ "node": ">= 0.4.0" } }, + "node_modules/utrie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz", + "integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==", + "dependencies": { + "base64-arraybuffer": "^1.0.2" + } + }, "node_modules/uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", @@ -17143,6 +18665,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "optional": true, + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", diff --git a/package.json b/package.json index a439095..0f64599 100644 --- a/package.json +++ b/package.json @@ -3,13 +3,19 @@ "version": "0.1.0", "private": true, "dependencies": { + "@ant-design/icons": "^5.2.6", "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", "@types/jest": "^27.5.2", - "@types/node": "^16.18.54", - "@types/react": "^18.2.22", + "@types/node": "^16.18.48", + "@types/react": "^18.2.21", "@types/react-dom": "^18.2.7", + "antd": "^5.8.6", + "html2canvas": "^1.4.1", + "jspdf": "^2.5.1", + "pdf-lib": "^1.17.1", + "pdfjs-dist": "^3.10.174", "react": "^18.2.0", "react-dom": "^18.2.0", "react-scripts": "5.0.1", diff --git a/public/test.pdf b/public/test.pdf new file mode 100644 index 0000000..f94696d Binary files /dev/null and b/public/test.pdf differ diff --git a/public/test2.pdf b/public/test2.pdf new file mode 100755 index 0000000..f7c782b Binary files /dev/null and b/public/test2.pdf differ diff --git a/public/test3.pdf b/public/test3.pdf new file mode 100644 index 0000000..6aa6210 Binary files /dev/null and b/public/test3.pdf differ diff --git a/public/test4.pdf b/public/test4.pdf new file mode 100755 index 0000000..bbfa0c4 Binary files /dev/null and b/public/test4.pdf differ diff --git a/src/App.tsx b/src/App.tsx index a53698a..d826115 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,26 +1,23 @@ -import React from 'react'; -import logo from './logo.svg'; +import React, {useState} from 'react'; import './App.css'; +import {PDFViewer} from "./PDFViewer/PDFViewer"; +import DrawingCanvas from "./DrawingCanvas"; function App() { - return ( -
-
- logo -

- Edit src/App.tsx and save to reload. -

- - Learn React - -
-
- ); +/* + return ( + + ); +*/ + + +return ( + +); + + + + } export default App; diff --git a/src/DrawingCanvas.tsx b/src/DrawingCanvas.tsx new file mode 100644 index 0000000..caef3cb --- /dev/null +++ b/src/DrawingCanvas.tsx @@ -0,0 +1,271 @@ +import React, { useRef, useState } from 'react'; + +type Point = { + x: number; + y: number; +}; + +type Drawing = { + path: Path2D; + offset: Point; +}; + +const DrawingCanvas: React.FC = () => { + const canvasRef = useRef(null); + const [isDrawing, setIsDrawing] = useState(false); + const [drawings, setDrawings] = useState([]); + const [currentPath, setCurrentPath] = useState(null); + const [drawMode, setDrawMode] = useState(true); // true for drawing, false for selecting + const [selectMode, setSelectMode] = useState(false); + const [selectMode2, setSelectMode2] = useState(false); + const [selectionStart, setSelectionStart] = useState(null); + const [selectedArea, setSelectedArea] = useState<{ start: Point; end: Point } | null>(null); + const [selectedDrawings, setSelectedDrawings] = useState([]); + const [mousePos, setMousePos] = useState(); + const [dragStartPoint, setDragStartPoint] = useState(null); + + const handleTouchStart = (e: React.TouchEvent) => { + handleMouseDown({ + clientX: e.touches[0].clientX, + clientY: e.touches[0].clientY, + } as any); + }; + + const handleTouchMove = (e: React.TouchEvent) => { + handleMouseMove({ + clientX: e.touches[0].clientX, + clientY: e.touches[0].clientY, + } as any); + }; + + const handleTouchEnd = (e: React.TouchEvent) => { + handleMouseUp({ + clientX: e.changedTouches[0].clientX, + clientY: e.changedTouches[0].clientY, + } as any); + }; + + const getCanvasRelativePosition = (e: React.MouseEvent): Point => { + if (!canvasRef.current) return { x: 0, y: 0 }; + + const rect = canvasRef.current.getBoundingClientRect(); + return { + x: e.clientX - rect.left, + y: e.clientY - rect.top, + }; + }; + + const redraw = () => { + if (!canvasRef.current) return; + const ctx = canvasRef.current.getContext('2d'); + if (ctx) { + ctx.clearRect(0, 0, canvasRef.current.width, canvasRef.current.height); + ctx.save(); + drawings.forEach((drawing) => { + ctx.translate(drawing.offset.x, drawing.offset.y); + ctx.strokeStyle = 'black'; + ctx.lineWidth = 1; + ctx.stroke(drawing.path); + ctx.setTransform(1, 0, 0, 1, 0, 0); + }); + ctx.restore(); + + // 선택 영역이 있으면 항상 그려줍니다. + if (selectedArea) { + drawSelectionArea(selectedArea.start, selectedArea.end); + } + } + }; + + const handleMouseDown = (e: React.MouseEvent) => { + const point = getCanvasRelativePosition(e); + setMousePos(point); + + if (drawMode) { + setIsDrawing(true); + const newPath = new Path2D(); + newPath.moveTo(point.x, point.y); + setCurrentPath(newPath); + return; + } + + if (selectMode) { + if (selectedArea && isPointInsideRect(point, selectedArea)) { + setDragStartPoint(point); + return; + } else { + setSelectedDrawings([]); + setDragStartPoint(null); + setSelectedArea({ start: point, end: point } ); + setSelectionStart(point); + console.log("out"); + return; + } + } + }; + + const handleMouseMove = (e: React.MouseEvent) => { + const point = getCanvasRelativePosition(e); + + if (drawMode && isDrawing && currentPath) { + currentPath.lineTo(point.x, point.y); + const ctx = canvasRef.current?.getContext('2d'); + ctx?.stroke(currentPath); + return; + } + + if (selectMode && selectionStart && !dragStartPoint) { + const normalizedArea = normalizeSelectionArea(selectionStart, point); + setSelectedArea(normalizedArea); + redraw(); + drawSelectionArea(normalizedArea.start, normalizedArea.end); + return; + } + + if (selectedDrawings.length && mousePos && dragStartPoint) { + const dx = point.x - mousePos.x; + const dy = point.y - mousePos.y; + const newDrawings = [...drawings]; + + for (let index of selectedDrawings) { + newDrawings[index].offset.x += dx; + newDrawings[index].offset.y += dy; + } + + if (selectedArea) { + selectedArea.start.x += dx; + selectedArea.start.y += dy; + selectedArea.end.x += dx; + selectedArea.end.y += dy; + } + + setDrawings(newDrawings); + setMousePos(point); + redraw(); + if (selectedArea) { + drawSelectionArea(selectedArea.start, selectedArea.end); + } + return; + } + }; + + const isPointInsideRect = (point: Point, rect: { start: Point; end: Point }): boolean => { + return ( + point.x >= rect.start.x && + point.x <= rect.end.x && + point.y >= rect.start.y && + point.y <= rect.end.y + ); + }; + + const handleMouseUp = (e: React.MouseEvent) => { + if (drawMode) { + setIsDrawing(false); + if (currentPath) { + setDrawings([...drawings, { path: currentPath, offset: { x: 0, y: 0 } }]); + setCurrentPath(null); + } + return; + } + + if (selectMode && selectionStart) { + if (selectedArea) { + const normalizedArea = selectedArea; + const selected = drawings.map((drawing, index) => + isDrawingInsideSelection(drawing, normalizedArea) ? index : -1 + ).filter(index => index !== -1); + + setSelectedDrawings(selected); + redraw(); + + if (selected.length === 0) { + setSelectedArea(null); + } + } + setSelectionStart(null); + setDragStartPoint(null); + return; + } + + setDragStartPoint(null); + }; + + const isDrawingInsideSelection = (drawing: Drawing, selection: { start: Point; end: Point }): boolean => { + const ctx = canvasRef.current?.getContext('2d'); + if (!ctx) return false; + + const { start, end } = selection; + for (let x = start.x; x <= end.x; x += 5) { + for (let y = start.y; y <= end.y; y += 5) { + if (ctx.isPointInPath(drawing.path, x - drawing.offset.x, y - drawing.offset.y)) { + return true; + } + } + } + return false; + }; + + const normalizeSelectionArea = (start: Point, end: Point): { start: Point; end: Point } => { + return { + start: { + x: Math.min(start.x, end.x), + y: Math.min(start.y, end.y) + }, + end: { + x: Math.max(start.x, end.x), + y: Math.max(start.y, end.y) + } + }; + }; + + const drawSelectionArea = (start: Point, end: Point) => { + if (!canvasRef.current) return; + const ctx = canvasRef.current.getContext('2d'); + if (ctx) { + ctx.setLineDash([5, 5]); + ctx.strokeStyle = 'blue'; + ctx.strokeRect(start.x, start.y, end.x - start.x, end.y - start.y); + ctx.setLineDash([]); + } + }; + + + return ( +
+ + + +
+ +
+ ); +}; + +export default DrawingCanvas; diff --git a/src/PDFViewer/PDFViewer.css b/src/PDFViewer/PDFViewer.css new file mode 100644 index 0000000..816d542 --- /dev/null +++ b/src/PDFViewer/PDFViewer.css @@ -0,0 +1,119 @@ +.textLayer +{ + position: absolute; + text-align: initial; + inset: 0; + overflow: hidden; + color: rgba(255,255, 0, 1.0); + line-height: 1; + -webkit-text-size-adjust: none; + -moz-text-size-adjust: none; + text-size-adjust: none; + forced-color-adjust: none; + transform-origin: 0 0; + z-index: 99; +} +.textLayer span +{ + position: absolute; + +} + +.pageLayer +{ + position: relative; + direction: ltr; + margin: var(--page-margin); + overflow: visible; + border: var(--page-border); + background-clip: content-box; + background-color: rgba(255, 255, 255, 1); + padding-bottom: 17px; + +} + +.pdfViewer +{ + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + text-align: center; + padding-top: 17px; +} + +.pdfViewer .canvasWrapper +{ + position: relative; + overflow: hidden; + width: 100%; + height: 100%; + z-index: 1; + justify-content: center; + box-shadow: 5px 5px 15px 5px #888888; +} + +.loading +{ + width: 100px; + height: 100px; +} + +.drawLayer +{ + position: absolute; + width: 100%; + height: 100%; + overflow: hidden; + z-index: 2; + background-color:transparent; +} + +.waterMarkLayer +{ + background-color:transparent; +} + +.pdfViewer .pageLayer :is(span, br) { + color: transparent; + position: absolute; + white-space: pre; + cursor: text; + transform-origin: 0% 0%; +} + +.loading_canvasWrapper { + position: relative; + display: flex; + justify-content: center; + align-items: center; + text-align: center; + width: 100%; + box-shadow: 5px 5px 15px 5px #888888; +} + +.loading { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + display: flex; + justify-content: center; + align-items: center; + width: 100%; + height: 100%; + background-color: rgba(255, 255, 255, 0.8); /* semi-transparent white background */ +} + +.loading img { + max-width: 100%; + max-height: 100%; +} + +#printFrame +{ + width: 0px; + height: 0px; + display: none; +} diff --git a/src/PDFViewer/PDFViewer.tsx b/src/PDFViewer/PDFViewer.tsx new file mode 100644 index 0000000..b1922a9 --- /dev/null +++ b/src/PDFViewer/PDFViewer.tsx @@ -0,0 +1,1242 @@ +import React, {useEffect, useRef, useState} from "react"; +import { + getDocument, + GlobalWorkerOptions, + PageViewport, + PDFDocumentProxy, + PDFPageProxy, + renderTextLayer +} from "pdfjs-dist"; +import "./PDFViewer.css" +import {Button, Dropdown, Input, MenuProps, Modal, Progress, Space, Tooltip} from "antd"; +import { + CaretLeftOutlined, + CaretRightOutlined, DownloadOutlined, FullscreenOutlined, + PercentageOutlined, PrinterOutlined, + ZoomInOutlined, + ZoomOutOutlined +} from "@ant-design/icons"; +import html2canvas from "html2canvas"; +import {PDFDocument, PDFPage} from "pdf-lib"; +import {PasswordException} from "pdfjs-dist/types/src/shared/util"; +import { jsPDF } from "jspdf"; + +const PdfjsVersion:string = "3.11.174"; +GlobalWorkerOptions.workerSrc = `https://unpkg.com/pdfjs-dist@${PdfjsVersion}/build/pdf.worker.min.js`; + +interface PdfViewerProps { + fileUrl: string; + fileName?:string; + downloadFileUrl?:string; + scale?:number; + renderText?:boolean; + waterMarkText?:string; +} + +async function loadPage(pdf:PDFDocumentProxy, pageNum:number, scale:number, rotate:number, container:HTMLDivElement, isRenderText:boolean, waterMarkText:string|undefined) +{ + const pageLayer = document.createElement("div"); + const canvas = document.createElement("canvas"); + const cavasLayer = document.createElement("div"); + const loadingLayer = document.createElement("div"); + const drawLayer = document.createElement("div"); + + const loadingImage = document.createElement("img"); + + loadingImage.setAttribute("src", "pdf-loading.svg"); + const textLayer = isRenderText ? document.createElement("div") : null; + if (textLayer) + { + pageLayer.appendChild(textLayer); + textLayer.className = "textLayer"; + } + pageLayer.className = "pageLayer"; + cavasLayer.className = "loading_canvasWrapper"; + + pageLayer.setAttribute("data-pageIdx", `${pageNum}`); + pageLayer.setAttribute("id", `page-${pageNum}`); + pageLayer.setAttribute("data-pageLoad", `false`); + + drawLayer.className = "drawLayer"; + drawLayer.setAttribute("data-pageIdx", `${pageNum}`); + drawLayer.setAttribute("id", `draw-${pageNum}`); + + if (waterMarkText) + { + const waterMarkLayer = document.createElement("div"); + waterMarkLayer.className = "waterMarkLayer"; + drawLayer.appendChild(waterMarkLayer); + } + + pageLayer.appendChild(drawLayer); + + container.appendChild(pageLayer); + cavasLayer.appendChild(canvas); + pageLayer.appendChild(cavasLayer); + loadingLayer.appendChild(loadingImage); + loadingLayer.className = "loading"; + cavasLayer.appendChild(loadingLayer); + + const page = await pdf.getPage(pageNum); + const viewport = page.getViewport({ + scale: scale + ,rotation:rotate|0 + }) + + canvas.width = viewport.width; + canvas.height = viewport.height; + + const context = canvas.getContext("2d"); + if (!context) return; + + + if(pageNum <= 3) + { + const isLoad = pageLayer.getAttribute("data-pageLoad") === "true" ? true : false; + if(!isLoad) + { + pageLayer.setAttribute("data-pageLoad", `true`); + await renderPage(page, context, viewport, textLayer).finally(() => { + cavasLayer.className = "canvasWrapper"; + if (loadingImage && cavasLayer.contains(loadingLayer)) { + cavasLayer.removeChild(loadingLayer); + } + }); + } + } +} + + + +async function renderPage(page:PDFPageProxy, context:CanvasRenderingContext2D, viewport:PageViewport, textLayer:HTMLDivElement|null) +{ + const renderContext = { + canvasContext: context, + viewport: viewport, + }; + + await page.render(renderContext).promise; + + if (textLayer) + { + page.getTextContent().then(textContent => { + const txtLayer = renderTextLayer( + { + textContentSource: textContent, + container: textLayer, + viewport: viewport, + isOffscreenCanvasSupported:true, + + } + ).promise; + }).finally(()=>{ + const parent = textLayer.parentElement; + if (parent != null) + { + const drawLayer = parent.querySelector(".drawLayer"); + const pageStyle = textLayer.getAttribute("style"); + if (drawLayer && pageStyle) + { + drawLayer.setAttribute("style", pageStyle); + } + + } + + }); + } + +} + +export const PDFViewer = (props: PdfViewerProps) => { + const { fileUrl , scale, renderText, downloadFileUrl + , waterMarkText, fileName} = props; + + const [modalVisible, setModalVisible] = useState(false); + const downloadUrl = downloadFileUrl || fileUrl; + const fileTitle= fileName||fileUrl; + const [threshold, setThreshold] = useState(0.7); + const [scaleValue, setScaleValue] = useState(scale || 1.5); + const [currentPage, setCurrentPage] = useState(1); + const [totalPage, setTotalPage] = useState(0); + + const rightClickCountRef = useRef(0); + const leftClickCountRef = useRef(0); + + const [observer, setObserver] = useState(); + + const [calcScaleValue, setCalcScaleValue] = useState(scaleValue); + const timerRef = useRef(null); + const timerClickRef = useRef(null); + + const [pdfDocument, setPdfDocument] = useState(); + + + const [modalTitle, setModalTitle] = useState(); + + const [progressVisible, setProgressVisible] = useState(false); + const [procPercent, setProcPercent] = useState(0); + + const [passwordVisible, setPasswordVisible] = useState(false); + const [pdfPassword, setPdfPassword] = useState(""); + const [pdfErrorMsg, setPdfErrorMsg] = useState(""); + + + const waterMarkCanvasRef = useRef(null); + + const isRenderText = renderText||false; + + const containerRef = useRef(null); + + const items:MenuProps['items'] = [ + { + key: 'ACTUAL_SIZE', + label: '실제크기', + }, + { + key: 'WIDTH_FIT', + label: '가로에 맞추기', + }, + { + key: 'HEIGHT_FIT', + label: '세로에 맞추기', + }, + { + key: '0.5', + label: '50%', + }, + { + key: '0.75', + label: '70%', + }, + { + key: '1.0', + label: '100%', + }, + { + key: '1.25', + label: '125%', + }, + { + key: '1.5', + label: '150%', + }, + { + key: '2.0', + label: '200%', + }, + { + key: '3.0', + label: '300%', + }, + { + key: '4.0', + label: '400%', + }, + ]; + + + const handleRatioMenuClick: MenuProps['onClick'] = (e) => { + const key:string = e.key; + switch (key) + { + case 'ACTUAL_SIZE' : + ZoomCtrl(1.0); + break; + case 'WIDTH_FIT' : + ZoomCtrl(getWidthFitScale()); + break; + case 'HEIGHT_FIT' : + ZoomCtrl(getHeightFitScale()); + break; + case '0.5' : + ZoomCtrl(0.5); + break; + case '0.75' : + ZoomCtrl(0.75); + break; + case '1.0' : + ZoomCtrl(1.0); + break; + case '1.25' : + ZoomCtrl(1.25); + break; + case '1.5' : + ZoomCtrl(1.5); + break; + case '2.0' : + ZoomCtrl(2.0); + break; + case '3.0' : + ZoomCtrl(3.0); + break; + case '4.0' : + ZoomCtrl(4.0); + break; + default: + break; + } + }; + + function calcThreshold(stdScaleValue:number) :number + { + if (0.5 >= stdScaleValue ) + { + return 1.0; + } + else if (0.75 >= stdScaleValue && 1.0 < stdScaleValue) + { + return 0.9; + } + else if (1.0 >= stdScaleValue && 1.25 < stdScaleValue) + { + return 0.8; + } + else if (1.25 >= stdScaleValue && 1.5 < stdScaleValue) + { + return 0.7; + } + else if (1.5 >= stdScaleValue && 1.75 < stdScaleValue) + { + return 0.6; + } + else if (1.75 >= stdScaleValue && 2.0 < stdScaleValue) + { + return 0.5; + } + else if (2.0 >= stdScaleValue && 3.0 < stdScaleValue) + { + return 0.4; + } + else if (4.0 >= stdScaleValue ) + { + return 0.3; + } + else + { + return 0.65 + } + } + + const raioMenuProps = { + items, + onClick: handleRatioMenuClick, + }; + + function enterFullScreen(elementId: string): void { + const element = document.getElementById(elementId) as HTMLElement & { + requestFullscreen?: () => Promise; + webkitRequestFullscreen?: () => Promise; + mozRequestFullScreen?: () => Promise; + msRequestFullscreen?: () => Promise; + }; + + if (!element) { + console.error(`Element with id ${elementId} not found.`); + return; + } + + const onFullScreenEntered = () => { + // 여기에 원하는 로직을 추가하세요. + console.log("전체 화면 모드에 진입하였습니다."); + ZoomCtrl(getWindowHeightFitScale()); + // 이벤트 리스너 제거 + document.removeEventListener('fullscreenchange', onFullScreenEntered); + }; + + // 이벤트 리스너 추가 + document.addEventListener('fullscreenchange', onFullScreenEntered); + + if (element.requestFullscreen) { + element.requestFullscreen(); + } else if (element.webkitRequestFullscreen) { + element.webkitRequestFullscreen(); + } else if (element.mozRequestFullScreen) { + element.mozRequestFullScreen(); + } else if (element.msRequestFullscreen) { + element.msRequestFullscreen(); + } else { + console.error("Fullscreen API is not supported."); + } + } + + + function scrollToDiv(pageNum:number) { + const divId = `page-${pageNum}`; + const element = document.getElementById(divId); + if (element) { + element.scrollIntoView({ behavior: 'smooth' }); + } else { + console.error(`Element with id ${divId} not found.`); + } + } + + function movePage(pageNum:number) + { + if(pageNum < 1) + { + pageNum = 1; + } + else if(pageNum > totalPage) + { + pageNum = totalPage; + } + scrollToDiv(pageNum); + return pageNum; + } + + function getWidthFitScale() + { + const parentObj = document.getElementById("pdf_content"); + if(parentObj) + { + const parentWidth = parentObj.offsetWidth; + console.log("부모 : " + parentWidth); + const pageLayer = parentObj.querySelector(`.pageLayer[data-pageidx="${currentPage}"]`); + if (pageLayer) { + const canvas = pageLayer.querySelector('canvas'); + if (canvas) + { + console.log("자식 : " + (canvas.width / calcScaleValue) ); + return parentWidth / ((canvas.width / calcScaleValue) + 15) ; + } + } + } + return 0; + } + + function getHeightFitScale() + { + const parentObj = document.getElementById("pdf_content"); + if(parentObj) + { + const parentHeight = parentObj.offsetHeight; + const pageLayer = parentObj.querySelector(`.pageLayer[data-pageidx="${currentPage}"]`); + if (pageLayer) { + const canvas = pageLayer.querySelector('canvas'); + if (canvas) + { + return parentHeight / ((canvas.height / calcScaleValue) + 30); + } + } + } + return 0; + } + + function getWindowHeightFitScale() + { + const parentObj = document.getElementById("pdf_content"); + if(parentObj) + { + const pageLayer = parentObj.querySelector(`.pageLayer[data-pageidx="${currentPage}"]`); + if (pageLayer) { + const canvas = pageLayer.querySelector('canvas'); + if (canvas) + { + return window.screen.height / ((canvas.height / calcScaleValue) + 15); + } + } + } + return 0; + } + + function zoomIn(stdValue:number) + { + const maxZoom:number = 4.0; + let calsZoom:number = stdValue + 0.25; + + if (calsZoom > maxZoom) + { + calsZoom = maxZoom; + } + return calsZoom; + } + + function zoomOut(stdValue:number) + { + + const minZoom:number = 0.5; + let calsZoom:number = stdValue - 0.25; + if (calsZoom < minZoom) + { + calsZoom = minZoom; + } + return calsZoom; + + } + + function drawLoadingPage(pageLayer:Element, isLoadingIcon:boolean) + { + pageLayer.setAttribute("data-pageLoad", "false"); + const cavasLayer = pageLayer.querySelector('.canvasWrapper') as HTMLDivElement; + if (cavasLayer) + { + cavasLayer.className = "loading_canvasWrapper"; + + if (isLoadingIcon) + { + const loadingLayer = document.createElement("div"); + const loadingImage = document.createElement("img"); + loadingImage.setAttribute("src", "pdf-loading.svg"); + + loadingLayer.appendChild(loadingImage); + loadingLayer.className = "loading"; + cavasLayer.appendChild(loadingLayer); + } + } + } + + function drawLayerShowNHide(isShow:boolean) + { + if (containerRef.current) + { + const drawLayers = containerRef.current.querySelectorAll(".drawLayer"); + drawLayers.forEach((layer) => { + if (!isShow) + { + (layer as HTMLElement).style.display = 'none'; + } + else + { + (layer as HTMLElement).style.display = 'block'; + } + }); + } + + } + + const ZoomCtrl = (calcZoom:number) => { + + if(calcZoom === calcScaleValue) + { + return; + } + if (observer) + { + observer.disconnect(); + } + + console.log("cal : " + calcZoom); + console.log("calsc : " + calcScaleValue); + console.log("cur : " + currentPage); + + + const targetPageIdx = currentPage; + const startIdx = Math.max(1, targetPageIdx - 3); + const endIdx = targetPageIdx + 3; + + if (containerRef.current) + { + drawLayerShowNHide(false); + setCalcScaleValue(calcZoom); + + const pdfViewer = containerRef.current; + + for (let i = 1; i <= totalPage; i++) { + const pageLayer = pdfViewer.querySelector(`.pageLayer[data-pageidx="${i}"]`); + if (pageLayer) { + const canvas = pageLayer.querySelector('canvas'); + if (canvas) { + if ( i >= startIdx && i <= endIdx) + { + const tempCanvas = document.createElement('canvas'); + const tempCtx = tempCanvas.getContext('2d'); + if (!tempCtx) { + console.error("Failed to get 2d context from tempCanvas."); + return; + } + tempCanvas.width = canvas.width; + tempCanvas.height = canvas.height; + tempCtx.drawImage(canvas, 0, 0); + canvas.width = (canvas.width / calcScaleValue) * calcZoom; + canvas.height = (canvas.height / calcScaleValue) * calcZoom; + + const ctx = canvas.getContext('2d')!; + ctx.drawImage(tempCanvas, 0, 0, tempCanvas.width, tempCanvas.height, 0, 0, canvas.width, canvas.height); + } + else + { + drawLoadingPage(pageLayer, true); + canvas.width = (canvas.width / calcScaleValue) * calcZoom; + canvas.height = (canvas.height / calcScaleValue) * calcZoom; + } + + console.log("can : " + canvas.width); + } + } + } + } + + if (timerRef.current) { + clearTimeout(timerRef.current); + } + + timerRef.current = setTimeout(() => { + if (containerRef.current) { + setCalcScaleValue(calcZoom); + + const pdfViewer = containerRef.current; + + for (let i = startIdx; i <= endIdx; i++) { + const pageLayer = pdfViewer.querySelector(`.pageLayer[data-pageidx="${i}"]`); + if (pageLayer) { + drawLoadingPage(pageLayer, false); + } + } + } + + const container = containerRef.current; + container!.style.setProperty('--scale-factor', `${calcZoom}`); // 원하는 값으로 설정 + + setScaleValue(calcZoom); + setThreshold(calcThreshold(calcZoom)); + + console.log("타임 : " + calcZoom); + }, 500); + } + + const observerOptions = { + root: null, + rootMargin: '0px 0px 30px 0px', + threshold: threshold, + } + + function createObserver(pdfDocument:PDFDocumentProxy) + { + if (observer) + { + observer.disconnect(); + } + + const newObserver = new IntersectionObserver((entries, observer) => { + entries.forEach(async entry => { + // 관찰 대상이 viewport 안에 들어온 경우 image 로드 + if (entry.isIntersecting) { + const pageLayer = entry.target; + const pageIdx: number = Number(pageLayer.getAttribute("data-pageidx")); + setCurrentPage(pageIdx); + await drawPdfPage(pdfDocument, pageLayer); + } + }) + }, observerOptions); + + setObserver(newObserver); + + const pdfPages = document.querySelectorAll('.pageLayer'); + pdfPages.forEach((pdfPage) => { + newObserver.observe(pdfPage); + }) + + return () => { + newObserver.disconnect(); + }; + } + + async function drawPdfPage(pdfDocument:PDFDocumentProxy, pageLayer: Element) { + + console.log(scaleValue); + if (pdfDocument) { + const pageIdx: number = Number(pageLayer.getAttribute("data-pageidx")); + const cavasLayer = pageLayer.querySelector('.loading_canvasWrapper') as HTMLDivElement; + const isLoad = pageLayer.getAttribute("data-pageLoad") === "true" ? true : false; + + if (cavasLayer && !isLoad) { + pageLayer.setAttribute("data-pageLoad", `true`); + const page = await pdfDocument.getPage(pageIdx); + const textLayer = pageLayer.querySelector('.textLayer') as HTMLDivElement; + const canvas = pageLayer.querySelector('canvas'); + const loadingLayer = pageLayer.querySelector('.loading'); + const context = canvas!.getContext("2d"); + if (!context) return; + + const viewport = page.getViewport({ + scale: scaleValue + , rotation: 0 + }) + + await renderPage(page, context, viewport, textLayer).finally(() => { + cavasLayer.className = "canvasWrapper"; + if (loadingLayer && cavasLayer.contains(loadingLayer)) { + cavasLayer.removeChild(loadingLayer); + } + }); + } + } + + } + + async function runZoom() { + if (containerRef.current && pdfDocument) { + + const pdfViewer = containerRef.current; + const targetPageIdx = currentPage; + const startIdx = Math.max(1, targetPageIdx - 3); + const endIdx = targetPageIdx + 3; + for (let i = startIdx; i <= endIdx; i++) { + const pageLayer = pdfViewer.querySelector(`.pageLayer[data-pageidx="${i}"]`); + if (pageLayer) + { + await drawPdfPage(pdfDocument, pageLayer); + } + + } + + createObserver(pdfDocument); + } + } + + async function loadPdfFromUrl() { + const response = await fetch(fileUrl); + if (!response.ok) { + throw new Error(`Failed to fetch PDF from ${fileUrl}. Status: ${response.statusText}`); + } + const pdfBytes = new Uint8Array(await response.arrayBuffer()); + return pdfBytes; + } + + async function getPdfBlob() { + const warterMark = document.querySelector("#draw-1"); + if (warterMark != null && pdfDocument) { + const waterMarkCanvas = await html2canvas(warterMark as HTMLElement, { + backgroundColor: null, + }); + //패스워드가 있으면 이미지를 만들고 없으면 기존거에 워터마크만 추가한다. + const isSecurity = pdfPassword.length > 0; + let pdfDoc:PDFDocument = isSecurity ? await PDFDocument.create() : await PDFDocument.load(await pdfDocument.getData()); + const waterMarkData = waterMarkCanvas.toDataURL("image/png"); + const waterMarkImage = pdfDoc.embedPng(waterMarkData); + + for (let i=1; i<=totalPage; i++) + { + setProcPercent(calculateProgress(i, totalPage, 100)); + let pdfPage:PDFPage|null = null; + if (isSecurity) + { + const page = await pdfDocument.getPage(i); + const viewport = page.getViewport({ scale: 2.0 }); + + const canvas = document.createElement('canvas'); + const context = canvas.getContext('2d'); + canvas.height = viewport.height; + canvas.width = viewport.width; + + if (context && viewport) { + const renderContext = { + canvasContext: context, + viewport: viewport + }; + await page.render(renderContext).promise; + pdfPage = pdfDoc.addPage([viewport.width, viewport.height]); + const pdfPageIamge = pdfDoc.embedJpg(canvas.toDataURL("image/jpeg")); + pdfPage.drawImage(await pdfPageIamge, { + x: 0, + y: 0, + width: viewport.width, + height: viewport.height + }); + } + + } + else + { + pdfPage = pdfDoc.getPages()[i-1]; + } + + //워터마크 삽입 + if (pdfPage && waterMarkImage) + { + pdfPage.drawImage(await waterMarkImage, { + x: 0, + y: 0, + width: pdfPage.getWidth(), + height: pdfPage.getHeight(), + }); + } + } + + const modifiedPdfBytes = await pdfDoc.save(); + + setProcPercent(100); + const blob = new Blob([modifiedPdfBytes], {type: 'application/pdf'}); + return blob; + + } + + return null; + } + + + const downloadPdfDocument = async () => { + + const blob = await getPdfBlob(); + if (blob) + { + const pdfUrl = URL.createObjectURL(blob); + const link = document.createElement('a'); + link.href = pdfUrl; + link.download = 'overlayed.pdf'; + link.click(); + + URL.revokeObjectURL(pdfUrl); + + hideModal(); + + } + }; + + const printPdfDocument = async () => { + + const blob = await getPdfBlob(); + if (blob) + { + const pdfUrl = URL.createObjectURL(blob); + const printIframe = document.getElementById('printFrame') as HTMLIFrameElement; + + printIframe.src = pdfUrl; + const printWindow = printIframe.contentWindow; + if (printWindow) { + printIframe.onload = function () { + setTimeout(function () { + printWindow.print(); + hideModal(); + URL.revokeObjectURL(pdfUrl); + }, 500); + }; + } + } + }; + + function calculateProgress(currentPage:number, totalPage:number, totalPercent:number) { + const progress = (currentPage / totalPage) * totalPercent; + console.log(progress); + return Math.min(Math.round(progress), totalPercent); // 진행률이 100%를 초과하지 않도록 합니다. + } + + function showModal(revModalTitle:string, isProgress:boolean) + { + if (isProgress) + { + setProgressVisible(true); + } + setProcPercent(0); + setModalTitle(revModalTitle); + setModalVisible(true); + } + + function hideModal() + { + setPdfErrorMsg(""); + setModalVisible(false); + setModalTitle(""); + setProcPercent(0); + setProgressVisible(false); + setPasswordVisible(false); + } + + function PrevPage() + { + const movePageNum = currentPage-1; + setCurrentPage(movePage(movePageNum < 1 ? 1: movePageNum )); + } + + function NextPage() + { + const movePageNum = currentPage+1; + setCurrentPage(movePage(movePageNum > totalPage ? totalPage : movePageNum )); + } + + + const handleDoubleClick = (event:React.MouseEvent) => { + event.preventDefault(); + + leftClickCountRef.current += 1; + + if (leftClickCountRef.current === 1) { + timerClickRef.current = setTimeout(() => { + leftClickCountRef.current = 0; // 클릭 횟수 초기화 + }, 250); + } else if (leftClickCountRef.current === 2) { + if (timerClickRef.current) { + clearTimeout(timerClickRef.current); + } + + ZoomCtrl( zoomIn( calcScaleValue || scaleValue ) ); + leftClickCountRef.current = 0; // 클릭 횟수 초기화 + } + }; + + const handleRightClick = (event:React.MouseEvent) => { + event.preventDefault(); + + rightClickCountRef.current += 1; + + if (rightClickCountRef.current === 1) { + timerClickRef.current = setTimeout(() => { + rightClickCountRef.current = 0; // 클릭 횟수 초기화 + }, 250); + } else if (rightClickCountRef.current === 2) { + if (timerClickRef.current) { + clearTimeout(timerClickRef.current); + } + ZoomCtrl( zoomOut( calcScaleValue || scaleValue ) ); + rightClickCountRef.current = 0; // 클릭 횟수 초기화 + } + }; + + const handlePasswordSubmit = () => { + loadPdf(pdfPassword).then(r => { }); + + }; + + + + useEffect(() => { + if (waterMarkText && waterMarkCanvasRef.current) { + const canvas = waterMarkCanvasRef.current; + const ctx = canvas.getContext('2d'); + const fontSize = 70 * scaleValue; + const padding = fontSize; + if (ctx) { + + ctx.font = `${fontSize}px Arial`; + const textWidth = ctx.measureText(waterMarkText).width; + const textHeight = fontSize; // 이 값은 폰트 크기에 따라 조절하시길 바랍니다. + + canvas.width = textWidth + padding; + canvas.height = textHeight + padding * 2; + + ctx.font = `${fontSize}px Arial`; // 캔버스 크기가 변경되면 폰트 설정도 초기화되므로 다시 설정해야 합니다. + ctx.fillStyle = 'rgba(0, 0, 0, 0.10)'; + ctx.fillText(waterMarkText, 0, textHeight - 5); // y 좌표를 조절하여 텍스트가 캔버스 내에 잘 들어가도록 합니다. + + //setWaterMarkImgURl(canvas.toDataURL('image/png')); + const waterMarkImgURl = canvas.toDataURL('image/png'); + if(waterMarkImgURl) + { + const style = document.createElement('style'); + style.innerHTML = ` + .pdfViewer .waterMarkLayer::before { + content: ""; + position: absolute; + top: 0px; + left: 0px; + width: 200%; + height: 200%; + background-image: url(${waterMarkImgURl}); + background-repeat: repeat; + transform: rotate(-45deg); + background-color: transparent; + }`; + document.head.appendChild(style); + } + } + } + }, [waterMarkText, scaleValue]); + + + const loadPdf = async (password: string | null | undefined) => { + console.log("PDFViewer component rendered"); + + const container = containerRef.current; + + if (!container) return; + + // Clear the container's contents whenever fileUrl changes + container.innerHTML = ""; + + const loadOption: any = { + url: fileUrl, + cMapUrl: `https://unpkg.com/pdfjs-dist@${PdfjsVersion}/cmaps/`, + cMapPacked: true, + enableXfa: true, + }; + + if (password) { + loadOption.password = password; + } + + let isError = false; + + try { + const pdfDocumentProxy: PDFDocumentProxy = await getDocument(loadOption).promise; + + setPdfDocument(pdfDocumentProxy); + setTotalPage(pdfDocumentProxy.numPages); + + container.style.setProperty('--scale-factor', `${scaleValue}`); // 원하는 값으로 설정 + + for (let pageNum = 1; pageNum <= pdfDocumentProxy.numPages; pageNum++) { + await loadPage(pdfDocumentProxy, pageNum, scaleValue, 0, container, isRenderText, waterMarkText); + } + + createObserver(pdfDocumentProxy); + + } catch (error:any) { + isError = true + if (error.name === 'PasswordException' && !password) { + showModal("보안 PDF", false); + setPasswordVisible(true); + } + else if (error.name === 'PasswordException' && error.message === 'Incorrect Password' && password) { + + setPdfErrorMsg("PDF 암호가 잘못되었습니다."); + showModal("보안 PDF", false); + setPasswordVisible(true); + } + else { + console.error(error); + } + } + finally { + if (!isError && password) + hideModal(); + } + }; + + + useEffect(() => { + + setTotalPage(0); + setCurrentPage(1); + setPdfErrorMsg(""); + setPdfPassword(""); + + loadPdf(null); + + }, [fileUrl]); + + + + useEffect(() => { + runZoom().then().finally( () =>{ + drawLayerShowNHide(true); + }); + }, [ scaleValue ]); + + + useEffect(() => { + const handleKeyDown = (event:KeyboardEvent) => { + + switch (event.key) { + case 'PageUp': + PrevPage(); + console.log("up"); + event.preventDefault(); // 기본 동작 방지 + break; + case 'PageDown': + NextPage(); + console.log("down"); + event.preventDefault(); // 기본 동작 방지 + break; + case '+': + ZoomCtrl( zoomIn( calcScaleValue || scaleValue ) ); + break; + case '-': + ZoomCtrl( zoomOut( calcScaleValue || scaleValue ) ); + break; + default: + break; + } + }; + + + window.addEventListener('keydown', handleKeyDown); + + return () => { + window.removeEventListener('keydown', handleKeyDown); + }; + }, [currentPage, scaleValue, calcScaleValue, totalPage]); // currentPage가 변경될 때마다 이벤트 리스너 갱신 + + return ( + +
+ +
+
+
+
+ +