feat: Refactor utility and component exports, update dependencies, and add Knip for unused code detection.
This commit is contained in:
Generated
+516
-22
@@ -12,6 +12,7 @@
|
|||||||
"@tabler/icons-react": "^3.35.0",
|
"@tabler/icons-react": "^3.35.0",
|
||||||
"axios": "^1.13.2",
|
"axios": "^1.13.2",
|
||||||
"pdfjs-dist": "^5.4.394",
|
"pdfjs-dist": "^5.4.394",
|
||||||
|
"prop-types": "^15.8.1",
|
||||||
"react": "^19.2.0",
|
"react": "^19.2.0",
|
||||||
"react-dom": "^19.2.0",
|
"react-dom": "^19.2.0",
|
||||||
"react-redux": "^9.2.0",
|
"react-redux": "^9.2.0",
|
||||||
@@ -22,18 +23,19 @@
|
|||||||
"@babel/preset-env": "^7.28.5",
|
"@babel/preset-env": "^7.28.5",
|
||||||
"@babel/preset-react": "^7.28.5",
|
"@babel/preset-react": "^7.28.5",
|
||||||
"@babel/preset-typescript": "^7.28.5",
|
"@babel/preset-typescript": "^7.28.5",
|
||||||
|
"@eslint/js": "^9.39.1",
|
||||||
"@svgr/webpack": "^8.1.0",
|
"@svgr/webpack": "^8.1.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.46.4",
|
"@typescript-eslint/eslint-plugin": "^8.46.4",
|
||||||
"@typescript-eslint/parser": "^8.18.1",
|
"@typescript-eslint/parser": "^8.18.1",
|
||||||
"babel-loader": "^10.0.0",
|
"babel-loader": "^10.0.0",
|
||||||
"copy-webpack-plugin": "^13.0.1",
|
"copy-webpack-plugin": "^13.0.1",
|
||||||
"css-loader": "^7.1.2",
|
"css-loader": "^7.1.2",
|
||||||
"dotenv": "^17.2.3",
|
|
||||||
"eslint": "^9.39.1",
|
"eslint": "^9.39.1",
|
||||||
"eslint-plugin-react": "^7.37.5",
|
"eslint-plugin-react": "^7.37.5",
|
||||||
"eslint-plugin-react-hooks": "^7.0.1",
|
"eslint-plugin-react-hooks": "^7.0.1",
|
||||||
"globals": "^16.5.0",
|
"globals": "^16.5.0",
|
||||||
"html-webpack-plugin": "^5.6.4",
|
"html-webpack-plugin": "^5.6.4",
|
||||||
|
"knip": "^5.71.0",
|
||||||
"style-loader": "^4.0.0",
|
"style-loader": "^4.0.0",
|
||||||
"typescript": "^5.7.3",
|
"typescript": "^5.7.3",
|
||||||
"webpack": "^5.102.1",
|
"webpack": "^5.102.1",
|
||||||
@@ -1868,6 +1870,40 @@
|
|||||||
"node": ">=14.17.0"
|
"node": ">=14.17.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@emnapi/core": {
|
||||||
|
"version": "1.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.7.1.tgz",
|
||||||
|
"integrity": "sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@emnapi/wasi-threads": "1.1.0",
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@emnapi/runtime": {
|
||||||
|
"version": "1.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.7.1.tgz",
|
||||||
|
"integrity": "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@emnapi/wasi-threads": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@eslint-community/eslint-utils": {
|
"node_modules/@eslint-community/eslint-utils": {
|
||||||
"version": "4.9.0",
|
"version": "4.9.0",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz",
|
||||||
@@ -2495,6 +2531,19 @@
|
|||||||
"node": ">= 10"
|
"node": ">= 10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@napi-rs/wasm-runtime": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-Fq6DJW+Bb5jaWE69/qOE0D1TUN9+6uWhCeZpdnSBk14pjLcCWR7Q8n49PTSPHazM37JqrsdpEthXy2xn6jWWiA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@emnapi/core": "^1.7.1",
|
||||||
|
"@emnapi/runtime": "^1.7.1",
|
||||||
|
"@tybys/wasm-util": "^0.10.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@nodelib/fs.scandir": {
|
"node_modules/@nodelib/fs.scandir": {
|
||||||
"version": "2.1.5",
|
"version": "2.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
||||||
@@ -2533,6 +2582,289 @@
|
|||||||
"node": ">= 8"
|
"node": ">= 8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@oxc-resolver/binding-android-arm-eabi": {
|
||||||
|
"version": "11.14.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@oxc-resolver/binding-android-arm-eabi/-/binding-android-arm-eabi-11.14.2.tgz",
|
||||||
|
"integrity": "sha512-bTrdE4Z1JcGwPxBOaGbxRbpOHL8/xPVJTTq3/bAZO2euWX0X7uZ+XxsbC+5jUDMhLenqdFokgE1akHEU4xsh6A==",
|
||||||
|
"cpu": [
|
||||||
|
"arm"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"android"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@oxc-resolver/binding-android-arm64": {
|
||||||
|
"version": "11.14.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@oxc-resolver/binding-android-arm64/-/binding-android-arm64-11.14.2.tgz",
|
||||||
|
"integrity": "sha512-bL7/f6YGKUvt/wzpX7ZrHCf1QerotbSG+IIb278AklXuwr6yQdfQHt7KQ8hAWqSYpB2TAbPbAa9HE4wzVyxL9Q==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"android"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@oxc-resolver/binding-darwin-arm64": {
|
||||||
|
"version": "11.14.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@oxc-resolver/binding-darwin-arm64/-/binding-darwin-arm64-11.14.2.tgz",
|
||||||
|
"integrity": "sha512-0zhMhqHz/kC6/UzMC4D9mVBz3/M9UTorbaULfHjAW5b8SUC08H01lZ5fR3OzfDbJI0ByLfiQZmbovuR/pJ8Wzg==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@oxc-resolver/binding-darwin-x64": {
|
||||||
|
"version": "11.14.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@oxc-resolver/binding-darwin-x64/-/binding-darwin-x64-11.14.2.tgz",
|
||||||
|
"integrity": "sha512-kRJBTCQnrGy1mjO+658yMrlGYWEKi6j4JvKt92PRCoeDX0vW4jvzgoJXzZXNxZL1pCY6jIdwsn9u53v4jwpR6g==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@oxc-resolver/binding-freebsd-x64": {
|
||||||
|
"version": "11.14.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@oxc-resolver/binding-freebsd-x64/-/binding-freebsd-x64-11.14.2.tgz",
|
||||||
|
"integrity": "sha512-lpKiya7qPq5EAV5E16SJbxfhNYRCBZATGngn9mZxR2fMLDVbHISDIP2Br8eWA8M1FBJFsOGgBzxDo+42ySSNZQ==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"freebsd"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@oxc-resolver/binding-linux-arm-gnueabihf": {
|
||||||
|
"version": "11.14.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-11.14.2.tgz",
|
||||||
|
"integrity": "sha512-zRIf49IGs4cE9rwpVM3NxlHWquZpwQLebtc9dY9S+4+B+PSLIP95BrzdRfkspwzWC5DKZsOWpvGQjxQiLoUwGA==",
|
||||||
|
"cpu": [
|
||||||
|
"arm"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@oxc-resolver/binding-linux-arm-musleabihf": {
|
||||||
|
"version": "11.14.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-11.14.2.tgz",
|
||||||
|
"integrity": "sha512-sF1fBrcfwoRkv1pR3Kp6D5MuBeHRPxYuzk9rhaun/50vq5nAMOaomkEm4hBbTSubfU86CoBIEbLUQ+1f7NvUVA==",
|
||||||
|
"cpu": [
|
||||||
|
"arm"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@oxc-resolver/binding-linux-arm64-gnu": {
|
||||||
|
"version": "11.14.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-11.14.2.tgz",
|
||||||
|
"integrity": "sha512-O8iTBqz6oxf1k93Rn6WMGGQYo2jV1K81hq4N/Nke3dHE25EIEg2RKQqMz1dFrvVb2RkvD7QaUTEevbx0Lq+4wQ==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@oxc-resolver/binding-linux-arm64-musl": {
|
||||||
|
"version": "11.14.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm64-musl/-/binding-linux-arm64-musl-11.14.2.tgz",
|
||||||
|
"integrity": "sha512-HOfzpS6eUxvdch9UlXCMx2kNJWMNBjUpVJhseqAKDB1dlrfCHgexeLyBX977GLXkq2BtNXKsY3KCryy1QhRSRw==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@oxc-resolver/binding-linux-ppc64-gnu": {
|
||||||
|
"version": "11.14.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-11.14.2.tgz",
|
||||||
|
"integrity": "sha512-0uLG6F2zljUseQAUmlpx/9IdKpiLsSirpmrr8/aGVfiEurIJzC/1lo2HQskkM7e0VVOkXg37AjHUDLE23Fi8SA==",
|
||||||
|
"cpu": [
|
||||||
|
"ppc64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@oxc-resolver/binding-linux-riscv64-gnu": {
|
||||||
|
"version": "11.14.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-11.14.2.tgz",
|
||||||
|
"integrity": "sha512-Pdh0BH/E0YIK7Qg95IsAfQyU9rAoDoFh50R19zCTNfjSnwsoDMGHjmUc82udSfPo2YMnuxA+/+aglxmLQVSu2Q==",
|
||||||
|
"cpu": [
|
||||||
|
"riscv64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@oxc-resolver/binding-linux-riscv64-musl": {
|
||||||
|
"version": "11.14.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-11.14.2.tgz",
|
||||||
|
"integrity": "sha512-3DLQhJ2r53rCH5cudYFqD7nh+Z6ABvld3GjbiqHhT43GMIPw3JcHekC2QunLRNjRr1G544fo1HtjTJz9rCBpyg==",
|
||||||
|
"cpu": [
|
||||||
|
"riscv64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@oxc-resolver/binding-linux-s390x-gnu": {
|
||||||
|
"version": "11.14.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-11.14.2.tgz",
|
||||||
|
"integrity": "sha512-G5BnAOQ5f+RUG1cvlJ4BvV+P7iKLYBv67snqgcfwD5b2N4UwJj32bt4H5JfolocWy4x3qUjEDWTIjHdE+2uZ9w==",
|
||||||
|
"cpu": [
|
||||||
|
"s390x"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@oxc-resolver/binding-linux-x64-gnu": {
|
||||||
|
"version": "11.14.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-x64-gnu/-/binding-linux-x64-gnu-11.14.2.tgz",
|
||||||
|
"integrity": "sha512-VirQAX2PqKrhWtQGsSDEKlPhbgh3ggjT1sWuxLk4iLFwtyA2tLEPXJNAsG0kfAS2+VSA8OyNq16wRpQlMPZ4yA==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@oxc-resolver/binding-linux-x64-musl": {
|
||||||
|
"version": "11.14.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-x64-musl/-/binding-linux-x64-musl-11.14.2.tgz",
|
||||||
|
"integrity": "sha512-q4ORcwMkpzu4EhZyka/s2TuH2QklEHAr/mIQBXzu5BACeBJZIFkICp8qrq4XVnkEZ+XhSFTvBECqfMTT/4LSkA==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@oxc-resolver/binding-openharmony-arm64": {
|
||||||
|
"version": "11.14.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@oxc-resolver/binding-openharmony-arm64/-/binding-openharmony-arm64-11.14.2.tgz",
|
||||||
|
"integrity": "sha512-ZsMIpDCxSFpUM/TwOovX5vZUkV0IukPFnrKTGaeJRuTKXMcJxMiQGCYTwd6y684Y3j55QZqIMkVM9NdCGUX6Kw==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"openharmony"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@oxc-resolver/binding-wasm32-wasi": {
|
||||||
|
"version": "11.14.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@oxc-resolver/binding-wasm32-wasi/-/binding-wasm32-wasi-11.14.2.tgz",
|
||||||
|
"integrity": "sha512-Lvq5ZZNvSjT3Jq/buPFMtp55eNyGlEWsq30tN+yLOfODSo6T6yAJNs6+wXtqu9PiMj4xpVtgXypHtbQ1f+t7kw==",
|
||||||
|
"cpu": [
|
||||||
|
"wasm32"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@napi-rs/wasm-runtime": "^1.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@oxc-resolver/binding-win32-arm64-msvc": {
|
||||||
|
"version": "11.14.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@oxc-resolver/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-11.14.2.tgz",
|
||||||
|
"integrity": "sha512-7w7WHSLSSmkkYHH52QF7TrO0Z8eaIjRUrre5M56hSWRAZupCRzADZxBVMpDnHobZ8MAa2kvvDEfDbERuOK/avQ==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"win32"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@oxc-resolver/binding-win32-ia32-msvc": {
|
||||||
|
"version": "11.14.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@oxc-resolver/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-11.14.2.tgz",
|
||||||
|
"integrity": "sha512-hIrdlWa6tzqyfuWrxUetURBWHttBS+NMbBrGhCupc54NCXFy2ArB+0JOOaLYiI2ShKL5a3uqB7EWxmjzOuDdPQ==",
|
||||||
|
"cpu": [
|
||||||
|
"ia32"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"win32"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@oxc-resolver/binding-win32-x64-msvc": {
|
||||||
|
"version": "11.14.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@oxc-resolver/binding-win32-x64-msvc/-/binding-win32-x64-msvc-11.14.2.tgz",
|
||||||
|
"integrity": "sha512-dP9aV6AZRRpg5mlg0eMuTROtttpQwj3AiegNJ/NNmMSjs+0+aLNcgkWRPhskK3vjTsthH4/+kKLpnQhSxdJkNg==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"win32"
|
||||||
|
]
|
||||||
|
},
|
||||||
"node_modules/@svgr/babel-plugin-add-jsx-attribute": {
|
"node_modules/@svgr/babel-plugin-add-jsx-attribute": {
|
||||||
"version": "8.0.0",
|
"version": "8.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz",
|
||||||
@@ -2853,6 +3185,17 @@
|
|||||||
"node": ">=10.13.0"
|
"node": ">=10.13.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@tybys/wasm-util": {
|
||||||
|
"version": "0.10.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz",
|
||||||
|
"integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/body-parser": {
|
"node_modules/@types/body-parser": {
|
||||||
"version": "1.19.6",
|
"version": "1.19.6",
|
||||||
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz",
|
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz",
|
||||||
@@ -5237,19 +5580,6 @@
|
|||||||
"tslib": "^2.0.3"
|
"tslib": "^2.0.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/dotenv": {
|
|
||||||
"version": "17.2.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.3.tgz",
|
|
||||||
"integrity": "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "BSD-2-Clause",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=12"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://dotenvx.com"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/dunder-proto": {
|
"node_modules/dunder-proto": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
||||||
@@ -6138,6 +6468,16 @@
|
|||||||
"node": ">=0.8.0"
|
"node": ">=0.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/fd-package-json": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fd-package-json/-/fd-package-json-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-jKmm9YtsNXN789RS/0mSzOC1NUq9mkVd65vbSSVsKdjGvYXBuE4oWe2QOEoFeRmJg+lPuZxpmrfFclNhoRMneQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"walk-up-path": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/file-entry-cache": {
|
"node_modules/file-entry-cache": {
|
||||||
"version": "8.0.0",
|
"version": "8.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
|
||||||
@@ -6280,6 +6620,22 @@
|
|||||||
"node": ">= 6"
|
"node": ">= 6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/formatly": {
|
||||||
|
"version": "0.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/formatly/-/formatly-0.3.0.tgz",
|
||||||
|
"integrity": "sha512-9XNj/o4wrRFyhSMJOvsuyMwy8aUfBaZ1VrqHVfohyXf0Sw0e+yfKG+xZaY3arGCOMdwFsqObtzVOc1gU9KiT9w==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"fd-package-json": "^2.0.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"formatly": "bin/index.mjs"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/forwarded": {
|
"node_modules/forwarded": {
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
|
||||||
@@ -7544,17 +7900,26 @@
|
|||||||
"node": ">= 10.13.0"
|
"node": ">= 10.13.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/jiti": {
|
||||||
|
"version": "2.6.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz",
|
||||||
|
"integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"jiti": "lib/jiti-cli.mjs"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/js-tokens": {
|
"node_modules/js-tokens": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||||
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
|
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/js-yaml": {
|
"node_modules/js-yaml": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
|
||||||
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
|
"integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -7654,6 +8019,74 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/knip": {
|
||||||
|
"version": "5.71.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/knip/-/knip-5.71.0.tgz",
|
||||||
|
"integrity": "sha512-hwgdqEJ+7DNJ5jE8BCPu7b57TY7vUwP6MzWYgCgPpg6iPCee/jKPShDNIlFER2koti4oz5xF88VJbKCb4Wl71g==",
|
||||||
|
"dev": true,
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/webpro"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/knip"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"@nodelib/fs.walk": "^1.2.3",
|
||||||
|
"fast-glob": "^3.3.3",
|
||||||
|
"formatly": "^0.3.0",
|
||||||
|
"jiti": "^2.6.0",
|
||||||
|
"js-yaml": "^4.1.1",
|
||||||
|
"minimist": "^1.2.8",
|
||||||
|
"oxc-resolver": "^11.13.2",
|
||||||
|
"picocolors": "^1.1.1",
|
||||||
|
"picomatch": "^4.0.1",
|
||||||
|
"smol-toml": "^1.5.2",
|
||||||
|
"strip-json-comments": "5.0.3",
|
||||||
|
"zod": "^4.1.11"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"knip": "bin/knip.js",
|
||||||
|
"knip-bun": "bin/knip-bun.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18.18.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/node": ">=18",
|
||||||
|
"typescript": ">=5.0.4 <7"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/knip/node_modules/picomatch": {
|
||||||
|
"version": "4.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
|
||||||
|
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/jonschlinkert"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/knip/node_modules/strip-json-comments": {
|
||||||
|
"version": "5.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-5.0.3.tgz",
|
||||||
|
"integrity": "sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.16"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/launch-editor": {
|
"node_modules/launch-editor": {
|
||||||
"version": "2.11.1",
|
"version": "2.11.1",
|
||||||
"resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.11.1.tgz",
|
"resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.11.1.tgz",
|
||||||
@@ -7738,7 +8171,6 @@
|
|||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||||
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
|
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"js-tokens": "^3.0.0 || ^4.0.0"
|
"js-tokens": "^3.0.0 || ^4.0.0"
|
||||||
@@ -7917,6 +8349,16 @@
|
|||||||
"node": "*"
|
"node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/minimist": {
|
||||||
|
"version": "1.2.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
|
||||||
|
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ms": {
|
"node_modules/ms": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||||
@@ -8036,7 +8478,6 @@
|
|||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||||
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
|
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
@@ -8225,6 +8666,38 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/oxc-resolver": {
|
||||||
|
"version": "11.14.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/oxc-resolver/-/oxc-resolver-11.14.2.tgz",
|
||||||
|
"integrity": "sha512-M5fERQKcrCngMZNnk1gRaBbYcqpqXLgMcoqAo7Wpty+KH0I18i03oiy2peUsGJwFaKAEbmo+CtAyhXh08RZ1RA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/Boshen"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"@oxc-resolver/binding-android-arm-eabi": "11.14.2",
|
||||||
|
"@oxc-resolver/binding-android-arm64": "11.14.2",
|
||||||
|
"@oxc-resolver/binding-darwin-arm64": "11.14.2",
|
||||||
|
"@oxc-resolver/binding-darwin-x64": "11.14.2",
|
||||||
|
"@oxc-resolver/binding-freebsd-x64": "11.14.2",
|
||||||
|
"@oxc-resolver/binding-linux-arm-gnueabihf": "11.14.2",
|
||||||
|
"@oxc-resolver/binding-linux-arm-musleabihf": "11.14.2",
|
||||||
|
"@oxc-resolver/binding-linux-arm64-gnu": "11.14.2",
|
||||||
|
"@oxc-resolver/binding-linux-arm64-musl": "11.14.2",
|
||||||
|
"@oxc-resolver/binding-linux-ppc64-gnu": "11.14.2",
|
||||||
|
"@oxc-resolver/binding-linux-riscv64-gnu": "11.14.2",
|
||||||
|
"@oxc-resolver/binding-linux-riscv64-musl": "11.14.2",
|
||||||
|
"@oxc-resolver/binding-linux-s390x-gnu": "11.14.2",
|
||||||
|
"@oxc-resolver/binding-linux-x64-gnu": "11.14.2",
|
||||||
|
"@oxc-resolver/binding-linux-x64-musl": "11.14.2",
|
||||||
|
"@oxc-resolver/binding-openharmony-arm64": "11.14.2",
|
||||||
|
"@oxc-resolver/binding-wasm32-wasi": "11.14.2",
|
||||||
|
"@oxc-resolver/binding-win32-arm64-msvc": "11.14.2",
|
||||||
|
"@oxc-resolver/binding-win32-ia32-msvc": "11.14.2",
|
||||||
|
"@oxc-resolver/binding-win32-x64-msvc": "11.14.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/p-limit": {
|
"node_modules/p-limit": {
|
||||||
"version": "2.3.0",
|
"version": "2.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
|
||||||
@@ -8590,7 +9063,6 @@
|
|||||||
"version": "15.8.1",
|
"version": "15.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
||||||
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
|
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"loose-envify": "^1.4.0",
|
"loose-envify": "^1.4.0",
|
||||||
@@ -8736,7 +9208,6 @@
|
|||||||
"version": "16.13.1",
|
"version": "16.13.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/react-redux": {
|
"node_modules/react-redux": {
|
||||||
@@ -9613,6 +10084,19 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/smol-toml": {
|
||||||
|
"version": "1.5.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.5.2.tgz",
|
||||||
|
"integrity": "sha512-QlaZEqcAH3/RtNyet1IPIYPsEWAaYyXXv1Krsi+1L/QHppjX4Ifm8MQsBISz9vE8cHicIq3clogsheili5vhaQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "BSD-3-Clause",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/cyyynthia"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/snake-case": {
|
"node_modules/snake-case": {
|
||||||
"version": "3.0.4",
|
"version": "3.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz",
|
||||||
@@ -10572,6 +11056,16 @@
|
|||||||
"node": ">= 0.8"
|
"node": ">= 0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/walk-up-path": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/walk-up-path/-/walk-up-path-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-3hu+tD8YzSLGuFYtPRb48vdhKMi0KQV5sn+uWr8+7dMEq/2G/dtLrdDinkLjqq5TIbIBjYJ4Ax/n3YiaW7QM8A==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"engines": {
|
||||||
|
"node": "20 || >=22"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/watchpack": {
|
"node_modules/watchpack": {
|
||||||
"version": "2.4.4",
|
"version": "2.4.4",
|
||||||
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.4.tgz",
|
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.4.tgz",
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
"dev": "webpack serve --mode development --open",
|
"dev": "webpack serve --mode development --open",
|
||||||
"build": "webpack --mode production",
|
"build": "webpack --mode production",
|
||||||
"lint": "eslint src --ext .js,.jsx,.ts,.tsx",
|
"lint": "eslint src --ext .js,.jsx,.ts,.tsx",
|
||||||
"check": "tsc --noEmit && npm run lint",
|
"check": "tsc --noEmit && npx knip && npm run lint",
|
||||||
"test:engine": "node --test tests/workspaceEngine.test.js"
|
"test:engine": "node --test tests/workspaceEngine.test.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
"@tabler/icons-react": "^3.35.0",
|
"@tabler/icons-react": "^3.35.0",
|
||||||
"axios": "^1.13.2",
|
"axios": "^1.13.2",
|
||||||
"pdfjs-dist": "^5.4.394",
|
"pdfjs-dist": "^5.4.394",
|
||||||
|
"prop-types": "^15.8.1",
|
||||||
"react": "^19.2.0",
|
"react": "^19.2.0",
|
||||||
"react-dom": "^19.2.0",
|
"react-dom": "^19.2.0",
|
||||||
"react-redux": "^9.2.0",
|
"react-redux": "^9.2.0",
|
||||||
@@ -25,18 +26,19 @@
|
|||||||
"@babel/preset-env": "^7.28.5",
|
"@babel/preset-env": "^7.28.5",
|
||||||
"@babel/preset-react": "^7.28.5",
|
"@babel/preset-react": "^7.28.5",
|
||||||
"@babel/preset-typescript": "^7.28.5",
|
"@babel/preset-typescript": "^7.28.5",
|
||||||
|
"@eslint/js": "^9.39.1",
|
||||||
"@svgr/webpack": "^8.1.0",
|
"@svgr/webpack": "^8.1.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.46.4",
|
"@typescript-eslint/eslint-plugin": "^8.46.4",
|
||||||
"@typescript-eslint/parser": "^8.18.1",
|
"@typescript-eslint/parser": "^8.18.1",
|
||||||
"babel-loader": "^10.0.0",
|
"babel-loader": "^10.0.0",
|
||||||
"copy-webpack-plugin": "^13.0.1",
|
"copy-webpack-plugin": "^13.0.1",
|
||||||
"css-loader": "^7.1.2",
|
"css-loader": "^7.1.2",
|
||||||
"dotenv": "^17.2.3",
|
|
||||||
"eslint": "^9.39.1",
|
"eslint": "^9.39.1",
|
||||||
"eslint-plugin-react": "^7.37.5",
|
"eslint-plugin-react": "^7.37.5",
|
||||||
"eslint-plugin-react-hooks": "^7.0.1",
|
"eslint-plugin-react-hooks": "^7.0.1",
|
||||||
"globals": "^16.5.0",
|
"globals": "^16.5.0",
|
||||||
"html-webpack-plugin": "^5.6.4",
|
"html-webpack-plugin": "^5.6.4",
|
||||||
|
"knip": "^5.71.0",
|
||||||
"style-loader": "^4.0.0",
|
"style-loader": "^4.0.0",
|
||||||
"typescript": "^5.7.3",
|
"typescript": "^5.7.3",
|
||||||
"webpack": "^5.102.1",
|
"webpack": "^5.102.1",
|
||||||
|
|||||||
@@ -41,5 +41,3 @@ export const useApi = (): ApiContextValue => {
|
|||||||
}
|
}
|
||||||
return ctx;
|
return ctx;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getHttpClient = (): HttpClient => httpClient;
|
|
||||||
|
|||||||
@@ -421,5 +421,3 @@ export const usePanelResizeBindings = (
|
|||||||
isPanelResizing: resizingPanel === panel,
|
isPanelResizing: resizingPanel === panel,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export default PanelManagerContext;
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React, { createContext, useContext } from 'react';
|
import React, { createContext, useContext } from 'react';
|
||||||
import type useWorkspaceSelection from './useWorkspaceSelection';
|
import type { useWorkspaceSelection } from './useWorkspaceSelection';
|
||||||
|
|
||||||
export type WorkspaceSelectionValue = ReturnType<typeof useWorkspaceSelection>;
|
export type WorkspaceSelectionValue = ReturnType<typeof useWorkspaceSelection>;
|
||||||
|
|
||||||
@@ -23,5 +23,3 @@ export const useWorkspaceSelectionContext = () => {
|
|||||||
}
|
}
|
||||||
return context;
|
return context;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default WorkspaceSelectionContext;
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||||
|
|
||||||
export interface DetailDocument {
|
interface DetailDocument {
|
||||||
id?: string;
|
id?: string;
|
||||||
[key: string]: unknown;
|
[key: string]: unknown;
|
||||||
}
|
}
|
||||||
@@ -102,5 +102,3 @@ export const useDetailPanel = ({
|
|||||||
setDetailPanelOpen,
|
setDetailPanelOpen,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export default useDetailPanel;
|
|
||||||
|
|||||||
@@ -285,5 +285,3 @@ export const useDocumentSelection = ({
|
|||||||
configureSelectionEnvironment,
|
configureSelectionEnvironment,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export default useDocumentSelection;
|
|
||||||
|
|||||||
@@ -231,5 +231,3 @@ export const useManagementModals = ({
|
|||||||
activeModal,
|
activeModal,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export default useManagementModals;
|
|
||||||
|
|||||||
@@ -115,5 +115,3 @@ export const useWorkspaceSelection = ({
|
|||||||
inspectFolder,
|
inspectFolder,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export default useWorkspaceSelection;
|
|
||||||
|
|||||||
@@ -7,17 +7,17 @@ import { usePanelManager } from './PanelManagerContext';
|
|||||||
import { FolderManagerProvider } from '../folders/FolderManagerContext';
|
import { FolderManagerProvider } from '../folders/FolderManagerContext';
|
||||||
import type { Identifier } from '../types/identifiers';
|
import type { Identifier } from '../types/identifiers';
|
||||||
|
|
||||||
export type EnsureAssetUrl = (
|
type EnsureAssetUrl = (
|
||||||
docId: Identifier,
|
docId: Identifier,
|
||||||
asset: unknown,
|
asset: unknown,
|
||||||
options?: Record<string, unknown>,
|
options?: Record<string, unknown>,
|
||||||
) => Promise<unknown> | void;
|
) => Promise<unknown> | void;
|
||||||
export type EnsurePreviewData = (docId: Identifier, options?: Record<string, unknown>) => Promise<unknown>;
|
type EnsurePreviewData = (docId: Identifier, options?: Record<string, unknown>) => Promise<unknown>;
|
||||||
export type GetDocumentAsset = (document: unknown, assetType: string) => unknown;
|
type GetDocumentAsset = (document: unknown, assetType: string) => unknown;
|
||||||
export type NotifyApiError = (error: unknown, fallbackMessage?: string) => void;
|
type NotifyApiError = (error: unknown, fallbackMessage?: string) => void;
|
||||||
|
|
||||||
export type DocumentsTableProps = ComponentProps<typeof DocumentsPanel> | null;
|
type DocumentsTableProps = ComponentProps<typeof DocumentsPanel> | null;
|
||||||
export type DetailPanelProps = (ComponentProps<typeof DocumentViewerPanel> & {
|
type DetailPanelProps = (ComponentProps<typeof DocumentViewerPanel> & {
|
||||||
onClose?: () => void;
|
onClose?: () => void;
|
||||||
onOpenPreview?: (args: { documentIds: Array<string> }) => void;
|
onOpenPreview?: (args: { documentIds: Array<string> }) => void;
|
||||||
folderNodes?: Map<Identifier | 'root', unknown>;
|
folderNodes?: Map<Identifier | 'root', unknown>;
|
||||||
@@ -27,7 +27,7 @@ export type DetailPanelProps = (ComponentProps<typeof DocumentViewerPanel> & {
|
|||||||
) => Promise<void>;
|
) => Promise<void>;
|
||||||
}) | null;
|
}) | null;
|
||||||
|
|
||||||
export type WorkspaceSurface = { content: ReactNode; detail?: ReactNode | null; detailMode?: 'overlay' | 'inline' | null } | null;
|
type WorkspaceSurface = { content: ReactNode; detail?: ReactNode | null; detailMode?: 'overlay' | 'inline' | null } | null;
|
||||||
|
|
||||||
export interface UseWorkspaceSurfaceArgs {
|
export interface UseWorkspaceSurfaceArgs {
|
||||||
sidebarHidden?: boolean;
|
sidebarHidden?: boolean;
|
||||||
@@ -44,7 +44,7 @@ export interface UseWorkspaceSurfaceArgs {
|
|||||||
closeDocumentPreview?: () => void;
|
closeDocumentPreview?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UseWorkspaceSurfaceResult {
|
interface UseWorkspaceSurfaceResult {
|
||||||
surface: WorkspaceSurface;
|
surface: WorkspaceSurface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
export type AppShellContextValue = Record<string, unknown>;
|
type AppShellContextValue = Record<string, unknown>;
|
||||||
|
|
||||||
export const AppShellContext = React.createContext<AppShellContextValue | null>(null);
|
export const AppShellContext = React.createContext<AppShellContextValue | null>(null);
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ import type { DocumentVersion, Document } from './types/documents';
|
|||||||
|
|
||||||
type Nullable<T> = T | null;
|
type Nullable<T> = T | null;
|
||||||
|
|
||||||
export type { Asset, DocumentVersion as DocumentVersionLike, Document };
|
export type { Asset };
|
||||||
|
|
||||||
export const resolveAssetExpiresAt = (asset?: { download?: { expires_at: number } | null } | null): number | null =>
|
const resolveAssetExpiresAt = (asset?: { download?: { expires_at: number } | null } | null): number | null =>
|
||||||
asset?.download?.expires_at ?? null;
|
asset?.download?.expires_at ?? null;
|
||||||
|
|
||||||
export const resolveAssetUrl = (asset?: { download?: { url: string } | null } | null): string | null =>
|
export const resolveAssetUrl = (asset?: { download?: { url: string } | null } | null): string | null =>
|
||||||
@@ -20,7 +20,7 @@ export type EnsureAssetUrl = (
|
|||||||
|
|
||||||
export type GetAsset = (document: Document, assetType: string) => Nullable<Asset>;
|
export type GetAsset = (document: Document, assetType: string) => Nullable<Asset>;
|
||||||
|
|
||||||
export const getAssetFromGroup = (
|
const getAssetFromGroup = (
|
||||||
assets?: Asset[] | Record<string, Asset> | null,
|
assets?: Asset[] | Record<string, Asset> | null,
|
||||||
assetType: string = '',
|
assetType: string = '',
|
||||||
): Nullable<Asset> => {
|
): Nullable<Asset> => {
|
||||||
|
|||||||
@@ -1,46 +1,3 @@
|
|||||||
export const DB_NAME = 'papercrate_desk';
|
export const DB_NAME = 'papercrate_desk';
|
||||||
export const DB_VERSION = 1;
|
export const DB_VERSION = 1;
|
||||||
export const LAYOUT_STORE = 'layouts';
|
export const LAYOUT_STORE = 'layouts';
|
||||||
|
|
||||||
export const CLICK_ACTIONS = {
|
|
||||||
selectSingle: 'selectSingle',
|
|
||||||
openDetail: 'openDetail',
|
|
||||||
addCard: 'addCard',
|
|
||||||
addStack: 'addStack',
|
|
||||||
none: 'none',
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const DRAG_ACTIONS = {
|
|
||||||
dragSelectSingle: 'dragSelectSingle',
|
|
||||||
dragSelection: 'dragSelection',
|
|
||||||
dragSelectStack: 'dragSelectStack',
|
|
||||||
none: 'none',
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const STACK_HIT_EPSILON = 4;
|
|
||||||
export const POINTER_DRAG_THRESHOLD_SQUARED = 16;
|
|
||||||
export const LONG_PRESS_DURATION_MS = 450;
|
|
||||||
|
|
||||||
export const DRAG_HYSTERESIS_PX = 4;
|
|
||||||
export const DRAG_HYSTERESIS_SQUARED = DRAG_HYSTERESIS_PX * DRAG_HYSTERESIS_PX;
|
|
||||||
export const EDGE_COLLISION_THRESHOLD = 0.5;
|
|
||||||
|
|
||||||
export const DEBUG_DRAG = false;
|
|
||||||
export const DEBUG_FOCUS = false;
|
|
||||||
|
|
||||||
export const DESK_CANVAS_PADDING = 24;
|
|
||||||
export const DESK_ROTATION_RANGE = 7;
|
|
||||||
export const DESK_DEFAULT_CANVAS_WIDTH = 1024;
|
|
||||||
export const DESK_DEFAULT_CANVAS_HEIGHT = 680;
|
|
||||||
export const DESK_CARD_MIN = 240;
|
|
||||||
export const DESK_CARD_MAX = 340;
|
|
||||||
export const CARD_PAGE_WEIGHT_GRAMS = 5;
|
|
||||||
export const CARD_BASE_WEIGHT_GRAMS = 30;
|
|
||||||
export const DEFAULT_Z_START = 10;
|
|
||||||
export const MIN_TIMESTEP = 1 / 120;
|
|
||||||
export const MAX_TIMESTEP = 1 / 20;
|
|
||||||
export const MAX_DYNAMIC_ROTATION = 7;
|
|
||||||
export const MAX_ANGULAR_VELOCITY = 210;
|
|
||||||
export const ANGULAR_DAMPING = 10;
|
|
||||||
export const TORQUE_TO_ACCELERATION = 0.007;
|
|
||||||
export const SETTLE_ANGULAR_VELOCITY = 0.45;
|
|
||||||
|
|||||||
@@ -3,19 +3,19 @@ import ApiTokensSection from '../settings/sections/ApiTokensSection';
|
|||||||
import CapabilitySetsSection from '../settings/sections/CapabilitySetsSection';
|
import CapabilitySetsSection from '../settings/sections/CapabilitySetsSection';
|
||||||
import PasskeysSection from '../settings/sections/PasskeysSection';
|
import PasskeysSection from '../settings/sections/PasskeysSection';
|
||||||
|
|
||||||
export const PASSKEYS_SECTION: SettingsSectionConfig = {
|
const PASSKEYS_SECTION: SettingsSectionConfig = {
|
||||||
id: 'passkeys',
|
id: 'passkeys',
|
||||||
label: 'Passkeys',
|
label: 'Passkeys',
|
||||||
component: PasskeysSection,
|
component: PasskeysSection,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const API_TOKENS_SECTION: SettingsSectionConfig = {
|
const API_TOKENS_SECTION: SettingsSectionConfig = {
|
||||||
id: 'apiTokens',
|
id: 'apiTokens',
|
||||||
label: 'API tokens',
|
label: 'API tokens',
|
||||||
component: ApiTokensSection,
|
component: ApiTokensSection,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const CAPABILITY_SETS_SECTION: SettingsSectionConfig = {
|
const CAPABILITY_SETS_SECTION: SettingsSectionConfig = {
|
||||||
id: 'capabilitySets',
|
id: 'capabilitySets',
|
||||||
label: 'Capability sets',
|
label: 'Capability sets',
|
||||||
component: CapabilitySetsSection,
|
component: CapabilitySetsSection,
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ export const SIDEBAR_COLLAPSE_STORAGE_KEY = 'papercrate_sidebar_collapsed';
|
|||||||
export const THEME_STORAGE_KEY = 'papercrate_theme_settings';
|
export const THEME_STORAGE_KEY = 'papercrate_theme_settings';
|
||||||
export const DEFAULT_NEUTRAL_HUE = 29;
|
export const DEFAULT_NEUTRAL_HUE = 29;
|
||||||
export const DEFAULT_NEUTRAL_CHROMA = 0.44;
|
export const DEFAULT_NEUTRAL_CHROMA = 0.44;
|
||||||
export const DEFAULT_NEUTRAL_CONTRAST = 0.56;
|
|
||||||
export const DEFAULT_THEME_MODE = 'system';
|
export const DEFAULT_THEME_MODE = 'system';
|
||||||
export const THEME_MODES = ['system', 'light', 'dark'];
|
export const THEME_MODES = ['system', 'light', 'dark'];
|
||||||
export const THEME_MODE_LABELS = {
|
export const THEME_MODE_LABELS = {
|
||||||
|
|||||||
@@ -8,5 +8,3 @@ export const VIEW_MODE_STORAGE_KEY = 'papercrate_view_mode';
|
|||||||
export const SORT_FIELD_STORAGE_KEY = 'papercrate_sort_field';
|
export const SORT_FIELD_STORAGE_KEY = 'papercrate_sort_field';
|
||||||
export const SORT_DIRECTION_STORAGE_KEY = 'papercrate_sort_direction';
|
export const SORT_DIRECTION_STORAGE_KEY = 'papercrate_sort_direction';
|
||||||
export const INCLUDE_DESCENDANTS_STORAGE_KEY = 'papercrate_include_descendants';
|
export const INCLUDE_DESCENDANTS_STORAGE_KEY = 'papercrate_include_descendants';
|
||||||
|
|
||||||
export const ROOT_FOLDER_LABEL = DEFAULT_FOLDER_NAME;
|
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ import React, { createContext, useContext, useCallback } from 'react';
|
|||||||
import type { Document } from '../types/documents';
|
import type { Document } from '../types/documents';
|
||||||
import type { Identifier } from '../types/identifiers';
|
import type { Identifier } from '../types/identifiers';
|
||||||
|
|
||||||
export type DocumentOpenTarget = 'preview' | 'sidepanel' | 'viewer';
|
type DocumentOpenTarget = 'preview' | 'sidepanel' | 'viewer';
|
||||||
|
|
||||||
export interface DocumentOpenContextValue {
|
interface DocumentOpenContextValue {
|
||||||
openDocument: (doc: Document, target?: DocumentOpenTarget) => void;
|
openDocument: (doc: Document, target?: DocumentOpenTarget) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import React, { createContext, useContext, useState, useCallback, useEffect, use
|
|||||||
|
|
||||||
export type ToastVariant = 'info' | 'success' | 'error';
|
export type ToastVariant = 'info' | 'success' | 'error';
|
||||||
|
|
||||||
export interface ToastMessage {
|
interface ToastMessage {
|
||||||
id: string;
|
id: string;
|
||||||
message: string;
|
message: string;
|
||||||
variant: ToastVariant;
|
variant: ToastVariant;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ interface CorrespondentUsage {
|
|||||||
[key: string]: unknown;
|
[key: string]: unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CorrespondentEntry {
|
interface CorrespondentEntry {
|
||||||
id?: string;
|
id?: string;
|
||||||
name?: string;
|
name?: string;
|
||||||
usage?: CorrespondentUsage;
|
usage?: CorrespondentUsage;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import React, {
|
|||||||
import { LayoutStore, LayoutCard } from './LayoutSystem';
|
import { LayoutStore, LayoutCard } from './LayoutSystem';
|
||||||
import DesktopDocumentCard from './DesktopDocumentCard';
|
import DesktopDocumentCard from './DesktopDocumentCard';
|
||||||
import usePreviewMetadata from './hooks/usePreviewMetadata';
|
import usePreviewMetadata from './hooks/usePreviewMetadata';
|
||||||
import useDeskTagInteractions from './tags/useDeskTagInteractions';
|
import { useDeskTagInteractions } from './tags/useDeskTagInteractions';
|
||||||
import '../styles/workspace/workspace-layout.css';
|
import '../styles/workspace/workspace-layout.css';
|
||||||
import '../styles/workspace/workspace-items.css';
|
import '../styles/workspace/workspace-items.css';
|
||||||
import '../styles/workspace/workspace-cards.css';
|
import '../styles/workspace/workspace-cards.css';
|
||||||
@@ -32,7 +32,7 @@ const computeFallbackCardSize = (_doc: Document, defaultSize: number = 200): Doc
|
|||||||
return { width: size, height: size, source: 'fallback' };
|
return { width: size, height: size, source: 'fallback' };
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface DesktopWorkspaceProps {
|
interface DesktopWorkspaceProps {
|
||||||
entries: DocumentsListEntry[];
|
entries: DocumentsListEntry[];
|
||||||
ensureAssetUrl?: (...args: any[]) => Promise<unknown>;
|
ensureAssetUrl?: (...args: any[]) => Promise<unknown>;
|
||||||
getDocumentAsset?: (...args: any[]) => unknown;
|
getDocumentAsset?: (...args: any[]) => unknown;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { constrainDimensions, getInitialPosition, CONTAINER_PADDING } from './ut
|
|||||||
import { fetchLayoutRecords, upsertLayoutRecords } from './db';
|
import { fetchLayoutRecords, upsertLayoutRecords } from './db';
|
||||||
import { CardPhysics } from './CardPhysics';
|
import { CardPhysics } from './CardPhysics';
|
||||||
|
|
||||||
export interface LayoutCardState {
|
interface LayoutCardState {
|
||||||
id: string;
|
id: string;
|
||||||
x: number;
|
x: number;
|
||||||
y: number;
|
y: number;
|
||||||
|
|||||||
@@ -47,26 +47,6 @@ const requestToPromise = <T>(request: IDBRequest<T>, defaultValue: T): Promise<T
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const iterateCursor = (request: IDBRequest<IDBCursorWithValue | null>, iteratee: (cursor: IDBCursorWithValue) => void) =>
|
|
||||||
new Promise<void>((resolve, reject) => {
|
|
||||||
request.onsuccess = (event) => {
|
|
||||||
const cursor = (event.target as IDBRequest<IDBCursorWithValue>).result;
|
|
||||||
if (!cursor) {
|
|
||||||
resolve();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
iteratee(cursor);
|
|
||||||
cursor.continue();
|
|
||||||
} catch (error) {
|
|
||||||
reject(error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
request.onerror = () => {
|
|
||||||
reject(request.error || new Error('IndexedDB cursor failed'));
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
const transactionComplete = (transaction: IDBTransaction) =>
|
const transactionComplete = (transaction: IDBTransaction) =>
|
||||||
new Promise<void>((resolve, reject) => {
|
new Promise<void>((resolve, reject) => {
|
||||||
transaction.oncomplete = () => {
|
transaction.oncomplete = () => {
|
||||||
@@ -182,36 +162,3 @@ export const upsertLayoutRecords = async ({
|
|||||||
console.warn('[desk] Failed to upsert layout records', error);
|
console.warn('[desk] Failed to upsert layout records', error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const deleteTenantLayouts = async (tenantId?: TenantId) => {
|
|
||||||
if (!tenantId) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
await withStore('readwrite', (store) => {
|
|
||||||
const index = store.index('tenantIdx');
|
|
||||||
const request = index.openCursor(tenantId);
|
|
||||||
return iterateCursor(request, (cursor) => {
|
|
||||||
cursor.delete();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
console.warn('[desk] Failed to clean tenant layouts', error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const closeDeskDatabase = (): void => {
|
|
||||||
if (!currentDbPromise.value) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
currentDbPromise.value = currentDbPromise.value.then((db) => {
|
|
||||||
if (db) {
|
|
||||||
try {
|
|
||||||
db.close();
|
|
||||||
} catch (error) {
|
|
||||||
console.warn('[desk] Failed to close IndexedDB', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -239,5 +239,3 @@ export const useDeskTagInteractions = ({
|
|||||||
handleCanvasDrop,
|
handleCanvasDrop,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export default useDeskTagInteractions;
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { NBSP } from '../constants/ui';
|
import { NBSP } from '../constants/ui';
|
||||||
|
|
||||||
export interface CorrespondentLinkEntry {
|
interface CorrespondentLinkEntry {
|
||||||
id?: string | null;
|
id?: string | null;
|
||||||
name?: string | null;
|
name?: string | null;
|
||||||
key?: string;
|
key?: string;
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ const normalizeQuickAddOption = (option?: QuickAddOption | string | null): Quick
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const TagSection: React.FC<TagSectionProps> = ({
|
const TagSection: React.FC<TagSectionProps> = ({
|
||||||
tags = [],
|
tags = [],
|
||||||
onRemove,
|
onRemove,
|
||||||
onAdd,
|
onAdd,
|
||||||
@@ -292,7 +292,7 @@ export const TagSection: React.FC<TagSectionProps> = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const CorrespondentSection: React.FC<CorrespondentSectionProps> = ({
|
const CorrespondentSection: React.FC<CorrespondentSectionProps> = ({
|
||||||
entries = [],
|
entries = [],
|
||||||
onRemove,
|
onRemove,
|
||||||
onAdd,
|
onAdd,
|
||||||
|
|||||||
@@ -187,4 +187,3 @@ const DocumentThumbnailImage = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default DocumentThumbnailImage;
|
export default DocumentThumbnailImage;
|
||||||
export { DEFAULT_THUMBNAIL_SIZE };
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { shallowEqual } from 'react-redux';
|
import { shallowEqual } from 'react-redux';
|
||||||
import type { DocumentId } from '../types/identifiers';
|
import type { DocumentId } from '../types/identifiers';
|
||||||
|
|
||||||
export type ManagedDocument = { id?: DocumentId | null } & Record<string, unknown>;
|
type ManagedDocument = { id?: DocumentId | null } & Record<string, unknown>;
|
||||||
|
|
||||||
type FetchDocument = (id: DocumentId) => Promise<unknown>;
|
type FetchDocument = (id: DocumentId) => Promise<unknown>;
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import React, { CSSProperties, useCallback, useEffect, useMemo, useRef, useState
|
|||||||
import useFloatingMenu from '../ui/useFloatingMenu';
|
import useFloatingMenu from '../ui/useFloatingMenu';
|
||||||
import { CheckIcon, CircleDashedCheckIcon, PlusIcon } from '../ui/icons';
|
import { CheckIcon, CircleDashedCheckIcon, PlusIcon } from '../ui/icons';
|
||||||
|
|
||||||
export type AssignmentState = 'all' | 'partial' | 'none';
|
type AssignmentState = 'all' | 'partial' | 'none';
|
||||||
|
|
||||||
export interface SelectionAssignmentMenuItem {
|
export interface SelectionAssignmentMenuItem {
|
||||||
id?: string;
|
id?: string;
|
||||||
@@ -24,7 +24,7 @@ export interface NormalizedSelectionAssignmentItem {
|
|||||||
payload: unknown;
|
payload: unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SelectionAssignmentMenuProps {
|
interface SelectionAssignmentMenuProps {
|
||||||
label: React.ReactNode;
|
label: React.ReactNode;
|
||||||
items?: SelectionAssignmentMenuItem[];
|
items?: SelectionAssignmentMenuItem[];
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ interface BulkCorrespondentRemoveArgs {
|
|||||||
documentIds: DocumentId[];
|
documentIds: DocumentId[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SelectionFloatingActionsProps {
|
interface SelectionFloatingActionsProps {
|
||||||
selectionCount?: number;
|
selectionCount?: number;
|
||||||
selectedDocumentIds?: SelectedIdList;
|
selectedDocumentIds?: SelectedIdList;
|
||||||
selectedFolderIds?: SelectedIdList;
|
selectedFolderIds?: SelectedIdList;
|
||||||
@@ -487,7 +487,7 @@ const SelectionFloatingActions: React.FC<SelectionFloatingActionsProps> = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export type SelectionFloatingPanelProps = Omit<SelectionFloatingActionsProps, 'selectedDocumentIds' | 'selectedFolderIds' | 'selectionCount'>;
|
type SelectionFloatingPanelProps = Omit<SelectionFloatingActionsProps, 'selectedDocumentIds' | 'selectedFolderIds' | 'selectionCount'>;
|
||||||
|
|
||||||
export const SelectionFloatingPanel: React.FC<SelectionFloatingPanelProps> = ({ onClearSelection, ...rest }) => {
|
export const SelectionFloatingPanel: React.FC<SelectionFloatingPanelProps> = ({ onClearSelection, ...rest }) => {
|
||||||
const { selectedDocumentIds, selectedFolderIds, clearSelection } = useWorkspaceSelectionContext();
|
const { selectedDocumentIds, selectedFolderIds, clearSelection } = useWorkspaceSelectionContext();
|
||||||
@@ -512,6 +512,3 @@ export const SelectionFloatingPanel: React.FC<SelectionFloatingPanelProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export default SelectionFloatingActions;
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import {
|
|||||||
import type { FolderTreeNode } from '../lib/apiTypes';
|
import type { FolderTreeNode } from '../lib/apiTypes';
|
||||||
import type { DocumentId } from '../types/identifiers';
|
import type { DocumentId } from '../types/identifiers';
|
||||||
|
|
||||||
export interface SelectionFolderMenuProps {
|
interface SelectionFolderMenuProps {
|
||||||
label: React.ReactNode;
|
label: React.ReactNode;
|
||||||
folderTree?: FolderTreeNode[];
|
folderTree?: FolderTreeNode[];
|
||||||
onSelectFolder?: (folderId: DocumentId | null) => Promise<void> | void;
|
onSelectFolder?: (folderId: DocumentId | null) => Promise<void> | void;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React, { type DragEvent } from 'react';
|
import React, { type DragEvent } from 'react';
|
||||||
|
|
||||||
export interface EntryShellHandlers {
|
interface EntryShellHandlers {
|
||||||
onClick: (event: React.MouseEvent) => void;
|
onClick: (event: React.MouseEvent) => void;
|
||||||
onDoubleClick: (event: React.MouseEvent) => void;
|
onDoubleClick: (event: React.MouseEvent) => void;
|
||||||
onDragStart: (event: DragEvent<HTMLElement>) => void;
|
onDragStart: (event: DragEvent<HTMLElement>) => void;
|
||||||
|
|||||||
@@ -1,31 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
interface IconSizeSliderProps {
|
|
||||||
scale: number;
|
|
||||||
onChange: (scale: number) => void;
|
|
||||||
min?: number;
|
|
||||||
max?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
const IconSizeSlider: React.FC<IconSizeSliderProps> = ({
|
|
||||||
scale,
|
|
||||||
onChange,
|
|
||||||
min = 0.5,
|
|
||||||
max = 2,
|
|
||||||
}) => {
|
|
||||||
return (
|
|
||||||
<div className="icon-size-slider">
|
|
||||||
<input
|
|
||||||
type="range"
|
|
||||||
className="icon-size-slider__input"
|
|
||||||
min={min}
|
|
||||||
max={max}
|
|
||||||
step="any"
|
|
||||||
value={scale}
|
|
||||||
onChange={(e) => onChange(parseFloat(e.target.value))}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default IconSizeSlider;
|
|
||||||
@@ -35,5 +35,3 @@ export const useDocumentsFilter = (): DocumentsFilterValue => {
|
|||||||
}
|
}
|
||||||
return context;
|
return context;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default DocumentsFilterContext;
|
|
||||||
|
|||||||
@@ -1,12 +1,6 @@
|
|||||||
export interface CorrespondentReference {
|
|
||||||
id?: string | null;
|
|
||||||
name?: string | null;
|
|
||||||
key?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
import type { Document } from '../types/documents';
|
import type { Document } from '../types/documents';
|
||||||
|
|
||||||
export interface ResolvedCorrespondent {
|
interface ResolvedCorrespondent {
|
||||||
id?: string | null;
|
id?: string | null;
|
||||||
name: string;
|
name: string;
|
||||||
key: string;
|
key: string;
|
||||||
@@ -44,5 +38,3 @@ export const resolveCorrespondents = (doc?: Document | null): ResolvedCorrespond
|
|||||||
|
|
||||||
return results;
|
return results;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default resolveCorrespondents;
|
|
||||||
|
|||||||
@@ -6,8 +6,6 @@ import type {
|
|||||||
} from '../utils/ocr';
|
} from '../utils/ocr';
|
||||||
import type { Document } from '../types/documents';
|
import type { Document } from '../types/documents';
|
||||||
|
|
||||||
export type { Document };
|
|
||||||
|
|
||||||
const asyncFalse = async () => false;
|
const asyncFalse = async () => false;
|
||||||
|
|
||||||
const resolveDocumentDownloadHref = (document?: Document | null): string | null => {
|
const resolveDocumentDownloadHref = (document?: Document | null): string | null => {
|
||||||
@@ -82,8 +80,3 @@ export const createDocumentActionState = ({
|
|||||||
openOcr,
|
openOcr,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const documentActionsTestExports = {
|
|
||||||
resolveDocumentDownloadHref,
|
|
||||||
hasDocumentTextContentAsset,
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ interface DescribeSummaryOptions {
|
|||||||
formatDateTime?: typeof defaultFormatDateTime;
|
formatDateTime?: typeof defaultFormatDateTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type DocumentSummaryRowType = 'text' | 'editable-title' | 'editable-issued' | 'tags' | 'correspondents' | 'folder';
|
type DocumentSummaryRowType = 'text' | 'editable-title' | 'editable-issued' | 'tags' | 'correspondents' | 'folder';
|
||||||
|
|
||||||
export interface DocumentSummaryRow {
|
export interface DocumentSummaryRow {
|
||||||
key: string;
|
key: string;
|
||||||
@@ -17,7 +17,7 @@ export interface DocumentSummaryRow {
|
|||||||
kind?: DocumentSummaryRowType;
|
kind?: DocumentSummaryRowType;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type DocumentSummary = DocumentSummaryRow[];
|
type DocumentSummary = DocumentSummaryRow[];
|
||||||
|
|
||||||
const coercePageCount = (metadata?: { page_count?: number | string | null } | null): number | null => {
|
const coercePageCount = (metadata?: { page_count?: number | string | null } | null): number | null => {
|
||||||
const raw = metadata?.page_count;
|
const raw = metadata?.page_count;
|
||||||
|
|||||||
@@ -2,20 +2,20 @@ import { useMemo } from 'react';
|
|||||||
import type { WorkspaceSelectionValue } from '../../app/WorkspaceSelectionContext';
|
import type { WorkspaceSelectionValue } from '../../app/WorkspaceSelectionContext';
|
||||||
import type { Identifier } from '../../types/identifiers';
|
import type { Identifier } from '../../types/identifiers';
|
||||||
|
|
||||||
export interface Breadcrumb {
|
interface Breadcrumb {
|
||||||
id?: Identifier;
|
id?: Identifier;
|
||||||
name?: string;
|
name?: string;
|
||||||
label?: string;
|
label?: string;
|
||||||
title?: string;
|
title?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FolderClickHandlers {
|
interface FolderClickHandlers {
|
||||||
onDrop?: (...args: unknown[]) => void;
|
onDrop?: (...args: unknown[]) => void;
|
||||||
onDragOver?: (...args: unknown[]) => void;
|
onDragOver?: (...args: unknown[]) => void;
|
||||||
onDragLeave?: (...args: unknown[]) => void;
|
onDragLeave?: (...args: unknown[]) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UseDocumentsPanelPropsArgs {
|
interface UseDocumentsPanelPropsArgs {
|
||||||
currentFolderName?: string | null;
|
currentFolderName?: string | null;
|
||||||
breadcrumbs?: Breadcrumb[];
|
breadcrumbs?: Breadcrumb[];
|
||||||
refreshCurrentFolder?: () => void | Promise<void>;
|
refreshCurrentFolder?: () => void | Promise<void>;
|
||||||
@@ -65,8 +65,6 @@ export interface UseDocumentsPanelPropsArgs {
|
|||||||
selectionValue: WorkspaceSelectionValue;
|
selectionValue: WorkspaceSelectionValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type DocumentsPanelProps = ReturnType<typeof useDocumentsPanelProps>;
|
|
||||||
|
|
||||||
const useDocumentsPanelProps = (props: UseDocumentsPanelPropsArgs) => {
|
const useDocumentsPanelProps = (props: UseDocumentsPanelPropsArgs) => {
|
||||||
const {
|
const {
|
||||||
currentFolderName,
|
currentFolderName,
|
||||||
|
|||||||
@@ -51,43 +51,43 @@ export const createDocumentsTableHeaderActions = ({
|
|||||||
|
|
||||||
const includeDescendantsToggle = isFilterActive && onToggleIncludeDescendants
|
const includeDescendantsToggle = isFilterActive && onToggleIncludeDescendants
|
||||||
? (
|
? (
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="icon-button documents-toolbar__toggle"
|
className="icon-button documents-toolbar__toggle"
|
||||||
onClick={onToggleIncludeDescendants}
|
onClick={onToggleIncludeDescendants}
|
||||||
aria-pressed={!includeDescendants}
|
aria-pressed={!includeDescendants}
|
||||||
aria-label={includeDescendants ? 'Include subfolders' : 'Limit to current folder'}
|
aria-label={includeDescendants ? 'Include subfolders' : 'Limit to current folder'}
|
||||||
title={includeDescendants
|
title={includeDescendants
|
||||||
? 'Including subfolders. Click to limit the search to the current folder.'
|
? 'Including subfolders. Click to limit the search to the current folder.'
|
||||||
: 'Limiting to the current folder. Click to include subfolders again.'}
|
: 'Limiting to the current folder. Click to include subfolders again.'}
|
||||||
>
|
>
|
||||||
{includeDescendants ? <FoldersIcon /> : <FoldersOffIcon />}
|
{includeDescendants ? <FoldersIcon /> : <FoldersOffIcon />}
|
||||||
</button>
|
</button>
|
||||||
)
|
)
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
const sortControls = onSortFieldChange
|
const sortControls = onSortFieldChange
|
||||||
? (
|
? (
|
||||||
<div className="documents-actions__sort-group">
|
<div className="documents-actions__sort-group">
|
||||||
<SortFieldQuickMenu sortField={sortField} onChange={onSortFieldChange} />
|
<SortFieldQuickMenu sortField={sortField} onChange={onSortFieldChange} />
|
||||||
{onSortDirectionToggle ? (
|
{onSortDirectionToggle ? (
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="icon-button documents-toolbar__toggle documents-sort__direction"
|
className="icon-button documents-toolbar__toggle documents-sort__direction"
|
||||||
onClick={onSortDirectionToggle}
|
onClick={onSortDirectionToggle}
|
||||||
aria-pressed={sortDirectionIsDesc}
|
aria-pressed={sortDirectionIsDesc}
|
||||||
aria-label={sortDirectionIsDesc ? 'Sort descending' : 'Sort ascending'}
|
aria-label={sortDirectionIsDesc ? 'Sort descending' : 'Sort ascending'}
|
||||||
title={sortDirectionTitle}
|
title={sortDirectionTitle}
|
||||||
>
|
>
|
||||||
{sortDirectionIsDesc ? (
|
{sortDirectionIsDesc ? (
|
||||||
<SortDescendingLettersIcon size={18} />
|
<SortDescendingLettersIcon size={18} />
|
||||||
) : (
|
) : (
|
||||||
<SortAscendingLettersIcon size={18} />
|
<SortAscendingLettersIcon size={18} />
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -152,5 +152,3 @@ export const createDocumentsTableHeaderActions = ({
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default createDocumentsTableHeaderActions;
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ const serializePayload = (payload: TagPayload): string | null => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const createTagTransferPayload = (
|
const createTagTransferPayload = (
|
||||||
tag?: TagLike | null,
|
tag?: TagLike | null,
|
||||||
sourceDocId: DocumentId | null = null,
|
sourceDocId: DocumentId | null = null,
|
||||||
): TagPayload | null => {
|
): TagPayload | null => {
|
||||||
@@ -65,7 +65,7 @@ export const writeTagTransferData = (
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const readTagTransferData = (dataTransfer?: DataTransfer | null): string | null => {
|
const readTagTransferData = (dataTransfer?: DataTransfer | null): string | null => {
|
||||||
if (!dataTransfer) {
|
if (!dataTransfer) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -133,4 +133,3 @@ export const isTagTransferEvent = (event?: DragEventLike | null): boolean => {
|
|||||||
return TAG_MIME_TYPES.some((type) => typeList.includes(type));
|
return TAG_MIME_TYPES.some((type) => typeList.includes(type));
|
||||||
};
|
};
|
||||||
|
|
||||||
export { TAG_MIME_TYPES };
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { createDocumentEntryKey, createFolderEntryKey } from '../app/entryKey';
|
import { createDocumentEntryKey, createFolderEntryKey } from '../app/entryKey';
|
||||||
|
|
||||||
export type PointerEventLike = MouseEvent | PointerEvent;
|
type PointerEventLike = MouseEvent | PointerEvent;
|
||||||
|
|
||||||
export const isPointerModifierEvent = (event?: PointerEventLike | null): boolean =>
|
export const isPointerModifierEvent = (event?: PointerEventLike | null): boolean =>
|
||||||
Boolean(event && (event.shiftKey || event.metaKey || event.ctrlKey || event.altKey));
|
Boolean(event && (event.shiftKey || event.metaKey || event.ctrlKey || event.altKey));
|
||||||
@@ -17,9 +17,9 @@ export const isPrimaryPointerEvent = (event?: PointerEventLike | null): boolean
|
|||||||
return type === 'click' || type === 'pointerdown' || type === 'pointerup';
|
return type === 'click' || type === 'pointerdown' || type === 'pointerup';
|
||||||
};
|
};
|
||||||
|
|
||||||
export type EntryType = 'document' | 'folder';
|
type EntryType = 'document' | 'folder';
|
||||||
|
|
||||||
export interface WorkspaceEntry {
|
interface WorkspaceEntry {
|
||||||
id: string;
|
id: string;
|
||||||
key?: string;
|
key?: string;
|
||||||
type: EntryType;
|
type: EntryType;
|
||||||
@@ -31,7 +31,7 @@ interface UseEntryPointerOptions {
|
|||||||
onDocumentActivate?: (id: string, metadata?: EntryPointerMetadata) => void;
|
onDocumentActivate?: (id: string, metadata?: EntryPointerMetadata) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface EntryPointerMetadata {
|
interface EntryPointerMetadata {
|
||||||
modifierClick: boolean;
|
modifierClick: boolean;
|
||||||
primaryClick: boolean;
|
primaryClick: boolean;
|
||||||
rowKey: string;
|
rowKey: string;
|
||||||
@@ -72,5 +72,3 @@ export const useEntryPointer = ({
|
|||||||
},
|
},
|
||||||
[onSelectEntry, onDocumentActivate],
|
[onSelectEntry, onDocumentActivate],
|
||||||
);
|
);
|
||||||
|
|
||||||
export default useEntryPointer;
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { DEFAULT_FOLDER_NAME } from '../app/workspaceUtils';
|
|||||||
|
|
||||||
type FolderId = string | null;
|
type FolderId = string | null;
|
||||||
|
|
||||||
export interface FolderManager {
|
interface FolderManager {
|
||||||
getNameSync: (folderId: FolderId) => string | null;
|
getNameSync: (folderId: FolderId) => string | null;
|
||||||
resolveName: (folderId: FolderId) => Promise<string>;
|
resolveName: (folderId: FolderId) => Promise<string>;
|
||||||
}
|
}
|
||||||
@@ -55,5 +55,3 @@ export const FolderManagerProvider: React.FC<FolderManagerProviderProps> = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const useFolderManager = (): FolderManager => useContext(FolderManagerContext);
|
export const useFolderManager = (): FolderManager => useContext(FolderManagerContext);
|
||||||
|
|
||||||
export default FolderManagerContext;
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import { useManagementModals } from '../../app/useManagementModals';
|
|||||||
import { useAppDispatch, useAppState } from '../../app/appState';
|
import { useAppDispatch, useAppState } from '../../app/appState';
|
||||||
import { fetchAsset } from '../../lib/apiClient';
|
import { fetchAsset } from '../../lib/apiClient';
|
||||||
import { useApi } from '../../app/ApiContext';
|
import { useApi } from '../../app/ApiContext';
|
||||||
import useWorkspaceSelection from '../../app/useWorkspaceSelection';
|
import { useWorkspaceSelection } from '../../app/useWorkspaceSelection';
|
||||||
import { useEntryPointer as useEntryPointerCore } from '../../documents/useEntryPointer';
|
import { useEntryPointer as useEntryPointerCore } from '../../documents/useEntryPointer';
|
||||||
import { isTagTransferEvent } from '../../documents/tagTransfer';
|
import { isTagTransferEvent } from '../../documents/tagTransfer';
|
||||||
import useDocumentsSelection from '../../documents/hooks/useDocumentsSelection';
|
import useDocumentsSelection from '../../documents/hooks/useDocumentsSelection';
|
||||||
|
|||||||
@@ -342,15 +342,4 @@ api.interceptors.response.use(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
export type {
|
export type { ApiTokenRecord } from './apiTypes';
|
||||||
DownloadLink,
|
|
||||||
DocumentResponse,
|
|
||||||
AssetResponse,
|
|
||||||
FolderTreeNode,
|
|
||||||
CapabilitySetResponse,
|
|
||||||
CapabilityResponse,
|
|
||||||
ApiTokenRecord,
|
|
||||||
PasskeySummary,
|
|
||||||
Identifier,
|
|
||||||
TenantSnippet,
|
|
||||||
} from './apiTypes';
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ export interface TagResponse {
|
|||||||
color?: string | null;
|
color?: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CorrespondentResponse {
|
interface CorrespondentResponse {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
metadata: Record<string, unknown>;
|
metadata: Record<string, unknown>;
|
||||||
@@ -29,7 +29,7 @@ export interface AssetResponse {
|
|||||||
[key: string]: unknown;
|
[key: string]: unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DocumentVersionResponse {
|
interface DocumentVersionResponse {
|
||||||
id: string;
|
id: string;
|
||||||
version_number: number;
|
version_number: number;
|
||||||
size_bytes: number;
|
size_bytes: number;
|
||||||
@@ -57,7 +57,7 @@ export interface DocumentResponse {
|
|||||||
current_version?: DocumentVersionResponse | null;
|
current_version?: DocumentVersionResponse | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FolderInfo {
|
interface FolderInfo {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
parent_id?: string | null;
|
parent_id?: string | null;
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import { resolveDocumentAssetUrl } from '../asset_manager';
|
|||||||
import PanelHeader from '../ui/PanelHeader';
|
import PanelHeader from '../ui/PanelHeader';
|
||||||
import BreadcrumbTrail from '../ui/BreadcrumbTrail';
|
import BreadcrumbTrail from '../ui/BreadcrumbTrail';
|
||||||
import DocumentViewerLayout from './DocumentViewerLayout';
|
import DocumentViewerLayout from './DocumentViewerLayout';
|
||||||
import useViewerLayoutMode from './useViewerLayoutMode';
|
import { useViewerLayoutMode } from './useViewerLayoutMode';
|
||||||
import { usePanelResizeBindings } from '../app/PanelManagerContext';
|
import { usePanelResizeBindings } from '../app/PanelManagerContext';
|
||||||
import type { DocumentId, FolderId } from '../types/identifiers';
|
import type { DocumentId, FolderId } from '../types/identifiers';
|
||||||
import type { Document } from '../types/documents';
|
import type { Document } from '../types/documents';
|
||||||
@@ -46,7 +46,7 @@ interface DocumentViewerPanelProps extends DocumentSummarySectionProps {
|
|||||||
sidebarMode?: SidebarMode;
|
sidebarMode?: SidebarMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const createDocumentViewerHeaderActions = ({
|
const createDocumentViewerHeaderActions = ({
|
||||||
document,
|
document,
|
||||||
actionState,
|
actionState,
|
||||||
onZoom,
|
onZoom,
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import React from 'react';
|
|||||||
import { DownloadIcon } from '../ui/icons';
|
import { DownloadIcon } from '../ui/icons';
|
||||||
import { AUDIO_EXTENSIONS, VIDEO_EXTENSIONS } from '../constants/preview';
|
import { AUDIO_EXTENSIONS, VIDEO_EXTENSIONS } from '../constants/preview';
|
||||||
|
|
||||||
export interface MediaViewerProps {
|
interface MediaViewerProps {
|
||||||
src: string;
|
src: string;
|
||||||
mimeType?: string;
|
mimeType?: string;
|
||||||
filename?: string;
|
filename?: string;
|
||||||
|
|||||||
@@ -5,8 +5,6 @@ import {
|
|||||||
PORTRAIT_RATIO_STYLE_ID,
|
PORTRAIT_RATIO_STYLE_ID,
|
||||||
} from '../constants/preview';
|
} from '../constants/preview';
|
||||||
|
|
||||||
export { DOCUMENT_VIEWER_PORTRAIT_HEIGHT_RATIO };
|
|
||||||
|
|
||||||
const ensurePortraitRatioStyle = () => {
|
const ensurePortraitRatioStyle = () => {
|
||||||
const cssValue = String(DOCUMENT_VIEWER_PORTRAIT_HEIGHT_RATIO);
|
const cssValue = String(DOCUMENT_VIEWER_PORTRAIT_HEIGHT_RATIO);
|
||||||
const cssText = `:root { --document-viewer-portrait-height-ratio: ${cssValue}; }`;
|
const cssText = `:root { --document-viewer-portrait-height-ratio: ${cssValue}; }`;
|
||||||
@@ -78,5 +76,3 @@ export const useViewerLayoutMode = (
|
|||||||
|
|
||||||
return isStacked;
|
return isStacked;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default useViewerLayoutMode;
|
|
||||||
|
|||||||
@@ -1,61 +0,0 @@
|
|||||||
import React, { useEffect } from 'react';
|
|
||||||
import { Navigate, useNavigate, useParams } from 'react-router-dom';
|
|
||||||
|
|
||||||
import { useAppShell } from '../appShellContext';
|
|
||||||
import type { Identifier } from '../types/identifiers';
|
|
||||||
|
|
||||||
interface DocumentViewerRouteContext {
|
|
||||||
previewWorkspaceDocument?: { id?: Identifier } | null;
|
|
||||||
ensurePreviewData?: (documentId: Identifier, options?: Record<string, unknown>) => Promise<unknown>;
|
|
||||||
notifyApiError?: (error: unknown, message?: string) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const DocumentViewerRoute: React.FC = () => {
|
|
||||||
const {
|
|
||||||
previewWorkspaceDocument,
|
|
||||||
ensurePreviewData,
|
|
||||||
notifyApiError,
|
|
||||||
} = useAppShell() as DocumentViewerRouteContext;
|
|
||||||
const { documentId } = useParams();
|
|
||||||
const navigate = useNavigate();
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!documentId) {
|
|
||||||
navigate('/documents', { replace: true });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let cancelled = false;
|
|
||||||
|
|
||||||
const hydrate = async () => {
|
|
||||||
try {
|
|
||||||
await ensurePreviewData?.(documentId);
|
|
||||||
} catch (error) {
|
|
||||||
if (cancelled) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
notifyApiError?.(error, 'Failed to open document preview.');
|
|
||||||
navigate('/documents', { replace: true });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
hydrate();
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
cancelled = true;
|
|
||||||
};
|
|
||||||
}, [documentId, ensurePreviewData, notifyApiError, navigate]);
|
|
||||||
|
|
||||||
if (!documentId) {
|
|
||||||
return <Navigate to="/documents" replace />;
|
|
||||||
}
|
|
||||||
|
|
||||||
const previewId = previewWorkspaceDocument?.id;
|
|
||||||
if (!previewWorkspaceDocument || String(previewId) !== String(documentId)) {
|
|
||||||
return <div className="document-viewer__message">Loading preview…</div>;
|
|
||||||
}
|
|
||||||
|
|
||||||
return <Navigate to="/documents" replace />;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default DocumentViewerRoute;
|
|
||||||
@@ -1,12 +1,5 @@
|
|||||||
import PasskeysSection from './PasskeysSection';
|
|
||||||
import ApiTokensSection from './ApiTokensSection';
|
|
||||||
import CapabilitySetsSection from './CapabilitySetsSection';
|
|
||||||
import {
|
import {
|
||||||
API_TOKENS_SECTION,
|
|
||||||
CAPABILITY_SETS_SECTION,
|
|
||||||
DEFAULT_SETTINGS_SECTIONS,
|
DEFAULT_SETTINGS_SECTIONS,
|
||||||
PASSKEYS_SECTION,
|
|
||||||
} from '../../constants/settings';
|
} from '../../constants/settings';
|
||||||
|
|
||||||
export { PasskeysSection, ApiTokensSection, CapabilitySetsSection };
|
export { DEFAULT_SETTINGS_SECTIONS };
|
||||||
export { PASSKEYS_SECTION, API_TOKENS_SECTION, CAPABILITY_SETS_SECTION, DEFAULT_SETTINGS_SECTIONS };
|
|
||||||
|
|||||||
@@ -59,13 +59,13 @@ interface PasskeyRegisterPayload {
|
|||||||
nickname?: string;
|
nickname?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type RegisterPasskeyFailureReason = 'unsupported' | 'busy' | 'cancelled' | 'error';
|
type RegisterPasskeyFailureReason = 'unsupported' | 'busy' | 'cancelled' | 'error';
|
||||||
export type RegisterPasskeyResult =
|
export type RegisterPasskeyResult =
|
||||||
| { ok: true }
|
| { ok: true }
|
||||||
| { ok: false; reason: RegisterPasskeyFailureReason; message?: string };
|
| { ok: false; reason: RegisterPasskeyFailureReason; message?: string };
|
||||||
|
|
||||||
export type RevokePasskeyFailureReason = 'missing-id' | 'error';
|
type RevokePasskeyFailureReason = 'missing-id' | 'error';
|
||||||
export type RevokePasskeyResult =
|
type RevokePasskeyResult =
|
||||||
| { ok: true }
|
| { ok: true }
|
||||||
| { ok: false; reason: RevokePasskeyFailureReason; message?: string };
|
| { ok: false; reason: RevokePasskeyFailureReason; message?: string };
|
||||||
|
|
||||||
|
|||||||
@@ -295,12 +295,3 @@ export const useSidebarContext = () => {
|
|||||||
}
|
}
|
||||||
return context;
|
return context;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useSidebarControls = () => {
|
|
||||||
const { setCollapsed } = useSidebarContext();
|
|
||||||
const openSidebar = useCallback(() => setCollapsed(false), [setCollapsed]);
|
|
||||||
const closeSidebar = useCallback(() => setCollapsed(true), [setCollapsed]);
|
|
||||||
return { openSidebar, closeSidebar };
|
|
||||||
};
|
|
||||||
|
|
||||||
export default SidebarContext;
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ export interface FolderTreeNode {
|
|||||||
expanded?: boolean;
|
expanded?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FolderNodeProps {
|
interface FolderNodeProps {
|
||||||
node: FolderTreeNode;
|
node: FolderTreeNode;
|
||||||
depth: number;
|
depth: number;
|
||||||
isSelected: boolean;
|
isSelected: boolean;
|
||||||
|
|||||||
@@ -57,14 +57,14 @@ export interface Folder {
|
|||||||
name?: string;
|
name?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type FolderEntry = {
|
type FolderEntry = {
|
||||||
type: 'folder';
|
type: 'folder';
|
||||||
id: Identifier | 'root';
|
id: Identifier | 'root';
|
||||||
key: string;
|
key: string;
|
||||||
folder: Folder;
|
folder: Folder;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type DocumentEntry = {
|
type DocumentEntry = {
|
||||||
type: 'document';
|
type: 'document';
|
||||||
id: Identifier;
|
id: Identifier;
|
||||||
key: string;
|
key: string;
|
||||||
@@ -77,4 +77,3 @@ export type DocumentsListEntry = FolderEntry | DocumentEntry;
|
|||||||
import type { MouseEvent } from 'react';
|
import type { MouseEvent } from 'react';
|
||||||
|
|
||||||
export type FolderEventHandler = (folder: Folder, event: MouseEvent<HTMLElement>) => void;
|
export type FolderEventHandler = (folder: Folder, event: MouseEvent<HTMLElement>) => void;
|
||||||
export type DocumentEventHandler = (document: Document, event: MouseEvent<HTMLElement>) => void;
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React, { ElementType, ReactNode } from 'react';
|
import React, { ElementType, ReactNode } from 'react';
|
||||||
import composeClassName from './classNames';
|
import { composeClassName } from './classNames';
|
||||||
|
|
||||||
type TitleProps = Record<string, unknown>;
|
type TitleProps = Record<string, unknown>;
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ interface FloatingMenuState {
|
|||||||
|
|
||||||
type CSSVarStyle = CSSProperties & Record<string, string>;
|
type CSSVarStyle = CSSProperties & Record<string, string>;
|
||||||
|
|
||||||
export interface QuickAddMenuProps {
|
interface QuickAddMenuProps {
|
||||||
onSelectOption?: (value: QuickAddOption, normalized: NormalizedOption) => Promise<void> | void;
|
onSelectOption?: (value: QuickAddOption, normalized: NormalizedOption) => Promise<void> | void;
|
||||||
onCreate?: (value: string) => Promise<void> | void;
|
onCreate?: (value: string) => Promise<void> | void;
|
||||||
options?: QuickAddOption[];
|
options?: QuickAddOption[];
|
||||||
|
|||||||
@@ -1,4 +1,2 @@
|
|||||||
export const composeClassName = (base: string, extra?: string | null): string =>
|
export const composeClassName = (base: string, extra?: string | null): string =>
|
||||||
extra ? `${base} ${extra}` : base;
|
extra ? `${base} ${extra}` : base;
|
||||||
|
|
||||||
export default composeClassName;
|
|
||||||
|
|||||||
@@ -12,15 +12,11 @@ import {
|
|||||||
IconLayoutList,
|
IconLayoutList,
|
||||||
IconLayoutGrid,
|
IconLayoutGrid,
|
||||||
IconArrowLeft,
|
IconArrowLeft,
|
||||||
IconArrowRight,
|
|
||||||
IconArrowUp,
|
|
||||||
IconAnalyze,
|
IconAnalyze,
|
||||||
IconUpload,
|
IconUpload,
|
||||||
IconWindowMaximize,
|
IconWindowMaximize,
|
||||||
IconTextScan2,
|
|
||||||
IconFolderPlus,
|
IconFolderPlus,
|
||||||
IconFolder,
|
IconFolder,
|
||||||
IconFolderUp,
|
|
||||||
IconFolders,
|
IconFolders,
|
||||||
IconFoldersOff,
|
IconFoldersOff,
|
||||||
IconRefresh,
|
IconRefresh,
|
||||||
@@ -37,10 +33,8 @@ import {
|
|||||||
IconDeviceLaptop,
|
IconDeviceLaptop,
|
||||||
IconLayoutSidebarLeftCollapse,
|
IconLayoutSidebarLeftCollapse,
|
||||||
IconLayoutSidebarLeftExpand,
|
IconLayoutSidebarLeftExpand,
|
||||||
IconLayoutSidebarRightCollapse,
|
|
||||||
IconLayoutBottombarCollapse,
|
IconLayoutBottombarCollapse,
|
||||||
IconLayoutBottombarExpand,
|
IconLayoutBottombarExpand,
|
||||||
IconClearAll,
|
|
||||||
IconInfoCircle,
|
IconInfoCircle,
|
||||||
IconCircleDashedCheck,
|
IconCircleDashedCheck,
|
||||||
IconFile,
|
IconFile,
|
||||||
@@ -56,7 +50,7 @@ import {
|
|||||||
import FolderSvg from '../assets/folder.svg';
|
import FolderSvg from '../assets/folder.svg';
|
||||||
const logoWebp = new URL('../assets/logo.webp', import.meta.url).toString();
|
const logoWebp = new URL('../assets/logo.webp', import.meta.url).toString();
|
||||||
const logoSmallWebp = new URL('../assets/logo_small.webp', import.meta.url).toString();
|
const logoSmallWebp = new URL('../assets/logo_small.webp', import.meta.url).toString();
|
||||||
import composeClassName from './classNames';
|
import { composeClassName } from './classNames';
|
||||||
|
|
||||||
type TablerIconComponent = (props: TablerIconProps) => JSX.Element;
|
type TablerIconComponent = (props: TablerIconProps) => JSX.Element;
|
||||||
|
|
||||||
@@ -223,16 +217,6 @@ export const ArrowLeftIcon: TablerIconComponent = ({ className, size = '1em', st
|
|||||||
{...rest}
|
{...rest}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
export const ArrowRightIcon: TablerIconComponent = ({ className, size = '1em', stroke = 1.6, ...rest }) => (
|
|
||||||
<IconArrowRight
|
|
||||||
className={composeClassName('icon', className)}
|
|
||||||
size={size}
|
|
||||||
stroke={stroke}
|
|
||||||
{...rest}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
export const SidebarCollapseIcon: TablerIconComponent = ({ className, size = '1em', stroke = 1.6, ...rest }) => (
|
export const SidebarCollapseIcon: TablerIconComponent = ({ className, size = '1em', stroke = 1.6, ...rest }) => (
|
||||||
<IconLayoutSidebarLeftCollapse
|
<IconLayoutSidebarLeftCollapse
|
||||||
className={composeClassName('icon', className)}
|
className={composeClassName('icon', className)}
|
||||||
@@ -268,16 +252,6 @@ export const FileInfoIcon: TablerIconComponent = ({ className, size = '1em', str
|
|||||||
{...rest}
|
{...rest}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
export const DetailPanelCollapseIcon: TablerIconComponent = ({ className, size = '1em', stroke = 1.6, ...rest }) => (
|
|
||||||
<IconLayoutSidebarRightCollapse
|
|
||||||
className={composeClassName('icon', className)}
|
|
||||||
size={size}
|
|
||||||
stroke={stroke}
|
|
||||||
{...rest}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
export const BottombarCollapseIcon: TablerIconComponent = ({ className, size = '1em', stroke = 1.6, ...rest }) => (
|
export const BottombarCollapseIcon: TablerIconComponent = ({ className, size = '1em', stroke = 1.6, ...rest }) => (
|
||||||
<IconLayoutBottombarCollapse
|
<IconLayoutBottombarCollapse
|
||||||
className={composeClassName('icon', className)}
|
className={composeClassName('icon', className)}
|
||||||
@@ -295,16 +269,6 @@ export const BottombarExpandIcon: TablerIconComponent = ({ className, size = '1e
|
|||||||
{...rest}
|
{...rest}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
export const ClearAllIcon: TablerIconComponent = ({ className, size = '1em', stroke = 1.6, ...rest }) => (
|
|
||||||
<IconClearAll
|
|
||||||
className={composeClassName('icon', className)}
|
|
||||||
size={size}
|
|
||||||
stroke={stroke}
|
|
||||||
{...rest}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
export const FolderPlusIcon: TablerIconComponent = ({ className, size = '1em', stroke = 1.6, ...rest }) => (
|
export const FolderPlusIcon: TablerIconComponent = ({ className, size = '1em', stroke = 1.6, ...rest }) => (
|
||||||
<IconFolderPlus
|
<IconFolderPlus
|
||||||
className={composeClassName('icon', className)}
|
className={composeClassName('icon', className)}
|
||||||
@@ -349,16 +313,6 @@ export const RestoreIcon: TablerIconComponent = ({ className, size = '1em', stro
|
|||||||
{...rest}
|
{...rest}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
export const ArrowUpIcon: TablerIconComponent = ({ className, size = '1em', stroke = 1.6, ...rest }) => (
|
|
||||||
<IconArrowUp
|
|
||||||
className={composeClassName('icon', className)}
|
|
||||||
size={size}
|
|
||||||
stroke={stroke}
|
|
||||||
{...rest}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
export const MinusVerticalIcon: TablerIconComponent = ({ className, size = '1em', stroke = 1.6, ...rest }) => (
|
export const MinusVerticalIcon: TablerIconComponent = ({ className, size = '1em', stroke = 1.6, ...rest }) => (
|
||||||
<IconMinusVertical
|
<IconMinusVertical
|
||||||
className={composeClassName('icon', className)}
|
className={composeClassName('icon', className)}
|
||||||
@@ -567,16 +521,6 @@ export const ChevronDownIcon: TablerIconComponent = ({ className, size = '1em',
|
|||||||
{...rest}
|
{...rest}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
export const FolderUpIcon: TablerIconComponent = ({ className, size = '1em', stroke = 1.6, ...rest }) => (
|
|
||||||
<IconFolderUp
|
|
||||||
className={composeClassName('icon', className)}
|
|
||||||
size={size}
|
|
||||||
stroke={stroke}
|
|
||||||
{...rest}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
export const FolderMoveIcon: TablerIconComponent = ({ className, size = '1em', stroke = 1.6, ...rest }) => (
|
export const FolderMoveIcon: TablerIconComponent = ({ className, size = '1em', stroke = 1.6, ...rest }) => (
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
@@ -601,38 +545,3 @@ export const FolderMoveIcon: TablerIconComponent = ({ className, size = '1em', s
|
|||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
|
|
||||||
export default {
|
|
||||||
ChevronIcon,
|
|
||||||
TrashIcon,
|
|
||||||
EditIcon,
|
|
||||||
FolderIcon,
|
|
||||||
TagIcon,
|
|
||||||
CorrespondentIcon,
|
|
||||||
DownloadIcon,
|
|
||||||
ViewListIcon,
|
|
||||||
ViewGridIcon,
|
|
||||||
SidebarCollapseIcon,
|
|
||||||
SidebarExpandIcon,
|
|
||||||
DetailPanelCollapseIcon,
|
|
||||||
AnalyzeIcon,
|
|
||||||
LoaderIcon,
|
|
||||||
WindowMaximizeIcon,
|
|
||||||
FolderPlusIcon,
|
|
||||||
RefreshIcon,
|
|
||||||
ArrowUpIcon,
|
|
||||||
MinusVerticalIcon,
|
|
||||||
LogoutIcon,
|
|
||||||
ChevronDownIcon,
|
|
||||||
FolderUpIcon,
|
|
||||||
FolderMoveIcon,
|
|
||||||
};
|
|
||||||
|
|
||||||
export const TextScanIcon: TablerIconComponent = ({ className, size = '1em', stroke = 1.6, ...rest }) => (
|
|
||||||
<IconTextScan2
|
|
||||||
className={composeClassName('icon', className)}
|
|
||||||
size={size}
|
|
||||||
stroke={stroke}
|
|
||||||
{...rest}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|||||||
@@ -1,94 +0,0 @@
|
|||||||
import { useCallback, useEffect, useRef } from 'react';
|
|
||||||
import type { PointerEvent as ReactPointerEvent } from 'react';
|
|
||||||
|
|
||||||
export interface PointerTapContext<T = unknown> {
|
|
||||||
clientX: number;
|
|
||||||
clientY: number;
|
|
||||||
pointerType: string;
|
|
||||||
event: PointerEventWithPersist;
|
|
||||||
data?: T;
|
|
||||||
}
|
|
||||||
|
|
||||||
type PointerEventWithPersist = (PointerEvent | ReactPointerEvent) & { persist?: () => void };
|
|
||||||
|
|
||||||
type PointerTapFilter = (event?: PointerEventWithPersist | null) => boolean;
|
|
||||||
|
|
||||||
export interface UsePointerTapOptions<T = unknown> {
|
|
||||||
onSingle?: (context: PointerTapContext<T>) => void;
|
|
||||||
onDouble?: (context: PointerTapContext<T>) => void;
|
|
||||||
delay?: number;
|
|
||||||
filter?: PointerTapFilter;
|
|
||||||
}
|
|
||||||
|
|
||||||
const defaultFilter: PointerTapFilter = (event) => {
|
|
||||||
if (!event) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const { type, button, pointerType, isPrimary } = event;
|
|
||||||
const isPointerUp = type === 'pointerup';
|
|
||||||
const buttonValid =
|
|
||||||
button == null || button === 0 || (isPointerUp && (button === -1 || button === 0));
|
|
||||||
if (!buttonValid) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (pointerType === 'touch' && isPrimary === false) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
const usePointerTap = <T,>({
|
|
||||||
onSingle,
|
|
||||||
onDouble,
|
|
||||||
delay = 240,
|
|
||||||
filter = defaultFilter,
|
|
||||||
}: UsePointerTapOptions<T> = {}) => {
|
|
||||||
const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
||||||
|
|
||||||
useEffect(
|
|
||||||
() => () => {
|
|
||||||
if (timerRef.current) {
|
|
||||||
clearTimeout(timerRef.current);
|
|
||||||
timerRef.current = null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
|
|
||||||
return useCallback(
|
|
||||||
(event?: PointerEventWithPersist | null, metadata?: T) => {
|
|
||||||
if (!filter(event)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!event) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
event.persist?.();
|
|
||||||
|
|
||||||
const context: PointerTapContext<T> = {
|
|
||||||
clientX: event.clientX ?? 0,
|
|
||||||
clientY: event.clientY ?? 0,
|
|
||||||
pointerType: event.pointerType ?? 'mouse',
|
|
||||||
event,
|
|
||||||
data: metadata,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (timerRef.current) {
|
|
||||||
clearTimeout(timerRef.current);
|
|
||||||
timerRef.current = null;
|
|
||||||
onDouble?.(context);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
timerRef.current = setTimeout(() => {
|
|
||||||
timerRef.current = null;
|
|
||||||
onSingle?.(context);
|
|
||||||
}, delay);
|
|
||||||
},
|
|
||||||
[delay, filter, onDouble, onSingle],
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default usePointerTap;
|
|
||||||
@@ -93,7 +93,7 @@ const srgbChannelToLinear = (value: number) => {
|
|||||||
return ((normalized + 0.055) / 1.055) ** 2.4;
|
return ((normalized + 0.055) / 1.055) ** 2.4;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const hexToRgb = (input?: string): (RgbColor & { hex: string }) | null => {
|
const hexToRgb = (input?: string): (RgbColor & { hex: string }) | null => {
|
||||||
if (!input) return null;
|
if (!input) return null;
|
||||||
const match = HEX_COLOR_PATTERN.exec(input.trim());
|
const match = HEX_COLOR_PATTERN.exec(input.trim());
|
||||||
if (!match) return null;
|
if (!match) return null;
|
||||||
@@ -163,7 +163,7 @@ const buildTagStyle = (backgroundHex: string) => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const relativeLuminance = ({ r, g, b }: RgbColor): number => {
|
const relativeLuminance = ({ r, g, b }: RgbColor): number => {
|
||||||
const toLinear = (channel) => {
|
const toLinear = (channel) => {
|
||||||
const normalized = channel / 255;
|
const normalized = channel / 255;
|
||||||
return normalized <= 0.03928
|
return normalized <= 0.03928
|
||||||
@@ -198,7 +198,7 @@ const contrastForPair = (backgroundHex: string, textHex: string): number => {
|
|||||||
return contrastRatio(relativeLuminance(background), relativeLuminance(text));
|
return contrastRatio(relativeLuminance(background), relativeLuminance(text));
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getReadableTextColor = (
|
const getReadableTextColor = (
|
||||||
hex: string,
|
hex: string,
|
||||||
{ light = '#1f1f1f', dark = '#ffffff', fallback = '#1f1f1f' }: { light?: string; dark?: string; fallback?: string } = {},
|
{ light = '#1f1f1f', dark = '#ffffff', fallback = '#1f1f1f' }: { light?: string; dark?: string; fallback?: string } = {},
|
||||||
): string => {
|
): string => {
|
||||||
|
|||||||
@@ -51,13 +51,3 @@ export const toIssuedTimestamp = (dateString: string | null, fallback: string |
|
|||||||
candidate.setUTCFullYear(year, month - 1, day);
|
candidate.setUTCFullYear(year, month - 1, day);
|
||||||
return Number.isNaN(candidate.getTime()) ? null : candidate.toISOString();
|
return Number.isNaN(candidate.getTime()) ? null : candidate.toISOString();
|
||||||
};
|
};
|
||||||
|
|
||||||
export const parseDateValue = (value: string | Date | null): Date | null => ensureDate(value);
|
|
||||||
|
|
||||||
export default {
|
|
||||||
formatDate,
|
|
||||||
formatDateTime,
|
|
||||||
toDateInputValue,
|
|
||||||
toIssuedTimestamp,
|
|
||||||
parseDateValue,
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -7,19 +7,3 @@ export const clamp = (value: number, min: number, max: number): number => {
|
|||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const formatTransform = (
|
|
||||||
x: number,
|
|
||||||
y: number,
|
|
||||||
rotation = 0,
|
|
||||||
scale = 1,
|
|
||||||
): string => `translate3d(${x}px, ${y}px, 0) rotate(${rotation}deg) scale(${scale})`;
|
|
||||||
|
|
||||||
export const toNumber = (v: unknown, fallback = 0): number =>
|
|
||||||
Number.isFinite(Number(v)) ? Number(v) : fallback;
|
|
||||||
|
|
||||||
export default {
|
|
||||||
clamp,
|
|
||||||
formatTransform,
|
|
||||||
toNumber,
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -4,12 +4,9 @@ import type {
|
|||||||
} from '../asset_manager';
|
} from '../asset_manager';
|
||||||
import type {
|
import type {
|
||||||
Document,
|
Document,
|
||||||
DocumentVersion,
|
|
||||||
} from '../types/documents';
|
} from '../types/documents';
|
||||||
import type { Asset } from '../types/assets';
|
import type { Asset } from '../types/assets';
|
||||||
|
|
||||||
export type { Document, DocumentVersion, Asset };
|
|
||||||
|
|
||||||
export type EnsurePreviewData = (id: string) => Promise<Document | null>;
|
export type EnsurePreviewData = (id: string) => Promise<Document | null>;
|
||||||
export type EnsureAssetUrl = (
|
export type EnsureAssetUrl = (
|
||||||
id: string,
|
id: string,
|
||||||
@@ -32,7 +29,7 @@ const pickAsset = (doc?: Document | null, getDocumentAsset?: GetDocumentAsset):
|
|||||||
return getDocumentAsset(doc, 'text-content') || null;
|
return getDocumentAsset(doc, 'text-content') || null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export async function resolveTextContentUrl({
|
async function resolveTextContentUrl({
|
||||||
document,
|
document,
|
||||||
ensurePreviewData,
|
ensurePreviewData,
|
||||||
getDocumentAsset,
|
getDocumentAsset,
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ const decodeBase64 = (value: string): string => window.atob(value);
|
|||||||
|
|
||||||
const encodeBase64 = (binary: string): string => window.btoa(binary);
|
const encodeBase64 = (binary: string): string => window.btoa(binary);
|
||||||
|
|
||||||
export const base64urlToUint8Array = (value?: string | null): Uint8Array => {
|
const base64urlToUint8Array = (value?: string | null): Uint8Array => {
|
||||||
const base64 = base64urlToBase64(value || '');
|
const base64 = base64urlToBase64(value || '');
|
||||||
const binary = decodeBase64(base64);
|
const binary = decodeBase64(base64);
|
||||||
const bytes = new Uint8Array(binary.length);
|
const bytes = new Uint8Array(binary.length);
|
||||||
@@ -77,7 +77,7 @@ const toUint8Array = (input?: ArrayBuffer | ArrayBufferView | ArrayLike<number>
|
|||||||
return Uint8Array.from(input as ArrayLike<number>) as Uint8Array;
|
return Uint8Array.from(input as ArrayLike<number>) as Uint8Array;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const arrayBufferToBase64url = (
|
const arrayBufferToBase64url = (
|
||||||
buffer?: ArrayBuffer | ArrayBufferView | ArrayLike<number> | null,
|
buffer?: ArrayBuffer | ArrayBufferView | ArrayLike<number> | null,
|
||||||
): string => {
|
): string => {
|
||||||
const bytes = toUint8Array(buffer);
|
const bytes = toUint8Array(buffer);
|
||||||
|
|||||||
@@ -1,22 +0,0 @@
|
|||||||
const { readFileSync } = require('node:fs');
|
|
||||||
const ts = require('typescript');
|
|
||||||
|
|
||||||
const compilerOptions = {
|
|
||||||
module: ts.ModuleKind.CommonJS,
|
|
||||||
target: ts.ScriptTarget.ES2022,
|
|
||||||
jsx: ts.JsxEmit.ReactJSX,
|
|
||||||
esModuleInterop: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
const compileTs = (module, filename) => {
|
|
||||||
const source = readFileSync(filename, 'utf8');
|
|
||||||
const { outputText } = ts.transpileModule(source, {
|
|
||||||
compilerOptions,
|
|
||||||
fileName: filename,
|
|
||||||
reportDiagnostics: false,
|
|
||||||
});
|
|
||||||
module._compile(outputText, filename);
|
|
||||||
};
|
|
||||||
|
|
||||||
require.extensions['.ts'] = compileTs;
|
|
||||||
require.extensions['.tsx'] = compileTs;
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
const test = require('node:test');
|
|
||||||
const assert = require('node:assert/strict');
|
|
||||||
require('./ts-register');
|
|
||||||
|
|
||||||
const {
|
|
||||||
WorkspaceEngine,
|
|
||||||
DESK_CANVAS_PADDING,
|
|
||||||
} = require('../src/desktop/workspaceEngine.ts');
|
|
||||||
|
|
||||||
const makeEngine = () => {
|
|
||||||
const engine = new WorkspaceEngine();
|
|
||||||
engine.setEnsureDocumentSize(() => ({ width: 200, height: 200 }));
|
|
||||||
engine.setCanvasSize({ width: 1200, height: 800 });
|
|
||||||
return engine;
|
|
||||||
};
|
|
||||||
|
|
||||||
test('syncLayoutSnapshot clones from layout map', () => {
|
|
||||||
const engine = makeEngine();
|
|
||||||
engine.setItems([{ id: 'doc-1' }]);
|
|
||||||
engine.ensureLayoutForItems();
|
|
||||||
engine.syncLayoutSnapshot();
|
|
||||||
|
|
||||||
const firstSnapshot = engine.getSnapshot();
|
|
||||||
assert(firstSnapshot.layout instanceof Map);
|
|
||||||
assert(firstSnapshot.layout.get('doc-1'));
|
|
||||||
|
|
||||||
engine.layout.set('doc-1', {
|
|
||||||
centerX: DESK_CANVAS_PADDING + 150,
|
|
||||||
centerY: DESK_CANVAS_PADDING + 150,
|
|
||||||
rotation: 0,
|
|
||||||
width: 200,
|
|
||||||
height: 200,
|
|
||||||
});
|
|
||||||
engine.syncLayoutSnapshot();
|
|
||||||
|
|
||||||
const secondSnapshot = engine.getSnapshot();
|
|
||||||
assert.notStrictEqual(secondSnapshot.layout, engine.layout);
|
|
||||||
assert.equal(secondSnapshot.layout.get('doc-1').centerX, engine.layout.get('doc-1').centerX);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('recalcVisibleDocIds respects viewport bounds', () => {
|
|
||||||
const engine = makeEngine();
|
|
||||||
engine.items = [{ id: 'visible' }, { id: 'hidden' }];
|
|
||||||
engine.setDocumentLookup(new Map([
|
|
||||||
['visible', { id: 'visible' }],
|
|
||||||
['hidden', { id: 'hidden' }],
|
|
||||||
]));
|
|
||||||
|
|
||||||
engine.layout = new Map([
|
|
||||||
['visible', {
|
|
||||||
centerX: DESK_CANVAS_PADDING + 150,
|
|
||||||
centerY: DESK_CANVAS_PADDING + 150,
|
|
||||||
rotation: 0,
|
|
||||||
width: 200,
|
|
||||||
height: 200,
|
|
||||||
}],
|
|
||||||
['hidden', {
|
|
||||||
centerX: -500,
|
|
||||||
centerY: -500,
|
|
||||||
rotation: 0,
|
|
||||||
width: 200,
|
|
||||||
height: 200,
|
|
||||||
}],
|
|
||||||
]);
|
|
||||||
engine.layoutSnapshot = new Map(engine.layout);
|
|
||||||
|
|
||||||
engine.recalcVisibleDocIds();
|
|
||||||
|
|
||||||
const snapshot = engine.getSnapshot();
|
|
||||||
assert(snapshot.visibleDocIds.has('visible'));
|
|
||||||
assert(!snapshot.visibleDocIds.has('hidden'));
|
|
||||||
});
|
|
||||||
Reference in New Issue
Block a user