UNPKG

@rpldy/uploady

Version:

wrapper&context component to expose and provide react-uploady functionality

88 lines 2.79 kB
import { useEffect } from "react"; import { logger } from "@rpldy/shared"; import { useUploadyContext } from "@rpldy/shared-ui"; const getUrl = form => { const loc = window.location; let url = form.getAttribute("action") || ""; url = url.replace(/\s/g, ""); let path; switch (true) { case url === "": url = loc.href; break; case url.startsWith("/"): url = `${loc.protocol}//${loc.host}${url}`; break; case !/:\/\//.test(url): path = loc.pathname.split("/").slice(0, -1).concat("").join("/"); url = `${loc.protocol}//${loc.host}${path}${url}`; break; } return url; }; const getNewDestination = (input, form) => { const method = form?.getAttribute("method"), url = form && getUrl(form); return { filesParamName: input.getAttribute("name"), method: method ? method.toUpperCase() : undefined, url: url }; }; const retrieveDestinationFromInput = (input, onUpdate) => { let destination, stopObserving; const form = input.closest("form"); if (form) { destination = getNewDestination(input, form); logger.debugLog(`Uploady.useFileInput: using custom input's parent form url ${destination.url || ""} and method ${destination.method || ""}`); let observer = new MutationObserver(records => { if (records[0]?.attributeName === "action") { const newDestination = getNewDestination(input, form); if (newDestination.url) { logger.debugLog(`Uploady.useFileInput: form action attribute changed to ${newDestination.url}`); onUpdate(newDestination); } } }); observer?.observe(form, { attributes: true, attributeFilter: ["action"] }); stopObserving = () => { observer?.disconnect(); observer = null; }; } onUpdate(destination || getNewDestination(input)); return { stopObserving }; }; const useFileInput = fileInputRef => { const context = useUploadyContext(); if (fileInputRef) { context.setExternalFileInput(fileInputRef); } useEffect(() => { let stopObservingCallback; if (fileInputRef?.current && "closest" in fileInputRef.current) { const input = fileInputRef.current; const uploaderOptions = context.getOptions(); if (!uploaderOptions.destination || !uploaderOptions.destination.url) { const { stopObserving } = retrieveDestinationFromInput(input, newDestination => { context.setOptions({ destination: newDestination }); }); stopObservingCallback = stopObserving; } } return () => { stopObservingCallback?.(); }; }, [fileInputRef, context]); return !!fileInputRef ? fileInputRef : context.getInternalFileInput(); }; export default useFileInput;