@rpldy/uploady
Version:
wrapper&context component to expose and provide react-uploady functionality
88 lines • 2.79 kB
JavaScript
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;