UNPKG

@rpldy/upload-drop-zone

Version:

drop zone (container) component to initiate file and folder content uploads

96 lines 3.89 kB
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); } import React, { forwardRef, useCallback, useImperativeHandle, useRef, useLayoutEffect } from "react"; import { getFilesFromDragEvent } from "html-dir-content"; import { isEmpty, isFunction } from "@rpldy/shared"; import { useUploadyContext, markAsUploadOptionsComponent } from "@rpldy/shared-ui"; const getShouldHandleDrag = (e, shouldHandle) => isEmpty(shouldHandle) || shouldHandle === true || isFunction(shouldHandle) && shouldHandle(e); const isOnTarget = (e, containerElm, allowContains) => { const target = e.type === "dragleave" ? e.relatedTarget : e.target; return target === containerElm || allowContains && containerElm && target && containerElm.contains(target); }; const UploadDropZone = /*#__PURE__*/forwardRef(({ className, id, children, onDragOverClassName, dropHandler, htmlDirContentParams, shouldRemoveDragOver, shouldHandleDrag, enableOnContains = true, noContainCheckForDrag = false, extraProps, ...uploadOptions }, ref) => { const { upload } = useUploadyContext(); const containerRef = useRef(null); const dragLeaveTrackerRef = useRef(false); useImperativeHandle(ref, () => containerRef.current, []); const uploadOptionsRef = useRef(); useLayoutEffect(() => { uploadOptionsRef.current = uploadOptions; }, [uploadOptions]); const handleEnd = useCallback(() => { dragLeaveTrackerRef.current = false; if (containerRef.current && onDragOverClassName) { containerRef.current.classList.remove(onDragOverClassName); } }, [onDragOverClassName, containerRef]); const dropFileHandler = useCallback(e => { const getFiles = () => getFilesFromDragEvent(e, htmlDirContentParams || {}); return dropHandler ? Promise.resolve(dropHandler(e, getFiles)) : getFiles(); }, [dropHandler, htmlDirContentParams]); const handleDropUpload = useCallback(e => { dropFileHandler(e).then(files => { upload(files, uploadOptionsRef.current); }); }, [upload, dropFileHandler, uploadOptionsRef]); const onDragEnter = useCallback(e => { const isHandling = getShouldHandleDrag(e, shouldHandleDrag) && isOnTarget(e, containerRef.current, enableOnContains) || noContainCheckForDrag; if (isHandling) { dragLeaveTrackerRef.current = true; if (containerRef.current && onDragOverClassName) { containerRef.current.classList.add(onDragOverClassName); } } }, [onDragOverClassName, containerRef, shouldHandleDrag, enableOnContains, noContainCheckForDrag]); const onDragOver = useCallback(e => { if (dragLeaveTrackerRef.current) { e.preventDefault(); } }, []); const onDrop = useCallback(e => { if (dragLeaveTrackerRef.current) { e.preventDefault(); e.persist(); handleEnd(); handleDropUpload(e); } }, [handleEnd, handleDropUpload]); const onDragLeave = useCallback(e => { if (dragLeaveTrackerRef.current && !isOnTarget(e, containerRef.current, enableOnContains) || shouldRemoveDragOver?.(e)) { handleEnd(); } }, [handleEnd, containerRef, shouldRemoveDragOver, enableOnContains]); const onDragEnd = useCallback(e => { if (dragLeaveTrackerRef.current) { e.preventDefault(); e.stopPropagation(); handleEnd(); } }, [handleEnd]); return /*#__PURE__*/React.createElement("div", _extends({ id: id, className: className, ref: containerRef, onDragOver: onDragOver, onDragEnter: onDragEnter, onDrop: onDrop, onDragLeave: onDragLeave, onDragEnd: onDragEnd }, extraProps), children); }); markAsUploadOptionsComponent(UploadDropZone); export default UploadDropZone;