react-dropzone
Advanced tools
+26
-16
@@ -40,3 +40,3 @@ var _excluded = ["children"], | ||
| import { fromEvent } from "file-selector"; | ||
| import { allFilesAccepted, composeEventHandlers, fileAccepted, fileMatchSize, filePickerOptionsTypes, canUseFileSystemAccessAPI, isEvtWithFiles, isIeOrEdge, isPropagationStopped, onDocumentDragOver, TOO_MANY_FILES_REJECTION } from "./utils/index"; | ||
| import { allFilesAccepted, composeEventHandlers, fileAccepted, fileMatchSize, filePickerOptionsTypes, canUseFileSystemAccessAPI, isAbort, isEvtWithFiles, isIeOrEdge, isPropagationStopped, isSecurityError, onDocumentDragOver, TOO_MANY_FILES_REJECTION } from "./utils/index"; | ||
| /** | ||
@@ -469,7 +469,8 @@ * Convenience wrapper component for the `useDropzone` hook | ||
| isFileDialogActive = state.isFileDialogActive, | ||
| draggedFiles = state.draggedFiles; // Update file dialog active state when the window is focused on | ||
| draggedFiles = state.draggedFiles; | ||
| var fsAccessApiWorksRef = useRef(window.isSecureContext && useFsAccessApi && canUseFileSystemAccessAPI()); // Update file dialog active state when the window is focused on | ||
| var onWindowFocus = function onWindowFocus() { | ||
| // Execute the timeout only if the file dialog is opened in the browser | ||
| if (isFileDialogActive) { | ||
| if (!fsAccessApiWorksRef.current && isFileDialogActive) { | ||
| setTimeout(function () { | ||
@@ -491,6 +492,2 @@ if (inputRef.current) { | ||
| useEffect(function () { | ||
| if (window.isSecureContext && useFsAccessApi && canUseFileSystemAccessAPI()) { | ||
| return function () {}; | ||
| } | ||
| window.addEventListener("focus", onWindowFocus, false); | ||
@@ -500,3 +497,3 @@ return function () { | ||
| }; | ||
| }, [inputRef, isFileDialogActive, onFileDialogCancelCb, useFsAccessApi]); | ||
| }, [inputRef, isFileDialogActive, onFileDialogCancelCb, fsAccessApiWorksRef]); | ||
| var dragTargetsRef = useRef([]); | ||
@@ -692,3 +689,3 @@ | ||
| // https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts#feature_detection | ||
| if (window.isSecureContext && useFsAccessApi && canUseFileSystemAccessAPI()) { | ||
| if (fsAccessApiWorksRef.current) { | ||
| dispatch({ | ||
@@ -706,9 +703,22 @@ type: "openDialog" | ||
| }).then(function (files) { | ||
| return setFiles(files, null); | ||
| }).catch(function (e) { | ||
| return onFileDialogCancelCb(e); | ||
| }).finally(function () { | ||
| return dispatch({ | ||
| setFiles(files, null); | ||
| dispatch({ | ||
| type: "closeDialog" | ||
| }); | ||
| }).catch(function (e) { | ||
| // AbortError means the user canceled | ||
| if (isAbort(e)) { | ||
| onFileDialogCancelCb(e); | ||
| dispatch({ | ||
| type: "closeDialog" | ||
| }); | ||
| } else if (isSecurityError(e)) { | ||
| fsAccessApiWorksRef.current = false; // CORS, so cannot use this API | ||
| // Try using the input | ||
| if (inputRef.current) { | ||
| inputRef.current.value = null; | ||
| inputRef.current.click(); | ||
| } | ||
| } | ||
| }); | ||
@@ -738,3 +748,3 @@ return; | ||
| } | ||
| }, [rootRef, inputRef, openFileDialog]); // Update focus state for the dropzone | ||
| }, [rootRef, openFileDialog]); // Update focus state for the dropzone | ||
@@ -765,3 +775,3 @@ var onFocusCb = useCallback(function () { | ||
| } | ||
| }, [inputRef, noClick, openFileDialog]); | ||
| }, [noClick, openFileDialog]); | ||
@@ -768,0 +778,0 @@ var composeHandler = function composeHandler(fn) { |
@@ -205,2 +205,24 @@ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; } | ||
| }]; | ||
| } | ||
| /** | ||
| * Check if v is an exception caused by aborting a request (e.g window.showOpenFilePicker()). | ||
| * | ||
| * See https://developer.mozilla.org/en-US/docs/Web/API/DOMException. | ||
| * @param {any} v | ||
| * @returns {boolean} True if v is an abort exception. | ||
| */ | ||
| export function isAbort(v) { | ||
| return v instanceof DOMException && (v.name === "AbortError" || v.code === v.ABORT_ERR); | ||
| } | ||
| /** | ||
| * Check if v is a security error. | ||
| * | ||
| * See https://developer.mozilla.org/en-US/docs/Web/API/DOMException. | ||
| * @param {any} v | ||
| * @returns {boolean} True if v is a security error. | ||
| */ | ||
| export function isSecurityError(v) { | ||
| return v instanceof DOMException && (v.name === "SecurityError" || v.code === v.SECURITY_ERR); | ||
| } |
+1
-1
@@ -174,3 +174,3 @@ { | ||
| "typings": "typings/react-dropzone.d.ts", | ||
| "version": "12.0.2", | ||
| "version": "12.0.3", | ||
| "engines": { | ||
@@ -177,0 +177,0 @@ "node": ">= 10.13" |
+30
-20
@@ -21,5 +21,7 @@ /* eslint prefer-template: 0 */ | ||
| canUseFileSystemAccessAPI, | ||
| isAbort, | ||
| isEvtWithFiles, | ||
| isIeOrEdge, | ||
| isPropagationStopped, | ||
| isSecurityError, | ||
| onDocumentDragOver, | ||
@@ -455,6 +457,10 @@ TOO_MANY_FILES_REJECTION, | ||
| const fsAccessApiWorksRef = useRef( | ||
| window.isSecureContext && useFsAccessApi && canUseFileSystemAccessAPI() | ||
| ); | ||
| // Update file dialog active state when the window is focused on | ||
| const onWindowFocus = () => { | ||
| // Execute the timeout only if the file dialog is opened in the browser | ||
| if (isFileDialogActive) { | ||
| if (!fsAccessApiWorksRef.current && isFileDialogActive) { | ||
| setTimeout(() => { | ||
@@ -473,10 +479,2 @@ if (inputRef.current) { | ||
| useEffect(() => { | ||
| if ( | ||
| window.isSecureContext && | ||
| useFsAccessApi && | ||
| canUseFileSystemAccessAPI() | ||
| ) { | ||
| return () => {}; | ||
| } | ||
| window.addEventListener("focus", onWindowFocus, false); | ||
@@ -486,3 +484,3 @@ return () => { | ||
| }; | ||
| }, [inputRef, isFileDialogActive, onFileDialogCancelCb, useFsAccessApi]); | ||
| }, [inputRef, isFileDialogActive, onFileDialogCancelCb, fsAccessApiWorksRef]); | ||
@@ -691,7 +689,3 @@ const dragTargetsRef = useRef([]); | ||
| // https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts#feature_detection | ||
| if ( | ||
| window.isSecureContext && | ||
| useFsAccessApi && | ||
| canUseFileSystemAccessAPI() | ||
| ) { | ||
| if (fsAccessApiWorksRef.current) { | ||
| dispatch({ type: "openDialog" }); | ||
@@ -707,5 +701,21 @@ onFileDialogOpenCb(); | ||
| .then((handles) => getFilesFromEvent(handles)) | ||
| .then((files) => setFiles(files, null)) | ||
| .catch((e) => onFileDialogCancelCb(e)) | ||
| .finally(() => dispatch({ type: "closeDialog" })); | ||
| .then((files) => { | ||
| setFiles(files, null); | ||
| dispatch({ type: "closeDialog" }); | ||
| }) | ||
| .catch((e) => { | ||
| // AbortError means the user canceled | ||
| if (isAbort(e)) { | ||
| onFileDialogCancelCb(e); | ||
| dispatch({ type: "closeDialog" }); | ||
| } else if (isSecurityError(e)) { | ||
| fsAccessApiWorksRef.current = false; | ||
| // CORS, so cannot use this API | ||
| // Try using the input | ||
| if (inputRef.current) { | ||
| inputRef.current.value = null; | ||
| inputRef.current.click(); | ||
| } | ||
| } | ||
| }); | ||
| return; | ||
@@ -743,3 +753,3 @@ } | ||
| }, | ||
| [rootRef, inputRef, openFileDialog] | ||
| [rootRef, openFileDialog] | ||
| ); | ||
@@ -769,3 +779,3 @@ | ||
| } | ||
| }, [inputRef, noClick, openFileDialog]); | ||
| }, [noClick, openFileDialog]); | ||
@@ -772,0 +782,0 @@ const composeHandler = (fn) => { |
+28
-0
@@ -206,1 +206,29 @@ import accepts from "attr-accept"; | ||
| } | ||
| /** | ||
| * Check if v is an exception caused by aborting a request (e.g window.showOpenFilePicker()). | ||
| * | ||
| * See https://developer.mozilla.org/en-US/docs/Web/API/DOMException. | ||
| * @param {any} v | ||
| * @returns {boolean} True if v is an abort exception. | ||
| */ | ||
| export function isAbort(v) { | ||
| return ( | ||
| v instanceof DOMException && | ||
| (v.name === "AbortError" || v.code === v.ABORT_ERR) | ||
| ); | ||
| } | ||
| /** | ||
| * Check if v is a security error. | ||
| * | ||
| * See https://developer.mozilla.org/en-US/docs/Web/API/DOMException. | ||
| * @param {any} v | ||
| * @returns {boolean} True if v is a security error. | ||
| */ | ||
| export function isSecurityError(v) { | ||
| return ( | ||
| v instanceof DOMException && | ||
| (v.name === "SecurityError" || v.code === v.SECURITY_ERR) | ||
| ); | ||
| } |
@@ -429,2 +429,56 @@ beforeEach(() => { | ||
| describe("isAbort()", () => { | ||
| let utils; | ||
| beforeEach(async () => { | ||
| utils = await import("./index"); | ||
| }); | ||
| it("should work as expected", () => { | ||
| expect(utils.isAbort(new DOMException())).toBe(false); | ||
| expect(utils.isAbort(new DOMException("some err"))).toBe(false); | ||
| expect(utils.isAbort(new DOMException("some err", "Noop"))).toBe(false); | ||
| expect(utils.isAbort(new DOMException("some err", "AbortError"))).toBe( | ||
| true | ||
| ); | ||
| const err = new DOMException("some err"); | ||
| const e = new Proxy(err, { | ||
| get(t, p) { | ||
| if (p === "code") { | ||
| return 20; | ||
| } | ||
| return t[p]; | ||
| }, | ||
| }); | ||
| expect(utils.isAbort(e)).toBe(true); | ||
| }); | ||
| }); | ||
| describe("isSecurityError()", () => { | ||
| let utils; | ||
| beforeEach(async () => { | ||
| utils = await import("./index"); | ||
| }); | ||
| it("should work as expected", () => { | ||
| expect(utils.isSecurityError(new DOMException())).toBe(false); | ||
| expect(utils.isSecurityError(new DOMException("some err"))).toBe(false); | ||
| expect(utils.isSecurityError(new DOMException("some err", "Noop"))).toBe( | ||
| false | ||
| ); | ||
| expect( | ||
| utils.isSecurityError(new DOMException("some err", "SecurityError")) | ||
| ).toBe(true); | ||
| const err = new DOMException("some err"); | ||
| const e = new Proxy(err, { | ||
| get(t, p) { | ||
| if (p === "code") { | ||
| return 18; | ||
| } | ||
| return t[p]; | ||
| }, | ||
| }); | ||
| expect(utils.isSecurityError(e)).toBe(true); | ||
| }); | ||
| }); | ||
| function createFile(name, size, type) { | ||
@@ -431,0 +485,0 @@ const file = new File([], name, { type }); |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
414534
2.29%6602
3.22%