From 3acd9aba3a34e0a6de5ec738e0210b08a9bfc7e8 Mon Sep 17 00:00:00 2001 From: Artem Tyurin Date: Tue, 9 Jul 2024 11:38:24 +0200 Subject: [PATCH] Migrate to Biome, update packages --- .gitignore | 2 - .prettierignore | 6 - .prettierrc | 1 - .vscode/launch.json | 18 - .vscode/settings.json | 7 - .vscode/tasks.json | 36 -- biome.json | 27 ++ e2e/page.spec.ts | 2 +- example/src/App.tsx | 45 ++- example/src/Sidebar.tsx | 9 +- example/src/index.tsx | 7 +- example/vite.config.ts | 4 +- package-lock.json | 612 ++++++++++++++++++++---------- package.json | 30 +- src/components/Highlight.tsx | 3 +- src/components/HighlightLayer.tsx | 55 +-- src/components/MouseSelection.tsx | 41 +- src/components/PdfHighlighter.tsx | 135 ++++--- src/components/PdfLoader.tsx | 10 +- src/components/Popup.tsx | 5 +- src/components/Tip.tsx | 1 + src/components/TipContainer.tsx | 35 +- src/lib/coordinates.ts | 4 +- src/lib/get-area-as-png.ts | 6 +- src/lib/get-bounding-rect.ts | 8 +- src/lib/get-client-rects.ts | 2 +- src/lib/optimize-client-rects.ts | 12 +- src/lib/pdfjs-dom.ts | 53 +-- 28 files changed, 697 insertions(+), 479 deletions(-) delete mode 100644 .prettierignore delete mode 100644 .prettierrc delete mode 100644 .vscode/launch.json delete mode 100644 .vscode/settings.json delete mode 100644 .vscode/tasks.json create mode 100644 biome.json diff --git a/.gitignore b/.gitignore index 4142690c9..bbc713769 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,6 @@ node_modules .DS_Store dist -dist-ssr -dist-example *.local types /test-results/ diff --git a/.prettierignore b/.prettierignore deleted file mode 100644 index fb2c27165..000000000 --- a/.prettierignore +++ /dev/null @@ -1,6 +0,0 @@ -package.json -package-lock.json -dist -dist-example -node_modules -build \ No newline at end of file diff --git a/.prettierrc b/.prettierrc deleted file mode 100644 index 0967ef424..000000000 --- a/.prettierrc +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index e786ce4e4..000000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "type": "pwa-chrome", - "request": "launch", - "name": "Launch Chrome against localhost", - "url": "http://localhost:3000", - "webRoot": "${workspaceFolder}", - "preLaunchTask": "start-dev-server", - "postDebugTask": "terminate-tasks", - "timeout": 30000 - } - ] -} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 7de146e73..000000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "editor.formatOnSave": true, - "[typescript]": { - "editor.defaultFormatter": "esbenp.prettier-vscode" - }, - "files.eol": "\n" -} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json deleted file mode 100644 index f50cdae07..000000000 --- a/.vscode/tasks.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "version": "2.0.0", - "tasks": [ - { - "label": "start-dev-server", - "type": "npm", - "script": "start", - "isBackground": true, - "problemMatcher": { - "owner": "npm", - "background": { - "activeOnStart": true, - "beginsPattern": ".*", - "endsPattern": "ready in \\d+ms\\." - }, - "pattern": { - "regexp": "", - } - } - }, - { - "label": "terminate-tasks", - "command": "echo ${input:terminate}", - "type": "shell", - "problemMatcher": [] - } - ], - "inputs": [ - { - "id": "terminate", - "type": "command", - "command": "workbench.action.tasks.terminate", - "args": "terminateAll" - } - ] -} \ No newline at end of file diff --git a/biome.json b/biome.json new file mode 100644 index 000000000..54a85ca9a --- /dev/null +++ b/biome.json @@ -0,0 +1,27 @@ +{ + "$schema": "https://biomejs.dev/schemas/1.8.3/schema.json", + "formatter": { + "enabled": true, + "formatWithErrors": false, + "indentStyle": "space", + "indentWidth": 2, + "lineEnding": "lf", + "lineWidth": 80, + "attributePosition": "auto" + }, + "organizeImports": { "enabled": true }, + "linter": { + "enabled": true, + "rules": { + "recommended": true, + "a11y": { + "useKeyWithClickEvents": "off", + "useKeyWithMouseEvents": "off" + } + } + }, + "vcs": { + "enabled": true, + "clientKind": "git" + } +} diff --git a/e2e/page.spec.ts b/e2e/page.spec.ts index 0a40ce23c..0e7cf3695 100644 --- a/e2e/page.spec.ts +++ b/e2e/page.spec.ts @@ -1,4 +1,4 @@ -import { test, expect, Page } from "@playwright/test"; +import { type Page, expect, test } from "@playwright/test"; test.beforeEach(async ({ page }) => { await page.goto("http://localhost:3003/react-pdf-highlighter/"); diff --git a/example/src/App.tsx b/example/src/App.tsx index 7bcc0652d..7d983276f 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -1,19 +1,24 @@ import React, { Component } from "react"; import { - PdfLoader, - PdfHighlighter, - Tip, + AreaHighlight, Highlight, + PdfHighlighter, + PdfLoader, Popup, - AreaHighlight, + Tip, } from "./react-pdf-highlighter"; -import type { IHighlight, NewHighlight } from "./react-pdf-highlighter"; +import type { + Content, + IHighlight, + NewHighlight, + ScaledPosition, +} from "./react-pdf-highlighter"; -import { testHighlights as _testHighlights } from "./test-highlights"; -import { Spinner } from "./Spinner"; import { Sidebar } from "./Sidebar"; +import { Spinner } from "./Spinner"; +import { testHighlights as _testHighlights } from "./test-highlights"; import "./style/App.css"; @@ -51,6 +56,7 @@ const searchParams = new URLSearchParams(document.location.search); const initialUrl = searchParams.get("url") || PRIMARY_PDF_URL; +// biome-ignore lint/complexity/noBannedTypes: Not sure what to use instead of {} class App extends Component<{}, State> { state = { url: initialUrl, @@ -75,7 +81,7 @@ class App extends Component<{}, State> { }); }; - scrollViewerTo = (highlight: any) => {}; + scrollViewerTo = (highlight: IHighlight) => {}; scrollToHighlightFromHash = () => { const highlight = this.getHighlightById(parseIdFromHash()); @@ -89,7 +95,7 @@ class App extends Component<{}, State> { window.addEventListener( "hashchange", this.scrollToHighlightFromHash, - false + false, ); } @@ -109,7 +115,11 @@ class App extends Component<{}, State> { }); } - updateHighlight(highlightId: string, position: Object, content: Object) { + updateHighlight( + highlightId: string, + position: Partial, + content: Partial, + ) { console.log("Updating highlight", highlightId, position, content); this.setState({ @@ -165,7 +175,7 @@ class App extends Component<{}, State> { position, content, hideTipAndSelection, - transformSelection + transformSelection, ) => ( { hideTip, viewportToScaled, screenshot, - isScrolledTo + isScrolledTo, ) => { - const isTextHighlight = !Boolean( - highlight.content && highlight.content.image - ); + const isTextHighlight = !highlight.content?.image; const component = isTextHighlight ? ( { this.updateHighlight( highlight.id, { boundingRect: viewportToScaled(boundingRect) }, - { image: screenshot(boundingRect) } + { image: screenshot(boundingRect) }, ); }} /> @@ -217,8 +225,9 @@ class App extends Component<{}, State> { } onMouseOut={hideTip} key={index} - children={component} - /> + > + {component} + ); }} highlights={highlights} diff --git a/example/src/Sidebar.tsx b/example/src/Sidebar.tsx index 2330f2eab..7d640f821 100644 --- a/example/src/Sidebar.tsx +++ b/example/src/Sidebar.tsx @@ -42,6 +42,7 @@ export function Sidebar({
    {highlights.map((highlight, index) => (
  • { @@ -71,11 +72,15 @@ export function Sidebar({ ))}
- +
{highlights.length > 0 ? (
- +
) : null} diff --git a/example/src/index.tsx b/example/src/index.tsx index 5ae5403ba..0b75b2544 100644 --- a/example/src/index.tsx +++ b/example/src/index.tsx @@ -1,7 +1,8 @@ import React from "react"; -import App from "./App"; import { createRoot } from "react-dom/client"; +import App from "./App"; -const container = document.getElementById("root"); -const root = createRoot(container!); +// biome-ignore lint/style/noNonNullAssertion: Root element must be there +const container = document.getElementById("root")!; +const root = createRoot(container); root.render(); diff --git a/example/vite.config.ts b/example/vite.config.ts index 19e2b1423..69624e9f6 100644 --- a/example/vite.config.ts +++ b/example/vite.config.ts @@ -1,12 +1,12 @@ +import react from "@vitejs/plugin-react"; import { defineConfig } from "vite"; -import reactRefresh from "@vitejs/plugin-react-refresh"; export default defineConfig({ base: "/react-pdf-highlighter/", build: { outDir: "dist", }, - plugins: [reactRefresh()], + plugins: [react()], server: { port: 3003, }, diff --git a/package-lock.json b/package-lock.json index 8d600964c..c54605065 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,19 +9,18 @@ "version": "6.1.0", "license": "MIT", "dependencies": { - "lodash.debounce": "^4.0.8", + "debounce": "^2.1.0", "pdfjs-dist": "^4.4.168", "react-rnd": "^10.1.10" }, "devDependencies": { + "@biomejs/biome": "1.8.3", "@playwright/test": "^1.45.1", - "@types/lodash.debounce": "^4.0.6", - "@types/node": "^20.4.5", - "@types/react": "^18.0.0", - "@types/react-dom": "^18.0.0", - "@vitejs/plugin-react-refresh": "^1.3.1", + "@types/node": "^20.14.10", + "@types/react": "^18.3.3", + "@types/react-dom": "^18.3.0", + "@vitejs/plugin-react": "^4.3.1", "playwright": "^1.45.1", - "prettier": "^2.3.2", "typescript": "^5.5.3", "vite": "^5.3.3" }, @@ -317,12 +316,13 @@ } }, "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.14.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.14.9.tgz", - "integrity": "sha512-Fqqu0f8zv9W+RyOnx29BX/RlEsBRANbOf5xs5oxb2aHP4FKbLXxIaVPUiCti56LAR1IixMH4EyaixhUsKqoBHw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.24.7.tgz", + "integrity": "sha512-fOPQYbGSgH0HUp4UJO4sMBFjY6DuWq+2i8rixyUMb3CdGixs/gccURvYOAhajBdKDoGajFr3mUq5rH3phtkGzw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -332,12 +332,13 @@ } }, "node_modules/@babel/plugin-transform-react-jsx-source": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.14.5.tgz", - "integrity": "sha512-1TpSDnD9XR/rQ2tzunBVPThF5poaYT9GqP+of8fAtguYuI/dm2RkrMBDemsxtY0XBzvW7nXjYM0hRyKX9QYj7Q==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.24.7.tgz", + "integrity": "sha512-J2z+MWzZHVOemyLweMqngXrgGC42jQ//R0KdxqkIz/OrbVIIlhFI3WigZ5fO+nwFvBlncr4MGapd8vTyc7RPNQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -398,6 +399,170 @@ "node": ">=6.9.0" } }, + "node_modules/@biomejs/biome": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-1.8.3.tgz", + "integrity": "sha512-/uUV3MV+vyAczO+vKrPdOW0Iaet7UnJMU4bNMinggGJTAnBPjCoLEYcyYtYHNnUNYlv4xZMH6hVIQCAozq8d5w==", + "dev": true, + "hasInstallScript": true, + "license": "MIT OR Apache-2.0", + "bin": { + "biome": "bin/biome" + }, + "engines": { + "node": ">=14.21.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/biome" + }, + "optionalDependencies": { + "@biomejs/cli-darwin-arm64": "1.8.3", + "@biomejs/cli-darwin-x64": "1.8.3", + "@biomejs/cli-linux-arm64": "1.8.3", + "@biomejs/cli-linux-arm64-musl": "1.8.3", + "@biomejs/cli-linux-x64": "1.8.3", + "@biomejs/cli-linux-x64-musl": "1.8.3", + "@biomejs/cli-win32-arm64": "1.8.3", + "@biomejs/cli-win32-x64": "1.8.3" + } + }, + "node_modules/@biomejs/cli-darwin-arm64": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-1.8.3.tgz", + "integrity": "sha512-9DYOjclFpKrH/m1Oz75SSExR8VKvNSSsLnVIqdnKexj6NwmiMlKk94Wa1kZEdv6MCOHGHgyyoV57Cw8WzL5n3A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-darwin-x64": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-1.8.3.tgz", + "integrity": "sha512-UeW44L/AtbmOF7KXLCoM+9PSgPo0IDcyEUfIoOXYeANaNXXf9mLUwV1GeF2OWjyic5zj6CnAJ9uzk2LT3v/wAw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-arm64": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-1.8.3.tgz", + "integrity": "sha512-fed2ji8s+I/m8upWpTJGanqiJ0rnlHOK3DdxsyVLZQ8ClY6qLuPc9uehCREBifRJLl/iJyQpHIRufLDeotsPtw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-arm64-musl": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.8.3.tgz", + "integrity": "sha512-9yjUfOFN7wrYsXt/T/gEWfvVxKlnh3yBpnScw98IF+oOeCYb5/b/+K7YNqKROV2i1DlMjg9g/EcN9wvj+NkMuQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-x64": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-1.8.3.tgz", + "integrity": "sha512-I8G2QmuE1teISyT8ie1HXsjFRz9L1m5n83U1O6m30Kw+kPMPSKjag6QGUn+sXT8V+XWIZxFFBoTDEDZW2KPDDw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-x64-musl": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-1.8.3.tgz", + "integrity": "sha512-UHrGJX7PrKMKzPGoEsooKC9jXJMa28TUSMjcIlbDnIO4EAavCoVmNQaIuUSH0Ls2mpGMwUIf+aZJv657zfWWjA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-win32-arm64": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-1.8.3.tgz", + "integrity": "sha512-J+Hu9WvrBevfy06eU1Na0lpc7uR9tibm9maHynLIoAjLZpQU3IW+OKHUtyL8p6/3pT2Ju5t5emReeIS2SAxhkQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-win32-x64": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-1.8.3.tgz", + "integrity": "sha512-/PJ59vA1pnQeKahemaQf4Nyj7IKUvGQSc3Ze1uIGi+Wvr1xF7rGobSrAAG01T/gUDG21vkDsZYM03NAmPiVkqg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.21.3" + } + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", @@ -903,19 +1068,6 @@ "node": ">=18" } }, - "node_modules/@rollup/pluginutils": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.1.1.tgz", - "integrity": "sha512-clDjivHqWGXi7u+0d2r2sBi4Ie6VLEAzWMIkvJLnDmxoOhBYOTfzGbOQBA32THHm11/LiJbd01tJUpJsbshSWQ==", - "dev": true, - "dependencies": { - "estree-walker": "^2.0.1", - "picomatch": "^2.2.2" - }, - "engines": { - "node": ">= 8.0.0" - } - }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.18.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz", @@ -1140,28 +1292,58 @@ "win32" ] }, - "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } }, - "node_modules/@types/lodash": { - "version": "4.14.172", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.172.tgz", - "integrity": "sha512-/BHF5HAx3em7/KkzVKm3LrsD6HZAXuXO1AJZQ3cRRBZj4oHZDviWPYu0aEplAqDFNHZPW6d3G7KN+ONcCCC7pw==", - "dev": true + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } }, - "node_modules/@types/lodash.debounce": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@types/lodash.debounce/-/lodash.debounce-4.0.6.tgz", - "integrity": "sha512-4WTmnnhCfDvvuLMaF3KV4Qfki93KebocUF45msxhYyjMttZDQYzHkO639ohhk8+oco2cluAFL3t5+Jn4mleylQ==", + "node_modules/@types/babel__traverse": { + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", + "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", "dev": true, + "license": "MIT", "dependencies": { - "@types/lodash": "*" + "@babel/types": "^7.20.7" } }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/node": { "version": "20.14.10", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz", @@ -1179,45 +1361,54 @@ "dev": true }, "node_modules/@types/react": { - "version": "18.0.28", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.28.tgz", - "integrity": "sha512-RD0ivG1kEztNBdoAK7lekI9M+azSnitIn85h4iOiaLjaTrMjzslhaqCGaI4IyCJ1RljWiLCEu4jyrLLgqxBTew==", + "version": "18.3.3", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", + "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", "dev": true, + "license": "MIT", "dependencies": { "@types/prop-types": "*", - "@types/scheduler": "*", "csstype": "^3.0.2" } }, "node_modules/@types/react-dom": { - "version": "18.0.11", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.11.tgz", - "integrity": "sha512-O38bPbI2CWtgw/OoQoY+BRelw7uysmXbWvw3nLWO21H1HSh+GOlqPuXshJfjmpNlKiiSDG9cc1JZAaMmVdcTlw==", + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", + "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", "dev": true, + "license": "MIT", "dependencies": { "@types/react": "*" } }, - "node_modules/@types/scheduler": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", - "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==", - "dev": true - }, - "node_modules/@vitejs/plugin-react-refresh": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react-refresh/-/plugin-react-refresh-1.3.6.tgz", - "integrity": "sha512-iNR/UqhUOmFFxiezt0em9CgmiJBdWR+5jGxB2FihaoJfqGt76kiwaKoVOJVU5NYcDWMdN06LbyN2VIGIoYdsEA==", + "node_modules/@vitejs/plugin-react": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.3.1.tgz", + "integrity": "sha512-m/V2syj5CuVnaxcUJOQRel/Wr31FFXRFlnOoq1TVtkCxsY5veGMTEmpWHndrhB2U8ScHtCQB1e+4hWYExQc6Lg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/core": "^7.14.8", - "@babel/plugin-transform-react-jsx-self": "^7.14.5", - "@babel/plugin-transform-react-jsx-source": "^7.14.5", - "@rollup/pluginutils": "^4.1.1", - "react-refresh": "^0.10.0" + "@babel/core": "^7.24.5", + "@babel/plugin-transform-react-jsx-self": "^7.24.5", + "@babel/plugin-transform-react-jsx-source": "^7.24.1", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.14.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0" + } + }, + "node_modules/@vitejs/plugin-react/node_modules/react-refresh": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", + "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=12.0.0" + "node": ">=0.10.0" } }, "node_modules/abbrev": { @@ -1479,6 +1670,18 @@ "integrity": "sha512-jXKhWqXPmlUeoQnF/EhTtTl4C9SnrxSH/jZUih3jmO6lBKr99rP3/+FmrMj4EFpOXzMtXHAZkd3x0E6h6Fgflw==", "dev": true }, + "node_modules/debounce": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/debounce/-/debounce-2.1.0.tgz", + "integrity": "sha512-OkL3+0pPWCqoBc/nhO9u6TIQNTK44fnBnzuVtJAbp13Naxw9R6u21x+8tVTka87AhDZ3htqZ2pSSsZl9fqL2Wg==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -1599,12 +1802,6 @@ "node": ">=0.8.0" } }, - "node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true - }, "node_modules/fast-memoize": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/fast-memoize/-/fast-memoize-2.5.2.tgz", @@ -1817,11 +2014,6 @@ "node": ">=6" } }, - "node_modules/lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" - }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -2090,18 +2282,6 @@ "dev": true, "license": "ISC" }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, "node_modules/playwright": { "version": "1.45.1", "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.45.1.tgz", @@ -2178,18 +2358,6 @@ "node": "^10 || ^12 || >=14" } }, - "node_modules/prettier": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.2.tgz", - "integrity": "sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ==", - "dev": true, - "bin": { - "prettier": "bin-prettier.js" - }, - "engines": { - "node": ">=10.13.0" - } - }, "node_modules/prop-types": { "version": "15.7.2", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", @@ -2239,15 +2407,6 @@ "prop-types": "^15.6.0" } }, - "node_modules/react-refresh": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.10.0.tgz", - "integrity": "sha512-PgidR3wST3dDYKr6b4pJoqQFpPGNKDSCDx4cZoshjXipw3LzO7mG1My2pwEzz2JVkF+inx3xRpDeQLFQGH/hsQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/react-rnd": { "version": "10.3.4", "resolved": "https://registry.npmjs.org/react-rnd/-/react-rnd-10.3.4.tgz", @@ -2976,21 +3135,21 @@ "dev": true }, "@babel/plugin-transform-react-jsx-self": { - "version": "7.14.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.14.9.tgz", - "integrity": "sha512-Fqqu0f8zv9W+RyOnx29BX/RlEsBRANbOf5xs5oxb2aHP4FKbLXxIaVPUiCti56LAR1IixMH4EyaixhUsKqoBHw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.24.7.tgz", + "integrity": "sha512-fOPQYbGSgH0HUp4UJO4sMBFjY6DuWq+2i8rixyUMb3CdGixs/gccURvYOAhajBdKDoGajFr3mUq5rH3phtkGzw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.24.7" } }, "@babel/plugin-transform-react-jsx-source": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.14.5.tgz", - "integrity": "sha512-1TpSDnD9XR/rQ2tzunBVPThF5poaYT9GqP+of8fAtguYuI/dm2RkrMBDemsxtY0XBzvW7nXjYM0hRyKX9QYj7Q==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.24.7.tgz", + "integrity": "sha512-J2z+MWzZHVOemyLweMqngXrgGC42jQ//R0KdxqkIz/OrbVIIlhFI3WigZ5fO+nwFvBlncr4MGapd8vTyc7RPNQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.24.7" } }, "@babel/template": { @@ -3033,6 +3192,78 @@ "to-fast-properties": "^2.0.0" } }, + "@biomejs/biome": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-1.8.3.tgz", + "integrity": "sha512-/uUV3MV+vyAczO+vKrPdOW0Iaet7UnJMU4bNMinggGJTAnBPjCoLEYcyYtYHNnUNYlv4xZMH6hVIQCAozq8d5w==", + "dev": true, + "requires": { + "@biomejs/cli-darwin-arm64": "1.8.3", + "@biomejs/cli-darwin-x64": "1.8.3", + "@biomejs/cli-linux-arm64": "1.8.3", + "@biomejs/cli-linux-arm64-musl": "1.8.3", + "@biomejs/cli-linux-x64": "1.8.3", + "@biomejs/cli-linux-x64-musl": "1.8.3", + "@biomejs/cli-win32-arm64": "1.8.3", + "@biomejs/cli-win32-x64": "1.8.3" + } + }, + "@biomejs/cli-darwin-arm64": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-1.8.3.tgz", + "integrity": "sha512-9DYOjclFpKrH/m1Oz75SSExR8VKvNSSsLnVIqdnKexj6NwmiMlKk94Wa1kZEdv6MCOHGHgyyoV57Cw8WzL5n3A==", + "dev": true, + "optional": true + }, + "@biomejs/cli-darwin-x64": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-1.8.3.tgz", + "integrity": "sha512-UeW44L/AtbmOF7KXLCoM+9PSgPo0IDcyEUfIoOXYeANaNXXf9mLUwV1GeF2OWjyic5zj6CnAJ9uzk2LT3v/wAw==", + "dev": true, + "optional": true + }, + "@biomejs/cli-linux-arm64": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-1.8.3.tgz", + "integrity": "sha512-fed2ji8s+I/m8upWpTJGanqiJ0rnlHOK3DdxsyVLZQ8ClY6qLuPc9uehCREBifRJLl/iJyQpHIRufLDeotsPtw==", + "dev": true, + "optional": true + }, + "@biomejs/cli-linux-arm64-musl": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.8.3.tgz", + "integrity": "sha512-9yjUfOFN7wrYsXt/T/gEWfvVxKlnh3yBpnScw98IF+oOeCYb5/b/+K7YNqKROV2i1DlMjg9g/EcN9wvj+NkMuQ==", + "dev": true, + "optional": true + }, + "@biomejs/cli-linux-x64": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-1.8.3.tgz", + "integrity": "sha512-I8G2QmuE1teISyT8ie1HXsjFRz9L1m5n83U1O6m30Kw+kPMPSKjag6QGUn+sXT8V+XWIZxFFBoTDEDZW2KPDDw==", + "dev": true, + "optional": true + }, + "@biomejs/cli-linux-x64-musl": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-1.8.3.tgz", + "integrity": "sha512-UHrGJX7PrKMKzPGoEsooKC9jXJMa28TUSMjcIlbDnIO4EAavCoVmNQaIuUSH0Ls2mpGMwUIf+aZJv657zfWWjA==", + "dev": true, + "optional": true + }, + "@biomejs/cli-win32-arm64": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-1.8.3.tgz", + "integrity": "sha512-J+Hu9WvrBevfy06eU1Na0lpc7uR9tibm9maHynLIoAjLZpQU3IW+OKHUtyL8p6/3pT2Ju5t5emReeIS2SAxhkQ==", + "dev": true, + "optional": true + }, + "@biomejs/cli-win32-x64": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-1.8.3.tgz", + "integrity": "sha512-/PJ59vA1pnQeKahemaQf4Nyj7IKUvGQSc3Ze1uIGi+Wvr1xF7rGobSrAAG01T/gUDG21vkDsZYM03NAmPiVkqg==", + "dev": true, + "optional": true + }, "@esbuild/aix-ppc64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", @@ -3279,16 +3510,6 @@ "playwright": "1.45.1" } }, - "@rollup/pluginutils": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.1.1.tgz", - "integrity": "sha512-clDjivHqWGXi7u+0d2r2sBi4Ie6VLEAzWMIkvJLnDmxoOhBYOTfzGbOQBA32THHm11/LiJbd01tJUpJsbshSWQ==", - "dev": true, - "requires": { - "estree-walker": "^2.0.1", - "picomatch": "^2.2.2" - } - }, "@rollup/rollup-android-arm-eabi": { "version": "4.18.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz", @@ -3401,27 +3622,53 @@ "dev": true, "optional": true }, - "@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true + "@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "requires": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } }, - "@types/lodash": { - "version": "4.14.172", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.172.tgz", - "integrity": "sha512-/BHF5HAx3em7/KkzVKm3LrsD6HZAXuXO1AJZQ3cRRBZj4oHZDviWPYu0aEplAqDFNHZPW6d3G7KN+ONcCCC7pw==", - "dev": true + "@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } }, - "@types/lodash.debounce": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@types/lodash.debounce/-/lodash.debounce-4.0.6.tgz", - "integrity": "sha512-4WTmnnhCfDvvuLMaF3KV4Qfki93KebocUF45msxhYyjMttZDQYzHkO639ohhk8+oco2cluAFL3t5+Jn4mleylQ==", + "@types/babel__traverse": { + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", + "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", "dev": true, "requires": { - "@types/lodash": "*" + "@babel/types": "^7.20.7" } }, + "@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true + }, "@types/node": { "version": "20.14.10", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz", @@ -3438,42 +3685,43 @@ "dev": true }, "@types/react": { - "version": "18.0.28", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.28.tgz", - "integrity": "sha512-RD0ivG1kEztNBdoAK7lekI9M+azSnitIn85h4iOiaLjaTrMjzslhaqCGaI4IyCJ1RljWiLCEu4jyrLLgqxBTew==", + "version": "18.3.3", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", + "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", "dev": true, "requires": { "@types/prop-types": "*", - "@types/scheduler": "*", "csstype": "^3.0.2" } }, "@types/react-dom": { - "version": "18.0.11", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.11.tgz", - "integrity": "sha512-O38bPbI2CWtgw/OoQoY+BRelw7uysmXbWvw3nLWO21H1HSh+GOlqPuXshJfjmpNlKiiSDG9cc1JZAaMmVdcTlw==", + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", + "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", "dev": true, "requires": { "@types/react": "*" } }, - "@types/scheduler": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", - "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==", - "dev": true - }, - "@vitejs/plugin-react-refresh": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react-refresh/-/plugin-react-refresh-1.3.6.tgz", - "integrity": "sha512-iNR/UqhUOmFFxiezt0em9CgmiJBdWR+5jGxB2FihaoJfqGt76kiwaKoVOJVU5NYcDWMdN06LbyN2VIGIoYdsEA==", + "@vitejs/plugin-react": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.3.1.tgz", + "integrity": "sha512-m/V2syj5CuVnaxcUJOQRel/Wr31FFXRFlnOoq1TVtkCxsY5veGMTEmpWHndrhB2U8ScHtCQB1e+4hWYExQc6Lg==", "dev": true, "requires": { - "@babel/core": "^7.14.8", - "@babel/plugin-transform-react-jsx-self": "^7.14.5", - "@babel/plugin-transform-react-jsx-source": "^7.14.5", - "@rollup/pluginutils": "^4.1.1", - "react-refresh": "^0.10.0" + "@babel/core": "^7.24.5", + "@babel/plugin-transform-react-jsx-self": "^7.24.5", + "@babel/plugin-transform-react-jsx-source": "^7.24.1", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.14.2" + }, + "dependencies": { + "react-refresh": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", + "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", + "dev": true + } } }, "abbrev": { @@ -3650,6 +3898,11 @@ "integrity": "sha512-jXKhWqXPmlUeoQnF/EhTtTl4C9SnrxSH/jZUih3jmO6lBKr99rP3/+FmrMj4EFpOXzMtXHAZkd3x0E6h6Fgflw==", "dev": true }, + "debounce": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/debounce/-/debounce-2.1.0.tgz", + "integrity": "sha512-OkL3+0pPWCqoBc/nhO9u6TIQNTK44fnBnzuVtJAbp13Naxw9R6u21x+8tVTka87AhDZ3htqZ2pSSsZl9fqL2Wg==" + }, "debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -3735,12 +3988,6 @@ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true }, - "estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true - }, "fast-memoize": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/fast-memoize/-/fast-memoize-2.5.2.tgz", @@ -3889,11 +4136,6 @@ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true }, - "lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" - }, "loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -4069,12 +4311,6 @@ "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", "dev": true }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true - }, "playwright": { "version": "1.45.1", "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.45.1.tgz", @@ -4111,12 +4347,6 @@ "source-map-js": "^1.2.0" } }, - "prettier": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.2.tgz", - "integrity": "sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ==", - "dev": true - }, "prop-types": { "version": "15.7.2", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", @@ -4162,12 +4392,6 @@ "prop-types": "^15.6.0" } }, - "react-refresh": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.10.0.tgz", - "integrity": "sha512-PgidR3wST3dDYKr6b4pJoqQFpPGNKDSCDx4cZoshjXipw3LzO7mG1My2pwEzz2JVkF+inx3xRpDeQLFQGH/hsQ==", - "dev": true - }, "react-rnd": { "version": "10.3.4", "resolved": "https://registry.npmjs.org/react-rnd/-/react-rnd-10.3.4.tgz", diff --git a/package.json b/package.json index 9e68884c4..21c61b059 100644 --- a/package.json +++ b/package.json @@ -4,15 +4,8 @@ "description": "Set of React components for PDF annotation", "author": "Artem Tyurin ", "license": "MIT", - "keywords": [ - "pdf", - "highlight", - "annotator", - "react-component" - ], - "files": [ - "dist", "README.md", "LICENSE" - ], + "keywords": ["pdf", "highlight", "annotator", "react-component"], + "files": ["dist", "README.md", "LICENSE"], "type": "module", "types": "./dist/index.d.ts", "main": "./dist/index.js", @@ -23,10 +16,10 @@ "build:esm": "tsc", "build:copy-styles": "cp -r ./src/style ./dist", "build:example": "(cd ./example && tsc && vite build)", - "test": "tsc && npm run format:check && npm run test:e2e", + "test": "tsc && npm run lint && npm run test:e2e", "test:e2e": "playwright test", - "format": "prettier --write './**/*.{js,ts,tsx}'", - "format:check": "prettier --check './**/*.{js,ts,tsx}'", + "format": "biome format --write", + "lint": "biome check", "clean": "rm -rf dist" }, "peerDependencies": { @@ -34,7 +27,7 @@ "react-dom": ">=18.0.0" }, "dependencies": { - "lodash.debounce": "^4.0.8", + "debounce": "^2.1.0", "pdfjs-dist": "^4.4.168", "react-rnd": "^10.1.10" }, @@ -46,14 +39,13 @@ "url": "https://github.com/agentcooper/react-pdf-highlighter/issues" }, "devDependencies": { + "@biomejs/biome": "1.8.3", "@playwright/test": "^1.45.1", - "@types/lodash.debounce": "^4.0.6", - "@types/node": "^20.4.5", - "@types/react": "^18.0.0", - "@types/react-dom": "^18.0.0", - "@vitejs/plugin-react-refresh": "^1.3.1", + "@types/node": "^20.14.10", + "@types/react": "^18.3.3", + "@types/react-dom": "^18.3.0", + "@vitejs/plugin-react": "^4.3.1", "playwright": "^1.45.1", - "prettier": "^2.3.2", "typescript": "^5.5.3", "vite": "^5.3.3" } diff --git a/src/components/Highlight.tsx b/src/components/Highlight.tsx index bd65578c3..991b10bcc 100644 --- a/src/components/Highlight.tsx +++ b/src/components/Highlight.tsx @@ -53,9 +53,10 @@ export class Highlight extends Component { onMouseOver={onMouseOver} onMouseOut={onMouseOut} onClick={onClick} + // biome-ignore lint/suspicious/noArrayIndexKey: We can use position hash at some point in future key={index} style={rect} - className={`Highlight__part`} + className={"Highlight__part"} /> ))} diff --git a/src/components/HighlightLayer.tsx b/src/components/HighlightLayer.tsx index 2ab05d733..cdf9d8bff 100644 --- a/src/components/HighlightLayer.tsx +++ b/src/components/HighlightLayer.tsx @@ -1,6 +1,6 @@ -import { viewportToScaled } from "../lib/coordinates"; import React from "react"; -import { +import { viewportToScaled } from "../lib/coordinates"; +import type { IHighlight, LTWH, LTWHP, @@ -9,29 +9,38 @@ import { ScaledPosition, } from "../types"; +import type { PDFViewer } from "pdfjs-dist/web/pdf_viewer.mjs"; +import type { T_ViewportHighlight } from "./PdfHighlighter"; + interface HighlightLayerProps { highlightsByPage: { [pageNumber: string]: Array }; pageNumber: string; scrolledToHighlightId: string; highlightTransform: ( - highlight: any, + highlight: T_ViewportHighlight, index: number, - setTip: (highlight: any, callback: (highlight: any) => JSX.Element) => void, + setTip: ( + highlight: T_ViewportHighlight, + callback: (highlight: T_ViewportHighlight) => JSX.Element, + ) => void, hideTip: () => void, viewportToScaled: (rect: LTWHP) => Scaled, screenshot: (position: LTWH) => string, - isScrolledTo: boolean + isScrolledTo: boolean, ) => JSX.Element; tip: { - highlight: any; - callback: (highlight: any) => JSX.Element; + highlight: T_ViewportHighlight; + callback: (highlight: T_ViewportHighlight) => JSX.Element; } | null; scaledPositionToViewport: (scaledPosition: ScaledPosition) => Position; hideTipAndSelection: () => void; - viewer: any; + viewer: PDFViewer; screenshot: (position: LTWH, pageNumber: number) => string; - showTip: (highlight: any, content: JSX.Element) => void; - setState: (state: any) => void; + showTip: (highlight: T_ViewportHighlight, content: JSX.Element) => void; + setTip: (state: { + highlight: T_ViewportHighlight; + callback: (highlight: T_ViewportHighlight) => JSX.Element; + }) => void; } export function HighlightLayer({ @@ -45,45 +54,41 @@ export function HighlightLayer({ viewer, screenshot, showTip, - setState, + setTip, }: HighlightLayerProps) { const currentHighlights = highlightsByPage[String(pageNumber)] || []; return (
- {currentHighlights.map(({ position, id, ...highlight }, index) => { - // @ts-ignore - const viewportHighlight: any = { - id, - position: scaledPositionToViewport(position), + {currentHighlights.map((highlight, index) => { + const viewportHighlight: T_ViewportHighlight = { ...highlight, + position: scaledPositionToViewport(highlight.position), }; - if (tip && tip.highlight.id === String(id)) { + if (tip && tip.highlight.id === String(highlight.id)) { showTip(tip.highlight, tip.callback(viewportHighlight)); } - const isScrolledTo = Boolean(scrolledToHighlightId === id); + const isScrolledTo = Boolean(scrolledToHighlightId === highlight.id); return highlightTransform( viewportHighlight, index, (highlight, callback) => { - setState({ - tip: { highlight, callback }, - }); - + setTip({ highlight, callback }); showTip(highlight, callback(highlight)); }, hideTipAndSelection, (rect) => { const viewport = viewer.getPageView( - (rect.pageNumber || parseInt(pageNumber)) - 1 + (rect.pageNumber || Number.parseInt(pageNumber)) - 1, ).viewport; return viewportToScaled(rect, viewport); }, - (boundingRect) => screenshot(boundingRect, parseInt(pageNumber)), - isScrolledTo + (boundingRect) => + screenshot(boundingRect, Number.parseInt(pageNumber)), + isScrolledTo, ); })}
diff --git a/src/components/MouseSelection.tsx b/src/components/MouseSelection.tsx index 775f9807c..ff8d933f1 100644 --- a/src/components/MouseSelection.tsx +++ b/src/components/MouseSelection.tsx @@ -1,6 +1,6 @@ import React, { Component } from "react"; -import { asElement, isHTMLElement } from "../lib/pdfjs-dom"; +import { isHTMLElement } from "../lib/pdfjs-dom"; import "../style/MouseSelection.css"; import type { LTWH } from "../types.js"; @@ -20,7 +20,7 @@ interface Props { onSelection: ( startTarget: HTMLElement, boundingRect: LTWH, - resetSelection: () => void + resetSelection: () => void, ) => void; onDragStart: () => void; onDragEnd: () => void; @@ -68,13 +68,10 @@ class MouseSelection extends Component { return; } - const that = this; - const { onSelection, onDragStart, onDragEnd, shouldStart } = this.props; - const container = asElement(this.root.parentElement); - - if (!isHTMLElement(container)) { + const container = this.root.parentElement; + if (!container || !isHTMLElement(container)) { return; } @@ -102,7 +99,7 @@ class MouseSelection extends Component { return; } - that.setState({ + this.setState({ ...this.state, end: containerCoords(event.pageX, event.pageY), }); @@ -114,8 +111,8 @@ class MouseSelection extends Component { return; } - const startTarget = asElement(event.target); - if (!isHTMLElement(startTarget)) { + const startTarget = event.target; + if (!(startTarget instanceof Element) || !isHTMLElement(startTarget)) { return; } @@ -131,7 +128,7 @@ class MouseSelection extends Component { // emulate listen once event.currentTarget?.removeEventListener( "mouseup", - onMouseUp as EventListener + onMouseUp as EventListener, ); const { start } = this.state; @@ -142,35 +139,39 @@ class MouseSelection extends Component { const end = containerCoords(event.pageX, event.pageY); - const boundingRect = that.getBoundingRect(start, end); + const boundingRect = this.getBoundingRect(start, end); if ( + !(event.target instanceof Element) || !isHTMLElement(event.target) || - !container.contains(asElement(event.target)) || - !that.shouldRender(boundingRect) + !container.contains(event.target) || + !this.shouldRender(boundingRect) ) { - that.reset(); + this.reset(); return; } - that.setState( + this.setState( { end, locked: true, }, () => { - const { start, end } = that.state; + const { start, end } = this.state; if (!start || !end) { return; } - if (isHTMLElement(event.target)) { - onSelection(startTarget, boundingRect, that.reset); + if ( + event.target instanceof Element && + isHTMLElement(event.target) + ) { + onSelection(startTarget, boundingRect, this.reset); onDragEnd(); } - } + }, ); }; diff --git a/src/components/PdfHighlighter.tsx b/src/components/PdfHighlighter.tsx index dddf48f35..c7183d295 100644 --- a/src/components/PdfHighlighter.tsx +++ b/src/components/PdfHighlighter.tsx @@ -2,7 +2,26 @@ import "pdfjs-dist/web/pdf_viewer.css"; import "../style/pdf_viewer.css"; import "../style/PdfHighlighter.css"; +import debounce from "debounce"; +import type { PDFDocumentProxy } from "pdfjs-dist"; import type { EventBus, PDFViewer } from "pdfjs-dist/legacy/web/pdf_viewer.mjs"; +import React, { + type PointerEventHandler, + PureComponent, + type RefObject, +} from "react"; +import { type Root, createRoot } from "react-dom/client"; +import { scaledToViewport, viewportToScaled } from "../lib/coordinates"; +import getAreaAsPng from "../lib/get-area-as-png"; +import getBoundingRect from "../lib/get-bounding-rect"; +import getClientRects from "../lib/get-client-rects"; +import { + findOrCreateContainerLayer, + getPageFromElement, + getPagesFromRange, + getWindow, + isHTMLElement, +} from "../lib/pdfjs-dom"; import type { IHighlight, LTWH, @@ -11,25 +30,9 @@ import type { Scaled, ScaledPosition, } from "../types"; -import React, { PointerEventHandler, PureComponent, RefObject } from "react"; -import { - asElement, - findOrCreateContainerLayer, - getPageFromElement, - getPagesFromRange, - getWindow, - isHTMLElement, -} from "../lib/pdfjs-dom"; -import { scaledToViewport, viewportToScaled } from "../lib/coordinates"; +import { HighlightLayer } from "./HighlightLayer"; import MouseSelection from "./MouseSelection"; -import type { PDFDocumentProxy } from "pdfjs-dist"; import TipContainer from "./TipContainer"; -import { createRoot, Root } from "react-dom/client"; -import debounce from "lodash.debounce"; -import getAreaAsPng from "../lib/get-area-as-png"; -import getBoundingRect from "../lib/get-bounding-rect"; -import getClientRects from "../lib/get-client-rects"; -import { HighlightLayer } from "./HighlightLayer"; export type T_ViewportHighlight = { position: Position } & T_HT; @@ -56,12 +59,12 @@ interface Props { index: number, setTip: ( highlight: T_ViewportHighlight, - callback: (highlight: T_ViewportHighlight) => JSX.Element + callback: (highlight: T_ViewportHighlight) => JSX.Element, ) => void, hideTip: () => void, viewportToScaled: (rect: LTWHP) => Scaled, screenshot: (position: LTWH) => string, - isScrolledTo: boolean + isScrolledTo: boolean, ) => JSX.Element; highlights: Array; onScrollChange: () => void; @@ -72,7 +75,7 @@ interface Props { position: ScaledPosition, content: { text?: string; image?: string }, hideTipAndSelection: () => void, - transformSelection: () => void + transformSelection: () => void, ) => JSX.Element | null; enableAreaSelection: (event: MouseEvent) => boolean; } @@ -122,17 +125,17 @@ export class PdfHighlighter extends PureComponent< attachRef = (eventBus: EventBus) => { const { resizeObserver: observer } = this; - const ref = (this.containerNode = this.containerNodeRef!.current); + this.containerNode = this.containerNodeRef.current; this.unsubscribe(); - if (ref) { - const { ownerDocument: doc } = ref; + if (this.containerNode) { + const { ownerDocument: doc } = this.containerNode; eventBus.on("textlayerrendered", this.onTextLayerRendered); eventBus.on("pagesinit", this.onDocumentReady); doc.addEventListener("selectionchange", this.onSelectionChange); doc.addEventListener("keydown", this.handleKeyDown); doc.defaultView?.addEventListener("resize", this.debouncedScaleValue); - if (observer) observer.observe(ref); + if (observer) observer.observe(this.containerNode); this.unsubscribe = () => { eventBus.off("pagesinit", this.onDocumentReady); @@ -141,7 +144,7 @@ export class PdfHighlighter extends PureComponent< doc.removeEventListener("keydown", this.handleKeyDown); doc.defaultView?.removeEventListener( "resize", - this.debouncedScaleValue + this.debouncedScaleValue, ); if (observer) observer.disconnect(); }; @@ -168,10 +171,14 @@ export class PdfHighlighter extends PureComponent< externalLinkTarget: 2, }); + if (!this.containerNodeRef.current) { + throw new Error("!"); + } + this.viewer = this.viewer || new pdfjs.PDFViewer({ - container: this.containerNodeRef!.current!, + container: this.containerNodeRef.current, eventBus: eventBus, // enhanceTextSelection: true, // deprecated. https://github.com/mozilla/pdf.js/issues/9943#issuecomment-409369485 textLayerMode: 2, @@ -184,9 +191,6 @@ export class PdfHighlighter extends PureComponent< this.viewer.setDocument(pdfDocument); this.attachRef(eventBus); - - // debug - (window as any).PdfViewer = this; } componentWillUnmount() { @@ -202,7 +206,7 @@ export class PdfHighlighter extends PureComponent< return findOrCreateContainerLayer( textLayer.div, - "PdfHighlighter__highlight-layer" + "PdfHighlighter__highlight-layer", ); } @@ -211,19 +215,21 @@ export class PdfHighlighter extends PureComponent< } { const { ghostHighlight } = this.state; - const allHighlights = [...highlights, ghostHighlight].filter(Boolean); + const allHighlights = [...highlights, ghostHighlight].filter( + Boolean, + ) as T_HT[]; const pageNumbers = new Set(); for (const highlight of allHighlights) { - pageNumbers.add(highlight!.position.pageNumber); - for (const rect of highlight!.position.rects) { + pageNumbers.add(highlight.position.pageNumber); + for (const rect of highlight.position.rects) { if (rect.pageNumber) { pageNumbers.add(rect.pageNumber); } } } - const groupedHighlights = {} as Record; + const groupedHighlights: Record = {}; for (const pageNumber of pageNumbers) { groupedHighlights[pageNumber] = groupedHighlights[pageNumber] || []; @@ -232,21 +238,21 @@ export class PdfHighlighter extends PureComponent< ...highlight, position: { pageNumber, - boundingRect: highlight!.position.boundingRect, + boundingRect: highlight.position.boundingRect, rects: [], - usePdfCoordinates: highlight!.position.usePdfCoordinates, + usePdfCoordinates: highlight.position.usePdfCoordinates, } as ScaledPosition, }; let anyRectsOnPage = false; - for (const rect of highlight!.position.rects) { + for (const rect of highlight.position.rects) { if ( - pageNumber === (rect.pageNumber || highlight!.position.pageNumber) + pageNumber === (rect.pageNumber || highlight.position.pageNumber) ) { pageSpecificHighlight.position.rects.push(rect); anyRectsOnPage = true; } } - if (anyRectsOnPage || pageNumber === highlight!.position.pageNumber) { + if (anyRectsOnPage || pageNumber === highlight.position.pageNumber) { groupedHighlights[pageNumber].push(pageSpecificHighlight); } } @@ -279,7 +285,7 @@ export class PdfHighlighter extends PureComponent< return { boundingRect: scaledToViewport(boundingRect, viewport, usePdfCoordinates), rects: (rects || []).map((rect) => - scaledToViewport(rect, viewport, usePdfCoordinates) + scaledToViewport(rect, viewport, usePdfCoordinates), ), pageNumber, }; @@ -312,7 +318,7 @@ export class PdfHighlighter extends PureComponent< }); this.setState({ ghostHighlight: null, tip: null }, () => - this.renderHighlightLayers() + this.renderHighlightLayers(), ); }; @@ -385,7 +391,7 @@ export class PdfHighlighter extends PureComponent< ...pageViewport.convertToPdfPoint( 0, scaledToViewport(boundingRect, pageViewport, usePdfCoordinates).top - - scrollMargin + scrollMargin, ), 0, ], @@ -395,7 +401,7 @@ export class PdfHighlighter extends PureComponent< { scrolledToHighlightId: highlight.id, }, - () => this.renderHighlightLayers() + () => this.renderHighlightLayers(), ); // wait for scrolling to finish @@ -414,8 +420,11 @@ export class PdfHighlighter extends PureComponent< onSelectionChange = () => { const container = this.containerNode; - const selection = getWindow(container).getSelection(); + if (!container) { + return; + } + const selection = getWindow(container).getSelection(); if (!selection) { return; } @@ -452,18 +461,18 @@ export class PdfHighlighter extends PureComponent< { scrolledToHighlightId: EMPTY_ID, }, - () => this.renderHighlightLayers() + () => this.renderHighlightLayers(), ); this.viewer.container.removeEventListener("scroll", this.onScroll); }; onMouseDown: PointerEventHandler = (event) => { - if (!isHTMLElement(event.target)) { + if (!(event.target instanceof Element) || !isHTMLElement(event.target)) { return; } - if (asElement(event.target).closest(".PdfHighlighter__tip-container")) { + if (event.target.closest(".PdfHighlighter__tip-container")) { return; } @@ -521,18 +530,21 @@ export class PdfHighlighter extends PureComponent< { ghostHighlight: { position: scaledPosition }, }, - () => this.renderHighlightLayers() - ) - ) + () => this.renderHighlightLayers(), + ), + ), ); }; debouncedAfterSelection: () => void = debounce(this.afterSelection, 500); toggleTextSelection(flag: boolean) { - this.viewer.viewer!.classList.toggle( + if (!this.viewer.viewer) { + return; + } + this.viewer.viewer.classList.toggle( "PdfHighlighter--disable-selection", - flag + flag, ); } @@ -565,8 +577,9 @@ export class PdfHighlighter extends PureComponent< } shouldStart={(event) => enableAreaSelection(event) && + event.target instanceof Element && isHTMLElement(event.target) && - Boolean(asElement(event.target).closest(".page")) + Boolean(event.target.closest(".page")) } onSelection={(startTarget, boundingRect, resetSelection) => { const page = getPageFromElement(startTarget); @@ -593,7 +606,7 @@ export class PdfHighlighter extends PureComponent< const image = this.screenshot( pageBoundingRect, - pageBoundingRect.pageNumber + pageBoundingRect.pageNumber, ); this.setTip( @@ -614,10 +627,10 @@ export class PdfHighlighter extends PureComponent< () => { resetSelection(); this.renderHighlightLayers(); - } + }, ); - } - ) + }, + ), ); }} /> @@ -632,7 +645,7 @@ export class PdfHighlighter extends PureComponent< for (let pageNumber = 1; pageNumber <= pdfDocument.numPages; pageNumber++) { const highlightRoot = this.highlightRoots[pageNumber]; /** Need to check if container is still attached to the DOM as PDF.js can unload pages. */ - if (highlightRoot && highlightRoot.container.isConnected) { + if (highlightRoot?.container.isConnected) { this.renderHighlightLayer(highlightRoot.reactRoot, pageNumber); } else { const highlightLayer = this.findOrCreateHighlightLayer(pageNumber); @@ -663,8 +676,10 @@ export class PdfHighlighter extends PureComponent< viewer={this.viewer} screenshot={this.screenshot.bind(this)} showTip={this.showTip.bind(this)} - setState={this.setState.bind(this)} - /> + setTip={(tip) => { + this.setState({ tip }); + }} + />, ); } } diff --git a/src/components/PdfLoader.tsx b/src/components/PdfLoader.tsx index 3d2471779..adfc4d198 100644 --- a/src/components/PdfLoader.tsx +++ b/src/components/PdfLoader.tsx @@ -1,6 +1,6 @@ import React, { Component } from "react"; -import { getDocument, GlobalWorkerOptions } from "pdfjs-dist"; +import { GlobalWorkerOptions, getDocument } from "pdfjs-dist"; import type { PDFDocumentProxy } from "pdfjs-dist"; interface Props { @@ -50,7 +50,7 @@ export class PdfLoader extends Component { } } - componentDidCatch(error: Error, info?: any) { + componentDidCatch(error: Error) { const { onError } = this.props; if (onError) { @@ -71,7 +71,7 @@ export class PdfLoader extends Component { } Promise.resolve() - .then(() => discardedDocument && discardedDocument.destroy()) + .then(() => discardedDocument?.destroy()) .then(() => { if (!url) { return; @@ -100,8 +100,8 @@ export class PdfLoader extends Component { {error ? this.renderError() : !pdfDocument || !children - ? beforeLoad - : children(pdfDocument)} + ? beforeLoad + : children(pdfDocument)} ); } diff --git a/src/components/Popup.tsx b/src/components/Popup.tsx index 343f4c101..075f97ca2 100644 --- a/src/components/Popup.tsx +++ b/src/components/Popup.tsx @@ -37,8 +37,9 @@ export class Popup extends Component { }} paddingX={60} paddingY={30} - children={popupContent} - /> + > + {popupContent} + , ); }} onMouseOut={() => { diff --git a/src/components/Tip.tsx b/src/components/Tip.tsx index 7f02fef08..637f4ae13 100644 --- a/src/components/Tip.tsx +++ b/src/components/Tip.tsx @@ -57,6 +57,7 @@ export class Tip extends Component {