@uploadcare/react-widget
Version:
React File Uploader. React component with uploading from multiple sources
202 lines (197 loc) • 7.55 kB
JavaScript
import { _ as _objectWithoutProperties, a as _objectSpread2 } from './index-881e303a.mjs';
import React, { useEffect, useRef, useImperativeHandle, useCallback } from 'react';
import uploadcare from 'uploadcare-widget';
import { u as useCommitedCallback, a as useCustomTabs, b as useDeepEffect, d as defaultPreviewUrlCallback } from './default-preview-url-callback-19e28ce7.mjs';
import isEqual from 'react-fast-compare';
var useValidators = function useValidators(widget, validators) {
useEffect(function () {
if (validators != null) {
var instance = widget.current;
validators.forEach(function (validator) {
instance.validators.push(validator);
});
return function () {
instance.validators.length = 0;
};
}
}, [widget, validators]);
};
function useDeepMemo(factory, deps) {
var isValid = true;
var valueRef = useRef();
// initial hook call
if (!valueRef.current) {
valueRef.current = {
deps: deps,
result: factory()
};
// subsequent calls
} else {
isValid = !!(deps && valueRef.current.deps && isEqual(deps, valueRef.current.deps));
}
var cache = isValid ? valueRef.current : {
deps: deps,
result: factory()
};
// must update immediately so any sync renders here don't cause an infinite loop
valueRef.current = cache;
return cache.result;
}
var _excluded = ["id", "name", "value", "onFileSelect", "onChange", "onDialogOpen", "onDialogClose", "onTabChange", "apiRef", "customTabs", "validators", "tabsCss", "locale", "localeTranslations", "localePluralize", "previewUrlCallback", "metadataCallback"];
var useWidget = function useWidget(_ref, uploadcare) {
var id = _ref.id,
name = _ref.name,
value = _ref.value,
onFileSelect = _ref.onFileSelect,
onChange = _ref.onChange,
onDialogOpen = _ref.onDialogOpen,
onDialogClose = _ref.onDialogClose,
onTabChange = _ref.onTabChange,
apiRef = _ref.apiRef,
customTabs = _ref.customTabs,
validators = _ref.validators,
tabsCss = _ref.tabsCss,
locale = _ref.locale,
localeTranslations = _ref.localeTranslations,
localePluralize = _ref.localePluralize,
previewUrlCallback = _ref.previewUrlCallback,
metadataCallback = _ref.metadataCallback,
options = _objectWithoutProperties(_ref, _excluded);
var input = useRef(null);
var widget = useRef(null);
var cachedValueRef = useRef(null);
var fileSelectedCallback = useCommitedCallback(onFileSelect);
var changeCallback = useCommitedCallback(onChange);
var dialogOpenCallback = useCommitedCallback(onDialogOpen);
var dialogCloseCallback = useCommitedCallback(onDialogClose);
var tabChangeCallback = useCommitedCallback(onTabChange);
var metadataCommitedCallback = useCommitedCallback(metadataCallback);
var previewUrlCommitedCallback = useCommitedCallback(previewUrlCallback || defaultPreviewUrlCallback);
var widgetOptions = useDeepMemo(function () {
return options;
}, [options]);
useCustomTabs(customTabs, uploadcare);
useDeepEffect(function () {
if (locale) window.UPLOADCARE_LOCALE = locale;
if (localePluralize) window.UPLOADCARE_LOCALE_PLURALIZE = localePluralize;
if (localeTranslations) {
window.UPLOADCARE_LOCALE_TRANSLATIONS = localeTranslations;
}
uploadcare.plugin(function (internal) {
internal.locale.rebuild({
locale: locale || null,
localeTranslations: localeTranslations || null,
localePluralize: localePluralize || null
});
});
return function () {
if (locale) delete window.UPLOADCARE_LOCALE;
if (localePluralize) delete window.UPLOADCARE_LOCALE_PLURALIZE;
if (localeTranslations) delete window.UPLOADCARE_LOCALE_TRANSLATIONS;
};
}, [locale, localeTranslations, localePluralize]);
useEffect(function () {
var inputEl = input.current;
widget.current = uploadcare.Widget(inputEl, _objectSpread2(_objectSpread2({}, widgetOptions), {}, {
metadataCallback: widgetOptions.metadata ? undefined : metadataCommitedCallback,
previewUrlCallback: previewUrlCommitedCallback
}));
var widgetElement = inputEl.nextSibling;
if (cachedValueRef.current) {
// restore widget value when called twice in React.StrictMode
widget.current.value(cachedValueRef.current);
}
return function () {
// useEffect could be called twice inside React.StrictMode
// to reinitialize widget on the same input element, we need to cleanup bounded jquery data on it
// `uploadcareWidget` is a data attr that is used to store widget api
// see https://github.com/uploadcare/uploadcare-widget/blob/feat/unsplash-tab/src/widget/live.js#L11
uploadcare.jQuery(inputEl).removeData('uploadcareWidget');
widgetElement && widgetElement.remove();
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [uploadcare, widgetOptions, metadataCommitedCallback, previewUrlCommitedCallback]);
useValidators(widget, validators);
useEffect(function () {
widget.current.onUploadComplete.add(changeCallback);
widget.current.onChange.add(fileSelectedCallback);
return function () {
widget.current.onUploadComplete.remove(changeCallback);
widget.current.onChange.remove(fileSelectedCallback);
};
}, [changeCallback, fileSelectedCallback, uploadcare, widgetOptions]);
useEffect(function () {
var dialog;
var saveDialog = function saveDialog(ref) {
dialog = ref;
dialog.done(dialogCloseCallback).fail(dialogCloseCallback).progress(tabChangeCallback);
dialogOpenCallback(ref);
};
widget.current.onDialogOpen.add(saveDialog);
return function () {
widget.current.onDialogOpen.remove(saveDialog);
dialog && dialog.reject();
};
}, [dialogCloseCallback, dialogOpenCallback, tabChangeCallback, widgetOptions]);
useEffect(function () {
var files = [];
var saveFiles = function saveFiles(file) {
if (file) {
files = file.files ? file.files() : [file];
} else {
files = [];
}
};
widget.current.onChange.add(saveFiles);
return function () {
files.forEach(function (file) {
return file.cancel();
});
widget.current.onChange.remove(saveFiles);
};
}, [widgetOptions]);
useEffect(function () {
if (cachedValueRef.current !== value) {
widget.current.value(value);
}
cachedValueRef.current = value;
}, [value]);
useEffect(function () {
if (uploadcare && tabsCss && typeof tabsCss === 'string') {
if (tabsCss.indexOf('https://') === 0) {
uploadcare.tabsCss.addUrl(tabsCss);
} else {
uploadcare.tabsCss.addStyle(tabsCss);
}
}
}, [uploadcare, tabsCss]);
useImperativeHandle(apiRef, function () {
return {
openDialog: function openDialog() {
return widget.current.openDialog();
},
reloadInfo: function reloadInfo() {
return widget.current.reloadInfo();
},
getInput: function getInput() {
return widget.current.inputElement;
},
value: function value(_value) {
return widget.current.value(_value);
}
};
}, []);
return useCallback(function () {
return /*#__PURE__*/React.createElement("input", {
type: "hidden",
ref: input,
id: id,
name: name
});
}, [id, name]);
};
var Uploader = function Uploader(props) {
var Input = useWidget(props, uploadcare);
return /*#__PURE__*/React.createElement(Input, null);
};
export { Uploader as default };