This is a different approach to React components suggested by @arturi.
Instead of the components adding and removing plugins when mounting and
unmounting, plugins are configured at the start, and the components act
as slots for the plugins to actually mount in. Because all plugins are
still being configured up front here, we don't have to change how the
provider `target:` options work, they can install themselves into eg.
the Dashboard plugin immediately.
The core of this approach is the `UppyWrapper` component, which takes an
Uppy instance and a plugin ID, and mounts the plugin inside itself. The
other components only provide a default plugin ID.
The one change required in Uppy itself for this to work is to the
`mount()` functions: now, `mount()` configures `this.target` on the
plugins. If plugins do not have a `target:` option, they do not mount on
install. Some DOM code also had to be moved into the `mount()` function
for the DragDrop component instead of staying in `install()`, but I
think it makes sense.
(Still have to work out how to make the `DashboardModal` component's
`onRequestClose` option work.)
This PR adds support for extracting metadata from `<form>` elements.
This was asked #153 and came up elsewhere too, I believe. You can use
it like this:
```html
<form class="MyForm" action="/">
<input type="file" />
<input type="hidden" name="bla" value="12333">
<input type="text" name="yo" value="1">
<button type="submit">Upload</button>
</form>
```
```js
uppy.use(DragDrop, {
target: '.MyForm',
locale: {
strings: {chooseFile: 'Выберите файл'}
},
setMetaFromTargetForm: true
})
```
Then UI acquire type plugins, like Dashboard, FileInput and DragDrop,
before mounting themselves or doing anything else, extract FormData
from the `target` `<form>` element (it must be a form currently), and
merge the object with the global `state.meta`. This is done via
`setMeta` method on core. Then, when a file is added, `state.meta` is
merged to that file’s meta right away. The ability to add more fields
via UI plugin MetaData is also still there, though probably needs an
update.
In addition a new `meta` option is added in core:
```js
const uppy = Uppy({
debug: true,
autoProceed: true,
meta: {
username: 'Artur'
}
})
```
This way some data can be set right away, it becomes the initial
`state.meta` object.
Every element that was opening a file selection dialog by simulating a
`.UppyDashboard-input` click, was also already rendering one of those
input elements. This patch first creates the `input` elements, and
saves them so their variables can be used to simulate a click event
directly.
This way the `container` prop no longer has to be passed down through
every layer, and we can turn the `.target` property in plugins into
a DOM element because it isn't used in `querySelector` anymore.