UNPKG

@uploadcare/react-widget

Version:

React File Uploader. React component with uploading from multiple sources

202 lines (197 loc) 7.55 kB
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 };