UNPKG

6.82 kBJavaScriptView Raw
1function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
2
3var preact = require('preact');
4
5var findDOMElement = require('@uppy/utils/lib/findDOMElement');
6/**
7 * Defer a frequent call to the microtask queue.
8 */
9
10
11function debounce(fn) {
12 var calling = null;
13 var latestArgs = null;
14 return function () {
15 for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
16 args[_key] = arguments[_key];
17 }
18
19 latestArgs = args;
20
21 if (!calling) {
22 calling = Promise.resolve().then(function () {
23 calling = null; // At this point `args` may be different from the most
24 // recent state, if multiple calls happened since this task
25 // was queued. So we use the `latestArgs`, which definitely
26 // is the most recent call.
27
28 return fn.apply(void 0, latestArgs);
29 });
30 }
31
32 return calling;
33 };
34}
35/**
36 * Boilerplate that all Plugins share - and should not be used
37 * directly. It also shows which methods final plugins should implement/override,
38 * this deciding on structure.
39 *
40 * @param {object} main Uppy core object
41 * @param {object} object with plugin options
42 * @returns {Array|string} files or success/fail message
43 */
44
45
46module.exports = /*#__PURE__*/function () {
47 function Plugin(uppy, opts) {
48 this.uppy = uppy;
49 this.opts = opts || {};
50 this.update = this.update.bind(this);
51 this.mount = this.mount.bind(this);
52 this.install = this.install.bind(this);
53 this.uninstall = this.uninstall.bind(this);
54 }
55
56 var _proto = Plugin.prototype;
57
58 _proto.getPluginState = function getPluginState() {
59 var _this$uppy$getState = this.uppy.getState(),
60 plugins = _this$uppy$getState.plugins;
61
62 return plugins[this.id] || {};
63 };
64
65 _proto.setPluginState = function setPluginState(update) {
66 var _extends2;
67
68 var _this$uppy$getState2 = this.uppy.getState(),
69 plugins = _this$uppy$getState2.plugins;
70
71 this.uppy.setState({
72 plugins: _extends({}, plugins, (_extends2 = {}, _extends2[this.id] = _extends({}, plugins[this.id], update), _extends2))
73 });
74 };
75
76 _proto.setOptions = function setOptions(newOpts) {
77 this.opts = _extends({}, this.opts, newOpts);
78 this.setPluginState(); // so that UI re-renders with new options
79 };
80
81 _proto.update = function update(state) {
82 if (typeof this.el === 'undefined') {
83 return;
84 }
85
86 if (this._updateUI) {
87 this._updateUI(state);
88 }
89 } // Called after every state update, after everything's mounted. Debounced.
90 ;
91
92 _proto.afterUpdate = function afterUpdate() {}
93 /**
94 * Called when plugin is mounted, whether in DOM or into another plugin.
95 * Needed because sometimes plugins are mounted separately/after `install`,
96 * so this.el and this.parent might not be available in `install`.
97 * This is the case with @uppy/react plugins, for example.
98 */
99 ;
100
101 _proto.onMount = function onMount() {}
102 /**
103 * Check if supplied `target` is a DOM element or an `object`.
104 * If it’s an object — target is a plugin, and we search `plugins`
105 * for a plugin with same name and return its target.
106 *
107 * @param {string|object} target
108 *
109 */
110 ;
111
112 _proto.mount = function mount(target, plugin) {
113 var _this = this;
114
115 var callerPluginName = plugin.id;
116 var targetElement = findDOMElement(target);
117
118 if (targetElement) {
119 this.isTargetDOMEl = true; // API for plugins that require a synchronous rerender.
120
121 this.rerender = function (state) {
122 // plugin could be removed, but this.rerender is debounced below,
123 // so it could still be called even after uppy.removePlugin or uppy.close
124 // hence the check
125 if (!_this.uppy.getPlugin(_this.id)) return;
126 _this.el = preact.render(_this.render(state), targetElement, _this.el);
127
128 _this.afterUpdate();
129 };
130
131 this._updateUI = debounce(this.rerender);
132 this.uppy.log("Installing " + callerPluginName + " to a DOM element '" + target + "'"); // clear everything inside the target container
133
134 if (this.opts.replaceTargetContent) {
135 targetElement.innerHTML = '';
136 }
137
138 this.el = preact.render(this.render(this.uppy.getState()), targetElement);
139 this.onMount();
140 return this.el;
141 }
142
143 var targetPlugin;
144
145 if (typeof target === 'object' && target instanceof Plugin) {
146 // Targeting a plugin *instance*
147 targetPlugin = target;
148 } else if (typeof target === 'function') {
149 // Targeting a plugin type
150 var Target = target; // Find the target plugin instance.
151
152 this.uppy.iteratePlugins(function (plugin) {
153 if (plugin instanceof Target) {
154 targetPlugin = plugin;
155 return false;
156 }
157 });
158 }
159
160 if (targetPlugin) {
161 this.uppy.log("Installing " + callerPluginName + " to " + targetPlugin.id);
162 this.parent = targetPlugin;
163 this.el = targetPlugin.addTarget(plugin);
164 this.onMount();
165 return this.el;
166 }
167
168 this.uppy.log("Not installing " + callerPluginName);
169 var message = "Invalid target option given to " + callerPluginName + ".";
170
171 if (typeof target === 'function') {
172 message += ' The given target is not a Plugin class. ' + 'Please check that you\'re not specifying a React Component instead of a plugin. ' + 'If you are using @uppy/* packages directly, make sure you have only 1 version of @uppy/core installed: ' + 'run `npm ls @uppy/core` on the command line and verify that all the versions match and are deduped correctly.';
173 } else {
174 message += 'If you meant to target an HTML element, please make sure that the element exists. ' + 'Check that the <script> tag initializing Uppy is right before the closing </body> tag at the end of the page. ' + '(see https://github.com/transloadit/uppy/issues/1042)\n\n' + 'If you meant to target a plugin, please confirm that your `import` statements or `require` calls are correct.';
175 }
176
177 throw new Error(message);
178 };
179
180 _proto.render = function render(state) {
181 throw new Error('Extend the render method to add your plugin to a DOM element');
182 };
183
184 _proto.addTarget = function addTarget(plugin) {
185 throw new Error('Extend the addTarget method to add your plugin to another plugin\'s target');
186 };
187
188 _proto.unmount = function unmount() {
189 if (this.isTargetDOMEl && this.el && this.el.parentNode) {
190 this.el.parentNode.removeChild(this.el);
191 }
192 };
193
194 _proto.install = function install() {};
195
196 _proto.uninstall = function uninstall() {
197 this.unmount();
198 };
199
200 return Plugin;
201}();
\No newline at end of file